From 36ba48b7ddf52a2b63b3c8c5971209f46639b7c3 Mon Sep 17 00:00:00 2001 From: HoRnEyDvL <73101201+HoRnEyDvL@users.noreply.github.com> Date: Mon, 9 Feb 2026 09:00:27 +1100 Subject: [PATCH] Initial commit libcurl-7.65.3 + BearSSL/0.6 for Original Xbox --- BearSSL-OG/Tools/bearssl.dll | Bin 0 -> 256512 bytes BearSSL-OG/Tools/brssl.exe | Bin 0 -> 452608 bytes BearSSL-OG/Tools/testcrypto.exe | Bin 0 -> 622592 bytes BearSSL-OG/Tools/testspeed.exe | Bin 0 -> 355840 bytes BearSSL-OG/Tools/testx509.exe | Bin 0 -> 198656 bytes BearSSL-OG/XboxOGBearSSL.ncb | Bin 0 -> 6155264 bytes BearSSL-OG/XboxOGBearSSL.sln | 30 + BearSSL-OG/XboxOGBearSSL.suo | Bin 0 -> 23040 bytes BearSSL-OG/XboxOGBearSSL.vcproj | 1381 + BearSSL-OG/bearssl.c | 1640 + BearSSL-OG/bearssl_xbox.cpp | 150 + BearSSL-OG/bearssl_xbox.h | 85 + BearSSL-OG/ca_loader.cpp | 861 + BearSSL-OG/ca_loader.h | 65 + BearSSL-OG/cert-ee-ec+rsa.pem | 14 + BearSSL-OG/cert-ee-ec.pem | 10 + BearSSL-OG/cert-ee-rsa.pem | 17 + BearSSL-OG/cert-ica-ec.pem | 10 + BearSSL-OG/cert-ica-rsa.pem | 17 + BearSSL-OG/cert-root-ec.pem | 9 + BearSSL-OG/cert-root-rsa.pem | 16 + BearSSL-OG/cert_pinning.cpp | 163 + BearSSL-OG/cert_pinning.h | 49 + BearSSL-OG/certificates.cpp | 858 + BearSSL-OG/certificates.h | 23 + BearSSL-OG/chain-ec+rsa.h | 171 + BearSSL-OG/chain-ec.h | 122 + BearSSL-OG/chain-rsa.h | 188 + BearSSL-OG/client.cpp | 461 + BearSSL-OG/client.h | 17 + BearSSL-OG/data_store.cpp | 108 + BearSSL-OG/data_store.h | 28 + BearSSL-OG/debug_utility.cpp | 28 + BearSSL-OG/debug_utility.h | 7 + BearSSL-OG/key-ec.h | 45 + BearSSL-OG/key-ee-ec.pem | 5 + BearSSL-OG/key-ee-rsa.pem | 23 + BearSSL-OG/key-ica-ec.pem | 5 + BearSSL-OG/key-ica-rsa.pem | 23 + BearSSL-OG/key-root-ec.pem | 5 + BearSSL-OG/key-root-rsa.pem | 23 + BearSSL-OG/key-rsa.h | 113 + BearSSL-OG/libbearssl.vcproj | 484 + BearSSL-OG/libbearssl/inc/bearssl.h | 183 + BearSSL-OG/libbearssl/inc/bearssl_aead.h | 1059 + BearSSL-OG/libbearssl/inc/bearssl_block.h | 2618 ++ BearSSL-OG/libbearssl/inc/bearssl_ec.h | 967 + BearSSL-OG/libbearssl/inc/bearssl_hash.h | 1345 + BearSSL-OG/libbearssl/inc/bearssl_hmac.h | 241 + BearSSL-OG/libbearssl/inc/bearssl_kdf.h | 284 + BearSSL-OG/libbearssl/inc/bearssl_pem.h | 294 + BearSSL-OG/libbearssl/inc/bearssl_prf.h | 150 + BearSSL-OG/libbearssl/inc/bearssl_rand.h | 397 + BearSSL-OG/libbearssl/inc/bearssl_rsa.h | 1655 + BearSSL-OG/libbearssl/inc/bearssl_ssl.h | 4307 ++ BearSSL-OG/libbearssl/inc/bearssl_x509.h | 1474 + BearSSL-OG/libbearssl/src/aead/ccm.c | 346 + BearSSL-OG/libbearssl/src/aead/eax.c | 525 + BearSSL-OG/libbearssl/src/aead/gcm.c | 318 + BearSSL-OG/libbearssl/src/codec/ccopy.c | 44 + BearSSL-OG/libbearssl/src/codec/dec16be.c | 38 + BearSSL-OG/libbearssl/src/codec/dec16le.c | 38 + BearSSL-OG/libbearssl/src/codec/dec32be.c | 38 + BearSSL-OG/libbearssl/src/codec/dec32le.c | 38 + BearSSL-OG/libbearssl/src/codec/dec64be.c | 38 + BearSSL-OG/libbearssl/src/codec/dec64le.c | 38 + BearSSL-OG/libbearssl/src/codec/enc16be.c | 38 + BearSSL-OG/libbearssl/src/codec/enc16le.c | 38 + BearSSL-OG/libbearssl/src/codec/enc32be.c | 38 + BearSSL-OG/libbearssl/src/codec/enc32le.c | 38 + BearSSL-OG/libbearssl/src/codec/enc64be.c | 38 + BearSSL-OG/libbearssl/src/codec/enc64le.c | 38 + BearSSL-OG/libbearssl/src/codec/pemdec.c | 526 + BearSSL-OG/libbearssl/src/codec/pemdec.t0 | 314 + BearSSL-OG/libbearssl/src/codec/pemenc.c | 173 + BearSSL-OG/libbearssl/src/config.h | 256 + BearSSL-OG/libbearssl/src/ec/ec_all_m15.c | 121 + BearSSL-OG/libbearssl/src/ec/ec_all_m31.c | 171 + BearSSL-OG/libbearssl/src/ec/ec_c25519_i15.c | 398 + BearSSL-OG/libbearssl/src/ec/ec_c25519_i31.c | 390 + BearSSL-OG/libbearssl/src/ec/ec_c25519_m15.c | 1478 + BearSSL-OG/libbearssl/src/ec/ec_c25519_m31.c | 800 + BearSSL-OG/libbearssl/src/ec/ec_c25519_m62.c | 605 + BearSSL-OG/libbearssl/src/ec/ec_c25519_m64.c | 831 + BearSSL-OG/libbearssl/src/ec/ec_curve25519.c | 46 + BearSSL-OG/libbearssl/src/ec/ec_default.c | 36 + BearSSL-OG/libbearssl/src/ec/ec_keygen.c | 86 + BearSSL-OG/libbearssl/src/ec/ec_p256_m15.c | 2124 + BearSSL-OG/libbearssl/src/ec/ec_p256_m31.c | 1469 + BearSSL-OG/libbearssl/src/ec/ec_p256_m62.c | 1765 + BearSSL-OG/libbearssl/src/ec/ec_p256_m64.c | 1781 + BearSSL-OG/libbearssl/src/ec/ec_prime_i15.c | 824 + BearSSL-OG/libbearssl/src/ec/ec_prime_i31.c | 826 + BearSSL-OG/libbearssl/src/ec/ec_pubkey.c | 85 + BearSSL-OG/libbearssl/src/ec/ec_secp256r1.c | 51 + BearSSL-OG/libbearssl/src/ec/ec_secp384r1.c | 57 + BearSSL-OG/libbearssl/src/ec/ec_secp521r1.c | 64 + BearSSL-OG/libbearssl/src/ec/ecdsa_atr.c | 134 + .../src/ec/ecdsa_default_sign_asn1.c | 36 + .../src/ec/ecdsa_default_sign_raw.c | 36 + .../src/ec/ecdsa_default_vrfy_asn1.c | 36 + .../src/ec/ecdsa_default_vrfy_raw.c | 36 + BearSSL-OG/libbearssl/src/ec/ecdsa_i15_bits.c | 47 + .../libbearssl/src/ec/ecdsa_i15_sign_asn1.c | 45 + .../libbearssl/src/ec/ecdsa_i15_sign_raw.c | 174 + .../libbearssl/src/ec/ecdsa_i15_vrfy_asn1.c | 48 + .../libbearssl/src/ec/ecdsa_i15_vrfy_raw.c | 166 + BearSSL-OG/libbearssl/src/ec/ecdsa_i31_bits.c | 47 + .../libbearssl/src/ec/ecdsa_i31_sign_asn1.c | 45 + .../libbearssl/src/ec/ecdsa_i31_sign_raw.c | 173 + .../libbearssl/src/ec/ecdsa_i31_vrfy_asn1.c | 48 + .../libbearssl/src/ec/ecdsa_i31_vrfy_raw.c | 165 + BearSSL-OG/libbearssl/src/ec/ecdsa_rta.c | 121 + BearSSL-OG/libbearssl/src/hash/dig_oid.c | 84 + BearSSL-OG/libbearssl/src/hash/dig_size.c | 50 + BearSSL-OG/libbearssl/src/hash/ghash_ctmul.c | 345 + .../libbearssl/src/hash/ghash_ctmul32.c | 251 + .../libbearssl/src/hash/ghash_ctmul64.c | 154 + BearSSL-OG/libbearssl/src/hash/ghash_pclmul.c | 389 + BearSSL-OG/libbearssl/src/hash/ghash_pwr8.c | 411 + BearSSL-OG/libbearssl/src/hash/md5.c | 208 + BearSSL-OG/libbearssl/src/hash/md5sha1.c | 141 + BearSSL-OG/libbearssl/src/hash/mgf1.c | 56 + BearSSL-OG/libbearssl/src/hash/multihash.c | 166 + BearSSL-OG/libbearssl/src/hash/sha1.c | 191 + BearSSL-OG/libbearssl/src/hash/sha2big.c | 285 + BearSSL-OG/libbearssl/src/hash/sha2small.c | 341 + BearSSL-OG/libbearssl/src/inner.h | 2584 ++ BearSSL-OG/libbearssl/src/int/i15_add.c | 46 + BearSSL-OG/libbearssl/src/int/i15_bitlen.c | 44 + BearSSL-OG/libbearssl/src/int/i15_decmod.c | 124 + BearSSL-OG/libbearssl/src/int/i15_decode.c | 56 + BearSSL-OG/libbearssl/src/int/i15_decred.c | 100 + BearSSL-OG/libbearssl/src/int/i15_encode.c | 56 + BearSSL-OG/libbearssl/src/int/i15_fmont.c | 59 + BearSSL-OG/libbearssl/src/int/i15_iszero.c | 39 + BearSSL-OG/libbearssl/src/int/i15_moddiv.c | 465 + BearSSL-OG/libbearssl/src/int/i15_modpow.c | 50 + BearSSL-OG/libbearssl/src/int/i15_modpow2.c | 160 + BearSSL-OG/libbearssl/src/int/i15_montmul.c | 184 + BearSSL-OG/libbearssl/src/int/i15_mulacc.c | 61 + BearSSL-OG/libbearssl/src/int/i15_muladd.c | 173 + BearSSL-OG/libbearssl/src/int/i15_ninv15.c | 38 + BearSSL-OG/libbearssl/src/int/i15_reduce.c | 66 + BearSSL-OG/libbearssl/src/int/i15_rshift.c | 47 + BearSSL-OG/libbearssl/src/int/i15_sub.c | 46 + BearSSL-OG/libbearssl/src/int/i15_tmont.c | 36 + BearSSL-OG/libbearssl/src/int/i31_add.c | 46 + BearSSL-OG/libbearssl/src/int/i31_bitlen.c | 44 + BearSSL-OG/libbearssl/src/int/i31_decmod.c | 124 + BearSSL-OG/libbearssl/src/int/i31_decode.c | 57 + BearSSL-OG/libbearssl/src/int/i31_decred.c | 103 + BearSSL-OG/libbearssl/src/int/i31_encode.c | 79 + BearSSL-OG/libbearssl/src/int/i31_fmont.c | 60 + BearSSL-OG/libbearssl/src/int/i31_iszero.c | 39 + BearSSL-OG/libbearssl/src/int/i31_moddiv.c | 488 + BearSSL-OG/libbearssl/src/int/i31_modpow.c | 65 + BearSSL-OG/libbearssl/src/int/i31_modpow2.c | 160 + BearSSL-OG/libbearssl/src/int/i31_montmul.c | 127 + BearSSL-OG/libbearssl/src/int/i31_mulacc.c | 74 + BearSSL-OG/libbearssl/src/int/i31_muladd.c | 157 + BearSSL-OG/libbearssl/src/int/i31_ninv31.c | 39 + BearSSL-OG/libbearssl/src/int/i31_reduce.c | 66 + BearSSL-OG/libbearssl/src/int/i31_rshift.c | 47 + BearSSL-OG/libbearssl/src/int/i31_sub.c | 46 + BearSSL-OG/libbearssl/src/int/i31_tmont.c | 36 + BearSSL-OG/libbearssl/src/int/i32_add.c | 51 + BearSSL-OG/libbearssl/src/int/i32_bitlen.c | 44 + BearSSL-OG/libbearssl/src/int/i32_decmod.c | 77 + BearSSL-OG/libbearssl/src/int/i32_decode.c | 63 + BearSSL-OG/libbearssl/src/int/i32_decred.c | 107 + BearSSL-OG/libbearssl/src/int/i32_div32.c | 56 + BearSSL-OG/libbearssl/src/int/i32_encode.c | 72 + BearSSL-OG/libbearssl/src/int/i32_fmont.c | 60 + BearSSL-OG/libbearssl/src/int/i32_iszero.c | 39 + BearSSL-OG/libbearssl/src/int/i32_modpow.c | 65 + BearSSL-OG/libbearssl/src/int/i32_montmul.c | 69 + BearSSL-OG/libbearssl/src/int/i32_mulacc.c | 56 + BearSSL-OG/libbearssl/src/int/i32_muladd.c | 138 + BearSSL-OG/libbearssl/src/int/i32_ninv32.c | 39 + BearSSL-OG/libbearssl/src/int/i32_reduce.c | 66 + BearSSL-OG/libbearssl/src/int/i32_sub.c | 51 + BearSSL-OG/libbearssl/src/int/i32_tmont.c | 36 + BearSSL-OG/libbearssl/src/int/i62_modpow2.c | 493 + BearSSL-OG/libbearssl/src/kdf/hkdf.c | 107 + BearSSL-OG/libbearssl/src/kdf/shake.c | 590 + BearSSL-OG/libbearssl/src/mac/hmac.c | 122 + BearSSL-OG/libbearssl/src/mac/hmac_ct.c | 193 + BearSSL-OG/libbearssl/src/rand/aesctr_drbg.c | 206 + BearSSL-OG/libbearssl/src/rand/hmac_drbg.c | 157 + BearSSL-OG/libbearssl/src/rand/sysrng.c | 285 + .../libbearssl/src/rsa/rsa_default_keygen.c | 38 + .../libbearssl/src/rsa/rsa_default_modulus.c | 36 + .../src/rsa/rsa_default_oaep_decrypt.c | 38 + .../src/rsa/rsa_default_oaep_encrypt.c | 38 + .../src/rsa/rsa_default_pkcs1_sign.c | 38 + .../src/rsa/rsa_default_pkcs1_vrfy.c | 38 + .../libbearssl/src/rsa/rsa_default_priv.c | 38 + .../libbearssl/src/rsa/rsa_default_privexp.c | 36 + .../libbearssl/src/rsa/rsa_default_pss_sign.c | 38 + .../libbearssl/src/rsa/rsa_default_pss_vrfy.c | 38 + .../libbearssl/src/rsa/rsa_default_pub.c | 38 + .../libbearssl/src/rsa/rsa_default_pubexp.c | 36 + .../libbearssl/src/rsa/rsa_i15_keygen.c | 583 + .../libbearssl/src/rsa/rsa_i15_modulus.c | 99 + .../libbearssl/src/rsa/rsa_i15_oaep_decrypt.c | 41 + .../libbearssl/src/rsa/rsa_i15_oaep_encrypt.c | 44 + .../libbearssl/src/rsa/rsa_i15_pkcs1_sign.c | 37 + .../libbearssl/src/rsa/rsa_i15_pkcs1_vrfy.c | 43 + BearSSL-OG/libbearssl/src/rsa/rsa_i15_priv.c | 209 + .../libbearssl/src/rsa/rsa_i15_privexp.c | 320 + .../libbearssl/src/rsa/rsa_i15_pss_sign.c | 40 + .../libbearssl/src/rsa/rsa_i15_pss_vrfy.c | 44 + BearSSL-OG/libbearssl/src/rsa/rsa_i15_pub.c | 113 + .../libbearssl/src/rsa/rsa_i15_pubexp.c | 152 + .../libbearssl/src/rsa/rsa_i31_keygen.c | 37 + .../libbearssl/src/rsa/rsa_i31_keygen_inner.c | 608 + .../libbearssl/src/rsa/rsa_i31_modulus.c | 99 + .../libbearssl/src/rsa/rsa_i31_oaep_decrypt.c | 41 + .../libbearssl/src/rsa/rsa_i31_oaep_encrypt.c | 44 + .../libbearssl/src/rsa/rsa_i31_pkcs1_sign.c | 37 + .../libbearssl/src/rsa/rsa_i31_pkcs1_vrfy.c | 43 + BearSSL-OG/libbearssl/src/rsa/rsa_i31_priv.c | 203 + .../libbearssl/src/rsa/rsa_i31_privexp.c | 318 + .../libbearssl/src/rsa/rsa_i31_pss_sign.c | 40 + .../libbearssl/src/rsa/rsa_i31_pss_vrfy.c | 44 + BearSSL-OG/libbearssl/src/rsa/rsa_i31_pub.c | 106 + .../libbearssl/src/rsa/rsa_i31_pubexp.c | 152 + .../libbearssl/src/rsa/rsa_i32_oaep_decrypt.c | 41 + .../libbearssl/src/rsa/rsa_i32_oaep_encrypt.c | 44 + .../libbearssl/src/rsa/rsa_i32_pkcs1_sign.c | 37 + .../libbearssl/src/rsa/rsa_i32_pkcs1_vrfy.c | 43 + BearSSL-OG/libbearssl/src/rsa/rsa_i32_priv.c | 160 + .../libbearssl/src/rsa/rsa_i32_pss_sign.c | 40 + .../libbearssl/src/rsa/rsa_i32_pss_vrfy.c | 44 + BearSSL-OG/libbearssl/src/rsa/rsa_i32_pub.c | 77 + .../libbearssl/src/rsa/rsa_i62_keygen.c | 57 + .../libbearssl/src/rsa/rsa_i62_oaep_decrypt.c | 61 + .../libbearssl/src/rsa/rsa_i62_oaep_encrypt.c | 64 + .../libbearssl/src/rsa/rsa_i62_pkcs1_sign.c | 57 + .../libbearssl/src/rsa/rsa_i62_pkcs1_vrfy.c | 63 + BearSSL-OG/libbearssl/src/rsa/rsa_i62_priv.c | 223 + .../libbearssl/src/rsa/rsa_i62_pss_sign.c | 60 + .../libbearssl/src/rsa/rsa_i62_pss_vrfy.c | 64 + BearSSL-OG/libbearssl/src/rsa/rsa_i62_pub.c | 125 + BearSSL-OG/libbearssl/src/rsa/rsa_oaep_pad.c | 112 + .../libbearssl/src/rsa/rsa_oaep_unpad.c | 145 + .../libbearssl/src/rsa/rsa_pkcs1_sig_pad.c | 100 + .../libbearssl/src/rsa/rsa_pkcs1_sig_unpad.c | 121 + .../libbearssl/src/rsa/rsa_pss_sig_pad.c | 106 + .../libbearssl/src/rsa/rsa_pss_sig_unpad.c | 121 + .../libbearssl/src/rsa/rsa_ssl_decrypt.c | 52 + BearSSL-OG/libbearssl/src/settings.c | 313 + BearSSL-OG/libbearssl/src/ssl/prf.c | 73 + BearSSL-OG/libbearssl/src/ssl/prf_md5sha1.c | 43 + BearSSL-OG/libbearssl/src/ssl/prf_sha256.c | 36 + BearSSL-OG/libbearssl/src/ssl/prf_sha384.c | 36 + .../libbearssl/src/ssl/ssl_ccert_single_ec.c | 157 + .../libbearssl/src/ssl/ssl_ccert_single_rsa.c | 149 + BearSSL-OG/libbearssl/src/ssl/ssl_client.c | 78 + .../src/ssl/ssl_client_default_rsapub.c | 32 + .../libbearssl/src/ssl/ssl_client_full.c | 179 + BearSSL-OG/libbearssl/src/ssl/ssl_engine.c | 1589 + .../src/ssl/ssl_engine_default_aescbc.c | 64 + .../src/ssl/ssl_engine_default_aesccm.c | 67 + .../src/ssl/ssl_engine_default_aesgcm.c | 89 + .../src/ssl/ssl_engine_default_chapol.c | 65 + .../src/ssl/ssl_engine_default_descbc.c | 37 + .../src/ssl/ssl_engine_default_ec.c | 36 + .../src/ssl/ssl_engine_default_ecdsa.c | 38 + .../src/ssl/ssl_engine_default_rsavrfy.c | 32 + BearSSL-OG/libbearssl/src/ssl/ssl_hashes.c | 46 + BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.c | 1967 + .../libbearssl/src/ssl/ssl_hs_client.t0 | 1398 + .../libbearssl/src/ssl/ssl_hs_common.t0 | 1385 + BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.c | 2009 + .../libbearssl/src/ssl/ssl_hs_server.t0 | 1510 + BearSSL-OG/libbearssl/src/ssl/ssl_io.c | 261 + BearSSL-OG/libbearssl/src/ssl/ssl_keyexport.c | 83 + BearSSL-OG/libbearssl/src/ssl/ssl_lru.c | 537 + BearSSL-OG/libbearssl/src/ssl/ssl_rec_cbc.c | 440 + BearSSL-OG/libbearssl/src/ssl/ssl_rec_ccm.c | 213 + .../libbearssl/src/ssl/ssl_rec_chapol.c | 177 + BearSSL-OG/libbearssl/src/ssl/ssl_rec_gcm.c | 235 + .../libbearssl/src/ssl/ssl_scert_single_ec.c | 142 + .../libbearssl/src/ssl/ssl_scert_single_rsa.c | 162 + BearSSL-OG/libbearssl/src/ssl/ssl_server.c | 52 + .../libbearssl/src/ssl/ssl_server_full_ec.c | 149 + .../libbearssl/src/ssl/ssl_server_full_rsa.c | 132 + .../libbearssl/src/ssl/ssl_server_mine2c.c | 71 + .../libbearssl/src/ssl/ssl_server_mine2g.c | 71 + .../libbearssl/src/ssl/ssl_server_minf2c.c | 71 + .../libbearssl/src/ssl/ssl_server_minf2g.c | 71 + .../libbearssl/src/ssl/ssl_server_minr2g.c | 70 + .../libbearssl/src/ssl/ssl_server_minu2g.c | 70 + .../libbearssl/src/ssl/ssl_server_minv2g.c | 70 + .../libbearssl/src/symcipher/aes_big_cbcdec.c | 69 + .../libbearssl/src/symcipher/aes_big_cbcenc.c | 67 + .../libbearssl/src/symcipher/aes_big_ctr.c | 84 + .../libbearssl/src/symcipher/aes_big_ctrcbc.c | 142 + .../libbearssl/src/symcipher/aes_big_dec.c | 254 + .../libbearssl/src/symcipher/aes_big_enc.c | 157 + .../libbearssl/src/symcipher/aes_common.c | 112 + BearSSL-OG/libbearssl/src/symcipher/aes_ct.c | 328 + .../libbearssl/src/symcipher/aes_ct64.c | 398 + .../src/symcipher/aes_ct64_cbcdec.c | 104 + .../src/symcipher/aes_ct64_cbcenc.c | 81 + .../libbearssl/src/symcipher/aes_ct64_ctr.c | 114 + .../src/symcipher/aes_ct64_ctrcbc.c | 433 + .../libbearssl/src/symcipher/aes_ct64_dec.c | 159 + .../libbearssl/src/symcipher/aes_ct64_enc.c | 115 + .../libbearssl/src/symcipher/aes_ct_cbcdec.c | 111 + .../libbearssl/src/symcipher/aes_ct_cbcenc.c | 91 + .../libbearssl/src/symcipher/aes_ct_ctr.c | 116 + .../libbearssl/src/symcipher/aes_ct_ctrcbc.c | 422 + .../libbearssl/src/symcipher/aes_ct_dec.c | 170 + .../libbearssl/src/symcipher/aes_ct_enc.c | 112 + .../libbearssl/src/symcipher/aes_pwr8.c | 445 + .../src/symcipher/aes_pwr8_cbcdec.c | 670 + .../src/symcipher/aes_pwr8_cbcenc.c | 417 + .../libbearssl/src/symcipher/aes_pwr8_ctr.c | 717 + .../src/symcipher/aes_pwr8_ctrcbc.c | 946 + .../src/symcipher/aes_small_cbcdec.c | 69 + .../src/symcipher/aes_small_cbcenc.c | 67 + .../libbearssl/src/symcipher/aes_small_ctr.c | 84 + .../src/symcipher/aes_small_ctrcbc.c | 142 + .../libbearssl/src/symcipher/aes_small_dec.c | 176 + .../libbearssl/src/symcipher/aes_small_enc.c | 129 + .../libbearssl/src/symcipher/aes_x86ni.c | 240 + .../src/symcipher/aes_x86ni_cbcdec.c | 223 + .../src/symcipher/aes_x86ni_cbcenc.c | 122 + .../libbearssl/src/symcipher/aes_x86ni_ctr.c | 211 + .../src/symcipher/aes_x86ni_ctrcbc.c | 596 + .../libbearssl/src/symcipher/chacha20_ct.c | 106 + .../libbearssl/src/symcipher/chacha20_sse2.c | 237 + BearSSL-OG/libbearssl/src/symcipher/des_ct.c | 411 + .../libbearssl/src/symcipher/des_ct_cbcdec.c | 87 + .../libbearssl/src/symcipher/des_ct_cbcenc.c | 69 + .../libbearssl/src/symcipher/des_support.c | 166 + BearSSL-OG/libbearssl/src/symcipher/des_tab.c | 310 + .../libbearssl/src/symcipher/des_tab_cbcdec.c | 85 + .../libbearssl/src/symcipher/des_tab_cbcenc.c | 67 + .../libbearssl/src/symcipher/poly1305_ctmul.c | 260 + .../src/symcipher/poly1305_ctmul32.c | 297 + .../src/symcipher/poly1305_ctmulq.c | 475 + .../libbearssl/src/symcipher/poly1305_i15.c | 221 + BearSSL-OG/libbearssl/src/x509/asn1.t0 | 757 + BearSSL-OG/libbearssl/src/x509/asn1enc.c | 93 + .../libbearssl/src/x509/encode_ec_pk8der.c | 110 + .../libbearssl/src/x509/encode_ec_rawder.c | 161 + .../libbearssl/src/x509/encode_rsa_pk8der.c | 97 + .../libbearssl/src/x509/encode_rsa_rawder.c | 96 + BearSSL-OG/libbearssl/src/x509/skey_decoder.c | 650 + .../libbearssl/src/x509/skey_decoder.t0 | 373 + BearSSL-OG/libbearssl/src/x509/x509_decoder.c | 773 + .../libbearssl/src/x509/x509_decoder.t0 | 321 + .../libbearssl/src/x509/x509_knownkey.c | 105 + BearSSL-OG/libbearssl/src/x509/x509_minimal.c | 1745 + .../libbearssl/src/x509/x509_minimal.t0 | 1526 + .../libbearssl/src/x509/x509_minimal_full.c | 59 + BearSSL-OG/main.cpp | 63 + BearSSL-OG/main_test.cpp | 132 + BearSSL-OG/missing/stdint.h | 213 + BearSSL-OG/network_utility.cpp | 127 + BearSSL-OG/network_utility.h | 16 + BearSSL-OG/pointer_vector.h | 132 + BearSSL-OG/server.cpp | 326 + BearSSL-OG/server.h | 16 + BearSSL-OG/session_cache.cpp | 153 + BearSSL-OG/session_cache.h | 35 + BearSSL-OG/socket_utility.cpp | 160 + BearSSL-OG/socket_utility.h | 14 + BearSSL-OG/ssl_config.h | 30 + BearSSL-OG/ssl_debug.cpp | 147 + BearSSL-OG/ssl_debug.h | 31 + BearSSL-OG/ssl_errors.cpp | 73 + BearSSL-OG/ssl_errors.h | 8 + BearSSL-OG/ssl_test.cpp | 574 + BearSSL-OG/ssl_test.h | 44 + BearSSL-OG/stdafx.cpp | 8 + BearSSL-OG/stdafx.h | 15 + BearSSL-OG/string_utility.cpp | 239 + BearSSL-OG/string_utility.h | 18 + BearSSL-OG/trust_anchors.h | 33591 ++++++++++++++++ BearSSL-OG/url_utility.cpp | 36 + BearSSL-OG/url_utility.h | 7 + XboxCurl.sln | 47 + libcurl/include/Makefile.am | 5 + libcurl/include/Makefile.in | 720 + libcurl/include/README | 18 + libcurl/include/curl/Makefile.am | 39 + libcurl/include/curl/Makefile.in | 693 + libcurl/include/curl/curl.h | 2873 ++ libcurl/include/curl/curlver.h | 77 + libcurl/include/curl/easy.h | 112 + libcurl/include/curl/mprintf.h | 50 + libcurl/include/curl/multi.h | 441 + libcurl/include/curl/stdcheaders.h | 33 + libcurl/include/curl/system.h | 493 + libcurl/include/curl/typecheck-gcc.h | 698 + libcurl/include/curl/urlapi.h | 123 + libcurl/lib/CMakeLists.txt | 121 + libcurl/lib/Makefile.Watcom | 274 + libcurl/lib/Makefile.am | 154 + libcurl/lib/Makefile.b32 | 185 + libcurl/lib/Makefile.in | 4257 ++ libcurl/lib/Makefile.inc | 85 + libcurl/lib/Makefile.m32 | 387 + libcurl/lib/Makefile.netware | 734 + libcurl/lib/Makefile.vxworks | 177 + libcurl/lib/altsvc.c | 569 + libcurl/lib/altsvc.h | 77 + libcurl/lib/amigaos.c | 95 + libcurl/lib/amigaos.h | 44 + libcurl/lib/arpa_telnet.h | 108 + libcurl/lib/asyn-ares.c | 830 + libcurl/lib/asyn-thread.c | 760 + libcurl/lib/asyn.h | 184 + libcurl/lib/base64.c | 326 + libcurl/lib/checksrc.pl | 756 + libcurl/lib/config-amigaos.h | 166 + libcurl/lib/config-dos.h | 183 + libcurl/lib/config-mac.h | 125 + libcurl/lib/config-os400.h | 578 + libcurl/lib/config-riscos.h | 513 + libcurl/lib/config-symbian.h | 805 + libcurl/lib/config-tpf.h | 772 + libcurl/lib/config-vxworks.h | 916 + libcurl/lib/config-win32.h | 783 + libcurl/lib/config-win32ce.h | 448 + libcurl/lib/conncache.c | 638 + libcurl/lib/conncache.h | 87 + libcurl/lib/connect.c | 1472 + libcurl/lib/connect.h | 144 + libcurl/lib/content_encoding.c | 1020 + libcurl/lib/content_encoding.h | 55 + libcurl/lib/cookie.c | 1657 + libcurl/lib/cookie.h | 120 + libcurl/lib/curl_addrinfo.c | 624 + libcurl/lib/curl_addrinfo.h | 115 + libcurl/lib/curl_base64.h | 35 + libcurl/lib/curl_config.h.cmake | 1026 + libcurl/lib/curl_config.h.in | 1058 + libcurl/lib/curl_ctype.c | 133 + libcurl/lib/curl_ctype.h | 81 + libcurl/lib/curl_des.c | 63 + libcurl/lib/curl_des.h | 34 + libcurl/lib/curl_endian.c | 124 + libcurl/lib/curl_endian.h | 43 + libcurl/lib/curl_fnmatch.c | 389 + libcurl/lib/curl_fnmatch.h | 44 + libcurl/lib/curl_get_line.c | 55 + libcurl/lib/curl_get_line.h | 29 + libcurl/lib/curl_gethostname.c | 108 + libcurl/lib/curl_gethostname.h | 31 + libcurl/lib/curl_gssapi.c | 136 + libcurl/lib/curl_gssapi.h | 61 + libcurl/lib/curl_hmac.h | 67 + libcurl/lib/curl_ldap.h | 34 + libcurl/lib/curl_md4.h | 37 + libcurl/lib/curl_md5.h | 63 + libcurl/lib/curl_memory.h | 156 + libcurl/lib/curl_memrchr.c | 62 + libcurl/lib/curl_memrchr.h | 44 + libcurl/lib/curl_multibyte.c | 84 + libcurl/lib/curl_multibyte.h | 92 + libcurl/lib/curl_ntlm_core.c | 823 + libcurl/lib/curl_ntlm_core.h | 105 + libcurl/lib/curl_ntlm_wb.c | 489 + libcurl/lib/curl_ntlm_wb.h | 41 + libcurl/lib/curl_path.c | 199 + libcurl/lib/curl_path.h | 47 + libcurl/lib/curl_printf.h | 48 + libcurl/lib/curl_range.c | 95 + libcurl/lib/curl_range.h | 30 + libcurl/lib/curl_rtmp.c | 316 + libcurl/lib/curl_rtmp.h | 33 + libcurl/lib/curl_sasl.c | 629 + libcurl/lib/curl_sasl.h | 143 + libcurl/lib/curl_sec.h | 51 + libcurl/lib/curl_setup.h | 832 + libcurl/lib/curl_setup_once.h | 517 + libcurl/lib/curl_sha256.h | 32 + libcurl/lib/curl_sspi.c | 236 + libcurl/lib/curl_sspi.h | 350 + libcurl/lib/curl_threads.c | 155 + libcurl/lib/curl_threads.h | 64 + libcurl/lib/curlx.h | 103 + libcurl/lib/dict.c | 276 + libcurl/lib/dict.h | 29 + libcurl/lib/doh.c | 967 + libcurl/lib/doh.h | 113 + libcurl/lib/dotdot.c | 182 + libcurl/lib/dotdot.h | 25 + libcurl/lib/easy.c | 1160 + libcurl/lib/easyif.h | 32 + libcurl/lib/escape.c | 244 + libcurl/lib/escape.h | 33 + libcurl/lib/file.c | 544 + libcurl/lib/file.h | 40 + libcurl/lib/fileinfo.c | 44 + libcurl/lib/fileinfo.h | 36 + libcurl/lib/firefox-db2pem.sh | 53 + libcurl/lib/formdata.c | 950 + libcurl/lib/formdata.h | 60 + libcurl/lib/ftp.c | 4430 ++ libcurl/lib/ftp.h | 162 + libcurl/lib/ftplistparser.c | 1019 + libcurl/lib/ftplistparser.h | 41 + libcurl/lib/getenv.c | 54 + libcurl/lib/getinfo.c | 490 + libcurl/lib/getinfo.h | 27 + libcurl/lib/gopher.c | 174 + libcurl/lib/gopher.h | 29 + libcurl/lib/hash.c | 351 + libcurl/lib/hash.h | 100 + libcurl/lib/hmac.c | 132 + libcurl/lib/hostasyn.c | 128 + libcurl/lib/hostcheck.c | 150 + libcurl/lib/hostcheck.h | 31 + libcurl/lib/hostip.c | 1071 + libcurl/lib/hostip.h | 246 + libcurl/lib/hostip4.c | 503 + libcurl/lib/hostip6.c | 203 + libcurl/lib/hostsyn.c | 107 + libcurl/lib/http.c | 4110 ++ libcurl/lib/http.h | 257 + libcurl/lib/http2.c | 2437 ++ libcurl/lib/http2.h | 80 + libcurl/lib/http_chunks.c | 351 + libcurl/lib/http_chunks.h | 90 + libcurl/lib/http_digest.c | 181 + libcurl/lib/http_digest.h | 42 + libcurl/lib/http_negotiate.c | 220 + libcurl/lib/http_negotiate.h | 38 + libcurl/lib/http_ntlm.c | 259 + libcurl/lib/http_ntlm.h | 40 + libcurl/lib/http_proxy.c | 686 + libcurl/lib/http_proxy.h | 51 + libcurl/lib/idn_win32.c | 111 + libcurl/lib/if2ip.c | 243 + libcurl/lib/if2ip.h | 82 + libcurl/lib/imap.c | 2107 + libcurl/lib/imap.h | 98 + libcurl/lib/inet_ntop.c | 197 + libcurl/lib/inet_ntop.h | 37 + libcurl/lib/inet_pton.c | 237 + libcurl/lib/inet_pton.h | 39 + libcurl/lib/krb5.c | 341 + libcurl/lib/ldap.c | 1088 + libcurl/lib/libcurl.plist | 35 + libcurl/lib/libcurl.rc | 63 + libcurl/lib/libcurl.vers.in | 13 + libcurl/lib/llist.c | 197 + libcurl/lib/llist.h | 53 + libcurl/lib/makefile.amiga | 21 + libcurl/lib/makefile.dj | 71 + libcurl/lib/md4.c | 320 + libcurl/lib/md5.c | 568 + libcurl/lib/memdebug.c | 503 + libcurl/lib/memdebug.h | 174 + libcurl/lib/mime.c | 1904 + libcurl/lib/mime.h | 164 + libcurl/lib/mk-ca-bundle.pl | 558 + libcurl/lib/mk-ca-bundle.vbs | 431 + libcurl/lib/mprintf.c | 1173 + libcurl/lib/multi.c | 3076 ++ libcurl/lib/multihandle.h | 138 + libcurl/lib/multiif.h | 99 + libcurl/lib/netrc.c | 245 + libcurl/lib/netrc.h | 45 + libcurl/lib/non-ascii.c | 332 + libcurl/lib/non-ascii.h | 61 + libcurl/lib/nonblock.c | 91 + libcurl/lib/nonblock.h | 30 + libcurl/lib/nwlib.c | 328 + libcurl/lib/nwos.c | 88 + libcurl/lib/objnames-test08.sh | 217 + libcurl/lib/objnames-test10.sh | 217 + libcurl/lib/objnames.inc | 107 + libcurl/lib/openldap.c | 758 + libcurl/lib/parsedate.c | 607 + libcurl/lib/parsedate.h | 30 + libcurl/lib/pingpong.c | 522 + libcurl/lib/pingpong.h | 151 + libcurl/lib/pipeline.c | 403 + libcurl/lib/pipeline.h | 56 + libcurl/lib/pop3.c | 1546 + libcurl/lib/pop3.h | 95 + libcurl/lib/progress.c | 618 + libcurl/lib/progress.h | 64 + libcurl/lib/psl.c | 111 + libcurl/lib/psl.h | 47 + libcurl/lib/rand.c | 186 + libcurl/lib/rand.h | 49 + libcurl/lib/rtsp.c | 827 + libcurl/lib/rtsp.h | 66 + libcurl/lib/security.c | 581 + libcurl/lib/select.c | 585 + libcurl/lib/select.h | 115 + libcurl/lib/sendf.c | 821 + libcurl/lib/sendf.h | 92 + libcurl/lib/setopt.c | 2779 ++ libcurl/lib/setopt.h | 28 + libcurl/lib/setup-os400.h | 223 + libcurl/lib/setup-vms.h | 443 + libcurl/lib/sha256.c | 267 + libcurl/lib/share.c | 257 + libcurl/lib/share.h | 66 + libcurl/lib/sigpipe.h | 79 + libcurl/lib/slist.c | 144 + libcurl/lib/slist.h | 39 + libcurl/lib/smb.c | 1004 + libcurl/lib/smb.h | 259 + libcurl/lib/smtp.c | 1639 + libcurl/lib/smtp.h | 91 + libcurl/lib/sockaddr.h | 42 + libcurl/lib/socks.c | 803 + libcurl/lib/socks.h | 75 + libcurl/lib/socks_gssapi.c | 527 + libcurl/lib/socks_sspi.c | 606 + libcurl/lib/speedcheck.c | 73 + libcurl/lib/speedcheck.h | 33 + libcurl/lib/splay.c | 276 + libcurl/lib/splay.h | 62 + libcurl/lib/ssh-libssh.c | 2739 ++ libcurl/lib/ssh.c | 3337 ++ libcurl/lib/ssh.h | 245 + libcurl/lib/strcase.c | 177 + libcurl/lib/strcase.h | 50 + libcurl/lib/strdup.c | 100 + libcurl/lib/strdup.h | 32 + libcurl/lib/strerror.c | 1103 + libcurl/lib/strerror.h | 34 + libcurl/lib/strtok.c | 66 + libcurl/lib/strtok.h | 34 + libcurl/lib/strtoofft.c | 242 + libcurl/lib/strtoofft.h | 52 + libcurl/lib/system_win32.c | 451 + libcurl/lib/system_win32.h | 68 + libcurl/lib/telnet.c | 1699 + libcurl/lib/telnet.h | 28 + libcurl/lib/tftp.c | 1410 + libcurl/lib/tftp.h | 28 + libcurl/lib/timeval.c | 214 + libcurl/lib/timeval.h | 58 + libcurl/lib/transfer.c | 1902 + libcurl/lib/transfer.h | 73 + libcurl/lib/url.c | 4195 ++ libcurl/lib/url.h | 100 + libcurl/lib/urlapi-int.h | 34 + libcurl/lib/urlapi.c | 1440 + libcurl/lib/urldata.h | 1837 + libcurl/lib/vauth/cleartext.c | 169 + libcurl/lib/vauth/cram.c | 138 + libcurl/lib/vauth/digest.c | 1005 + libcurl/lib/vauth/digest.h | 47 + libcurl/lib/vauth/digest_sspi.c | 669 + libcurl/lib/vauth/krb5_gssapi.c | 401 + libcurl/lib/vauth/krb5_sspi.c | 514 + libcurl/lib/vauth/ntlm.c | 871 + libcurl/lib/vauth/ntlm.h | 143 + libcurl/lib/vauth/ntlm_sspi.c | 371 + libcurl/lib/vauth/oauth2.c | 126 + libcurl/lib/vauth/spnego_gssapi.c | 282 + libcurl/lib/vauth/spnego_sspi.c | 352 + libcurl/lib/vauth/vauth.c | 147 + libcurl/lib/vauth/vauth.h | 215 + libcurl/lib/version.c | 467 + libcurl/lib/vtls/axtls.c | 706 + libcurl/lib/vtls/axtls.h | 71 + libcurl/lib/vtls/bearssl.c | 1662 + libcurl/lib/vtls/bearssl.h | 21 + libcurl/lib/vtls/bearssl_ssl.h | 4306 ++ libcurl/lib/vtls/bearssl_xbox.cpp | 150 + libcurl/lib/vtls/bearssl_xbox.h | 85 + libcurl/lib/vtls/ca_loader.cpp | 861 + libcurl/lib/vtls/ca_loader.h | 65 + libcurl/lib/vtls/cert_pinning.cpp | 150 + libcurl/lib/vtls/cert_pinning.h | 49 + libcurl/lib/vtls/certificates.cpp | 858 + libcurl/lib/vtls/certificates.h | 23 + libcurl/lib/vtls/cyassl.c | 954 + libcurl/lib/vtls/cyassl.h | 92 + libcurl/lib/vtls/darwinssl.c | 2858 ++ libcurl/lib/vtls/darwinssl.h | 101 + libcurl/lib/vtls/debug_utility.cpp | 28 + libcurl/lib/vtls/debug_utility.h | 7 + libcurl/lib/vtls/gskit.c | 1381 + libcurl/lib/vtls/gskit.h | 38 + libcurl/lib/vtls/gtls.c | 1881 + libcurl/lib/vtls/gtls.h | 34 + libcurl/lib/vtls/mbedtls.c | 1086 + libcurl/lib/vtls/mbedtls.h | 32 + libcurl/lib/vtls/mesalink.c | 627 + libcurl/lib/vtls/mesalink.h | 32 + libcurl/lib/vtls/nss.c | 2452 ++ libcurl/lib/vtls/nssg.h | 39 + libcurl/lib/vtls/openssl.c | 3954 ++ libcurl/lib/vtls/openssl.h | 37 + libcurl/lib/vtls/polarssl.c | 931 + libcurl/lib/vtls/polarssl.h | 32 + libcurl/lib/vtls/polarssl_threadlock.c | 144 + libcurl/lib/vtls/polarssl_threadlock.h | 48 + libcurl/lib/vtls/schannel.c | 2302 ++ libcurl/lib/vtls/schannel.h | 108 + libcurl/lib/vtls/schannel_verify.c | 572 + libcurl/lib/vtls/sectransp.c | 3277 ++ libcurl/lib/vtls/sectransp.h | 32 + libcurl/lib/vtls/session_cache.cpp | 155 + libcurl/lib/vtls/session_cache.h | 35 + libcurl/lib/vtls/ssl_debug.cpp | 147 + libcurl/lib/vtls/ssl_debug.h | 31 + libcurl/lib/vtls/ssl_errors.cpp | 73 + libcurl/lib/vtls/ssl_errors.h | 8 + libcurl/lib/vtls/ssl_hs_client.c | 1967 + libcurl/lib/vtls/ssl_hs_client.t0 | 1398 + libcurl/lib/vtls/trust_anchors.h | 33591 ++++++++++++++++ libcurl/lib/vtls/vtls.c | 1354 + libcurl/lib/vtls/vtls.h | 279 + libcurl/lib/vtls/wolfssl.c | 991 + libcurl/lib/vtls/wolfssl.h | 31 + libcurl/lib/warnless.c | 508 + libcurl/lib/warnless.h | 112 + libcurl/lib/wildcard.c | 73 + libcurl/lib/wildcard.h | 67 + libcurl/lib/x509asn1.c | 1283 + libcurl/lib/x509asn1.h | 134 + libcurl/libcurl.vcproj | 234 + test/test.cpp | 3555 ++ test/test.vcproj | 116 + test/test_minimal.cpp | 578 + test/test_minimal.vcproj | 115 + test/xbox_console.cpp | 570 + test/xbox_console.h | 85 + 735 files changed, 329942 insertions(+) create mode 100644 BearSSL-OG/Tools/bearssl.dll create mode 100644 BearSSL-OG/Tools/brssl.exe create mode 100644 BearSSL-OG/Tools/testcrypto.exe create mode 100644 BearSSL-OG/Tools/testspeed.exe create mode 100644 BearSSL-OG/Tools/testx509.exe create mode 100644 BearSSL-OG/XboxOGBearSSL.ncb create mode 100644 BearSSL-OG/XboxOGBearSSL.sln create mode 100644 BearSSL-OG/XboxOGBearSSL.suo create mode 100644 BearSSL-OG/XboxOGBearSSL.vcproj create mode 100644 BearSSL-OG/bearssl.c create mode 100644 BearSSL-OG/bearssl_xbox.cpp create mode 100644 BearSSL-OG/bearssl_xbox.h create mode 100644 BearSSL-OG/ca_loader.cpp create mode 100644 BearSSL-OG/ca_loader.h create mode 100644 BearSSL-OG/cert-ee-ec+rsa.pem create mode 100644 BearSSL-OG/cert-ee-ec.pem create mode 100644 BearSSL-OG/cert-ee-rsa.pem create mode 100644 BearSSL-OG/cert-ica-ec.pem create mode 100644 BearSSL-OG/cert-ica-rsa.pem create mode 100644 BearSSL-OG/cert-root-ec.pem create mode 100644 BearSSL-OG/cert-root-rsa.pem create mode 100644 BearSSL-OG/cert_pinning.cpp create mode 100644 BearSSL-OG/cert_pinning.h create mode 100644 BearSSL-OG/certificates.cpp create mode 100644 BearSSL-OG/certificates.h create mode 100644 BearSSL-OG/chain-ec+rsa.h create mode 100644 BearSSL-OG/chain-ec.h create mode 100644 BearSSL-OG/chain-rsa.h create mode 100644 BearSSL-OG/client.cpp create mode 100644 BearSSL-OG/client.h create mode 100644 BearSSL-OG/data_store.cpp create mode 100644 BearSSL-OG/data_store.h create mode 100644 BearSSL-OG/debug_utility.cpp create mode 100644 BearSSL-OG/debug_utility.h create mode 100644 BearSSL-OG/key-ec.h create mode 100644 BearSSL-OG/key-ee-ec.pem create mode 100644 BearSSL-OG/key-ee-rsa.pem create mode 100644 BearSSL-OG/key-ica-ec.pem create mode 100644 BearSSL-OG/key-ica-rsa.pem create mode 100644 BearSSL-OG/key-root-ec.pem create mode 100644 BearSSL-OG/key-root-rsa.pem create mode 100644 BearSSL-OG/key-rsa.h create mode 100644 BearSSL-OG/libbearssl.vcproj create mode 100644 BearSSL-OG/libbearssl/inc/bearssl.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_aead.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_block.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_ec.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_hash.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_hmac.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_kdf.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_pem.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_prf.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_rand.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_rsa.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_ssl.h create mode 100644 BearSSL-OG/libbearssl/inc/bearssl_x509.h create mode 100644 BearSSL-OG/libbearssl/src/aead/ccm.c create mode 100644 BearSSL-OG/libbearssl/src/aead/eax.c create mode 100644 BearSSL-OG/libbearssl/src/aead/gcm.c create mode 100644 BearSSL-OG/libbearssl/src/codec/ccopy.c create mode 100644 BearSSL-OG/libbearssl/src/codec/dec16be.c create mode 100644 BearSSL-OG/libbearssl/src/codec/dec16le.c create mode 100644 BearSSL-OG/libbearssl/src/codec/dec32be.c create mode 100644 BearSSL-OG/libbearssl/src/codec/dec32le.c create mode 100644 BearSSL-OG/libbearssl/src/codec/dec64be.c create mode 100644 BearSSL-OG/libbearssl/src/codec/dec64le.c create mode 100644 BearSSL-OG/libbearssl/src/codec/enc16be.c create mode 100644 BearSSL-OG/libbearssl/src/codec/enc16le.c create mode 100644 BearSSL-OG/libbearssl/src/codec/enc32be.c create mode 100644 BearSSL-OG/libbearssl/src/codec/enc32le.c create mode 100644 BearSSL-OG/libbearssl/src/codec/enc64be.c create mode 100644 BearSSL-OG/libbearssl/src/codec/enc64le.c create mode 100644 BearSSL-OG/libbearssl/src/codec/pemdec.c create mode 100644 BearSSL-OG/libbearssl/src/codec/pemdec.t0 create mode 100644 BearSSL-OG/libbearssl/src/codec/pemenc.c create mode 100644 BearSSL-OG/libbearssl/src/config.h create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_all_m15.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_all_m31.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_c25519_i15.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_c25519_i31.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_c25519_m15.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_c25519_m31.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_c25519_m62.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_c25519_m64.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_curve25519.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_default.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_keygen.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_p256_m15.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_p256_m31.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_p256_m62.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_p256_m64.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_prime_i15.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_prime_i31.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_pubkey.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_secp256r1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_secp384r1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ec_secp521r1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_atr.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_default_sign_asn1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_default_sign_raw.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_default_vrfy_asn1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_default_vrfy_raw.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i15_bits.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i15_sign_asn1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i15_sign_raw.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i15_vrfy_asn1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i15_vrfy_raw.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i31_bits.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i31_sign_asn1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i31_sign_raw.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i31_vrfy_asn1.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_i31_vrfy_raw.c create mode 100644 BearSSL-OG/libbearssl/src/ec/ecdsa_rta.c create mode 100644 BearSSL-OG/libbearssl/src/hash/dig_oid.c create mode 100644 BearSSL-OG/libbearssl/src/hash/dig_size.c create mode 100644 BearSSL-OG/libbearssl/src/hash/ghash_ctmul.c create mode 100644 BearSSL-OG/libbearssl/src/hash/ghash_ctmul32.c create mode 100644 BearSSL-OG/libbearssl/src/hash/ghash_ctmul64.c create mode 100644 BearSSL-OG/libbearssl/src/hash/ghash_pclmul.c create mode 100644 BearSSL-OG/libbearssl/src/hash/ghash_pwr8.c create mode 100644 BearSSL-OG/libbearssl/src/hash/md5.c create mode 100644 BearSSL-OG/libbearssl/src/hash/md5sha1.c create mode 100644 BearSSL-OG/libbearssl/src/hash/mgf1.c create mode 100644 BearSSL-OG/libbearssl/src/hash/multihash.c create mode 100644 BearSSL-OG/libbearssl/src/hash/sha1.c create mode 100644 BearSSL-OG/libbearssl/src/hash/sha2big.c create mode 100644 BearSSL-OG/libbearssl/src/hash/sha2small.c create mode 100644 BearSSL-OG/libbearssl/src/inner.h create mode 100644 BearSSL-OG/libbearssl/src/int/i15_add.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_bitlen.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_decmod.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_decode.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_decred.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_encode.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_fmont.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_iszero.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_moddiv.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_modpow.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_modpow2.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_montmul.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_mulacc.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_muladd.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_ninv15.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_reduce.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_rshift.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_sub.c create mode 100644 BearSSL-OG/libbearssl/src/int/i15_tmont.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_add.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_bitlen.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_decmod.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_decode.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_decred.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_encode.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_fmont.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_iszero.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_moddiv.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_modpow.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_modpow2.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_montmul.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_mulacc.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_muladd.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_ninv31.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_reduce.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_rshift.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_sub.c create mode 100644 BearSSL-OG/libbearssl/src/int/i31_tmont.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_add.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_bitlen.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_decmod.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_decode.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_decred.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_div32.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_encode.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_fmont.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_iszero.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_modpow.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_montmul.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_mulacc.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_muladd.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_ninv32.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_reduce.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_sub.c create mode 100644 BearSSL-OG/libbearssl/src/int/i32_tmont.c create mode 100644 BearSSL-OG/libbearssl/src/int/i62_modpow2.c create mode 100644 BearSSL-OG/libbearssl/src/kdf/hkdf.c create mode 100644 BearSSL-OG/libbearssl/src/kdf/shake.c create mode 100644 BearSSL-OG/libbearssl/src/mac/hmac.c create mode 100644 BearSSL-OG/libbearssl/src/mac/hmac_ct.c create mode 100644 BearSSL-OG/libbearssl/src/rand/aesctr_drbg.c create mode 100644 BearSSL-OG/libbearssl/src/rand/hmac_drbg.c create mode 100644 BearSSL-OG/libbearssl/src/rand/sysrng.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_keygen.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_modulus.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_oaep_decrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_oaep_encrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_pkcs1_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_pkcs1_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_priv.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_privexp.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_pss_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_pss_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_pub.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_default_pubexp.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_keygen.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_modulus.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_oaep_decrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_oaep_encrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_pkcs1_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_pkcs1_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_priv.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_privexp.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_pss_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_pss_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_pub.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i15_pubexp.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_keygen.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_keygen_inner.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_modulus.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_oaep_decrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_oaep_encrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_pkcs1_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_pkcs1_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_priv.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_privexp.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_pss_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_pss_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_pub.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i31_pubexp.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i32_oaep_decrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i32_oaep_encrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i32_pkcs1_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i32_pkcs1_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i32_priv.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i32_pss_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i32_pss_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i32_pub.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_keygen.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_oaep_decrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_oaep_encrypt.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_pkcs1_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_pkcs1_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_priv.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_pss_sign.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_pss_vrfy.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_i62_pub.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_oaep_pad.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_oaep_unpad.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_pkcs1_sig_pad.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_pkcs1_sig_unpad.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_pss_sig_pad.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_pss_sig_unpad.c create mode 100644 BearSSL-OG/libbearssl/src/rsa/rsa_ssl_decrypt.c create mode 100644 BearSSL-OG/libbearssl/src/settings.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/prf.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/prf_md5sha1.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/prf_sha256.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/prf_sha384.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_ccert_single_ec.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_ccert_single_rsa.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_client.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_client_default_rsapub.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_client_full.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aescbc.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aesccm.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aesgcm.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_chapol.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_descbc.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_ec.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_ecdsa.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_rsavrfy.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_hashes.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.t0 create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_hs_common.t0 create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.t0 create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_io.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_keyexport.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_lru.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_rec_cbc.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_rec_ccm.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_rec_chapol.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_rec_gcm.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_scert_single_ec.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_scert_single_rsa.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_full_ec.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_full_rsa.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_mine2c.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_mine2g.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_minf2c.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_minf2g.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_minr2g.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_minu2g.c create mode 100644 BearSSL-OG/libbearssl/src/ssl/ssl_server_minv2g.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_big_cbcdec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_big_cbcenc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_big_ctr.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_big_ctrcbc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_big_dec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_big_enc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_common.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct64.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct64_cbcdec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct64_cbcenc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct64_ctr.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct64_ctrcbc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct64_dec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct64_enc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct_cbcdec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct_cbcenc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct_ctr.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct_ctrcbc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct_dec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_ct_enc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_pwr8.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_cbcdec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_cbcenc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_ctr.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_ctrcbc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_small_cbcdec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_small_cbcenc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_small_ctr.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_small_ctrcbc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_small_dec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_small_enc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_x86ni.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_cbcdec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_cbcenc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_ctr.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_ctrcbc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/chacha20_ct.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/chacha20_sse2.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/des_ct.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/des_ct_cbcdec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/des_ct_cbcenc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/des_support.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/des_tab.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/des_tab_cbcdec.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/des_tab_cbcenc.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmul.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmul32.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmulq.c create mode 100644 BearSSL-OG/libbearssl/src/symcipher/poly1305_i15.c create mode 100644 BearSSL-OG/libbearssl/src/x509/asn1.t0 create mode 100644 BearSSL-OG/libbearssl/src/x509/asn1enc.c create mode 100644 BearSSL-OG/libbearssl/src/x509/encode_ec_pk8der.c create mode 100644 BearSSL-OG/libbearssl/src/x509/encode_ec_rawder.c create mode 100644 BearSSL-OG/libbearssl/src/x509/encode_rsa_pk8der.c create mode 100644 BearSSL-OG/libbearssl/src/x509/encode_rsa_rawder.c create mode 100644 BearSSL-OG/libbearssl/src/x509/skey_decoder.c create mode 100644 BearSSL-OG/libbearssl/src/x509/skey_decoder.t0 create mode 100644 BearSSL-OG/libbearssl/src/x509/x509_decoder.c create mode 100644 BearSSL-OG/libbearssl/src/x509/x509_decoder.t0 create mode 100644 BearSSL-OG/libbearssl/src/x509/x509_knownkey.c create mode 100644 BearSSL-OG/libbearssl/src/x509/x509_minimal.c create mode 100644 BearSSL-OG/libbearssl/src/x509/x509_minimal.t0 create mode 100644 BearSSL-OG/libbearssl/src/x509/x509_minimal_full.c create mode 100644 BearSSL-OG/main.cpp create mode 100644 BearSSL-OG/main_test.cpp create mode 100644 BearSSL-OG/missing/stdint.h create mode 100644 BearSSL-OG/network_utility.cpp create mode 100644 BearSSL-OG/network_utility.h create mode 100644 BearSSL-OG/pointer_vector.h create mode 100644 BearSSL-OG/server.cpp create mode 100644 BearSSL-OG/server.h create mode 100644 BearSSL-OG/session_cache.cpp create mode 100644 BearSSL-OG/session_cache.h create mode 100644 BearSSL-OG/socket_utility.cpp create mode 100644 BearSSL-OG/socket_utility.h create mode 100644 BearSSL-OG/ssl_config.h create mode 100644 BearSSL-OG/ssl_debug.cpp create mode 100644 BearSSL-OG/ssl_debug.h create mode 100644 BearSSL-OG/ssl_errors.cpp create mode 100644 BearSSL-OG/ssl_errors.h create mode 100644 BearSSL-OG/ssl_test.cpp create mode 100644 BearSSL-OG/ssl_test.h create mode 100644 BearSSL-OG/stdafx.cpp create mode 100644 BearSSL-OG/stdafx.h create mode 100644 BearSSL-OG/string_utility.cpp create mode 100644 BearSSL-OG/string_utility.h create mode 100644 BearSSL-OG/trust_anchors.h create mode 100644 BearSSL-OG/url_utility.cpp create mode 100644 BearSSL-OG/url_utility.h create mode 100644 XboxCurl.sln create mode 100644 libcurl/include/Makefile.am create mode 100644 libcurl/include/Makefile.in create mode 100644 libcurl/include/README create mode 100644 libcurl/include/curl/Makefile.am create mode 100644 libcurl/include/curl/Makefile.in create mode 100644 libcurl/include/curl/curl.h create mode 100644 libcurl/include/curl/curlver.h create mode 100644 libcurl/include/curl/easy.h create mode 100644 libcurl/include/curl/mprintf.h create mode 100644 libcurl/include/curl/multi.h create mode 100644 libcurl/include/curl/stdcheaders.h create mode 100644 libcurl/include/curl/system.h create mode 100644 libcurl/include/curl/typecheck-gcc.h create mode 100644 libcurl/include/curl/urlapi.h create mode 100644 libcurl/lib/CMakeLists.txt create mode 100644 libcurl/lib/Makefile.Watcom create mode 100644 libcurl/lib/Makefile.am create mode 100644 libcurl/lib/Makefile.b32 create mode 100644 libcurl/lib/Makefile.in create mode 100644 libcurl/lib/Makefile.inc create mode 100644 libcurl/lib/Makefile.m32 create mode 100644 libcurl/lib/Makefile.netware create mode 100644 libcurl/lib/Makefile.vxworks create mode 100644 libcurl/lib/altsvc.c create mode 100644 libcurl/lib/altsvc.h create mode 100644 libcurl/lib/amigaos.c create mode 100644 libcurl/lib/amigaos.h create mode 100644 libcurl/lib/arpa_telnet.h create mode 100644 libcurl/lib/asyn-ares.c create mode 100644 libcurl/lib/asyn-thread.c create mode 100644 libcurl/lib/asyn.h create mode 100644 libcurl/lib/base64.c create mode 100644 libcurl/lib/checksrc.pl create mode 100644 libcurl/lib/config-amigaos.h create mode 100644 libcurl/lib/config-dos.h create mode 100644 libcurl/lib/config-mac.h create mode 100644 libcurl/lib/config-os400.h create mode 100644 libcurl/lib/config-riscos.h create mode 100644 libcurl/lib/config-symbian.h create mode 100644 libcurl/lib/config-tpf.h create mode 100644 libcurl/lib/config-vxworks.h create mode 100644 libcurl/lib/config-win32.h create mode 100644 libcurl/lib/config-win32ce.h create mode 100644 libcurl/lib/conncache.c create mode 100644 libcurl/lib/conncache.h create mode 100644 libcurl/lib/connect.c create mode 100644 libcurl/lib/connect.h create mode 100644 libcurl/lib/content_encoding.c create mode 100644 libcurl/lib/content_encoding.h create mode 100644 libcurl/lib/cookie.c create mode 100644 libcurl/lib/cookie.h create mode 100644 libcurl/lib/curl_addrinfo.c create mode 100644 libcurl/lib/curl_addrinfo.h create mode 100644 libcurl/lib/curl_base64.h create mode 100644 libcurl/lib/curl_config.h.cmake create mode 100644 libcurl/lib/curl_config.h.in create mode 100644 libcurl/lib/curl_ctype.c create mode 100644 libcurl/lib/curl_ctype.h create mode 100644 libcurl/lib/curl_des.c create mode 100644 libcurl/lib/curl_des.h create mode 100644 libcurl/lib/curl_endian.c create mode 100644 libcurl/lib/curl_endian.h create mode 100644 libcurl/lib/curl_fnmatch.c create mode 100644 libcurl/lib/curl_fnmatch.h create mode 100644 libcurl/lib/curl_get_line.c create mode 100644 libcurl/lib/curl_get_line.h create mode 100644 libcurl/lib/curl_gethostname.c create mode 100644 libcurl/lib/curl_gethostname.h create mode 100644 libcurl/lib/curl_gssapi.c create mode 100644 libcurl/lib/curl_gssapi.h create mode 100644 libcurl/lib/curl_hmac.h create mode 100644 libcurl/lib/curl_ldap.h create mode 100644 libcurl/lib/curl_md4.h create mode 100644 libcurl/lib/curl_md5.h create mode 100644 libcurl/lib/curl_memory.h create mode 100644 libcurl/lib/curl_memrchr.c create mode 100644 libcurl/lib/curl_memrchr.h create mode 100644 libcurl/lib/curl_multibyte.c create mode 100644 libcurl/lib/curl_multibyte.h create mode 100644 libcurl/lib/curl_ntlm_core.c create mode 100644 libcurl/lib/curl_ntlm_core.h create mode 100644 libcurl/lib/curl_ntlm_wb.c create mode 100644 libcurl/lib/curl_ntlm_wb.h create mode 100644 libcurl/lib/curl_path.c create mode 100644 libcurl/lib/curl_path.h create mode 100644 libcurl/lib/curl_printf.h create mode 100644 libcurl/lib/curl_range.c create mode 100644 libcurl/lib/curl_range.h create mode 100644 libcurl/lib/curl_rtmp.c create mode 100644 libcurl/lib/curl_rtmp.h create mode 100644 libcurl/lib/curl_sasl.c create mode 100644 libcurl/lib/curl_sasl.h create mode 100644 libcurl/lib/curl_sec.h create mode 100644 libcurl/lib/curl_setup.h create mode 100644 libcurl/lib/curl_setup_once.h create mode 100644 libcurl/lib/curl_sha256.h create mode 100644 libcurl/lib/curl_sspi.c create mode 100644 libcurl/lib/curl_sspi.h create mode 100644 libcurl/lib/curl_threads.c create mode 100644 libcurl/lib/curl_threads.h create mode 100644 libcurl/lib/curlx.h create mode 100644 libcurl/lib/dict.c create mode 100644 libcurl/lib/dict.h create mode 100644 libcurl/lib/doh.c create mode 100644 libcurl/lib/doh.h create mode 100644 libcurl/lib/dotdot.c create mode 100644 libcurl/lib/dotdot.h create mode 100644 libcurl/lib/easy.c create mode 100644 libcurl/lib/easyif.h create mode 100644 libcurl/lib/escape.c create mode 100644 libcurl/lib/escape.h create mode 100644 libcurl/lib/file.c create mode 100644 libcurl/lib/file.h create mode 100644 libcurl/lib/fileinfo.c create mode 100644 libcurl/lib/fileinfo.h create mode 100644 libcurl/lib/firefox-db2pem.sh create mode 100644 libcurl/lib/formdata.c create mode 100644 libcurl/lib/formdata.h create mode 100644 libcurl/lib/ftp.c create mode 100644 libcurl/lib/ftp.h create mode 100644 libcurl/lib/ftplistparser.c create mode 100644 libcurl/lib/ftplistparser.h create mode 100644 libcurl/lib/getenv.c create mode 100644 libcurl/lib/getinfo.c create mode 100644 libcurl/lib/getinfo.h create mode 100644 libcurl/lib/gopher.c create mode 100644 libcurl/lib/gopher.h create mode 100644 libcurl/lib/hash.c create mode 100644 libcurl/lib/hash.h create mode 100644 libcurl/lib/hmac.c create mode 100644 libcurl/lib/hostasyn.c create mode 100644 libcurl/lib/hostcheck.c create mode 100644 libcurl/lib/hostcheck.h create mode 100644 libcurl/lib/hostip.c create mode 100644 libcurl/lib/hostip.h create mode 100644 libcurl/lib/hostip4.c create mode 100644 libcurl/lib/hostip6.c create mode 100644 libcurl/lib/hostsyn.c create mode 100644 libcurl/lib/http.c create mode 100644 libcurl/lib/http.h create mode 100644 libcurl/lib/http2.c create mode 100644 libcurl/lib/http2.h create mode 100644 libcurl/lib/http_chunks.c create mode 100644 libcurl/lib/http_chunks.h create mode 100644 libcurl/lib/http_digest.c create mode 100644 libcurl/lib/http_digest.h create mode 100644 libcurl/lib/http_negotiate.c create mode 100644 libcurl/lib/http_negotiate.h create mode 100644 libcurl/lib/http_ntlm.c create mode 100644 libcurl/lib/http_ntlm.h create mode 100644 libcurl/lib/http_proxy.c create mode 100644 libcurl/lib/http_proxy.h create mode 100644 libcurl/lib/idn_win32.c create mode 100644 libcurl/lib/if2ip.c create mode 100644 libcurl/lib/if2ip.h create mode 100644 libcurl/lib/imap.c create mode 100644 libcurl/lib/imap.h create mode 100644 libcurl/lib/inet_ntop.c create mode 100644 libcurl/lib/inet_ntop.h create mode 100644 libcurl/lib/inet_pton.c create mode 100644 libcurl/lib/inet_pton.h create mode 100644 libcurl/lib/krb5.c create mode 100644 libcurl/lib/ldap.c create mode 100644 libcurl/lib/libcurl.plist create mode 100644 libcurl/lib/libcurl.rc create mode 100644 libcurl/lib/libcurl.vers.in create mode 100644 libcurl/lib/llist.c create mode 100644 libcurl/lib/llist.h create mode 100644 libcurl/lib/makefile.amiga create mode 100644 libcurl/lib/makefile.dj create mode 100644 libcurl/lib/md4.c create mode 100644 libcurl/lib/md5.c create mode 100644 libcurl/lib/memdebug.c create mode 100644 libcurl/lib/memdebug.h create mode 100644 libcurl/lib/mime.c create mode 100644 libcurl/lib/mime.h create mode 100644 libcurl/lib/mk-ca-bundle.pl create mode 100644 libcurl/lib/mk-ca-bundle.vbs create mode 100644 libcurl/lib/mprintf.c create mode 100644 libcurl/lib/multi.c create mode 100644 libcurl/lib/multihandle.h create mode 100644 libcurl/lib/multiif.h create mode 100644 libcurl/lib/netrc.c create mode 100644 libcurl/lib/netrc.h create mode 100644 libcurl/lib/non-ascii.c create mode 100644 libcurl/lib/non-ascii.h create mode 100644 libcurl/lib/nonblock.c create mode 100644 libcurl/lib/nonblock.h create mode 100644 libcurl/lib/nwlib.c create mode 100644 libcurl/lib/nwos.c create mode 100644 libcurl/lib/objnames-test08.sh create mode 100644 libcurl/lib/objnames-test10.sh create mode 100644 libcurl/lib/objnames.inc create mode 100644 libcurl/lib/openldap.c create mode 100644 libcurl/lib/parsedate.c create mode 100644 libcurl/lib/parsedate.h create mode 100644 libcurl/lib/pingpong.c create mode 100644 libcurl/lib/pingpong.h create mode 100644 libcurl/lib/pipeline.c create mode 100644 libcurl/lib/pipeline.h create mode 100644 libcurl/lib/pop3.c create mode 100644 libcurl/lib/pop3.h create mode 100644 libcurl/lib/progress.c create mode 100644 libcurl/lib/progress.h create mode 100644 libcurl/lib/psl.c create mode 100644 libcurl/lib/psl.h create mode 100644 libcurl/lib/rand.c create mode 100644 libcurl/lib/rand.h create mode 100644 libcurl/lib/rtsp.c create mode 100644 libcurl/lib/rtsp.h create mode 100644 libcurl/lib/security.c create mode 100644 libcurl/lib/select.c create mode 100644 libcurl/lib/select.h create mode 100644 libcurl/lib/sendf.c create mode 100644 libcurl/lib/sendf.h create mode 100644 libcurl/lib/setopt.c create mode 100644 libcurl/lib/setopt.h create mode 100644 libcurl/lib/setup-os400.h create mode 100644 libcurl/lib/setup-vms.h create mode 100644 libcurl/lib/sha256.c create mode 100644 libcurl/lib/share.c create mode 100644 libcurl/lib/share.h create mode 100644 libcurl/lib/sigpipe.h create mode 100644 libcurl/lib/slist.c create mode 100644 libcurl/lib/slist.h create mode 100644 libcurl/lib/smb.c create mode 100644 libcurl/lib/smb.h create mode 100644 libcurl/lib/smtp.c create mode 100644 libcurl/lib/smtp.h create mode 100644 libcurl/lib/sockaddr.h create mode 100644 libcurl/lib/socks.c create mode 100644 libcurl/lib/socks.h create mode 100644 libcurl/lib/socks_gssapi.c create mode 100644 libcurl/lib/socks_sspi.c create mode 100644 libcurl/lib/speedcheck.c create mode 100644 libcurl/lib/speedcheck.h create mode 100644 libcurl/lib/splay.c create mode 100644 libcurl/lib/splay.h create mode 100644 libcurl/lib/ssh-libssh.c create mode 100644 libcurl/lib/ssh.c create mode 100644 libcurl/lib/ssh.h create mode 100644 libcurl/lib/strcase.c create mode 100644 libcurl/lib/strcase.h create mode 100644 libcurl/lib/strdup.c create mode 100644 libcurl/lib/strdup.h create mode 100644 libcurl/lib/strerror.c create mode 100644 libcurl/lib/strerror.h create mode 100644 libcurl/lib/strtok.c create mode 100644 libcurl/lib/strtok.h create mode 100644 libcurl/lib/strtoofft.c create mode 100644 libcurl/lib/strtoofft.h create mode 100644 libcurl/lib/system_win32.c create mode 100644 libcurl/lib/system_win32.h create mode 100644 libcurl/lib/telnet.c create mode 100644 libcurl/lib/telnet.h create mode 100644 libcurl/lib/tftp.c create mode 100644 libcurl/lib/tftp.h create mode 100644 libcurl/lib/timeval.c create mode 100644 libcurl/lib/timeval.h create mode 100644 libcurl/lib/transfer.c create mode 100644 libcurl/lib/transfer.h create mode 100644 libcurl/lib/url.c create mode 100644 libcurl/lib/url.h create mode 100644 libcurl/lib/urlapi-int.h create mode 100644 libcurl/lib/urlapi.c create mode 100644 libcurl/lib/urldata.h create mode 100644 libcurl/lib/vauth/cleartext.c create mode 100644 libcurl/lib/vauth/cram.c create mode 100644 libcurl/lib/vauth/digest.c create mode 100644 libcurl/lib/vauth/digest.h create mode 100644 libcurl/lib/vauth/digest_sspi.c create mode 100644 libcurl/lib/vauth/krb5_gssapi.c create mode 100644 libcurl/lib/vauth/krb5_sspi.c create mode 100644 libcurl/lib/vauth/ntlm.c create mode 100644 libcurl/lib/vauth/ntlm.h create mode 100644 libcurl/lib/vauth/ntlm_sspi.c create mode 100644 libcurl/lib/vauth/oauth2.c create mode 100644 libcurl/lib/vauth/spnego_gssapi.c create mode 100644 libcurl/lib/vauth/spnego_sspi.c create mode 100644 libcurl/lib/vauth/vauth.c create mode 100644 libcurl/lib/vauth/vauth.h create mode 100644 libcurl/lib/version.c create mode 100644 libcurl/lib/vtls/axtls.c create mode 100644 libcurl/lib/vtls/axtls.h create mode 100644 libcurl/lib/vtls/bearssl.c create mode 100644 libcurl/lib/vtls/bearssl.h create mode 100644 libcurl/lib/vtls/bearssl_ssl.h create mode 100644 libcurl/lib/vtls/bearssl_xbox.cpp create mode 100644 libcurl/lib/vtls/bearssl_xbox.h create mode 100644 libcurl/lib/vtls/ca_loader.cpp create mode 100644 libcurl/lib/vtls/ca_loader.h create mode 100644 libcurl/lib/vtls/cert_pinning.cpp create mode 100644 libcurl/lib/vtls/cert_pinning.h create mode 100644 libcurl/lib/vtls/certificates.cpp create mode 100644 libcurl/lib/vtls/certificates.h create mode 100644 libcurl/lib/vtls/cyassl.c create mode 100644 libcurl/lib/vtls/cyassl.h create mode 100644 libcurl/lib/vtls/darwinssl.c create mode 100644 libcurl/lib/vtls/darwinssl.h create mode 100644 libcurl/lib/vtls/debug_utility.cpp create mode 100644 libcurl/lib/vtls/debug_utility.h create mode 100644 libcurl/lib/vtls/gskit.c create mode 100644 libcurl/lib/vtls/gskit.h create mode 100644 libcurl/lib/vtls/gtls.c create mode 100644 libcurl/lib/vtls/gtls.h create mode 100644 libcurl/lib/vtls/mbedtls.c create mode 100644 libcurl/lib/vtls/mbedtls.h create mode 100644 libcurl/lib/vtls/mesalink.c create mode 100644 libcurl/lib/vtls/mesalink.h create mode 100644 libcurl/lib/vtls/nss.c create mode 100644 libcurl/lib/vtls/nssg.h create mode 100644 libcurl/lib/vtls/openssl.c create mode 100644 libcurl/lib/vtls/openssl.h create mode 100644 libcurl/lib/vtls/polarssl.c create mode 100644 libcurl/lib/vtls/polarssl.h create mode 100644 libcurl/lib/vtls/polarssl_threadlock.c create mode 100644 libcurl/lib/vtls/polarssl_threadlock.h create mode 100644 libcurl/lib/vtls/schannel.c create mode 100644 libcurl/lib/vtls/schannel.h create mode 100644 libcurl/lib/vtls/schannel_verify.c create mode 100644 libcurl/lib/vtls/sectransp.c create mode 100644 libcurl/lib/vtls/sectransp.h create mode 100644 libcurl/lib/vtls/session_cache.cpp create mode 100644 libcurl/lib/vtls/session_cache.h create mode 100644 libcurl/lib/vtls/ssl_debug.cpp create mode 100644 libcurl/lib/vtls/ssl_debug.h create mode 100644 libcurl/lib/vtls/ssl_errors.cpp create mode 100644 libcurl/lib/vtls/ssl_errors.h create mode 100644 libcurl/lib/vtls/ssl_hs_client.c create mode 100644 libcurl/lib/vtls/ssl_hs_client.t0 create mode 100644 libcurl/lib/vtls/trust_anchors.h create mode 100644 libcurl/lib/vtls/vtls.c create mode 100644 libcurl/lib/vtls/vtls.h create mode 100644 libcurl/lib/vtls/wolfssl.c create mode 100644 libcurl/lib/vtls/wolfssl.h create mode 100644 libcurl/lib/warnless.c create mode 100644 libcurl/lib/warnless.h create mode 100644 libcurl/lib/wildcard.c create mode 100644 libcurl/lib/wildcard.h create mode 100644 libcurl/lib/x509asn1.c create mode 100644 libcurl/lib/x509asn1.h create mode 100644 libcurl/libcurl.vcproj create mode 100644 test/test.cpp create mode 100644 test/test.vcproj create mode 100644 test/test_minimal.cpp create mode 100644 test/test_minimal.vcproj create mode 100644 test/xbox_console.cpp create mode 100644 test/xbox_console.h diff --git a/BearSSL-OG/Tools/bearssl.dll b/BearSSL-OG/Tools/bearssl.dll new file mode 100644 index 0000000000000000000000000000000000000000..d601c32d8a8b360b33cb23ca22b63ed97b6dee01 GIT binary patch literal 256512 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%0DXCJS9m4)h0^Pnmos7l@9A2IVj{_fJIPQ8P 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%0D>=h6V)(h6f7pG?<=Rl9-ZGl$n>7uc2wB0QMe( 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

AkMu7v51AEb=G1+-u(G`RbH7$sOSWO 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%0AyYxcimfM0Ia_a+vUbM1yw>YJ+!1dI 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

1%OHup5`BnrADA0O7j6GP&Wu9#mxvFm;GPN z^S_wo#a{*xPvU>E%>QDM7w^Hdx+-a)LqXFz*+I)2EnQSh%6LI$7@urD#+25{V*!@# z4P)Zpej=@tt=AEhI+zaxWHAK2ILE@o0G@zoKEjjM>Ba=o2l3?p5*4Qx@#Y|3vhZ&| z0CJ5>KzP`TKY5HG|7d_tYW-iV@*>6>q(q_hZHX1w9yCjO-I%f%0$!xCK-yP60bwtG zWq?d5W%*yq@Inr(8{GYY4v5+ydK8;KfodL5aR9D)AdOVeq=x`#=@fqpXebMGs$no_ zdR?ITp8$Uo8)(Cn+yCCU|IEjkZ(5%y=dixd-wZlTieEtV!4waM(C&A=@jTt%dmUMt zpMKE(2)dvLw59=+YQgcJ#-Hc#r#D(4jX%%(Nv{KFe~I&x=0l)m6QDJp;5DEjr_%V- zPeO2=#~YBA4{7{)KI|VrTVU8fK$bm%);pfyM^y__=I{k%_M0^RI_EdIRe}^b`~ay0 z8S0G3%pcZQ`I}t-|NjrVw+B=R#9Ch~meu~*%fhAoX+jrAuLEOOh{gX7AB+DT0pR7t zuj8X3mERfA`fPBBf`U+je>;0xCtLF|rrrqtgRfbbZwG^x)U0A+VgQd=rFH7@Z)XRc zIF{DQ-doNDYuyEaRJAaH*Pfa*ACc%jsQSMiv|pPIG%3dq<{W$}m)7ad((BH|d^oMs zpAB@dPXMH+^UDO3g20IkR1qtL2fvt}!^ptD-J7ZV1IRYzv)V61!-HQq`hqfvLiaIH z%LJArn%}5^Cp>M!Kwhv3=ihGLeeB>17VQts$Jh`4V-5@LEK#v|u@&4o<}tnvN;)Ot z{M&f6x({A_!F9O%W(SLw)4|8=*4K(&@^9zw&1397c=4@fj*3U~1AdR*NdAK_{&cJH;RV7PP*GKl};kylnpP+x+3*KJ(Xw z_=2tt`OIJE@dBJc6EA=+e$qI^9|q;0;153qQpf&*KkOq&-3QS6Xnv522M`?~75rg0 zt$kEH%GP$*sMzp_-2>f;5cU+ydT4$P(ETDeIQYXJr196?;1>XMS-3wy1RikTus&6; z(aYkm{l5E`_D^^I?IIez4ov*pJ^pdu0xk9hO>4XY*#f?i`CRwm?>E2S;6BHFSoy^F zi>)Us6}x>@96)`6?hqA&)|34GZT~>qw_?FXUv%>kmBaCIps6ui-pj2tl zeHgSt)S&qRe^_{LHK*z`wN4SkV4L&?P)7oh2$7uerKwK$qcw#-oBk zQEKx-71YXbQPF8W!qa-7lxGJ+0%#YzOD)4|L;md{wG5z=Uzq#C4$uLZX`C*#|I#`` zY8hUG4n$Jf0cy6SU4D?peJHKdrIsPBnUC4{Qd&2k@onR8{M%20ubvk%J^(7qKqn)C z)^vatmw`5>fUaEN-)`CbjIsM%_w~zjz(RFuw<%qb2eEX7fYl z%a0f#hY*VJZ##AH6$kUh?sK3OHkY5fF&_tyR)7|QfzGgD1~ojmy00=H1g)8CeDt4@ zf#Kj=&gO$m%&$N;T9>E@6m@imsDMoB{tTL^dB)Ft>fmdZ?u*Qy558n+e#FmwaVIBe z;mNOquUML&^E3Yf4c5tn9Kxmjb0?^Uq&6!kzLNibtN9VD_OI@%&5!I4 zzGY*+3Oag&x%nYG^QrC&nI}P4#x*|z%}Qxs*bxq@77saTgBor!-6xDsDW5Vvu|pet z0vOna23{ zBui8rn*TAEvNr!zcrDlbkF}Jw`9I@pk>-EwrR=t#m6ESHn*VW^iZuUX1SPKCQYMfK z_*>?HH0P*TbjPTGcFgPWZ?9!&KF)veJ&SvD!>GL65xn8937ti9%K{GG+hz#x6#`;F!UOrWtw5C%^ryS(uI1?oSD zfP&=!f6M(p;A|M(d_)0Oo`d!mfpVHaShpakL>K8T&_I=?F8DZ zv;#D<-Rt+i`3TQ0P<3Pdp)3w`?PUPJhN!`O4~FK4^1+WJ^AXPTmjyMy(y zqVJ$hIQ-jL?3$nQm-2#ZwX{wayZE@+!#lyNX3k#zrF?;Z`yrSpxD3fC5Oe}<;sXu% zV#P0{z$2ls0BC#zntw!$7sarE=c7_sAj=3qv!UZfj?Y7`e0mEI5)mF5HT zy*z(GDi6M3*{cb*t1OR<(b%gz#bfutlBSn zZ5kmV8Hg5=wxBa=JK38Nv-0jNpjP*XAIPED0Sm>>C`c$4Dx-!XC@i3%Xz?5rilC5# zgd#X8g9%V;ks};3lJ&og<9`{;3rkR+q)egv2WYUYOyGYR&kHpM1_tBfpe>c46Dkja zSG|9~p?o|Z-tGh&cIM2P#y4|N);G)mt#6p3vIIo+s4QS(V1OJ8v4suN-`~T=zyM40 zijJV217E@GK31^7XCkVffgBGq_HeJ$Z`=P23=HMBTmP5vgT@b$@`LrS@*}PPOAc87 zDrM_pvtlgY*5$(WUxnF*xpd7p7xVv&B}-u$#LWPdL1I)?K)X|$56fpU9(>ILY71(- zs7_>L=+%)9?Tt|}0JZX%?`AOszbO3<31eOZ1_n?%cS-AH?sZXd$zliyesRMId^!y% zK0*S5Uz`MSkAP0CkN`{X1oL@7MX}=l|NlYSC3QN7xLdP9DFISeB%2}<&WLRnjbKNhR|L%|3f-T9vr3A zPah2^>7xdeFs7(g33%~Lh5^*| zR{*V6%3=)YjkZ7dnzb`VMdihtQc&`k3+fDjl86o@d4zq1B#(6|`vG_#vDXn?u*X7Ng(y`T->g9?pI1Q2=N+K( zIkbC?3W(8}qhbSEg>`_1fg!y42Qz=uRb~c;6^#5XXF<*CFph3Nmexzq{0*7^2GxbI z%+KGx3^ds1!u6k#zhyQ^N1Q-+9Z&1+65g~44UqX1&^&stGo-NKZ!ZI@w+5-t2B~L* z3=M;>MFOp}jAVvZodE$abaX%^gNsT?Z;476#J9oWy(Vs9FNDA{Y&-w|XJANU^ifG_ zKER*G=m%;MC4er`?6q+Ve{uF7Fy-tjsB`N|JL6w3={NvzzdF8*#zq@Z4$Ee6C z-|Rl8?V}=Me5?EW!PoNN?{#17KBjzE*+oT06ErvBq9S5^!PrGbK>31ljEamg=uAEh zaQ~qDkn$9;XO&%4RJ2bhpVRbFQ2=e|>^`Usx(G->`B?X7?F--UfyZ|Rx{q~V1kHA6 zx~Rw)gHGZEnG7};Y^DM>GeLW0l+S4&()3Z$P(G#!I!OO(^EXEB@89o%u0`lR2x^*l zU%&XG`4OY>!SA<}j~RpRJW#m!0(?HyDP-bJb5u+iJ9AV-_*+x{{r?Zz zYtG2u3Oe`#G=kV$qvF+T;N}kF2XKi8RR}GQ$SYqKL(3O%X+gMrDFK%k;PNFCR9+A& zUqCAYzqwe0$`?zJdbILI9jScj5d$|RLB&f1#K)lGr7i45F-U^#zmG~v^8xw)ek}h> zR1yxpV0GxVX$yaG4XId}1saw%Z$2h}@EvO}%T`by4OXi7zXX>mpuvK$fESK=j0~NS z(-WJIIP`kRg9;T^v_hp5R4zaZ70~!b_X$v+A?V-(d1jX_KEW4X1_Zv~sAgp7blHMZ zs9XmXDxj5)-4qupETd(Li^`xbQ%XTC0Gr+#6`x+4_U?1X*%iSB3QzaJgD>Sl*I3kd z`g3%;gVL-=*b7ah(&PXC`hzd!JK@Derys|Qo4zQe#V#?NrA6Z{w9*39zW|+Wh3Nl* z&M<&p_tV`2z6`i~3iv+4U{DJKbb@Mc3}`j=9`I!i!2y9mVJ|>uxHKOTX+2OX5g!Ly zpARy`_{<9-uyr8w4})@)K){QC6`*-%&92g5=T z@miqUQ~@L+0}=rdVW8E&AlC=HU=?Cu_`gME2Ll7c3r#Tw(EVnh)x{uw!2fcN-WC$~w3G|>I z)IJ3*zXn}&9q>Z58g!;-FXS9VkTXE%1O~j26NEO7A*U9CBtRzz2E1Su1lt5EU_gQ< z%;0uXzX$_EZx8s$#=zbd6$j8v=drMW7v&-#Cpv%zm3muLctA^Dh1@T)s=$RPXb)4si`oj1Cly)`lw%K_y^zcOKyo1K!vbDB7G_}hZ;ovI5|Fz<2h4%@<#+c$t_%Iq z*#kbM6SPttv=`~1{K1#32Oly8f_nV_UNACTeBaxmvXz;E0ldr`bU}>(xBpC2w zcR3>iXtxRYSjk?+DsMoG%|Rgu zqCvVr7dQlfLfr@CX;5+kTdM~SPM==Lg`%OL-~wHJ9`M2yYAZMa_O_^mfRux@feZu% zE{Ol)yfA3~7IZu%h}+wu0@`2_@S=hbv|hTmMdb?Updj$_deFv?fEWAuz{!gnbowgj z`U!9dg7$(0yjTK~Is#hf4@$CNmw+R+w?zeXH5kZc4IsN;L<=)8fUetsIVvpt1&0tg zaZUiq_wtyB1-|$OO2)?hQE+y0Hpz)Zpe+=&_Z6g7>X9p9wj1cJtl}!TOz6_w!^#BtC!{ry@pi*iRX#V`Ac!>;D0#_ zXnYcsg9Bc~@Pb!88oX#01iJv#B{v8F9p(u-$~G+E#cp1Z4;4VglP(i@ZG%EUa4(A- zC zWXQR|!Qk@n)qPOXm)Xn+N&27z_ds@mTHVma`5@PwfTmE$Ijd%+;H6$6y)EDqCI4?x z`2yOWRiY9S@ZuM^%MKbYQUK*%7nPEL7i>J>gd5Q7qGA9t95i7N@ZtkE0|RLJKX^+H z=n`;{6evxAXdRG+FV+fxlO`w`fdmCW@fYwSoFAew1|$Z$4+unqGafYm2fQc&mt{V^ zE-E=7$pxU~6YxR~R7{i$g#9mN>1_e;dJ1^)>K-GcVEY4B1M=(Dm`sDO33_^!7_MU@Fu%J+gpAcY&;P6pkgR?+LC zq5}$=7Vw?Q0WV%~!9xce6rkhL172L>f));-wSOQ#fQ}Chc(I#{f#LfFWl#|SI*2{s z#VYVJXcOh*(5$)!v1Lo}5-6*JG6X2Af_of|Z$LFWBEN!yo7DD31~?O9wl@}C1X%|% zAJ*RJ11+Zk9egbUYHu{$#n#@)LFfXz5S3_r11f0{?xnc>u^+Sju?AG#Q`Y`CDg|zT zYy-7FPKtnrTtKT?(V8Hj@&%mb%q8J@+yK%90ToP;{Mmd2oP$A?IOtv>P-z~}?aG4M z2m$T)3wV)GhSmrHExitSA*l-;zC|=bKzjlMUNGo_TLKrr<$Q|@Xoe~*;Dwb0xDf){ zOAKm+fYLrQs1c$h0dgd)5i$XkB|t@3XuyjZi@}W$eo+4kluO`p0WV^g{{IhhHmE5A zt}j6u50rR8m!t>0SO*$yY*B%}bU z0WaFcp>2^lplSuAIRaEI!`mWh@Wx0QqBRl+IwE8H$>xLnpw(t4!R?W}2hjEis9OxK zO(E@(ZxWzkaYz#+trKU9WW6@Xk=R=#leNK%Td}lAUKV3(kz6i@wManm67VAU7N}S@ z*$pk0e}Fs)x<>#Mc_=Ls&|%h~AOKad0Wao&O9PY^38aBg47C-#MFL8cAng?(gJ1Y+ zgO>J!nnfTk=u}=1{US{Zx@8g3A_2D+UaZvur!~|T38>Bucrghig}p_R0W!3=MTG_A zsTVgvhS#VVAhk%AiGquL5s*BjMKVPclp3+ONVLv^${kQS0jmE&?Epl1L1BC3> zfEV|`t7yRm+HdqG320+)z>7Pe8UoTJ0kv)*O_K2IptLUox(5-|8V9xgKuHv>Ndj(@ z_qM1&S_+HvL1WIK3lpHN5oq-c+CCKU!W6tA6}3_FQ5~Fi(HbSU)fo|u5?EshR7-+f z04W_bG{EI3sG9;3gf>b(2_ZE~z?reP1$?6cNDa6=eDNM+;}LkH1at^iaKMY5LJSPu z<)DiPL3_ABZIgf(q1P}PC7=dBxJX5Bl%zpgC7_}X+ALWHI=~67sB69rDyuLXCfp*R zqRvG{2Q*ZV(KI=$1`i{orpb0SXeqG=Tq{71t`2yyK#dW#X>vaoWGB|9N!dwI9s%VI zc+&)2@q-4$o8O2u|CHx%=L9905EYqjCdkmiPtfcFXd62Rbd3dQIJ@}>X!9XY_lMU1 zC8B8)8tfQKxj_5KJ8M)pNUAU;-0_ zV&T5feNg*YC+I{cP=h@bG#}d?qM{KV7}U+w?Z5#(*3+T+2oK0!MR?uol(1oWa zC39QfmdpfIU9r)v2TDL<2Av$;J}Nq$9xR;|9Nov`3%95y}xA|dBxg>@S>|C2BG zsCDa(QQ_%6*UbzHpc3$*;u5X@OS$>CwK>f9V2F>4KHTjr6867{<9`tg=ty`U(5V#y zttU&KbXKy&cN)fZI&wrGjstBd00%$Fd=}#a-CWHF?GL_WZT`tv<_=n4CIDXZ^8I#L zcyAGl_N(5?|Iqat-F&@eEZre`f0!>aU+6vrx=Qqaz466^FXWXk8(-`U`vY40b_>)| zgTyoFei+itzo;Fe_eYx;^Mk?bEG0k(go3J0hSvWj&Y_^m4}bn`I+oohy011L;JEyV z`x9vOSMv|~8VT@awDrv|r^1b9AzS!WR;3aI*OgXtl5jXi)$IWIPYlzXjA_>JCwH0iSPphy|2HyF*lL zyqK?R$Edh;#;E9Y$Ebi#I#aPeU(CwC&FVFi@qfsQy5?gX+^?Gd$@BLt1ubU_QITi_ z-Ai5H{7%06F4(`FB`OBm=eplterp|~qEQ~xT%#fa8X^!V;RYo` zcXFXFngpLu6W(pn`oEO3+eL+^(;`0dFnBwaNUu9+eIEGK2tSriJIH=8i5Fhi7#X^c zci%twg0=aveD{gw!|VqivNj*#(FV<($uQqM_?p?<`bLo`XoOHE>_ruLTMIFO#6HH)$VhbA9SC;{EGV! z$T)=;Z?YH}c7T?Mbf3HY1GKgE=xdIH4>-7wHXr8zo!V|4qoPo>A-45@iBWfn3QzZW z&>E(0v&+x8KkNW4>d`(9N#6m%FBrqXopz0|;1|=t$61JgT?kLQU-3R&CAJ@LXzaF%@ z^bm-Bf`9!fi0B9Y^&h*B@vlGL{G9Ro{pJ@;{OgY?ACCvm7(iDJHNSBH<^2+s7?7DE z-E5ugy&3Wc-?Da}?aWcJXny#o(?><4*PjKtB@wjk@Wu1Xj10!NL0728sMxf=nh zHPw7nB6?ZYcbBNdG#>vmB|(7wJ;0q>D@nv%G0ccIQ$7|5>UNWEqp1TizSCQ)e(S54>*mq^{ zP3Jnors-J&6T;FS>y+=yq2L z{xyH)nZJVEUBuD-uK6MZB;@$loCP^cr1`J_C{=cva5NthXg(+anWhd=kpLA^psQ;6 zTVH_6o)VQ9SQK@~sCabOsDyx`oi;O^ z`PY1v2N_(n1C&f&vvgn62AzRx1KPF8d>7<^?!({+IQSZLwt-D2=r#ZcP%3IZ$kLpn z;=%|@OZ=_dK&x~=bhBkKgoSsqzX<>F|Nr;fpc4AEJogRIVY#k9KwW+bNbYffROR3- z1g>rcy3HZ;x1a-t!Oewm&>}N~G;m4L3_3X%xB&3{Iw+3>bc;71vOoBW zwU=cosD1=By`WpsLG>I|lo_;+L!y^O2(&!F`a>}nY(>1m;oYnZ3=BIJK&?7?hF(WT z{`H5fkCkzFUp(3To3Z{K$PSP2&KQ-H7yh8?1C*bRa5Vo0RXP!%Lyy8sxkFz(IR$p> zYkyG6?v>FCesSp(cy(e1s5{PZ`9bp$p5`A+W$L{d|3F;|=FcE9JUHwH7kK-pNcTNZ zx&v)|e$btxBGO%=64D)`644DhWR3yL;>XYD!N$h~W-)|=_I85mp5rX-ppx^&_Y_73 zt zgoK8N2fr}-{U3CAyFqaHi{mFjfujJ5NU-OcYgA$w`TIcAG9dr;`m%KTsF-v!bh<*@ zJfKQ6iy`m@AIOt2Dk?ic-U5|xJ}L&xcP&BJ_qJJqN~0PTf!^}}ouKQQAm{CZ629?4 zuzJX4;?O1p=)Tr8{=7qJ`~?>ntbg*i-3ARpg7#E_=0rhF@!o2d-hw~P2mUZ0X8vmF zqGD3cVf~%I8MF!*wDYL9*aWnKsQYqvj*39@1Agrnplv21`~rR#nhy%}Iym%}IduQz z4>`pz;IM%|>;%7{#|C}@AAtk>0uBd2!eF5T`~rR(_yrs;z(p?b3;2Q5Jb;Tlus&O~ z0@MNlr33346@g+caPyI+7nHoae={G|{;T~F)_&%(=yhOGKE>(r2Nb*?Ko?$vx)-41 z^?F(Mf^;}C-{|yFF|Y=OTGJg+K~n>62}Xd@SQsc7f_5J@|Aa(Ww~LC!_Z!?UDi*;9 zU&x0Cym<8&y!<(#`G^XrjD5N8@BjZ`UEwe0$AIFM2b@44S=#_9Ya{YE54e)#-+sOO zoc1YD1$a^W5dZpv{M%0us2A%QVCP_i4Lbw6F90L|^KTb#J|ute6$>bLyQs*ZWPTw? z#>bcI@n(4)eMSaQ+1QMk{{As=oUrFDw9zc5e6mH!Lqm;ar_ z!OcZ*{yz%xCPw~W3Ch7PDgnK|OrZP^_A00Zfch0w0Puo5ilYEX18D~p0O6p;dn%Cg zMnU<1AE>l2KG+Rfn|T8h^n72J3(PZJ^VnntuuKH=O}>Ye4r- zR5SGk{A)h&kNGh3RcQXd&fg3=xd)v8gQdXv|1>oJf95YZa6|jWClJ-^&IKx0ZfKvM z@R`5P>qW1F!e{=vL%l%?{2?crkAZHg&}CiTQ5r~DCa}V zifjDaKf=xnPwNI17))u(=h8Sm{()M#pe=GL@FGK|+7VG$tjASYq=`b}7NfA(`xCXW zXhakiMzNqofL>UD`cU8vjy(L^C7KU|_GPx-E)@iwHxV5Af)8AA@We(R237YW#+Qsw zLOTcFN_6-^^9O#-KRIeetbdpD@^5FUxcq?m0;qlF-h7b1LqxCnCC9;69If9+omiHZdz+kno63h(7%us+A{bguazi!ta<0Ts}CP~+S14)uTI zx1ez#(70i*7gKkLiV1k7ijRtgC-XV&5EanQMupB06&>q$piZ>mYbN7w-RHZnU4GPj zoP+yT^M8K+o^A#PhQ`OB4L!~8`MWQJ)-!@T(cSm7&tC>LN;NEfR3yrs!5v*t8?}T7 zw6Rb5LRzN?-)ndN?VOM@kwy&P6nJG zTmP4s@XIssZ*$TA?|=D0^Fa>o3(Y_IYlONFHNS*xqD|{$DRw*fiof-L>5bNtC9G+k zBE@dKZvO*%otXk&OmYRKAC9z6W{{2G$UFnSuSo#3IS14PvOoBO)%rp)v+;q$psK(} z1=I!;2FyDhA;DyU~(EI>TXWJLh@!>Gj&zu1*i3RBa zk4=Ny0wF5k8#M%)53z)X_hx{~9+~dn2j8-2|LgVUceValuGH(sZ+*B(y89UTwAwBn z_Fe}@(3#$^7)wF@6`9vO`~rOZ0?hp3C-?>VK-&?*g8pv++5DpB2j~(IHqfwPuQxxa z(RfUt`Mm(YATy|GxF|k08ro5WR)`?Cq57u;?4K6!F+SM+1HDrMJRlDmQUVQcf#OX8 z>>sdSdIMRs|G9$VOMopb=>JBL+dzl@%e?T8XJqJg2D!}oL%AZvr&3U#g6=m)@hqB0 zL8FJq1VES1f&A1P$O84&EReS#w;*8prvvPtC10_}4`^Hgia|F}3%u|K?bdcb4vdpkl4pMa4+_N3R>G_bmZhiQoZRo!|We zT3?o^2!J+}gYK;|05L%KRvCgApnI!~x{r0Zs2GDz@&G9?0Wm-dOhF8g0yEI~H%Q6? z!~jWIf*2qvE6{>!kdzIG0g|!>F+fsw;B_3Jj>P{G6^)J<75k156=z5e=d_Yh9j?6H2jf8prug!A z`>5E&b;PoFgmQPd@_}yxtKR@B1Wgd-Qy{3Ml>m+Tv_aZ2Jiee>qxk?!FzDP|P#;aE zH;_5J`zNS``T_0{M=-f|9|DJI_hoQ+2C*1;`~_b|01D4v;PCXZ`oq5s6rg`V0eS<} z(FN74pa_FR)QgLs!F9b1sE|4g%Fv(^YFT_-bZjKTeW1L8T0X4+=jSUQvFB${XoB?6 ztGu;IXJp_PprpLr1NILK9{*5O-p&Rcs!PxE_5#>HCLgfJPxBiEM0qF!x|Rhr3IK{R z6VO134X8x~x>2h2KYt78kcME;t}waociOLe13@RF+ko!J>~`P)l}w92v~-{#k#^1(+%qWPEr=)}zCqoA!p zBE5kupnA47=KufyvE7HG9j)Kc z>$mwULHTEJ)NhK3jNpC$B-U>%3qbveC7-e9=f*dn__hKJ+QPBZ)??KxUp|lN@24Cv(BK$i8Xk9UA%K~V% z0e^QmOLsm;w>uB$>NL;(8_8B&~g{>dD{xmW`Ngsu!K&)3s4URJnmQqYIs>R9|2t$q|;ra zV$$jNqBHDGXWoa-x-XzL44vT3e>Ezg_NYK7KlFlv&U}u}aF$MY9#99*_{@t*%Ry^A zK;eb2Js|-OZ<9~B!W*=95fR>?B{JPT;HA5u_2mwr`x-#O4%%4(3U)+zgDz}R33$Q% zje((ik4gf#2f+inr^=h7JD8_iyVFHQ05o~i8KNQqs_iU6yA_Ucbi08LqI2kW`_l zK)?$DP=n1yB?NSV=h03#(D}_Cpsl8zZlL+10Am*wkxtNTSA;R>z(F?_kbA>G18T-D zDlXli5&94no9-MHl}$zIx>UV$6ZuFE72MFw>h$c zTH^fM0$IQk{M#JaU<`H`gOmFP|29W1aNm%BnV47j0WG;YK$Gk5Phg3FfES4$z@0z`P&r~@T%!`u?eU{K;E%D7ii2^8 ziU+79?5g4EWQ00F=RWx?8|u()5+YC1B5x{wkbjw~Qrpu>?BM00dF zvULQqgQuzwfedhj_Bb7(Jx)iijzDhE$@n1E5*>~_AX=cqkrzaBbU1&)PY?Tlan<;hY{La05DXR9rwui*?qh$h?^G0d#MqF9Yb@Uhn`*C~SZwmIpDw0v<|%46uOn zm@6wcXk~*4|29`P{%yV-;A{jLQ-NfuZZrOEuAJPUL%s~a!z+;M?p?XT!zbXO70{rJ z1bAo#G(rO&S^+UY9pBCv6@_jGP&p1-pd|z8!f1eGx*b48IVg#xFflNIw$;>va$Agw zK<^e6J0=DO5AA;kU$8VE=5PQnJ`mwQ0h%Q4bWyQ^=02D1W8fSY;>LdxbUI%5x$ieY z%PzPMq_UL9d z2KAvp6_PWHv5N|*aE<`oqY?1p>l<)#bpX{KDWD<%mRxfn>DVXW#icjk>=@8HMI{JS zLP82kQ08<|aRHAeKyT0K22~3!;3NPVZt84N0bQZf>--C}-UK|}02;p$2lvlF;|(~* zZ#&e4-3Y zkI@|N@CB`IQvqd1S5S_T>4@d;2xX7&^Z+ezQRy`3^Z>2G)QIc!;DKfc@CeS{d7#V# z$~52#t?>;g#~|{L1!#h3#$ZU9aF z7TpKId!}pu~=RhR^Xsr(SIY`=v4Aw~?Cv(){I#9X?4SO-40F6ID&C}_I*kb~< z#|E0qT$=w1lv%lTgRBwxev>3ipcR-#z>C8#!8t|;lw$%wIYtLsfmuPal10Fa1uwxl z#-{m*NM{T9PA^bXsk22z2NcOJDi)nBD&Y1g=!BdW6;MM3G$z^!*;&@@qGHksX`+Bm zuRvrjmrh9LYW}NGmJC|M*Xz!-543!xcM3SX;aLna1cEb*K@vgpafN0V6&Z!*x1fnJ z(Ar6nPKXSDtN*|M|6fbDzAX{&?E$-A`+OIRWp6#Bf%|{ZU>|5Q1FQp7`GVFcfX0m_ zI@m#!K!-aci00^UXX-xI;SL=Zb%zd%x4bLx)A(p~Ir?ypXKu z52}_x z{|elX0_90iKZ>tAjHNq|quY(=xQmJmsJU?5MMVWlqx8r?{VdR>)SzA*D6+i|zGi7Y z&f(nsq1zqS-*Sibx7eZmEq4}UP)>pNx00WO(-&rc>lQ5Gy>NIAKBCp2w;rXxRia`7 z>SIj>ugU}6KINh!5Z}qy-J=59$BbWWE{^nOfr1Uu$3kmga~x;$0k^N8 zWP>{9Je_Tz?UG1SP>pX?Q1zclA1Rga`cJ3^JkD zMWrI(g?!{)C+{Z$tgg-*~x zPHwQ8O{AL*TC+)jdaaO}4RpAk04R5cfC!6#7Z)?Y9U+^57w-9BmIG*K1!!3Y)KM?^ zLEFo~7u=}kgD1F4K-U8OFHtG^U!oEN!T~Q)DWHG_&wC?{7jhhDO90152zUi9w)j|p5+8Fw=PmT8EP+PL1{MYeP_%&P zUPq3A{~N)v(W3GOv~}J`MFi9mlL2)wUQ8;2M2-q5a$0XPFm$g`xd4rvxBM-wpv|e^ zi?zeMj~;x%)cn^WnBN(EyHQENi_n{(Smf#5q5|5M*IT2Kvzvv1fgx=|c(0p6K-de{ zbZ~NNJ}%IFj02QfpZ7wyU-AlAeGFZs&yzvL^!|1DoYJJ+C8_=_j$j0|qgM?^p__{UOn z1Jsk&>0YA(I)jT}z(+-fA2c`XqoULN*P$rQ_y8>Z@e8=H*zgPZu;f4#u-G&o5NQ5k zQ1gsmpap!;253wfyhB$YAQ;p&*LYEJgMp#>FlggP^IHe-N>GSB;Lzi5-TUwV|Cc7< zBW9Vv2g7zkqC%rAIuQoZ(0bN={cs#&%n@7$?DO3;)6r?)!rBt z9qkLfIVv{bTY$SicmIHlhYPUC_r|E?fSeoyTBTO+0CqS}AHM)kcW;bJ4Zna(F9TT2 zrF%AQ0@_dvm5D);0j+zBQPHtJRWlPBa=oR0x{s;w+b|WGb{|t^ zggNk^L-$qf3%xEqF`)G^Ep&MQgO<1W^yoAnWU@Y0^T_&atx#`BPfRyc zZxD;2OOKAD_1T(F`~ogpazK|+8Gu$7NbdWZUUw5<|91d z0?v0TC@+CB1-M?oEZ<7N`H2ORAhDEhS5Wd3C zpkATG3%7j8rZ9~x=71NL*BBT+^Vhkk7&IS|Xx^jp0hBX9DI7Y-;i6&yW?6vFV*|55 zXKDxVx4i;Q>-MP30%hsL+6TLPR6y2;f;!*e%R50SAC!(2x)1hlQ30)MYI+@+K>8d&$|0M|J6ph!-s{K=k_doEfOfHU zLJ~PN8`nWr8Gtg;F%D3R0F;eE76-g|oC(gSpdDqPV)g|C19%_21~eNl0Tsb5D&SoH zVmtU!6i_x!F#gs%M+J1+0JOdMzvMH^f0NJuw|oH=Bv2~+g=z{)_Pq((wb1LLl8_|; zvJ7;{Ucd{+tKc$=g%zAon*TcRw}H+L0G+PX>&&#z0d!{16qQ9RpoTDUlgd6S0?lt7 znh!g4u2J~`DhiK-va<+id3}uvXtAw8>s$WTN>E4SV0>CGF+TI+_#{v&1SO@z z-DklKswpa&q-W64u!#N!=nT~E9+e1Cnrcx=fhKFv`Lf{AXwb>Cpw@e@BdF?z zRTiL4<&bVWX!j84wzbq8Mh54;hwcy+9cWL&1vEAT?z4c#&1AqVAJ9+$XtXQ2*=b2zbGn0B*g253c~9>Co$ugYQ12uHn(uUSz}XVK750UF8YAe`BTy#nbx|q!zXhBh|8G$N z84INXUhGT&g_FboE#M*nMwO_58b_c;QAxmyX$g#=9bX!t(E!jH$Sx`(0?lhwK;bIT z?f#?N|4+AgcRgsV&d1nA#lhG|#RW8k*Ic7wz|dLE0vbRCbs;*Pe{_2P=@jmcQPC(7 zG5!G`mAh&D%D6;D;k6WK;H3Kpcrfs$ag0hx_bcNZl?c$dT=O2Vb)ZpC&12 zgL9y*=%6Aw26X4Ei%Ldkj!FQikstA5R~$Gva{^u%q=H!mpl}0kxCM=5K*Q||Xc`_I z&RnVBKm!$Qplb^MZ-E_Q0;(mUp%d_;B_13iCCx`nKu4E%=cssem#Fwa2lpgELv0cr zj35d;uy+VFjsU)H8n>&ZZ+@eJ#MvUexOu%2=ssEh&?58#>- zRJxow)A$C|AV-uJ;DVwDe2Fk<{seRh7^pp20;&JNM|go^9nr7^)drnDDkh+c&;~S4 z`ob~;t*kJImlg1W0$NBYzzYeSg@Xp!g#)-)=yqoTjUaWqgT}=Ty4`uQK%12;Kshao z0W`#7@S<}b_B*h4^x9aOP{gi8Wmtbqs@ z1iVm60xKv1DF8K{L8V9lG&ej;2bUtC>NMcR&qQ#B096Xm6VLu{Q2`kVEmJ_ufEUH! zy#k;D*yH~e6;N>oqe@hA{+Foa1iT1{0d=ihRD7C`i1a%D0*@*7P5}omzhDcvj+y`; z+#tCA%Lg)k=+S%}Gy?#dZ32xOf(CCxKpR=WV}^d9syar+05nGlTIUKHW02@z22lbX z&Ws?Mqr;i0!lP zpfN%TP~LWij%PSS$1|LHLDHZlUJ77ozD|G0xS>CI)UeYZG-wFQU7hC8PGL(ID0_l( zBU1J})A(iyO8XSlsOaud0kwd@`=@qjCh?dIAk2f=+uWU=K}P}i@_;v=?EtkZwZXk$6Xt`UR)+U1Q0>Xn zTcT3XTcctCZg@jm&khk_Ddg6(i%LPjixrR>2_@%QKyzMB3R2Fij{_M1YBw8z+s&Yy z25T^ve5v_g@}(yH#jgmIrt*DI<=P7xa{)J%!G-mUYbU{DFQCRMXtl$ChqCnU92Es< zXm{7B$UvIQu1xU!M_~LOk~Er+I)DZj9h%=efO1G@j*3DjM25fB2{gDU-}=8qx*K%n z!4#DOP{dyBV&UrbWHfO64_;ga(gmK$0$m~uS}y<|)Mo>YHugG_(LcldF4_o#qQ?8_Lmy2Op8 z+YZ#chAawD=yrotKN_G`AE^4NQBirpHG>f}LIleApv$K~s|`-_x10uz0hFll^j3mS zCKdtJ#V(*~=sjqj$sIKR1F98NAhiN$ae+oRGkBqg4yaB5Wgi3Z2o&f}YEaQ{6YyeV zD7e6P2za3$17^8^ihgiQ5#sO{?-Rk|0Rb;qW5DBMpz}UF{+Fm!fKKNH;eZ$2pi4Pj zRAPFgL9;gzp!ScCiVkSc1*o429srB`{~xqv4qf8AZ8f;2wHa-3}ixc?IZJ{*dtv#o^@We*u> zxvU6iiUPcr-$#YR7qs$S0Mw0==nZ5!_?Ef(7*n__|2DUOy>PIL=>JBLr7sFW7kvA(^plKkxpjNO2fB|piSq|vCyLfKuaeDK%43$dgED+v+r5p!4UjnBKRmKp3ZiVY0dvQ zN_m4{oGl0CcoxvX5xwCYz1tfY85s6UfVZxKs#FGsZnrwO*0ELA^IQRtbI8bnO z=d-|lH@OJB1x=;5i~~IH#Av_{S^#0-_8qkJ!NBbY|29Wv1Gk_2+ZO)XH2^sbWg>Els!3${g^My?fBWR!#I)c>twxrOv z`54o|x6H2L;Qk>0Hs;>Ce;~g)Gm?@jKxgKLgPKqh|2Keae6hKTk)fL%lsNoZK&gYd z)0+h}f-*0@yGLaL3j+hB)ah#iC47*dAfW;|Y6302JOQVdgO!jVK~67o!G|eQF}*at z0l5uP-hl$PyGI2SuH7vvpf)lrbU~|tF+x}%;KePF$6HijA$*{u#-sTdQ}DqT%nqQT zES~UgSX%3KQIP?MnG7_{>MN;|<^&*Vu5?;_EcmozP+%LMd7<103Tlw|AVCezBi$}4 zEX^;(OFWxjFqY_p2+?jI6%O#m9`NN+-9nv$-3*7pf)QIi7Pb*_2RbXZ zm!%=R*QV8Fp$7w0g|)jtiBvr3=DF@36_8HjGcWemgF+c(=;5$%P|YI|9PlEIiGd;f z{}vU{d0E|{^BzHG6*q#bPSCBb!7rwQj#%tb0iDLyd_<@FSX?}KaJK+q7}z(U{wioD z1L0nfMIeWQHZb+NsIb5s3reM+v&X^%!d^&#dI2>m65#>CFJ!tI8G2c^H6IbNwrLGn z=)ury0`^ghXsTcAS&p^gO&^oIt#xCS~h8QjAPe(?&tQV?{+EU2;v9lr#2 z>d`uozd?>eN?joLf^Hr|xc3gIncJfB0YvqHkKP40<3ZQ1gECZi3;2xRP8Ssc=m8+0 zC5X&NLEiZSJsTHv4r#9p*wxn60wwIm2VOp9U|?ya=oXg*hmI;bGqR29y#I;SEZ_p!5Msz@W4NI#mul ziUA5Jursn4fqlwboS|F?&j|X@0wzTT+I27xt9fW zTnd9F{5ZU(s|9^AP6^7j}9DAL8!kEtm2E6#U_5Xk67oeGc z{%sQ7?9HE9x-CF!271fw558kP_>3v+e*p(*EpWh#;tucFG(qVXbbcfvJkLN9?iJ8kxZQJ9Kw%FaNCq7u-OU^h zTAtCnM+KZSG(hu)tlBS*F|u?s?*!el^?7NxLGw}egKwF8-9Vc;LB~LV(gp(q1IRZF zy^IVQ7eMI-bdYH07Vta)D1CsAw>l0vtrX-jNO=ORm+i^}c64xe zEJqlqktEW)2YhCDx2s6^XK?xk4LFGOLQ+7$=cS+_Fr62t7#SGA8hiJsya0_je+C_j z&d9* zvFY6d4iShmTU0c_u7mJOR2+Kus61c>xtD*NahH#Z0oZu~mqAAsgH{*>G(ThRKGyxO z`2*AU`yL11%O89pAMj%FZkRtHC(<{6V+KVXXpOsHz`=L&VJ{kYgO|(rG#_yQ2Led? z2RN=;RL+1-@_f+`DvnB2K*!>OPCAF!3odrMk1HPwcwvuZ#}kl_UKbUQfbL`8FDM@m zc%itPf#Li0<|78m-$5(snsZbHKs&&B_&cBf`~Uwx=%#^Kf!5pnttTM$flP0SiUQcv zpO-?rgz?~Mm|vh<5T3?@b3x-9&p--WnAJ(6%Pfdf?AXySJ!-6o75*-J=33jXp004LNQHojxn?z|j4p`^Lfd z9NnNBdz&BfAAG^n{G7k}F+XVdrTGU7e|s$GK5dm&pC~7W?8832Au0;Y7kYhE6ta)| zFrVNTVB!~K_{?ADQ`Cvf!3xN&)|969yMSjR)_-`EkB4NXS(6MaX#{xjS zAdqZ`ib?Ykm6y*LAcmBvD1Z#gVr2dRF(mAT_J;reLG5Cd{{~?%_O1W_AGGzk`G~|z z&~b~PWyb#tc>Wt?9|XBTgZW?pL?6gE2LoQ5+X7av(tJeZCFt%bkosl|Z0_>MU&;6>c#|NpaHR8&BQ=`^&Mu(L2Q{DT_`TGI};4U{24{r3QJl`K?8&NV8Dxfaj>|^_Y2KOSd=e-qL6>PD^v4PCeSSqfuLjry07RrJRx--0w*O0 z#A*2J%0NX8C=DH+Fek!^;c0{ugI1&yLtLa2Ltms5L*pAzRk-kgt0#l;kjma#;dye}R02rTqnREVTXg3~T!fR8_&-U#?)Mf*c3Vw@~MvX?$~o5&8a1 zP{jqBas?HHJu0Bq7`XifDsG_dFHn($wfzNZcz_msf!blcGOZw2W46CQRaF3v_Sb~Z zphL27wZA}B6uA8biUdge>pisn1u8@l?XR1l_E*j_r1lr+uG@eYjNplISo_Ncq#z*R z#cR;a4dgukfERh7g#MxXe8xS{hgY@Er^DH$*e+O&v-zY!(CPo`malkY*UjbD%2Qy#?G1OY7VNo?r#{uhKeOR6s=> zs8N=&U>R~t40ITIFGfoY)Ix=ZYh@8ATtNYOxbY3>W(7oef{tJB?ok0X!$83b3j0t{ zUIV3MMEeVrGx)b_fLdNhcbbFlhkn8Gd8zh`Ze~#P>o0TKQvU4*y>9XcU$8JA0M)~w z#TOu-)HXw}<4o(^0=_{gQ#shk^al?aBkIV7pyG zjWST0`n)s)l;UA6GEmnq0Nfr+Tl(S!s6_?}h2A|Xpu_FEK`kT0Og}JP{Ryz z55^tP$>T3Tl`%MN!rEkMO_*&m@Nq^h;6MT;Qy-PAG|(9HUK;2kK8x7Q`gSOG`ZbY=vKtThFY*6rlXwWqX z0WW4F+GwCoEZ8_uH{T)v(ngz&WXBPVHd^gQ&|)2f@7I;TgWG4Ih8pNxQvS}zsBN?( zpvtvI1=20Ix}mK!SZNRHugIXJ9MHv6po{_UV$(a#0J@A7+G0~U4L;BT++uqPZn1gwmZ+qF41%=SK!$|9_<0JllndNq z>j9Y2SIMg0XMHeIzc`<81O<1Vhgy<)(p}CYIt)5 zA_{I$>IdDT{SVY)yR#M2Vgngf(BNXC4QZ}_53@j+eJ z!`Q|rn)iT@!*>LwQ*fK9dk?r@ULqN9d;m0p391Q<&%8(iI|@{`9}dfM>~&EQ2oHD> zt;_&g;{$3mfLnH;5v+DS@Y-^ffEQ;C!7R|_EyQua!u} zgAOML4L>q6Fc_bCVF$JXWai<}EJu(VWddH9D}loZRL*t3042ZRfEUTSpppo5V;d;Q zTmP2||KFk_0$TJO@IqZ5B**hwImu5%+kRhc7b1@rRNA}(C#1yf7prUp8_?{ z_`^=|L)M*xg!ly@OVGjR!quH<{wY!`2r`Ger3bW>$+7vTNX_T&58v-`e*j&a!N|by z{Tis-{i0iifguBwfI!!kfqUC7DhdJJ$G=|y^{C&j2FIR8z>CF@c+>$67U{e=stryo zpzvruqM-a8H2M}B-+c_+KfaX-ibil4pJ{#*0gF5r@V3#I;Lxz}EJ!`H-oq;TPbs z0I!{fN(lO>xTH~v=EDI9CpP{E&1CR51w&3v1J7de zZ$EhOr9dZBrx$2q%Z7jZ!A_?Dkcd|ZXz34_&jIFxE*EeB^CQ6g7|=QsFkb-72c6#L z0_G=x`6-~eaxh;4%mo!)LH=vb%Ev?LEE-LqD~edAurH*!4XhTH-XCE z&MwemIM9~y-c6tdU|_WlV6~u)_cfCnv%1Bp6$fP}n23*{2B0w88) zF?2S823o^9yFkO7FMfc=Uwl*wnvd`tX9Ja*&}MNGcnx<1Qfm=Z--8CPx~Hgs7TAO4 zHjTQEfeHvvm#ABwfBoU^e3tIB{Oiv_7dCf0v2;T2qu^hEnE6Dv6GvwYc(oE}g;)!C zSyLzUUd(6x`yZ6ftUpASwi6C}^y++h2fxy_W#UfgrO$hJxJzVmK)v423vd z25Pzt)KIYLAZwf;E9Kllln=yoP~qI|CBnbnA7nb%P!PjO1<6pDEudI&l7adKY$!;^ zT>)kd$Ud+&pjCJt-R>aD1!4_oZEm-}2>*I75s)V&_}9CGtD5qFSdz*ZY{x~N!myMrhbh*wX58hZW`{Oi3WKwdRK zvJd0{cTgyS7$BFxeF(N#2WGJb)X!jx!S;c|7_0{5IFQ9)7l5RkOgddu47%M-I(xu- zg20~F=?42x0+I)vOdxImTMc#;C{V#}Fo1gA0BSYZhhP~MSQP2N90PI{$VRZ$V8?(Q z40a62RUj!R&_)i8Zg&u+(%GYO0TdP|y1^F9KpkTNaSS+gL5=}i31Wbp2?`K*6R2ar z-UmCz0O|&?)nE~jV?b^Ig(5hT+(BM|I|d}>4sssYRW_h`f^K&ZCDYjhzAF?|O4;zQ zKMZvgC_rRDMF=RMK@2AgXvkO~I|k%Tup2-OkbA+&!U^OUkgLEh2f4usoazF1DmczSP6ay%#Bg$eI@JN{RB&*CoC?lqAcm6-%&8#nz+DJ( zGbkP)@e7Jgum~t@K`sP49^^2vzu-;?l5+BZZtv-K2eClaZ)Xo=Wcft5lLy?{ zVAraELf8fBS{G#3g8Tt?Erm``*c>V&K*=spj3u#1WZ|9a4=I$Kmg zp6Z^X0&0dZpXi3{W`cO)82@@m1AGXP1XfSC#)W(k<70b=HWnK~e5 z2AC-WVpf2eDj;S7$kY7mk9PK`fQGTVeL#-)QSo3t(S00b38;w#Rt@$DD2QBCz)lBw z?=VOO)JNbDK=lE{+hAvdJh}$liv}%82U!gAQwvxGWC*HXkh~7@3)lk?uYW;sA~#uronX2X!6D@rOVbLR<`X8ps#mn1#C->^6``4uh0J z+zWOE$QQ>zVi5O&9SQOS)MpTT!U=*aGZSu=^mv4R#;I)!^`gxEdTx5Lbg80e3aT zVPMyQ91HdU$O+(J2RRBFt`Mh!0}kW?uv0wQ#A!0rP( z3KFVdM?stlb`->^U`Iim3U&*`sbK3sPK7!GH0NP(?~I0|e%#8F`DA&vrD4{{XP zdXSUA)`J`b4jPaELt^@fRYJ@^(j|ynKtJ?>ZcYRbq)jTv=f*cMu5@Ze7 zNRTC9BSDscjRaW&HWFkBR3E4@3YyyO_5r!lM+MXd0Gk7HIoKSK$zXFpCWFlZnG7}u zWHP9N1P^!mfQognDK21Bz?wlW1ZxHv2i6QS4y+ku99Rvg!3i1%1q}@NsDRoYU>zWr zfOUY(0P6sm0hSWz>`?)&QUgWkSx8moq5^7kft7(ZcJ_eR(R82VUw<0X5&_GBOh4Y) z1HOf{`xIzEVh(saEdTm*{Of;pUuHgGe4uj=c=)1s5BPwAPRQl;+P`}X)F&{rfHq=u zpE&q~xAEbBc?O0~FYrY$&*S4_JDWknCDDyXKtmwVQIWLA-NXtF7a;2K5Wn$ z7tlIE&@?P)03a+pAP}@LI^f0jcmMx)?*Wf5Ku>gNKEktGgn@x!Lbo4JuUPlNgFo09 zomjdLHb1aG_<)`Hcz4yGPSD1SA3VK9f3$yeA5{I%&%n@W$9zE3=?6$Ti>A{ZkaGTm z4>&cQZgd}PeE1)91i}waMyCS@AF?od?ExJNvB3C%@g-)LDFVno^qC^y)ci}N=y`XH zN=*0fgAZ65AA>c&=i~+*YAC>by!(3h`Gb$R4nAbV%_=m^w<5YWgcD1@QG4I9RW(~WOHr^z6~A9UysXjlqz0%329 z$^z&rPSAmbz4JhWXThL(N{JUmY7C%rF+g|ff@a%5g9qUOFLXegTwB0*af61Kb%Fz4 zNP>hw%VvAyK?*?=sKEg*m_efJLFR!rmxKnqPy(3;S|8QhqS6Ce(i-sMK6n8rXpf!< zNGGUF3=Md3@-KM87F37?^tuIrtkDQ~u^FsZ0(3Hl0|Vl`4Ss@K3A@nx``z9a z70|L1?w0`v-^#zpPywd|&>ROSnm{Q56e%SEFXaA!qbdVDjt@Cp7Ni1HmIb_E1WAI@ zMfeLfhzS*-BTJ8H^p^Wr|0w5%&I?$7C{~6py0rdL4q9!RV*R05pz*)Uau0@blg59b z_$|^gzQhmSAKwMycDsnA9DK;kd_enzc8>^X!i14Wy!jAI^RIxKyRTi152PXHGde&T zK#`r2#$WW2IgP*Q10yVbfOJCGEEeE&BFJL_O$o<9@tih+nP)muM6*l>$MdUhHqaG~ zoZyINM0S`6v3-D^7DFbz9!O8@Cz+KyYAQx$WPn*!oGrgO|kokZ%Bcscd6i{f?ya9z2 zEWDY0rlcSR7*tIWXqGDllxQRZf?vG&2~IT|ps5B_pMz2jXv{9)#p$1*MM)C9;UUH+ zLH7+df^6;$5@9}|-NFOP;*3r&x*Pv2^I!mrfCgq6o!)deGAxIRfCf_;oj!CovcN<@ z36|06OLrqEw7|L`Q(Gd8PCuG|2Gq{Y5`y2%P-)r0FnSz-~0mZ1|YTtsMHj2cL1?Hz-(sFF)kAP0?q;;h6cZY zvjT`=!7t!!0AhIX3phJ~7!fb@6~ME38KBq&)gxg6FW!6ypI{2!YYHkhLIYmh1PQgM z6o8WhsJw^t{R3Vc_zp@6I>ramkjp!Gc@OGKpq2Na$_$)r1zcDJ_yv1dAOeuWJ^@zP zCqT3KW>CUq?wJBogcMsXU;%K9!3z5XBx#o^31GPw-H;QcP|Ev+PN-lDcp9dcdH;oxfdN|HSIB|Odr%DkiaAin0YrncQNRoBZ{YO01sq$DML!@(@FMpY zd=N=c%@Pp)!T@3pXo*-ea;YD{$iQIzp;)aKvabhP7l4|8NCm$gwBR=b75okiu=1rF zQvSDyfRrPu0FaT0D&Q8h3UC44Z3Hdat*ag05vR8s{~M*My(P+&CTY6=vBf5n$`!< z=667EJ1EWr0$!Z^1TOYLZE?_sA6T*f(*soOgPQJ#8{dFRVMKc#wAHD3j|!;03R<7y z!w5NV55(_uQDG^OFg_3qIt~`H8f636Adm@%gTuo4x79NA#;Bw;e`hhi^!+~gOwWVw z<&97BZ)4H(y9~QCjTdxh+QC=Qeh72(VV35Xysh6#Z+1=r_eFZ=fEOJaUjiEd((R(B zKv???Py?uQ3S{lh3l#wd2JRodkZLjDg(!sUqLKqj8wvq0o=AeL5)}})0z~KpyjbuN zToi$lEGWf*`ojS)c1wavOqFI^jUZ13rkV(T4bcs2JQ%=DLgezmg$33gv~V~CDF9kn zKuHI}Zt#G#h)#f7j-YPB34TEzcsF6^Ya>vxXnhYKsC~p;(<1_2-17}QS})+Dl9CmW#lSDf(7OSYh(YUOYQp#h9Rxt<6M`lH z_yrvlKy0wApo0O34Js)31sxnfY;eIO=nw#6gQAjO&>;cD1{FE{f(`{BHfTJXU$6mG zuYkCqJkKxK05bhWbU6690#I=Q$}-0xD>S~};64tz8S485<1+_e$iLX`3d%v?gb(i; zgBgu)KotNYKY=n3q<;)D5t<&uLCZpW*MWQx8t@`goPnX&&8PVYM{kb`sI_T*qMW<8 z2fP={`dqO9=+YkR6XjW;GkvU&6(xaIT<-<7VzrNHzXL7k?Ecr=0@er~($GEzI(is1 zs|O0-ZV~q0dX{b%{XgCQf0z$wA7Vb(>0mR z)S%-rJ_*a6QT!Ubpxg;LnNq+-B`1yF!r>sOu?eySoS5Ju;KMcrAX95_LD1wUC`o`u zp5TI@b?^rtGJ(U>g(s(%#i6r>2V@}V7V)0}HLt*agw;YP%}3N>dK-Ij390e$Tgs8KyXJBl4D$^0>~>MfKq;Rawbty>G@ zOCbMXH4mBt0>WN!iGV^@6x0I+9pKb_go9r|7SwGuzSJA%!!Mu;>b3C;=z`L?^@nmE zP3Q|Q;;WRAf0E8v!M1K6WGU)Vx0}#hyeu>zaSr2 zoL}P%R1s*%$V~vIz=mJYPXMaoG_nc>m_jSw~L6(!G}zs@d`#BF=&PG1Qg@UJkyY(n`Ig}wqJEKBlR}anI zjHNHTU6K30z6_nN@D8vm)J?8%H@V7yDo4;{DFXwu&r}8^54ucc0Q>L-sE{H^wtG{yx;Scvf@r2Z=;J@l4|bhn6rB7*tA!G}!RC%T(JBN~i;FS>g~KrPXO515!w zf{t7j0kwY_-QF;t>}~=LaU6WW1QrI(STMSM011P}IbgydyBXcSfP_KWrumQvSccK< z2WV)l$@paV_1;1eT#Z_Hjku_6LbLuXqEow z&r1VdoPZ2iurM(&fOUW({Rd=c^&S-v1Ei?=#sB}1bfGvmYk_L~*V%>pLTZgn7o0)+Dx=R{#-T`z6PIMi3FaR_T1o9^j3uwdH zvgcqIdGxlZfEKnwtO6hH1le?>RtHM_4!teljoWZ(4fx(@);h@EXaS^sH~gK<|55fu zKLPEH0JUmLR20D81n;>49cl~Nar4L;bH@!Ve%~-5@3I8%dw1ms4(l%E2?sj|v=|Mv z@*cFwOu`o$GoW+!L79>P6f>YUXBuQbI}>Q9d#nKeHaRzNOAs7ChrWWdyh^}}9T1jA zz>9SdmQKKnC13yl2VLI5()@tG`$WL^o4qaI3A=+YbwZP2=2Uq#@fJs0|l-O z69YppWV;oJ2}(vXZ@?jK(%S;Q%Bj0XMF;GDP`d=Q)f}|Zd`Ar;5<#6rkX!_ON&T!E z(AxWhk6D!eH6L*R?Q&x5tWn|NZ#4z2Addx|iX{Qsg)Ri*VuUv6Pyk41msnwj_8HK5 zfDFhX4Q?ZMuK~~9@e8zqxMAVFdqMO*IncRLf-WjNkU>Xqa|JZw2wJoN9&QA!#Q~2s zx~TX-&tvX&QQ-*)c=41Q-2D>?4+wa%@-e736KQ_OSo)A(fIWEMqyPW^@BR-pJOO5S z0csMk@h!oRIeVulmLf0b6A8BU;U z=mY{@GlKRervwDN&;;Ah;|6MmABYB@IRXlCk$@NckN^J%of|F_5c-1oF*tdYfTT16 z0$zN6^#6ZvX+Rk0=!1Z;7f&Aj{~!7Sv~?=%1t<;lwt&ak1H!{!oO}fGpG)`)P(=Wp z?`uB75)VF@?41RuECtW_O(>b}#85rmiJ@z{69WSie!z%dn%1%eoJUBSk%th45#5&*vMJ;C^!@d17Tc2Mh^0~Y%dkl1%o(SVF(yQo+|;vIBJUI+_^Hh36W z`&xGi3y<~&Q03cw3NoR6@Rhvwr%oRhj_wc^f$nqK6F}82RO+3)_O(tQ7M|`B7Lo2# z+8aPsFGQ--heZIav-{k^ck*yCk!~Lr3GEJ0U95es`y*UjqWOTx!FTe_KLYrBazXbq zfRYJM^EbwT@URyzD!}(_WHcWU=spI%(e;NJXva#(VNiYpuS}f+UOoxxs2X)2>yBap ztphmLoyEhy{&aYE6=*rWPxoQaQs^2LkIozw2j&CddjXI0uRqqy;@Ew@6SO(zDF6Cn z{OeDH7F-H2p9I|x1=8W85&>F=01`gVzy5eHi%0ia&}D($PM{$P(E4ir_2NseCZ3Zn|04>Wu4qH(I-T}AfwNL4xH}>t$GDbvV!j6S?>f|Dgn~z z1X}O_)&esFtQE8@UWFNS`&9vGHKUUPCef;1iDU+)B3s{t|&Y~OkQ z^_3@qkn5ckI(<|sK*0^R z8mtMV8>9)ev;?FHr1>~hGsJueke@-@1-w8z6l%J`tItKitIeH2OFuxmK`UKAxf8=EhsiDK|KH8lHT1yS;q=Q}Rz`q`pE8=7TjB*0)fdP2{>|l@&KnVeC1H@pE6<~wG zHh^{|fCG>DBxLa{sLlbo8=NUXJ8?kknZSmE`~Wr-Y&yubAk!g+f;|A*rT{h_w0az5 zC@75|=nnGXU;hb|2z*pv3#vhGKhD4Y7W0ShgP_$uAG%#Y3t3%MT$n*j@VZi9|JiT zl$1b?El6Pr8b*XpQi5Fs4gyffg1rV>Y6f))sB97dT|fqk2p1I{h$86by(*QP-nDgq8n z57-hv&|PMrd4Gs2K<)$U1{nj^4KfC-8)OW4xg5wCuo@X~e1nz8d~K->;fwX=>r=8DWpLwBtVq~NFi7rT2~wc z8F#j`1+w?(IDCHsSPiH~I0Pz-4#V~Wod@m8ngd?$&U^x7JGg#6-`N7$lyeAPIfJ!< zmN$ai9OwDhpYLUH>}-MTI5`Ar9Mq`z@UOoFj(bqc+4w-`6!5`|+P}Lm_ZFz95w~6t zWIVK!j$^$b=sXbc!8o9q1IRg!A^|Vne*>=*1Z9ohE#MuD%||%EgX;8HCI}fn9x`hM zx9Gro4$!tVh=QCC0NN10BVi-zc>zm6{N^_Wi1v0)bB#&`_*ei?a{+WHY)y$U_)GvF zl^oFdhdQ8UY5~$|0KDShz3QN?BJk4yBBj86IhBAH{EA?f#xZu5fL?dTEQNph0<&jE2>Kx{W;7nkvw7kt{FSOS@O zI2e4Uf<$P*i{ql;Pz3h}LDQxx|4UR90$vD!r#eAL27saidSn1-{30yi#Stk`hZc5Z zKpVsW(4e96jb6y6mau>q=OsXjUOuTSI zmW**jT8!L2DmC0bDiz#5Dka=LDh1p=DmmPshWp3w_qabocl`epV_?Y2fpu^}CuqUP zCjMoEBgQ1)1&chGWpT`vfhC~V6`U48cc6nN(E@sX6|)oqUx2PA?S`ysZa!iIJ_O)% zH0Tfj(23nwHQ@mVj~sA+5mfnrZeh>>^_EIhbi%tWnJv1nAAB#@2pTxB?-XOMWMQsg z0Ui90EF8wdT*<*)!2!B&9Yvgjxsr#uf~OO7XEKs8VLZ&00?ZWxogpd;DCz~6D@B+q zM7rO1hN!4CKK=jyzx~1Ya-Df1%#{+%6%yU|J9AVtK+bs#lIo0;V6K#5u8;v;S>N~^ zB-EXwB5?4nTxXpObEX1whC=tzgKq^?!7^t%-4wd78Xq|LkS(p#O{x1UbB>Bg_tAro zcn&_}11sswQ32h4ZqVt<0BTGe{2|8-I(*ti1!6*{D+@vx)HQ<%bAWCAE2sSuw26c{ zM+IcsR-mtXC8_5c5W<`1p^OAo|G z$9Erso;M6C|BNqzjO7S3{?>Y+#4Q+9uE}_Go$ByWk!b$MQ7hjqzY}CK$f(P&nvb(| zpS$#Urx*hR16PcS#A~jun+IQU?EC>T{$q!XM(csnL-EmZkmDN9G`;~%TY`=Z0abFK z!+!QacGGEhAMNJ<{;<GtOVYcS{r zT}PeK?ab2s>3ce8x1=+VFjOlCTq~%jt^(DX)9o(+)~W&4S^(7w+C=FL*1^GiLikg+ zvjD_?kZBMHgGLKvpoWxm`-^}LQ2-lK0W}2FHHR1iHckZQ60jj)#|gmQ1UfB11ZrGO zx4#6~IEn5PozT)A;v-Ol2x21GY_LIKvn60=gG~gR4YCg6R8YEi0Gkad-Mal{I=6r~ zAcD@1g+_!k%lC9pTMA-4*dnm;V2fl>j0f8YHXdvd$ZoJj?h4)23c{Z{LF>P7bRYfx zxU&bmV-)NQa5vFKC7}D$_Z09R5Em5_VGtW+sf&sZmR-C3fEIDD zgNBVj{Q`(>5St-(fNX}D3$hR53Xp9_!S+IWWuX0DpgC`-UEppP#4eEepkRaf1mZ)8 z*${gmZU)%{F%e-4#B9)E1E6je)ND`-5S&|FR8%1T0NsuTb_>L8hvnxepdCZ|76}CK(0960`?bZXvm@YhfvMK?l~%;dCTtK-96wncHIa0 z*Boa89e#W82NUxi70`;J?(3a3Dk{P)Dn6j|*gz*yeBfX6iK+WA|C$pl2mdi0{K=wy zLHeWdf$r1I51ILwoRB&AP=@)U@CW88;Mue8L*2K8x2S+u@;zV%-wt-J`%w40<_G+s zS*q?s{A*5d@vnK!a_}b?xac^f`k$GBq0Pzo&B1?6%(sO9G0#x}%>;rjl@;Ct-Z$2LxcLEdXN?Nz_RcsO6hrwV4uO3dxIh$RE?%!@k>s33pkuRp|uTYFXNgMTnB$M zfx;z5MFeE1_6aGJ`!K{S;8x>*nJw5 zr8*(~AW-uc9Ce_;cTuST@u9UOSe?MZp90V$nm|&J6v@B+K&Oui=yWX=h;Kl%C&mX3 zf)gdkTbe#9prg4wq;J5p5=clIG;pW@jXcmOn(+PZ8WjQUU()xqYgBxsV^ji|_kd^l zyN`o90K#*?cT_;Uq|kl3`#31Ug9;Yt;FR&DgFjiikAqTd4|vUYCuCw1q!jE)7ZsoG z<4FDkoqa99zx@L&4f?1+M%vb#5a3^PAM9Bd6&YiY_awS~R7yaZ?BH*KgAb)NeN<#5 zT~s8DPl5+GmmCy1_yE+%16_G0qwS(%BI%<7(jvmY#z#ef>EKT$W)~Gu9*`0AQIRk{ z06sthk}ny3R6yM_89^5n3GK6>_Pn%mNv2^zl?0iDt<{E~mk zC%%Kv_?VA@$9_vxWQ1Qaw?OK|3m~1sYrw-_;OOGxU-L@t;6uKHf904jcApb|!F*l# zHS-j3T?uNN3$Fo>fkC1kq!z48R0T-J=5PkxRb-3-cX($j5vUp;T)9^X2>jFXNXFO@EY*28OSJ5tbq*r$)$Zk8r1m;0Gk3zRN5d@a!`yFe!(1~ zQXrh8lE6F#(y=(y8KROPyaqf3VSKVXM5Tg%$wd+VH8122J_5N=`%rg?N{#eOn`npJ^{fkOe5*Cm8sXwLy3Y}W0fq9VNpJnzj6sq^`_ z9}r#xKDmH7MkS*&MkPad4Y<%ZzSR7jnSaSIzJt&Cn16I1Yrez)$^>AMpDYKT^J)K( z1_e8)kqHhia5)01&_Jz3=?h>nu(N(jUjUU1FXTXR`vaN_gs<{%KcKw_ToQsVqLU6$ z(O`ybKo*_?UgXXUIRaC73i#jvP}sfXJNT53`2}cUPIruoLGwihkR@PI(A^!~Yrw1G z`Io$qI`~vd6V!jsQBeRF-WL38jtLz6A;A2udy5LFbtrrSr1gWy!Dk}c??9I_NP~`8 zS#v?|;4eAm7ohARdFNiolZ*KK?(=o$!ou3ehKcCgEe(B zgE9`7$@~II*qH^ip%sfb2WaUhn>NV7Ay8@P0LHO{57K-*_~t5td-o5;cgUi5%Ovpt}D zs`Wr7LHAUHRzimbyvY6nYF5MdRD+u7p#d*KLE0eW`vJXf;9V3N0Wa)9qAn@{ptVP! z-bO&ci#sx4w}EmE$RRcX0WVI1gg^tNFY0+27`jVTGJ0FUB_Vf-N(y(0N&iVt@Q=;C9@nx}vlZGvD^K?_|#rh=DAg0gDBi#_0tJ)nhT5Gx_2 z56D5Fy#N6(=0LUtDFg(+aD*5F@@GJB@Cze|vuZ$WH4q!RZ7?|ag*b!@3eDhvfEOGx zpkYoI@Jb!<0R!PLTtUV{Ml?Zof%-rohxr7&&<4qX!X!NW#d&E4(1kT7phZHV0WSnV zQm{Y-ZA}S%@%Ixbv~9YNeZRqd?BEOe_&Cs5E+|QW4zqO>1*I7f51wWk-+)|&NH3sX zfAb#ju?XOSbx?;Hv}p%)%q~dI_{@vnA|O*h+75$;kU`-To~6LQ%?@w`QQ&q_k>Li-mkGG27;w9&h;X~82ylZ|l?gI;L%ImuA3*DZK{p@= z#PbU}3v@awfCNBIp8|eCXB7}9fnU(sq|@1@``B@3A5e$y`;Fty0U!qVvE$AmAjbC# z$DJcUjN{HR5Gnyer9h|*5EXaa*#mSYXf$M_iJve$vcN?Iw)h5>4 z-L{~l15#NK@Z#4CP!e_NEmrAuQ3(kPc=3}LY*kD^K){Q;FTktRGC*oof&*UYf{b-h z(E-UFgviAN1iv^2(c%EgYrDXc2A~3l2gF@1!N3q62Av%Uc=6^v*j-@z1Hxa_Ld-A# zWy3}Zu)W~KkP;B~;vkYz=ti4>7csoByjlTrgDpruWJO6pSlA0Y3GjRbXmF+Zhy-L^ z;vGTc5D$gkpX9@YyeiQHv^v+7XQwpiybj65tq6J*h zgLQyP2++|5-Jg5+sDK!tg_+F1{{PR)>4h%ty{ZIVLMnm0xEIul^+vl839`8NDd>y~ z@Z#Rvf58hpL5q7qEkm${pvAqAE091A?u9Py1&crz_h#ilR`!AmQLHO_7Y9LST|j4T zK$rD`#0rDOX_?`j%pJ2CuN@GxUkOj`#pp~ScqnU$(KrsVe)5{1l z8kA%Z3wlk0ur282M_thS0eL|$$ZOyQy&+7XmExfCQcwV6iD~1T7L=H50L5gBN(U2U zpCjnXhp_N0&>d8uTblMjZ|-ta1Ye=P0(7Uq5yYzA1N<#%po=;Ax5YAexPp30kagW6 zojEEhpojx4^o8wAdEp2;zXGz6HsFN`gac}21-wv)a6nyX zUjXmr`F`o(EBWuY()jZZK@Xa4Q316&pr=F&w5UK2GJ%K+^joY&oH*U0vIVq9U$6(F zNTA;XMG~|V8?+Y~tVp0g0wF2bqXLplo6vo#w~R&E?+<5B3&>W7<{v^uuR-IV&Br~O z4|_EJ2VF4C-(>wCv;_&`vTlg2y<5O7(#{s}pjdB>N&sl{6R67XZczc<3j$8s{7?^c zwt(+N>xRsjf>eUXm0DCl$C`r_fiE*?0q+h44SMxLw$6hT`hbQHK}tZEj`X&ufbM)d z4si;oK>oZGqzE)F7{DKX0K^7m+2bwXoC_+cK|&p%U=nBnx0*qG&^hiPBSGV$AU^15 zb`T#lZwp#iY69Yb?u-F(TwZMB0Ouai;qai`13K#&L`Q&g(Mw3B2D*&`BnZlMAR3fp z174hgNcMnK_QDQ5Xi)*}B?x%29wMm&m8<~K0WUm-!R2NO$Pkdb0s>x`34`*YOK%JK z#-M-~p!zSGXn#tQlBXVbDRoTxr<6j zK){P;kXq>djNnD;0WS(bLMgO6F7k0^k~WtwwTBpAU%F|B8Q|Nr0JqOt%~ zFy*MIfNtWN^ZWn*=)=7xY+3{aykG>|z~ctGrHxP{>XN=Tq}@TWoiQWe-b_&p${FVsNiLA?NNQvo+zgM(iz zc@A#11i#=0O(^()qKzdEd=E`baXK8%-|Nnpc?t=$k%4=VQ^k@A!8bQgok_QWGpXzi`5$F!*!KOo? z`4vdHNcSPITF{zykaCIcaL|cYFQFz}1dsFkOQ0F5&>b$*_>w_@0kr22$r%cbuNV&e z2brsarb7ed25_q70WXjL|KA>TO+@oI#!ep`m&;cXC$;a{_Z5`YFI+d$Tf zK~KB^RsY@c-G{$F?#>4d`|5Nb?)C>Q;4t|9w9`jLfq%&%M&<*ZAu6Dwu}!)ULuPjQ zmz-nlKKlJB^GW6t;OPjPZhz3sE@*BZG{Ib=;sBY42TkT47XAcM&wR2IG?4}xiH1&( zi-6}JkA6=FP5!!rX2u^t6haO4>GlWB8-ffK08fGkKnw-VgMyWVG$I)u0UlrWmjJmE zG!hCk9yIX`Q4iJ$awx(g@HzM@-G?Eo1iq)sbb?j~fMy1dLME>vI>Baubfyb**MsIB zL31sjY2N1$CwG>pWOVwdq;!AkJ^`Ah1}`{O08giaRwTNpfM&E|lhhzzAzW~@(?=yo z_|y02oh2#-U^ly{D13hmHUXkb20Gyio(t{Hfga(g0P*_w=ird7==4!30o(4PA_3J6 zvgaw-9091>2jCb3t!D92sR7%$1w8HwwN?bG5j5iu(I^7d2(kn^zuyBM(}Y?j0M>C7 zstS@IKttG&S$e1qpso$rhNCE|A!dS_@UY1PP~aVg1n778+%jmb=;7`;kYT@1&?&9& z&pWq(hXA@uR5YN8bP9Md5;mQ5{QGn0j2>vv6ngN6@ujp0%q~}S!1J{R1m& zdxo1NpzS5X><3yrBY|v^h_)AKnX^o{n*=L^0s{l{iSCyNf66t2_Y8DqOK5w^bi2v0 zGBo`E51PnlKGFRXBn{pq&{-{`?WNEir_gwqfq{vE8MM?wgMa(sgRccT9TkiZq;)zf zb)P=?kgYpMMWg$2_veF;c$h&8*bX0j#&_^H#E;A|D&UO*hmiyXKwAXh0@^n_T{)OR zYt+tmg9MplR3spQ=EwsU0CSjQRAfMV06;3h0@}AgdjMio6u@ej?}G)I?}2s!z}3We zI?6CdD#Ssi_G3FE6{4Guh@iyYnKPjE`o}?G!?43=6Y74Y98|vX0g%?lH=tc3uptx3 z5NY!s70^hn0%&6nhyj{a&0u0+0By_x(V#68{H-fN(~tiY_}dq7GcYuy%GU>nzWB$@ zz_3G*k%8fOi%J`4uo-j^7-($_fA|5=fHec?W@^wZDR?L`O98s+B{Tpu>Q)9CSO)2O z@!bCZ|18kq>Y(YH-Jn^bj0YP%7y{Bd=YV^CFW5rB_vC^GBS8z1A+j$%1T!#XNP96b zfcY6Ln>;{ffM#ky3c-WXFKj{>K!>5LyZ{ZGwSezrZa(7B*#ch6vr`y+NCspIJMDOj z$|bNLKx5k=*MqDFjaGx)`2?gAGJJjrv{o3hQVJvkx$Vok*i}Ij{u7V8n$zlZ0(ttbc zpv}_)&=ngXpQ(T%3KBamDkd+A0vQ-UZr6Y~>IG9E#O(&%E-C>qw?n73YanVsP6RD0 z4*=N((whRd4W#JBWT^IxZis(CX$Ulg-U7ZH0HhOi{xB$SK@Xz`nNb0CuK?(v9MB;# z0xc>fpvex9d%+O_p4bs|QAv1lC;;N#5Qtk|1O-6c8`JHgQqz0{wCNvYOgAKJfGh;f z*gyjaJk=xMqM`w{5Hvponz;o933vet$U<-cfp++TI3_PX`okj~7Djdf;Cu{;bQ7pU zG@%Z$>2^_x>1bMoB@t7l#~Y2@#4Ne zXl4f#kqKavARg*%QE>rJ(732*1iaYo4+&z>}^qL0XbX{ zQj&DmfKHS_q!7@VlaLewS}Fx{Hh7sy1c+tw!qg8EE3kxd)EDAVl*|JvXrRskI}w~& zz$GZi*`Q#D+90@74K@+WD^Wi3f$~%yWph6p*SYmozRD8h3fgJo|E7X7B zi0FhYcL%8lxd3bu$c7Y<2x!{_*jUhg(9mQQlcBN6gCXEWK4|U@vigHxz(*ye6Otc5 zdP_j}zV<>Ylq^P2*m!_z6L7sH2+PwxDn6j_k9iU515ZE!VA}#-Eb;**W`|~2nJfbp z@A3g>7#EN&Dqy#Ewt!FD>4mHXfG7ji7N9ID2+2j@FaS-WfzmES`HPJ{kT`}GI10_L z89NcxD5%~9Spm-NpgNqt(-E}%;w!YK3IkO$padH5Vh1w=189W}=oo8|D5QE?#0)YX zVtsdxiVo%Q2;tYY(J6#ko^Flv;|B!4IHG?&c#RU>EIp{U2hD&*dK=fr1r`CC+FD!B(Y!v)PL< zWb^R(kH0hf|NsA(W`UMvfIR9G@PZ53to@(`5}lB<$aa9rO|Vu_s}|H$1r-?}2UdV1 z9~6+_#b%(G2el?ofm@T{mvfms2j!nGj$ViVT_WZkJmzj40T6e_$00Oy`>1dj zUjlVEIY7Nlk?;3(F!66M_}Bf*_@DC6?(@d~ zj8CO?`Y`_kT_Km&S@Ey=Eo15R*!Z~U!zlefh0Un_KL-%M@eOE&7^1%iYFst%0k0QR z0IjfZsphCPgf`@^j8PwPF=YjO~!b4vOfmQ*!sAL?6w5&mCJ0MGe zKm5RP7nK4~Q4DIyFff3+f}qq6DqkS|yc$qx2-^AZV!jfzp9h+JJKh4m5`>+RfgxiB zxO!Wl`2Ts6!7*LkT|HDa2(RrU|?Vn1}Omv@e57?uLeuwzt*Dy z>STb_f{GQ81gH-PmH;&hUQGT8spLQrqJ1nl;04nc25^rLv_z))2&l)`%>?c7?Sl6B zK#gSM|D7Q!0`U8ux=;1CsDKngyML#^-9OL~7obqM{JQxuqw()>P#Az(Q2{UZa4|51 zLmOQnQBcP&;Ked%*AG-KWij?bs@3k_pt8>Z+|7sqHH<)u^Fcx$pZV(`OS#hcueqp1 zyhxV^#XGqBX9JGKfEQcj!Ep`g33xyS=gWhl5!`)(#WyH`K*0{R6H>;4i&Riw58C$w z+XqT;0pJ(|T^#blSOsJjB&{|d0eJ zuNo9*;4lGs34CHds9^}=7=Y~qMIYFI4lka|{r?ZDJyf9nD3=4-?V_TSA&u-0Q2QCw zYG#1cZY}{}e}I~ppy3g)^)V11fRg`5H-8KetJ%|PeImo}@RqP;95heym zvIS*5a3Fxznt{9kTJ8#Rv=4{_S_lW?#DIMOn%M^XAm@cD)CU1jA8eI{*d5V)1hlFS z)T{+r^934oD$t$^XqhZL=xo6Df(~j0Sp{l%g8MDtpab_G1zl7iK?f==z!p2a@R5Zl z4Or;SltoG!22cmJKpkWOat3Hn3X~E&KpfDjKycVafb9n@D+JjOTFDIZsznwfhzlA; z>1_e;0|mPZ6kQJBPyko`VArI)kduW(BrHL$lYs<70BS^nRtcgc$lex}6i{0o<{s?n z5>&>%m<=lAj)1IBK^O{3o}hXgB&-tfqFfPTtp+&eL1R83gF!U7K?z!GZU9a@pcn-E zJtPfORPBLAPYlT8CZG@k_ZMBjN@~D<40&-&8Xn>n(7;ufK?-pfsGtzk?>-1;f?NUW z&h$ch-5?9VeHIpX%tEPy+Ypd{p?k^%OO!;2hgNQ}V}&mSp>eP~$^)Nz2GI1F+%H0yyJ zik|gA+uL7!gBC;?sD1|(;h?=f;9zb6udM;a9LN}Obb$1N+JxYA1!}xQax-Wk?!{uL zku}XnKx@W9)e9&%VZKBPWss4ep(?PEV28V?_<*A@2Vx$`883pN=0TDs$S6?Z4DuW} zN8cOHv-CkE-D!>Dkb3w%m-{|z>8y&pk^$hZz%y4UndEPEd|tY z230!H5kHWJEI=UwDr&$X0y+x{bRrhmcL9(P0VSUoj?hv!2DCM>`G`XED@IVTfQo%k zl?XBk+_?nR*-f~J6%h4ITXVD>j*HC!)f2N)==_yoMz1}!@Rpk2BY zXyCi3lpuvXs6GVsId>ys9~K^<4OvjLvWPe9H6wp(G^pQM%m?c)AQ_G1J~5b?;I3x( zxywHYI&=kNi94EM&;byrI}b@i(lSwg=I;dck1@>yWo@W=MKJRasz7N06vLn#3TbJB zQU<7*3kqLw-xHK9jzijKu;wnPNe}=}9lemjCvaK>>4r9KLAeB+oIpwZIOHq}P~Z2( zYbo#sCQx|-?vc(0XJr%POOX2sy4ZW`|9A0db+BkTb@($j{}QNq6CW1~nm%Cw?b!qM zH;m7`aK8)cnu59_psp#Xjy663S-z}`kO6fmK^;(Ne-zZ80dW!iQG?Bh{-`qc{wTO- z2|B(?0NgW`=?-Q1e!u&Zv9a>^?qkNE44Jz_SvpG@x<45gvp|KMS-L|xI!jqVVjM6r zj_y#N&QcDL7!OR0r#n=jvy=xUCIAx?=nfU>EENEWiNM4}x4|?ogS| zQVEcl3`|U>J5-^wR0brb01`8FRxtk59jeka&VSV8Ci=79K(Z+cK}a_C@TU})Z>GKGbKL7}@vWd;ia1Lz*K?iQ6fERY#KkQ7LW zzcr7IfuZ?_0)Kld8v{c_x_rIyCD0jh?|bK{STKW5qJi8pvCWmCH<$791Ha~j9NZV0 zf8x3i?HZ^c1ZnJ?qS697RIo(_y#EKB%s}@Mgn<+UFhj>dSfHh93WyeLQ4s;rp!p0C zE!d)>0-^<4z(#>Gf(bJN!;9QE3=CPIk{PtMDJ zkWDV2pacnWfCNFiYQR@s6hoW{YAJvuL9qp*Ilz)>?4ZyDjkH5uAp#NxOkCEvVZBnl)i$U|{Z<0#k$^W|Kog80aZuq6%3+{MJ`f*tgE@!~N_-$bX!9C~uK^l05oiI=t%LZW zom8MW25s_V1npLhhq)h|s$osffEVuIoTLD%`_F?61X&DjY(SDHNC<4VU<-H@6T}DG zE!d(0>H4*(fbAA+Q33V-K=L5FL2dw5Euee|tN+366{KVz@ZuEcT9+dNAj_YFLJZuY z2Gxq7q#E#IHB|aFW9i}EVm=hD{mcvuNG%3|6^tcH;B^b20a#F|gJ$kPG-wNFz>5T^ zQSTTlcc3T(M^3;C2WW`~D!ZDG2C zK>6TVUV#>s8&E!Iei2eXcenI_3}ZgjeL?lVJOe`~gztFp6))(js|VdJ;H{C}C-}F4 z4y;}R8pmk?4^3r(%LtHD55D9G2z-$w4k|(fdgrKscD=!Gw}f6e1iA(jc0rMN^Ggo* zgReMRzm-0Wi;V^)Cx&>?i722_^2`hCtDv?3sG0(`1wgd%fq3IHFO(7Dpq2mxgBk#! zI*wm}6;$7WxQO;Z&t^n>fEj#GHpcjLw~Go7_|zAU?>E401JG8VH2%B;VZF{iY5WBb z7olYsUoSo+}?i1^S8y0B5Cn_uHJfA}f>kTd)m2l>NK zgT{jeS-L@YMhbdd;1}>=d%!Oc@ql0BB7gX0{*Wu+5$VhP;RpEzUDzJ*3kE!B{wYwi z9&~f0e)ql5y&?<@481H};o2{|4SF3|y8jv1F#l1mQIP?S_!{~!|LLsw0~+al7#|BB z>4k(x^Bd4HN)p`{L3>cOFMv1tfHu|@3V^oZ^+vF0x~K?fpYJRIo%+?A58CV_1KP>U z0vbyH`I@C0bV{rDpWbK@X1@=;xuBgdh@!~#Nq30w8}QjY0?fg0KwFcbg_Miro9+_* zH_XK!m_KzNJNOPN?D__DBucmU7iNz?%;!M&HiEWW!6ZL)2mfHc$Sl@;Or-k|$VHG8 z==!Dm(7_kH;4Opvt)TfB(AL0%uQ;*~2{)$ufVSZoUt(sN-hJZW3tnge%QGEZK)wVW zKGJ+d05P8c+3$oH-v&*~H17c)H3OOs1~rGFSH^%ww?W+S5&=;8&J*zBz-&;jl;bsj zAV@$U;DvuSNPwpsbduFUPyv2Hn19>BOdpj9(1;J{ju2)a6%OW8;Knbg_X6411@*7X z6pl=nDKQ|W%q~-SoS08E{}Qgb$G`38!IvD_2Zce?`OGe$=?}2aKx$yV16^|`RPzEN zejFkS2`oR4?jGk3+F2RcGVL;FOhkBUfd97p##?GxZbbp*nDD_B5N4&8nqdh12B{a=6*#VOEL zYzGhig!;+(3Fx$)?htlJs*uqR2c?Q%P+1qtH{CwkZ?yeCFrNag@`DOHztQ&p!tD0~ zS?Ghd{|{!rH{A!jFM>UG@E0fn2rza!f8lSf0y!OYp;seli!CVN4+uA=!BfICaJWE1 zrIQB~Rw6Z+DFKo{KxGBAJ$wVy9!BE-0P!2&7@+K*2W_Ek-UHqQ3~C?SK$pFNsuS>X zY{*)U&KecaGDiXa)`y@v7t}_+!HUvGHvZPT2YgV|ZqTAH#C$A2q_qq>uB-dp?6Vz%Bx(#kMn}E+808Lj|L#8Xb zYg9yd96DN5KqJM*Z^2DyM0kPQ&mff;?Prir5$$Kti8L?Pvp^cppiB?S!WIE9K)sq? z7ZscCcOU`q9&yk}NWhC=NJ|l93aEw#jpYZt*vAFlY6)&aBOStXod?{^1Z6UiT2T8Z z;Kd{^Q2hrQy92i_p`(c)c~Aux@L~}}6KKQ-BnTQJ1JU4ds~1-x4OdX`fdoP0RbU$2 zj>~}PggFh?AOVl}zL17AVqwOD(knPL!5ZP9mL*6MlsE!jB!XL6pw=$f zo&_!Vv!0jQ>fjBB4`ys}F4p(_$2Fg`Oc)%^$U(l8; zXnqQ$Ga%r_acDCZ?9yHr6^noupq4pk&;z_^toevUCu9{8ye$hF&j87rfHDDiG)^8g zasq1MgQNliUK|1)2LQ4i)Sd=)O9H^@srd+akN9;^o&u@th8Wx%$JYs&OakSW9FQ#7 zR6!S&8gLsEaX(v5K){Ps4p3s@05vk-_CjVOL4GL+2zcQIjuwz#OOJsXnBZZl7bYAi zO-qgyj3wgW5jD`EI3TSh0WSogI^Qu?o`lJP4jTFaZb!PPgk-6JmIY;`@z;SG9V#Zx z2ZcfPu^h9HiUoLuG3Xc$un3sP?4x1>THl8v0=i$w2DS+Mr5xx8&@}!!&fC+Jv7kO-K^?4#n-3A#=UStI~-SOtm&6_AaY;QO}@Ha`4c4?emzq}NBq zB(T>1IT&gE-J#WIgm~xX9pENt+z{eA~#DxS<3j#izTN(6)UKA05wZN zG^APDgAhM+<_xF-3aV511z17#3y6zokG?=^k50zk9tF2Shw}JTXDRpuIB??wyng_6 z#H9*ooCtiEK#ht{w-~b^sObnCVC&#=#s2s#PW6TkGXI z-8q=Uc$fo0`v+u@g?X661egN_x?h1$0CrK)f$jmw7dZGzjyX((IZ&kg7U*YJ+MVP}Rm;)uce}Ptmfy5#E0xBe!!(^BPWk7QRjgT7;0%SlZnI3#0$LyxS?5NQF z;ouAY>=VL}Q}394R6u(bz{wuEwBMBhkwKV!RAfLq0uF-n03>%PG(H0-YgY~wbt;{% zJV*kkJ6#2ka>n^iR}m!HQ=P67NU|T}J4+SfI$dQzR{==CLLYSBM+&U*>!OkXx|JH# zC4gS}0cyd3?w5da176fE`2WA#MJ2@e2 zF)A9JF)A|67a921oR%{_36%-~OX+})`9PP7081Hk#;8c3OT~btOuAop#;7QOCC|!z ze`b6Ve2`;;@G0gT6^rh>ptx(k$ngCc#73}FQouTGx_?6@&dV8}Wd0$1in&I`q5C`7 zsB>~4FB_lS1@a5%hKBEtm_G=gVlGi}>Au!{ks;GXB?lzMzvdJ)T|iD?ghuU!ZWk2~ zRZv_pUx1{A?n8}_Kzv9F0Clp!@e1C>@)DY&!8b>UK*SG%F9U>dIvqhLL4xuFgbzv# z5P4|2apVAs1$&@OvYzk96buEkx~#T2hv_{ej@@Z zl4OieLU#Y`1&wTlce8ze+WiA;S|{iPZh>w$7XCHY<-R{<{?UD0_!LCO8Iq~pIKDsS zUjvC8BuPltcH_Y+3CZAY0$3$Mofd^|HxVSs_rj;3IX+ut7s!d-ZW7-g!EJR>(dfP} zdhNOU@}pa{rxI-%x%g-$2r+<&&y z2|4$l?sP)V{pUNKAh|ytY#H;pxY$l7nNBZ^EkMn0u;%{~l^R&)4|wrnH#pY^pyhfF z(28_u)*foP9(?9<1~}J$e+0_+BO}){|L$}YA(-pqyM0u0AhT=d52EGz<~N}739Y`? z7Hoc{)_v&UFGyk1$*vv9!W;(4-Oyuieu1iN?LZFZFi5^e66VkjH@ z<}j>P_Afc@KoRCJSe5+?S~PdYi)aT*Fo(ga>|b(_T-sS7p&cm09EPRJ{voIBsKD%| z(EWiGG|_YL1wW)@&prXlviR!lPFEIC)eXt%;EI;nM+I{CPA3iPZP2(3PwTf5D^QCA zbh8dm^8qIQZ2|v!9a#9cdHn9JXF2$YgZm=?Hjh6r#$Pa_GyD&zJ8>C#HSL)*AoB!T zzm=GR8l@of1ey;pb&L1bvvi;82w*(;Qli&^rNiS__o;&~1v)%_gJ_Np53o@;;^Pj3 z3V$BZ_1>V)Znuw$0H|%s(|nLEESw*-o|k`{&$z-Qg^~^&H*tKYATFK;iK9;7f@Pk53@a3v_sV2GJZH9$&gogT=prXn_uo z?;x6^!{bLs#7|IA?~IQ|TDc6VFS|ojI9e~2NOilYuz>B>{?N_C*6YC1>G7xe6=Ufq zG#%X`Dm+m2;04bd+8??(K+1jCu&Z}b0jm>f{Z^t8+!dq31Bz6MZ@0C7fa9Y}guT~+ z(J0`*(q)5y{~%YsMR6r;JWwSpy!o#{iFNZ|i4yhZzX~N>pq1bUqCtbF2j4R7wgIgl za8VK91C0xR?aWcpd94aMnUjZsfnm1^=-wz^5SI(Y)d8zH_>QR)R6mBOXc+$owNsi8 zF@f59{M)?#^#-xGP@4RPcDpvy6=U-LJE z26{oK_jI4=4p9;4^ik0PHOV_mRAjniHvDP*UmDnb8r)7|0A){sgD*Jvw;kZ$Ho;(< z2Lu1MMi6!I0SEU5{%wa3zLq%nh=YGy14xj6+iVcU4QkwpfU?dlW0_Wi?H&xTeVhNX zmH9OPXDM|D-9;||Hm?Ju7{rx;>IWHm0we&k@8Cn2u^^uv26JbCbZ~<<6zg;|HXj6y zsjC=+?(NX&WZBdk&IlS4H~#Nt9ik$`@A|9PgOT4AbVr2>Xap8?C5Ls1iUfa;IB3w* zMMVIVra`d+Nng!xWWeLO2B5@c5YE3Xl!1SnD%{trG+OdfO= zxk&dd{%t=&c?=Y(Dxf<$4!-2*^ik31K5_6R2miK{{M$Yqe9ghX?M1gpZ^U*Fu%?4A z1^Bm}Ja|f=n+Gg*@Fa&Z=y-pSC|pPaEF^L8rGznDr;KsnkM2{TD`-H)7sLXXxhLSJ z9(*AIHw9!c&sMO-B`PupPeM!;L6~YB_6K4X$a3&Kco5t8x1BzCiUV$rfbqp{p1mM* zU}mToi?o9Hpg1_$eF)|Z9~BL--_W$K1u2DT6+pJ0rTLgZbB>AvBPd6JhKNDAg1>b> z=)71^cj?5z6cqy&i0AmX%><=KNH9zAZ|el{Krs$VpaPKa04ENx1Sn!pA#)KP<=?gw zq!koN$i{$U5)^9(pL0M>=l%(@4df+cAy5s&zYTQ5f(ZY%jbNjER6yQ>>H@jxBPdyb z4SU9M@Ra~mhWjJ`wi5@Ralo=T#HAnkx1EA!N&amUq2__&9;ypu9w>zvfYU#yKIPwb z08tEp^S_C)2xGSoBa88AP_pfgVdgLfT`*$M?ZVDue5@lB)VVPLO-D&|xH5offeu$j z5Y5ry3OWJdg+zxdOZUNpF9bSVSwS>MhbtSXY>?=1U zQ1`uV(ET3~-Q30(J3~}5x^EcAs1$TxHx5zJ=|0pMqhioqqGDitP`N}!q8oG+Vu11K zZqOwgF~%+`1>GSk5#2YGLsU$ZW5741 zPa7XJK4g5nyGBJpxt5_jM^nwxN55|Eq-KULD8Q-$IB2rB`w-|x8RMhMH;iv} z#;7v5Sg>@_pl@#`i!syLF#72Hnn{V*DO-U|;v;&KMOJAz259pLXWgivLeoWA)Qi`&R zN=0XhiVbKI20Z5Jq9UT`qM`!27Fy9oMW*{GC~%BHtQ-{=t7RH~H zV^m^{Z+5zGW5SpaEUobvooTE}<9HZj${i<<|N`Y~Vib|)O1SrQDgDy|WQ4Ud& z04eLf2J#1}CkqN&7Zn9#7Zm|x7nK0x92J+&DxOX+fleom&M1~nEl91GbGY#hXk`a% z2&+W}w2`43GB*U;o&;Lv0qV#?E{X&V$~ONNC^2dNEm5M-{9B=f-T1&u&|-&!ubFnC zG-*D+RzB{cA^>X6>_TnM>;gAuJ|BF?)P1k}mGQ}Lmi|tcGcKJjXFMFO&((Z@Hc)Qy zH-l&0LR18LL3dJuy7-`GN{Nb0>;KZwgC{`!AeBx?4%6v$Q854wu7iftL02DvhRu7y z=b1}`YDw@;a6!;1*`NuB7oZiJ-7YE$%}03nw>3oU_Fyn}QBisA-~5}c%n#H&@$7U_ zA;Rqapd|!gv$y^RpDL>p@M1NnvF4&;02PfORA5#FG zZ~GqP{N5TB7vpcB&IX5Z_@Bl{p`oFn#^HZDMK-uuf30~AN*~=lDxi%hpx8D(^TKg6 zXowvY;qXR$^BW0J7eoOR!NnZi&H~-uEZx;I-P+y3pdO_}w=<{&6zMJ&>Auz}iAVt}(s^s!K1v zFg^$x!vrhnzHfXGtN>)LK=--Ehafw;4>6y-_zJAR_!{>Kh}SxOR8)+wfi~eW-|hyL z0uo>a7hiJUFg_0okM6IH&y0*BJ!Gv`+_m(sG3vV#~^k> zY=T+~vCQ}rH>f?X(D)c+1<2}yub4o(jIV<2HtzIbF}~VaAkuxl8`K>*bnq1m#4zLQ z2OqLDJ_5NI><#1V+$TE2B)SiS0v#*@GATqw25OEUhjECC%)!?zun;i51v20<$N=sW z#OAak%%g z2z8$@J_U&i;}hM7F1|26)amyF9A(CbI^F(Q|1P=|7at2=RSRi*gUIGL7NGR#0y57h zyqmeZM#aOBt=pN!(2b?rnZwYHquZIs(2b|tS-{Xupxar*&`qS;}IEYXgWCatJI75t)D@a)Muj^#EMtBNKlZNaVp3&=L3` zT_BO0NE!v@_yxiQ_%&o9mfzwBoBf%IUjyWVi%bxu5EFU9&VVTZI|uA?xCqE9kOR~B zi!L(pha5s!jt~J`E*K}!?I+O9)*Z*v9mdmL2kHz6bo+^bN}_IX4+3-#u8WGs!516{ zA4+tFsF-k{0N23=-G>i8k^l|f9(=*Uec|A9P_3f_V*dbLy4HOIq~oy!H|QEUfrAe~ zr$vEkR#0b=6H>`aKtw^8o=F^h!NKXG0%9saL_syQ0z?#ak`zRcr`t^iBF58w&=};Z z6QD|r2V82{7`uUQ$L(b6K4k2oVsH>DcgXl4=psgAHyMx)aJAsZ(tX_6MMVds%abFg^~^u5<7-Xb9Y-(+xB+!()8I7$j|D947;s zzBIlCYWaXmgAf&kgXaZ|Yg9yxe;zy~0Lo6?Cyf1Mj6+mJjB8Xt0ul#L3K*a0j1w^S zQ33fjz}QDcp|eh;Gfbk>Po~@92dEj;$p$*JrrY5U*zInhS&V>gP@QDZ=>{4l4(N7Z zF?LabIw+vqfx{SdLUKSSC_oT@ZTK}iXe88mFcX3T;LBo%O7?hD*pi@A9jvE>=r~wLll$&A;KXS_`^=~hn?aV^b_c2kvC-Pc992{ zB`)&d!o)=$T$;GZgNqXvd2o5+A`dQ5T;xF|N_<>&^AQVJg$cgT41#Vd58LZ~n(vX4`z|L$AL8^P%3b z|FHFqy`BQS4j{WSJ4TmW>#JV*dk zT%Lis2h>&qow^_Pzf=J1oMe!5K=&xg^!hO#e8>_Q@V}Jfh3$4wD?+0C7}!W~|3@I$ z_~Z^o(4N>uVZ9|P9Gz^&2Rh?eI{i30!$3>%1R5VQFmNz6{sfV6{8J!fSYXS~fcL-i zH2)CbZ%G3!A^9P}-*N%8;OK`!3A6Em!=T!NUx0&OAOf@qj)h<2Vj6$(FBX1{Ll7FY zIFo~4;}O4LgaCi|1E}C5evQ*<{KY?6()g|JA7)JBFF5d@Kl}lB+2>)f1Za_`V1fdF z_yq_z{35@`888#10*F~4Edc@i;V{SDgb0V<;17q}!h*$? z1njmTTLD`03iTw|mI6GsKtt>h2h1vPh{65AFE|6#<3I^Cq;Q7&39Jk56@I}9pcBU7 z!2|UX%q{_(c7YZPq1$D3A6w8(04-)i`0F7w^d9hsKZM1R0@NB%5&=cZL4LsnppAD> zrHA-6;9(95y(0|#;Wt5AR`G}5;1`?$+QH7RaRrjT;EC@Dzs4#4@DpHBkgmfH{NblS zy8iQrpWqkl0PS?#0UDr1q+P_ctP_Eh!->tr|}?k9@po0QRBwXYdOb|c` z%cmgYj)GHeC`959D1jaN4-T+mP}~?gW_y3bA94K#n^Ma$Eq|aY*SZ!2#k1XpZIJ55EWsMvz(j8jsWXA;y92 zOXDy8!@?i_m|rj;0pvi?Qf`DvAa_DjJIILQ-{2zP2sn|2@`v96TLUo-yW=!o^9weB zQ#p#k(D;BG%`ccx0P^!;aJmZR4}XnfGAvFG!V^Eti8uK*p2BSgC9z^qxLe&n>HzgH zL>3&mm*FKEIC5Wu!tV$pzhDD6xr4$Klvu(KgHoa33P^TAB*r5R(8L%DNsOS>z5~>q zh9*X6feLci4;JuRcmZ&o35u`q6X5({b^j1J!TnF;F9yZSx4M700h9*dwoCve zL#Qrn7D|1qCqJ_Ww> zq@IDn_|(C7{K_Xl2jBSrYktjGdObciy8Bohs4t0Oz7K}^{M!$NgNBVjc0es~(f`+d zO8bQNIbg>jb*L-KCc$ z4!ktdMJ1y702BBM8XItUFc{zF-=4)}{GWe4XqeW3f4dtKsH4REf`7YA?F2U{m-H0PYQk4g+^;G!F}JHtR5G!LZ! z8l}`Y_<{+v)KjO|rWLeNxU)vZqq{~$f`2;`|8^d6{`JTB*PmquwenS%K|LD*{_P^d z%on;rmjWI-_=+FAXezDK@egR6nSZ-C6aV^i{M#M=@vlD$xs!w$bVIKS|8~%!y$27z zglS*_&76wxZx3eSUw@5%I|E2Pc%lxx>qLWpI}0OdMuPbQXaylm6L?0Af4esu#1bZu zCXi1Anq5=`IQX|auz>9p0o$q3eG{^(^x$j$v`!wT<^vp{&QkLs(14vtbB>A*XjVmr zzf}-20hiGI0~9&hzq(6QLON?yBtV@M(CyT(LH(cv>lzi4;;>$KM(t0%EKZpjrrh&3t+Y2EBu z4B=sEoop{&|M~y_``zXbj0fM!bH4};4|{PFd_RcBcvp1^EjPxOy@e z9|0W#2}+xgOVGM|R2)FODd6KPL8GrAE@*3TcMEtQUZ;x+4`>$+Xm=ZEIs%loXEQP| zgc`qXuwwv?$dz!rHrVJfl>P*9!vAjpYwNCLfgXJpbnrb#VDt0(fX*5fgBK6^{y|Rt z1?@@zEpfI9cwx);?|&%h^v)R5Q?idw`|0SPUK&ztv zn|uyXT5NtDY=#Qh3EH4sl9mQD?|;d6sAIkd zyjahVe$Om?b@uk-PC7`ajK<^e6(0&)~57w89xx0ASoD4V| ztgjb+WDHRe(7sjTi0)PeOt;$d|NGzD0=`ZV6oL)`FQUP=D7+K~EtddYz6;vQ5(m0X z^6*^H=qo7tk9 z&HtH7IQh4^GJ*AX@@#hNb^9OC>&z1HLS7HlJLKqO2BlqyBb(oV#z161&Xfr4764sF z-hDJIytjzGGekw=;5%mH|JGmm-H(Av`_=>eEudXl-KTp4{&&Zy=xCo{KHKS|B4B;3 zh{gE8YpL!--KP$|U}}EIeDEQ2w@Wk2#Id9#&2IU^KaAaKI^4@Li;G_ zSnz`{aUXz+_$%NQ8Kf?s^*U|{HG>n&yJbY*Bh0E>t$hOifwYZw@g zvw_mN@ult(6&KJIhM-v60hVW2Off4q??9P8s5fbpfL?s|NIP}Fduw3v9yJg^( zKuGfum+lf36(`X2zIBL-NYM;Xif=x`ak%-73#@Qb{Q3(NEFc0!}04SMt zhJZJtiGYG2AS}H3H#dJ%Cg`L9SB8BTc6%^bv+=irng!jiEY@x;{H?yA&BEJVInu1% zIQU!b85tNr+nyL8`-2;7^!}H!x>QkNs6l@nvBNAv%GC8Ax9Ojb@zrPj^=|CexdIWk*0F_-Fr z8Zp{80+{cDBlgAgCEzRy9+d(`3~093_{@u@86aVo!=P9JpR5TgRdb<&pv-vY%$deF zpp%1OQ3yF?xw}Qh2NXX&Dxl+Cx*;iX+2OP(k;|r!^Kd_>S%qU=xaAb9JHRm`UHQA8K^R6 z+6_AVb{{ind~KTzhxYyM^9NtccfUXQlBN5w@%isJluvxWYy9)zTY2s8-PaGklRx;1 zsr#7m_3t;7FBo43AAhP1nur%U_+GyG`1fun7Hv>;hN!6YvN-p$xbbf@>a}ra{@Z=N z`5`+fb(V1M04?mg{6HBr`=rsE#n^hX*Por=_0_?b%%C=@^-cbEP^$qnFJ*m@zr7!H zg8cy|=EERP6DX~2bJ6_Y{nr$9d!hDk?hpRK%s;yihJ&)4_F<2J&=(mK!3jd8`3NYd z3PLvjoPb#SL%|i)))p~7*?macMMXmUaPxtGpa3qZX#T-bl+gU(2Y>i&{_soC{aR`K zc|4lnb3_wPr12-7;19c*#-Hb-$&$vOaH9Dj2Sn_m^@*aZ{9%_N1BW*__`@#n3xK-5 zH(2`+q0n6WkxIFBiS&KKA_v_c3tw_L|A~0H`g<2)c$Ee8p(zRB+3Ik%0lS zUKCXFh=9-65$O(P=oIfQl0W#4we=Ez3#c#A&D`rDfAA$MII<5F8};h+GB7YOgo3L0 zUU!y&7ZwY_@dujzwmw!Is{Nt)IE(Rt?sLq4Kd%O5x5L`!dReyq`TrlZs7$2!AX7ju zOLqWR>)!aF?ivG#_Iu5eofpvN`+(XrQq92)H792R7%-nKKZlg6Btb z8Cu_#a)QRT<2p5B!9Ee_b%oUoz0NG1+MsexY8eAVuPZxf1pNiGhxM@{QP4zrSYYsr z3*W%o!#lO3<6;kocmLD=(R`e_`S~B~e`W5VI=|Qbzwt@!>((Rik-SkR3!YHk1-v5&&2$}9UPy2|M<7L{RcOu__smYV*K0O z7!N+=2<1Kz82qBDA5?1b^p>%JChpJ2gB%YntU%-EJ}NB1#<#l}n-AC@e8JlMgRv|D zv}P3?ZrT^azTX9{fAa|Mtpv>`h)n1<2Q4jjvHHV&jQMc)1?^+qCycKdpHn^snq&Qb zX7^cTP%luz_*`?2iU?z;|DV$Rpc9J^BPLzDeNnn5c6>DdR3Qs2^D22B(fR2Q7WYPWzaunz)dX^QSTA7g>kx7~+(%UHgr{ps~&VLsk`iGk7aPxB>)?q8s$^J8%1 z5mLO0fNlZ>O|W-bG#_SZKETo$qoUIM3S0|=f~0gBC?XN-Mqx1u&Xoe)=FP{zS@K(n zIH=tq5T3;l{Gy;2oDx6{z4y`3R#o#G7tn?<&=>~;sFfDc8zF!2HEVA^$U>7&cF>}u zUX!_?3>TKg5c=ZJBCr|Y5>wbk#iI2#e~U7xas%x?1C2GrsOa8v0^WS8((MAieO3Wl9(Nn^hac#c>ORZA{vLP(x&&ws z7Pzu>QITMdW#C^Qqmp6#A1vq7oud)}D%?RkSvo=MmRwXMx z`4R(jiHd-5h>8fPwFNpG@VJW#=}#1rR6xU>pyrr{@LT2(6$RlO6%|m612me@eYYF5yh)%NqL||C>i+9LfcNb6s z1;-vJGxC5MyE5UuW$XvvF}J=gHSBffw*FA$2wGaA{khleZ`yHo2F8G1ccu(b{TuKi zXdyVJj=9+VXLt!3)$4L);NNzl!$n1**IAVLAh>w`P|OZl7k(IQ&PVOf&F{FuCiS}g zLo$qYAp=8~kBUyOGY8YbwBsyx3{ytO9dof` zWeW{>;Xj)J6!@T{_|uNN*s-%R9CNYbWa)^p<7z&}4XV{-dRgoOUZ~FoI~CsE0(l&o zpc~(SHqtMIk5_<>mF{<-~8?G7#J9= zU-P#=11+_3Wnw;VeVD)fCa6_=O#7(zapuFI_H1v!|JJu9yxokUL4n{(z4-_aX!V!& zcTj~b;>Y|MESkju+KkB`ejp4atdPckjSXCvgPJx5phF8l!jKvtw79_|6x1F-s`Ei- z-Gj9{bUO(AztDXc+)H)QKHmI-DFBo?t^7d;6o9Hw<1;UMdO?*xC>B7`0!oiO zp!7&d{XY}zOtR|#8F=dd24iqC0+ny@`X5xjhp5OvGEcWq_o?QG^4(^=Rr1Y`9vpnn z+Uq6{S{ixq1*l)b(S5A>fqe6`2h1mS$T2W5Xdh(0c<_ZhGiZELhWS&cLF<417SK^+ zpiLm4)gHm2y;+RfCwe15tLk-nbwCw?3aIMnW|1^L30kPuda1;%yGBK$`*ZVgmhM;G zH@Xk^*0X$1|I=H>!t4er`a!3NHD3Z>b63y5=AwM38~D_p>)^T|M@0lQ+yrV=cKR|j zA7%kwn10mv%Qh-GPiY;=4axH5p0|NPs{n~#Ckk+q^!0P{`Y0R*c6K)tRo z{_PCiA6mbaa)ai}jZemp-jp3Bd*4|D$u2yJ{08Zduh zz{UXT&ufH-zL*L!;D`v=Ina^@LIr{nICvA31gJU`;ot7c(0w7TlfBoA|KLkdJoA8B z0bL9X4E)=f!+Hxqp=^Dq*sNE_EVS2|2~=hVya<~HPT?}3fyocW@!H3lk25j(AK^*sa0M%3yp<&_t+YP`e?^xrr51{)rwu|?AfV|NB zfFIPG>^{}_2qfN{$>02tpZUbWw=6qAbIqVMg`Dsem_Ma;8nnLUZvEDK! z{`IGsPcUCZ+H#%N83w-H;3hcrgC;O?z!kbcca4fpS|?-kVW#GTpj}5Q&2PcSKy>D) zNR)O*$H&EjQ$MKx4Jx`2^#$nsn{LQ8Io&9@gxp_I)7 zR0MtPWr+oieOZ6tZvq{_(#s+ZI(rE;8Pn_d&-wy?`ymDf2FoofpmYEEo3=7AFa&|p zx%MySf8j4grhreTvFXfFu?gsQ<@kT${}vVKVbCt1jvu762kIVxss&f(*P)==!vaz> zxTtt&yQuhp>IG2yDvP0)CBh-#g*~X?^-+oGjscHsdmMBB&*x-CnP<;W41yGV~ zd;=QuK*R@Vbfmind44@ZeXB z3TWGcjP;9R$ynn9pkro1#u}e_@t_T4H^|1rVd33>L1S6Jdy5$TnGc5t1O|tJmfpS4 zYGhylWpWcxonR0a9{fV05ggVroh2$U0o`tpum+u}13DWVbQWkpw;QBm4L<1`d^T~n z8>j{@V`)C(aPS?+E>OkV{Hz|dL5{yo4K$+hkAuGn)DY|S{@>eT!VEh4@tpOIa{k^H z6;Lb1`UHP7XnjZXKL`G%MWDvT8nAfxIqlcI&I-*B?LkSq`yZ$gsr|Ee4LIp)zwYgU zsDgw5sFR=q>f0jbBlraz9`rgm@C)z=g6Hi$7Vrx=Y~UB@5dod{*?h$@TfCKmpJ1GBx_4T4H%{3|-9H2f3C<7N6cAx9r1Gc^S;g4PxDed2&^H@If z*D>@uaD3*k^Rf8Re24?Qp5>ay59^CXPpq#M%R#kh|L*0H(*Be-p^JsT*OSq}5xjNr z6KJ?_7ic85yF^97_`jR+ZT@YHte{{!_<}?Gg7w#8E&gpRhHkwbATiJ+*Gmo$Y= z$SWUg{>Z3&k^2Y82ui8_*1`Mt2W*unjV@ZhYp&ycT#00#^v2l)}Nkow@k{sQPO?P!b91orZ?< zZ?9(B3(DU7+fQA7Z+*1LdMBvH(FScq6A0tqZjznWeJ$jJRB*6j>BbnZSf6WK}F&}0IEsqb` zq3StFr87h&;QK@EQx{({pMnhOSr{K^KJ_2me@Za^)|sOc(|r0rs9oGyqN31!9@KdQ zwVXhGkZu>19Bt6uS2^JQ4FVJRx7TR=>&^YgzrB>fvlFy?>RR{tZqTyZ80Eu;E-Ijq zkT5=>?4yzZUSX>MGPnDX@j>Oo#^6a9(B!-E1<)p;?(^K|j1M&){QsW;bjC4gnXf?i z<%2H;JV7@~D}%Pf8MK}(?d{G{i2Ph7U-BnP(J3q0opkNPL-#Q zyQmm|#J*qbKB#<7`RKui{0ATKcfVu4q5KNu7w#Mt5$2b$4kiC~Q01EfvW|Z{$PF>ibRQ z@7)KRzcVVksKh9r)pSuw(7wt2tNYydTimXMf(9#&UVLGER2j4pD8cvzXj~GsuE3!A2S0z$zkmNh6LH|`J2()Oj&;I7t-p%@ zTU0JGca_Y02cwx4;h;uFfpHOJ|d%i(fDomDgN~#DkA*r&l!K~3{i>c^ifIJ z35pc$6QIeW)BNjQR6tupK>JTYTW=IVTZ#F%gVx7sfa2jGNI^{ZEzo#D0>~%@{`Ed8 z2Fy43x4Woh@UOqYe35_sg~rFA{Mi|!Vgot$r87ju0hCrj6?S)s3TVC=G=lRRRO@U1 z>UH|pS)=089in2QeHk?F&>5oQ!@s?P3ABfQyCna15y5UB@UVtQ_i?cO{OfB#D+5k3 zAMJk4zdlDLf%zZv!S2tX1p^AqpulqAUk?g73FaTn-&-%0$byQq?xWo?DlX6!7A)ML zV_oVQ7}7dHD!18>i$E3O4-WpO3{drVpf?n>@+G0yM1vWW(mQTDObTzcfx4t$*AfK_kLU zLO#0rhzF?Q2Cn@;=S%T`=954TdE*1%KCOW9TTq$;Ak@C+!cQy{f$t z|M<7_c=b9n@oxw1Vvy+m1j>CDpiJwdVgkw)I-ullz_>$8L+i;BNw6o6 z!P31p==?8mx@QKh`fxn>j{o2*e*XQ(`1ij8RrTQf=c6KGeZHu#J4Qvp_!6i~p4RD7 z{qNul`R)&CojH~NzTZ3eRvxk#2c*9HMC<<&fBx+(!N$iRM>;_k+%!LAOzUI`cCx-+ z^avE<-Cw`o>plw6XMBl&J5R9jIZ#La;0u1p+M?zMjA@-bU=0uB<9byCA-2Z8x&^~+crF{3x z=GTm+&$~lZM7ocG{Qmt0I8eYTQu{CT2s9b)f1v4u@AtJ2fjV5!@l*coJObeOcKT<0 zR{6a4LG5GRAHcfPI-UN3QUj>QdCgdQ4b)se44SXxU|>MB&kaD+<}E4~AZm(=4+jH7 zFlgBiXax`l0|RJ`&4mM8z4G)nG5iDHyRHEmaSH&6mZ(_RGVn1l@V6fXmFsgqi}B*i@a|uop$ytTJ6&0N13`0% zG6!EVGau><<>>Wi?{wuk_>!6VV5hG@r>h9_p-xvB=7XJ~5}m#ZovtdKp&G52wn)$>BiE@$9$sG54>Gl;WF0ScH;nb z-vqk-cpN-C-8ee^cp5AiNS-WnAT<{zN4v9m_Srk4fO-DBu20F6)@?Dz*N z9=~h5s90zp3J3!QIA}O9AQ04WGk7tR71BM)VhnikmmAzJGig4+!h9?sxYtD`Cm`%a zIcUqn5tG&frQx6?0U9zwtWQ!A0j;MB4FmP-bOOR(cp(|L4y$pXO}EV;<4O*8*Qi)@ z=cs_3D#D7NC9; z*v<%0g&*?bGWhUHhb+eM7Z#|thKIe_2C68INVFa(wF7wo6vhw-n}9SMyqE?$NS-nL z#Xl~v_XD8b4-b1$1J-HMdY}ZflFlHDF+BXmj}8C+H~X_NhC}wEym+w%>^z14r7|z> zZ29-U+eO8p`G|_Oi;7CAXBGn}c)|l-C~f=)YO8?8Y?^;CmYRU4D_vAv!UJABZ~gcG ze<{cRQXY_RZ-RLe|4U^+{yp6a8r)I=5ATCoe-54Oput;97Zr^%uH!7$pajr-3^Yvc z&>P3n$<~at7A5$_+D@>Cz?L3hIS%S3GB6(l#kEL6gV9=QK=?(_avLv13t_+~oTQ^%Ldv7@lawvqoSPoL-qhbQOviIP@ zm-3)9&+0qSI@th0{-JuNN#z^xc#_kW= zrvih+U;J1HQl1R_zbX$3PP+p<&^jB`OXt zwr&C$!DD>e_!4Lcm46$Lc=y4JFSrhO-|S!!cRKi(-TGS5%WhwW-a6+0rJxfc-ZN>| zs01`WkoV|~lt1`FUi-ws*Q}nPc4McHip-0U&Hq4MB8}!Fprqi^dVs%g8K|}6qvFwP zv$L0HK4?i~Zy;!Z5j0N)Iv3hU`!c9~>D3vcqVT^&MZyDoxT-4yC`-6>vL6QpC&LSE zR&WZ^0ZoVdsK~5fEa3z7E4x9%KL}a-*$L{ocE_{$ z8JDv(9|2h=(EORv`XYbROVCh+)Bk2rt8FD{%l89z{_soM7x=@UbcU#C^twuPU*`|M zt$me095i3113DiMGzbMNZ};Y(y z0yORrcGLP)*;&x>3;bbsL7jAd&`t$#8|M*!*bSuS4Zp?_XyfMrsHMX%0OqoAf8Y-T z2|VDwVSTFHpqB-_(t!DB_j~Oe6^HI$+CSaFr!5)#X#C-h(f9*t@x18<9UuWxaIX9C z_nY5uaG&EotbF48#nzLRirt_yZA(;4K!MnLfWN=#ANbg*9iY&TZa$)M7&2c5Vu5l2 zC_RBE_D+Ku(H6}Q<->ZN`2@6Y0vgl=EpleQ0A8~w!~6@}csZ{6pOJy#;CoKyA5PuJK-1O-Ux8Y(6X+UUkgNE&9R&6AIhr5YGao$onvMA~Xjd>x^J9MI8#_Q(YG@w@ui0#V zAfkO^2PbG==WzE4Q`9oit-j|X3}Hb0Zs{@8p>5xi95 zoboy26FWp1K*1;f{but+9qo@u5}-{KP^-nXKZ1IJ+Q&fIqx*z0SSM&vJWKNf{(~>& znGb!xnSDXK`60LV$L2=~{4J|NGs-S1Dxg)c^Z)+;-}t-%bS`wuDQLyVYtiPP?4=xy|3N!OUUM}6KPSq5LfoAf2G> z5~Jb+8hY-At*CV9wP}7)weH{l&0{NQ3-+J08nlUcp?7l|9{ZMe5EWP+h+a&=U{N=Jp)>A z0_xfdgmw#ps{o1KVsKNB~QqLD?NF4k~@X`(HUgi#JMC1dMMRzYT9aP@>Ae-N)@;_vP=mJh(3#pZ4`=@+sq+-DizYD4#NZ*?OS#_72c6S@&=4!w26Bbe}N(ZG5`>v-0Wh_l!?)e+KnI z4jz0b|NX|nhb+oJm_Hi-hRhlt?>^ss;owUS0+EexK!rkg3wXE=v?l~~ zt!eWCmQYZq55xwqd+OF}J_=nn717JH7S!hLwUO*)vFxl-0X17hKv&N(Ffar*A7BXx zeqmk-y7~s9%#S4?Fubz|d=k_PIfO(&7HF>4{xIKUKG-=&1=Q(=9^SvBv!kQq`=f)eK#OQ| z_~jXl4;*(x~TYgb%O@G?w(kXyMg z9CuLx&3Q3&p9T$Ce!mDCsO~;^+(jh@q(=EDXjZDBJ4eOA_}lkK;IS*=7H~L&7f)3% zzYzYUe7+kr94xbwfq|i+`}_BY%AfaxG;^1z_%MF}T@J;-z|dKu5+MAm6XYh)@G5As z*QXoQsaqzvo z@sCdE!DR=JL(&+?cI6*P9MA-&G3da#nC|bFUwpr={NeIzFU0kO@A%HDsEG=iJ}MI3ue*Izd?Z~!%clM-hp4D1*QjV{)~J|B zf~)`yrH6oKy*hnVe45`fcHi$lD}7t}T=!w+L(CsLK_{4>6~542qN1UE4%7tz4@ZOL zx_wj@MZ*vkhwnE)YvPnY z7=n)0Jk;%@V)6Y3Xj%_6n*aS)r;mz7_bK83;PANLeO&n%BgpMODh9%!@k$frpP*UI z?h=&%^emP7=9_yN#@4`COTitZAX8t_Fj;M5bN5&+6^mY}W?N{&kbovejOZVug$ zlng${4s^m=4S0k*W&&siy}Jc`V-jctB8#D0XGX6(OK7KyO2LczJn;0FO81ZMTcA!6 z=8w$K+-C$zYuysvpS!t0!_p-x37}ab7tq*r4FCG` z;NsB&R-!V0;9tK*1+>SR`6mDRIbas35A(kseB3-}&L6ZWqy&_18$s#TM@68w=nuGD z)zLoG4axx(pp>S4u(JldTosgfL9<_=DOqSNLDMnlIu;X9fd@+M;Po`1Anca!bz}Ko zqLR|Bk;M?)*`flPNqw;?8ys#LpktZ;m#8Fw23zK3Gk^|L4PXZ4K^0J#34?lKpamly zS)lcvbOjX@&6EK!XvDA3^CC zdZwT$C`I$HIVcY*S`NODZ+^+p>7x?Te1oy^Ge`=W*j-e7_}AQ$Kloa{8JyTHnr|~U zA7ydx%uxyG&QXc5{tFs4=>~;rjEV_=(|J((7lW1(&@&;sV^nOqLsTrfw}9IL2Vcks zbnX#_e!<@c8t7@>1D509Z^{Ox z5f>GK=0hyKEGwE1fSN8jy^bu<7D}%p=iKnqB~XA6P^+rfhFU_sE%Hqd^+Uf=)SN1GqAYai79-07lH((5hKeY~?or9vAt z&jq!OKl~D?DCmBn{kr?U_KnUp;6MUx@!1P%l|lopa}K!K&^-t27*J6P-~S3dxU|<( z0o1u+KGb}agI|Eh0(2CZ07JKnN(JbAB>^rFUy!T$5J=SnegPlu2OyEKi~IsE93Va) zm@nwV@u1s9rNBBzrKD&nDERopE<=NzUjuZGrw4Qt=tAcjuv;*8;dFzx!$epgEjD@0 z3W)^JoH$RjCTKswZ|%#V6Y;cPbc0r*uy8y6;r`I=!u5yKg&Vx+61)orX)3Jo2&kYy znhiU1CKxoCBVl|SGxJpU}*RI?jI1dwGV4M{sGNH-2koZe+?Rv z2hFpALsk1VxWrZ9eg|q9eZLEuy@E{Qq)q4sP2aF|JN+>}t$Y?XdjqO8oc@3mAABbd znzOqZ8xOq`viS{%@d0p$w$nugbf_3;#{UFp%PQFSpg}2#?-vigln(=)Dao@B)R|Pi z*;%3@0Xg5j`$YHU%a6K`cAo?9g_QxHnyUhu%rm~w{m=ME_c7&P-!B;d=spaV7r6Wm z)N1?8{R1@J-hKW1E#*(f_rT4NbC(}1gW_qof@{Wxn>L_jAP zH~&zm=>v_~bYIoJ*nQOaVD~5EkIEmq4}HI2d=-2utjNK4^4y=h&wanC3~D56#2a7b zJ{A|-DHsjf90}fE2U^UHn6CnDl1I-YJuVCbF)d6L-AKgbUzVE&d z+Wq9hzyO-y;cx)WuYG;Z*Lhhy^##?r5^c^fPn zK$Bk}T*L}m)xgvIyOzKGDrj8vM=gK*84v@suTe$Bfcda3D6tfAA9GO=ZR~JS5qr(j z;i4iceW2GzMI@}ZfaRDAi!@V5jERIB^EvDLWqhEWl(NSd8A6$l1-$0$KB|2 z;0wtd1_tKOpz+)o6@gb0`9z)}k-As@H{MG{{9Naujpy2ueYD;h*{0`b6 zjg(`W-^c`m$5{-z<(m(Kww8c)jDRXI@b0$j;1)YiXNZbGXs-uLFUt(jj2hB>W;Y|~ zg8KC?Di+{cSp_r^4LW=tT(cN|1FZ%EZR21BZR0rF{X+N`|C+z@2j9!LekWG$$%EgbZV5&?ygZWi3QbRphFd2NKXIvzxe}WKzP^- zJ`nSW1o#Lx$dS#2_a8@Pf%hLTp7-xR_Wj2@^J%jG*lG5^|KOFH7GW>8%}3pTtOk|~ zez7l;0kk_3&;Da@Q35VCx{rn(e8Jj%HeCBeugzUhyUqG%8Elv%h9C z{tsG4gtUjwjipl$H0g9LkAVR+->4DxLVFr$EbxWPd(e=aLZ=?m*cB)}HNF9*JkLGIry7ED_|S!4ES3?RUiL0KgPzNpj=m`)cCUzv?RNg8MKpf zn;%oJ`(M!hW6(0xouF~2*8;un|3D&-7#JA9(;p2sd`$eUmqEI=&EAoq+*VinxF#3|(G4NC)M3gYM(dMY*7I zFdlLb%<*V=CI^K&0)whE4$u+@HuwrhZvO2&Zrm3^nffbebPu|rFAkimk<-5dNV7yZ z|Mpsj=Hv1Q-?K3P4-X4|5t+`w5E}fV==}fxpw;tfph-#4;>qS?OyKPUVK27lFff3t zC*w;X*&_;|&G4Y$=|$Otp99*159$(t>l%U^@B?@Jhi8DTb5JvYDOfJ}#ojbR82}M9 zU{*8ie%&zs?Xe8ahd~GbfJ(3$(3p^qibD5M{_Q0y8rlaz%S%9&NpB!iFHa<>1-A`Y|$1$IR;qDEhsyOTi-0>?agG@zIpI1bMs?Re!dOL&-~kerFGi%x`X13`9MIg z8xtr^GG{~5q(<0_8H@k@4-R|r@CrCfr*+za5*avkfYu9v_uA-$ciVwh2q`mxXD2m6 zdox&?|I3%_fu>AdR7?W?gU*n+`10Tbd2Y~so`ElnK`m?-&}j?;ovsYA@o~*ZWDfWG z%O8Bn+AY!nS^*9U(_WKa@V;QsNJfc@NpP=B2WVQR*MS3+m3mqFKovssbNNz@UKX&* z?qA?J0ht$vQ@}290Im9UW#|?Lt*hyleqGcZ{RiAA0(Z2|Yk$A|y8965re5wFpd2Uz z?c>F$n7n9&n$Uf|)0F{KJ%d(01^nq|xcmyFp&K+Nq5*C{NkB$eyCXo7ufazzSzLa= zeFI_`=m3R)?&Bb@9|{iWK7R2c+`qqH^Z?BW zUH3frUS9dc_xs%kn~w;9hYgHxEB`S5*<7O{z*tn+eM}p21i3~xk4A4UOLr-#bN`(A zM)zUZ?jr3E{A(`DcOQdvUO^k1ZghfFX&*EG*nJH&B=<@l)bjd%iTj-Lh3^-^1D7Ho z%Ws0uJJB#c1x}HmbX__Vv?!+gGwAf9?t|KgjX!q(F#fH5Q~96qkAv^!A@$IU{QiIc zyAOZA4mws=`Is?i9*)~ZMM3#EI8Iz%tnUZSvP(omV;hv=K-;sM-^lQ9=V(32-|`34 zfD2Jk2=0wyYW~SzuFJpOfvML=MJJGdJ9hwRC8xo`hy2_p0$)5~WMD|^hRmR*buveT zQcq}DcyA?WsdV#0e*Wz`RlO!vy+NRL)1WC)jb4@tP_@#TqoM#BGXUk^Qlnm$TF`zR z&?cCG;Gh?MNf1*(sV1$HnSVRm!KeJ-b(;eG+YMfV3VYBhV(_iA+8_D12mI?k3P}yz z7obK3fa*ce%{B@z9FR-{&6{_ff*kTB!M{D@AOCiS%WpyHsOuCrXknfzrmBGDVo#J|1zA7};cS>|)y z@YB1re{_F`Y^6H*PM-N=S|>=2_Icx9{-B|y_wwLTZ;|i!l|h{Y4db89IVv)Yoi!>V zr7Jo<^o8UmP`LsoefHox`R-%i?zPnj{(vhJfLfBz<2Nnbc^(U z*bBRW2YfFJ_Q(nPnUf8v2mo-*yr-$cJ#60{^y?kb8GPs=)5z z-*y7c92H}cxgcp{afp5qgnq>3J0JyM{oOoULG0do&>S(x@iZ(1>Fq; zyRv5|NT?fhID){zm!R8rKzxuvXt(Wvgt>o$ZpQ)Nv;*NnBNlv-(ngRF$a0B;F9g8% zS;5@|-emxZ8t`^XumtF;om2eVCV;iMsDQi<^Tsm{kYoc$29)AJyIw^gH}XI()d5L> zt2YCF*gZQ?p`+a%EXD%Hr@JFKx*d3o?;C>_cUXY#!vI~SBN5-h2BHNz+@M$MxIwSh z31jYX1FfBUA<*H*3fhIj(cuQYUB?Z)TvMRK4SKtd8&`)P((O8K(A#y~cp=*2xI5hV zI{f&-Z6D+^19m<&X!lcacPt0^%GqiULrZphU$7wkk8=kM%+R zzAn%b(qA0>O`U8E42_T285kNWS-qN1{cz&f-~}D<-Ti}K!<6BW2ZQ#nT>_xy;33fd zMgbWq(CISa|M@ju^J_c?uV^Z|Dv-usbU}hYZI$^r#0tde! zWQ-13@mcV3HANp8)A)-%fHfTe^<4yAR1!dov%)WdtwGj-FdlM7>_L7kiq2pd`v7FD zri)4dl7p}t3+n8F55+FJz>&uP>j!_xKmPD<{NX?OHBR$uyienYxb`a}$bo`uR6xs0 zV6ObYAO3_t1RUZZd%{2RYn%gXKr-+Fe~2n5O29`qpXJxM13HnN19TKSBP1rk)?NTl zhWTT6=k-8RW%wGX-8m`=Y5YZBIKb=d!1O~1KYR_;m6!O# z*MQS0fB1h86JppJh&hm)!XNgOUrXc&14$F% zmq1wp>{DnKfuu-;hO_({x?tU)qmYX}fN}{a6M~{Za0=A>mypud1^$q$*fJsLq-W%; z1W|;UOTe*!HSe3PgZl0^zs7Tjk}n{Kg9?Bp;N+3U|LX&P z$X9->+2aO($X)*MxBQ?()XzXty~gD<{-RHekUR~}9WUUi9-NFo_a7kT1aM+Q6$^jC zuW^H13pjqV=fA}d-j)3I&hv5A33Y<0GgJi;UK!wl|P=bM!WQX`63Gh59fr0}7 zo(925dkr{lL6YEb4DW&FHE2Q$hnxul$_xo0LqQ{q{E+Mfb}_VQ4TqMx;XTj@hGhy^ zx`#|FgE9vs9YYqTr12Mh<=_tkdHX8|fB3WBAO&dI4_fFN{)j*9B{VNDfo3*vUWa9L zSVo0qPiTgQWDcm=Z};?c_@ z)O`UggCuIx%OV8oJomELV@eue)#3utBGb!ahN;B@Q%f(4bZ3Z4O|J>e`pyy+6C@`% zfVA8=_?qMU?Z(Go=icZ()+-|2{p;X+j_>ymzTo(N!x+@J0A0@lWrFT>fig|Hzc)XZ zHvZN446OHu@h4*!6$|5g#x5!@po>?GK~p0kDmBK3LAR6{|1z#okpW#L2f9whxJJbW zbO)Dljfw}Tw`yFYqGAlXz^q0^!?;F8=iqY=@RWxG=o%E`LkFL8fX#MMkuY{qu>rSt zKvJN~UqJeFKzg}pl;i$Tp&LzgKU z;FcQywgZMPQ*`*Z9W->AVgNd^@s~i&S4$A~Dm3L9`>GV;F0G*lA2|7y8 z1-y&Y2f9Vm26X2QXfGgWIZY?%_$n6_&>Row7zNO30te9Y7SLMl?wGv{y*Vld-7NdM zKXm8pW$3=z?XyS2_=54r?w`iLnZFr-W&Usc!T7K759Uk8SB-xfzc#+e{MPuh@eAY2 z-N%hz9(=(8I;`^h4dd6U;G_w<>`0MVLW-KnX*iRt69Q)Y~)k zY0&_&L0uF>o;Ln%r+PzF3=Dainh&rv{}8A--Fz5y;iv>7DAn+{P6H)9&{5wdDmmRX zDg~fTIgpSCoqzxeP-w_QM_k+(sJD~!Yzk~J<8(#t)5C#f<(0r&EDBX~fn0j4Q z5{ysA$64PfR|5^LTfZoh>vHLl>0sdoC;HE^(V$ff#%Eq^bO8;RM;zuCfHdfRRANB4 z+{nc8ha61fPd@;`b<7|^4OB5_7LcF?nji;A&;w172Q-)F2DJ)wZ}cv3pW^@r==_9k zj~~4buzOHDJzjKsyy1sj;o9l(rrYBKob#dE;|rYg1$4;n5zvrp^BW&T{`Uao|Crto z74Qj7F~%oBqZu*1&itTJ3F`~sLLdOC5D)=}2lhfh1eC#13IP?62udMf0un(f1YE+p zzaM6h@4Yc9 z3Sc99b5tZIfL7E&kB$Q!`wzN!5tNZZcXEN&8-g+|WLgijmd`~6bYL#%*fvmxHURC* z>I9vr>jOS~Kn1kb1KdegEQE>qkoFEMmFTQ~nf3Wm|YJp1#FH8m9L=Em{8@fzE zc!6ay$OkObp&mF7Hs?hVXza2^MWp!%i+}Sw0Z>WO`k%km8k$eROUZmxK%M}t`T@~2 z@{A_LGsc(VK<6j&Xn}$rl%GUE3}}3S;|3ZZG9cf$Oi_S(=WH+N0?(7yH_EkoL2D_T z`K=EX$#=Q*h`=)x=-LDy6%XSxFXA0RIm!nqM}>g0gh)KLEG2`MQNUSB2Tc&1rEJgy z!CC6F1H>*+H3-L$^S(raLz@qAfJQ+osBMcK*>T!`WG)0@`XLVEoni6sTY{K5zVi`6Tl<<5R|; zjL#b1H$Gu}7j)*W@psUW3`iC8ZQ~Qhx0p|Y&iF7sZ+zeQtnm$F&^{KC?sErUa`dur z8Xr9PfZ6z9^TT@MW6US{w;eD(*nPUw2{eX=Dtj0v3%*2|qtodRLLPLlD*v_v%@6CD zPlAud5CM(uF(DLyjCWBHff~{2#L|2SRKClAu0D|9Z~X?@)C9f_9v*aH2F~(H;E)Fc zynKRipyd;U11+B*97Op9S})Lj3cPAY^?_&viQMGZID@1YdbMH*=t4*6t#sfX9TR`ZeTXuIfuI}eZh(diz{Z1kC-^mv zfx31W_b7gZh(Io>ixYS;8&s^g|1f0hcK-vqlad`2cJ3^oD=FPMKvz<_^BB5`bh`_H zuB3DqF?5p&doi7ffdLwFz4Z@ZL3f0s`86YI=<&B61l9aCDk6{|yv46^h(ClC6w;s$ zc8Dw}@Ij*~psOlDVQ>SY02~1!yr2jG%R>AMzSj@z!_Uwg`4Axh(u^%g!*1|{0y0j3 zU*j^r#$o;t=xv#&`9pZ2mR|x{4hj}gkbV4N7a;0DW~cENU1EZZfSnCGjR7PG+F1y` zU6U2!SXppnf@MLMWL^ZF?kpH4@B*}9x0}8B2n#5L!O0U8tQ_5-VC4Y^t3Wp>SVg+s z!O7DdlssXpu|V^mu=5fWy4kzqCB9$i4j1@-x!a$myPW6y#qN9&&_vVstKIG#-Swba zO9XTgBxqRQ_@MDU@PZUaneL;;$3R)U(@~=PyzwdHzo7FDAhRpopNv7b`hpfzIf1l- zdLS_>0-&21j~ctEh=8@Z@pK>Rj9}@$5!~s)(P{l+dh`GP-OQjSTQ$f*-Xh?r4yM1iHaTyBLGkv?&-L?R1m@O>u!8Bm#2KX=6~C2^zXq zF#gvKTEYdo0qLpEq^_DFB6x0!Wh!xTC3IeAM_j zIE)314|h6&?(35pa2W3X!>@*vHi(RvNIS6oyKK)qMv!`-)xy=9DjR0NEDR6w+Wv5$(v z!IJ`=&OF_RK&NCFpY9G(u`xbpd=~689~Beh^HB8?#y%=w^_?C9-Joy**#k|Upnf>G zKOUlD0`dpwJbf4AW8FW&PPPDDnF@6bD4;+tHt2K|=|0}=FJpWWe6?waii|Pn_K#Bn z#+Qw+8DH(r0pE3MVtmo~D(DhakYs0oL^r6TZ()3}`#jiW8L(yGKn7VN5)T%Yh>PuX zl!v-==eo${LWOd;{ZrjqZ9K<4Tjx8WojpOVBZZhBYcSpi_E{ zD?!JAN_6f~0iQ)$qXM#S1p@%J_5V7L_|7=X^IVV(A7Ygow^9;8DEp@5Uu6 zDxHu;`rRceA;w!EVSP?{57=AApiNRG-E+VP1$X+WRCJ%}+@br zw5yWtQ^t^iKx5Eu9T$}d=*G0}bH-;o=cs_zdv@oj6ezEO_}WJ$K-ovdp|eM22gqUP zlzSlde(s(F_Jwkcii>gyctcW*@kiw;;1KVOQIY6|Y$GuAQISxd0}ik59z)E0{a2m>jwj;_-H=%UWk~oMA2L2`eB9VaB?PpG47%|Jyc@d*>{(^d zf#IOtcc2*uWk*ma8(cOUx~Pa4=BS7m#;6Dw)~JB))e$jX19r4AC^3RA58eYF!Z+Rn zb{}X(L^oudUwI8AeSy@xGF}6AXE$VdyE14PEk`BB_@D6}aF`g^s00|-s5ls}f%qMA zy;hC#9!OFOQIRnIZM+9;gfVCb4d@o+7!{w+92FVRZUW^s;1p;K+EBL!VjyVgzmJNF z@XhDkcRb?OWppQ=XN6@A;%_yMZE)hl0Ml2T<14Yozy&M%2ko!Rkww1Sl(>$p9>&#IJ0jE-H+VcS1(>jdN5oj3LPbI^JiY3@?x> zI$OYgFm_SNF$RqYLK1QJ8gTws%u&%WEK$)gj8W0(&QU2*%ux|A41wkeXdpxKDyZaD z-UH4dpvD4pcZo6R$om#Z;rA0X@M!$c7<9ba7D%~sLvaguLzVF@&@Dd7kixRNM8&}P zVs{TjW(v4?G(KV611T_Dz$w17Mx_L_)ESg1I%8A{x*-`OK+y$!jD3jm7DxtyRH-G# z&~PeIDKLg^Ldj7HG0sr|9To%1{-AsoGTm#y7DG!r@DRL2r>{mgsL|k~Qeg}!LOWeSgE*iO z_!@9r`AUFthjI^iKOZQQ7(+`(S5Tu=M;TJZfg2N$blB+&>adq|x{7?i*zKZH0BV?g zzhDf?T0SZnpfu1~s?Zs#(&@|5>BBJNd=;Z*280UDZAXnY8AYWHRSHHX2M&KWd51_>N| z!2z*F6~qHA=mc+Oxd|%P!n(imuX(`%8Z|J1NV}+*fL+JXedyp@4*oSaI2xaW^ff*O zk=%z4zUJV*397F^fp`tH=8}P-`#Ara3mo98H%3K(`#Ar0&>A}(kmiH0IJjL@bhxj9 z*1m!kZi0?Q16}0T~6l98&{g$-#FV z+$AdD15Owiz`Hy_6^R1>niHTzsln}{BGc)}0&>a?0q*0SjvU>G_}6?8h>znw6x->@ z6Wx47uVtp3v`L^YtY~r2k5ww;LxzZgYTJo zT~tcK1767H|Njr_Y=W1!?#VI!X8gAMelO2d&@h_yPyS{p(EN;#N&#rp3%ozE^;>Bg zfB1oeCpbXeHPCQ-0C=N@2ADJelaQ?&4q&zin1rZ_=qyoDd11v2KHf|r;6=li|NkMg z3~Hd0OSZK-9QFV$v<1}`uQQtevz4Vc|6?gl;txLnvkYvS3dA@9mVp-6f|fnMILQRF zkRNX0R?vi!i;4!w-=H23V{aH^^FfwQmpKK--$0&q?)7D~zRvIZiQn}sXe&wgOIWCY z&XpD5@A(WGIPp;t=?zh-0386^%hC%9G!N)Ks~OPwt8TA9#<#nTx~o{aoqlv*;9qiC z;NT+x?hBw1dT{l6(D;(^ZT=;Pz(oY8VG{#t4j5ko6%t@UND}2f21?z>`Ij6P=za+* z9v*{=2kztDzxbED=iuKCnh6%*25tV70OyYX2cL3)^EdZP?jPN!__rN`lo8NO^Ada< zkN{Zkwv*gH4?g7pT`U0Z41@NGDuDHN{|03T{w3ErK>7Z6cZ^C7_cch)g;>&kn)?UD zTv#a)15yoIzxRlP`vUjR&JYz)-^T$oqyU;b0-eYW+Up8VIH2Q=J9AVFK-Zsw=BYbD zo4P|(K(~d0njR70{i@ucoDia70~*b6Q88$I)X~w=0jjN3U0hsTKvPrTHEJ4-55fEx zm6XP3ASK)%Rh5*Klt8=BzzP%^AA3_ zTMB>ct-t^OcSEk{02Rz}vC;9yXI`*r!E-aH+JWQdH$KqwITO0$CA#xvy2Ay!%SF1` zyZu@Cm)vCp@6Lb6eB1aIs6E{Hbk(X=t1iAYeg|s9G(HCLI&)NXx^q+#jBkO?59o|h z(YW}o`<8LMME5accNvJ9?s^4PkXms2)TX=C#Q0WsC}>W_r29DNwCV0xmG09Zt2#lK z7P?woeAx*)QNh;+JhCFdzXY`7%CJO5pfN>70AvvJTM*Cq6~sZtuRvB`d^{`^5Tq59^^MPUgU*KqwbuhUx=(c%@N^&Ru2D(gUvh$x8FcZ6 zNH;rp*j=LApT*EeMWiuBMFOPR&_zX}F-1iL#0G^fc<>ywl0t-k%|WJvFF-dfgC;XU z(=jUDCyYVETo%UHx<58P18He|1R{+?R4j}?bRPp1U)`rVLsTsI*PH+!GJfzS$bbm& znb#rRf4d7cx{q~x>hLc)$Y^|;`2c9G0K^liUHi-kWMF11Kgq0 z%b+_%CBisF1$1nk0^Fw&AeS6`z+!yL_!!g}nEjo;G9Y_9T_p~_VgcLd0Jd8Jq7GvB zIpag1)~`jUs|{#RklJz_T%)jxPs0b>SO^QIR@%sfVUY5goQUB6@Z-w z27nlHovt^e&vk$1U-OBn)A!E7cT70dcDg>0KF7c2K69t`zvB)^930ubX8c)hZSA!zfy2J3{w9t@y$Z6S~etm4Zop!uzkQ~V+K z)A)-&vOwl^3Sg6BAo(!(92S@dn!^H5kAYQ#W_JSMszLe@6J{X0_yuE(9`Fl<91{SY zj;3)djUQx4$SH_rusJhA_CZx20v#uy!3weuAp)5*i#a9$UgW~T-^2g^|NpQTD?x$g z{sB70^93}C=Kcdbi}nXJi^dL~L}LL@qH%yH(Rd8qWWX~&3gDR^74XcDMz_0+p_@*( zyMm#cLASe#p_@s!yN02gMYp?7^Kl15H=E`h6&^qR}1BaN#=`{Z0ODy~$XP}s(nKA{5hCruG!EOT0?|}qCX0k$EaghZS zrCM%rzweogyn$dH#wlbb%{z%cy}C6 zH(U1)&>T@1NB1jGH?ccTpfg5Ar#nsr+zN@4=!{V@>5h}>1YNZk2f8aFqBBOtp*v0m zw9pIG5$lXmap{iJ0PTy3QSs=G)9H*+@#&5;03D&z9cN=3{1F8yCb94HrfNBgEh$>J|*#W95$N190m!N(@j!FtAWONX8F^CUDC1}{w z1FEtBY96PL3P?Brw6>{x4S3KPq8N1kRsd9S2|}?1?C6;gl?vla-5wU*2O;VOx({~y z+JH2`d?Ns^2qTP7a-RS-(ZHibpmR1-jL&ypHx5yW0Z+Pk*ce|k4zTDH=mt%~fTpix zIz3p7FB_i(PsAh`gL>E*+$X@=A!B^TXN^I-CKZeWEQ~#Dj6ro6Xh1E118l58rw0$% zW*v~tQ0E$7Gd^#8*%%bsXN`SSKsPkxbOs1?dO&7FO^i>1_QyhP0Xf9N_$=6Y=V1n1 zHogX$dg%rYmci`R0nJx|ri?;VM2tgJTsl2ujISG?G`?nh8SDaw?iiI4h@qfiD40=a zyK_`*;Ep!|jW%@#D1iO%)9IlC_q&JjHPFFa+$Z1~L8gFPWF;yUodFu)^&%lEA)OvN z#@CEbg6#|dd(#7Ks|0uy%?BE<-N%hxEjmL%mA-&+s7@4B zgMfIns80yl2Pq&!NU2XGL1PE*A3*B`Xi=FMy4i%iNM!-3wGAlpKy^Q)5pWW!*7y=XB>wnGuWCR+2(4ToOD{lG$t4zW4SbkC z1ih+(glHJJo`F;{F~<- z+GlFQ-rPit{RBGw1VBwVH*gcq4cvrt12^H^z)d(ea1+iA+=O!jH{smCO*l7j z6VA;Bx+J6-X?+9R_Y2*ApkA}Y_lwfx4jr-EKVHc{1NG zbccazFOhCHP$i=QSq7og?WXY^v=+et)Y$=F1L3Cg{Q{_C-|c47U1kAh+ZcnUut4YS zm~I^9e_9V_Ec zpd+)4uXms82Hkga$k;~(v_L?o(_f?0T?cd&m@#Pd$Hw?>H|Weim+r$L)4{V^zMzRX z(47omJw7U++6T5IUd9-7Of9I01e>Yq65l{evgHr_-oZui-fCOhAXf2BlC^*9u zU?Hsm2~H76a0e>1Ti(oCcua1Qq+>eirCTB+!-s9ndNdc(7Vv30Ba`56~V272_Bcg-&qr zf>vXQfGp~C1ubF)Es+2%?odDrPSElRkBRzH`vB_TG{30;o$?CWgB2PU-t7!p8)VY$EYNM;{T_4~PPem2w>M}S*`nK7qC1$Q z`%@?ATvKOIXh(EAgA%Pvw=*bNdvrU4Cq25ILDQci-Ok{Y-|cK-d>b^Q4-W6+pjHNG zvoEBza|1M+1Zru$JopSWWDaRE)u_aPn?j)V`rP1@0XlE3`vXYt!Dj*>xsRP8;EB`- zQ1b?Sy%oq&U=^JqDxkL1GXe0poC{1fXwK2Y_)=$yN=f$z==o-yYru1H2cHRmjE0RD zgBwBMsT7dipu_nqx-Wnf9DD?}`(kH_N)4#f2x>cm21UTB;3}jo1#0+7fE0t8Ae^8B zBOsGZpk*wOmZAo@8)TfIZ4Adi;|h=& zG~;Wau@U3T-H=H?W6;I|P}>&N0yREq9A*J-4Ja7a(W3ZQd(>0ajuRot+J^F+Kox zAt>vB$}i9y0i?AW0vdGzwH`rH2$~KCg$6h10y|KU7Z|&!lo*4OAZTF_WZE1wodGH; zp*x5`1)q;`jYeGK@=9DvV21Qj8&U=72 zN(AW49Psil4P!_Mlo&&n99V!8)NA7$6%}JpgFZ*4pfg;f`?|3cDBXkB&Vi<+BRaiw zy1gunL1Uo;pj9%)pd}GbCg4<9VSKPN3si*)be{)pIO_&A_-jBJ2b4)fz?sCu7&NY@ z0dCf-bRRbcb-W<{1hv&cOWHsg1{5}+rGg%y@;Shw)59jZ`A7w*?G7rRLBns&KR8P2 zA-!VoAs758ZF_|(kFa*Eg2VMQ+E)dYW z52QT&g*Hb2nm8r&cy zkOMUMx4A(M&**hg;Q<|H2RidYAmGJkP=6!_JoE)x3=TTH4m=j;q5`VaBtoI<`@KPH z{XutP8oveiN4jNRcK_%udCAg!`QR&d&_&e(t_R->aQ_6InZRv)-T3suSKJ3*@-#oP zZ+>Wh@IAlrzvk!m-6B&pj(9L|i}Y$7^69->% zL&Z)^RM>`<|j5HV(u7&BDt6v#Yok-ZwHJs1wY{$&FwmRoQ0w}OUFKm~SuEa-efcxVN@@C1dFkBUI^5svPI z9e&IQUr2PYf%kfJxG{Ev=Bs%QzToJ99m0Tl0z-!%dmQY%Md*270-@l08x?|IfQ~P1 zKEh!Pnt~Nbo6v1?xR>Q{cLj^_ZO{o!#&3-e@Net*aM**P`&#oO#*6PRKjPok!2=4+ zTiw?kKtk^?KjMDX{6nS&bR3IFrvzw1qB8?@Esg+a|D6D6KiUdVB5OXvaTv60fCs#@ zP@vnmTO716j>Y(xDnCCzzwrmq(Dnt8kbv9%U8VcGsanATqCwqKcCwDX~tAVoH84UX` zzA!$f3esf!f%yQ$GIW!V9ejaq|Dl5~P~CXy;7b;e^&pRQ9|X@xV0A#Zj|%912mWo2 zjQraQS;G0ZS%UYXf=~2tWCF9hb5un5w>dI{IsDrkS-C&(Z*ycj_>2S0U6ka`!L3Hon*R7!(M-BGSh9jIVbe>OKWp#PRSy zKf`}jh7Sx3-JiG*9(>2seY)`(Xn%L(Lk5Qb4BQ91Pd7f~XJGgbTA&T)fYzxTe8B=b zdE|8CBQWowz<$u#Mck(jzGFG~kcIoB@$K#t-PgV!XKrL*DB(HyQkwa|!B^7E-(CwG zd@0py0=~85-~*44ox+S)7}H3)JicB`TEIJ#z+} zw0Mla^}5$U$_tM_y$(ORMYebHZ0`(U=?>Y>((S>~>9d`s`504Y07vsbftuU#khAbW z38eWAN4Jj(PxnE{G;)ZFKydesgO6FXZ-8j;Byvj(43w^_wj@0 zSd6O#4xW%P2Ayv$0J>cYtoYzdrtTM@Lz5uW#h@!IUUc6y&f)+W3SMi_{nI##r}6p2 zpNn0(52|YZRCv_*eZpR)CgmCx1>+yx2UQs(6dW4AORQY5$dt|OPqFe}WzbG$kc`3) z9aXRrZ9D((jo){N9zSWiSR^V9qyXF?Kd8Dk$KZqMnGf$jDIWz-#U51saW^=#@uAo1 z1$iKW#*a&<_3r_#qgVD(Q7~OvcJUW@btPy)mVj#HNrlD6CmKI4-SB>q@>xUBVgEiV z0-(^DP_xsN&7e9MWEIGq?t`ifg#}rS4>uUTF8~QNemwA%YZAy%km05Wgf1s5gI2qN z=7U{S1XOJebtZwY{1s4D?OWs7_>o7k>XF-NS&=12C%T!J*9f zg!1pkk7uqv$mu?&%59X-qmWXCd^YD;)thcmo9U(T3*-03 z?;5}Q>MVcX{k8jO^83=Iqn5E*7w z1_l8zoB2QYZ;);WkkrA~tldYM|2IEi0Vz{uU|?W5_?(&hM)%Q!ubEUC7!(+|Z+4%( z_`3070}BHKNL-bHfrH`TYZmTX2VXNm1sE6)zGmh=-1wA1!G+=A3nuPk7hiB6y!e9q z=)o6k+{Zx$0;rY&SI(g36$}41Z&>rn8P>dVhBvP`K+P-AZW^9|7gK(K7k+^T7+WuufL08HHW`S3 zPDSGh4fpB>t=y66zOff{&{25U3)bKN{~I3$O+y}+0IlH%9dP;r+;aKc9ik%Bc(4Jo zLJf2(nL_KO(tV))BJr`EB`Q2|y)G&cn*(0V1KH}M!UJilc!QfN%%Fl(pu-u`RN(+M zRh*&cML9zci*kk@7Uj&=;mr`(K1M*h~S|NsBTMaM(yA<+Iv&;lON1%E*=_(0(i0&e6Q z{|CDlbg7f^fi%Q<>n6YWw{>Wo@nGl<`NeYi9sjlti!&Y!&CeJwzvAE4;Q?YlVm$ba zpZgy3ZEn!AW07u?UvRY%Ao*t?c?a%ymtQqMVq|{H4Z2QO1k~zU)G70;Gv^nJd-H#R znpRNeINbOKbp9@Ei+PI*=m6gC9`M~W-7PAh1GYiKMWCx_Lc_Z&S&ZL;tC1G)g*6A? zgJu&XnxEGj9{?>F0IkUck51p_ZvpLv3G3aW@&$BWu8Rt2eoiHz+mYk{h5uW?D;RrS zRCNBAsHlL}rz>RYR$H&uz=dQ2M@jw=x9-4g|az1T2$CT>k}c;S>T&9 zZ8~~X_!$`(K*s2Rjp>D)$OKCJE+A2pZU=$?7n+Z#7+(S%0NxFn*ix`QT+GwO!{%hb zqv2qEy$Ey3DU@q~R^Rl34?-;lUF~4;zl`OD!J_~FL3`4hj|gq4njQ!3dVykSVO~mSz1BM3&E#juz<#h6?!W`he60RKa($I>DG8H z-K`Jqv~@FRpS%1Ndc3;`H>hbL)6LS=TLl`#)98hqk{ZzK1X}MW5+3kkHa~c#!3A_C z8hdw*ibU(TQf|;Hj&2+IZh_aPpvoCyaE&~R_PK7*jHtrpN8RVT87{v7OK@M%1})E$ zxct2PTsMov^`9u)e*cj5p4-6xK_sDJ{9;rmVFzuYJI!w-DFn8q*cq5`^K z#Q=0zW%CgMPi4>ryEnLxgHIIyeuMi&bB&4!BdD(BZvy9R(8j3C+94{SB`}~xbUNVk z6l9pX4}X6MT9DNJf%$9qJK^iymfHV}-*+E3W>kJ*e8BkK!MF0vuez@bA20^p;SL&a zJN5l0_o+^c?-#odAABjVef;~)?hnS_L1$Jfg9gHNj6Z;nlLT#C1MdnEFg^!bQji02 z4`_`#X!uj0w5j_(_#Rl$d5ap|U%L+)f7Ct-+61Qk5_&Ky_ixZj4u}6GDmE_~^Zx(u zKKlJK=t!CG*OiYMA3gX&UimP$i;9Z!anOm*pv(3=Ufjz254y}QJ{FQ7Lc8B&G5i;0 z5pZPyT}dm-AmGZ7!O6mK;J+w`fGb15e^DL*SBBWbXF|K*G`>+`W?;w?|1T;a;L6Z? zpoBGxDe|o5VvYb$hE84<5Gl$4B4z*hdopyI{s57-U;I58(t1P{0zee62$+)n02X9@ z1Ey48fGOQ4{+XG_fByeJ&KlwG$-v0K z$gmJ3xmd*Cli@fkhrcHS$mPdbdBCy^498g|psXyGi0lIl#~Wn)JsCi&j3E4O-UF_l z44po#KeAXN4nAP$=4Eh$@G~;bcrd)U|L_0*2`3MO!ieJqXtZKNEQr(iMg}b$x_vq5 z9S%?a{Qpmy@4J0DIy*oC0P!3X#B#R&CtoBa#)u^fPtZv;q}X~EXEfKi3|)c4s$Rt1iW~Y&cN_uZ{FYk z-5*}GW->5jF?Jff$YcYZslXH0a-gL6_M;b6;m%-iaAbJloyfot`C=MKVj_sh1`%O-fBy%(sL23Hg>x`4 zv>Yg5eZdQIfKA@t|1WlPGBC6rC}ljH#r|Rz2Lr>I7xCbGhY!Da!O6hzLISLN6G->r zERl=`El-9QQ@B7be$l|nz!2GTfWHN_=-udcN9^!>t;vn^Z%uHUIeg#ymgJ8fuZ|@@qbIZ66vrPD1OO^=yZJ$ z81Ujg$mqz!-Kj5Lgh8|$HPk+5C}n*S8q2@{)8+c0+xJ6CCoiaN9~mDPeG(KKJnRe% zVJ|vj85sVTK6v303yK?4HU@^5CI9~a2c4~{suASLz|j0gqnTI0&69yKiwjoR@VBrs zGcW{)g&QB}t-WD%w#wR<&dAeP1bl2YLbp6x#-90t0wA=NG zX=YxkXQ%6nZr2B&;e_Qu}mWbSr-!R`8n`*>$DOQ$zSXE0BxWw+}M z)erXn`E3udF*1}W+a|CvF_g&I7Jw*G+W>K0%im@-6YyYr!hJNAiX=h+y$YPIxI~i;(+`8`AJKe5NI%9uyy1w~-7*sfw zK#gN+uD!unqXO3Ii0ov9Ue_nxAdN4wR3a>0|J2ADpX{x@0aXf;fd&pJXln0thkjWI z3e;|14mVGR<`YcaraU0V!+*zFLBS3hC0Pto&Wnf@f3=-=EtF^vW>euc1VHfDw%WmH<%7>KCSsyAjus&C+1J(&iV-C#^ZbQt5 z7{Z2X$ZKwhBv{9H*Eb9d4Gbj$pfRC;5L>_&es_HV>MoWfV%q0teXi82`?&GRgYN}Y z|1+>KG(TrwtPhfr0V+MP;yKzh76j1v?!=g2kGDFqZK*Ki?0rs1qy`9~W(W z;3T*)2)ZvFbW4wqiU9Ws(6CV{C+NJD?+*_NFa&>p*bSQhZ2W64Tz+-9`;hUahKKT(UmP|*V0;Nw*>$^egmrt^FrVPx z?kLh5D8YPzf4d`F_6H5-Pp?J0y?88rd5XBYoj8~eTDtNS@iZUOu)bFM-1tCT?BVW1 zuYZQUsAC0{lqCu&3ndsB81|V2c`|edu)JomzEC1ye4zW(2mXzGtp`d!7#)Z^yn!(e zWM^|N2SX|QF;)vurh4(@_y7MdF7kqk`BE061F?r+RHlPDTv-e+ZtyZNM81Bxfe~CY zH`rQ&%8wEj5I?NDl%w@q32XB|#?qu0-&w%UP;32Gs+3_9dv4^u*U+6M1 zFr3Na$XEcXQXE+r7(lhh4&NvShBQl71_lR)(%6MI3=Ry9J3yQOR|bYspPir`C~1}* z5+G^2ZdZ<-AUW-W0f8^-{{8juWx^4+d)x*3d5Hd?SUFdX2Y zaS+w17U7F>9#DM-3Qth^Y-)>L zjt!78$N&HT|NTZJ=yGKbuwe5WkzUs?{NV>cyR2Nl{1;UaaAoLr{bB6-rPKA#e^D6$ zR|Z26LjuC+b$t`?UsMFF=tHmXA7j@y#;$*i51u>>X}yJo@ArG=uzMe9kjVOc2}|p_ zQneRTKnt5sSf4Lt-|7F%VfSmk)^nv?yn^lw3_`am zWH|g{V(y>+-5xB>94eh2EH9peTma%Rb$YNIHa=jr|7kr_mw>6>8DMH|37Bdv08>kIz|`7|zyJTw>2I9_+9%}7(%CxY@Bjb3 zAjX2f|NkEc+Y4%GcRT#a3g~Q|0G3?=a)|?|>EX)Ke1zw?>k3f@28ZLWYe02Kr|Xvg zq8gwG`_SvUqSN(9FW8VQ25|g>dK$g1KLY-PyBe(rN_m_AF_v&-F~0y^;2Rlt^6<;@ zl)wK$oe~2`FT;2zBnNSnYJv-*MoVzck=X&sIgS#gg3XmBd}Z9tJ3&WmFz`=3aMo7iqL-jGT)|=cYCvj11R=F&&YZ~*c;d{E@*i};A?W%$ zfzBKif!-Vy0qqCDVd3Cm6hqfP#zzA>Q(ycq{n73E2U-MxLf!R4%3@IK3!M6HM0kP& z23GJx>2T199B6HfNOuir+M)X*^D*mxWgON&_?xDH1{Z!R@HbrojX{7fMk*HO-=zww zqZ#>|`dAnkUOoohkF-k_-1;fz{JaD--WeBvxcj*Av6cJ`3=E}w2n`QFyD%YY8Tgw) z%jUly2UYR>t#d)`g<}vlC<*cJdd^hL+s)SelBKtdrIWq4o`rwcbLL{f&-`_K%`Z86 z%Q({bukrWRb9_I>&cMJ>lFGm988d$~=!lCn{(QeLy=7mz|EKZi#|bpQG)UvmcT-5? z&(AaHEi-8T3F2Q)-1x*ZfkTw@e_7zn;IhUf}f${#_3-L-!%J(CudF4Y}{k@c#iMqDq9j*gDuf zn~yOzA7_LJmA>u1*bGV|>p<6CzGV8mwD}S9f0e0VZ7RJf_njFgfQX#?&I}dzof&%W zJA=|OPh9-r2_VCu=>^R0a%1dpXM~FMdNP3IA!1!_Odak_P?-t6CVag%{9s!HA;}M# zB0=ZZK%7+~(tW-85wrHGF1P<3?*IM#K?huZ25XT64ewn%_>!sl5p(l9mge^?e?Kq% z^Iv5u!vklA2?7tC86+M!GiW?;X0UmHpI?^nnLod-;4^a1CYAA-w%TBL@E(&e$UeU zj-{KelfC&R3q-K=b?eCz{^s|L&F>gNUTJ>GSPD8>1QegInL+K*W6clvLCb|f_s4W! zY<^gO@D+PWTJI7SP)P(%-)x}N4$5a?piCKOkj7uno(A$u8ptncAit!6ybQ{*0cjvF zr-8hj2J&AT$bV@d|D}Qa*Sihmzux^I(yMfF>&cS%?u!Rsv9?|+QS6-!vJojfp&som zQ|PT%@G5=U{7}Bc0CXD-Qwe{!Sf_aNahB#|ED#@^Xnx2HN$qa#o~7TR&hPbvrCq2% z_kZwB4cZs9PX%@#>IUoL>=Nq`2kSccf~kZTWO8pAOK&}kN9pItmoNYQ{|_yC!4#;~ z&c6-Rh`-)lqrw8Ziv@HfZsq|-Mn*ZMd-HLD=I0-@&qItT^MSe?N=<+UKBx?-cUMT`uXhK< zhr0ua6#yaT1UX#S~C{O0>X z&{d%&Nxe1v58(1p_kTYKD*8+KI@sNtUot{?rJueZ1dT|SaCEYRVg{4~fBgUdzeEA* zbV&SmvUj?(G#}?^e#!CuAV|LSE!0qO@PbAyLEV7x?pmI1w&oxIN_e~dSeVZn^H{uK ze*6D_w;M;d9}k!x9~b-b!yDAtIRnxUy3z-H)5kH_{|x_)kGp;WHF93$sxdNjGIz)F zbUSnO77G}&f`$^q0y;}Sbh`d{(efV@MglK3gVsE`ax@yu9BKh6LDm1K7N{^)gQ>Sb~7mTBx|Y3%l3>2!V5da^{M``U}2%nS@089RLc zw;revsrPuz+~xbf`*-v2f2Ai|PL}AsRyghon)P6KEe z{+IrE0Xk0rG%e=(1$qK_w<|}Z1-LC_(QI3A#)E;OL_Y&WzwnS{WN1FZ(t4moy4w^a z(tR$A5j;2y8FT6`{Qx$JquZCK`@)Nv%nS_Ot~{0%JS9R9%e$|4pLnqdA`G&;GlJ(u zF=*SG?;DWDYu%n4FPxb{V?XCuz#TbeqXUOult9?*FTS!cFuZ=dff3Yd19w)qUUaiC zFub_S!oUFShjhDwEVn*b%3^#V_Hgq-*5(7OT>@5ur4lWdO5St@Fj@sNmhv>nGnB1xh5l9VEIrT2Gb;bTbBmj&y+!;9=>hb^CJs59NtH#K92S{RY$_D=|WC zyec+>8n4ogbr7dYG}b|!%HLQAc4`S*d>klTUNkZ>Fmx6OfZDBPV5Z26?-2|Ppj7=L z6|~L7L8bLT317D_hb2b|Pqzb0>w(g*#s?f?4}-LacE16|a41JuH)D4p3-h7YZxy`V zo*dmGV%EI+8kHUM2D*K4&xIqCcOZSab`&TFW~uKAn?CHJ0W(fQ*Y9Zjt5FZx}GXiv18Anjy{}L6E7YqJDTmwmX3qhIP*6@}yLy3G! zH!o=H29)a>jxaDVSUYkQv06K_l(A;+RCW ztpESPQZJq`f$~%9fl?OZ+pnF%vNW<7UkHYSM#v*0TfdbEg+bNrfvFQRz8wq|TLBh( z&C-3(_*>YE)y@nIk#XVwMIAr^(S11jaEAFyXNDIS85tNBgPalB{NsNqs6fg9`6S>) zCRlsxfl~GtpqPIBbOYnzg&>8^KmM2S1-!TnN}#+Tf&Y;k7!QYq@1FshCHR)bkgH`WRUXWDtdx_?EjHR#RK?7x=C=L$X?cnCg@DkL(MB;;*6`;{< zXO_-vp3uO6h{)K;=tC?FXZ~LRm8yY(-L4#Rj_+c;OGqNTGkaKScKO zOa-ZG{Z=Z`eY~Bq`7n!htVrp;?$96YR>lY7qT^2PJYoMu zGa#M(>)oM0x=*xoy}laS{U(EfgMlFnH2m~mGzTnSY6M9t%|F6RRkPSLj$HEqNxzs9 z3LXtTuhs}8ts)?;JRkzZ%3^-uh0w}_)#4Z=-5MZ`3LpZ+%3^uJgXCS&|D^)m z=fIT|2Xt`a+G`#dKLBn_V7D*$p6yzR?r@&&Pu=kXouPkPPgdw=9};Ok%)xxPJ653i z*Z&gR<`*JfmJxqyS*#`MSet+SFJ0^g^l7 zjw$b)8M=LWIvI@*IJ`U!x^O-92*YvL6A#}zGk`0PUf(0e2RmKQbh}D)x?TXg;Yzow zOsDIOZdZj)*E`Lr4;Y$LpD=(N+?o2IGxrJ1K}ULBk3byM?aJ}r;DxsgBSR#}D~!io ze}F23ZdZ;@*Eiju#@~k*Pk;UY-|fKB>H4SJ_s~>@6WPE+=#iRg8 zY6}eh1M-Uphp{iui@y*4|DOO#o(?R{57J5myIpyXJAhUtF&H0kc%Az?JBzW~mFItf z1eg>7lMru!nP8vTae@jV1yHb8s4#$9fE@ozdBFAQ1W>62!M(130y03U@J0GxP(>@# z?fM549mz7?*$V$37$0ze#2;vhd|3FOPS-!i2Lb{Dz;Ph*zf=H{OJ7{%09)4S`UBLE zcl`mn#3xH2qeI)1;l;Vv|Nk4`?sgUE_5gP!xfmH3EFwAhTfl9Y0FKs6r5u(L{Joz* zr8Y-*DNpOk3fAUhJj|auWB+v5inN@pRQSd&P$IoB2V5~c0hO!WC!i%o=#%afuerNj zIldj_D3R&*kO1{ocY-SSZ~QGA85kHk`Fh!~e`9AXv2Cu9VBl|=36-D7z`*do zT;zX&MA(b=*C7A%G}nu;l!i6iF_Z*?^!+z`(e)KH;nB(V+M(M+!ZKc>RJrwJNmT2% zlCb~fA|N$^FVewE0>WN6K@52<+Iq6Yy!Bg&@i%ssEQVDo10u*`^Uj6^y9V*c6%hPPdP|MQ&^EF#AISLv%`X^B6hXI|oAkPI1pF_Scyam*$oW}}0sqS+!e6}SW?*IA&d`}6;Qcd5#Mv;U*ZK=}VskxthS|4Vr~TwlCc z%?&DSLCd;)e>DI6&)<{7%)nsn&%)oE4C?vCax_|l+W-8m-$8|JwE#1J>s!!JMzsjI zeE&Q$LKnE0mvn-b3Z#~QaT37P*|9{H@0sa>|F58a`lKJw`CAu&T8`j=na0S#0CO{zfGKBWV6b%O;cw#ub)HHUdR;Go;vz7h*Y!Za z3t!M8&(I^yM+Fn^5v zywuWl4uAg=P)pu*0e?Seq|Eqar|$<#-xd5Vy`aJ&Sf<;Fr`w?U086LqgKpO~ouzj` zRo92!+6_yWE?wGPdZ)YgLF>0Vm7xFTy{;PqUaW$(a!ZxEgJt}hkF&IXtAEt(`=Q(Q zjbrlxfll8Kovv@JeOHw3daeDxRHoN;&i~RE|4UW=mnsB6%mAlH5pa3O6a3;o`0y5k z?$9sYzE7OGU2ilW6zL58(&_sI551`D~%?_HGmj}=0 z6lHX~D;#{m)LbvaP|CA{u_OYNn@WRTv#ek&5q**J`TzgU2!R(dpa1{w_Wjf8A@bV& zf4NNXiyn4JyqCnjRB39(iHM%)pRwL>sh{?MT22X-)=)7mq(d9B}&+*a6M8 zDh$D(b4Ofx_+4F90$wEi`2Qbd6{s%x!3ye1tOsXPfq)kYtPBh<4tYY$h&L9Xt7sdo znHd-w_*=vo85qLCU$lPu|KIq(Wd%oxTljy`0`PR)i-J#}EX7e`+-ME%q-!@?gFEfY z5TC(f094lmzc}y>RL;qOMsp8>(gdhM^ro}+gJlH|f7=!Y1_p4{m5TJbzWHA&6VU5= zC*Z{aP*w_k08Wf|I$ghXhW@b*eZk)h8leRz#vh=>cmkRjWuS@iM7^K2>zR7bZr>~2 zt~U-oWNAL|f%zb~5-VYAsN`TM)%(WaP^t-9ob`@jw2~;5YPnq^)D_8S6~S1_*L;wv`2bVP z?b0XR$6m97hnHFpl&}~dc&+`7ovDQN8xu!~RJW_ZHwH!!hp~kB8v|IFsf5}1n_Ks> z*UZKT9AL$4a9B8~1=|8j#4k>L03`?s<8R%e9J~Mj|1ZB^iFLB1Wr0GeQlk~9P%V*a zv{GYWXebftW>h|GeY}Y4o1+3Fe=BGP^_vq*T8WxvAq#)YJO%~^%TgKs)~O5(41wT) z;(4)-8PtB@dD#e(EaWMb0~rCyFRYe@GNpXh$BQz$9YGmq1!GAZ#KKam<|+Z^A`{Ch zkuv>mCzx`{%x)*0sl)C{+G&tj0g2BKuISE+F-cWd_>{3JVgF~sR~F5q#YCV zV$n}f+EPFYf!LQ{A#1?GKwYwrFF=Dg$JsKjdoY07e}`BYniE+Vx(_xdaxffsWGT4r z!El@rBn#@#hIN1Jbz?cs=5gJFp;>{UIe~>Cpxc$B`2b763q9~!HmDiBjx5I+L8<~? zRD#4onxP7N9a#ciEPM@Ktsr$E^4|f_*hOgf8)UNsUO2NdFnn|6V2mu`%Hj!o5yZvF z5E%(IJj*771JsW2cmx_-l<0JQV*J0e_CPmii1-hvFHy?zzf7XnbxXhtE^sTR)Ah`Y zd+$Kq0D(@|6E7}mJY~Iyl53nKk&u zo=>2l6zRUv8T+KO_RmYueFva1$ZAFg2FNPCs&}BGptC}uyHupxjib}`M%e#SiSAgQ z;1^FJsiFHqXXpdaX%?<`y3cp|Ua_p>DRam^DAFA#U>zdC(jCiFrvc)Y-mwlb;OH(D zsh0$C{RFyQI9MD&RYd5GZjnQsp$}ejI(GVAvG(IBIuH~V9{eI4RLLC?=)MneU3V!5 zv}tzSbq}cj@Ineyv>e802mS9Z<>-!m((QTy+}-%|zx2$DAD{pKk9@HPG;Z&EqSHg* z#X>OiNT-JgbXwmFJTmG68yOXXjf`?aM@CCEn`;j+lq$F0E|LFVCh_9)tN;HaTMv{7 zS=R31pL&3Q+kt?v7dKvl3hl#LEIWj_T^U|XVP|A`Vg43cz{`RfgD)n68W750+c`k3 z`%Vv;7w*gq3@`Lt7@+H`Lc8C9x)lu2;bk-M@Uj8!;bl>9{lWj@?3@4pjZZpudMJQa z(Ll#xv;IRe4yfq|8ii^;A`p8xOCaL`Xe|52eNdYPl<`2)!jOu%`$K2xlNSwd{{R2) zAOUi-b*V^6M)SY_{C&$nAzmwBUCzSaI}5~i=ji77(CG_mG=sXS%{3ob7)lI4)f~r* zhv4|*$zTRIJvh4EIsTV?V0qyJYTxjJlG$%iXn{t$L6&rvKIklc@_I5fj$f#Qni!=b zrDkDZ_jA0M1ThXhy1PrCyto2t&_f1^Prm;D|G$UC;TQLvAcZw(4koO-lqVdt=>b%i zblVx%onUC!nE#51qbWI$eLX9;mbEc4J{a)am-- zf9ae5h5;{rf=eKt)&r%I-L5~neZP2s4rm4`?ezW9?fRnr`fH}mjG&gA>yzd~pmtpI zd&bh$@o`;;qfZ`w;RH2PmE0vf+B6#x(63xI?`Zgh}|J=|Q$!muOY zx(5Tlt0N0^2p8PKW(f`i^&P=o_HI{>P_UT--MN2W$iDgiKP>$Jh4{GcyRqHA0-@cn z8-IdY@TIIfL5na0U;KXk|9@;`^vOd!3}G)Of_g9oEUn*4xDX>#FIXHQfe7js`f@Z@ zuz&)vo{fK>BS-AvZV&-YtDu6013Z`uS}W5~&%#jR(aqm_vc#!3kg_**B(F$WgLuopIZpyAf&*W93) z1olqGV~#8g@n9=J-Tj6-7KRegYGqN7vSu}gV{RWT8l~Cqq~ka~x=lcL!(z?rS#dW3}wv#}onQXeZ2XBef9~9ZkDMZLO>JF91@_BW=_!LC1`$z z{kWR|XmYRln1y@ezaMU%45jNqvnhwW|A%(J$#&(iUM{#BksQ`$T=@2fo>R81u;Rj2*_-3MF~>w z0^ShR$dJ(SWO(6v8&m~?2Eh*f|NlP{QZ(@VFJtLu`)}~V4m_mZa-hVh z+l`~af}xbJo2{Fn+kt1o#TP3WOJu-`ESVV?Kx6SG?A>lG{~2Dhb-VF2bNq*uEJC1y z3w43{As&WqSAqWqFOooZ9?sIqumHJb=Pj69RJ=h(rv72*273`4@x3x_-L*WOrB|#! zm-u(Hb-F(IZyo?%c^4Vka-hV#JDj82pQW3J> z1Jvs6bv+W$>v|)g*Z290U!c*}TAt=(EU#A)!2^IV z+Cb|+!C~jh)6MYT;DstE;J_t2%xG~?FdRcGPC)@t3Yuj8Z}1`vWCkQ{bYBFGfN*p; ziF7h`IB|41$#giWw4N+s?`G`wWO*%Y$(j-3$xte~kio-~p_`Y*!;|5dlL%v{mq4cz zPxm2Ed#L+=Sa|o(hI$dEQqFGn<^=)F3=Dr8>SY*8xVy_GUVskm?JN*zs8?Yq;q5M0 z=sy4ABxqcyKqNj6;)doo3eBls7G~p~(-qWH z>~;MR(Chjj05lx>!tme!|Dc)RZr30DuC8BBLd=59ILUT<@Js;h@#I~>SRxSkq7*ds z+H#9*{S zWYPZJDG6%hw*Id(4t(*!6V%J%2@eiG}p#KttmDO~8wffByeJc{qzFV*w~b{JDmlAxeM43KL(R7u>v{3aGR63DJ4M3#1+5 z+Qv7aw|Nj9 zsFBCh3wBsgz>5rS1_p>|XY7|3hXfcHASzq`mlSmSax_0=dR$|_IppvCS{!egDK6pN)Po_arDf zn|HE+7W0&{f$P`9-Hi+^3=9`vK;j}0)D#Hs{@Dns*6PcIx?OpWImj>`caQ*GEn;-w zb#SopZRT&5^Fd~may0$}X)fci-VUP6SvD}fHVk{A9L@mB(4fY=6ett-_JdTvIK%~N zmHgSv*a=o0@M5 zjkP@g|NpP&pMD_rFuW+~b`|je4FJo72(jiDoF#(IwIaMF{9UdBHpwL%HpP%V2p|K% zmVlPM`|<>bb(e~~n4}0AHZ0L;{Z?Yz{Ew-IwfUb)opHA-M*!5{pmYWv{0|6tG0O^^ z+`4@QK*Q}}pv4HTJe`a$LHlYzt;W#&ZajbynUSpH<|fl`w$cJ~g~51q9E?qcUo$tK{BM1(*tk3POZQ>^^~ZWeIIJ&phJKMg`TeG4 z><7>u1MU+CA2Kzc+L&%n@qKmOZcj#7bc zR{_v2)^6W7ogBsoUZ-}KehCYH@%%5S|JQP$#G%`j0~#Yr3=9n44l_csfqu8Iz_-Ip zB?7G{OISfOgp4~F7#JE}t0MTI6!TgXq=@PJz3xzf)=MRCcbyFAupX8b zjJ=K=pu1ify8~HXry+z(c)Q&MdOcV={RFxhUi)`^~jqIR2M%bi`Sdat8%=pL?+uw5E&$#Bu}8PPoY&e8Ikg zu|(1`&ZLB++s&ZC!k~obzn?+3pTRLkga2+O8yG>ug@;%ept%Z{rS)VzX!OIl*YUscrA~L1?qgY8k>5Wy95U$s(D2K$j<3s?r{N>xfrqRO z2ich}b_m1mKGa?MNBe_AXF1e*c~h>Gk{H9m>Ic0_@37-#-Xn8o+(Y zfAAFxi$T{78_P28uHz<*2OhApurnR*F8$NN2C==<_0Q|0$X-X-jn(q?ptY;993aa} zd6-Xh`u^y?2y%hDO6!4o&hEq9$4V5s-Bmn5p?p|{oqx?|P%twdd;pMnQBXaEUX)CpjVQ!B8gJm4_@(S5G7+yE5zr5xSiDy^65*}9K$A1<*8&SJ>o z3hs6KAJ*xv@?ya!28QSf4F?UnKXl(}_-R?k)8#4v3xE^du75f>Kmp)y(CPc<_4e-4 zAH9x@+8>c(fCriYu!h1)&`cBlP%uJ-0zdzn&nzqk2j8)DU9hn%Lw3ob4n~kOz~OQb zcer%BLQg2=04?L;>hxmi^x^^ajk|1E7#KRc96+R(NQak1r>&vTaHHV=Hc&o#A!5wH(7X)9 zWQc@zox{36{x^H^+lYaoJCvhYjUlp|sgteyShErXc#j%5@*3Zyu)wbS19fYH!OaY| z?mCukiQpHBNem1f;66q-TO_3O&<*W2bh`=sH|TZ)4bgyTj{gNL{|z9Wjer+_Knor~ zy>@UfqF>D03u^v@ z-PY~O6Wqy*{y5>AIMj;@O>Crdv%w45w4e$CzR zGqr@L;iqc}y8}pJ>HDzm4<20t4ZjRZepp@Z_4v>4dP4hS7Ymp* z<7quvs?qJnVSF3f+(l_VO6Y+r$>tOPLFOIqZVO;xU~uRJQ_Vk^_*>3`w)o%fj5Fzo zljst3>BrL%rrUCfzhxdH14BpX_g*&4|{u{hFBnEOJPj8(_>wywYxDUhsmwtF*APQOn!_&p#(CNn0;iubjlD`Gi zlI-yPjjZtZ3wBWkhL;yW6Z(EC|2yLpI^uLX<77JHG&ijs zT%yzbf}=zc+y@kDe!MHEj7$A34Gm+!y{RpkH6r=Ue0ZX*Ak zIJ()pp?1?dOI-g&-7IkhG*b!664LCTbj06s8gGsL8tV@BjaX5-tqlk}eGTk}eFTk}eF(C0!WSNV+hbmvmvcA?d=<<)~}pRw~}j z*!+N_`2+)ht0N-=!!bt*_LrdT)y9`>{7Oy0lH7;*TU8-)9Nms+J^4b8AP{)bs{x8j z38MptEdw=5Z`fq<_iq6032XtaiMH`9aklX(F}4XQQMSq8Z@mtxXdQVPEHX-Y96B9& zKr5aPfX<>}0vBh;9W_9Q^SlHZaNJRYgMoqJC1^=lSa%^$7n_Z7sc1tTqfse;uN%{G zM-9;3zMYOduPtoMz!D~`*O&6LF)(dnqMf$=czfHh)eU?4SMP1HvN78JK7_oA1Bf#D@+iE#6ah!Pd;gC*k4FW5_- zX&>ZoZD(L$2<|@jLXnGs;dN#Axfk!)85mv{WHEN1d-3)C|NpO3n}6ijTb1ZHzep|F z0y23$h*$-&hqctJ``n8{kY3wnKN$g#Nk;Gf|9`FDeeT75kg!_wi-Hm;&k|1K^woi!(>2Lucvj!-Z}V! z#jzvyUiWXMgC$y^qr=&h4wkSTbG@VcTC&Sc2FlTX&C`A8;tMEGq5Ef-pKim?iW1g_ zpAn_pAZ@H$7*!ZcnYtb~{7fui?>gM@)3KCk17pjRQkIqjC9=m{Z0{H}{ER5!Z20L| z!m^>_HFH)(M2Cy*-R9#=-EIonZYJ8tJ6*4QJH%7!)$Pa8>HDHH_D1W0I@{hhP>mCq zrOe&jGb;G%|HK@NP`Z|@_pf8?Ro_?oe5T6bN)38s4@aIklaK9 z!h2osK-!D}FKl@j7`pvrdh0|$b8gHl7)v}3zGV7#kg?RE8?>|tWUpoHl{%wx9f|V%deT6`TsZ6Suk|Q{^4(V30j&KXTskHKDY^N zYD0wxLn&AHi5I^?E1F$jfL40=8FYu4G*)oD{L8>l8s8avhd=y48o#jXgVsy@ExSO) z;&#U7gG~R+I68fA^!h#kt(Scf@M2vMD60#ACe>9z9t1arK}q^Wz>9d$XY zovwGR-Aqb%zb4UuN*)HWvefWt>Qj zZ#QTx1~j+l++BMG5~;2K>&%d2v=p2|OXN^uRHWPY1w@gv_5GS_kf_|i*zNlT={UA- z-w(!TU;JMW>Yjl%jzOj`iO=?(r7tMT`IAAXhv3io>TJ-Q{{_^lh2(tDau;H9emO`l zJm*`yg690EAYt4&|0hTql=E+ao6q2!&%zAN`9C3JmByD2zF=`m>x_NSeYzv|QK#<{ zr9&kq;J9K_It0r54|HF1gYy2N67FNJ545{ab^1PeE!6EMbMb}Jp%Ttxt`8KtPj!Yq z=?c?r_ysBienph>fDJ&D0>2=oz%S%dK;f7R?*oH|U!YRp7jh}U`>^>S6KI`xn1Xhg ziT1^BZZbTbp%+S{I%Ds&UaAZ3juYwjz0(bDdv?2XSi7^73O3a9FqAMmzh-Ve{l7C# z8#iH zL8t4J!0r<-yg0zc1FUR_hL#P%-M$w;6XK{wNXhHmrbfB#EZovm-y9PBQAVSJmY;^GV|X#Njtaq$FN zT-?A?Ts-LYy#XyQKwCtbk6#l;=W;^IYT?2`b{u7BSL z0WW5P&N(~+EiRrwi;EZG|4W}hip_u*|JXoozXLHHTo_?1E^dHS`H8fitcV7uAy9!4 z*j#&op|?(?&ZB!8sQ8Blwh$<=yN{PJJA$XuIyqiTgG*#kSYwHF{^pca3}r8QU81+--+sLNZo;b%IiI(IK+ z?F?4wKJ>qsqqo?GH5PnS^tsN`KQ9Cy{{P={pi~gll6mm|KkMRu|Nn!uGj}_yfKF@j zHt22xjrX-4==6QV?{W;Z3<$i(kg?laARIJL=PUqTsMG2Cq}N%Of1gCB?~Cqpovt5V z%mdwEcdq-#i=~f23&;O-e|XUi5(@p(eWJSwVkp1Mq3+Nx|BE=X82=Zs{5Sev`Xe|z z43x&71ia{VWnk!z{nC6yr#tjR_owdKH{IvEon;QbU|qpjqSaij!ceNxUCq%@53YpI zzW^O3&|9qA>&_GKzu4f#p*Nrj(_U|bE;gI=61MJ-Htwam-Oe)IAHgP+DkAH(0-a`7 zYyi{y@HI$pcd$Wx7n6-{DQB~{jDu6BSQnE`W(kjtX9}UAH&hCg6WL%YXA1fuK=GMAAChU$b_(iFB|ZbJJl2&0HSt4wL~m zD_1a`g_oR-HWA9{{KJR{U1E;56@{kKy%pL z@hZ)~|Nk%7=r-baxd94YP|$Xk8~ita@%bJ!dzDDGekVwT=w&{o&5?f{?OYJpC%?f{Q~PVpBt77Pski&?r$ z|AdFVIBUVc(A@@Ftk!%)Vg*wvZ}SPJPB8zNvj`JtALY~7!_AfqrNS@N5SGuCWMD8l z06GN_Y-=}T>w!`w9IG_GNWfx{J>Z2IXbBp~*?e z<9GT6+S2&n;Dy4*|Npz0n~(4?T68lrR&aDPBkSU}{#U{Z(#gbV0iJFYfQ&za#^*uD z{eV`1`Tps4lK_pzyUBFAg7%{`AMSMhVSS^-DZIN@fPWivSip-<|G?$Cl!cp2iF$LL zgjT6yx9^{@Ec+KXz%nH)|JlLa8)xg-A0-^!zJFdHYv%tS4;rI)ljwH+(CH=<7k%;& z)cS5;o?b^rThJQsa-MEi4*u;d9?Gr)kn;?{@zVSz2DE*n*LTSa)oY-otumlZtDt4) zJYYw1be4VrEt+tB(CPc6^-`&Fuj`Uyt_K(cj1L@l-2)og2bDPiFC4*x<`STFU3RVC zN^XMI<%PcKbUoAS`@h$9NoVMbPS*>dK91{^UeMW`H+n$}Gw*;FWcIqA3Fviw5%41P z#{d7_A3#odboKxLZpa!*a19DxdicLo=0)RG(84tZ&{9Lljumja0-a;&fuq<~mRyaQruT;UW)P-|Nfs zA_Z|Q&kIl*#?6FmIU{6IcSAyWH9w=2ix z6A%TlpcBL&fL1C7ft>NP!B!*KlYxQ171XscKH#uZA=s0lozeJqXY3!)m}={RQhl&l zpgl9ZD#4x%)+b8D0$O#j1rJQ0Z4!mEYR)FVkuF|dyEz2Fvf0oj$;grXkl>} ze41=GL#OK<=)yshykJIS^%tc`Wa+JFX;S(2fePJJ6)fE7B~0$e#&Bs=yZJpKGNY0 zs6P!!T+*OvN04zUFSdf}kKFZw&ASZ$bF(bi89aIRoLYMMp{m&>y_%$#L)2pc; z7*nEH- zgo5PsIOxgFVE1;rax4ZVk=Vmoj9E-s3@<7`A##KV#08y4n+fHD6=yMIF@d}i0uh9z zTabQhR?wMX{H?$FK&y#4UTA?9xIs;Z=>?yrB7veeFf9DV0?=F!$OAInV%?{Dn#pUnv@GFmKFDKz0(4|leB8;yttU&qbysq<{x5mo{GYXy6SR!k_<+Of$Ibsi z3+GP!e|-~l6oV`1^o340mgY(p4*u5Npy9$pD!ooQui2ZEI2f7_@mOCd{kmf!1H*yf z?l=xh#&Y)(yGF}i28IJA`i+)-AX=f(vL8eXHd;<#U^viyxHM@8Xg}lYh#hSV3=FRW zcQk`2uN_Sw%6SK9ChoOOqva%!CjCas$sk&x(Q*qD!+{dPM$4^CU_)egfadOA3-17p zVZP?s(F)Sdx}ys;!tKTpki~&G(KRx%GmazrwGhaU{|i}=B)VPybh@#;xiY#Dkr?1WA==&U8bH98rT{Plo1)^2VZ|n7Vwb^%Ce1ThMumpc)XA4nPWG z4@1&1L{nI|DM%2c%M`5Z9B7%YG3elJ)Wmj#1#w~&IJ&_p8GN@&^85{v6Jcu@vAb>-Mg&=C{C;B!ne zK)31awg~oQF#Z-C_Trik14E~5K!_&;XkCD8LWn0r>+KTO25W{=RqC}}{|V@J{nN|R z77!Nv0+a@tkBETMn@qRsACFGch!9VP#UUXer(`j_*eA%q(0%N6c(3aZ(3y;)u54hU!K;JB^;fGpe=B|Jl(D${~3%gIT;^#&E)RT#ozEVrsR9W zPo+}56^y0QV4F&K8tNI9N}1hXb9edvH@?(zl7EWp|BEkPb9;am#2;gear@8QdZ6?p z$mSBz>@`CvhmAssp$%t=ZtJBI<<@T{%pGiQ{QKAgUNFJ@<&NaB|IF?$D?pnpzLl^X zV`Fgp&-~I1wCCTKCq6E^^<)Wivmyi7q0mk{Xc0Mh1-X5(C1{bcFOTu1@1+9PCyKTB z*ZT?_e8$v$?E3}lgJsgaEPPpv0WSjiL7Td|KfGAM4{E#fbRT=o1kOF+JQDlz`=9^+ z7dn7a>w!`wOIDWwyx^7ohF6tp`fkz)B7qA2{4>3sTHb0y^0&?8RSy z28I_Vp`a}apmZDX!igW$I00`13wxmjsuEidl(IIT|Nok2u}_F6gYo~xApKbkFC_Ru zmt+Wm)JJy1*8>Lzf;RaZp9~A{{@f+}TDswvZTB^PmxJ9WdaD?_n4DTboAa)_F@Ne3 z>vd#oxm0=&v~w+o599*SA!(&t0WbFPfewj#oz_|U=XFr`>E25CuD3vdel^CA>$ zvxRs6d(9K@f`^ZRp|_r;n;o=2gdj zIqQEwaPSLp(1}VnK*h%G5H$hP>;W&NK~22a!!K9-1s#aAV*+SzG3#jt22dL)0~Gb(Jw?Y|L5mC+ zj+iN+VFPT9@*aNMSvhyp*T(1tdtp+uch!!e5Jb+qM2L;X_nwAfrL2n3wXD zJ^}49LU_>@bZmZ!vMoac1L%?z&{6p%qA%`)j<^A@LVpnkx>`ppBKGjkB@y7Z@PXLF z|3!NQTp1RF>Vp5G6F|(A5Ko2;jE8rC%Gkp@Km{yl4^RN8f&T+^j~Vzxtz=66BPIT4-=B_ft~CEVd*FH+(`?ch!}&=$Ohu)RU}dH|syQx6*- z*a_PH=FrXviP+{hJXtIeppiMyCbci1BkOxz|AQL30pJaWuwv(hjxu;fUiXJAhKTMy z&>+LNgG~HW4mdRb`d?z)da1;$`4?k}eDg1+644jOx!^r+@TpNJ{=XJ)e)tzO9?R4T z*8G~inYY8&li@$O(q5Po;>j=p633u61GsGJ1|M81)%=68MDzt{3J5w{@&=SePyCNP zyc47gbhX2df)GyzP(bbg1?2jL$eXFegrI@h?aT9G5oql%Xv;V(zzA+Elm}@C89f7J zbO?&ky9JSqHUU*IBpH1Kq#Yg$pnU$bv-V3jd$$2-`#0z&C2$L-`$V@`^F#UWI2Pjz z-DMocH;g}AK6Ux@<#V7zNAB^rf|lfIe**6~I{1&t`a}1>ECqh|AI$$E_+5Tj|0|Nu zVhIm=(G|j#m0}IzVM$; z<`>I9{{P?2-_6;{*z3#^@L~p-8`jO)>B#b;8_WS68O+(~$YFfoH8Z5Zfu^|THzL8^ zH^Vz)-*hu~TeSW!u|GOvKXk{wDP^^G{Zg{NyYxf%k51PwuNQ%)Yk0#TGeThP zpy3;aPJwRbZU)d*$Y6@Y_&^+d-2Hzk2e{AsA{$gaMuJW_*s&H=Ox`=nzyRJQ`T|r~ z_WFK?br_#OMk8K;W>o@Si2VKk|HZtcurd*nSA02IPnLrAU&kKqX0&$XDCGsmODAKe zBMUfqp+y;JgBEBb>YHBQ|5;4EptA=*fU-aMNWLH7eW;)Y=L@dCpgE7@te_GIQ~-f4 z2?2G~U-bU}|Nl6P3b>=*2rBD0Fdlv({OkY!4WJSwtQ*`&4|~x9I+6Lskr+@Nza{z7>gAO8RU{eSl%<%1xntbFk2 z!=DnZ)^8)Qw*xg$Wl!!FHWGwyI zda{(egX_gXkZPsZ7mUBXzVf0Y1~fZR!jUER;!q3&L*zGB(58N-5+&p-VY1jG&uV5d zW{5H{IAk%uV1pc^k;VK1bU`1eVt`_>J7Zs#vOq`8g2O;Z!FGd=OpZ|z`FNprmB_SKOo6}er0*<+HFhcfY8y|=}-0j8!T^ir`MuQo7*?V&>$NzB901L;9h*|&t zM`i`|wm$d+YIX&@=vwgqf5sWmBvh*bxFr_wqI|*s{}2VuMAeFYr``aOb3uz-JGWi{vG;;j2&VN+{Q0V}!43zV8QKcE@v$4E?G5OD2Jj6# zSq$AjAeVRcf}M@HRY$n>e4(`$2aA-3a&(K1UESVhdU@*nC6+v=98_ez+;1!wF@;tz_=*^DibI0Pl>~ z>fR6ox^e1Ti2|A_h`iQ(LNcsS&LsYtg;E682V59R-t3K)Zn&i|!6 zm(PKZzb)PSLJ*WGVf_aO@L`A|hfy*NYvftYuq?)X;w%gY!m^lNT>cAgGl!v!{Xx@D z^Bd6QgYhNMR0Bt^k8r2&k6xbh-G-38FV==7 z+Sa9@Nmkb%{7$DGK(DJox&1>&cRjy)4&_ zPg)!ByB>V~92^Uv@~-(GW08LIKi+cAZkDfiZhA1hc4+)3!Op-?E}5kZE_t^5WKcsiEQ{m6>4peThX0~dAOop4U-Q102C7vVK#M}bWjNS;(DiU7 zy8lZ#vKU}GW`K2+N`yg5i+~rP>GjC&4==+0|Nq|!@+YK#TnMt@@IraK zKm>@DCGpl$ zJfZbl377Rp{#MYa>}#q2CaoT~Js4hqb|Q3th;02!spp});XK)HY))G`2%+Jg=WN17rF>o&~*h48=sB_^%kO64;| z9(pij2!IF>D@*Fd(tn_dE65q(g5crOtY5HGgkH1mP-S9(-24SPMCTl+BnFLvBOUh* zzA_G4dW5~W22-K_zf=Qs3LfZG%m1Y^XayhK0?>hZ$a0`#kvU#$VqgH>x4cCFbc*;P z707gC?0?lcptBo6-T2u5sw-gZg**wK46*+ofYV3pf7JyriP-w!|~j5DCTaRfwwSXs<39)r&Z6=*#G8Yu^d0;mOAsvfovlsQ1B z3JWyb{Rf>c1({@NR%2*B#?tujO^7E$>4P}XNe)>889zV`!s(MB{o*W+7mVOjhf@DA zWHHBemOiispX^i;2|hfjn`J}mff6ssoHyvS88NW%f0GR_R)Bm5nrLVK@A?ER+Rd_| z`2gs!B+%jgU=ffyThIw4U|zGz1_rm+b6|~3VNeO}`UHJqE{o&EcF>tWkoFX)o(S)) zb{4Jn!nZvtl-?aYcZvjn{bh8JC^~SU8V^CmVV7_5}jNj)& z*b5g|1_o=>4`H4Rk^KH(y0i3;@waZ*KdlE!{F|-+mpCmRq~!z|Vx zN;k%VuL=MyMlt^1eZ2cTRNDs&W)rZc<~oW0B|Ob_68}or8vHaGUYB+sKjx;<*!+T_ zL;%#pWN&`KnDyl~Th`atOj+L|0{)9OfHJ`i&=N-N*4riO!EkrU@NYZN87I;FgQ*l` zmcwh!<{!+ZDh+-b9IxdX{4^YnyMgA!{)3~e^*{+%H_MLW4xp`3|J|GaGxN7b|Njr# z6$cszk>|3EAZd&g*3$eJ5NNy;$?LO9h4U|BCu_2CZgSb)&G+735kBb}jppeN0B`fllVVU*}} zozd+o!hEdLb;EzrBLc1r4b>tHovsr~*}G4_s0E#+=F9`yZ2zy@gTwg1>Q3LD)vLQ* z=X77_483CQx`Dr$7j(cz?H16Ihc#VH9j=$VUH5dx9ysoL26VV&3gR2B=p2e*ERgx82I-!Oz`z& zaOiYBp?$E^b%*tF{(jJ@Xx+cNW7l*scevQTaCf%;S@Wg4bcgZn)^ByfVZE*|m=6X8 zyb$aKEsi_`nuM&~(tWwRbWb)dZfFQqu2FCr|Xnn-xlKo z{NV?hYfrEQ@=pP8EogBF04xtKL z|4WZ#F$VR5P8s(@lGg^yUkMI&$YSjTtquZp6wiQ^1^+Ld@M5kd$S8$Q*AuM=_*?#g z_VM)kE&%xwq;AH4(H3y7{S*7s|kc9(K6 z*0H?yYW-jLy}NWvx9gs6NU(RY2s5ASaFNsl?W%b3`g*tPjxMea9}7K@5=csJ@UhTk z>2_V?(CNnVngdcOf%fPlE${#>HUw|IXsHABpTWHna5)(W?tB^_2=D#}Iy@`3@ct z28I{YYyba;7gT>hgF^?qLq(b&+8_MEmVFX@n0YrOK*Peje|NiZNOb!OFkkF!{qg$$ ze^8k-^~>x3|5vZJK2==Yy%!|dyY-yXJ zL(!AoR*;HLUjgk8y$Gb= z#*_w{<6`P{{bl{3=sGkUz`oS}(CI6X#n9Ud3Z~{~|FC-$B#G=%kj2)girTSy^jbB- zqY@yGUarRCQ2|68hCySnyOblm`yV6@MLJtSmN1_(KG4|@kc=S!GJ7=3{Xw;g5Q*Zp}Ul$`G`Vi>xl;O?5umn?N!$Pb-L)Le|NoWBb-Rijb5LPyPEcSt207;r z+)z33|0U>{{nq~#{MNRhwstXSB-;4fYZl{g-N#xFl&V5Cb`~fg=?e%0ffvPZK*L)S zuXl8xKlqca)As?S>2$%OGxSb33%KF@%|$?iv1C{H3t=k;hDgx9pV%kh_SOSfT>0Ml z=EA7KSSk*-348<}$Y~(gb`~hS76%_8FYv#VC;SCyRu42q1v+&c){F(;5r@%??XCqK zSK#8^%(O?nB=%tY9oz+8z4F_#3q0^UZ}_L!m@4IEyJPEbxVQAm|K} z56wqJg1i3(cGli`aTL_80v!hH4mtrs`&fxOsFwlR$9fC2W4`oDuj_^Xr9T2*82tjp z0#Ek`@O{z2|6wx!OFsm>@B-hbAoBWQcj%jL-xpBZ8)`T-7-~bIMq7f6Rse621r0%= z8UQ*qviXR>>jkL7X@CCzfBhU)tPiw{{&KeuheU7f1>*y&!&a~Eb-fbszx2!h(jS4a zw(gY?%F$``v*V{ZT(-Olf@cg{i9SI6bHwhCBTWo zS%tCFS>a{nzyJS(!(VI#@8fux4H{R0oLmfQ20N5+bi4j&u#hT|fohduU|;~nYG<*+ zOS^yn|7*KG0WG@$R}onp85N++!rly9(OU#M@f|!r1MUGGlz%G{6uI^e(hB`AlhfW7+#G*!$BnI!%I@iWvbEufht7PunFnZ`drT|dwq zGDztQ(5w+?Di?YOCg`e52X{|~?jJ8q-+*eVQf}xamBt6+4+n>3q%ec7lzB1x1!&+B zyr4?~e8(k7(+j3I|NjTSxc}n+|46v5*Y08eO~JBHz|~%*S3&Su=@j8 z19Sxz$WpO@7jrQ6vA=Kw>kETSMRp&5p#^dpxGA3n^^VR`1_rQcpaG6QAhY-bUIe@X zxxIw7`N#j)>@OI>J}KeMEad^kE%S%&V=o>qfh}Hm@#EG1{~1luE)0u6K6>%~<^TVS zpURJBAWgH|tNO-@319 zU$nl?-wNLCf1>-E_WACA-3LKSlYcP(wEkWqb@b!=lSjXnFdhAS{Xpx1qd&?^*_#h3 zSYI!F2I@PwaxkBG&DLPWP{QhDeX;bL_JxdMo7k@=wYi4rcT z(=L>L)4mwreF!$^1`D+Ai_l;L4H|+*PgT2Jd3sG8tHK*?MgXt8#U)I<7Ta7^FwoPESFOT*)&?pW#m`^aD>gDmX{s{}|Qg-B!KCWQ>v-BCrO+0Sa zKTG(G52RVLm#~9+nLkUvbYIuL_7cM8D^KGikl`=7i~s-6;^5zYATrJRV0mdVi_wACg~peRPj(+RzRi4?fAyi}9}4`= zr;IN)|8U@UKGl5afAhuv%GZ_8fz}7{GjLxlbx3Qj6)`AL;ot8o!oTJ_i*hZ`!FMd( z$CXP3Kt5n#=)U$srTG8~pNS)UFMkmbp zn`Nm?IKOYHjPa%JTAp4v?hbKFSAlY+ZeN`&rMN)IzD-9N#?C^C7hLy2^`k`hv6o+% zKqu71a_j_$r!&jJ7b40Btq+z4|1Z@6-LP1y5(L_)2kA702fsK0zL`e@wEX`VJHt!R zNitcf;V*VB1}&lj4V5imVqoaHVWhWB@gJm#FJy#8jrEoFJF?L<| zE?0$aZx$2A4%h#U4?#ZU-*({O1J>pP?46)3e0O@o89}@KKKy59VBkL38Tuv5AfnW` zgT33CrJGw76cOAfO2wcDAYAG8z0vJ@rPKFKr|XB;0?ny!7>>Js_y;<4gZUV{VQ&>9 z=oopU1Fx04U3I_*vG8`Ecu{l&)ZWqo-OuO1(+xY-k)eaB+nEJyL#OMFa?WOJ2L84~ zpatLtpmx$u1_pix;{%<(PdZ&+bjSYazRth>c4zE^?pTh_&>OAa>H@lhS(KTTFLwJr zfFv0H?I&M^7ykdBWe}Ohe2{hyLhbZ+^wn?fSxbQnVEd={5#me@tXOc!~fQAbpl~o1`z?_FWhQC zX@H0MU$^U*jV28i4E!!Xx?KN*j&=>`VDDz`4rY0=sNnzq?i;=SOpT90>7j`26` z*bmaBZz{OzSz2!wv24(O&Gr3umTvPkhVSmO%v5jSl%^?u-n^2S7*X!}1Of=x)+p*Dug?-doHV(Cx~R#TW)YKlH^_4+e(+ zr8>r!nrpx4{x8+wpK{3fWI*d}P$Rh8Re*o~LG6Ruhni~z{)h3qxC(Ta@&xp<2r?fF zcyY`L6jh)LNm-AvF}#-fU#im!I{iEVa#3OM|5Aal7oZcunvWX`M(geC)WxBsNTj-Xu9b?z+EoW@KU8m9I z#@NB;*6peS&KsaZioyK4Pk zO1$;;8jkKmGr#|5aAV5iLgq3vgt0W&N-)KjiZoanl=5dW_c}5L1is)Y0o!4G;3X5N zDuf2d;ajl98O?9NQEGeubRVHaZ|#@=r6Q|AV+UWr5z7z^iP%4GpomrJt`#so`M*>F z6usccbN#|UcAQ1RfT7t+xBGJ`+c9R{ z-eSgXCzjR&_4=hekT3&pM`toV05YM3rR6{=KPYX2ZtlDcYEB&yIL2n+_L_u(TeiRQ-MfWJM{9_3>J!?jPY{|3P-- zGcquQXBmXO5UT)%x=ehW@quXQ%pGW(IXH}s5A@c4fQ9mh?phg0K!-yDda^4hpmn-^ zzZhToU#ihu`$4xmmM4IJ${|o^vfEX_Q~OY-@1N#cf&aZGQsJOn6cF~J!yXaT%nYvs zx?R6`H2?Thqiub>R^8I|Pc2s$n_J6)(w`k}|G+uxLl$E|`2SLY;1~7attArB90wAI zyE)m1zYnV{HD;$o#*T#k$+1mEoBO1L*7@*FR9#X_x-7{v>_C znfWmD@&6F{puiV}S3rTu1KI_4pp@z4Vc06bf7fA&xI0v&^-_r%XzyM3x$s`pT}}bL zEMj2+FPICVra&=oQK+kcdDHvi`U z?L2-R`r=#!s3%)01S*dHm-2+Y_zoW86L@W93!08E6*E4N1{yuHbYrPeuV=AjD^lFR z_*xdcyT4QfBFS&*2CCYhTe20iynYCpe}^Rz@Wt%iwLGo=OI5mk4YI`I0%672ZO}fa z;1_kE+i{M7+9GbC&#i<5ba}`>_fnQ)u74Q2eN{mHFb?j+rH-JnnC+ljE4x8^8}z$fIV>Ys z>UnBdEG3HBj=BC|e9hbu`vZJ=uRu6xjPV6%xoqg@WdR=#^ge~aAlrr`#G4N(s@YESs z_qi7yyFrDAK(`-HcOXaOFVL(+sbN^J>kt0$0|EToT}1+dLG!^sUi5{5vaLYt{}QH7 z_U0cfb+a1kWEe`Obh}BsHf`PsnR)X|>-H7d^`C)(Abc`0a*;eFV+=< zJjj!!718M?0b0HZ_Dt*T61LU@C3zj(phZ5Qe$R1s&{X_O3s4s*^$$a@?;p@*y1}5y zRgr)!hM*U>q(LqLZHN_+06FHx`O6^ZNpv57nF8u?fhGhYD;s%0#)B@a?~WA!-RKSS zU4uPCsVHbE;sO4aU!XqZ$+S+6mmff3UMd0(ThO%Ro1OpvcZcybR&juXRUs?`v==NG zoLuIBs_c{hn~#XJ9^m&l_;MS_lmnJcpl~b|>jrHM;co%WtMhMTPwQj^pV!R4joeW@G^+0zhPq!}zc(Zc&{*nk!hR)C%{H{Mb zWA7M$>#V)t)_SS?7{4p%(1sT~7H7IM@Vg!|zGNACqto>Xzw5>3+7}F+p;t;dvi?Q9 z1l=n>HasF)wJDIx=y?g;$BNfilZQd2n*6Z}o zhKaxZ6ljUSZ$|zm(7c(|E&gWEzH$C-r>%WobRXn*2Cd?F(Czx9`-gVz4eQzmowYBz zYcCXQcUd_62gyC@I<9iSrh&h;33OKEHqgC`2cNNVf9Q67VGX+U{7KPOOWy~@5?Zkj z__rNO>vU(~-*&juJgw86?Iqv;|Nk5RG2CEaDB@`R_y0ZvLzz8j_pty&xjFx~L&se| zfL1mhcm2Y^!N73b^#^EMq;*N_iz3Nxu(y~xjg1eqehcS!IT856C76NXHRu1*JK-;U zgF&6aZr?wUNyPX#_>g#DASjo0hw_B&tBLSr;NO0V-?daAytk1-g@K{jj)8ysfl~MV zpblS}_3?7v|D_^fFa8ICOnaTy+r*#&Dld+AA1oJC{jdK2fAax{gAcem*^Cdo_5djb zCF&P^;BBx1ug(6KitL1#bg+CUyr4Ry`d|6~e{fO7%m&tQH;{oLEZ{{8Sf2#w3ykv33w3- zT1k2Vw2l84OSx3H@1Mq>|Nk>El(Fvo`yX^59=HTf>*VM@1R6dM?S2Ca84d=}Ho;n+ zZhQWgCE&y(&|S*Wdb=b$9JF%^w4VJxcrQahuj`NSfEOSB{Qut#vE+YATZyie>0XDH@*bLnRoZWPTwB~UvM=(1O*5$D8?c4?u{oI?l3To&|q?@ z#B1r+lO=Y{KYN`Sn}4$O`u-2+cRk!2!T4h3zyJTk{+Egbgl93lumHImbQeJL&;O<8 zKt&6*TmhH#-G^U)ha3)Je4zOxqa|+(D5Xp}a2Ooa-Jv|qSsaX&g8xeef5RDf|9`-XM~0y0 zPh=#x90J{R23k}LwhFwKB|PlK#{d8SM}kfn0QG0H7+*wyOvz%3w*FAczP}^Fli{^M z@C#>AH^Z2wthf;|~}{dl?=C#*cc!oW}(xTA@Qf#CxuV>75q$Y2lv?W}(Z z+Rf9+{^Ip{@cD84ttU%`di_K?<2X9~SUUMS<0LjPzLxCtW9eq^WIOK00n&BcO#(!{ zeu~`60<9V@F$4{~!I#!@u3#*Y1@|z$`#`4esQ(LJQY!&oRSO#MN?8b=?{+ZgcE~vR zf8uj~S6jya8|)ZL<-1FH zEbDkmdBKMy=d*)ir!)(6uLG#=e0?cAJnMg07U%y`kr(#Dpr{AcT4Ip8JmAHJv!L6x z)z1C@-_7vaq`Q{K+MTD2C!qWM3ss0o3jfP_{+DyW&G;<@HKSyYN2j|0sG5Sh7##hr z-%4d5F79VzU@*Q7ikdi{&Nu<%121QQs^Z&emU3VvmT@pQ*Rz4$T+{8w(IN5rGN_fC z^*<~aqP)s=ybdCG`~>@13Bl#r!)WmL(W3U zIt@An>!mxWHLk#5d{WW(MR0d4N4W8S(2!T{gKp3ciLhSZKWWEZ|7h6<1{`z!$MAw3 zv;_uqz=2e+>w^GLf9AjO3t>jk$qnEg3Z*5lg~8_+|2KXCx_kw^`=L~}`7jH}ywVNb zwGX;|pLE~s{;qxh;BO{p;{&hdyFa|P>lOpA_xl1p9irRyhj!=}2j)Y~$5=qen0+k0 zm&F(m{9^AO(3B#`&~K$;0WW5P0;L&r+2?~7zAWGaQ!08{=5@zD0Ua-P0kpaLcZpy3 zG411>u5Tb`I=g=9Vuaid?fV5Z&hXzHw0p|+gZ3e2*B=2vFL*;hDMg_5K&dh4sHxCD zogx;^$61&|zkp3E-3clp4U7*2ypRD|-s}6|#bss&2IB+q(Q$|lp6n@D2QRSOmjiJn zb$EBJfcB~G+!`4|`Dw zF8n}l0`&&8@AtCU{V(MR4tS9OmoV>+73n_xqKyTd;lPXCdBR>)g3K!Y6Zx9E+nJ@) zp!<8XGYd=ji=@+_9d^g!qF=Wd{|^U&7daKU=jY}2_$vCDp zL)P4yzo0^?b8f@m|Nq1IT`zXd1x;OdPA&NR|9{8aj=%r^znH|tz!1>e3ep%5{^Aj+ z0_p{61Ksm|sr5i_>l)DQ9psR5f%qKV-w6f=FY>|eLOxI(&hu*!Q5^B zn)|=m3w@A7L8pq8vy^`LZ~j6a#E0E~2`&apML?a(|DbjusM+BRI+Nvy0_cE9aE;mg z2DHr4_rnWiP88fyPAlyG(XerR480J^Ul(r^sx z{s`(tmhk>B<9M<3`2YWr$J|61U|YJvyFb3T0W!3fqt}fiEIi;vJb3ROXxkZAa~cl= zNbzgVV{Rghpk6LdJa}t7*im61y>lRX!+Kfl1A5&!0$wN(tNni|&x^1Jpj_e0(S5=A zK#{r}(11}e@E zlz>_*%?AWJ-8f!f)V4eLp9yp@!T<3;h z2Ce!w2G{VapjJs7PpKfdRRTI;4U|K`YXm^Gyzzm~IDyxt$W?s|Hz-4(RQ1M3K{a*f zQ7l!xHF!BmDOy#(1Cn3iRsE+UAOk!g2EeNNXz)ZWEG4jj;`D{;(f|Lmlp;Ghx(~wQ zIqnb(1E}vJQo`KfDAMW3(do$3=_mkc+%>+@K`q){IeL3RJG?Vk85tM?1OAJ4fD46E zL0Cg89pn__1Fu6twScQY^HR`OZ-&m^E1+@>TyAwj_L_tDogZrj?Gk5r!TtCD|A5}s z_YexCHlVi^WKY10a!?NfykQ)a13{a-U#JCu@_QCXhJ?N+!;5Xvpb;q0CL2Xi{R(Q1 zg5nC)6FKe*y4~$R-nD2ZAWetCTk>~;j(H30X6ptm#cMtw5fJ#_bOPukid@i~GTTnj z8E1iDNmfZvsT}y=yvkxWQ5xF;Xf>IcDr)uE@5V1DA8zs!BQgA{DK#y}lo^7+!n;E!9+=16nNvT1@uiU#ZY>RuC67H1=Qgfq*N+Yn|pF ze^G_+fP_VxfBXSm9{dHNq1%B2y_kVE6hZC3u<#5}xEX)zb(RPVc)^|ks#JJ7i&;90 zIeM#kIycLJuBJM$y8GPf)m@Dm9-a&xF5D81jXy!UYTkCWX?l7xbhH?Qg4C_?A1IJ( zULoeN8{a6fBeyQVU15&KdKOS|$lt;PTJzER;>Z90ptGC*i#`FTNB)*Cpsad(AIP-s z!yPTGpoHLHeXQt9SL?eU|Nr;)g2-d7AYp~q^8DKZ8Tq#zc+G2lteE#0M74s0^`Wx& z%?FvfK$Yp;;Q!?;y{&&h7J-)5|NH+x0Mz)(7Gz+6N`YD#;MM3Lxv>A+LH-VYal;3c z-yM2e|NQy?AEYu2t|kLCjt*0|0jy4?*IlyvH2?M~z95^v9bzouY2Xm(n!@`BbeWp) zw?j-I0R@l%Xc(BO>#}3V1dt~kn%^;&9)F#bwJaj5ElT@(ufJsH)F(gw|JOdA^*l=Z zdS~kcP>Hq|BxDQ;7v_V_KP1aJ8aM@d9Ti^l^|J7T_*@N~3cZdGm=3*W>N?!f2r}ET zmqpO}SU1>&qLZLn7rZ}Uz7HrHcK;9Vz7rVO{NzXT5th*IY?jU(6_)Ndjc+WN7#PCB z{}+q=FBW(K+Ew$vm;*BY;Vsa7ga_1!_VloJWGQ6_P1rFqFk~n&F)+L^zxDrrr|Tb3 zkAW}X#mfWWontQ_f`&bc1$y^_j-J>BI{c{nR6uu`$N$nVpOfH(w@BZ<5X|n>u zi=CkM){o|M|05%<|CLI=&_4iL)dkvT*6sQy;KkGf;C>9~9L$Dl9)?oZ7k9V(|KIH_ z09t^{f6&0MRJ7Y!ps@nHFtmj8e}Tt~qywNj%k|H3P;fAGdkb_rdUSgWATN)x>~$9C zbbZt7`#X!Z*IA?!yk7K6r|Tckd~mNT=;+r!0WaKt|NjrNw1lhMS)`j`F^h*M=&(~J zkdux_#>aI(jqQFM4cc+}1GF^uRv2s-VJ&nmPCKZUFX6K+_bK7*E(e`QnEN_1i}i&n zsFDXQcrW(=Z90tQu{JJIZ~X>a{L5C#-}nz)60wK9n6e+_8{k%-sp^d5D6Mc-w#?p_P_gl_wi2OCzdlDd^{QWTfQ+cFgP|JFzEDsVhb8i zFM8Ja`vquIUJI!5=HGre;J@e%Xc+-oy0HUPj9A|&RR9fr>;q-l&N_*-&N`XSIu7Fl zy>&dRSFe8Q3o2w>Ujzih%9oNlaGBTZCJ`R+LNppu;>EEv*S=ut1RGL%prQ61L$B+* z60I%|#+H*M%KY0b__v+3{#h>A8z!lJp82|C0~d=E=-{01%?FqoEEr0!^}0#z1nnqm z;NWloOZ+cmdGYk;|NqASJKI1`Yd*r_{xbRh|NoY@pu(KL6}0}W`NaR1dl?uQkX+Op z1$I%k>l1@c*E_up0Y07#ovu$BEEu{^lvsm%2PKC5+XVTy9k9MoF5ep`$$YEv7btBP z3w5l63p100}}jsLS0ZR(DF5ZoEZa@>sr zRH?kM{Ry&@1>(?d*E_v_JXvhL6I^^e8RFBrnR zVk^jd2SBH{Kn8`qJRpS%#E?}u3x$t__wnJ zv>q%4wOW~t4>;hcEwfm_XCY)UyqF7`oH`-^9Z~9b<=DCA9s`5*!E(0}wVlRCz)Zyw z>E;(&C1ScvM;I7N_(6LoxIhFe=r*q)P6*$jFqCWtv01xaL4&2PJk1X{pzgvv z@AOA1wL8T1KFF?r zt&4EDF~s3IAPwpuhYLa+E)5b8gE$-#DBZ3+s`dZ>|3^9_Bd|M^BRDL)@fRrTm+(O5 zB}+i}$TDqa{9now^a9k0HU8gnJ2Db95&V(g^*gxXSgX)-o8PtePYFBp6jsnO2EFI9VR&J#VXLUmD}3KK>dY_KLWyngF(mgX@L`q zN+)QHrj$GEzvveMR|ew)uY_+rmaNVgd(Zy5Z)^bcsdIxIN& z#Z&MY1*qG>5&mNGPSC!t;1}JX3C8=No;FBJ_hIme6fEh3id~M@Z>7R7-tU0bpP;fv zn+de=!#1q@-wWwl28K>o(9qKX{+7Rt3=G!C_*=d*GB9*GfL8Cl09`C+eA`kMbO2~+ zjb$uPiH@Z#=;+T9l@}LRgVto1ioBSJF#YuZu$OZf85mx)f%Y4FTg3h^d6&hK#rUFW z$N&Gq;3H&TT;BoC%n(CM&Opp7l?N+}1}g(u@L~f@8HiW16nv0vr|XZ_10^%NT|a0a z3kZ8*%>;7&7f=fL(R!f5-%_%~`@c!!i_#sS>e2U$MeP4lgYM8DuQ|G1x>!0{x*RQK zx=KH1u>=OaFyvui2<~+K^1@>WsQ2*&Jp59U^g6oR^+)&bPLqz;VHUCf`CD}U|NsB} z255Uo0F(6v{w7J#)Y`BA|Nqm&SD7)eDQ=EY}k(%zqf-7`vEqLzvV5c=i~bY zY+Pqd2MgH$ma#niEui*KuOB09CCSGu#$Gq30FZMcK_-AA^K9cC-ov>`~UyVr~gNWzX$_aarm`r*bATSpe-3MT(^UU`(KN^I1W({YG}PM0I5Im zKN6f%K&OT?-?wKQ zXzUiW9i$|!o4@sBNkDM-J?;C5!BOo~S&X0|*-qC#FXFd>hX`1#Uu@k5_Ghz=HA9Ks ze{;~X4HN4Z;v2!Dtp`fwn~$@Aj4Rz1oyG8?eH$pYkHx(#`v3p`3-65}zkp};UvzEx z|Njg);XsbS1**FF?7WlLgFcJy0r=#S@2g^abdQk=KjBI-3tTEC!k2{(3j4 zCCmOI7-TXewm^p#p8##8{K=Mmz=9dFa}?`lK|3_NS>}SanS(Z7GM2bB*RV_cFR^`bcESJupvx|ljSpylC=qFX#|T;# z#8@gEkoDy?M?lus*USM~-~NmK0o4f*6PkT2B>o#8crErKZ!@R>25n4y;kWt!|7HaS z$f2pw%B0(uqxt8*QqdQN5Xl#IaP_a9TTfP~Tl0cKq*%WDAZQQs3%2Z&7SLU>pnZ&t zC2XKA%&~`Gd<2yc3Jfp)ZGziZ3d%O1V|SZvK_?tDlyV(s1v4B#Qy7q7g`^bzmRF!o znj4QbtBtQG1L(kLP?Se@y9rpcIzUAvH-i$Hn}{{53si(1A|heU>H!t`x(TdC#+ua! zD)Ja2qF~J$02R3i5mB*b4S|a6hlp5Mvt~d=)JCA z2~?yUBI04qS^*VFg^2iAv(`XGfD`mH4GBgTwkD=zPJFOk2<$ zedWS0G>aG*y1#&;_c+^`GoVYq0$xl#2`Y*sTfddK9A~?Gmw}=A7$^algHDnUd%^At zItCfEXdFDe&lvn-!xxb2Ray^}i2N^=2mmdg{V&QO=*rOj<26(F_pleLpc8=`K-Z>l zb-O-kUI6Oi|Ls2Bn|cF$pvE8LvoDOT;oTx|SExj&`2|O#1;}>Le#ArT|Nloinf=3m z2cB+^8c-AV!+*x^juy};^2rirFbA}D2QJftkO|9T>-ErxYpndi;o-?p!r3j@dI_Y3 zsk!nCXo?~54~&0M05sTiE$;t@IiQ3BI#C5?c_1kLb+>^UD6I!da%{mFBDLGCru9Hc z9H?@S>}~_Q=0J%Ah$|fMf^9u0%0W6_tOK1O7TMhfb|ON>lXY+vU7*|JBLA1wyf}{# zJhBe7kfFN`VkUI0WTJSZZK+_!oa`)J{nN_c)*KZun;Ka zgLw5|^FT(tC|L)JFoFNuz}^EL!4jFp7STHolr2C5I&~V2^^ic41y}kaAnW)8Uf6() zFn(bQagOVs=K3!TC1Ty~e_9We@PO2?2fUB~Np`#bX+F%-d>nM5SEuWr(hc#^VK4rz z{r^7_enb*z0bhw&<4=c&9t@yeTMi%i4>p4CoOXyk48FV$TK0p&yY*X%V&gxsO3Cgv zkfI5o6?4>Q>V)nrIIEB^4`1Cf?Ek<$`qcLzA4 zzzK`9y8{$mXQrh?baw0hj6s6a9Qi{90s3Kz2P^tBUc zR6V@)b_sXzi<6*j#h`M+_&@*pQh~7G7wndxBi$n-TW^<$TK_8+)c)SfVjTt==IHeR zC0m~O?!%zw7}!Qs0&IWm%hLbQ&Bc)OLJ?~Ii?RrUrg#^F&JhKjJcy72vzk>w5)2y{ zp-1*Z^n*2OmZJq7{?}L0Rwy$ntQg<=x;*D)w!F<}}DkJkXK(rUyVLw1c%?K8MsM z$9KsB_&B;6C6l34A7B^=rZOG32|ma4ok1`YB5=&Zc~yVRh8k%8gAdDshZmlD+B7JAXP z98?U5fhyI%OaK3WeWUpRhY{$Y#n)2Z$C_X8mvDhXg|+zwW9j9v7l%Nl&JmVQ*E`Lr z7Z_S@mvCe;zmNsB1e#N?FdTDz#sEqv-L7}KIXZnGwA?P?34HOfACw+XboxH%^u5yj zlaYVQ@s8SOE&odkTTk-0{AFNZX#U4h!qxnbyM(p*A4{obw>wLx>xJfY7LY`#;|pof zW+4ZTPS-Op1or>`f82osRP1;AK4|{OQL2>98Ul(1X7+5+2r%OU=tQA9%w&z?TxP3 z=iR)jn&vUBaEk46dvryL}%V4uh!fj(za|awMuR#JXKCbh@*EY~X$oxet6) zUZ)3#@d5PSC^QfiK$UbB^NWUwu&Myu=i3b$A@4rdeXRMRz`=*i-5106gJ$r!udm?X zce&Vos_`VK)wqI%-{n;I#l};h)zK@MU@`&>3@aGHGTfKH9|P?_=6AWclYyCmLHS^b zlJ(&d3G3q}ptLI1c#0u`f#Ee@<0;VXGq2eiPl5W?f|@goC6Zv8sf5S+ zL#c4%DbW2iueqB~Ie=6E?%w2OqL@Uu-_b@$E1R*xk)1S-u_S0K2;R6w|lE0wB>}&F2}v z9ai9X`StBEQwdw+d9Y{J#s27a{n7m3K&R^${&k^Wx?_KU47Tqk+T2gg=OE^Of|z>_ zWG?r2&;ZG6Pvesy(@1gVspgXq<4!@0I|(wb`ygz11F}bL_RZQKY2C3uz!8Zx3_dlV zgM`7S?sLs2Az^S16i5)mFY<3c-TkTiU?bSI-wreJyL{ROid9tx9tH-`)j=!_3?*W= zpu|wZZ3_}C<>UVJnv47UYqrL7pcJKis)Wb-d?_Eu2u235C<7Bi_c{LUhr45W8c%}m z3r}0gAkgi~!S8ae`}6l}%7>Lda(}S?$ln6GVKD4PHRybtv`*JQH*^2YzFGT+f4lFW zeITolqtx{eB2HcZAR^WE4>(rA!R7i#0UX(lr$B-A&Gio``GQRAKB#=GLaAuYh}@1WBP zt~Wnp?7rW9toa1Xw?iEK+fRUwSwFE4lrZ?WU+g~Ad;(m;Y(LR`h~MP|R7e1nc~FHE zz8z-d-+lrTTu4emQO>}@05TXP3fgFYQ2APk7Gw^yMB4gt32*la>uaS_yr5k0nw1xv zLbjiH&B+T&Ij_HTpXffW%D}+P0LqgLj0~l0+^1hNai8PgezN-@FDM0lKMu-w@%-Bl z#PPcvgq5YiVd2LAcRyxeVCZGBo~eDP`@_Y5S)u<;zJB-%Il%ph4s_VJM7-DUKfmYc z?wh@SjQpNIt$){@0qu-n?`HY><*x^53JKbU1E2UW`@fXq#Y|AktMx#IfbA0o28LqJ zZkD4L-gq!TCbmEadV^XX$ISl!?=I!&EPc@WtyH<&l?S@@0@Q2>fUVAToD1p;fKL8; z?a=K8zHU2g1!D=v3k?GXhRD~?jsJJnK6$|u4H|T<{R7_KX$C_5VL~z8=yG1-k~kIrBK|7I?@=`sO)s*F<-_@q{;@{|`On+X-y- z!Px)*!@7UG_`DdTjt4Au33N$Nzzb77P`+tBPzk?jco+>jp6do^zVgMMf1ptU$bHO$F`%(%q|P>I{FL_v z+dNSF3)EA5ZP9wNLIpZ*DuX$0%D>HpL!z3`X=nmvd;oF$PVVc^N| zLfRBGBE`}C`yc3zbP3Q=gXjk%p8wx{{pC5(D9r5&ers9qI4$PUh+wT)k4B7`4GJ=e z*W0>JgO5gh(tWu3fqnJ`i_Xvo-H-up=+TJ5FMfcI#A-hOzq9s6XYC!(V7u!R=s0k< z?*qu`h?0oCJfLs@Ik~eyq5J!5dB_$c$aN{f;43zokBD@GTD0AtI!o`s(hTUN?e1&c zn5ia~qr3J-cj=wr7n4EmfHeFA!2?F&VK0nd{{P>6{(q$P@lp{~Cv+e0zWzG!f2l~X z?~g!;^#T7yIlw*DQelv*L~R6I83JDL&jCg7>+_%~xX?e!hpdm690sw^flh$^$(H@i zqMN4|G&J9kVyN*KzM%`6T0k3+Hbugc3ux>Px-~){+{_jMC!FqIFRn%Y|KEKbRPsT) z3LqDNm-0f@tAM9#MWC5G@P&XbXkP~87};J|4$uXZ#=5XVf-SAvmE$C6M2CR^YF=|K z4?_v)=(^X84xj@(3`%~qKz2jIcOZdwYnO6&yYe(xnDWm(5PSHAqBO{oQr+%Qo-QUE z(|U!P1W<@MF$TO?4k}b4TMm@+Sch_ycy>AcS7D4j3^L0WR1K9%g14vfyZ}w1M}kg* zRBNsk&@EATeFw6Y8*(rv&x?4dIVEgh`F)^0QQ(q45OhTjhw;hQ|D{UZt_oRVaRH!n zC;~y{QfGn0i>))jNwoXeOVEOwU`t<~GTH7>0nqB-4t{?BLk^&`ELgIXUUPQGinQJ? zmCq9Ec2$5F(pew@Hs?hF%#hdh-Oe1n<&2%Ke~z&mv|g$c>yl`>UBc|}nrX8^hn$;N z>!td)-LWDae65!%G@wfuj6vHVUL1hLWXpjPf!EB(*bMx-*la9IzWqDU!Pa1JSjzg} z8FcSVIb-)Z#{;Z#1As<%ETI8-s@4H-h$+xbk#c zfIEBqEelx~7<&Ewcl!QlKK`G-)daLUEr6vn^h)zD#!~(6VwT=k(020hfL?Ew&b^?e z{TZOs!~;96UwpX(vQ(h^nDHghQ1H{(!>uPv9pG951A41jI(y+-!aKQN9J~Ws8{U2F zd+C+tBLc=Jtxt7|OP`GYe$)6;Tqk#Q_tV(JknOjwAG%#XfHpj?>8@SV>H4Sn=l>FC z$6lW9PTwDC{PHdg48d6pLBjPK;?z8nX3we?T__At=7jTgHQYG1cL zRRdak?bvIwua~F0`4|hoJVUpgwPh)vq}x11t}c`qLZr9~QWsu^U=%^LNC7 zE_in3=oK;U3_Z~6!P3h!v(tA^ug9Nm*AKls6FYscbh@tKmj?}`GFXTHC}-^skQoiI{GK{NoVYxGMjGSGu^*0zc>EY?R(+H)<_11Zr=;s z$GNXve%xGpfEli^NEmb?xbK;6hd-BJaNp>5ebE_vr@Qn-7DHH2z>D56(4Dnm|4W~A z-{=f|^S|^3=*axo51pZ3UNnNt{9*j9+x1On=?m~>zQ6yMX@S-+ooGJH*nHuCK=6wg zjsO3de+YkSKK4N6iddWf|1b9p2sS?1{hizQ4oLT(PTwallr{eU zx4u@SSH4NQ^aVqw>z7il=Kuf8_P=HZIV1K+ z>w!`Z(89lKpaDJK8~ou1x?OodDfmHm>67l-2dyVdLc3%4fUoZT(dm1q8?@-H+x5%$ z)F<61x?MkfPkq9Ck@-hAbN6}SPu>5FzgZtFW^F#sDEv+PU?($Z$C>Mo<^wFvxpx>l zU4N8ikazp8p?w=r6Z0U~O(e1jW z({%?lKD)Vk%UFyL^aimo`~49;O=+F9%(-OzdQ6muhaid z*B`H$yF(9jm#zSfOI%?-+#S22`$zLNhR)g*&AEG6yuCVOH-K_l=z&h(E3LQrJ3*&x zzGmw#{Q~MQ`TppR<#6miXw6(K+8fN$E7COKI1?!4^aimwSTh%W>f{D3S8KNEW+-KE zKKQ?ryYzGS@$PHTas_mJi}59JMgte>jc;7I85qE$HJ}?8{&c%abheg&mJqwjbhgd` zEun5r`0@XLaKMYBY77kBV2<(a<_Gf5kv8(BoX1)-e*FK>@LISREEDiTUY&s;6PEb0-+>V7_>w5C1_V_w<|~EbI?H=Sqz=79KEeM zKmPyktmWA+&%nWu#SqZBx8TSB|1XY!Zrj`nV)nL9`SJfhsQm5y|Nj%efG-E=U?*1r z<4d3T1$#Sw{QvLJy|)JxE9W~~D}Ma{fAFP9_rcDoAYH1UlexGLm8yW!=;1Ve;noQt zg;3s}Tu;F*XWZ+#Hl@|>fpmzJ+xggs<@$2-0=q!b}&fWz- z{{IKbjU#|d-GC|C_{HE$O_|2t^Ye)4M2;Zz*g{2J=D3^1XOh|jrsHc zKZ8@}RGokS|Jxd~Ffi~p?FF5Kv2?<(|Nj||w@v|33<3pcX#=>hsp;_??e8F9iiOgYggl?&F<%YkvIy|NTNI*c06?U`O)r zJy62w(Af$K+}G^QOF=Y4cQ44?{h&I&mqoDoM{$|9@qvI&u$wzuL4NCP1vxdK7aR)V z0WaQyPX!Wq`4&`Dfg{9vE67FC-@e~t{>c2Pb1NtfH2*6u-`4B+zq54)D0{m7?`+-j zU?>~;HZeW;kFn-L_W4Dn4b z$lu-IG@?8e15y1`*``B8T-$P(^Doh`kffbBjA2}}=ANd>mw4{8tC86_Ou;DCAE z(G7MpBrIA_mhc-N=-mr4;PYy5$aHQ6xe|0qH6$#Wmx3b~9x@4k{{Qcs3rY~-0iAO} z(f#5$_yiV#mv=#xJviy~cAWbS8m0&J-yksxisx={jDo_b`$T6e$T!9Zu*WFK*Ps{$ zg)Ul*f}#)h0HfHg)z#-hY1NWi)k1jZgCLJ>J<1%9Y?ALH9xJ z56%CWz@hr7`CoCFRv;t=b@qai3^a#zf^!78JsR+$@gk^f7kKU8>-QhjBzEkL{NMf4 z`cyGzcMCXyg0hA6tzypZDSJUl6x3Kd_)6~J119bZp5C2Pz-mAmVJZC(Bq{GU1$6_! zzSo`$PKLh^zGvmVTUbGMgNheW#|Pw1>(8Y4a`pv?Fa4mtbRf!?^2`Ttc=9mRlP35*`AQRu zCwtu)VTB(kKOcO+6aa~&fZkS6Hit&ci}U~g8{cj|BIDfM3aT!QFJ*DXckTtHxz+>x z9g|oX7`}h+?gbeEDFH!idp0sNFhI(mEVU@>L)|C%-A{Fb%U}L&CcW-ro(%lkczWH$ zJQ=!w9(>Le-pgVLaSOx+SquR$%rrq`MIcvogDV97?JTV>VxA1WEUgZ_o(xd8G9M3k z(WCtTfA>^S!fHMuVSO2LhEMZeP((76N*N!3nB3V4aw1gQ%Tu8K0k|NxoC{LO-*S_Q zfdMobcM-I0?wj%dZg86UzGN>bESQgVwtyMUml)i;KUx0-jRNww%mkSNHn;glaj|6Q z7I45p0>iNr940S8lLSch49F1>Pof5MBj}6_u#V;<0!9ZQf%no4WC7Tj)~ET~LA{mk ztswVw9|8po#2iR11U0R5D#!w8)ajlBr#4XM_#3ER2OAGD+4?ho%X83`7$^B#?t?07 zu#Z7S6mB2C1WnXhU+e`3MDJE`usMI{pLC!TTq|~e?*)fBzw>v9le$0hJAG<7(76>< z&hfimG(KSbzY|=Ib++#L@&7-_U7)k0Ayrzl%}$0=IqM(%t)ieN!jioQKn+=NA_Xaa z2|B;4c_}CdGjxA%UJ9!H7(ji@OQ3S-UvWux_f(Kr_ql@)nLx91%}aP8CO9!NABR}j z-3szxH_L?Xsh}eCyUH$RaDCN$iGi^NtQu0Qc7vVQe2Kxab1KNfZm^@>I>A-0^{LVc z&3i$@3?-4hy&yY!L6thl^5%cV{4J)ST}yt9)*rgT^>FvcQqE=thR$A)FS<{F`ZN%6 zh}BEMCNVNX?F8G$P`V9l(rZxD0UUaeAab|<$KQJ8-~a!RvpyI>F%v z%Gb>d3=GzX`CAl0hn}3|Z;@nWU@-n>{2x8hKtdWdv%Ce3&%iT_4K%a-2aCMC06Gr? z)Ee9K1?Iip)&pPugSIDw5Al&@82PQ1i5_{ z=&}QHOQRJk#Fj??=N8a;JK*97>~c^|0xFKa{r~^+2onPXC`*D0pJs6V z#=zeK66^*yOpQ-MqQLln_p$Fwz*Qad!A?lM2oB^^*5K|)=>t#+)&nXu!1_R?l2B(4 zxIOzHEb=lRRJ?%#x(Duv-d1Svf!cx4fc|t69MDDwUOIqIik=H{Ypo=- zZmyO-cnLm@0o-7Kv{$V!qLx6QmJwMckR`}9y&&y~5(u<(wi%-YVgq>sl3!6upqtPV zsEDKz2xKFu1cDSi&6gM;Wl<-D4=IS6FEK#M1!zI!1}TZ)1yLuqf(TT!fr}3fL_q`+ z!&VT1#R(Tg_rOUQRE&3nLke6Fodp*}poD=^5P>2Qnh@3=2PYy(;RC*o3rpdX2`hX+ ztw-ZakirLa_#V9Q0ZD)|FlfOrsPF-;jqU~~1yE|A25Ox`iXf2H;F=o5=mr-6;M@VN zuS@bExe1gjEIYR#<%-uK;1UH=_JDi@FMB{HL49-o7}z&pmH0EyR*1^(y`WKx?(Yz{ zc5Vfg^sOgLijDspf9q}mC-N+=sPB)Mk9R_N;3WUc`eW(CZiwRlB`ydj^LOq+cCr=` z4$*-+g$^V+vUK-?#$Z4bxR4Q!at_b| zwWUnVC%Rn~Jgg7$JDo7P#M}#tjZU!Aj;WhLJ@k)|^9mqA3`$|oKxql)RZ!ILVmLL+ z`uiiWZ$W&BZ>|58-iO8zXgCras4&lhR6&Z`*Tlq7*AcL1(c(u6w4{D7$WxJ#Ssant z|BNqv2af|a95S%}SoUX}uQ@wJ479?&v*(CIn>0Rb;g)aoOy9ql7S)M#TH4> z>>CSY07W3v0apB$nx(*(E$);k@)6l^p4jKo39}hZ=&5e=kW<66u^U--L9}*x}XC-U}CVf0H7^<&7fU7U|pb7cbYpu(=0rZ-3~kx zR_^_u^gb&&0ffXs<|UPEeA>k(cJx-nSa}1 z*isG9z7U=l-R+o6zXf!YYPTyh0KI?fT42Efz9 zK`$1A2ag3jzTW_y#SLHA0E+215|DUdUcp$xvVrmBVep~jAh8t(x?MR+*t|J{2*_VBMi$9%rC_Xnt>dC>Th z_VMrE9GZV{@V74n^%>5W74@>%b+N#C%(S*{Qs{C_IQRn12@x=*(r;P*Sve6Raw zH`oB{n`IBW?{#0a{#hcc{j-ayH;A#zNBn<>i}?Qzum7NPQC~w8Laf$4*9|rpV!QSE z^10n$4|ju|+WdmC6U^Z6Pyn5vRnywi-2*NJJHZZr>Hh!!|BEm9*B@j40dZjX|E(Y& zb?*J}@Bjb*mz$4pv>xaN2WFj3=hiSy8q9WKIPKfhxv zeGSzg4$v1zkCa5B8maKSzz4|6T2baoeS~@zdVEW zzcOX!kDXx8S${7U4-dn%@cwH9h+ckq2Ih~}pUXwDse0NCHWOl0_f}AJgXW7NRv*^B z*$F-f$ohVnczE#tYhbU`KZN+J8!QD0;ZCqA*7u6MI(uJ$LjQ7!k@n~Ao6z|_sQ<+N zcesdw!|F9CtiaBP*bgz$`Zwsz>Eqo$UP}M}|KIvYu>n-S_CcsSj+e=XLn8;G1?(b- zOG<9OHi7tH0$e>fNtB6)2mHT=MLoprkWlJA-8~f)y4vR;DYpBN_HpZjHTKrOiX|Ya zw6mtQrE>~6Svo+HD>Q|JQ?m8PVz2IhkhBC%wbTFn|8M;nuDztSrE?C7c5uS8{>9(? z9<-|&Y)tp5mr)=NSnB0n5EHW78FE;+0BD9#r1gKPeCx?ldCOX!5{(yG6|j>(9+iQ* zz~GgKttU%Bmv^-uD7oMIzm)wL=n9wDPg`%7vUEtkKGXd{`)2p??u($s4gdd_3U;vw zcQ84%94NU3+Q0VkwO*&|54hMd(3V_o(9WzEptU8XkGo@kw0`S#{?G4nxb;9OQwLM) zx6*~p{~?t_R=_bA#{Ucv;LSA07#UuiF8}{OOX+0{C}V@X68jQ#Yy-660i{5jMWJnz zfPjGRP@Y~-hAt+q10|fzhZy-+v#7lO2wLX;zl)6vv|;QRBmZI+mEw=RZvR0S!JIq{ zE?+^D=-?w;L8tXJ9|4`&0kW_8jR0sOwN&JVV>!GS-BAjftvY!av}>mITdB|sRfOD} z(*OTovs#vN6oF1HaRt>rz8_v}2knXT{m~otzqyiwp+v^ZGL)m7i+>x_Hx~{`meLR1 z$FvW1Uu%BAsC~f;{gjjLL$C#Pfq{sLWAM6AiPryhBA}g^FT#Zx7$U8YNA^}Q)-ZMd z=#Eusy$xE*#L>;r9l_BVtCGc##Q;)ie88c(R)Zl6wr4YIH>e_(0H5K&-%`NHz`%R} zzG0KUC5VxM0lYl9T>M3e1!U7Ee~TR>0|Rv9rg*@MJN=-|GLfL+K2@*;X!|61^Co|b z2xvD(=?_q&K?HQJ*Y90m>p+ch&?IGd?GI?ofv!IR-4gtwxe{~-5@L3a$jxUmc5^yVW9t+z{r!(S`~oj(Y=09oOGsm$x!#{a`#Oacor z8Gkdr9rmIX#OXfVoB9T{Sil#wA9XPUsG$u`kj-xd{+EJJ$*BTuD=yXOb^QXlRt38F z3br^d;KhCLfukzu3FqYD7pu2|4%j)+{DBdY%3;TKvc>?%FTi^FjUm*4w4Ry`^8m0)hfx$OwWu5CYvFUhDoZ7YGOn z2+Uv%U@r3;^z42f4hkz?X_YJU1*u!3Q761Pq*--n0p@j2) z>5UiFAZ}duVVI*pm&`y$t!9hh%T1Lbodqzxz-A?V#JsJ6(Bt zoxtK=3f;%~-A`#BEahzdU&0D1Ymdi+wj@H5ODzXOspyN@MX;cGAq2Xu2Gm*kU&?{F zl~X_vbh;3<v=Z@j*g#gSnFTF>jv`Tsw3 z%R)_bw=2gAhZ3)5+X;T4OIaO3o2~fQg>pa_!oIcwod(U&Xu-{(LxqPGaDZ` zY<$4saChp9W>v7p=2VXTAZ@RYH$T|l>B<3OW30FamGFV!Jv{vTUH?F9g1|t~UJp?3 z>4dT?$M=hA%D#WnxKE^Y`u@0?`vXZK=zNGbJfN#9xo+!fhzasrGJr(B9b_rty!r0ti+dmM-kAOEph5}T&DS6aml(E~QyO5>(`oUjpko((DSU|4{hnzye z8y5cJCAh!a{oyqq^!R_!BIM?C|B2jJ=qm8v;DrguQfM*qMg+7pz4_n2QVCGs8GI|f z3L|J`Dzx|ex}^16g*Wsd59jVPk>kha>!j zG04%)KmM1p7=L^1x9~%VCqwgp#!}924WJF`jHTSo|CvfH$z!7IX_6LmY?&DcK+-%=}*0AK+V67#ISMyZ!-non9n@jbv#(Pzt)8 zsyp;Yx9^`$f#y^4ogOTpbl4gC<3%i74fhM?6QGtK$O5ocAjX+9&2KpP*Ttx?bi1gq zs5aCyFxWQ8GcfSC7BVp~+_X_i>t<0&Ykp9l*8HQMzcq%5fgz1wm_-G2b1y?0zs8F+ zevt!d{KZ#I()f>_1&Qzmhmz1~46RFpWR#a2kKagEao5M;KH; zu!Bt2Snxpxtb4};2@oCfA&o!gSQ>ximo)yEPoMZB{-yCp9!cZZc#y^)ajfy-e|`pr z=9i3(KmW2bFz~m7uG?*V3A)FV`P3(Vt&eH^BHs=^Wz_%&870JB4$rh#1( z@h6Qx^28_p$Qv+y4iK|0r15KfPvaN;mc}1>It_eHFUVZc1I=S>) z@xy8SLM$q2{NX1*@gF+Dkj8)XAVc#HhH@X!a*?FQpa0ky7|IKviZtM%3kg+lC?5L6 zf9L{8;~|j75}xKG9BKSQtUts(84mAy3EINupT;jF3exe3Kkh;rzYy;SaZiR_pc@EZ zn}E0v#KB%Yxa-XS|NmdAf|k`CWQ45gYy1gX*;i}>abVoZUEs3!jYJy1u#bvBXNU?< z_m$>DAO=VCA&$-v6_!pBl^6TDL9r?1q9V|IL;>VO5tTH4jYDbtbr;h3i!Ujp@z-61 zEzfNJ!BDag;?Cu1{MT4iUi{!?V7M!z@|nMmMWy)&$Kl>3Dxmb$a1?5sNaNS|k;Y$q!6c2p?m!xU2x|ja;@5>V{>!IUg0_#9_}KpEW?-nPP2>N3 z%GQX7fuWu|jsKbt+%UcW)hfH*fYu|v0R<8`v_v{XRNz51g$vX)6ad=|bJAx}0=!}S zpP7N7M$6WSg@K`dYa0KdgKQu-1c1|J#0ey8?y^ph@MJig#(zk*K*Ey&q)Zm1ERFwK z4AdpyVk9_h7ijb1K2Wy=)I{n&u6(H1>p+_I!BY0!;7xI&Y0W4T@C8%jLy#WsgN@HYJKqn!VCFs!A`ZuM zAA^r?2ZDQx9J@dp@c6eM2ipi*oc>4oR`-d6kC}FXj8HyT!exD`gcsDVc+CzfAr%-H zAlq$K!CgT34prlm;0?DR7xQ+1LUAsr1tM_p6;tygj_&i^7n&b3bsq6P$kdj1TN)XkcKlKE>~P<26^7L-cFb-JnS7J_g<~3<+~a z28I$D@XnkPKI4=7L6HFp^PjH;_Jj7TzUJHy+P(Uk$@qWwweDlh515)CF&=!x)O`-* z36Ab#2OlvtKVWHoX21uRKyf<{0|UhEJo`Z*@S1f$C_pgWeefj<%-t8?aUW`a$jp48`56oMLGEMR zu79{84o3v}4$wZ*?u!RsiXD8#r+h;BLi36L))$d)fl~+z&ti`RT|WBY^Xi+W4{oMD z=yrXeYA+9({+SHwghF=0cYlbiWidYanwNiF>>to&Tn`WYXJ80?u?uu`OZSED6U~q8 z8y|v(U=KcG;=b5@?%*S~=7;tW7AQf3ZlJz+@DU&PAyBe_Ix#TJ_&_*lH#Vqoygl?! z_owbd2j4L@KM-hs#?gI>`$O|Xri1U8x(_u&659t5i{;`w?i05xymp9{{J7D z#m>L|LT~MZNaF+GKz__vP-ues;lDuFr9#3nl7IV! z_!`y5N1)*2-+l)gSY0?iNYyDxSh zY<|S}{Z_d2rQX^H;AE}v{YDmp^nvCF0^AosS9P*{zX9TLKzJMw9t-z{?*~Cuegx?5 zwTBAa7rx)jVwXN?e4zOu6ZgePh*w;nG(WO$esF;MP^asYo2d^DzLRKvW)C^af${sz zEC%V5AS)j#KnxY&J^{*Fa0|gaxP>RaAA?!QeWLl9!uNae(%+h&F>#-RR5*-rHDcfh zbN$o&5Nzu~aDc%54!H#k)QSwxV%!hPY~e2!B!iEybYpq(Eg95B;OTYaX|7{oDB;L* zi2T6G@mdgEz<%K5=yemxV(N5biSMkF=yqdiPUB#R?_@(d-pTlY1!D=1wJT2vyF-Hw z2Se!>=w3wVph{S&M>D7sF8)F+8Qux+P5l2Ke6G}MJMad?$KXK`%Tj?dkr(fi;L6ex zL1VA4rQ%{=zGFunmtg}nxsC|H9Mb$o1XS;|{x6k!u?}H?D$Jgj^FX&~bjR|v-Yyk? z(SuOI3{&yC4mAD%x_Iz^eVO=+OoWmL2{6Y-L5C-TK)W4%-@N!f6Ep(!p}PZg(pRVN zpDuRy?$AH{+Yaz=KyeI_kHSYF((EZ^x zXY;@R{5`)xt9xn{TL0Gxga^I|1j%>*i0rIYc+CmAN4n=WNFFvAdIvTb+WM`8qxC<3 zE9f>>>+k$6tW2QUE=KtwiqGwGUug#bH|OKnsu#fDbKyY<$4s zr2^Yk`vN(fZ>{|*-!V;aXcR(YdplYF)hoLu+!}^r;0p&ydEmlZ_wa1kh z7`pF(hEY{OW3tTPaZd4o7y6(nz#HI$-nqdN;IYob;0<7)D^vfM-U$ZT*IlZT#TfR& z8)7BMKF~q$;8Eo6+6UoToMA8YA#$KQIuG!-Yz1xJM{y1)bioaWa`6`yAm{u6Eg9=% zU|>KDyDk6?*n)>$OOS_M)Bl$~2?uQqDt!QQ#nB~TkGCEuRSJLMx8eW);1?dCQ;tA& zQR*4^=xOTffB&IZe?j!$0nKlNM&LS<{{Ii}{_sKwtd|F@xBJ-ZLs<;3*9X7&v;P18 z*PF8#UVqJEdg%q4fC3E+AqHT7P6I7fPyr9Xg2r-@w!^fEg6}u1}VLR2YMj+YA1Z1kk}y{>?8K`CGFg2CR_qWB_Hz^WCKa$6X(=FfcHD z;um1(cIElRFX;LL#O`%{0Ahdm#4o@W0Al@soD=l_dgM#c@;azpFF|`#k3%ecz2+0Y z0P6{`*#e*V1sPs~+}Qj=n!jZhDBrzcEOBmrAzESza*ulR3+56@-PNE=TR`Vk@wc7_ zEmCvk09pQe-*ML`Ya~1wUW4{=ZUHd_j=MhD17ffrcYT89e$YYsAZDegW4XpZEpYK%3>yoPqYoN{mS8iiuR)TklIo^D8^W@Es&9-MiiIl&!1~lx#dqKjJVV5*$4yBTl0i=PU zp;Y|!m6iYh^D~snHrJ?dFqDd^f($4*diTa{-2^31h8>`Aey#N41gPgD4N-a&qI4ff z4HrlaC?Mf>3832bf|HAZA?k1z*MCs~0au2_pl+%$^deI5xkCFu3lqXJ?4=nPUIe@X zZ{2g{=)TeI%CigPrN~I*lgftzLHp)dRICq``oAy~0d1E9Wgv49VFV&{!5jX9`85tU zzY+Mv9|2C0pZEn`R5(8I3-YLB@nmtlxWNhPQ_8#!2@8Jl?B)OecU?JNyS-S-3C;+v z9L+~K?uLH28~X!f){iuPy%Y1l9dW6a`gT~MR5TcDuAmRtJQk3706q1nQf|=A78i|AT0JP?+zC1ZwutHb&F+KIaq%aS z&!Pia7~1`&`3*<&lMk>Ff)}81jFX^21{W0;JmXRfil7lC4N(CIEn5JgRTUt#sR5V< zkEl?4TxuT!0|U|HQU}29fQ(CB0JBlYr5-4P2WxJp@oVThK;*&WQUPE#?s2IPVEIUt zajE7v0?0#C$m3FJ{KC*7k>(=;(9i`9n>B!~M;@v20F6||K}V``()fkI!zvoQumFby zG&o?9i;*(hK*7!P(&G}ngF&r5;{sHj%Ad}3T>212J0x50Bn>>^5_5m zcfn&+G9V9zfJTELj>j=fwE!|qwG28S^_uz2nKQ>)3;zHA|Bvf!sTZgudMyK$gi;fr z@xUCDa5+w1K>ut%)n-5+;y?f)O6BEcmFNK*I7$VS}z*x!;vKXWd z#VD4SJYZcgNr)qvL5^Dw6FYqKz|DuZb>);i8SdRg_u15&2X6jB*w!@_6rwjz-gpQX zyZP|u2apkeZrq%G|G~UcshbDx@ER$3GJtg61B;dLg3JBGpo8=nUjNtuD&Sv#3~PQ< z()}f@`3=Wi85IaQ`)(P>3kA?{^AVA|X&iUinvaykwH_#8eW}O9z<^XpHB|AjmI|hI z&jqdeXgJT*@ciFq``0XKyX}S3I_Jjy|NsByS`fLr59E-iol|o_(FKV$NEk58?gDkZ z{$F@_;pc^eT?bY8uk-Ia(D;xAv_<6>^Nr@i0s%pR-Q18SOJr2Ue`P9Idh;a2)|*df zLmYGSWY=0ykY0Ft;qQf`T}M^;uXjB_a?^z;7oKn(;V0m-7yOJ23^z|gb3?Bu!`&M& zHe^)y@C(p(*VivV$?oR6!xJEM3pg(vzI$WB-5WPwz(;^nR2XjWP5S@;|LwIP@>^@> z|Ns9TN;sea2Ti36cUbF`JQ)sy^C!Y?h<(`fb3*mMW`{EF9fVmq0h@Y-n!H3+P zE-EaYJSw+!RGN=)ftpwo~WL~Kv%wP$y z!Og#9OW0pjGk{uSFJi$I*pj=fXFyr*Bq+o{1_d%?WCzfQ9eI{^<05 z((NkH?JEL0gT?nvuPaBd?}LEApcjXEK_E3Gm$TG2i@FjeD+1$oqwQ(y`T&4K#T9h zK?HcYh{TJU08p<6)CYOZ{URUC0d;XQK<(=A7k}@8mj{Cyx6TsAXXE2u2qTOF#S{dC zCqkOvXmtB>bccf06#g{+*8E()v-SsQ@q-ZPc12#WUz?wQe|ZkHS?!?mp%pA8y!$|j zr1|;pmphpl7``23F!|dTF)%QcRJR@|@dghh z@VA2QL;!c=1Q^oz^;rv4JQ>PFK;6n2DxM6@&;NnDl~GLKW;*Kxh!}r3Yl8}?#V5${ z(jMd-P&XE#AEX9tMU|3xe)C#0YU0$gNPjK<;gR z{_o{-P(U1H;%}J;VjL3SZ z^BYjVg+=9s2^#}Lcj%MmBRqFwL49=B7mbG)et~*Pg046C!%udGzG?ggI=P`%y4#fp z97B*O{KOx55abZ>a6)(O4dVl8{Q4*Orynpn3A(=B^{tn;&%_juXI$iG>fsUeW z{Kfp||Nq*UT_8$3^v!Ws(5^oQ@cCBV=bIlgmaw&c<98{2)9w1Dq4qxmXn@ew_07fi z-&{eb0Db9pz0=_fIx(+=6LiomLqlinjf*cpXD+{DEZx`b`UPZP?FZ1XgX@hFene=w z-srBq0UB?3(Q>ksrR6}0|BITl|Nnz$cIxd)lt6a^fM-lf4ZB@GycP#pUZU1e`-P#D z|C{R##@FoKt{+SoTMm>6HXmo~ti913dIw_5YgSOd`~_&?Pwfv_zz8zDW(9{-^Yg#o z?}5gn1we~=xW64zC}C?pr_lWTee1Up&afA+Zi9xXSd0&}{*ULMasYV|0yw{b)|VnK zJcFKTCj{=Y%fzBoPmuG^K*KM-0>NR&K_vV_D_ZgFo9MmfmKX|2(WAOakqd+QR_<-g61!E_U<_7|XP8=X1KIW6(FB*GsG(Y4p^n!?7dH1y(lA#(fw|LzN*qJkZ?jLMTo;M*aV5_Zr^7Y`neZ-+oTE?ha9 zJ$P8Y9TI?vGl4=Ks)n(f4N*{(8-pWW3|vT*8iOK_vH8K@<`ayajIUKdhARAdEdv$) z*L;Ghlkqh#cn%YErwKf0CnG3Kd_}rrWez@MHRfu3_~1VygCQ5lN)H9b=2``Y5-kuXLE&Myt3)?wjZdcs z=*Zz_j|4`rM8ZQ*RC9NF1iW?tne3?0{NORjiH-{0t`eYZ-whh{5_Ev;^5y7uOn@m$ z0Luz6f8rN(2za4&6Liud2k2T*hVcKQC7=a7z8v2iIRr|Wo7Mh(bL8LvF@Aq@kq_y_76b9W zgZL~A44rJR*&5aUfByf!oAKZarsfCi%`X^A6hI>_yr3hWR3MVCWk8xfgEWDT0_K79 zKqpDCfdh)G+c6+Mu9G=B_V6cu0TBBWzaWUmFVDdA+lArNFBgVKzg!q@{c>S|)I<;x zoWDR}`GT=T9Aq!}BzK7y{hqMOF81(?CNKw7*`ejOGtm6z%hUWu!T12bJcA|A(HBad z3?-fp%|B#oK0;551J{xNOEq3xzYdxU0Sy6xhD=*P2Y!Prg$z=HFY^)e1PvG|9A^Mk zw4gOY-7H7nD1q+^Z9P!34YVcB^+mU=uYa&R^aE%;-WSlK0?;7$^uv%- zu=w|W=bw6@X%=`Uupu?0O*hjxs23y|k`{m#(5r|adBhWe= zh3gBGf>HEQk;R5z^p`KT1I* za6y*9YrZU@*IZeGui3I#UNdEJ#0U1eNd$zyF#G~5O}x9kIhub8ln6Bc6f5Cw{wZ6+ z2I}R!7VCCB@QGi*O#ocsfT|hS4V|tBK-zoVI06F0ds{&cf%JZazJrXDfRtccLEL}|8O85<2rb7#t~WHk6dV@b?P0@wf`7ZC2>%oM=jv7 z{#V4=?ZLr(&iZE&ms9fr4eQHAFF-4TqtR-l(C#-`|1v5JJQ*?so;Wk4fHqh%fSUQi zVd3E3siEr+w%JxZdVRnkXQgjCJ4Ng zm811QiB-3Q%E1@%-!C*jU_9;$+Pd~1b#*+bCeq6 z|M$A6@Mx!~@C1j2cWQLM00)urQP9!E$6fz`rb2pMzd%BYke1HW5C2R5VCaH)3r>c0 zyQqk8A1Kx6_E8Z4&8`_=`u?%|2530v`^WAN-G{%Ys0ehQ=spIbnJ>O}?>^BTqax4^ zTIuPc!g2BC#oHHOUA)14vh>UM&)pxsr>KZ@pXhc`5%~U$`C<{Db%+X2IY$w{wTlWz z8KD2uZEY774(SjTp6|E5-)O$Y(0!`=a`#P;J#mKw7(%<>fL0GpWoBTA zL`zS>AO}luA1IaR_E8Z5Sp;`5&-ahrmtQ-A9VpTr0`U$O2TFh)C<1q&KsiSdyS0l7 zPZ^`1@ulu#anXka;BB(-uwdi=kT9whaR-_D{l@oO%{Lf2T~t5|H$h=0!+iiECxMWY z=?qbUIa30pAMQ*6s55VL`>05Chd?}W@%6=<;BdTM`UMp3-&0g%z|NF_J5vPeOaZ7f z{Y%-QffpSY4|j2RSg7%TC}lNDT;2#zH(991e~S0a%dpAc7n;k;BvN0t)t8VNk##q$D~+ zz^PmsCDFL3fRfB1<4gXPey@YOLB2tx8`KCn@jXRFVj?JYLsK;<(eQy24TrXiiimWG ziiEa{3XgP%ihw`dAMwa336kXkdwo1g=rP%PT;Q=yoRf9avi4-R)C8w&G$l=wDC8A z?uP2FM>)4Jw^jNflIzh~@n z<@x(*UGs593-%JwCR(QMbehhe>XnO z{DJvr^T+?qAO0JkH$K*Uh^6r%10!Q&siG=~D!B}z7)v=CK`q{f(j#&4(Z&Z3_d5NL zKHTl}$Les2S<8WvS5}Wp)LWjEJUaM7!0K>`Xv=|;>sF6T*jk>HoPRwrE*`AB*Xdte zeDvX7r@s*D4~PoweiH}{u5MqBnwZ9)TbLLQfKCYB%EWM>)Cabn@`L?~#uBHMEKCdx zrR+OE!$KzyuVezPnbuv&!2%Wp4IZ65yi$Mz%ma-rojkl!L4bi_2Wa4l-{nO2!IOt~ zfCi9G9-c4(6kfefJl$Szj8D8cd-UJ`9VyzL3@-zp{`-$4dB*s}iw#Hr{qOerV|?Pp zGLW(w9Z!arTBypN7@v62376zWmHc9S;zbTfat}!7hbJf&d@w%o!XG55qwC4=@-nLA z1LG4fj6jklAjxg0k`2ZuUWme-#tl*iwxAzX8OVZnNB;fa0XC!P$v@CBhM-2tC>}8( z@Whalfx(EALC%Pi!N`b{!Oe)1A<2l7p~i@lVUiIi!wMr#hC@c23^$B88QvIiGW;{* zWZ*OBWKb~XWY96@WUw*jWbiTOWJodQWT-LbWSC;i$*{+mli`FhC&M*kPKGDOoDA=b zIT`*Kb29Lma55;Ea55N}a56ZVa54m#a5AKsa59vca56NRa5Bs=;bd54!pX45gp=Wf z2`9r96HbN)CY%iKOgI_-m~b+%nQ}6ym~t|hnQ}6Cm~t{im~t|tnQ}5znQ}5rFy&-e zWXj2~&XkkkkSQm_B~wm@C#IYX?@T!vewlJIu$gf($e3|57@2W0_?U4rq?vItG?;NR zOfchQSY*b@u*Hm%;e;6{!woY|h9_p644=$685qnt8RX1CJDwOA3~xEZ)5N`t2)6b` zXNGGRof$s=cV?J%!G*zgk_$t?OBc9WRx1~VmDgMtPBS3H;F1gs4CcueDVB*zX30k8 zW`^cQ#%ZZ0MrjsFNu~y7$w|p+<{-6c*g&cQ9DvlMB$=lgS{fUfnOml%q*z*-n;0b~ zCK;F{CK{xeCR!MP)L=6vEe&oASdB@tS)yUGg>kB>nMHDnp+TCFd9qQ8xp7KrilJq) zkp*sZEZ_!#)L0s%CMTtu8Je4?nwgsgGXwMF zL~~1X19NjrQ%g%j17p)vGmskW<{$zHq{h@NF)hu&!qURrA}P(-*wiS^A|=hx+$hmF zG1bI81yA^-!2<|nj+tq)fvJ&Ma#E^^fuWgUl7)exWuj4{v7xzPVp56`9)G350|;b} zvAKCtszFk!v2l_~s&T5Zp+S;KVq#KCqM^BQnuSRkNDU5u!2<}S#?r*VDAh7C(Jal( zG9}f_)W9Sq(IUmjAlW1>IWf@)pE>XV0-0lIWSnf6W|Ej@Y-pUAVv%f=oN8ubkz|x= zZkU#2mTCx6gTp=W00OBoOiN2PGcrptHZU?UPDxHlGB7Z-OiQvbNHaGwOHKogwBm^O zG^Ns(qI7uGRMHeC^g9< zDb?6C&BVkgEy>i#%*-Oy&@9o^(lEs^1z-AsXEBgDsb;2TX_l$UX{KqZM&_x>#;GQW z=Ef-o2FXSiMrld-;yn!(Kp=CBk`pbA3@lU3jE&4ql2a@bjVzOr%uSM#Q_RiHEQ}LD zYH)=!EPz02%q^4BOjD9m4Na1g%u`a#jT0?Wjm-=VQ&P>7Qw@yp`wJRCAajh9Eleye zjV%*RQ;aN)EiKcGO-zza5)D$56D<-=&GDN9O+g@YQd5kR4H7L)QcNwAQj=3HEi8;p zQxeS+6HU@U+13c82B*KE0R&QGW^8F_nVMpfoN8!bXlZ6*Y>{M^m||d=VriM2Vs42y z-eD;SWRAI+xkZ|BqJ^<>nxSP{YNDlSnsKt3fstjZQBty*A-K%M?H)(~fy^;ZOf)ev zvoJO^Ff&gvHcPTJN=h|PHchiIOg1!5HYE@~kN^UiV`*e=lxmb>l$?@cXlP(+U}=8rz&(%v0-0lAVUcW-WNMsdnwo5omS$mSl5A+1n39-ko@QobVwMb2 zgWF$_6a-RZVqj>HXbLLC(o)h45)F(^O;S>ll9LTm3=EBu3~|?A5W~R%1TrVl!aUK~ z!qnW@EZHE@%+SIzDaFhbL|T}bm?m1{&lhQsECw>i)WkH+D9OS&#nQ~sEG0QP&CDPz z(bB@$Ak{KC#mIt?d%yt%GRGvz+`uf&Jk8R`#K6qh)X3P<#K71*(JaLz&BV;YA_b%d z;sxv^sE`J!Niw%IH%cF(DYv zpcDjhPohbRnVF$kQi_2|nuWQsv1yV)s;RNDsiBdPd7@=%Do72;TAVl);vVxfGfSf+ z17k}QQwuZm6hkvZbIU}FB$HLUi!Uz;7<|(O$ z=4MH021zEyNvX-nW=0mKiD^k7H6YjH!QgmLvrIBbOGz|HHc7Owv`8~evP?BgGcz+x zHc3u3NiiTC?`dh^Hj+hRN~(pWsimQ@nT2VxnR&9Qk(p(hMPg#AiIJs+G2wVmO9O|Y zv1L+9s+oC;X|hFXibbMDl3}v3d1{hHTB2o|X<{5zCtIc_T9}$9g0s7^iFt~VajHd% znVAXLU+@MlkqnTzX2~fAMy7@!V@y(#EiKHFOcK*l4J^zP%?y%K48UPwl$>gqW|3r` zYHVO;WS(r8Y+`C?nVOiAXkwC-Y+?*fE0&ffW=W=L7Uqd*CMITSrskGr$%bjEsbYFe@pC@q5;%VriSrlzLgy3^P++0ew?(83sEkfEt@ zQgW)PX^Lr5qPbC`0k|AVPBk+~N;WkzwlFg?Hc2xywMertF*Y$wH8ln`S-@dok!+r9 zWS*90Y?PFoW|5L?l#*;}o@{B5Y-DL*Y-t8=FB*eNxJ2{RWD64$OUqP4GqW^HV>1H- z;}meg1x~w(rpe~!MyaNtMx(J|YMPmuL29aDim8RUd74>@Ay|!pu|bM?s%es$Nt&^R zL85u8Nou00v4we(X>y8rnu#SSoDEWvEfbB*3=Is7%?%7JlgunF(hLoglFU;r%s@p6 zSdD>+nVF$cvbmXAilK#xL9&sNnX#EknqgX^d1{I|xQsBdurNqAPc^VeGcr#~O-nVm zFts!=H!)5&FikbHv;eyY)P+e-wJ-u%XlibrW{_rLVPuqSlA4@sVQyjo_Pd3-nQ5v; zVsf&fnWed@g|VS!a*~NzO0s!Ua++~UGB})5EiKYalE5t_;}j4p(a_K=#lX-oCE3U% z5!z=nHn&JKvq&~gNlG)dOf@nzOfpV1Gqp@KH#Rg+v4q6Cg>i~;l7X3JibZOYWm=Mn zu~CY-Ns^^ma-zAJQ4&~9qIs&Jg^5wBMWThdg_&Wpk&$7dseyrog|U%|X|gHU&F1Eb ziALrIpyXj;n3QT@ZUAa8Cz~6XnJ1^38-v5gz%a=m&BWX+#l*rS&BQp(FfldBEHy3B z(%8%}(IOF?o(+?Y6D>{B3_(4mWK+{*qZA8cQ_IA(G$TVZ<0MGmCenq*;WlALH}nq+9425Rv`>U*$ibZZU8Kxv98Kk8pni!;}nWtEqrlh8s7#SKF z8>c0L-E5wmXpn4}Vrgt_YL;S|nq-lfXbG~@B*ok`&C(F;<}{<^q%_OqBtr|cR3meP zloa!%lq67REG;!D+0+~yhRK#D#>VE!#^%W;spggjiAg4=<`xD?DVE8`X67c4Hn&Bp zv8ky=vZ1l5k*QHyl4Y`Gnz5OAYKobGrHPq&A~;_df&w!&F*Vi1!qPIy#KhRr&?MC~ z$vDx}JS{2F66`MnLqiKQkn56?P0cLKEK&?i4O2~xk}XryKwTnmyr-I&n;RM%S|p~J zCz=_jq?lP4q?x6fS{Nspo12)Yg43ayVXAS8p{0p|g+&Tzh{-(FGSw_4$=KY))I2pY z8B&IurKK6BCR-*arzIsDn^>lrrhr1qz|7dp(l`;)r!@xEWtNGSNvRge$;N4BX-P(@ ziAEq}Q!SH{48iebn3`&um;@@1lP%1Rj8e@_EDcOkEE6r#QjJrLO~G}rk%_6Xv8A!0 zrKyEUl0hPPEXc^h%reC+*$7lcfy!0$q!bfNGfP7YLqpRPLzC1LQ)3GQ3sWO=L$hQH z3qx?eFfunzOfpI{N-{|_HZw~!1tl+|M6l7u$reeFa5gkHHZx7MOat}%lMIp*%?wj5 zEldr}O-)S<%^+oOVp^i5WwNEEd1A7OxkaKuN@}8sp`m56WvYp38q^$1P&s2@nP_fd zVq{`$kYr(;mX>5`VPQc{f`&!REK@+^D(0q!mdS>uDaHn==B8%Jknl-MGzS+P$tj>(!ywtn+&C@K z*f`BBHPyt#5Sr#wj7<&F63q-u%?&IJKs^DoL{qaQL-W*RBNKxZaGjE7Y?5k{Xl86= zlA36eXqs$nnFwl~S)`?!CZ;4>fZM?a78XW{hGuCdplD1nF)}eRPc*VjOf~=w+8LUI z^Nw+%ak3$(Q($PAXlZI}o@{6gD$xuKOi~Sv%^>Y^Bco)4L{JAgCD|;+B00@8*&@*_ z#Wc~<(#*iz%p6?SC7GBd8CY6?Mk*|lEE7#k%}k7q63s1>Qj(2QjV-`xERB;A6VuX? zj7`&$Qq7GmlMT(2%@UK1j8apR(+nYQPPRx)1l8FVrUqu_rb)>L2Ik2oW+`a~W=STN z7G~f!rJ+%>S(>qhIjBiuWSD4aXpv}Pl4NdfYGG<&04)ze{dgl|BMYNs(-bpfV@o5G zG;>g+#W>A4IWfr)oPH85(hNZ@03&l_<5WxIN{W zq$Z^qry8fFBpMl~nHpH6rY4)4C7Bo{8$i-VqGgJunQ5w-k-3SXiE)~dX<}MRa$2&5 zMOs>lIV5}%4U)}G(ozhPKoy@ksLf?*m~3ifV31^BX=-c=&hG}GA*QsHWTT`Mqhw*GE1~bHZwA?G&BLX>r#ypjm=F#3DYb&Ey>)_!qm*j)WpQnEHTL-F*y+&KB)#t z#)$?7pr(kSd9rzGTC!zgN>ZY+k&%U=v8g%O@8-tFDJF(#Cgw)wNv5f31}UJiJd@-! z{W^9sdo&qlC zQ!NY(ER2#3%}mTqK{?3+l737KKts8SDFzls#wMnqTF$`IJUKbV*u=~PRJDN3NlrFN zOtnljF)~RqN={9-G)T5IH#9X)HUbr7kaEn_B*o0wD8;}yF)0z$7*4Y^v@kbMO-e~I zNind5xH-kx1k?~SPc=y~GEYu1H31F48Ji~=7$<{MtnYGIL_3~H^W zn46|18X6m?n5UYjC4uurqFHics)<=zl37|}N?NLUBB*LIN;EbxGBL6+GzW)|fst9F zxq*>Midmwife|Rw)6$ZYlM)jx4GlnrD9B%ireEzLODz{E7w#MsO{*}~X3)i?>#CNVZKNJ%uXOf~|IJtZ3_nVDOr7+54H zrx=;1q?lTQ>l6zkbIUaIWP@a*L<8g0R5LS!WU~}wOQVz|10&NELvT7w1VyDesF9gy zYHXO6W@4UfYG7iRXlk04lwt^JBbl3+npq|qB`2CDnkS{08X6lWr&^>Wnn6H^ldV^cFj<0R8W69eNEaNTWTVPtMYf;?-iKUsbpriD^kDpu#c@TtOe~BnlT4CLEfXQ-hGmkmp{bcgT53|Ng<*19vQes;X=0jTvV~cS zVWP1CIKC{C!Le?d2C95Pot`91i$oI(15k{lrKW)0oMdTWX=!9?Zea$>_r}SVMk$u& zh87ma$(CtJsVU%k$HK_W#5~Q=*cjB%H8)7KOfgBZG)gi`O*J<+Ofd$Bp|P2PNuqhG zg@J{!QIc_@rKP2*Nm6p68EB*-%@mR^EG$gSK+QkUaDGavabgl^*xAT3(J(d5)G#R( zY?qn2L2_E6fu(VZVM|D9I?zJUP)c$vD}<*euD=z}zAkGLL0qU}$M% z3TlI;rX_)OtFi$izG%zzW zPct&L02S4#pyozOGNfKMwMI~ zCmERB&V7f8d#X8rCFw>8d(@wni+%Dm?c?SfLbXQ1}TPyhM<-*Xu!|h%pwUi z_GAH0tDxDl)D&Ygb2Ct*-M}IxH8s(|D8V0J8k?FJftn_!DUdV|ni);9 zw6sh!0X1|D%}o>2%uJKbl0kiXP|*%5pHmGC(=0*54JnDqAY)7oO_NQN3{%WO<#rmx zJ(ekkptO`|Vg}9(1_r5##wM0&=7#2$mMLkL;C6U&YMO~*ilJGGk(pUiN?NLknWZtP z;cj7JlALUi3{I;_hQ=vLCZKsLb3=0II+|oSR0yHFIlmhK96FF9dOBu*dDJjWj zNonSm2FZq|=4J*dpqb~?Bs0*osA*aXbZjcoED6+{Gf6f~H8Zj>Fg7quOR-1=^&*o} z%^>;DGReXqH8m~CJT(b46_I3UW@KWXm}rm+>NcjCg43XRno+W8YBDH=Sz4r6B&DW; zra24^&CQK1P17Lr+U6F97AY161}VvDW@#o#sfMWrsg@>bpt9RA)g&2G?t*5wK>h4A z14~28WMk7r17jl-LnGr9(A+YlOtmnuG)go{Nlr6LNiQ&No04O7xmQ!F6; zR};&`G_xdQb0b4z)5PS|G(!VJW20146N@w>Lv!dng+)?wiits*rAca1l9_RmB`ByY z&CJbGK^ep_72HNhOEpYRO9OQUOiWXf(~^uWl8h{qQca94Qj$`P6TxZFASKz(A2;r)xglm$iN~k*%Dlar6gOV8Kjz68k(l1SQsWHnj0h< z8ygyfW(kba%phYDhNfng7N(Y|iDpUWMh0e}asD(=n=?5nEiu{H7+iiE8yF;}q*@xK zSy-f*SfnKyrKFh~8>A*1nx&?hm?VSa)G#g8EIAo8gk@=Fnv!f_k(y*+3Tlv)zrWs*)-WA#mpF#9SqG4&5Tn`O_M>*6eDojNHI+{wn$1dG)*%! zOR+RaHBL1Gm+&c|5sE}en>WcY&BVaWEY&Q{B+bymJS8pFG|eb6#W2ax+``Zj;%1N+ zlaozSQcWzAK*gbHig{w1k)?s9g{g_Tr3pA6Cnj5%B_*2~m?fE+nHVG+8(5~ATNtGo z85<>mI{M&zYz$r-keX(mlxA#XVPI}UgoS1B3kZ6!%lmvFOVVXs1YD#LNL7JIS zqM?a_S&FGea$2%+YI15KNIfW@CMKns7@C?S8XKFNCK`fT)=7pbCZ;AP#ujOo&@q2Y zvouSyRLc}I19Q;uyJ=dop{0?5nPDn;x*gK4Nlr61Pfke$EdenC6_v@LZh^TOs9g?H z3r=HcNuXhAgJcT>(DFXbK?{f3rmAkGjKm45i%EMWRRMa zY+(jU44__2nHZTRrCEa3vsjuNC8wnsm>VUT zf|lrj%ND~#Q$vfCl$69Y%ha?)gA@Y;qvT{$ixfix^VF2IWN_V{nwVm4Y?zp4l46`_ z1S%GcO_EYm3_$tMDAB|coWDT1AT=%3#J~u&Mhet5PclokNHI@MOEOJOgp3^~rx+y} zrllqu8m6UK8ki-UCYzfX8yHwxnwS`y8A9eI5)Ca(K?|+S(^8ErjVvrv3{8y<%?wiv z%#1C}Q;fiA%*4#t$k5aTG>d3zYMN|lo|*_6V+IZNrX?mp#-dU{UCG2`GZO>DL<1wE zREsoF22Hax1`Uy#K<2(dgDS>`#;KrjBXbkbU^1w$XKZ1bmSky~0!fF-$;PHeW=3X4 zNtQ-w21cnV$>55~+|Vq^GR?#k9EQmT7RDAShKZo5#6D9a>Mi>0J8B`(~B&QfAf%Jmgq2}hG`BwuAO9K<5RM4nj zvY}bBL9&HeqCt{rN)kBl7+R(oSfm=87#XCdnt=)<^W;QB6C(p73q#OAA-D`rG)ywI zOae8PQw|U%@a*6%q)|P3@s8Z(~J`hEX*uY3@sB= z6Acnm%)tIiN;WpNG)c8EGfe``?wJ`T85$cI7?~Rzf>xG6=8-Kx;cS?kYM275a#B-4 zMR=-3vbm{IGH5&#;&)R^OLId|BGuf$Aj#6g+$05@p3TjYOw9~U z5)Dj@%ni(wEiF=wKn)+$7P$3>;qu1_tJ-Mg~b1 zMwS+-pjLRA0ch05+{D}<&DbmnT!trEnkFS0m?jw;8>N88dDB1>nMuZmX~~HxmKNq< zb4<*P3=&N&lTs|r%t0+BGea{o%fuuj(7GqkI4vk&7=l))85x>@5~6`gngOT=Sb~BPGG}FAkz{0IlALOuoRn;l znrdmD25Q0?SR^Nbs!K?F%-Ax?*w{GL!pssh24HGpmY8Cgnv!CfVqu;N>hXZwW1M7U z4q9-KWRz-_YLaMV019VIgESN4q(sn)B#;_QkQa^9jFZyLObwG$42&&}(+m>Ljgym; zQ&JNl`O5+{$(EdymS%36Y?x+lWSX36Xpw4?l$4xeXqg1*TUZ*HCYc$TnWq`1m?b8e z8XFl{7@LB|z0wRU&C-m(Y1PogG|9{$1vIT_X`F0ioMvKVWN2YxkqDalGBX6LF*OA> zh|`kHQp`=06H^RKOiYuKk}Xma(-MtLlMKLRxOoyNWmh>8zrR~nHw2dS{fLpCYczd8KtCIrdSwTTBI17f*R8xzgrk5ni-oI7$usUr&%VZ zm?j&hS{fTBS{fUsCa0JifZH2pX%WE4%X5D zv@9&i($v7h#Ml%xT?*>lq^21dq@^TVK*|K8v=oC>6T@WFBnuM*BO`NjV^fnvbI>q{ zk(r?dWW3WjIVH`|IMv)JB{kI~*%Z_mO-oHSH%PKDO|vwEtb+ojx3simLt}GOb8}GU zG)gi9we<`wEmMq=O~7THMT(gPXnfK*)yyEp2wdbFC#RZNq$DMqfZFV!GzRLqnWTae z5vYDMHv&y;8d{hp8>bj2nwUe%Oalwhe6^WjGN=omYH4B!nt3%$G6yXLFf&X7hqFl% zXnCi3szs8K8K{Svm;{<=wy;P^O}0ofFb0>;prt|PNofYg1{Nk3Mh3~C2`_^bQzOuF z1v4{9+s4c|Eio-IDajmE_9vw!r5LBABwHpK8W|WH8ki)3+fg82fqFrv7N$vt7AB@f zDJdptX-P?-rmtyA8rVHX7G@TfCaESCpy}f@3v)B$BvUhU1M?K~6hl)}NP8^N#K<@$ zH8CmK&>U1Po2MEjns-=Zlim8c_Win_@ zG$;&>%ngmqQxX$Fa}A)8;OBwmZ?( zz|15q+0@b~%>>;3F|tfeH8nCbH#bNF^&(P|L96;KQ$VA_78b^kvcl9EjgQ!J8AQcO$?k_?kT zOJEEQ%#6TpPDwN~HZZnKF}47$*)TLpGD=A{HcLtbEgd#VvIM6?gEUjiWYB;$sJ)zO zl$dO4mTZ`4W|C%V3TknI-E5wemI|sI%#zJg%#4!_LAen$mzQc}m~3KT2`*a_lT#9t zQ!Nb4EfS55k_;0KEsT=VKz%Y$`^6Zt9uE{B2ija2p0v3#aJ0KJ=(M{s1hl&{l(f4t z%xHIIc+l?3pwi*W;L+jAP|)GZaHGSO!KTxdA)(Wip`+84L7>Z(VM>=P!;UUjh6i1) z3?1FB3_3lo3;{i^3>7`D3=X}n3@m-F3>tl|3;}(v3>N*a3^Eg385}0KGGt6}Whj{F z%1|=Nm0`vtSB3+VTp3dIg+)s-P)sw=~SX|4=Urn@po%y4C}nc>QiFvFFh zWri!mjv1~D4`#SBXv}nF$eHQNuwbSu!-<)$3 zyD}Keab<{@ovdWd=#41+?fz_@I5vyGp=B##QII!B4L1T?8!-O@i3|H2; zGW=NM%FwXZm4RcOD}&EESB8Rht_%|ET^SCncV%GN;L4z}!Ij~|23Lk18(kUxY;uTp29(LDYxrb7iR5=gP2VA4L6$eXa~V`&}6v_CwSs?003@u-}#8 z%YKM@fdj4#76)7zY7Riu&p6=9@Zf+egUUgOdWVAucbz%t%JATzE5nzAt_&Q9AZ(dK zt_%iHw#y+`h6pG-=a4Hy1C%}GkSoIqD0|N#SB48v_LD=d3_qZ3p2MyT3Wp(PnjCgz z@PM*o4!bfGK-n#aT^VLT*=r8FG8}-iuN-z|cmZYqIqb?Ha0FtG$`Mxv3n<&?h$}+^ zlnpY!1j_C>;>s`w%HD9qmEj1KedCBL!y71@;ixNv$We%y8b@6jY@qCbqpl1oPKt=raDcKyj=3^qK-o3NTp1=n z*-MVOGVFk|LFS)?B`^(Whb0;WhjBNJ5IVX%z?5uoOES40%hMg z>B{g1%4Rs_${=zIVy4C^R|Xp>8|3}~C_CkpD?PC=bX$*`PdN0A+*nfD4oj$^#KlHYg9|K-r)?&;VtF z^1u`*88J*K-r)?paW%t@_+-B z4ax%{P&OzJWI)-VJOIiIH5XhNKzPChSB51}yyJo^!x<=kaKV+~3lwu)bY+l%VuOpW z3@%U{anY3_2Z|dmx-v|G;uRNN8TLT&g^R8XPoVh6MOOx%OAxGZ$(6wbiajp5GQ>b} z!6jFQ7AT%^$(3OZ6d$v6vTp4VjIN*vaLkbjETybUSf#L;MTp6}N@rf(0 z40oXT!xdKsma7mfan+SU2Z|l8x-x`7amH0wh8ifIaMhJz2^8dJ5iiXU8cW%vTc z9M@bKWT4pKnk$0~6h~ZhWypczhHI`2Q=oXoHCKi`P<-K#htjP+V}`m7xWSXIyt>SOdieuDdc^f#Mg}T^asBvA_*i1{El_xZ%p+1H}n9 zTp3EBxZ{Q^!yG8yaKn}12o&GA;mYs^iWzRYGKfI2#!XiS8z>IA>B^7-#T7SQ8G4|2 z!A)0&El_;orYpl8DE@HMm4W3J1WVjpt#|-E5j5hUUA!%VGk5vxb4dD1d4y$ zc4gqX1HlS+Tp3KD*yD~XLktub+;L@Sf#Ml=Tp89t@qs(83|FA|#T{3MKTs@i*Ofs9 ziY@NCGWbAo!d+K}5-9Gt>&h?(iZ|SKWjF%GH}1MJyn$kdd#(&3P^@v!mB9vz1Mayp zq(E`SJy(VvC|+>Sm0=4MpSb7Ba0iM%+;e4Mxevh-_gxuupxEKQD?vjDyE5E?;t!8q8Cae`u*4Hr1|2ANc;dv3mTp4Phc)}A`h9ywEIlt)RiFziW{D~ zGE9Nu6;E9m_CWE4r>+c7p!mmAR|cME5UlXbmB9pxJ)XHT#6WSuGgpQdD4y}mm0=AO zA9&`gAWuZJa=U%f#Qzmt_*Xac*Ap7h9gjXt_(3yT=3eJ zp#_R(ymn<+1H}hkyE0sX;uo)78U8@Az#CTv6)3iNnV`dZ2j0TUUlHP<-O8E5jWq z{_xh7f#n?pOT2Ss(1BuycdiT}P@M73m7xZTC%kiISOUd6-nlZIf#L`6Tp7MVF~@sX z1{o+ec<;*K0>u&UT^VwqxZ%Ak!xSi9@!pkT4-{W`@5=B5ihsO!W#IV$!3rN-8BCzq zSD^UC2UmtaP%QA#l|coHEk3$3_&{;OM^}at zDDL>^$}k6tH+*zuI0D5tKDsizfntVFt_&hjtntZ}!3K&0KDjcaKyk$MD z!Dm;7FHp?!#g#z@iVeQFGPpo-#1~hF94K!1;>s`uidTGbW!MA77rwYMJb~gLUtAe@ zzCy6VS62oTDE9d3$`Av^1z%kmTA+BwS67BLP<-I4E5j8ie(}|n;SUrGd~;<`fntkq zt_(g zKU^7>{BUL1@dGkebOuEKbY&3v>B^w-)0M&Irz=CjPgjPPpRNome!4Q8`RU5Q@XM7! z_9!L&tAdh6TS}8GihBW$^jq%Fyt~m0`vo zR|bZ^t_&%ET^VNlb!FJ_*OfuzpDV+hf36G{{<$)|_~*({@ZXi;%YRn}4F)#`2L?BW z8w_p?IgD-$3mDxPb}+gzBrv%#urRwZSTMUW_%ORMBrv-%lrXz7tYCIy*u(6`@POHk zfrZ75!Ggt&!H30-p@GGXVGD~J!wVKS1_o9)1`k#@h8|Woh6Ai_3^!Qa7!26l7+Toe z7 z0J_rQ2A>4hEs#!8HwFeVh#n9Z87qjpF>pw@F=$A*G2}?NF?2|{F%(E* zR}0d&f6FqxcKbQK3y$bjN1E|(`2SGV^XW6Q4IYO$vdfnr2uw3&TN!y@yk7L%mZvW7 zifn=fgHE1I^q*v$QsB(~(Y{`E&4+^_wV?+z@60>%L{_lK^~xKd;UD@H9;D z2ai=Zi(5_kO-Ff$eUlsJDwj40sYMmZ+;!iqWqd<2@$skU`DuDbn6GrIoOyWGp0VlR z@AWRf&hV|8Te33s{ac^*51Ws@N^HI7m$oTtewE|VwD9{KAGUrvUiU0iaa!|@)#0bO zChd>dp!Y2;V55hoQ(Mjqwz?f#{eK_%eAsLv`?lLJ!)yX;x4z+8S(EnjhU&dbQ=%e1 zPJZ$sUVU%#@lzgIn?l!5-zCcos%L!kV$0WGw-YrFc+dDNe7RueI$4$GD68M{kK?!1 zo{VX`yyZmO%NGWRm-yzaU9z>bXxhOkFOOVY#ZqG|t?>GCOcJhUm=!Cpmv4Qc>B^x_;tC|zGdd4BX4w{Z7yB<#FeDgrsS6=Is7kB)# zeUV&8PTp)<^DrU8m7#%wf#Hg?E9g{t2GC{A46iyk1_dIj!2r!(++J36ng2-+9wz{UAK= ztxR;qd3MKXKKhF;o>&n7M=RQX&-G^$Ke}AI;h1LE@NP!&RilLZ`};R>FFhsLA;q^a z(I=|loX~;9uK|4D4j$_0etK@*gjD6_YfrO?Gc3BjLDBQBjb4wt`lpt_3cCsUy} zO+OEAPpA$`ys+-CcgDt0zST2Tf)e^}PcTV*JhjFoh3&M9ctOQM>GuBf8)_#ya;-;(Ksu^C|P&c(?pTXrW1xDR}bY#?OTws?C2|p$lqKBwpZ^? zS;sT~og~kSPp#?+tFG2WPLy9C$8bXT)RuyUKYF+}b4+EPw0cx+~A*Rb7e>B`-&<#xPwNqx~+`=I?G$CSI19KLkhY(2Pk zu8+vso4VVc%-mdEigsvC&0Ek>{7vbMvRcyGN#WsN zuH3&_b8qb>c_YnT&mS2rT(CcT)6eT^N1Iu*%1>;);JADb|7q{PPn7jqX1K|8Fkjd0 zx4b)J)k<5&d5i9KIeT<(`gg>6onfj@#T(0>gq*WW?$<0jpC#ldeN}K(@54IJi_b3v z$Z<_N=Cfe2`>~hoj1Pm0l;`?4&0lE7n_SlU=jYG6JpJFNS57L8cu>ueXrX)Sz3$TP z%rIjPhJM?_{jNbCC(fDNng3e(>+Y7M`*-$zn6dxdtPBos-IdKJzelh7bV=^#%#B%l zX1#Fna+`lFYJw;KeH$+Jyq&y76I#DT$&*%J{7CzhmDSx$GPkyH3e( zeUg#(CNspSSmqhUqlJJHZW$!#i!f-Z+#B zukkmtYMZqz;^f=Y*LH8Zxr*h;3wOJ{BD4Dw3o_G`lO!Go&3LTzGXIuF2FH$_-P60v z?N7~}yYH&5-66q*C|3qhL7(FS&A%KB3<=SYJpBMlC&WPcP&y$N!UyHwRpNzvCfRM> zYnO7KdA3Tbar_qd&Zo&w7DNS3WiNim@XgMU@0RG{Rf<_>|GQ=1=c?~Iq$=s|awF(q zm}=I8ONoLy-;3wRm#n&bZ++u89x1DzN8OuBWgS0k`n&7Vl7%~rJlJ?O^<6~1t_f*A zvaPjswhU{cMv}^k56>EwPkeE_FGzgf`eR&+e_vz~wH7g5>iE^*-}~U@of9hz_E~N8 z*7M?1l|3IA67;d7)lB)`t~AwzUf1h41RPV2d!H*3zOL{?t7Iwbm#7I}<~%=nUhe9g zHBT9ui|0Q-Hu(VC@*O|iCY-2H*E@4SOX29BWTl1I#MaKa_NOXu&Wyl!*}47i&(*|= zZ8$gQ-K6u|Uptyv<$U5*6V%U9Pg-;)Ie71%`TJ(?eY*VCl^<{8B6ZiC6@LA6o@G<_ z-xa@4x2YfZ_PMZ2=t7y)ZG)qmb$pH*F|(%kUJx;l)P5|ZYPa;sM_!ZNSHG3HM)S+D zbM2a2*nZD7;3>b+?ieFohqIDX{f>rM&2pRF`Y(9p52da`%?C)i>?+@xY_cR z>B;W9t0M!yJgnTeV{zX_nGL@@$_~w~VqChuXV)qpHf^q?50%kQe}3%0ayQB7@wtyW z&)%-+a$I~+j(wZ6K*RRW7lO5B%~9t;wRFz9=kR;or6E?MCq&{+s<4f}d~3 zbu3)i)NOG6*f~Fg(D2JuN;hWjciIxnB9PVcw?_8c7lG7OPapbiG5@~i`{hm6|DGp1 zz5HPFz-h~F&I_Ar3YG{?pTKy5uX=s0fnT=OnE=1_`iBqs*B#wlX8e2k#%W949FN_K z`YXO&zA>$5p&*HKQqyOY2-w)!)(csFK=yS)8o0h zdUB^w)9(p44HCYa>Pl3+)?Ub#Zho&w;Znm>o$GPO({&x5SDp9DoV$F&eCzw{(^E3p z{C9nMy0acii4MWE_?cXDZjBQT1-xQy{dBH&^52iRP$=!XuW-(6fK9hz0uPyiu^IR3HR;|z3*tcot6}k6mH~efr@qFC%d!_m%*N|p!fg`hw<{Y1O z-futqANB3iWbe&=(vrb2YrgHX<7$E)mA^R4PN-TvDfk)l*ls`P&3_HExv~wZuQ-v?`-rx z*L}^le7uJ=uaX8Vg-o)wn!g`OVMj zJAdNjhQxC9&JDk018eV?C^mFww@FIHODccG!ss zwBD^eBl3%RW6nAC?$z8&Z&gb+-%|HXm14+#*j;?~%kS&^e<*Z5ycZ~Uce;yEhTQj{ zAK8-+TF+m&BmQ)Y>(uYO%eA2@RuTZ{Le?O4-2DQiV` zq1f5%Ebe7zKdVP9dm?+sVSTl|i|ra&j+mDpdD)+EP0`tZ#$#1d#HYA^T{H84+fH+- zT>j7=%g1`;_o=GxrA5ERD{>C43Y)C|FK5x~D-w4LPjh$v+5G$M_M;m#bLZ?ldgNEc zbu&i(Cs|*(eRtdS&EGX6SL&(4`WAz`Yi!c?sN78VGEF?W_RPt&3^&OhmZf6N@l}7N z*RE62WnHg%XE$FP&z^bPG**5(6DQv`b?F>I$q(_jbXfi=HGH39vx_n8+T>s7lAd0l zp}czMantZ`kHpMgMqgj*DlxhI6u9x0l%riG7kD*B~CeHcDC5;UmSKLsWxZvxF%>OFJtJ9A!UbkCZJv!=a`r?9# z^R9lJ&cJ1mVmo{P)}A%T6}T>ynVH2tSrfa*#b`sBvBOm*n}zbCnu7hZb-4P|&q2an)Hhf9avex{g!#R;^;^qdA42OW-aAkDRJcI9R1B74J;BeIn#AsI%U`t7)iMpF*VIkc(KH(WYMCi znRiZ{67~K6u}k^J<&CqpaPNL$QNj~+ygS+FRc(BPNwA%=!0v?Xpt+s%Kg6HgJcqB8 zzx`XKFeoHI>Qse9D4hhQlc979gl5&|V`h?K zVCZ3BV7MUcz+fQaz%W6?0aUFr#0a`GEY5`B4lxfnzd_KQVTqtS!wIPT2SIm+5+MkG z28b4NXK)cl@H2$n8J-~VIYitUT14C#R)|2%J|p7J@Il0#K|~b7w-9w_*dq$zgUov% z>dp`&hTu1dxikDh;wy-|Gt3cpXE-1Z(f>r;oqU7!`Mh78Q4f6)NrwXH?u79;mo8aHzU7=%~6ggs8eRRH(W$ z%u#h`*r4jpa6{Fd;g702gNB+rgO8d!LxGw*LyMX_!v-~kzptpdGyG6<2ajEGsJkng&cLDN&JdvG&M-sEo#BBNL=Kc^K$s=r-<4geQF9GXCcZ8? zW}2IEz;nkW>%?C<&oYzr5}NNfMds=nMm5OD@D2AtRyf)b{;P7p;7qf+`yOOkp_|p}|85kILWV$jqGB7ZJ z*ncuz85BU4GcYi)ys`3gjP{dU64oZcG~cOy>8)AaN7hYxpvSiAsYbQ|Ps+U?A6`ue zZA(a56cQNHut&H-^yYTm+He)W74K&qIHuT{&arfI`p^42zxu53wwIZ^QKMT~#_GY9 zf5k3;RgKl$LH19&KTY2?Ye~67MWOkPX;+KI0g44_4mAoiRrR|fD#6p(uvJ6!`VR74s*;9I4>VGJQTubIJ$U%?Z)pn>9;%I@NjH+Ic*1M=dmOM1H+3fSB6#w1_ltjAlsF} z31l_{1A|PKD}zRsD}%^X4~7X?hFTX5pq6I zxd1(Ph8cS93<~-PxfRnOX712;XJ9aJXXr3M$Q^;oNf^2_BpA9gyf8$_f!uOK(v6|Q z$erPUkvoHjF+vXH7LeQxV|NAx6L*FcCI~r@TR?ISrtS$ph8Mb7*G91W8q?Zm~cLo7JcLoK2gdE5% zAU{|HxHB9GaA&v>h>!!h1tj+($ep1e*qxyv1R)1<3rKE8s5^r~m^*_(I6@BO7Lc4r zgge892zQ1Dkq9|hxcrE6XK09aXP6L!kOR2|G(S{BTQ$Vz_1H%FkZRWtRCc~XU!O4MP zONKjxfwKd{o(y*e1{Vj0BOq}%2Zjq7?hFp@4h(ld;sOo~JqKMG3Ah6zFr3>KO03GGABxJfXED(2KxFH2;S(k#c8vAnw5M1=J3daA07Oc4shCO-!@4%1)a;Jm?LqVoHLxX|?gNmj*gM*?2g9)gfRB~W&(R62+pya?1py|$_ zpzOd9qv_6YLD_*JL(`q1LB)YVMcbWWgNg%#i8iR-cVKYQc4rV!bzlh5c4u%i$aH7;k>$>yknPS; zkmJrUBgdWLO|CnGK%P58O1?WoN4`75g93L3jzV{agd%r_jv{x4C&lgz93}1yDW&cV z9i{FJFUs5*1j^kR3M$+gW>mN{{Hb(jP^fZeXsLE*SW)fHAW-YhU{UMNu%OPJ;Y6J~ zgGqxsLqvl+!;waJh8K88)=JGpKa9GkA2kGaTr2 zXL!-+&XCaU&d|~A&cM>^&Y;oj&akAja%Y$`*`49Q zWOoLasqPFJQ{5RpOmk`oVud?H!Af_A9V^`#F068AkXY@`V6euWp<<0Y!-Tc&3^&%gGyGWR&fu`#ogra^ zJHv_%?hGe3x-$rDa%V8u?9NcJ*_~m*7I%ghTih80wz)GzY;$L5*zV47V!J!ThaK(= z7CYS;GIqH$Y}n<_@L;z)gT@|rhKRlH3=8(UGhEo`&LFYhogv_WJHw0v?hF?Wx-&=| za%TuQ?9MRbusg$rBkl|mN8K4Bj=3`|IOfjq;J7=3#tC!-+HQ3CQ0Yr#pkhZ+C`--|h?#{to@z0&%!#{V1 z0tOF;9Sj}}4on^l9ZVh!0xTX35iA}I4_G}IG}t^CHn4jz{9yNB=-~8VxWMVbkihN1 zu!7rz!GhO=p@G+fL4eUpoPe_5NO&*^NJ7+@NO~|tK-o2t9t;bh>?4vM z3@@N;9w`q711X655GfCa3MhMyln28BDEo<&2Lp#RM2(KL2SWgqT_WwlFayfoBkjTP z0Lo^O@nF!9fvES9@n9%`vZu&+FzkS`@5p#CFvvpGsK|OSctF`XvK|Z*pzJNO9t=02 z>_4&|3<`1(^)7NA3>i>%kDLd?1}OWAoCm`XC|gF}gTX-_qCN#ggRqzf!y0)Hh6_;k z7kLi`2?dB68wC%B1Sq>j!GmE1lzm3QgW&^|Eu!ebV4(<6AEW5O&;VsGQS@Lq0cF2Y z^k5KBf~YZ3@?eO7vTKw)7#2X;N0dAmUO?GA${q{`$`JJ-${q|AQ1%>U4~7F!_7i0f z1`ZX78XXl6h5#tLM8$()29&)=#e?Ail+B{*!JwfEQSYPb!B7BYPf_(?*a2nVQT1S8 zP=lyZQS)H%fUf7Cn}6x1Q=UDQ1oGN9}pbq|IOQ1%sd4~8F5 zwv2`cgM$V{eF}&MVNm#McraXmvcG6}Fi2=Z)YxcxFeE_PEt(z-E1>K%njQ=vpllH> z4+aY@i24{U4~7OPdx@3@!wD$+jg|+4fHp*piM9tr1e9H)?ZL1B%08m)!SDjg=F#zB zFwlXh57F^psDQHP=y)(3fU=+HcrbA2Le%K!dN2e)*(JIj3^SnYJ-QwY51?!oJr4#A zJ&1ZAJr9NgD0_;Y2SbCPE4Un3BIwF+0?K|P=*l1<1Q9n8a%G5svTKA~85TgQSB3*n_7h=O1`ZL38XXZ=h5#tLM8uV029&)=#FgOz zl+7aQ%Ag?%QST$_%1{7hPZ4!x*a2nV5p`u?5QC^u5p!kmfU7Q1%sZSB4)@wv2=;gM$P_eF}&MVNjZpaAmjvWq*-y zWss1BsIifBWk`UsTO?f>RzTTjBwZOkK-nTvt_&7Z5cM%qt_%%O_7W*qh7(Zs8!1-? z0cnUD6KPk52q?Qo+Ld7elzl|nmEi@H%_HN=U?2lgA0p$*PyuDnk#S`>0A)Xsab@6; zg{aYyb!7;Ubp?;rfy)0CP&TOiKLcfh%Kr~gHmLj;k%OoQmH!q{HmLlMfwIBnKa>qB z|Cd17pz{9&lnpBX-$2=*@?St6VkW5kH-WN2<$nZ}4J!X@plne2zW~YxmH$VeY*6|C z0?G!J|2zs1GePCQ0hA3Y|3jc`Q2Ad0WrNE9IZ!sJ{67F?gUbIWP&TOi=TL;02`c|} zplne29{^>8%Ks858&v+!fU-g5{~jnCRQ^AJvO(oPixR|4Q2DO`WrNCpA1E7C{ue;m zpz?nTlnpBXcR<;o^8XH$4J!W`lp$t<%6}Co8&v*#K-r-3KL^SNmH!ivD%w?NrzG&~qqK-r-3{|uB3D*rz~*`V@YL>*!#sQkBpvO(p443rHn|DkM9`M(6p z29^IOplne2{|3qimHz@75HmsLzX_BLD*q#(Y*6`M17(BC{{>JssQfvD%&w;W*<^KUF8&v*3fwDp6KZh2?Oi=l+17(BC z{{Sc(RQ{Jh*`V@&29ymd|Mx)Ipz{9#lnpBXS+pT$g35mlC>vD%`#{;C^1lGe29^I) zplopY4`qYO|2t4NsQhQpftU#@|5c!DQ2FlxWrNE994H%9{!f6iLFNAzC>vD%-+;0~ z<^LZj8&v))=t9h2BjL*60%e2B{|qP_RQ~rs*`V@&1C$La|F1yVpz{9*lnpBXW%M9s zg35mfC>vD%r$E`D^1lPh29^J7plne2e*ww{mH%I$Y*6_xp${<=RQ}sQ*`V@20m=rI z|1J8i;JFb{`TqvW29^H;1`u&j`ELScgUbI1C>vD%*Ff2z@_zx84J!YSK-r-3{{@r{ zD*t&5A!dTge*-8RRQ`uR*`V^j0?G!J|8t;hQ2BoV$_ADHPoQj2`OjelF%wk&>pkinV|At1Ih-K|2|MQsQfR0vO(ql z6et^1{_lXYLFNA)C>vD%Gnhck1eO0PP&TOi_kglN<$n&84J!X9K-r-3e+!fiD*tal z*`V_O50nim{}oIj=7Y+A7bqK4{%1hhpz^;5$_ADH8=!1Z`F{n<29^Implne2FJlHV z6IA{?K-r-3KLyGLmH!=3HmLkx17(BC{|itysQmu|WrNCp33G^LFNAnC>vD%pMkPL<^KmL8&v*_SU}7KmH!q{HmLlMfwDp6e*=^aD*u;2*`V_O z1e6Ub|KC8_pz>e95@IH({5OHJLFIo0lnpBXYoKgU`M&_l29^Iuplne2{{qSemH#|e z5HmsLzX6mDD*r>EY*6`M0cC^A|2a@LsQfvD%&w#Q)<^LWi8&v*3fU-g5KZ^~-Oi=l+0cC^Ae;+6tRQ?x0*`V@&3X}~h z|93#ypz{9?lnpBX8EheDg35mtC>vD%dqCNs@;?X429^I4plne2zXi$$mH#)OY*6|C z2g(MO{|a^x^Figm3zQ8i|1+R$Q2E~jWrNE94Nx|y{J#QagUbIOP&TOim$8SK2`c{` zplne2p8{or%Kr{18&v+UfwDp6{{<);RQ`W~vO(p)gagD(Q2B2IWrNE91SlI+{rV0v?PP16tg5lGcz;LWtPUtkTdv<(m;oz8yhF5f=*4bv`8~aw6shz zF-S22oiz_RC)C6=InB_>5_IT{g^@{Ok~!#Bvcy!QG?Sz>0}IG`qXuc9d#+MUOp;9v zP0W)GjFSy5O%qcS?kZf#XY>;AL2EAXvz|11a$TZnJDJ=Z(0Q%Kmc~ZrmPx6Wh9I|qaI#5CGU)Cw zb0bqrGteD@Mh1okCW)5j#ujOyi@pnPi@vnrdNWo@iud3Oac?B`L`~**wwM$TH2s!raK%!obuh z)!59yFwxx75OfNBQlgomk*Q&_ks;{Jr4&=p{X^!7W{D}Lpp!X`%oB|*EfbRr%u`d1 zO(ADegX~E$O-xNOOSUvKGD-!VYoBOnnv!H_WMOD&X=;>YW^QU^YG9b0W?-6}l9XnV zoRVm4l4xRTZf<0jlA2-(I+-}tFwGF;Op6qAqm(35GgBjT6U#J%WV6Jy)Ku`tkZ=4PpeMky%HN^f{w>G z1YOXZXqcD?o1SK{OiTtj4Rl|nG3a16QEB*m}D9OUa zFgYbLDLDyrl|@pjMWUgJnW=e7qLBgQOkz;D8G<6qz!G$Jt(kF}v9X1jfkjf9S!$B0 zQF5Z8K~k!jsez?=nuTSuVJhgnG0+k7pd+G9%+0}f0VbP*4ni_YF)=qbGz487Ws#I( znU-dhmSkpNXqudsVr*z;3c8#m)jTB`l+IGkjV)4>QWHTp?wOdGgWLcaw_QH<}@SlF{z*fyeyJa zl2S}klPrx4EK*D@jX|eorkI$S8e5v0B!X@cGcX08SDt8`oN5WWTglQi$-p8Bbjww0 zQnIBH=sZXZ&@F@}#)gI#7O9r0CKg617N(}gmKH|IX~qW7vl&6|G&D#}G%`;z1YK{I zWNDn3W@u)aY?5eUkqWw9$u!y0GQ}dv#K^$X!XU}O6m&vml1Y+9njz@0Cu4In(9v1u zMixc}Mo9)1mT4wN7HO%;DM==V$>x@zTlEZ53{ulT$9kGun3-4@CMPF?ZZI`80$ul; z1iJIi%m8!+myw}`xrMn!Qle?HiDhyc=mNG>!zA-m$oXSQNvY;Z=1GYL=7vTlX(09H z$;KvzW@)JwNhW5d;PdOu)67hhOjA>h&5R9_Qd7*5EI@~6rhv{tv@}mN1gio0*C;VD z#UL4U8k>QcshLGmVv4zmi8&~_rx>RsCL5TV7@L63EKN%Vof`+bCCbv!5Omv#fuUiN ziMgdoQmRp+Wuk#WqN$-}qN!n`X_Bd-k%@t!Nt#J&iV^7OI17W6BqPHl6JwK9OUpz{ zL&KybgCsM9v{VBlQ)6>8V{;?Wv4<9*qlZBz7@C7TYMhvwmY9}onq-n}m;|~a&&13; z)jTQ9G!1m>qG4K^d2%A?AZd^vK-f6R0-T1DL6uOlX)@@nbPJ;-19RgfV`D=LljIa5 zGebiILsLsbbE8xf6H5z=)FjiiG*dG(!$iYWL$kER6f<)pQ;W3ZBv83xYGP(-1iCN^ zbXJ(TiG?NjUT0Hd;}m1FG*i&o&Bg|npsT=4EzQzEXPGC0uIV;32Ho;xX#u)4%G3~4 z5++(2r6#3WfUXu#OicnEm}~~RqR-4A5p+PBfw@UqvY}yW8aO^IEE7#ljm?b>OpJ}w z%u~%$%s>}trWl(WCxMQQ2A5H3=0+x_pd(g|O^l5}N4KS!q=G{|HPPI_#1fouLE&Lx zV4eiJw9L%HBsDb!bbeZLqOpOYg@G9;;eyhPkp<`;3)3`XvlIhU<7CssRM0(irisQD zX33yS3Czt6(o9m!jV#SmERrliSB|Bonj0CL8<`lUfKHn<1>H4blAN4oW^R_4nw(-{ zmYfJW+A!53#n>EF$EGG*B$}s~8d{hp8W|X-nt_hDOG`60OH4JiGzZ0ng+-!~v8e$l z4J26@8CqBvnWY$kS_hzGTn$q#)67zhQq0qm(h|**LCMF+Alcl)0CZb~5xCq3`P0O} zEHTZ{#KCeW@u@UYHDa|1Ufa-!onyObd;^RWn!{vs-c;AQi@TcIp~7Q#8d+dixi{OR0~s+ zG*Ho;3c5Yo+|n$`Fx4Eja~rLsw#QQfit>ih*HjYLbPexjE?S#>6ypL(u)T zCTYng<|!#=W+`cA$tEdDsfHE5#x$In6N90(6{bss-p`c8eqvgG2)hlN8fbOLHR=GqV%}b2HF2 znPzE8=4OUz7NF=&1D~IqW|nGUo?>p81Zs+=n58Bem?fH7q$Haqnj5B>Sc21)A?Sjq zG$S)ZOVcECv(%(i&|#=4$%)A(hDM1-kUL~S;hAP(l$4rgoNNxd1j#%NT;^Mtf|_w= zmWC-wW=UzLpj(uTOcO0kEmMq>5)DB2vY4iUPJm5HGEOoyOEfk#GfYh}v@kPEHAzXa zNHa<`O|wW%PBKX~F-tKwNi;!q6fyH6<<4FgeZA z%s9!?*a&okrKLIO=629c>;@L*hL&cj=Bbv3#%boDb1982j7&^S4M45WMDWSS7Dk5V zsfMP;#%3wti&!l|*LRp0nj4r~SQ@9LfX+`f1l^|$Ip-A=PN3_=42{x^Q`6EcQ&S95 zEKDsx7aSOaE}u^Xx516g%q>zt>BTT9)yyQ(BGDo(+0?=;&BW3m&B)Zq(8$spRMsUL zm|9vGfUoW{NHYaFDlsj|z|zbz%`(L@)eLkAN@|+1agt$@rEzL%ilwEQg?W;p8K}t! zI@HrNF)`W1*fKfQ#4OD?$s)zbD8<;o!pt<)%p}#sG!@hoH#Pv>x@uw!I%e9$B+<|? z*&;c`%pe66cc3dZl8jSRjSW(aOp=V#5-k$VOpKF^jVz2o*C3f07#gG{S{RudCtIYY zn3|-f86+AdnOPbeq?(!<86+lxN-0xI1EVy{Bnz`dW6(*o$%!V$X5ez&2vq-oPK`B8 zHa1K(GB*ZYw3n1;M|Xkcn=Y?5MW0cs{08JJjtPHRuIFiJEqPBTk1Fflbxv`98FH%+z# zT_KQSm|_SzoZ2`M)N8Xa0ChML%|RDorKYBsfvO`zlVk%!6XVom)8u4O!3H`+)+9OA z6xY69wyrWhC|8G>rH)D%!JFUbgW3j+faQ`1CaBLh=o3ky(G zCnqHu8z!X~rC5Njy-&6CIWW@u<`nPO;ZWNw;hlxksYW@%w;ZkA$X zkz{FPYGRRW25!omrC3^;q#7j~ni?3UrWje88yK3Tnj07;r=+H(rW&Q0nVOk^?h!LH zFt9W;G)b{AFic4`OioNpGdE7NNHR}LG&M_3GXxbpNoK}|md3_ONvWph=4M7FpzEDX z4M5H?0bi42YMNvOPP0jg=B8;TDTXPQDdx#(=4qy;h9)MaDW+!0$)LM-lZ+A#%q>z4 zO;Zg_EK`ypXV;p7E?hIWFf=zaF#wIHBqkagq$F8_ZeU6@Hh|oBmTYR6mTY8h2EJ}3 z#nL1xIVIUJ#mK_aFg4l2400zU=t@;f(?mlP&{^oFsYb?@DQU)LX=x^)^pOI&D=0M) zR1jN&PIFF7v;bXnW@%xVY+;<3WRYTFoRpMiVPIrxXlMw!d(8zfm8nwXed8k<{~rzN>BzSX~w1oW}tf{L9O>x#5e`0 z7&0|THAptIG%`#vH3HopW1ePinqp?2WRjL*YL*DPggiAR$s)-#(Jax@(mcr|#n9N$ z%*4PHbPu{wvT2Hig$d}kQ_vtxlBtD>SrX{@e$X8uhH2pNHZU_!0w2Pjk_NgZ%@TBB zEvT+EOaotAV3eF>ZklQax*{vp5)}L(|671gOt&;LuuL{JvP@32Ft#)VHT?{dQw>0O zWPsZgAa$TCa4k#|Ei5cS)iUU^P*anXL?a_3&@D>IMkz)~X`s8AEkTz!CtDgCfG*}W zF-%HL1zi?xXk=`enwXqsU|?pEW@2V&nVM{1m~3nYx@*iV4b+A;Pd2qk1zmq@Zkb|a z3F;Z97#bK@m|I$yrKY8snt;#12fM=*bi%WxxtRgz`eAc3BO@b=w3JjMW3v>{;qFE$ zDMl%YDJCWsDWF=;GAR`_jALn*nwDZ>mS}96Y+;g;VwecJ#o7{dJzBD*simPsa+0y3 zIjBMewZu|DV=kb}YLX1n43jNEr-qv+8k?A;fUf!lyTc$Y#n>_>)xtQ{ASu<{Jki`T z*&@*dG~AYIoRR|KB&HfAry7H9YBEZKw7JYv4O7gFER!ru(kzXW3_yd8riN*jiKc0$ z$w@}W;ISEy|BNltl2Q_l%~Opm(h@DqK$jaBCz=?8u9Y;jOi4|&G)*zGNCu6wrGc)8 zFfvU^GD}PbHCq$Y3=%EO3{6c^LAN%fq$PvyT}v`C1l`nPYHVqoYMKg8HOUsBk;)Vk z&?(*KiD{rC(9=vn!zih#pbH{QQ$UG4HO0itz{K1%%?xxmwXp&CUW1e*L$Lor?o3Td zOaTq^S|*y9rllF1n1c@cPO&sFNwzdeu{23EHb?|rQkarxl9HNamXw@il4M{G8mcfd zvotXUb_ED3abmzfFZ4l(0IV-wJYV5vz4#z_Wg zrb(vesc9C*pvnT&<}o%jFiuJ_OEt4FFfcYZHw9gWmTGF4nr3cbkp}8JWMq~I8fH#RHA^;1OtS=aYb-56^{knJfk}#ynYm%Ai6JP_rkNO| zrWzQh7$%z}ni?e;BpR53@5M3%UHWBgl9CJ_zX18e95gCtX>O8~Vr-NIx*iIo&@9;^ z)!5Q3$-*Kr)z~D-(8$=-+|C6jOsV<1|xa&@I8npvyi% z{XcVyG}B}ga}$$PQ-d_4G|;W}hGwS8MkW@fDTbh{na$0TLANcMnz8pnPRwo@|kvWNMgXZfRsVD~Bj|D#6AKei7sD_S zR5c`-nuEGDMxd67nIY&JW%FcEmpw7j#LV102~>5YnHqpD^+*EUkOdm90^RbOnv`s2 zYLJ|oWSX1;8X!(fvPiQ?NdetRm6{AX3*R!$FwMXs$ucd`BFz-k&Q4AQ$x_z?Us=HghBpHP6S;%X#^_83@yylK=+538W~ucTN)aGhA2Q+Z-Is# zjEpUeEK-t_%#AEeQw>rR6O%1K{W+sVvm`SEQv>4^Ghf1ogL)(=1aB3_x=i7RF{4mMI42mdTbz1_tKl$p!}I#>vKp7M2D{ zrlv`Wkb8|%jgu`blTttzEE^{#rKF^pnWTa4vQ0@cOG!#g1^3HAW+xja8k?J07^fu} zS%7Y?Pf0OMGD^0vOifElG&D;}0u8konSie4PBFAhF);yM)s~uKWM*NMY;KuolxA*d z2%gPJN;69|GD%8INijA8-LPP0Y@TdxoMfH|8pSg+G6h|I0&2fl8m1*#rllpCm?ov9 zB^xIv85$WGf+jf(lZ;bRlT%YHEG^BzlTV2jDaNT5hRK#G;1Nu-L=%&wWCK%k!_*WL z3o|3*M1vGFBcnu1Jbhn5LSi8k(n=g9bQ~3=GT-QZ0;4O_LLoQ$ZJLfkp^Tjg!m_Eey>PQ$Z7x zW~pgrpx(2&L6TWoT8eR!X;P9&l8Lc}g}F(JrD2MZxdmwID9H?TqpO)gim`>6g{3KI zM8ep>JjKi?$n5fKDTXPD zpw_54=u**C3q<<>bi+(ivaw-`MN(>FidhP1c-Fws1axPXaf+b{=t}HVvm{f~6eCN} zy_JcHAY+WoLAOArBpD|f8z&j1f?B91rbY%9W+`c@W|jsP#wLl$Mk%Sr21%e{B2$yp zWK$CZ!&K1V9;n^{B|&pbQ0WP3@|vVrB&LC`xHB{~F*h|c16@LBXlY<%m}rq~ZklLm zlxCKcY-*fhYy^t>MAIbmRKp}ggG5VE5p8Z_W@%&z>eyQvTY|=UEmIAWjSN7;=P79x zsphF>CKg7ZBEi@&(ZB?hEe%pFKy6`*WV58?M581V0~1qAV*?XY0}F#xOJifuWj7Yd zCPs;%!S7VaoGK_kS{j+9BpI22E+kJ%G%`ptNH#S$Gd4^#2lcSi3@lC3%qkK9<_OrA?ThtP$w`gF~!m>#oQnf)Q-1EN-{D_HUsxBL3bG%CRv(* z#=p%{jgw7GOj1B2gQnnioS~UfVhU&;(99&!z}&znG11i2FwNB5FeNo5+0YC$-jHOL zXqak}Vgj0)0=F5AOiT|u8(J8qCZ(jMm>MR7Z^t%FHZ@8$Nj69|G&D#`HZiaOO@bJKQc0qPL6SwHMPjmn zSyGavsZnCGVTySgsHJIQVqsvOW|(MhY?uV97Lyax%q@&f&CQHJ0}qzq7H6_~qNSyY zNvdHoXh0$@E!7Nk{iC_DacYXOk)er^v7wQnfrV*evVl=bnuVpAQBpFfOfv@Gv6Pww zDn1MnEkJk68>ggLB!h;;z+nwa$H|~kW20mfbF-AxL<>;U!YtLyz&sJO3M0+H*wQcw zbisO}Wooj8NusH-Iq3RMP%2DI0(BwH&5SM0Qw$7DO^i&^5);i5%}r90O+feHB_^6A zT38wwm{}U6Sy-ARnSo}$6D>e@jv8AUrx+QT7$>GACYzfXr5S=UoMEc5sd=iUMUuIZ ziMg4Pv7te73h0XYM9{^)piw!{IHQSKT8brTOduu6!ZJD8(AWrcp`f8TXw3yES0tNR z7#XFenkHJNSX!olib=C%a|_VOT#|u>g=un9l9^Gek!6adxdrHIaPw5~(2;41k)f%f zsYQyhk!hM`YAWawCS!BZU9{$A7AA?Hmb^iVrIER@rHQFwVzLG3w!*YDi)3TNB*-1v zpl~!xO#uxmrC6FLn^~r%fJ$>y3rkZYW6-REQKDILTAHb;Ns^&y8hC|=VQR9uQA&!X zd7?RJ9>D-yMq8K~f~rIlbI{es=Ah~|$=t{&B`FEicuY-JLOJZ^|=u&l~R6_%UL^D&+?dz82i79EOhUP}eCg41jlAH?4 z#YrZ~pcaLhsi6Vr&hpgc6wo!Hsb%T$Zx zq~sK1Q!`6*Qws~jG)q%+BT%>)r&)ror8F}$GfDxKa7LizCP|QWE+9V{fi5UbGY2&! zK((ux38;OUmSmJg5jTY{Pc zhDJuI=4q+s=4nZWMxgtGQxeTh6O%y0s)?qc8+So>tXd?R7@C@=m?m3TrkEI*fo4X{ z%nU)-M5iPgrzTq_8JUJPkDcm6B$Xlw@RT zX=;{~Y6dC}KywG63%pYkEzJ#0($Y*Ulfa!}^CV-FWXq&9(4~lpmL{Nu37{cGQzKB< z%E&y?BGmx2^32dIH8s@;v_Qnf)C@GKXpw4>oSb5kY-|C#+{-u#T#ta$EZD!MDW=Kh z=H^DAd*eW>N6d}QQ%wvF4K33WO+dGbgDNruP>ln+;@m9RI3>+IEiE-A(ZJXObT^%e zk%dJvXu2ucB-td{JjKw^$TZQ!(lW`w)X>-rWUFObiW#`cmuO~Uo|2eooCF&3NHR)I zGBve?hr4AW=qB-`6jKAUR0Ct9#5D7?L?eUbG*e>}V{_1mjaiBz$SOlqi)2vW$imzr zF)_`|1f0DSEx_ZghK8V)X0lmgl7%6t5=k>KG&43#1=lHNMv$?}WYDUvGz*h7a})Dq z(8XyLv1gdY$%oB}L%#%QlN;L;J z%q&byjX}*&W6<@0Cdr_Z!P3~$)F26Tr)VlDXibwX(vnk*Q%zG+5>1j*Esab-6TimB z=Ba7M2Btc64O9) zD4wHB#zrZop!G1I)ov*k z#%ZbMiDqfZ#wjVF(Ii7-&_aZ?L{oDE!zAOR)Wl>n!z9r3q(P!(DyS$nF#+ApZenTx zYB_-B6+x9zl0jmsA-F#S@@rzUaf(?=66oIVRD(2g69Y42qcl)CWn_?)W@Z4o>fSWT z&=fSTkYt$*D$EQ(>oAQilaoQq{fv_=j1v=+(~=WS3=)lv%uLgal9JNWEX+a6A3@WB z$%)BH7NE)TB;%wc(1=Z1s)?C#qM1dqfgxxD*T}-y!YI`^)zs8H$uKbm)Q?OtGqFfa zGD}Lburvh;7?`FQnWZKrr6q!fRZ}dIQ&QOa3fPKtmQL1{O&Mrb$N0;Blc;b5NyYW^9>a zl9&j(kO;b}*c3DYmX?xal44?JX|#mvk+CCMPw5VRuG zzzj4plbUFfW@MI_W|Ed_o?>VS&Xj2eCZ=Ylpv7&V=6a$*3V79UqG4K!S#pY{0cc5( zIj9!3FibQ}G%yFPVgpUr8C!y;A1sUwLHE`gSs0lnfyV63lR)#BW@&~-pe&MPnhY+V zLH;x`1ualaN;5JvN-;734f~p>C8ru&8X1^@Zjwz&PEAWnGqx~HOf)jGG_g#xFgCVG z1a&TrjLblO0Gp9)Xp{9U zI5p8S*~l~{#VFCz#MH#Z5~MB#Gz$y5dKz^5sG+%8N^+`&xrJ$Rs%c76Qj N>Z9p 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 z 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

cAfSLq5e4`i` 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

g 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

LJy;LID z4Q^6%b(ac&PLw^y#PDJb=qh4xk4c4@fdRAyIreb(FYQlVEOs62?kxvOM4Caj5wxBx zunW9<2vTtel!(GnScrJH%Z2vX@0r^*=uYgY6%F28Qxm-7JFEOr@8bU$c~n z^lte7@87@XLoDAfC?8wd(9qCOa?$ueTr}i<1ZmJQMegP~ONKllvg z<}?GEyI!!f z5f=~%xBf5X2ZaM97}RF`{~y`y`^Wff{0q)*PzeQ2DWH*qGkLBI@G=fGtewU1V$D9# zbxAh@{)5k1M2u*IR#P?~kpS(Jzqk)>3h3}g8E`9@yZii$!u{Zr1GKs~#4s~}+R_SW zrXcbXFBR!FX$85f`Jw#(QUPOd(fGfV=khu5@xY~fUkHM( zse<(n9KeS~iX286<716Hs~MKXxKEsg;Xqgx(~HZ0LFFgtL}sK*{-Ein`3-1t#`qFw zDu$!i@jvKP7SOcF!HX|Se7_xJ?2Y)(?|P$`N4V4XM=#I$ZbQi4AZx=CZR=9d47BSH zey7t8Aa?8zZ+_=onyar#(uHBT($$$AO_9g9(?`1^<>G%UY6^|C#?J(RjSsMPJFvW# z@AZ4z{8O-;HH$amwNMscZ<`CKTCqMMeL(qO^8t=HXsm|4umM&6z8ry_951>-O1eM1 zumcTR8Nif)@53wQ2{`7a!r1Ai@FEqY>X@4hW2c)0==9lH5)2I87k0QLx-zt0>h%)g zcRhIcMJq(m0V*f}5`_Dw^;-!~)&t{95#PUAyYdv7^RF)jt;+sfy0myJ@5{(T7l-1|6iMTv-irhUdVH0=r*3v`mKb^ z`XhfUXxR0&)PIv!i7ze;FF;#0x<5p=ek;uZ)z}BynVXNZSl5b_9x?uw#rHyvje#Mu z*YywhTA6?>mhj!6;0XRNx&<7FB_W{x!?&#eQN28^AeruC{4R&u89}EGWHE&!)ahjL zy^sQ#1*)q+>HAnaGw6g>jN{L{KfLaEk@x~OwvOfWa}P+gflfcSMmqg`8|)0L6406G z5kEn*6C5uVz(x5%RX=$819XZy(i~z~w`m3_i2waBF=_o)DxdKL6toXO1c;R-^kaR)tcxcuy*fC45S$C*1F&v14%vguLI14I@L9-!9=b?kI*Mk-xVK1)2RH*+i z)c_q62s-xjf2j;w$p^OpbfO@#9O&F=ju)F47(lm=?f@TCenhZ1*2@{MLWb zlnE{j&1wwI$5EydIlsG)=GykG<$%arqt&f-DLE9mgXE7XELt;l(P}VfJM7mHZ&gqohIco z!3A;x7D$~9=!h1ue6z|12DjI9V68}DP!a9=1bv1xi{r(1(4k0>1{J8H2=A@q>1LmB z@CC>Ls$dq|3dR!Y|79#M?*01zKXS+ZfB*k~P-Hhg(CNm~$=2z{0Ux|+e&f;Wx+CDf zsLlizhP39|R}B0upo6Q!yKCRH{^xH2&4YBa2Z!~>v+QF~U|?XrVSS9>=R?>Fe-8!* zYg2kp+HYyN@4p(`amd!B8RqYGblD zzhKPz@|rE{>uaX0ZxI3iMO#3b;09=cr*`Y@67^uXyJYyc9q5dcX#T-e3Np*#wPy1V z=2DdgKMju8at(eO4#(Xw+TK6&;QLG8h>cz_)aOZk+|4xE~3=r~{mvvRyeOSV5)) z{1=6th!)mu3ew*Ctps|5he9FJ4IUsVlp8!S%z>Vw#*^^_6juLx|Nl4s)(JYw3$zTP z!;OI<64bH+od(uz(G5B<4(+tKZ!R1fj3tWUFN{F}8t`BA2sn9_%0lXo?hh{lzk}-g z7xCZ!|3A(E+LY6L?mv-dDESKfH+-Q6as(u|HNO!6Ww_>l|4MmZ@WBmy9ohP=!WEJm zify}(bzcJ|&|hqbGwmR*R054il!C@Ozza@(be4in{Q43An&f@)^WXpfuZ3Ui_y%+4 z3;nPE|2Lob4?cwpbcz;e46ju5#Wb)AP#^XMFGNM`;cf?k3DCA(*8hxGh{^uuHwECq z3*)1mu4tQBTtQ2xN(Gu9*muWDWS_7A9mZEWr!)3QXXqa2QGA`gTe@8sB|2Sabi0Z$ zAM148@L%-A1Q&*eY7vG`*9oQU-KSr~-2DH)+nEP+8o|GA4-Vr4t2=#rRjwU2UeF07wOc@IN7i&Pb+}&ccHPq%d*Hb18PMsQjXz)h1uZl&0F5ZJw1N_F z_vz*Xdd$Z=UDq^NFqE)6IyC=et@+YjyFvR`r|+58lh7kQUDxn$W8mM{a3S55!J*Uj zg!aKs*B#c!`TIe~#&!Shj$PBm+~H#T!rj^WXU&)H(jCUPTffx_hxNL?U_KZW@Zv)^ zXzAz~&@5x^mhQ{lrF*(rwu0lDb@aP|t&_NS{{M(oiP6WGd3;0m;BgQ8? zLr*mSVBrrx(CfMaw25Oy0RNPOy{;!5K}%E*bo!nNc%g%2-Z4-B)o$r_y~6Ce!{cQ? zsDj`DhgYZXj;<6--ET)&O60m+EcF_m{Qh5hq{Hj`i)*+Sga>v|xIDJbAYt{liKphe*PE#4rjT~EB0`(Jt_ zi!rDdd<;91yf#?=N^r147HcPH`4p(9cm|{__;Jm%-KAT)UH5cDg1w7HnE70Xi=-ZC&&i9|*SlSJba8d~Sm=S2KvHspkA*Hvx9b{* zPB)g<9FRf@bcg}cN*T~_`60A-3l z)<25v`M1jlzqksT2Tij+T&mIR#=_M6o2yhbi#Iy>#a@`Wz<)QE|85-3$C<2a{}i1@ zxB%8d2Q?xg_JoJM&eg;(m-Hu zFG#EQ!HYivx(^0qF=T*hniowyx}EQa3RH?RNy z*FGE=07()Wf|PWFwOZdOI^BI-+f|^`jm3H|$hG`UZvX%Phldy& zC}|vnB#lMopb*Ov$&he&Wq2Xn`u~4-El2bJf2DHWt|G@AR2Z8R6c~;{4gv%>R8IVV z3A%@%^?wDwwJoTvT?`s(HvaaS#rRwIvDO2ns!)xc1qw*|0>VJxMbR73_?E=$9o^>- z{$%U)eE?}XU9jj3z0=JCZa9B)5zt^P*%kgm&K5Macltl*%<|Gd-L4N{apimGn+u}` zW2rdUCh!@BAg6&`+gYISS{!`FzQF%dp70l-X*9u#4TTcH;4G%Fu)r6AfuKWPJ~ST@ z3GV(E*jan$#ZgeV3UpeoJLrfE?PDeCpk4-Km+vjmc><+hdR;I4FZ~hl!sr($7I?Zp zfG^Yz{tuJ+U-}{7g%|k336a+iyF=e}`@VqM-cZA#!B86tHQEwnv;ueoF=%-issW&5 zHJgtJyk3ARoc8Dc|JTn^#ri;J3|#K^;gIO9y>q&h2GK&y|s5hcb~XEXgyGx(OrAT_#4Ebt^Z4OvREUmf0T-Y;^4Tm1UOMRt1xyt zE4-}y_y2!z_=_#zT`n)PLE|crqn$y`V22WpZr2|T7E&cLP^~fy3=E)H?JQP!Y4`8{ ze{I(%pmjCiDk6&`!vd69o;AW|^ou}8;)5q(z?}kyZU>JK{~2KE4d1MN14t+6KGX`3 ziBsSvDuBe1P4w_+Jy`-uNFVqQGM4f;{sc{Im9PiCm;mw-F;yO3W!<`h7uvrx?nzV2IF|a1iH!qeBmZo0cf@R8-Z?)#-AVu zmv9BXc=!?=M3MgsY+hW2u>Thryf_78n!MN#V_Lk}0%K~tSP5h5yqE`LI=q++W4gTP zfHF5EfNnsjdI`$mDq!z^0nG)oLS}(KK>Q5#N(*Rei3P3*a_I99P}dJMNeoi@0yJ#| znyZCg5(>Htv?0-zq5H=R(>I`6s+1dgi>L8{_`|_r87a)5J9l2pdI1`^1h3dq0AB(M z()5Dq&Hw+wFYdkg|34D0>$Q8>e^apR6L7UxDvnTp={0Chc^ydoYw--wTy+@uu%0Z2 z7c*agJjm014{A{N;kf8{NOA#phwFS8N;LkL`MhAYV_@iZ^NF+u&vloG*n+0JOL&_r zco<4S>zP2sJ*a$l^8sx%V-I-IV-318_3#TH22k=hhVD{3OR#y@EQTH6)l$coGB7mQE-7+l zU?|ZAWf8bpVgWCXzxw~b`v+(lr}2U2|Nr@2e!O;jQ3oome!RAYl!DzKz#5=StU#8E z1-zJpsgM1I8(3c$WG=G%_zO#r)4)ynEU0&^mohMbO#=;Z`~jK8AMhgJ70B%+tj$0E zzh-~I2=++{XJ#o6C~lcQbRT>1VF_$?!iyiT{{PP?zT(WV2;`#|?_d7^zZe=erJ(y; zU$FiMnFczH8nj;^^7U)b&8<)sCAdp~i9*r*fEr_x>k@ z-G^XvZm>Y>z8D4xHqe+MXz*0E+m)x+#L@a3e@i{+|DgV3nk74bi!*34^*EFD z&(aSs%^?v64s?hIp&@q-5^_kf2D+uCn+;mziFf;QECemaYi$J8mZj`3iYyrzI@w@R z-0cb)LFDP?v*u|9m9Zt58XQqHz)T0N=)t1+j~Xu1acDS=rhx;rK6u}M(4Kya?f@3h z{#g;_W7fw?t-C*UA8&m2|35zi_pwrDhu1ng7#KJhtS{CJ*RWXsEatWTS;}esp_Da? zCE~S!@&)cwB`jG?uRmuozkY9g06xJ0y3&Myf2>GYcL7WH>F{og?rX}S0^P@zU3nTG zfee4ay##cMHvjemk!jWk%S(${j1IgmG`?hfviq>{ZRW%Ls}D8*P~dkyWqh&uhXcR! zspdofn=k%XzOH-@wEl;mf%{^qLt1mKh(U=8|9)Q){x#oOlxukozGLY=u3Rbr@&N-w z_q7*G7Bet(-FVH{_>6(!Lp}J+P^Qg{4UZYS4ukf9BJaV`2{Zm?St=9G?^`Nke5t#Z zr`L_UL)_9;pj@fjS0_s;E)cS>)lr7Avrys%*L_g+DA9fFZ^nKIm`r)-ebLtz03XA_v)P(~zwHocfwuvunY5FEfuF(n zK&S7MPS+RRu|K-6^KZWmI%g!7qcikI>$kdq?qC*WX61|Bz7HS?hJX9X7uOduFk~4- zrZFGn-+rL^hh-TvGw95SC*7exI@p_Ev2?q>aOYohf~7O`$HA8@ex0r_I(?s{wO*>6 z``QaMAN%Wn>4U(4;1|Mdpm9l&mIEd3-L*He45EA8|95dT{7eHKYv5MO+9Bcb`h9mS z2WX)pU&Bw!Qf4OKJO2)LaJ**z=kUMvTb)2ymO(^7_zSgaP#WN2{@3mLWur-h1p~j! zk1p5$prdaCI@r6JyMtL?C@lo78}0RHYJ3bzADzB;jK68eevmGGQ^8fw(t5jyWrOx> zuJ5(WL}+gAmY zg+Zq^b{0w)p9}) z9AG{k03PmG48BNCpxafZ`+Kv6ZYkR_cHQ1`#@5?)8eMLT9c*sht}5WX0Xo6S>;Ncl zsDQ@Z5gCJxf19g9^9M%e!^|JF|1sC{G}rR{&j|SM!ocrR%M%{<;`ViLs%kw@n%?Wj zWZ^1O!hDR)wL4U%+ld2oe!G5m5KHqb#!9yDw~o0n>Sm?HTVJo?=sq;_`+o*ErYtUG zE;BDF*{Ux3C@#=svD} z5Zur{9?;8T81Ukk14@*N{4Z63L}_q%*bC564b4X+z@q?={#__&e-uYpw-<|NL#+fT zf&@xLtk0JU7$0c10>{k3wBsxi1`N$sy4{~k*^V*m_7*dCgYLVm*DvLPgc*3dK9lhQ zkO?I$EeA^ZL1`0ov*~3}bLxn|F*XCY*G$YGTL0H2!lZV9#* zBGj$hRixX2rS(9i>h~KUD@s|ckJmDF{|FBQ-=3P!$iNVuWf1n_TNxi93J2w)fUp<+_K2WnW_TUY?fS)|`Ny9cZR_K;>Xxp5YPq`D z+*%Hl{_Jr32hLd^vKRwE7jy={s0VKyk$~nnkT@jAL1d?b*IXzdqA9Qow6s%%f7`+4 z11#1Tin+U81+sXKF)&1&Jlt}!+gG53_ZXwD<1t1C&~67tFHi#^ES!H^twgU(D`**G z^LIw(|Gg~M-6pLU{<$!K4n}hQ19hEt=^yJ)(g&QG4>KSC50MWFe6i&UC@^_IySxsR zGMzjOTLt*64fKvny5OSWQ` z*AGF{@315SIwlsh60!AvsY4cf;P{GtwYd(aV3Tf_~NoNEOb$_2Vz zK`OyFt#lShyuQ+0E5cCn%J{ZrtOSPS&hAo~=6{YQLe2kNOL&|Axs`B$E?4>IUdnRJ z^$%mWuL`Ii#=(8K)DbikvmJD+XE$i?f_}Fvhh+pyJx>jbr9?5?G1niAubDeye}FGH z23@)RBk%=ixoq{MJX^C zA9y(*)P(`vIaLBW+ONA*0FqEzZ>Er}0 zrDO+J9FXyn<{wq1lUr|>h=5KqDC7HIDgbf>C)5#2@x})_>mTp3PBOytgzlDntbV8E==*Dx9?;7kGN=3op&EN71)Q3Eo*2(em11QW(MZjST znw31W*HF*MP{Pse#sgZV>kRUG^NIh* z-6TM}I$s;3nUlo`HfEO$)R>a<#s?f;^FrF@tRUZj`d6Ukm7wr~9x7kKX?&pNB- zhTiCOeZud0vAOmILucrfQjV;D5idcvrlvL5voVy02E6bA#qou1*C&x(91b16?>k+e zv|cLFw7yoN+Wd>DMymN2OTB0oJO8#rUAH2&L1)&#zx>Qk`NM15;Fq64(HwgPv=5wr z+rdue?n5tMfR;#wvviwx#k2J~{j*`>Z$AZEA@G}#zX>#LW_63d8MH5)f7@wm-xu8n z`JF+FI39GnKI#6UU3;wL7htfLTS@^dd?le#9bZ2|X_y7O@#(xYq7#NB; z8vp&j&%jV-587QUz))_^zwOX**AJkDjmKTTFmNz19C!Tz+V*H&()yxEvK#CzrcPty z1Fhe}`CU!~z6c3sV0g{>zw}P{i`ZaLXRzD%4`dE8E*d@}9vBG9W!<4XVf*$Jxiau? zKgI7_DiGe=$e_Z&&}_%Rzx_a|`+iV|FU|URIq&~ck+2v1VAEcw^)@kRfXa*G-3QAB zRsXC1|KEJT;ot+VPB!BMuRTCYL5cc>To5P?3cNP^Un;T_V$#9#o$!L{km`Ts|Np^7 z6*C)H!`naxhOmGaQ^5KpKxaHa+HSra4VDb0te}J})=(0ObL6@Cz zv>qs7PV408J_H&)2N@9vS`ZG}23X6}ZO`Ab1e|yTx=T4)ZHFj03$Dh8pa9_o z#W-Zzz40W&9R`N9PCn*e&BvIUUo)0Y?T+QqF6FrRulrc1_3J$2|HcQ>I@w;o1dV}P zbh}DG=WIcx0O)Q*Uy#d;Z@)MR8cQyfcrD#}vc!)0XRkA3^G}vu-~ZwKu7`Ug7+`M>lWsAz$fE8vp8`|#`Uki#F04>X@-wB$VkN-0wg z9ELnY_HZ{-moG;L$A2dNZLnJ$vzT6Vcm4k#Y3a&Q zqLIb;q7KR_6$j~zy!rosz>AlLpyp3xB)A*`-2?|(Qwz2Vyp$z8?8V0a|NlpVP7wh0 zXR{bzSb$8)Vv4r@P|Cg^v_tK+K=2D?kf8O4(#-v!{b>JLeR5qHdi{9187Hhfz{0># z8n~m0iGkq*Cu1|HO2}XkU|@J*@)ES0r<47~>+|5l_4r#)mJ0RyiFC$sbo#M$@^!{Z zY+!sX+3Cm9&ECm&+>HaI>$sZ)hZ+HnU$ zfozREyyF6x2R0#_SK*Tj15dXr5AzA@gC+dkp&XV0EG3-H2Y9RxmVN=50agdvCd~{Q z`T^gCin>jj4Kd#b+K2=)eKE-1#USezL#)oy$k+i2naj!GJKk$=DAt|G;Q8 zA6_EbeJqP9Qu|;@toFeY4()>_q1p#aRbD)Q3Yzcfti1u-0o%aH!0_KZ?1e2TO@fXK z5PD&G7BrV3#=yYvV#DeG|6ku|KEPoFTD1FGs{2^;3;q%=P^hprzhErA9QNYSKTz|9 zrPK9JbLs_#mfIy9SC|TR{7+PIUS{ z==8nP{F9M?%JGicXD$Cr3tLa}xBLYSi2vg#;cEWJUBcS@kEK+z+nuG;^+Izx3q$ii zj#9@L=b!xl-|fKB>3ZhHkthHEA9vvB0Tpk)4?xmN*{mv`To`zm*|SA8z>Eu^)qRIb zgqssM7@808y#4^L?7KtnbTS=x1>JM=AG~m*<$q}r$N=jX`A`1;|6jln)(txB7rH;; za^!10(Bwevjjq_|-M&{keIInyK5MyM!kxwZLIdRCZr=xo!yu}=V;}s#9NCQG3$bq3 z3!UyPARD+}@Pd5cd#2Na19Uy_2c!dxgS)^T*!@pRS+fSYi}{~PQWO69vtc`WOAN_oMj zspqqUN~+Q<&>b+KcI4|z;o({T!?HO4mx{cw7Y0>(pcb4Mq+J{E;>fB0|07>Wo&Nv7 zo8h%dcP)>#J5L!;K==6%ek&Hyz_Z>L$xft6Us!Q5QW26l5zw;M-?#OuqT9$(gf&_Prp zFWkW{R%ks?3U{#(*u@#Az%KRxwW;AwHiH;s^uHXm%k6(T2dFlAv6vNXJluebCqZ6T zhZw*H^8~yv`oB~Fbi4ud7_0(tRuF(zz}>Dq&2JRKK+bvb?BxIdkaK_HPJm9#d+849 znJO?CpH%dH5!@Zi5pMh+H2hoppc}MVD6H4_Pug+UKU(&I0moebF}&ao0yThI50pyv zx;_X1_3i%~zYqp>4L*Q3>y(zf76u=5{@?fo=%S|PBcLNkWSbAOfXpl1&|UkW+xJQL z&F=5o_YeMNayCBjTE6?kYrAeS@Y2^W(34O=r(T7AabP~we2fKj}~N$C1P`w+A1kAR>Tf`OovBG7uE)EIPpUFe@q5sT*I zEX<)_z^0Y%1T_~7j1L675CB;YviUMI1B3B__~+_|LyTQu37&}^5|NZ~p#;R1I*PYS&M2T<^=(Lvb z7f&Fm^CdTEJ_W4C__mFH371Vw37d^o*J04L1KQ_1=a&5a|KG85ZpGjKpxgB3*8Bxk z(4BJ|{{H_T#_xKub1rBVN9WXnzyJSt%jNQlMqapnt(0%RQ=C8T`o4rs5ITUn) zPB}~IhyUg;gh71RUAf?5uv7#z!15o|M*=m$ok8ah9Z>)sCJSw7fmZzbet4k_3UAjh zyFddXmH`|kJTEMcgA#b_fl@}NhT1<2C0yOUADR~ifbO=3bfUt#KY~V7N_hX5alDv$ zT<>(#PYvRGb}9R~Lf*j}6kO;WOfit_^{pq6{{0fA08j@K8p z?GFBD0v*EfzrKt$izni>X>b-xuZ(^0f3p{z;G>Q~wF+w%Puy#PPPSg29lb0wK>Z3g z4)8f~AoC-;k43}cC-&u+AOHV@qXE=FY5i8p4>~mG3aDm30Gi)r2sQ@S@T#CzNgPk9 zAh=ZmI!&aD>mt4h(T z`W=w`3a{#)9RwL*12F(r)klLDEx=L&3n)%sNFMtCKT9dHlcW0}ES}>Iu`q!8@ggP6 z9gZTMjvSqiJe`gLkd98{8y(c5-Ib%a7j)V|1}h^2Ltwyv(H?N2P$~#(XhnmZVtn9r zD5w^26=+@xI`)8}v-b+9TmzR|ose@Ez-KTVYXzN{!0>|m@BjY+y{+#d6i97AZ!5^2 zfEVSU-Zc2|1W*nH9eD6U(hHQ|vp6y&JX{%GbcKUPV?o_3F;M*qZnFFGfKOb5wUF^G zE7b&PIt)IZVkhWG!@zE~ZqTaK<^vJ|f&Wb(fKFY>1+A}O+X*_)FAyxrDhVo;1OJ;o z0ZIFTq}^DWk0^k4XESs&Ku%NvZCPPxv;eKNECD%B5EL}sY~2DN365?jk4{FYT_66# z@@BUyhwc()28I$1P)AOt`2{az2P6xq|FtmXzY9a`;e`nhDh5JDfGKcVZGI!r>-!;# z;l&5gs%6zTpoMdwb(KHZ90phMpOi@pG-NB)*Cpsad(AIP-s!yPTGpstdG^|7KaU9Ina z{QuwE3nGuTf`k=b%kyswWaQs=;5D!Hv0~n15Y-9})`!a8Hy>o`0#&AWga4Pa^tS#1 zSp?c;^6&ru08ryATabYPDg|m~fH!7<!|RWua|`%#OG?@ROoelz;x&}Q`g~+Mv&Q#y)1&($GX8L6rBXsy5Oxc zliWbru={^-_npAN<|jXzkFbPxXR~zXsIYXuX?$bB#J~_1{=Zn{f3d&|&<3;r#T<~a zKyQKOBRrr+w5Nx)BTFeeX!4qofgwYIiGksT_Vxe&J6->P`ty7NFYfLIZ=!tp5Y$I5 z7UG}t> zHlo)Rbe!~`fEVt+|NjSBTEf-sEYi)e*d@sobVlO0J^%lAACHWW>wX&B{Wu!5`S=HD zkYrsDY(s4=bX{6IsFp9`vn=;1;p{F4oxPd+Ix>s(g%qfg2ko^j_WUm& zRsvlI&sNIc_zzqXv4_3r*aPy7aVJ>mhyQG_ViI&j#p|`*rBAY0UkHKBJKTK?eGBu8 ztY!cIpJ}lD04iHbZH}{o7OH^^KF$g%3oBAx8IH4p3eAEPSB4iKF8}`zKFum1i!tl( z3()a8%|`@|v4V6nf{x2N2v_ie13ZiasdtbsZ~Fu4aPxpCfW$!!-W#2<4^q?`^0iaLz*iCf6F%p1_sCG0|uSGPi#SROGVEbf4>0jPi+BJ-u&AS2mBYk z11%#!%b0e6iV^D@r3#>7z$XhS;t{~ptp`^_3G6xeL;nc>x+P3Sou;? z2QKq^-6X;TUc3y0lz4G0&9yI>I>CmN9%!h2$I$Egu0*TLgR$jgi8B8-3;t~LUQ8>g!*{)9vI$iJdHcUu!W$1K$(qO^R zeWJt~+&d^Sw1cI7#MPjlV!?yI82Jy&}z(frHtJf14wtv-O3tXUzwh zK%@UBx?P{RHy_{totFNerD#)k?1SLWIF{pX9H2_&h3!vJD6n*b9op@Br`L}si>-G; zOPVV~d|EeCZxB;jCu6TCQ}cVq()VF66hPZq*uq|H1$plP=p-Y^1c|K^q)-91HM>hi zKnvB354_F=&l{Eszlhig8;!WI9h8e-gSwfZ304uyQl27yP+RtvKgc0G#s@&t9z0nL z0WUm4!6L2yOF3VNgAI7iV_C{mEc}8K#8UztYTO7hjyX##0yGv3t4{xya`gIsc(LH~ z|Ns2kLV3Dfe{}hZwD<@}mP&N{3bdXq;q7+)(#^oXoh6|4U@558%4~eV0Y`0_#R5JS zB#Yt2T+l@A5dr9kQnxF|&NcTK7_1MLyOpTzG(G}mDwaq$ztAcX(`7osz)->u8r|gr z5v-tV|AIj60bNs&%varHAqIvLS6v|v28NR7%`X^VKiIhuVw`Zvb=|f17#K<}fOMV) z$=%i61QOT}64<3{D$l@BvKho??REuC9Jul{Kj4763-i1a@El-dBxtVazv!C@pwy}ITT%)0fow@0$OoAaA0&Zni3Jf6%`cc=yF*;>gY5d(x(J6GLmaLH(x477G z3otu?n<=>$dhWP=Dd#kASe?V9*hiTHwT@(g_-)Ddi6PFZyGG3xn~2 z*FoU{FaDkf4T?twxBf2`e6eBM|NoH)dBfoUrGLWzm;ML~4u0_zJVpT;VdMyZ(Y_6| z#WDCr{kH%AyYIuabRPzfNP#01yqXC#;r6Xm_{HO`u=*2J)@U<<7D3sDb^m)|U&X-C z=?WTpI>6uZmyvPPFi zXvrCfd8P7TW&U7gAPZhBfhhy=N|u5TZSHja(R!d{X1D7H?PCF9FRYnBuKxl`0Y6#~ zRQOv;mU#a+X?&5n6;wU?ezA!CUuw`D`r|c6w@VjGCrg*3rA$}p=PZ`Mpcke*3=F}Y zu3ui*Yz6f`zJP~cN|Ihjcf0=R{@rQP@jA>R_CJ4%&j0`azuy4ulnP+7zQErk37Tg9 z_5c5Wd;Vt7iSb!1L4hw`aDxr|@#6g!kYPW-hVi$&1@(M>uYEx0DV2T+d*QPl9CED(O7lTi zW*yUZ<>>WdWIoX$BVc^M!u3CB>N@O2kppO4uJu5v{EOF{|Njp=&H$RaWt7SPn!YmpbbA?n3I(=RF@^(X#Ef^!NeJqN$g+XNdi z3G!Z+M@GU~?atC4 zpa3al>HhrMySI&jkAcDZLy2Q}Z=FK-hv19_{0t1e?hgW9oCBqQ{~!Mw(s_S$%J0~z}ov{|{EWiIH% z1<)R3#uAt28g_~QCAKdf&i(%%bb*et@d51*B_hr57(pxK7)yl%vcA0L2*~>SnmHir z+ka7pi7pIK6PkT2B>o#8crErKX#=PL2JO*(;k4oZ|7HaS$cg08%B0(uqxt8*QqdQx z5Xl!taP_a9TTfP~Tl0cKq*%WDAZR=P3%2Z&7SIjipe?naa@$y6cP0nzaC`Kn>k_EQJ&*{@qHb3nP)LXO+O&a3m=A&^K_krHOFzQftRNMj7R3e777g~W z7l;1;|KIB-lf@qJVmp{=k;N16Vhxy?0b(u$G21|MmRU>zFD8S|lijueRDvh1`~Uy{ zHqhFe7vW$gXqnv$pLPHL_qJ^Tn;!52wCu094PsXS_-MxFBQCvdZ$Q#K0pLbfZ<`Dw z0|Uq=bFfW5ARbe|3r(<1A&d+RFMg~A*%Sd{z6CR5K+H#AW&((LeJ!Z$)_?^>^BWoP zEI8;?q(8x+78*yd?~@n5pa1{g9V^p%yOgcl^+k6C2WY`gc=-QP5eLg!1<+VKXC%Mt z!GPcwa-f5kj({#o1MSiQtrlZG06O^HgTwkD=&a3>Ok2=pp5?+XeDfI?y1#&;_c+^` zGoaf61736<0~N)Qt=~#qjyzdMpf3L3?&H0wH^67h z{4qZJLd_K3EdqCiN`#tUa5P$gYzJ-4-L~fcf23OoKKys!>Gr4rHDN#eXYB510gWP` zEMW$7K6{}&jg3J9w>1I z8ST*B20BGk7u2H;crj)5|Nq@>Qy3T+z^7zt9}jrZ2o?gRd=Re~Y#zvn7a6NT5hn0| z8`yiG(}*Io*dlu8fwBc?K&MWlu^tjgvfxTz1Y{k5zzYMA5ymexA|=EE$_#|4^SFm}5BDcuks9rohWs{j8Z;irXx7PFR!HU1R% z<-!2k!RYXT|6n8Na(ai@!{A#kp=CcPyj#DOC^r5BtCZ|+11XvSTD=|JtwiB952#td^1=|L2ipKw=VVwj6}*P5 z^;?MzBq&U~Ev)~QvUDGNtsB;9@S-1-6hU`ig}*oh>Ri?HFhrIx+<;BaqG7u=|}r2Dg4Ik%phAD^Se;qILzS(uM59e(eMrSr2c$UBVsw;-o19LuB`l z*G$I$`PY{UgayA~Hv?_^ii~W%T_S4zuUJs~doPQ17-*;?)&-PwdE&bdgPLS;TM-O! z3nunuDd=J}kSOH*To4O_|BG@=bYW;cuo!f%F6bamh%lUNRs~5gY+wW}Jv(#e3`9TJ zR8U*EmczQ1rzEiZd$(Nc?GnE3(~vbq|1Y;3DB);6#$gS*PXu%`iJtZM61C=If12z5 zFq8;`Rr6*sAk;@TzvJk2W3fJ7de`Ux>JCp(=vkI>l*om5*ZpbzUjov19%|2ZkUr~D zj?yRb;EO?_`{Q4Pf|@3v6JNzZi@o9Z-+jLk30jK;ISn7D3Hb%%N3Kx@34U6Qmm& zxM$9s$>PbV0GYqU25!DSNChOdgUvtL3#yMgOP_#dk+1iH%EHAU3D~eMKHIcGW+7}l zbLPJ(=xVVSt)P4eY2AUFySqVygWc!4k2OCOIQWpc`(pTh(BuX8^%WfaE*HB`HJ$`j zm@8QLT~2jhY&->8B)x(OCL_SWu!0dR!+rVtG0-+-ewT|o8JHOuln<6DSsyNuus&V_ zT4gBKc#0u`f#Ee@<0;T3Gq2eiPl37-I~W)kn3X>?f=Y765=k)4RKjEZp;Wl>6zCe7 z*WAsg96+ia8WTgAZA{FE*dz_;#2D?C$21EZ+`ufL+~uis{>70g&jg=JSl-4lD4x{Q7p7 zsf4ZZJlHeqVt;hI{%C%1pwsmW|GLmG-LXGF2HSTNZSJS$a}aYsLCie|GMD>1sBie% z)A%IFG*X;-s`(_uxKj}0PJ)cOR+e z5)uaIK!F4?{38GM)7_uC4>p2b`|U6jzssjxpjcI9;9+0@-4MjWz)&J)3rY+n+_oUW zQa2Az_V*6I4^X6~QaH*5d!Z}2;M z^6P6Z?(3kG2l7qhLy!p6N2frm&A~DZObqO0kZlI8nxP(}m0wD}a%_v4_z zg~~C0KMqqz>tWMwIy1#eV6o{jwY68PJ@~!I#W1AGZF6`hY^;sX%-uj_@5Kk}iYY zO1jSu8DHZ*)_nq$6d4-6AChP0U;v%-&(wVkJhBC@9v~H8_jk~t1=pLOF?QeYKGuAK z<=Y_+{_Q6~hpnI32TBYCZujVYZ*>KE&^G0xBc`$~>q-3f~Sh@^3!@2`(h1 zpeSeHU;r5m5(VwIKd5}IL<=%~QzC7BxrDd-g!Q#jDPB-6c+JWSP9fV*yyoNurJUDa zx=(Z;S7l&eW&q_$21bTbHty4}nYhpKZ$H_6kQbDKz8?qWyLkTX2jci$4#LXP;IMGx z|GOVEFfjD8SkKfx)cxV&zpT*zCSMPTxib7O<#=&c2Rh1x<$>0g|2u1+yto|+8gHuo1K#Cn3~4U@=&XGLt2Dt|0gj`OR&|#?=&pSd z_F^MQH>7%mG{C{G0q@Z~?f^c|4z$86ARyqynmM2b8E6*vb#%8IPk8hB{}T?r03G%1 z1h#rs%>Vyk-9KKuT?|sk0~R~8{Qv*RfERXppnTJMpb~s(pl~y2>mcv{GMN`A=KcTQ zoF>B%8TKL;l()K%!@K{@Z$KA*gk>?j*cAmjr0WJ~s^-NW@U5@C;A^X2MS+Ilkop;* zp(EZG|L1~QpP)waYm3&C6)MmnBN@ygBmQkJ92(6J9AXc@I0e`A!f_60;57DdmPE!4 zP*i;}26e_cnt%TTT_rC8I&cvEc*OJnyRW}I2kM&MuHd(p1rJeS9*_vuiuHiRz}cW6 zlX$(Y`!x7~#3$W{n;+O`U$E#5eSmsEV(^Q=xwAl_`}=Eo$W9~3ttr9an>Lz{h;;wxti93wsk8JBEX{z<+wQ*B zjhSj`%7rZx-D= z;1eSoQVccz!uNGSQwwMxQg;L_xqyZ(psT|5LH(K|BH)D6{p-d0i2wh)uY*dylMpX} zTmW9h2vx5Fo~aUnX70cjlDeQJ>5#)@dqKxY1iY}(g%uKPY2B_ICqbQA1_r2k&9yuX zC7=WBUNbs?&haoP`OyN|6bavm1lqJ+%H8eC(_mrBKlecF;TKxcAWKShyF+=pm~2ez z6>1VdA?Cyw@M1ZrP>F0gP|9N+%2DFk<@8^LG4?RXEL%`DR4NJHrN;9DG4c(HBzT26jw;VKNaE#rc^-`T!mqg3$5@v_jOq&flpaR3sNEeA>jUNawKGw|zTv#~7s_U}LkTZ6q}DeHe{ z(DgIrjNRvuXIDUTD`DX;It)O*;DMeL0_*ueXmBtzzR`dlof8(`Z44TI+z47*@5<9{ z0p72}-?ET}fuYy$f2Z${=HvhQTTMVKbOKm9L$5UdVl36~E@tU%1#K@659sw~>D&ui z-kfm;w8F5{`o#zE`8)#M$BZw5hQpr59&SBZ>Hyag7|>hI(%B2w65h%EV()#>`q=Jc z-%GDF9}zG51E_nXF-;ySsbyPw7$hHS@m{m||D0ki>fO?T~@PS-!pKmV6F zJNEK)cl!QF6Y2v>H3F%@8Qna6D6EGKY&;z|5EWJE4JAL=`di?2j{m{!ZvD5cTr|SxSdC*`IgLUYSa@OuZj@L}a zmzrxYFmyYzbW0w0eF6%-&d?p8qkux6bjIE(v+4Fd)BXGMd*g52z879xjbvcx_PxM; zocr44$IZ0|nBfYGgh2;{`=04`_;dLM_l<7X7oD+px=T-FF@yyLy!aaqy6Q3Pf9aF% z8=awV{+GT0ouD84p)>T$i-jOFe}FE0(^Pz@Bd|5pfwyPnh!HJU-%yo{K7}| z|9|Em!k?N?|2IC+3D@rWrqlIH>$mcNBG%^r|I0lCf{jmhf9LkS1JeDc)Az{>Vb%Zt zt*;enma|&BJ}Fb`c74-)_>lt{y+1mA?{tF}{&c&3 z`JVcu`$V_vhwrIRm@hK_=w|LdFZ`+dpYb>AgT<`P#~FpcX&>xl2JO0W{n31Yr8)Nw zW2ftnQjqE0u}8XnZ-7mFVtl~*Sb0zpt7YwuV(-?IB`)2edq8d|ebW6Ca$hd)`;3s}Tu;F*XWZ+#Hl@|>fpa%Tixggs<@$2-0=q!b}&fWz-{{IK< zP5)nC!qNB>bm&1Td-GC|C_{HE$O_|2t^Ye)4L}P(z*g{2J=D3^1XPDFjrsHcKZ8@} zRGokS|Jxd~Ffi~p?FF5Sv2?<(|Nj||w@v|33<3pr$_m>hsp;_??e8F9iiOgYggl?&F<%YkvIy|NTNI*c06?U`O)rJy62w z(Af$K+}G^QOF=Y4cQ44?{h&I&mqoDoM{$|9@qvI&u$wzuL4NCP1vxdK7aR(pRhHnx zv;h*2}d_LU|x50gWU`X zi`J7R{Kf}*_ks-gyc!%bom)Y!1YJrE35({X;K+rCOv0c4|2yY`5=3}F=Uh;9zc>s& zKuF-_T~K8YPCC6E=YE4$kb*jLkQfEUb2m6fL1EN=qO%p`8{-4mV-)0TP>g~?7cE9X zQ3#4r5X}JbGT7Zj#;7>dt&kW68DhN^sKwBW131no@z6Okpe3yZNp&6QyjZgCLJ>J<1%9Y@*LH9xJ56%CW zz@hr7`CoCFRv;t=b@qai3^a#zf^!78JsR+$_6n$M7kKU8>-QhjBzEkL{NMf4`cyGz zcMCXyg0hA6tzypZDSJUl6x3Kd_)6~J119bZp5C2Pz-mAmVJZC(Bq{GU1$6_!zSo`$ zPKLh^zGvmVTUbGMgNheW4+!K<>(8Y4ayt0*B7xU_P+vL_oBj(Aa|No6|Hy@F4?rsHD7si*exZ*qag3?^;0sf9j zEDQ|azjyb7jDVDYp!E$KnHd-$F^H|2C6eaeY??{%t(HV*0KO z-9HaLXA19SF@(4U;({!OfER2Upg|*$tGdAz0{?cFRuO$yhF+Fd0X0_!s9Twj2fT<; z`v1RsDkxz!ACa)W3^~)Mc`qm;8A_#$4?s-rYy~+Hs_o?|Q2zj25L?a#Ddcat$;7|_ zI#1yuXzS27%|km?zbBOsnc4d&X5|NlcYHXji%Isgg0mu?^nz|OQj&EF2{t#oe% zxu^ROC}1GwKx!eVX`NF+7C@s;^CCD;fjYR4&fobb9q0ttirwFP!C}tt{2k(??vMOVpIQ!dZUvQd z{H_;`4;cUN1Xp97t$Tj_{||B(=qzbSmDX&tlc7}3`UiijD5#0BWbXk`Ll&G!L5g33 z&hu(s3d+F@-QSy+f@(hoP#^OWs2uuNT$0^A6(rVu?%+cv&@^515?+W2PK?aQAr^MG zf;`yGGNF4as0jV8vWpp9Uo~H1U~B=ahSaLvVCOYoVsPx73bL>p>}a=6aFuI)s&qp0 zUXU04l+HK!pZaAE;Ck>g)lx zXa9pmUgm>}H&8(Lz#Y-s3JpF`I}jSs@6Lb&+UUSb2hhpUb3u+RukQw1jZ*l4o0ZTC z9jbQ|L@%fh06OB#`Zs^ePf(VI`Rfg6Bo6EvxWB%2AOF5&E69G3zrc*w!v z)zSwq!8_8y4F*Vi)%qf82?S~xkyQd&f?U%J(vB#BK+6Z4F-jmdkS8Gd6{Q5a2`zz& zNGgFqHiAkZNWs&5i2+g;bwc=%f~fft1EgGl7DR54k_cW9bz&=sKt&t4_|QNUL?AJ2 z1rb=Ba6xnroPHZg5fnrS@r{)+wY20$B~NsX>fxZ~*|$9nku^ zBoC6CK)J%Qa|=?gcpU;RQ6Oax$Vc$92V@e|H@8oMeFIjBKl5yasO;Vg8nx*D4smPe zR!~Xbda|V0_`mVD?iO$&&*F;u{)qW_Cxi!1^1rMejgF?K_!a}V%?Pq#Ea z+5N%ze>bEJ^!-s57bu&8+X3JJJ{4vC5ANubB?%ByK;g{a*#mA9L5lg;Zb*&>HB{h5 z4^kOld;%QKuccZKlyXAqB#+m^EC#*hj2-L{XF)`v14)i7-MyeO7|={EWQ3!fqq$au zp_GaFM7OJghxI{zrxQk(n0rC7(Fs=CF?BPjhyD?=XB!g4pcM8Dl$Ky#1x5WXhEubw zzdr)|7Q~16*7{%ReP|4Uh9kj&3iB*T6{M(rO-u~69S3_BEq1OD}hWhorQRWpTz^ALn;J z&inxqYSvppCi1uP{Qv*|7#jn$o+)K%xm3breEUDr$k+d^pb@fw7l*1quH$Lg3mQIT zh>t7bg$*la2!R#|`u^!Y3_1B-<^yi8jlUmcVEF&PRIKqQ=q$w|j>ezh(=(m2m^MFnEdr8#@W0dqlo$jU%5}1s zH-Cr=@BY_y@Zd`}6?>kB4i<6HIPm*;(1BELj9fPZI;38JF3*0=4W6A7cp(Lzod+H4 z4jz>S9ZsbH9?a}^h3!-X9dZB@gDnaGZCh#v?OXus0!`zUbbzK=cp|$UcqXi1E0ynd z6*%qyx%$jOhOyg~Crco*`2f!cP7a7ZS00ecgD-eiFqVKW?>z1xp~S$z@cLpmL}mqJ zi3Z5rWJYlK^E4-NFtmV1%uBX)d$4qZ?!wFZ2R2a=%w__!Il=7jU^ZABbhI1PM9BGw zVjx4^K`ZlG4wQ0&I47kT7$QN3Qg_F4fKGUNAqT4Fj_|Y`C>2C=_iJYUZHHlNHb86R zd0y1C|NkEeI*;Q*wtIz zpfezN!u}Vq1ij$w2c-KRi% zV34=gyk_0uk?6|s%|Sz<KczDo@mWTiUD<5h;0=k#BbUm`$LB~6S(g1j#IOxR` z@Zhn4$M+kcv$^3596&MsMgkHq%qtj6ST-=8JPbaB93-~lK({ML341q(wFgT{1n64j zfEPEtezA6aQ^I6)8+6@>(E<1k1+g#Z{YA-O;KbJWMuHJ_;((*GmEr&Y|DYQY zJLj_e2d()i73kaw+Vc)N+6{CUWb6MD#TOMdpk)|hpk?*%tN#CopS7UI`u{&@+OqXq z$?ewLCD*%8zgSZ7|NrsUH~;>FI%5pY|Cx#|_WJ+t-V3safBiY;^PRmvKpoA4#+S5@ zfB)vt{DXtPeIcmNaK5alm&LBL^$SS)hV{*Ih4A42Q$en3KEly`y7d6R-+AVH-9Nj* z23X%Ld(eHa`=a&F5?Sq^T}-_}j9otB|2tg7|95!(2c47p8ln(lwf4Dgu)z@9t7;OkGCGEGlWWAwmw{g;ccP}U^!H%o5?f%$(+4^^hY4>r28T|5~Z4V3#*v$g#hM3q5@$OuZKltSttpAlM zGk@#^d(QfMv3PhGriJ%k8$k5(%QG;4wEkQ!icQtiZm^jUqq?_(q8l_{46*vK_RUW4 zVJO!3%f!Qj|6c=prT!trU)^9SNC;RkL16`UKE!^AiPpbCXHXyS{_#@!|NsBiKZ*^Y`n3;2-Eq83HXIr`5G`OAL0nRD z^R)@Y2NU4x!AYV_JUrn4H7x2OZij?Y_v!AbpwQJm2T8HrhqRAdAFQ#r{#7giNu`}N ztu38Xz{%2~6P#S3DIA=Vtv?ofb^n8;C1|Rh{^$RH>(6lQC9N%;b5OK{6Q1=i{^s|f zotXwfHxByV`O--yZrzEETxw*po|UjO6*I})^$j`14e>2%t6~G0RaKs zp*+2w3|&lI2TC}b4>9tuW>I~;GOx)=t!P6#xK z&I4L<2s*K(`3UIT0+4;pZv;RSsih(>49nrg=!#O%Y}Lubpj`v4-%5pEh$7^AO8@_V z&1zZ7Q3N`RUZzPWHnvXp-4KBj%B z`&#n@M(qn;=qEjNAA+r{3k*crqt;z3(fYqm1hgCNMYu2nL!|Zb$leOZ8m8_a-LWdI zw?S)~IJz0SBRD!^Rk9ee7(gnG4>&Z}YA|HM_N}Gu169Nl;C<};Ed`7W49o|5VVl(1vIK>$H>3{-Ml6q@ZwBAxHbeysDdRxTgbp0*!WvSKnLoU z{s1)^L_lX7eFq)Bb3_8v7za&KcGv!Z#vJH66wsx?FG?!^|L?v5I*jE80|Ub@&;rxe zP=OMQZdV16F3=d4^$q@h&{A#iO+5ksOJ(4i&0(5b=Q1!bfbaP0Ws!#ar=;5YP`U7n z)8-5e-JoqAdB@pdJMh>+p7;Se@G|l^JJdh_<)@Ux+~yE7-Y5Fi^~tkg? zFTNJT<#USu|9|bYMXY7s6 z*gKuE4?1F>bjH5ujD6Et`k^!SOK0qlj@UmhuCD_PGrC>?uW;2^3CbCu-S!$U_CX|G zfbMyE!M_r;WcWif=y1bQp0NL=H~x$M0iC;X1MCv^uoqRu|Nloe)IMP-;rw5E<3%=z z8`pgp<|xpmGtg6L9Kf5h__uTSMlt$^l|yEWHMm@PXjXJpB7z|3EWdU?6DI2dMXSLfMt$ z`^7Y6-#=;GC(=57f85Odfus<$NB#{D=qgLD+qysWT^Vl2{+a#lAV-P7?E4QOB6nlI z%$|M!!MB3~C0w_4SqxkmKqB7`vXpS%e0TH3y^nWq%>H&zp@i+`YmfxY1+(wg{()GO z#gif7>B{ip2ODIs7Ua(iJ%@BW4A?jAxro5gTL4y*SVjtfZiGo*@@2^7XIQT zxWC)|;WZ!hIsnjWfjoJ`if#iAa=liQ5kT;E!_q=m$Lgq_zMS+O!xWb=k^DG zvSnX~t%yG6BB;U8`mF?1pM|~Hp9eAuv{``(vT+lfzq(yHj8B64^BkQXEZwdgogN&Z zeyE4Qe=rBMV!0E1+jggi3`pVtPdf+bG@^ijEareL<_rb~28Rp*16PLsq6!mT7#3g2 zaAi2$%?qMHtM9pATm&_lzv2r>V~cF>WQ zr5v4XFLXH=7&_fpj1NH6f#sXuaDbB3f3p`mIT#o~rmSe> zz88sLBUxGxl!9)n>JI(U?fa)wp!t-1rw0ot9d?HPco7R%!~NnH=#*T9RS=t+-*E7+ zi&0_ec2QwbZK!8pux*fMVBl{pWMW{rX`_<8YB9_ z!0&P~jbDTJ0oWZHH`4euL_dJpktfplBX6hiN1OtQF&Mfsd;;?|bQ2)*U(@(CRuzER zAy3o5u8H`Q#vgg&6My6lm_7lp%OfwO@oRif;}`vw#vge)4Sa1c$Xw9_%||#s@kbo| z#2<0&6Mw|1G~l5N z2~}_?9{R+8=mJRNA&|xrp5`MQY5YR0Ck$K}4)1yi+RNsj#xEoa((#Eu?m`;B5bps4 zSB71n8wp>VfVdkBz+OGL>&*ZE|6i(tmen0(gskan{0UmwS8M}uVBE=F;Ij9PL>j-a zkBUHNhzd{lmF7br21oNDj?NGjmQE3s7yG$Eu_@%DBG7z90pvpwl{9{hLuveV7t;8P zFDaz)*Ik4y&usp|P_hu>&gE(R*H~0u{NQC^xGSUbnZJ%jrTGZQ;oc=Gp!D858$>qS zsua62Fz~l5=3`*Mo_I_7(GqTNiV6pRYY`sNpl@IlL9Z0i2SjxT|ygN=bt@(!oh{M6a z@S4N;cAE7eewTaQ$9I9YAuAs$(SqzKl!5FhId6&M&G`)*aiT|oF&RpXQ3owpzt^LBqiaW1F@B5?2(Q}ZK^?(^IinjbQC9|v(C za2$Nd403w&1D1=gxDPfzXJkHb@Hq?jA@1Ychq+z;i>la9H=p?t`HF zn(Yr9e8I&1LHX3dcVgj5A0@WU|_I5#qWCKHCL8H^lR4Lph)UI z2HrXh33EmUh7uX@7M&74gEp?d=G+h3#tJ$Rq5E3*vE~O%&5sxl zK4R)V2l50*_pyVIn3^B3G(R)o1})9uK6vl}GxsqNahUsfJR+dMPG@FdfH?i&J0?{I zh64QmB^-mTF^uC^4Y8ori$|;&z_>pb&V?x*rrE816p!k_G1Oi|@D(H9ur#KG6J( zh5I1)F>cpC+z^K&f_w*PLuvQLgD=GnzT#6pp?snF#DD9H$hX2NgoS6ZM}jUReeikp z&C&-qQy+A@K2Wun2TlJ>26aLqTjIMvMAotxpM1^Bzb^I<=yI-y2mUiK1ish>I=-U& zLidU0NA`^mK|`^^t!5nJ;^dk71Zpg}iMUp)ATkNXfPSwNi_7-oDR9JDPP z)HvQA`ltI-_o0LDn3^95G(Y3$KE?f^`61K6cTC-fnjwkp1Bk_P@g4Vx=0}XoCl5Yi z;r_@C+aq1eV*LL#7ubEZf101$cV8zm<(>eg+>@Y`dy)G(Xr%-PC>aQ#xU~6=0{Cp% zmw!Q5*0A$$ztCIzAkz2%IMBL5w^oCKtnuN22mk+fAL2gM>H4SB7ZjSHe)uoY^{J3> zjO5>bA-+bn@ewHa__rSd?XH1^s6E5~|NPqzai8e){lmX56xMkG-LV21>^gVwr9ksT z`|gX~2b&);e!mqieW|zh0XSJJe7}*!Abp_ufdKaf(AAwR-*13;91tD{gvY{t;rl^Q zl^+4Ri|wHT_l55_v)H9i8XstW$i#gy65ps zbYT2`GmAm`B*@B#3J^mDxKDtx7TiKG4{qU!@5f*ka-V2^rttkX1GOT>d_49gp0pmONMvCYZL$f2cNC;+77%E@iBN%#IjVNOytG= zB)GD$M9|plYpJ-{m+#n7$7R?+O|ByXFo!h15dqaZt^Z42z0(aolT4x$w9`$b)AdQG?}Kpgz3Krk3c;I>yL}&Y ze|XK={O>=1&u`G`o?3<0|8)Z4fiD6<^4&ioJ8KnQbAs-b?zs(;hYg0_fenVXektp%;T4uB7C zer$Ze;iUrTTr-9&2GCxzEY9E;yHYi_Uvc&zg<2S_F83f2FmcY;Cob(gAS zF^0Wxhgb=+4|Lcycoez2_Ca_SXV?pEh#ct7&I9}{TS2?{QJez`U2wypT>M1@$T@#N zOU61G7#I-4t`k55w%}pc669gm^#7$#!ohd*J^;Dm;Bv6XTMv{fg}?CH{QrOO3m4EC zo1nTV^$dLUG~@+n^b|BM8vxON2QOht>7^HF0tz%RgcyMR3OY#ud=oj?Nraxy&V=_BJkf-qZrg>SAiVW#=3vQYG;OSSCQr)QvCg&Kv#^mfJVKWfAH0( zmIOeqtg`~`p3-c7!CE5P{DP6c^*AWnT%Y6^x-z^JXJlaL^nGv~%1wkwWq_nW9bAYM zmDz6J}CjIFa{;J7yKm&%`Z4h{J~~tLky@ebY%c#$n)K$0>@n+urM$% zeBu{i=yv7##4qUj0>tiheE?#A_{1;3764-XfFGCi612PyYS&B9-qhm|3tzAK#4o@) z18layCw@VOmmoJbzmVo{nFY#sFBnUln_q~Qn1bA+-u!~OL{fJ(=;8{{m4p1P=RpHh zt{foCU++8a`lQCtmEkpLA7=}QA#mLFNe_s@e%$p5n)^Yc0w8Tfy1(^6Y3vK9SWw}t z2wIyFaNP9)XlDhQ!K9hU{o+Fm$VAX;k5Bvpu0KBU3$lTB&7U~~?T?ihk}?hR34c@fLWzz{V1rj1I8Pq&K-PgAWwJXC8P&mIV;s}#F37(*{61s^c95412LEW=)!f#F5K zEAZAmSB~x*-L5>lKwgTBG(M?(C=j%7jzz`#P^te5LlMw+IZy^N2N6afLKnQ@FPLBB zVDlS+Py7+!6#0o?&_#vg6TcvjN)}HR$BP@BpgyI{>yWVE7tdb)|9{t&CB6-q^e!R8A3fX!n8nJ4giU0Cpod0=xs zL`H&^dO*jfKvZb=oA9vUZeIcJlO?{O##=4VcE`<8+Y~_am}*>4y4Xw9xek;lHy>kc zKF(;eZSd#Fgh;& zB=T8YQ2UzSa5O*p02?8A0UF0R2^wT@QDMO|E_J~YG@_&-`T#=9I#_}EsvjVHQwA^} zJfcGFajAU_3=Bk%OHBZ~12QhP0L(@mm)c+j9;~^Y#;>6(0FeieODTZaxW}aqfaOug zrJCOeAP-F;k4vTT3qyxQnvV!TLl-n`767&$d8En%G*T4@9jVGm;}-%Ct7!1T0vr<1 z;DALNs$##(T4CjiGD-zf3>&2?utFK7N&wp&2_2;p$1+M~g*HkhgLRZj05(b``Sbt( zyWlY@8IT7xUCDa5+w1K>ut%)n-5+;y?f)O6BEcmFNK*I7$VS}z*x!;vKXWd z#VD4SJYZcgNr)qvL5^Dw6FYqKz|DuZb>CUJGTgg~?z5>k58V8Nu&rw6$m-|ZW+f51<-Kw5s|xT9Cz88kCeo<9w=dbsmH{?fK*5|RPnKv3Z`|> z1+DsMIM3AZ{NHB#*DPtf?S<1i=f?g2|NrJ%5V<=JIM1b z!ov$cFC6STsKS4pf8T+|hb*8iDz}(#G#?fS2ny`xhBR3sqayw*Q^C@kCn2`pd^#KA zn42fN)`Fe!^upf@N4t)y@L%tGfaInNPcA&+I>JxDWiR*{85nM!gyx1`PlmfUU~I^! z?%@}p?XIt1fRf$KcZVlH=oWBZIDGfUgu6FxzJQMar>HR8-kbFQ|Nq--LFBjA%>V!Y zJCtxh0}h%>8Sb$9S-UbE2Io(N-4Oe*>F0#%f6WeM+&c)fasoE>3O7$;6Gk_N@!mm* ze;_T4hP|MYf}tL22_x6Z!{G1$rFIuN;}< zly>htym|8GgPR{fCCSadcW)l<4pCugd;}T-Yd%$<))}J0b~8tX?eI#_$$cek;KY6S z4r>9ZnFAU_Kiuuaq6%tr*n)@>=DSQFk>)pCybKKg>pNXk*t(rqy1Dq5oZvqAkh{}G zg{6~6<+hGW^ARpkvx}kIiREy&iwXyl8H`|o!_cN0^GzL&nsV`ye1N=*3|kP&SB{&1 z?#BMO>-qz!6$HLs4AKHZyI%}+Vl-k%BCNZZqt{s?yt`TSoONUT1}{fL_;zfENy+5~fY z%~JvX@B?55s1M`}>Orxn{4eGSdtuEE3IvsS(CwwhXJ7c<{0Cat3%c|RwD?XOM1Yrz zNW91ifb~IMbH9iOb3k333{bl|{KemU;N`)f#;vo2@!9ye7fcAFKrscu;E9mtHyYi( z9NnRyHHANozcoLX@2vd+TKpgcx?zqN?APY!-(Q{sZB{#|d}swr3GY5oB58j9`{hn1 z28M438Tnf{85tNrXBxJE1~a-3?E|H1@RS4iP)z>zMGOoKCDpA5O1!}X3H+^~bK$|= zI01$!`79d`T0L^w=#+e+)QUpfQa#jvj*6LT6}^GFYQ6j0d->$ z`a!xuD$9$Z3Sq_wW2!B4fT@NldIuhJ;bCAXwIJxOLyQo2f!qqU3*_GB=l@ z2SE-24<~fj-Y`Cp#;<>ZfBFHVlb|cCUGFtN;P3GL-+V$Kt<&|M5$H_X#$U{T{{OFy z*#)AsL*E>C1?~D{0H1HweZKi2V+mX9H-4AWH{GsZ8fyPDfCdO%UEf@M|IHP23ecBs z*E=1)pri9jI6)`gGBkA7-njUp)AdgCE5_1&-L79i_SJp>4Li8rDB(whmg|k~+8dzp zh8Ha-OIcbDl=#1>Is5-VcxI>Gu0*NzKnV|c#-!A++x5e1aggODY7Mnt7)trSx!z!W z&ED<$!Gy8pK#5@UamLQt8_l72Ahx__1@+5cfENDL{(uFHAj4}`a7Z;j|NH$OXgpc~ zw3vtc+aZM#w&rsR&ClPrekXB|kQX6<^9yKs1m#6Ru;T64t!at=?oE64tR z28IL89xROC4l;qZmT>H!3=v=gtxy81muuhjMiDF`xW?(b$Wl`5}j)7ewUZOQ;A7OyuB8W~dMoNQkdH zl;hw_R;Uo8p%=#sk=y_OcV7S%73`p8RGvHn-wv^qu!B~*c<^w1I|SNs;mXnM!NcES8L05T<`Ybv zjIVjYbC{re9XOgfm_eq2hMJVY38{qN7Ss{|9l*!Ytnm1?6jbZ;<`XQhxuKlb%_lfI z89`ylY?ZqT5YpaWc&FGsgy0!&c?SXO}f z6ThHCzzeOLpd%MKKvyF&g#Q;U0WIM1<@n~vAyC5HtoHAlBL@eF@%x)22MdVt{hK2P z6NvHtnf0fph5*LO>KF~DmYqf4R)&IZ${|BG@+R64>48;Eq;YgGIH`TzfJ#)B`Injf$?zhEd)0FAWpf{uJrfk?iV0crXS(gZpamBhJOfjS3&W>k7lud0E)2JdT^JxW5rhQiFHl&% zU@Q>_*~<#DSK>vzC##n2jThIigXTg&LqMP*(-zRl-ylmNgOuP4P1rm^14atR89;-5pfy6> zEJycPgYQdhJy5a@v?b2PU4MYfq!*b; zLJA;75dVV)vN)RGfZ7O7=spEGEsXmhf9oXB zz^pGv_aRl#=pgqA{ua}?fWGjv>4|7{y5O7$`9WM*pv@OhV+mmc zsLXQZ0lCZ&+!SK?P+w{YN==ZYq<@0H9n{eTxe;V?J3G`Aki!wCfb@T40PQtk`0$^< z6|_+o6aoV9#to>Q)qI3w#e~vaR0+W^pcamRuK=jo3LcPk{gKA6cM#M_s&eE9jq-AQ z;*VslfHVPJKYZdBWKnr>>+}ErknvmBAK>L)dafV9S|HK-niCw~phJnk*71j*1o@y$ z5#Ij$!B}bo@(`kN2?88qfkyHc-){4 z+yuZC4yc-O-O%ZJ0HnRwjUym1ytftP5J>Mw=sUbt2VKX^@!#x)?Jw|F(m(OWXX9Q>JOl5$fU^N;&G}AH7rXnK@d4$F z))!07LGi%>9prxz09sNK3GyoVkU>5Wi`Dpm!|UiQrq@haED^7Rc7PT)z4qqc?#tKs z5VTN;`%tME=)}Nh;Nt373Fi(_d6gyb8Wg#%9LTNgD)uagh%ANI>^ndmlq`wiU@-5wmw=d6Dg zaXB>~(6GK-^a8XZI2x@+3hjQA^)JK1)0H9PL9{bN3TT5R1E`rF92O4lof^9SFg_a4 z>-r&OF=#BJGxY_uV9j7)aA0^*18!Bav>qr40p0x$5(|LH1c8^baOvFdhEIru{U z`-SEQjK^I;Ti5=hu8s#4h2WL;#wQ_b?fIu1>^=xuU=LMpd;n7excE8)36Gt=Q49=e zmK>$B;6Q1#3~*&&C>7WRnsqilkY*Vu!9V2ysQimP9NPWnn=1!nSog={Y*TDq8A`aa zc*0(2fwn+Lf)*1WVqxg^{gToNn&D!Ij0es4K8+1L9FX$g6y*P27Zo1u6cwJ}u<%Ze z?ib)7GCm4AqxiV%AJCOxy{=y%Aw@__XX=OlrGGGVLA(Vg!@6BmM7R%>YIOUk2!LkS zj4yrv*nI;uob&x-_lNGo-&0fsx=(Z;1JTSEU%Pjo=#Ehl=mxFybW!2B`10cIi?1%; z;67RU<@@LE58qQ%M7mFOyQm0!f5v>Vh|fAig{PdOh~L^pg`zWwIc4_ zAu0mjZ+ySie1oCWMFq5w666ON?gJ1x351+XXNZaf_kmK0ZXXp1kbby71-^gmzWmy; z`vzDhL`4MT`irkG-UR#WcIg*TIDAi0kpcTl0`4!7a*iT)YZn!PGDbh+OWnu(OWC2G ziH?guBmiyI1&4#3D*$s655h^Hi3gr;7m%}Rg}XykL=aLEogv^@k?!_^xCiW77ZslG zAG;43U-GZ?dmRjRum~swK+%Tg;1l0dR3s*XVgnir0_7YOCZ6Z1Of{2OP*L zpn&6n23#Dnt>Iyz#{Z4qf?|mKK&_~|E69V0fFUM|K}i`iiXllEM7@-+#C$J51E&*uVdvI6^XS>7mOH4tHNL zJ^(WB5!Ae3NJxUyJt%MRfTPbvg#(h3UI*aK&!A)^0!l^#&}0P4%%Eh%0Zv9>Z=>a8 zP-MP*W)9o*51J2#E_vf``U`3g*K(AXgYODIbnp=e_k}e6yj!363vM&;i{0MI&%nT- ze7^a_|H}`we;Qx<%%9Jn#{d3O8h^>fH2#v)Y5dnuDW52nNaMeLQuze`-h<4?TTk-4 zUT8k?zxlYp>kGkY{MT~Hy!B*>f;&X8^mQ74-l68>0%`nK$?hKC#@Gj_T1{Qb19`8cBmdkJWhEmQaLKk-Q8yU?&Jis#?vqQcRA;ot+b zFawSCgWb`5;=l5#%MY|Ke&)~TLJhUo7oj1?0Sc)@0Wc}T7Q4b_@tEpzw5!n z#s|7wR5*gWZybEU(H)|~@%<2};a?)!#npU>(du+bWXs8tK!{-JYwjE2-G>i876{|M z(ap90|G$5A-3PnB8=q$W!2GlM#pQr0Skf#mrfpDDZl~dfySOr9$u*+ zz`(ErG%&^Qa-#d-$-_H91576mPnZA-uU;pfZm&1SCtl1s^zZ);6&F{AmyA#T{YR2K zV|?O8{h@#VyS@GxpLkIUQfA}o%JA~mV-#gij8D9XfJ^R0mHc9S;)OLxvIeAc0jlH& z;}b9BK$34jlFg`+4~$Q|U<65;xVbXCOhc7yFh23($w8RYZXNvhe+SqCdsJm03-*E} z!Dc8u{s%r;1Jr66K6r%}E5i{lR)z;&tPKCWSQ&)8SsB#4Ss5I>SsB8-Ss8M?SsB{A zSsCVdvodV(W@R|!&C2l3pOxW>H!H&jZ&n5dA65ndA65npA65njA6AA4A6AA2A6AAQ zA6AB0KCBEYd{`Ma`LHq^@L^@RB9A8$36~3$tTYOm=4*0S%obzR6xZ}&p@XVK$fyIxNLClYpLBo%g z!NQM~!Of4AA!op~;Vxq0f(%VUZsz!zMpgh9iEg4Cnk<8E*NpGCcERW%%RA z${^&=%An)V%HZbD%8=mC%243X%FyJ`$}q*Bm0^WHE5i{Ier0U=Un^g`0!B{zM9_KmTXxirT16x-%5`vmiyc1^G^JoT>9-9 z1qt7GZk3mue9c~8ep__ps@C1APlVq;-`PILKJE#};=uFWYri~`iVwWIV&9943X+LA z601*f-E3Mm4|9xS*Kn<&Es^d(|td=HtcO_f%UW_S8sFMXWnO% zDEo5$M~l+^y@g5D=`;6mP7PTyqxtK~^PEfN6IHhq&O4!G`&lXcL=&|QDvSL5`A+)@s`~|n_Ac}oN3}!*!=72Hq}X{zFUr)d7O(=^jcPu z`lVKOkM*N3c7hQCIV^7Tdcz;EJbL4PezVqJpHPY0_pI-HiN5t&>V#u{vGqTj1-EzQ zr7nHJv^3`x^S7DbPkV0{44m9y|C6nCrQE5MAA(DzPJJ(*`hdx2w)3h}J_$#z_UmdG3G@zXaby99Pm@qPWasWmQR z_Rp8XXWJ$P@y&QP_>n{GB_M&<7PL4SS%;onF&AP*CdF|xBdl@V5s<$-V zmE1V}-Klb=NQL+R&)?mv@}uQi$F(B{;^lK^EEZur&bpglnK$1&{EbPvW6}%B(wk{A z+1-Z))#iNHTU_+w`-y39CLP+laE8|8nL8FaZ@;k5L8kw~76ta{&g<50p1=K3!pfvK zZ@9ymru{TC)iGax=v|?wS|7jq#$Wue?tJJD&e`OqepYjlDSvF2y+V($?ZW@96KB2% zc>7V4;hoBat?^bRYS$O3^mcaKFjZ3ON{fxT*WB|<{n^gfMI2{?y(japJ^Z8QU(0ol z&--i>)I{OxiREmA-m z3mF&~6v7-B0%p1}G=w`agv@kdco5;h5Hr(-!6C|lA!Viu!-8lBhMbu$3<|Lh3=JTD zoCCuY5I@0zVFiev=)kZC#7}l$xB%j(I50e!>B3-;=D_e}rVGP?bO#2OSuP9#nGOsh zvs@T1WH~TsfcQBM3^pKst^-2=h@bDkkOJZtI51Rz_(cv3J+oXG9uzw;ESTlOP*Cc? zuw|AD14Fq3!--ig3=I_y40k~MDhGxSAbzz21Iug|28LP(28r1&3=MS-3_2iwg9C%Z zY!`+JjSdU}vt1YznjIJtK;i-p3t=DIL6m^m=G%ynTfuy9}q0f}2WFr>_N zVVGd;z)&*Rg+amAfuUut3&RFG2Zkvibq)>;OF(=_2Zk*m^PC+Rj?8soxZvWzaAmFw zLx7tD!xIqS-GSlDTo(obPX`8uc`ghMUJeWb^IRAfcsVf0%yVHl;N`%eGtY(LftLe= z%{&(d1#bripLs3}3EmD25g_&64h$I}_1+E)HS=5;E_gdI^vrW%_~7lpFlU|%!v-G* zhBfnC7z%tH81~F_VG!_fU^oL(=i|WeV4e%Z1YZY+FY{a&4163IIOe-BeDHB#keKhn zu))`XL1VrPLx7J1gT;Io1_56O29NnJ3>SPI7$WAoFckPWFl5YkVKDG@V5kA<^L1dD zFyDn?f{z2k5|BP$2Zk*meSQuMM?mWQ92l<5cVTewb6|J?lJ|39cmp!W&w=3!NS~hr z!yk~nehv&Q3tSi$_&YH0EO24?;P1d7v%rOc!QX*FXMqcYg1-ZU#R3-w2Y&|!mjx~i z1^x~U0SjCh3<4Y&ViveC1OzxRT4oF>~1H&7Ty@3u4e?aC1IWTZ6bYa*KG8=)$*FnC4CrDhsW351BTRJ& zF}OM-Q!@;8NMdkxaC=LNAa=scg7V>dpnQ<};@rfX9GFX?ZikD3Oa_Tr8pXrKKt4hj zgQ^3WkFE|y45|*vUXV-RZiVWFiy`TSi-Ghem%tp12wR94$O5RCrBOUY4CG*RF@!ph z9q8&1VhD9Gd%+HY`X8hZ#)s*F@geHXOyDjB=`pg1PcDIoflUU9f!zra1G^MW45kiZ zKB_uoF_=1py(LB9v%m*m|NrMs? ztPDZ$L9z@CVD(4}koaH)$r*{s8Hq*)@yR6&aCUKVsu2SNLwZJHaYlS{Np5KlGTRtU z&I~lw3sGB;oC8t}*9!_R28M$CoJvDu15>C`Xne47Xkvv3ex@OKZXh+WA|8~MAY~>4 z1B?$TyWo6K*d}GB!}*}N0GAh_G8jn@x)?|wx)?}ratQ;%EN~t{@IiV|I z#CTB9f@xzz2;bNULYo;eq$bA~6lLb7f)#=M4Cfnz>obr%$dX(`Q?Obv+t?7nhMEBu z2l+WUKH13B)X)-YU@C$SHW0xFnaBV#2dX|7UEU0o{*csz(_d7>g>tf2Fs%vaete|S4XOyPk>!e@I1=^kK;iwA= zj9?E(T~M%sXi(+u=o+kRXk?+_?BuMFnwMNuSx};&k(8OP$-n?LC)Cd|%+b@w(aFb^ zi-7@IeM%~-da#_O5mvL1<*?~9GBv}g4xkHd@0Ks3gf2JV7GwWj-(#$MRfa!;ZAOk}Hv@M2YB)S;LSah*MklhHqnTDpC3=FQ05eneC!N>wuy`hLf zi&hjdkS~$-L5l|zHP9rDA_nsST(6}Ork$2X8W?t38i7L=Ss#X-mPQ&Fc3K)~pxbF= zYKCDaNDSRhkQlN*A$(BmAi@kJhHfWF3}$DrhoiTvs;+U0f<|UuR%&vIrUD8;ZiyhN zEhx%QDNRmARgA0_xgAqblvxI9$)JdpCV_;Y?G$g_Yy_drj8OFEmgayB zR4rD}a0}36aCKIIH}>FcV?%_vnGq7(1k8rDXB7g#%{6o}V+#`obTLySLu4^yLrlG3 zF*LnkF_>OxI~L?quvsuZxP9sBtN`Uh+Pz48ba_y-734mcdT_h9I5j6twn{ zJx{+ZwJ0;KQXwrdGbc3#)J8>)Td;~^E|hSEXaEN-gR8Sku%kk*p()gpP(Ii*p!O}4 zZ)SulZ)SqR&qUJ?;e!GQq94Ks1rC&tW_~7^kE9;V2dM|il;p?f=I51Eg8DPae#)hSK81^i(SaQ0NsGq^71QB2Wb+=A~qoWu}xS=780JC5o-M7!(u~R6!kp#GD+EGho;O!cc+G4*d|C;Q*L!Xwh>- z2Oem^8x8oOfdDiRf(9bc0Hd;Ndgto1@BiJ|HKQ!VNT6a#*7dOM$6wqoP*8byZtubM z{54;-jq;#;+do> z_swCm!-2r4IJH&Bx4n!N(7zTe;=4>UFaG^}q33VY^b|+*}@ur+-~u?OU?){5|gk@7>=D_UzwxtZuf( zFZG45S`FS`VU_J*vAl5Q=F^$CpZ%y=B%d0#=7@`u=9lUJwVanLPg!lbVDg{Ck z&hYftetG}@Vr)yRf8C1w2hVi=i8wPZUMR@n*Hjn$-Sm^y-rbk3YfZe|_L`B6n}L;! zpM{f;nS+;!orjf!n~#x&or{-&nT?Z&pNWB;kClg+i;;t$jhBU+i8BFoO|}4s@PZi* z3>RiNFf`0@U`Uwjz|b()fdM^iKRmp27<85^lL%KZ!$JoJgM|(Z3l=&s99ZPQ@L&-* z2{05eFfcI72m~{%a9}W4;lQw9g#*KZ6%Gs!Rycs=SQG?;1y(}j99AOaZp>pn$bPlP zO#E(vfn_A$cSG(2{{=-OGM4xMOj+XpYhU^^&aBpT>AQa#246;!8&{O z&1QMYvk#(Y=yy3ybTKbH|NFq!rMI`fj6M`*`BCs=(0sz zF}FH?mIVdc&B#4wxZ;F5^M>Q~k^4V$KRD(-arxE2;Jw9uX6&Hd|&)?-=~VgW1zi;tOg5;FRXK5Fj()vuwlIe!-e$@3=A6_7(jAt4hxD6 zHbCSifW)A3pm2|!yZbaK?6ov!C4s^}iZOB`C=PDC(H8~9L%N!AIw&sMy|(m$;)7R@ z=Qb!#WIeXJbDZ4s85B3x%TKj{;z#?(lz*T&`e-H_4~nOYP0!YX;z~ZpP8$?o*?S#- zgW{}Gu}&BiZ%XSlu7l$4Z0dVuQ2gmz`@R9i;hx)_ji7k6*y`~a6qk}0Shs=VbGEt=XX|r0>$;lX=2u(_%;*G97+&@0WNS`%2A z8VX8pS_*~XpftDR;%*~Qx;t^<(hgAC3tsIQ2ugo5U-#VyrNI>*vmb)eVRF>TqoA~S zy36q~C_NTGPA&(f$;CT1T?3`dKbzjig3@M!zPK|eeHN|$un?3+-&m$dfzqjlT(UAK zt-jpbbPtqXMJtbO0;O5);G)N%bUPXCHG z5kvz@Xut&xbf5u#K3*PfE=~@1HdYp9CfMo@28JfkGJOUHhAs%*zyN{_3=Q27K4=vP znAHds=LGW@8oD4AECXnFH;Bmzk!Rpy08h;`bVK>wAW6_3Bd9)RD9r?=ArwOc7nA|j z-vG0(0U{1Mh84`>fSB9xgMonobh066_p^YQBZGsOBLlLSf`lVOfCQ@82WdwJ1sPPa z2?~x32NWC`3X~lg3RE2#4rn=oT@2b*4rV|JkUdZ)m;$eX{}0;Y4dybWRum-Wr6?F1 z=_XZ{q$*^i^Z)<<&y0pqRwZ;X{I36x3YohY7*ZgnBS-;|!+aeX3Val_ zagRi%Y07P{C^#d(baii$p!x3`a`w?C2IAdM)ijhBb}i9-^>?0SLf7Z5%U;_vZ4)~@ zZLYz6UXL2hwAISX9O5iA~m)Je-7~5 z_$lIS-q$d@H2v%B^+7(uDtG#N&%7-^qIl^q$E)iHVuYI-4fVA-o;0vj@pReTQF;

VbH2{iDGC3eu65Y`)XwWM{|~K6_1g;yOArPv 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 IKK2j*064j)HUIzs literal 0 HcmV?d00001 diff --git a/BearSSL-OG/Tools/testx509.exe b/BearSSL-OG/Tools/testx509.exe new file mode 100644 index 0000000000000000000000000000000000000000..791581cc3336ca75fbf3c4a5a8c00b5c39dda452 GIT binary patch literal 198656 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�jXgRc(D#7+3otL`7lfKanRiXovwdMH^fJWy_f=$ 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 AEdT%j literal 0 HcmV?d00001 diff --git a/BearSSL-OG/XboxOGBearSSL.ncb b/BearSSL-OG/XboxOGBearSSL.ncb new file mode 100644 index 0000000000000000000000000000000000000000..282e38ea001a4bc659201ba860d6ca9532c4071b GIT binary patch literal 6155264 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⇸*q@XqiAA>JLAj5tu1|%^dhA4*l;Cy%_o{@ni0g~TJptN)%gnt-H zgYqH1{6%g!j_Ml?fuR@z*z*6`B;>pang3HtM()>x^1lMZXB2hJ3`z`23?a$L`IVKy zj=_}yoG;<|nvFq~!G>WrsD6d#Yc2*4h9Ynt2IWtXdRQI>)vcgu8aj3=y->v~ZJIfgR~e?j;Cz{?IvhW89yj7?6+ z>SP&s8I>4~osq>98O#{V7(+m3`@{7rGn{95!w_VNtWKSwl5qm~>`+kI^C1P&e&AAP zU}#N6u%*%vZ2lBRhV3bg47*Yo8TKNnhm~QVag7V6kh4O?9T^x@92po49U=U=P7Dky zofsIlIzig@9?poiJ+i(mO9lo|KcLbQ6epv2Gz6#<0@(7uR61t=e`Y!((*2*1@qbqo zG0^ybJVSjtBLj=L2D}ZQ#E=E9*FkA{V>)7N55$j2M;-qko&TdwoQ|3@8UnbT8ftvr5GEnpX==>kCu{Nr1Gz6#<0@(8Z zdr=_d7X_RpP`Ro6^a-KLl{FkLkWr)7egjPF2g)i1_s8tu(d;c3=_ z1mWfhFvu}@!OICy|2Z)WG9LzFgZd93dZrlz!+dKwvn1kFVU}JD*NMiVnqK<>Xmcfys1x1XD zL5snfVJ&DJ4rDy|>`*?2REAQVc^x^A!}2zAUI!U7ibq3WGz3Tw0c`nyb`EC#_smD` z*E2D^WB9-@B^Oy8Wc*(=4_OQ{{yz;x3^M+|7sU?9_`i5Qa(N=m@QL9+!wpb50dEsP z#{VDLGa!vcN-{7pnlq+?+7obf(%^CZT{g(->|D(puC~q_b zXbrIC|FlBP^?!fR@;_+&|00SQWc+_2NbLWAe#kyy(D;8ALr)2V5!m>DE<+i- zOh6z1e}Ys-fX4qfgUlNp|EF~_7&U){h5)wwpIn4_{>QH(QB~ z$oZOu0W|)97nIkL^1lN^JVPgnIt~Ua20Mm8kQiJYX#C%TA4c!6I!0g zFmyBeFzr-fU;vd9O68EUAfg;mR)ETh{4&hB29WsnGDe2;WsD4-9)=ReHpZcRQX)lu|)I3PO7G}_7xX;jpA|}D`kYO=n7f1}=PLO3-%2*7q|I@1= z`JcZEk^e#C2Zup!z%q{jD+3IxFxvox#D;p@kGg*}1km$8s9%4&3bcnGbe0w*Ue(KcMg) z#iJoWzYxHd|Myj6*8i_S`5#=bgYr5g|J&3cmkFT!Z^fWkgIuqpp8v~SgPQ+CYEbh( zs7+2kpO4x!8UmvsfGz*8tHJF5tJWgtb;$X@F(_h?^*`@HWdgYW4=N`>>wml$u7k=1 zdstf^|M|Z~wTLnT)NW@1*@30qJ{ohQAut*Ol!pMe{C~I>v;ALJhn)Xe7%Umw8CdI) z#n>2f7>XG#)gib4*}>-ozX9c8ct3%Yp_E}dgB^-qZiZlnECvS@J9rs983GxkZ9!-5 z!ulP846_(E!Pf-o)G;#bsbhqns|z}>3)HUwiDRQ-YX(5)=u#eXqb7`oz|ao?Z25n4 zJ!buX2PDP>%7-97gU|WkQi7UNQ|8!h#`aF5Q-QlgC#=% zgAYgyUM6re=rfoz=zz}fgNyMqWHU5_^E&7}P*{Ej<#!kx8$FuGLGd$+M?-+P5WtrI z`S&s~2%tz+lK=$nbp+1A`C~Y)*iIL6bp~LBA2yPJoF)#tGZi7{KTMLG&^) zL^H%NNSedyaFCnW7&sWk7*~VV|AF`Gg2cEOelxHzZilM_l^xs+rVN1$M;c*seIPMD zh8Ttvh8Z9+CeZvpNKA+!ouPtZGe`_PCjb%?WvFK8V8{oFF@e?{fy5*jx*29Nguul> z_R26UWcbbiS~~z*PXsz=*ufmKj~6uWht3D7x!lOeaJ!L_;b|jeo}rUpz9O6QC26bruht>ZK49X1344O@h3~ZqD zJHYF8kn%rVFB5|agDFF36LLR+nc*74Ert>lF?I%R21ABpa50d*JPf7`Cm2>YA@?VE z8BQ}?hUZtD#iJpB83H)-KX|Mkq8^_Ak;Fjx-?|xd zo&a3`qvikfX4pCbP(94dP|Q%y(1s!g$^SP%VsO2n{GZCOw;476XD}4N^FM5@&-`Z8 z{QsdDHUE#!D?s9LlpGBK^bo+A|H1umh-xhcEe5X^Mg}1yF;M=GKobM?3BdgXBy}nb zDh$ajnBxiHasuA|XJW8muw>`~se|W#W(HLTRWvac25kmy2ANh!p8&GQn3drI!xe@A z6fsT)eFjs8XDzUH2go1%3|0&W87x|n&oL5UIKpriUY;CjVPv@0!pHzyLzLEvC|5vp z5x+s^jm|}Y0&^4(lMuj`|F^bc=GQx*`~}X}pgNqLL5?8@oNqw+A_UZLN6Qz(BzQ)> zF&YBHIs~xgf4Mf$xE`#p59!wnwj+=AvoP#r2xIhVN8ZE3%Am=h!|s4ao#O{8=RoXJZHx@p+ZY)f+87x?`atIofbQx9jq}0Of$ru6sRhkP zfYi-2ft*p?Yz?``2Xs!suufQ`o*NP&fGz);Fs`R-%Y;F_<&> zF(h;#_t&`@0vRH~?F3L>=<7hVr$PLE9jN{E(Q&#Vkz__4IgCO8TmBdA#LWLCo#^>r zg~1L*47C2&hGA(ZYW}xpaEIsru1?haAKZzW|3}B^hEc*A^~#V40c`pIBPjoa+sGg< zK-&MMpmligbNyHtpU@L^}LV~Aup3R=Sh9>W8*6Sx>+7^X2C2er-NVmu5p z8CJl{ga``;hExkk+ZdS*Ye$3H2_QDeC8KyW1V%%Ex*>oq|9f;{*8fMlQ0xD540jnU zdXUG`*%*`<)ETCO#2Dr=K=$>sGw3iFGR){gZWC}Ym@&9BWP#OnLDg|GcrrvWWP{Yf z&khHb9k~pr!0J{&)p0ZAGc+)8gT&zD2|Nr<43il)b|brmmtiWyG6r{$7!&M_5k63< z!*CBI2G`5au$$ow1AjNN--H<07!?^yP{hO-?lXK~kOz$&z{@cy1{FpN##^BBj$sM| zWG+IE;WGmZ%6P)pE=C5XZbk;!cmn8tb9@+9-l2~*fW`}OjW2-YK;sM4O&O!6jf4=u zmjCs7F~|QW^dgVVLHhp@ATfBG0M!5YVL052JpRYc;Li{auj`lhqPG9@dQsc|qy7Jp zkm5%DIG92JTmBdB!>s?q`jG2LQ2tk8=md#@`w5V?zB+>ygKZyjU5~o|H@6Qp|IhD3 z&HtnQ|G|_pM%^+JLI7L-{{_nbhnGXw|3mu!cKwVDj9@WPUT0%aU|7PS1`>m}hXojx zGiZa`zMwYjZ!-plhJHo{(P#z+&{}$s7^qFl=*q|d+J6TU6Ax!(P!DHhSme&g@X4K# zVU0WENC@&#KaPgLpa}tN`Tt};X8WIW0&4zOWthb98I=FwWr6_1R0cM9{`Z`~IGXmYNO7>pQ<7=D1n!0msK7&C)0gE7M{kY01x zoRlaR%P7;+izFdRb>6KA-`pvCBiqE~|99OEU%^(g9; z7;G6&gUg+p6B!u{CowX7p1{b!bCZFA|0V;&S~Ug+E_KNK!qiEO42vhBwn>N)OPvha z>o?kd0mbtu9!?>EE&s2Y47&ddv~CXMQ%L*&5-1;n_XLC5|DgWAEqq*$gM*Plg@cj7 zk7Km`4hpeRJQ@N+B?P1vF*0y~9IL><0NUQi!N9`+E)&)*1NZ+yVjc`05V2*CL_z!d zL1KOkehiO17#M^YAZG`I#8??v8Qy}#pyvdD#Ml_v7-Xg(+7rwSkn*HsF(ZQ@0|SGD z0mxn^22KV}hFvIP%naNN+zbm*#8?=(7`PZN&SYd@1JAjE^s+JpG6XWXfW^8PAns#h z2w(_cXjuqS$H2e=_8U7x0Am1S-W-tFCa5|t260Al#+X?ku@z7;J_cS!UdAGjo1yI( zW(Gk9a|UyU8z^GJ43-R*3@%fV{U*v_#bCwo8bwT;!J5IE;oLN2b&?D=3^ojJrz49= zGuSfNGAMxEG7st&83t}fZpLGC85!7I6p|r+lVi|g)MA_h5@Xl{Rj0t9#HhsBz5wJ8 zn12-++!);$W9EVOXoq@2^eQvxGU_t+fy7cvN+DvZ40?=uj60!vA!6zbK8!w$KS6es z`{zKyPlG|5QJYZGe}5G>~74AHC2pwFn!_!%UYr(gvU(`7JVG+^9< z5+8aD!HmI-pXNi{3{hvmV9IF97zT9<#9l)N2Sx`*HK;m>m=S{^qakAiikLBj5u*`f zH&hH_o+*PdqcP(?6ftuK6Gjupr6_S}$zZ`?!JvX-uN8weqcx*FNFB6|%gkWQV8&p^ z5W1L=frSBbo*grT9m8n`PR7e9V)hJ$3?~_$E@Wh2hvzK^1|9|;200XUjtp50`3(At zKzRbxW_Dm;W^iVZXE0%yi6Z98z{eoVz_}P%ojXGaLkvSbOq~EIFL*LIF*qT_!0Fzb zL4i?$@j6VM0>}=3hIocFhHRLa07xv5!G*yEAqG|#%%H;9!^C9B#=vCB!N3&F4zBaR zMlvugv}9la(HyfF8H#2yGJK9;U|2GTkwH0#fq^HGfuSFijsqDOI0GU4ZJv;}_#q7j z2Ck`$;C6W#l$MjeS5vW*(>vV`P}J8MFRB zh9U;3|JS03LF)haE0N8E)c;8+VvzcO(MCoFws2T|$j-2waXDkp8f3j(40()sj8&_U z#rPOf7*iN0ptu=Q|9?XfgVg^?OOf?L>VM8<$YPNC{|$;5r2gk#fvgTv|J$LsMTQ}X zF^TcXTGaZ#k+G3+6G#jm&I$~bjFpT_H$cu~fYgzS409RhGFGiat^ZpXTNu}X#E|O$ zR>oGw>ma?Lgb1!P)EO2tE@l)5sY9y&n;4rIJwRee^?x&CGvj@*7^41fV{Bs-T+hhB zhE)HzGqy8c0>uY2EI#xYRxz$(6ad)^YAAy3HDKsr>|rbci7~*`88S>~oX+S1G7m0h z#L&Um!B~bOX3WsZ*vYsODh5frrVL$-U5s}?Vqu{A6;wx>Gjua{Gag2XOGy3igkrB1 z!z9K@jIk){AoYL!Cd3)n%nWu6oQw&K_ctTA3G5l#7}yz2H!(7>N5Jfb)c>(4>Kqx0 z8Cn<&wt(^kNFAsihSdL?HX(~a>i-WYVx9~k45dR2hSkB0d zqBoEsgCU>6b2HQqaQz<)uK(d;;QBw5p_-AMnaO~Sfk~NzfoU^l{jau)kzvA0Nd13k z4Wj;E3rfd0>VJ);kotNGl(t?5;ma+D(6%cebonac>VM9S5cRaK|3PIXuKHhM6C(rb zW=00n&Dh%kAoi7|1Iye8(EG%s8Il>Y!F?4_+x*)WMg}))#5x2J zAGDShM4#Hq$Z&rvBg6l#kbDagYer(9XM>3AZDVBUT+P7Xvkk!)`3&Jt+%`Jy2}(Po zc<6U~!C*L2x~6?2s8ec9;bcgO4Y&fX5C4L1L^hb*$jA z!%`IU*cdJ{Tx9Uyi);rwLn>n`;~^Av9N<2|Jdiq26ocDUoDAuV>5Qw7LdLHkZEh}x z1g2#Ll7~Df7KXjnQNK1qKIiQ)G^mFKY;3msMBJY!#sys0jdsSo;E`@ zb2W1yikJ>V4Ra0i3#b@GuO34^b3L=vVPty^7#f%xm~W%Rhatma=EcmCDE1mNv@*9c z*Fwc0_L?wEV4lG23pEcSX3EgW+{j#yB4)e7b2IZ(6frA?7UmY_ zYoPcA*N>onhYfg)(Hq5HTZV4tZsr1zI(WKw0FN=oo?>KRJO=9%xH42Tb~EZ62jvNv zm?y(T#ubdak1;YZvckmt81fiP8MmHfWMDZ48=v%NILj2t`~oD#1``WlIK_CH>D6)M z@yS5&_~ho}j0`NSFm*u;>lsfl2A@E-BLqA?DGzcVI4^+uEMegB$(tZ`ATe-%B9dVh z<7!5@7`Q(X!_dyQkxd??ZUfBC2@KMV>WsB0eoJD|WHe^H0kVS)rY?oSl+l&3AEXy# z2iUxH26x7A#%53$tcR(~V&GCYH=I&<*>D>q`k8g{Y@hUkY@F@`O{23@c7CGHf};$Z+NqBLhe*{x~B; z-f>3wTG6-17#X;re97aC46rd+P<@514+b&=q(|f=#5@?ATJ1lOd6Q2f=D9)U!p3-E zG-ym0Bo3m7N}I6j3?l5j&A`fVgy{lPgc`CsHikHcIEG9VF?NO;h8l)4keDT;ZNtsL!O+3b z!LS}A1`Pvl22O^h3`-gAqKI)Z++?`PV4;O<2R8#BJ0H6%iWm7-GQ4JZ&5(d1Cd5#{P{7~{5jy}0 zD`5s#23H1AuvjWIK19IvKLbeY5G)Kt8B7>V7>i`xqXg z#D@gKXSUC5teVK-BFXTT?JHY6ikK9`U$(z&lTpN^8UC~VXFH1`Cd0tU&d7cQ#SU49 zPi&vqOi|RyG5lux&GrgKOrC*>or#?TCHxc^nAw@xKcbkY$nb^j3!4IpUL}TKY`@q% zQN)xP{;>UF+lV5j!oa}Jz+Q?XrpoY-?H?QHJWDnM_95xB){gQw!5~l=v`a$YIK1Itbo>3R7pw zFoS6hQ;{38c@_*IOzBKVjF82w7&@6IGksGx0ZTOq6SX1L09lgS3fJU@n) zOfQ*OP~t6+L6KRJISEBw2*WR?Urf~~_J%Y3W8!2s0G(F=cXKp@F_SqHlQFWraSR?z z{!AgJ$YKc$T1WaHQ%)n>o6c~E?GW1@6tN73qijdn?x2WeG8|(&#@2u$mc?+G z?J(OM6tQfEBWy?5?xW<7e1@a!N7+mDkkdgi!wdEo?8{Nql`L5jgRe- zJ+d8J8PwR+*-}x$U^@dN8zb8;8)S968T8on*=D1J!G4CVtXo<4p@e&H7dyjnj`ch%_>K>_*ae1(Y?Ii)cYMIbt}t}6 zb+Li(_<)ODWoTk+Vl!4pcJnQUJxqI;TA|^>q~O57&2WdoiP4wQ7V0;M*gXbQMhC_~ zlsx@_p`NjqaVj+4AnG152^|*k6Wb)@D|DlyuL?*vZ<-3OR3pfdLXntcO^2Fh(%PG1o!E6rxU)(UsYiS=16#^?~|Rp!_Sw zc%1Dx+c#(&LDWezK4*Ku#sCddh?oN7UAB8{ccAGM;ud8_bw*=G50to6W0Yi6Wo(A( zg{aeHjAzVc+=LRBI*k5|v5Zro;Q~>o&p4NHC8Gf}e?Y{H82cG#GnPW_g}B9xQHNEB zl?^40TQa(^y0HERof8QUds{{~RyWoJX!t?&Ix*U_IlBEXJEIq?H|t%LGR&LN zmerPZ9n>ulb^eSVtRAesC}M$(8mtY+z|%xr|aaO=6tDGLhveir93V3c?}!mh~ukRf#E(HHbA9#ST@b zuZ&+Aw?plK=+$6iW8!8?LkW8wrqhh48Cg)$fdSJg##4-SC~4A!=>p>g#zv@HAZgcv z={)0k#>*(_)Q0IQ<5k9Fs6Qa;9GI>!USa%<(#~;VI?H&L@drv=dN7?~Jj3_|C7gYj zE-_wWG(qui0MkXri;TV~c`JnJI^%W57L+s;!E}xB8Y2r-3=#%0Oy0~v%&8v8^?nl5 zDz-Ij4^Z5k!L)^K8=EFd8p>w+#`ulV7^N)9WBShco$)A2*cUKuV&BBhiBdKdG0Czk zvX`QmSI!i}9?KpBbsr?Gs+c6$CD@}-{9D6h&Th`mh7x}DOrh+d>}pUqL;TjrWW(;j zZU?m&VqPngAG<&MUKD%VnLOD&*`ra)jV>k)c1?C0lsNBUGGsSocSNywGE)Y77W-oq zb+edC*~{5opl*TKJCA8P`waFXXc++!Tg0@0eIa{4iry7WjqJ_rJSgs4$JEQ-&psa| zZERp##=eZb3B_-ln3l6IXU|4SFI$*au&-cOM@i$`m{zi{WOs(97f4v`V7kNji18yz zxQP4-_aWU<3cLX1L;M=g-Wjxd4NbN@o=lN@I{#(s=_4oaWo z6w^!gm+T@aVrQ5hvp;4(j-vNG(-HO~?2#zyE-^i4f6ktUqV5{gKK6a=dvuZeQMZ^L zus>iI)J7J&!*rbeIQsz<^X@UdVt>Wng<{?#rv2>u*`K4B_l)Tw`$P5=9c1%fF4^iy>#B`qhJo`s|WOd(|KCypdzl37mFQyypH`p@`k=6ZU`py2E z{XL30Cgz*$H`%A5sAFUP!~Ta|1jWr<%(vKYv7bg!$H)Aa{V%&QiaH_Y+w8a5f1#)o zWB$kfk39-Soiy_u_B-r`M#%0{VE)hkpS=o2oeJ|^_PgwfDC#tr88{d?W}$?O4)YoI zGwh8h;bOr2p8Y-hRupx{%xBrpvadin%#D0lA1x1|)^H=t->`Ey1`Y@khKf!(*CA|bNzh-~Uo`Rw-nE4d@DRx5?_k}UP zWq-?FkD@M;`84}!_DB?UG0gAS-?4k5s7qiz$$pZZ4MklF^BeXz?EWbJ$Y8$Aewlq5 zia&Cgzp;N~|AAs&0rLg+3+xgo>PnbDvwvpajbdH}^L6&?>`o}@poaMu`!DuJ6m<>E zSJ|(!zd$jsh4}~j5B7N|>N=ROv0q~sMKQ03`6v5N_ERYCo4|aI{T%x#6#q_P{>c83 zeL70In#p{R{T_QCO1hfI%*esW!DQ*gz@+8Kz{KFfz@+8Oz;wZlfr-JDf$4%f0~3Q6 z1Cxn21CzD~1Cy~QLzM<(ojGVNJnZ~<&>RptzOBZ<01`{lVql2XgkTUKhC|dC7}V7m z7zCi|KzNAjTjhyLDhox)q>m)5(Clb>Ol8u%Bn-mMOMp?MGRd( z%q#~awOr6}1DTb9B#y2(!jyplrXQP}wJQTdjtv9DOBaa$rn@jO%rs*F&qIOcJQ4@6Syc7|e_zYrR0~Kx`NdN(&%9 zj0VLyh!3Md>X6-v><-ZRiXcAn{S6>K@|m^BY?wJ9H6S)2vq9-@yCnm|QA-8}aJqAY z&>%68dpnF77^WCAFf4%PNo4+NV+ID$TpY-*ttJTni$V9IXc=RQfx_t{G@YTdL3syc z7DybKJ>MFVK0x9iHppEKrVI={rVI?Aum|x$_V0nJ1F=Ej3p(ouCI{mmgx-gNtOh0q zG9RSpwH3rZkQ$Jjfej?TB8!WgGBD_wGBCj8C7l@<)SMyeK>E<-r`R$uEV6}|D`dmK z05VI?2B9D1Z;<#0Yly!orfjFZsc%*$swy->;O^s z+l+yM-5e2qptypCABYVLFHra)^K*_irag%3>L%9Me@ z-4vn@qz_$Q&khlO;wB6XAhS$O7#LvsL4E~^-v^Bsnj_q}!W^Oo??5a>(jFTR_~1tPW&0$c(`dejqo4!hu@h1M(ZPUqR-B{0a&akQ^u+FS{ec z8x}qXZ5bF~ad_UAf#I<&1H&hzJOEl38xPH|XN?&cougRKVx!xRq& zhGia*^z+@FfkD87fdM2BlJoU|gduXcz}TRA=7uYzogn7`Q8&qgfnk>g1H&XYNSy=n z3rH;A86hv@#J~U&1E~X<5p9Q%3w2;%$Z>#}2~q>nUuDn0FvT7shOBlC)Gh{l28LKC z28Odp<{-;)+hdmlnGLc7rWT#Q+77!uWO3M97i=^roMCwz6rZ3n{GTNQgSZs~gO(Ko zgN+pfgP#=xL%bCO18Cg|Xq^dYT?wN$q)i2CUoC;QuRv@mXdCJjv<-F>)DDKqgV?!R z3=ECXwpqIt1H%zrRK7UW+~ZI^lhD+EKvSQi!@yvx&A_lxn}NYmn}Oko0V@BQHY)$S zJ}Uo~4g-U;4g-Um4g-Uy4g*7xAu9hjn*3rkd0Aal^;gm49nj=Cj8N4lpvjl(GB8-6 zsR4;Kp{dJ4Q!^jUpY3S=+>Io^9!X9ZE&N>2!cQB`|2{el3^@jV;BXaA%GSFmS-6m zgi2y6Kx@W8QVk3Z4AE#}O$<#8-_D?_1FfZFM^jhJP|MJbCf3T(%AkoRR?kq+Ab}=U z$56-MjV9K}(8!Pl5<}Xb)XdP#Pz4f0a&rqq3*;;kBr(w1LGW25NMfKhhO^HyGO)qL z7{P0vK;sl3zmMY45EyA8uv}5!by5rr42mpTEOGY{=1DU!FsQPqvz$hJ%6l7!I=>Wm$C>VV(*D1H%QDn=JS4BGjoeFfd$UxyEt<$#0qr3=EH0 zUbB3>gHWf%z`*c~U?^v;XAJ=P4H~8<3=9l+8J{pdIfqbZ&A`CW z%G%5N^&&#diGhJ(GV5$sE2MCCWnf@f&AN$o`#FT0Js21mcCj90%|!CAHvb#^ z02Pa3U|@)5N@BW&=MNhAO5;rj*Bsbd}7&!0?>u9g`0zOrhqb zF)%QEWBSYV6C?&rLzxT=3~bE2%&V>;{F}$Xz~ISP!KemG2hei6n1O*okkNrr@G3%G z1p@;^6XR}1sv}ikJX{7>gK76N;E1gD8tA3j>On5Q89#AWQFkWIKcz)L7J5?xBc@Flex7 zupB}W6J=0mQD<>L5ffujW>IE2dk@(>afTx-M_A-g)JZTLV>!mcgd!%%09udJfTCB5 z;ULRF7G4xFX@;vTS6Sjv#AFz*vs`C!LJ^Z?xW;mg<-lEJx5zPo*7qo&h{-cNXL-)j zfg+~B@RH>vOAd;dBEt)o7c7_WAe*Pe09xO}g(9ZRP{~@!>V_hw!cfgx&02vXrpi#m zTEn^(MNAF6&QKjiOr4>MwTg8bikJpNEo&|7o7>24(PXG#tzbR=l#xL&1G1m8f4C`6fvtC0Hvt?Mzx|VedikKb4e%Af0Gf>3r8TPU6W356Fb70uRx`#Ca zMa+?bhmD8L21U$?ft!t+O%6rO8N819&kbbvxiCnxNwZx<5p!jbVv}Oqj3Va7Ai*ZV zHWNk6ogtAek*y9z%!46;ErBfoMa+{So-LkD4@Jz2A)76mO%O%Qn<0xWi|zAuWcT?n zWU^(l<)NfWUxr7Fj~Ihd#QYc@GCpK9LlN_5xX*Z>Q4~cifZ-G4C&ph-kn=(y!$-!C zjCWDQf*9U2zGvKnA{NY$z?8tW5JfD6A)YCosRczWlp&TWmMIxUEQ}$aDWAy$MJyb= zKSLWuECReQgbPJ1lA)fdp6UH#WH(1K)G^gDT|yCyW~gDRVcLiy7Q^s{=?&8~6tP%_ z*G#XODpADZzjLj1c12Ow&+w4>5p!z>BLgG*FQ^@p8MZQSW6r;T?2jqn{ng$eb)a?_*p8VD*O;#} z&&XtCU<9?-z+!V5PBWij=0*vFc?`3eXETd~)P=UQbe~D3 z0NEca8H|{XnaxnlTgC8~=`Yi}d}MX&8G@NZn3)Pe@o^X$ADbD}nKhV`?l3a2gWRXU zz)-=kh2b63JEkotcI;&EVD@Cb2+|Ap+g=7+W;^C*AbZ*Wu|vXd9|JElFY`i>y7>4Y zh(C@nBrqp3pFPLOzz&K_upLJkdRco}Q$cBnu@@Sb#~A8a>scROL=MyA46|8hv&Nx> z!3l=#EZbRF%0cn*2O1wI8B$qOSsg%P91I)~d(Se+u*$MtxsB|%a|}0GZn8v_F)}bZ zI=e#DU1qRlwPV$+Ku&8{7$R6BSkHsR7_UOp^9=?;Rw35SDDJz-aDwFoO94n7`){aQ z?lFMYmHSjNGB7f`GDGaR&rrx($oi`iIX)gUsIzLY?goV)C``fO@`T|v%WIbPDC%A@ zfY!$|p@hL}hG3>(CgW;QT=GHV@;$>crsYfrL1D^rj|CDR9~cUm3Yorx+`|4J>b|cG z$C*wry#ncF5n+M2?|xr=6jKYb_Yl-x zX2y+7o0#}O_Hr3R@F z%z)94(T~vprA{_vOk+%E44M;34GY=wW&Zx(z&)5nQD^1FQh*>Zy zGAc51T|oASC8HgqJ!2wD8nfbTgLf}3mDT; z#OxSB=gU1t5wmC9$+(O04k(U7Jp3W?=E^vkZ3LjD~DRY{4jc!x%w( z(ZKh#bqD$aa|xe5VcDF=)87G45kKzy`j90U}6klU^4e- zU}Dx}U}Dx_U@}){U}Dx`U}Dy0U^3TYU}Dy1U}Dx|U^3BVU}83AU}9!vU@|dcU@|pi zU}834U}7<6U}9lsU@|ddV6rh~U}7<0U}CXmU}E89U^1~{U^1~}U}CXgU}CgqU}EHE zU^1~|V6w1fU}CXhU}AJ;U}EHDU@~!HU@~@OU}AJ&U}AJb#8|?>#8}M0#8AY*#2>-HWE{l6WE{r8 zWD?B4#WRc6jWS+yo z#8k+@WLChyWS-B!#8}S2#8}3_WKzn}0^#8}C|WM09*#8k_`#8kt;jNGcZ}*V_-6Q z06yabwBBpiLq-Po3P$i6JP=!{9KlYnVq^%t3*m#tM?vafe9$;3NG*&H8t+6_4;t4* zRu3A#L{<+Prv#}7wO2uHBv5+~RR4qONl@JZ(hG9m?MD#zf!f5Nb{MEl32JwM>S9ox z1u_%VZUwcKK<&QWmlzp9^(Cmj0GSUm4{{4K8)iO89HgESHK28`ptTO75s3RIL1VNav6=|fJ19Y7J&_1?pz(2#m|P^L zI-e+nI?(tjX#GP4s7>$6$S^$$anBvh{*CDf^`P-|khwAGnC8ySK&S(a#e>u(WnijX zn~6{d8jA=UMg+*@@LJw$e1Z4KTCRDRwVKKiMp%ygX0#f^-8C5MTEYeyLYC&@; zAh-Mmwe8T{GW8;)ECQ`P^}P;Zue#32zkGQ)5jhW}U1MaZ=z*+z>gzzb2{dN`a{s;#RQH3#x;hc+K=U0SvEWWrb)dNn z&>RQMY~(wpLGvacJ?QsLgT#>Uq6N*lfW*-6qXmh<`~q5+3|h~G?aoSK)q&aq#HuA$ zUBDH}&YsMCjhI7WW?*1=$MBUQ>IFg!H2?RXfsL^WNsO0)fq|QG4$52$NDMyL0_`t@ z#6WW`n$Hkp8obcCmRrveXSeY(FfrU^xXbVvMU0sNbS5Cr3uJXH438NeGbo{mu`)bk zc*bCcBF4t>lHnzTG{`)-Ti6-)FzjK_MiJv+*w3(^!5Sn6YRf4wFz_;PG8|$!#NdY_ z#>H@y;V45QiWoP;35F94B`9J%45t}RGqj+H@iLraIL9yrMT`%8?%)y>F@A#%FbhRYk>L}=Cx%TZVoD5O7``w_p@=CnFfuYSnxTlPFfcPRGy0*3sWPxK zvNFoOM7CFr0o145i6W-X5X~6FSn~>5od&~9#@UQ=C}Nrn*^D`i=_q=&z;~*Ae}Sx5 zn?Zz8gs~Y#oeucUk_Bb3eYFk@ybQVwl1!3J`7aRtM_vX!hB=IL7(GzL^cmO~*%;5h zW@KRh54rn`m%)JHE5lcYOG}Z>GiESjGGh{2i7aNxaFFRR)7DkUV)hIdnJzOWt_F$8 zGl2TCybNv(kC>h?)vf`FLBzzgE{EYi(|@KrC}Oz`oXnieb;}X^OnDjd81k74nc|lt>&<5nW)^0Ck0MsUAj>Sv z%p|44z{H@+z_eP8fr&$%fr&wbfoZiS0~4n{0~3Q51Ji0f1||;!2By{83{0za8JNO# zz#mE5SgW41GUNSOlDq~;()e)e&15~Gg+67Jt zkhRqyw&qF(28Wdl3=u0C81h##Fo5K6iG$1psjpZKS+5N`cX`Qbh*|jLaG8fo9G_YE zZz!#u&yf6fqu#SjJe!*C=k`WAJD6XS6}FgP$RgF_2LMMNEJJ zbT3*MikJ}iZmtz5V!{lejG>H^P{c$SLKs6B?|uc~cQM*&ET;V4v{B*RO_myBItF$<`e6vHdV zSB%R*VsO3E46hkqGX{gi7-06wFg#~`&iLR9$lhsCy|N4*Odd?XKw@ycatxkKo=jq3 zy`E5Y@(f-~UQCBU>fq)nFt{XaEo zm_?W~L1J)qDh#5`qRe6-F@}dwb*c=4%!15MK7-u65-O$!K6}{_BnH>3&Hy^sB_Bmh zgW)CfOXhBn7y}zruO`DQ=2y(yL1J*dS`4q5Uo)$qh-ouCV}8bL`iYT25Ux&#!HmU> zRsJ;3O7AzJl?O?IzP%#4rOBPF(B_J`l zUPA^e7Auy6ATfr;P<2KO)-2X65+E_|m!gogVa#C4V#=cZ5fmE`ez6_$Q zqO7w~#QYc(Sru8ek0YxKX3%HVXSD>2J%rjD!eGs6&D!$~)Ru#k+1d=D450JW%fExd zWfj!FVGNHL9x+S-iNV7;9Ar4-N))jO@Y#ljKR|k)K=np~@A*3j7K7!ZCVn;84Gq6o23rR&5V~()MYY& z&aq(vtApvyVK~TmkZ}=M3>KyZ3`-f8GDf~ z{O1#*eXPw;%&itJ@2`mP)w}L^4MTn&kEcOJdu7*LIMTbQR zECy3o&!E7f!15F9KA2cDc&(n!2T+{D!li{FiY1EW**DO9LmUI>EER2rc7`sNJ{E)1 zAh*Eub~4OhnZXhR7P|$tx0hir%U+h}A3%B`=Z0!COk^lwsb%3m3(^Y*hZ1iy7(nL$-9!Je<9-Rg=R})fErSn}50lO|WcRIS z2xAIkItvnmyKfVCZu;nUM4v;OVH-miQ#X?-NK6jqzMbGTH$@=5pmY!R+g^rbrer22 zlytR^VFJ?xCVmvL{R~r?rZUY3xeufloM#R&tYBKfv;u5i2Q*v`F>Gbp%H#^Nm*F{7 z>?p$(rYlS?;IzREJ||F{;UvQ+rq4|6&^QO31EkGxhT$>OVAq_+15`*?I*<>;{7kvkf!Lb&$F} zP&eOU2xSgq{&EdDOz$&zF?%s9gTz2#01m&$40_CZ%vLCFc>=z_z#T>GDMJEt0`p(6 z`(SzI8ACC1F>^84Jdl4uY3&6A=*|EMuv=i^_nKio^L%D8P`H5O98_MtXV}ZUk2wM) z#=r^CBxY79(T>I_UgnhZ?bx{$tLv^E1%vagFXXOv;hN? zg&_lzl@SAzlr;krg9!suv>5|av^fKll?4Nnu_Xf&gB1f4gDC?Ow+#amgDnG7v^@ip zg#!cAN;?K7PA>)~25$x?N6o zmXYE2TSf-$cZ}e(MBLvoGL*ezWLWZ!k>U3nMh4}#j0}NqA>+9jZy|h;UeH-1(VrQ? zXKAeb%*gQaGy?;Se+`Xq@D(BtQsep&qNn)_LJX!4WDZO(sBQq2zo2pjly^b-1C$0q z@r-QF%a4o&!X!GiO>25={JM= zkNdteGPwR=WVro^;PdxgQuAKD>d9k%Po; zZf9V4xgByg3A!B2AE0ww%HK0GfcjG)vnE2#+Ja;jNDSF5bUBz=puQF;9CJ@IF!Y{= zxWnl*fr-JH!I|MRiWoEajt$;l$m&?YV%aF_ zSQ!!+5*S)h#Ml@T84?-hqlmFHBrzm0WdB06qu3ZY7*ZHg82sKbFffALC*Z)q#=yf+ z!BELy0#XMOQvjVc1{%3^V^Bp=C&UoU5W9UhCQl^_!7FkP%W& z2r#fR6f+bv`~itE!^GGaN*PKSPNRsiGn6otFwFZ4>eoX0`vMFc44}Qkx_=lM1mSu) z8Oj*S7@mN{pli$p7`PZfdy&;q^ny;TuV-)vse|j~VJK%PXPAN_#>-I2P|4tnqL+^W zw2yfmNFCe`euip>YKD_2Vglg%Ny<_53NnE9UY|t~6Jh}EcP<6#g}X(Vp@N};;rU-g z*(Sgs!qCRh#*h@nz`zKKBLN2n0R}OKgA4~5j8McR7a4C&o^2Us8ZUis1#r z8wSQ`P#awu+(s8*kYkv`FqeV-H)yRqOq~+LT81qQOtTmnm>78&nBIWakBKobSqLyN zF$gg*F$gm-F@R=w`52fO1R0nZL>QRM^-1vkj{|F06G(g9i$huF_%G# zp_HKloHC zgn()UxEM3TdWQ83IVfT*;I$x}C}OM(YZ%rr^fNFqz{(B|1~!IG44W8i-y_Nx4hAlU zdkps&mM}1Z%O_Bqn}dOe;U~ji24)m>f(+*wE-+jLwd+A)AmG5j!63@;hT$z}WiOH) zVhkA!84UOTA=)Aw4B`xV40#L@{}~w&ev@FBz%YT~4~jZThGvEqh9xNKq`-A4qz+_d zV6p=BfY=$BX7e*JMS? zpzEsm85kHgF`Pun{~$4V{zp;=%Kw^-OboE|b@-v}e?ewY>krZn=VxF7uNl)s5o2ap z#;}ax9uu-U7KQ~33mCqkh_Ny(Vpzmr4-$ix9sCSz;CtyJP{i074lo>GC_xe90I%!o zMG@ml3>_F)%P@6cm8wIQSXF7^;|RnErvp zm_TF94h;MZvJ7!d2~37x5bb(?1_g#}rW~eMAhDR_e288Z20tc$rpT`h42*ESS`4Qc z&oG`r5i?|1$GCy<@i$OgA7+OM!*0esjB~yti&-$tW1P>({R3Idj-iXOhp`St%#|UJ zv4BzkCj)#BEI)$>Lp5U!<3x}cD02yb{Nck8#~9DZ@QZvip)59x*;-^ z1XZA5by?u~pbQo!26j*wfYoI)oMbr3pzw(Sz896BA&22H!xIKJP}%^Q2iBX*(8kop zRL97Kq%IG<9&;6_-h-7VsI|CCV2LqEevj|`j6pFm@Gvm-^D;2?^MTvyur*?YXwXfOeg>s0kUY%ap!5Ud!~70P z7vGtg7(iy#Gcz%O^tdoHF@V&9%5obPJ@AgA%rKM=Q)x(T?Ph*Ieg3bj@TpAnKCdi>|#90DBu7Z{bpbQjYV33 z&h=tE%&2CEPzM@$xX$>DvB(ag&Y6LM;SS>i#$VP5b>0jN4Ax9OO#C(ob)Yk{Y?&OH zIBXGO0SpWbE==xBaaIVup!2X6F>PQfwnC@_orkrAX$4c4B|=?10|UcBrZY?`S_rYN z3=9lUn4U2o(?RIn$-uy%#jMY4tA`NV$H2f~z--1m-3X!=Ycj==}yd$BgF;&j~k#x}OXT3@don@LUW;sQb&nz!1!Rhg&%cA;!SSz#z-x z!XxF45MyFwV900eVw~@U5MyCvU`S@FVEXQh5MyU#V0h0U!DttN5aVQIVEDnv&-B9& zA;!(fz%Y$*BjbK&gcvU)14A>@45lmL2r&Uh1_o8eV8$s(X?-u4*wl~a~WhYCWfp0SNYFKBa1OJT;#vVKOIFK z3&Rcm8~o)cVyq0;`LFYDM-gLVxXFK$e-?^)>S`bC}M&P_xbPhKS6P`5W^+@OZ*#9#Dp0x@L%Bn z3U(i4-G~sQ2*Yju+x)>OVxkP!_^7o(gy_Mi@n}DtNAA0Z3gd7u3ya45R_Rx_+-CVHZfO zL;)I?1`OvJ&NC>1?0~z)kO6eA?lh2F;QloN&qw#6s51uN8-5pL9_XAGu=`BF`@P~o zVyrNGO~L!teuBgjlT#sS$PBz+jtRv)a|Y17kUNT)1w%VSJA*Nbm?d~_>=4L(a5q~q zlNLx!q1+H6X3L<$qQbHVBxa@q zjW;`nXqIS}c#s$)BY18>h|!)wmqnMQ3nZ4RU<=Xfz~IQ@$Pxx}3p}hG83Gsr7@mUi zhmJx4M4c1EYp&N^KR{yET*?qJXNEUiZ@84Wm>Ae96{;a(E)4Iu-f{7Q#QdC{AY!fz zZ@J!bnS;cfT-_mJZVd0a-gEhY#FUl6=OGI*x-)#>`oOgWWQUuhGen&S!*j0ZT>T)i zoWx>?m?y(Cu4i25QN+9$UUI$U+6@wO4A6k6^JaL#^@6JbB$g5cjW-{Lr(93D;z9QM zxx_=%`7(Us`oxt764R*AgoybueCGPhRSOcUhWXc@;S1Lnu0D{MU%UrIT>!&ZuCHA4 zL1HdGt`M<6hVNY8xi)~rd|aV%8N~2|>j#%GD4gMSPcVZ!gFC}clrkrT!G^(x;XjI4 zD0scb9Tc%J273m3hBu(NEUtovRX79a&O~RBe~T5YAa03ZuxGbt7YB(|IfMJlLX43N z*6h~ox*)Oq_3STQs{5*aG^EBL>N zBI`|JSkAwk{~1VcK>@T3OJ*qHFX8v$XJTMWGSPvUm%>oPU&F5?hO9T0VFmvRele7~ zCyn74|1thODDF#V$mP%FPY2nd;2sJwFN2|wzmWe3$bG)9Q1@jrRPtBy+o8BGi(xVU zVtzr8I)x-th~8|5QvOo@Dv&;J`Fw&V_YeX$T@9YX_u1Am|Zs4b8OP2=?p zP5e##t5E#bz_6NsHNP529Xwq%GBolx^4EjJ;+=gUZfRm@=5OY|fugsWVGaKp{uLm5 z71B!~>RK4;`0M!Z2r@CSSu4~+#9A48`Fr_!gqRrE5_6&DP#Z%Ze;+@aIC7k~Gpy%d z&)+41EY`uWoqs#OHApXLObuK|bu#qx_w!qz=W!!Fihv4 z&c72R<`@Dk|0Xib;Ge;N2E~1o7&h~7<`0lW_SG=@F=d-(ZK+&7)!Apb#r8<2U9ZV?dkW-v_UpUR&E63d6BwV4dl z_^0vz1H~`AzMRF-!Qa8J3krkcVrV{^&Cto;$)APdmN^U?`8V>vLkZ`(3_JOE@<)U9 zCPV9wc?@0rUHr3A^v-A4#J`DO9>pIE7ji=cUW3BzRm$^1Gf?pw;Rm47S$1{8ajG3@2v z%P#;5m&_z+{jr>33jY-TXcWCG7`E|mAR|9R4}{6F_1ynb105EyG;?x%_)UVwte~v5sLL|2%$S zkQhAAtY?_TKa1ZIBnGcPHZaWQpUq!~QnqhoIK_X8{~)OTbq#^mWt$k{`Q!OFprn`0 z3`h8n@Oz=?-NJC3|2Tg+HxmO}8q9rL8B+OE`R9Yg;BB963~Bsn{BJ>Gd8tspZD+{f z&)|Orav!{$+`+Jretvb9!tbMjmD!wi9(ft=e=#Evk8afWeT zL=ij65Y8FSS%e~Xj3I=c6u zw+VL>ir8reTW(wK`6yy%7@WABxb0EI&N6Uvb8_EQL-y}EhWFg>xzkX@&NIB>e#702 zB6fk{E%#gQ|0rS?89s1-;Fd?R;}XM1?vLC{P}E&!c*p&Y+XF@H3d1YzSKPU($ZomH zz{SJGGZ{tf8Ur^EH_v?)WOdgW*m>A_Bv91dVBp~4;Q5Inc9VgZhnGhL#ok*Cd^~(S z`%%>0X5iuB;ju&!yTicA!^txb#ooINtURndyeMM#7@~QidAv}>?lZ*l#PZxwMt1W9 zhA5sW9!(T=4;f;3VtATR#2$h5R-)*A%n-p7!7~j->d1@y+A2LlJw)FrRM$-x?ILR}72z7V~wWh`nZ5$hVO1FN)Y3 zh9!JU_{trT?RX2`Ph8}HEcOn(cWw!a*n5UUjE5L)QN%tl9AG@acnwADBg0|F!;B6n zc6?$u&UlBW z?qR%Qhpg@g!#&1(jBF_CeuB?=o{ysL7sFk~yNnhn>V7jkV0^&12u17<1LzFlP86}f z438NfGX|oF{R5vbosA;)AAAmV1d6>3jJFwYGg_mFF*4p{yvb-|gX|9`Mmr`uraTle zW=4A^d#3p)Vl0dfOb$$0w#a%}8A1D)O;NEKQQ~eIbE!>RGOwLRfQN(x{9hn@N7FZ#>kC$;N(^97UC}Mn!%b1oi z30Nbm<7Wizy*_{?V?4=pl1U9kOq}sF(`lypmdI|FU4JAfi4$#|6MDAQ9E zF)7C5Ovjm=b&>T-GwLwwFkeFvlVJqyiR(iVlV#Lp)@A;zgREDMQJYztnOh%OOrFu0 z*_gQ#MNEOwl-ZPdw;r-OMMfiLBj#`vbxMpT%qGlPDC(3M4Vev@j~F5ARbi}Uu4Ps; zMix_LtY@xg{)(bbjj@ioj(N2SvO0CfiOdt3PoRitFoN#FxPjspO-9h3!fB?+dbJq0 zFmGYriXx`XxRrS;a}y@ysVt#Ecn1`xY5c!o`F!kvWmsQVZEFri`zc zUNKdps54^(?Qgt?Vy`)43v&ze9~3bQu$TjiKP(wrnOm9TP{gdjVznq@){LP0N^Y1T zyTyhPv@d!aikL0q73M3N7_Tv3V-7~~hdtwaruR&pC}IwbADBKcZ81l-!;$e0 z^Bv}oC}K{GcbV@pSD}bGGu~pp#k|G>S+5J@1Lg(d))|gZT!t zB#M|j<8|ii%qA%L(u464^CRY56fsZ6C(KWn4N&axV!X$Ek2x1b%$xB(^L^%66gzwv zZ!+IxRzb-}zKr_J`pn<7k=^Xa$i&RVd=o{?pOKN7k$DD+c>#>KnQt@up|~%Q@iFsb zW?K}!L5!fYj>1vIg27^iC}JUCu~#T@6w3IM=_k{16tOTy&>8-mDETOyaS8Jh<~$U2 z5#Tsqfg%#mb2GCb zin@5lUrfK4B2dz40^>#Ii_9e`Vu_5Gm@hF;MG;G4yv%%=`3j1ElNnDipI~N3QJ2Da zlKCXF1xi_*$|%Gv#2kwvmIfA6L&?+WjG*)X|D%LU2BRahBeSFda@xpbbYga5wnY)k zVsvJ9W}bi&2HA{F%uUQrD0bv9<}v3nOQYoTTyPm-fZ~rl##79vn17&9LVgA zQic^UMleS(=c9-fGDb2-GK--2w}=sRm%|Da^NJZkd%ka=h?OvUGkY^Pqv$PVlxLP_ zZbMO5#^}lH$(({BR?g_b?7_SQMQ;V8DzhrHDoVUnGOlJ`&AdtzIZUeKUy#tvJh2#2OfFIBhs% zQN$V)#%zvk4#rSqzqK+>9 z4@Inv@e0Q^4#p5M;U9l>bQQPxaBzGSI)1T@hJX1#mLFR z%hJt{toIBfI|n<5fjn~BILin+<0wu5S>1U?6Lu4JUM^&@ON@Wm|FA2f`1cCqXV&km zvr)qD8Y441JNqXWWWU{D^knm8+k_GZw;10se`0=t5(ak}->`gO(L^!tKBF|7Je#F2 zvUv{~kFlI(DM#_|W5%6qd)X$(BCC7Gc#rKdn|2_w*bBy!Y-iazQ2h3WaT(ikHa8Ua zy<_xc4`f$D3BQkw>)F?{U*$s%moJP9*cY-dMKSL?<4g9J?4~GT`it=v`)&5ncx1Qy zWt3o%Vflul_dlZqhXjWL53(IhOq19ru^;6{7Gq^nRlf3Nbmdy0LBzMph@v^o#i)^L!NZq?mHq^4NB8BD+O_sfDeT zEgB_ls4%T$-N33ThislYQxoWpGnBa0W;(@sk@YD`Sm`oZvRbkh2_oB}&lJQO#QGma z%#djT>jKtpA!K#NOnIz%tOCNwVx~;5SzohGLlHA)a$s{{Qx-v1XUQbQCd4)$B~98g zMYATcY6c+t!-44z>jTzPDE@F}GGH@d+m8|k?o2yb53ufuM%L@aRK{AxT7i-#{g`gE zJYaD}5esDMXPv^DfFc&c^qb{B%QciV9?rzY%Ex+55!sF?CP`LV*027^VsT6xS+=u0 zLUBtX6AK#$n<9#TQ<&bfePLUKlKwK7nps*{+QX5}%VEl3$zzE_aZ5f^AIl_`Dmmox zrGUwW+l9N%2U)C;=|9(ht`>LXx}u0_HP31uEfle0rd2$vc)q$Jt1Dqz$+MCt!xdSq zl&OuUjb{&v-ZG{&JZpGtQPh<)HS#p_Y(x>OVCv)P{=Q)6etC1KEx$rae4+ zc+R4TRWt48+07&9iL9=MX)n)S9xD_#*D}rFnZxr4#eH>58+kVJNT8Tk&$NkW6OST_ zTN;?Ed8&C#Q0!=AI?QvJrvgQ+iRmcMQJxSKv1XQQXqPG@WNU&sr3FTbXw8 z?Ba<;QP;+_kY^#!Vid7YlV>MSJxaRjX1cK^jQ14pO_cI}0@Fg?WxRbs$oX;_6Av#RFGn!4*leb6JU@8qQN$K7mGf5eenAmi z%B0Jy&zl*7talYtJ8viNJruF^O!mBvyuqQ!>b5Y+@XGO?KoQ%?6wDjSyYw$&&xa7> zKBjcuOx~#|ZOr{lLEJ&y;z7u1;{a0ycNO>BKxDClOyS(&+>21u9b#I~y@6XS7+Kw6 zrkmWixm{55))6KF9s!UmmVYCP7$37Czac-j9dp$osi8FV=iGTXWE4#CeEDBl+JVqMXv<&JBD`*x_-!dC7D56;JH!6 zq?kW5d}e4t5tC*XWfW)BK#5-&X3!aVr2)w1$ue^>@iB#=h{-YkVf@4RG6LBj^2}2i zr!pG)BkNUQUd_0HQ4mE;k$D#5EJj;>WW7qv&lsOE) zh8A-iV;tiLlyXR$8Fbe9S(LdV9cCRS1E#eoV!F(7Oma+|fyjQ-W4_0AkBf;}ijj%& z8v_&Ldj_V|4-8D7zcMhrf5*V&@fo!HmVt@!BLh>*Ck7_QUkpr)-x-)ve=snm{A6Ha zWMpJg`oqAK`j>%eI|C!r``-*q9{(7al>dXyxnN{sWMO1VWo2Ya;bdfb&&0^&!3^4E z3EC|Q+O5UN#3;hZaB~ z%)`LMY{|%!YQYFT$HT*fk?FH3BNKx;BNKxeBNMYeBNMX$BU7p&BNMYRBNMX`BNHP( z0~4bYBU7p)Ba?>%Ba??cBhzPFMkWS3MkYopMkYpUMy6C7MkXd#MkYo#My6DEMyAis zj7;xc7?~K87?~Jz7@1OA8JRxkGBO#rF)}4IGcrABVq{|IVPs;cXJle%U}W-aWMpFK zU}R$GWMpFKVq{{dVPs;cW@KWR&&b3uiIIt6G9weiB1R_gPFB!4BvqjBV_;%vXJlds zV`O5O%E-hpjgg6AIwKRq5=JKW#f(f03mBOg7BVui%wc3=h-PGBn9In-FprUmA)b+m zA%T&JA(4@ZeF`HJ!%Rjdzhp+H6cGldyjVu2pg2Y*!x@ZBsojiBsVR(1KBlBxI!42(n1-T6k-^eTw55KoR={&l|(W!DMT?cafLH7rA06@F@Sbw zO=M(Zn9az<(96ig(8tKc(9g)kkj2Qvkjcozkj==%P{PQ>P|V20P|3)|P{7Em9v&B(;$!N`>A#mKbXlaYxj zfRTyGkC7?Whmq;MKO>W|FC!CEAR`k~Fe6iH5F-=gaz>^%s~DM5S1>YtUdhPBxSo-T zaWx}T>KaC-?duqs-mhh3V%WmS#I%c%$!RAelf@=RCgbglObk01nG`lNGBIprWMbRK z$i#Srk%{dDBNOK_MkbGwj7;wjGctJ`WMpDE%E-hZ$-u;Lh>?l$I3p9|0Y)bN{ftbU z`xu#c6_}Wq#F?1>iZU^6mtbNtmSkcA?Ue17WnyAbV`5@ZXJTTIW?=FZV`5^EV`5^E zXJTT|U}9p>WMX1a1<5fnF-S2nF~~46F(@)IF(@-JF(@%HF^VuTF$yy={S{(jVz6Lh zVm4=DVz6XlVz6Rj+TzB<#OT4q6zR^y#1O&6#2C)R#2mxK#1zfM#1PNK#1hBEv^{}| zi6NPZi8+ahi6M=Ni6xbZi7AVTi7Atbi6MuHi7AhXDLj{niKmE(iMfzTL6(UjK!yo? zHvbkGCWa|8Obl0Kn84>NTFNqk&+-qJWn$QVgn{9c3=_j7StbU5TSf*|IVOgQc8m-K zvP|If{6XjQZ?<7%D3M`eV31>CI3f!%19VOf=*%3@83CYk`$6aTgU%EL-3tIZ|3B_I zBLnCxf6$!(pfl<~Xa0lKgYF9e-6`-+19CS2=qxSUX%QZg^A%82NOdO zCliAjCliAWCliAJClf3wyn28}of{EdV zBol+FFcU+w1QP?h6ca;-5EH`&Atr`S5hjLhB1{aAMVJ_jM3@+&MVJ^SOEWRt;bLOA zDaFK4F3rR+gPVzAKQ|MD01p!buP774Gj1jZD;_2Wb5Tf~fa1ZB8xk)C+)Us*@BXMj z&YIX%#sIz}0d$Ak9aScVU{xlDbqc6za%>n-^ep(u0N&5KPmPITj|xOBNI$xnF!Mla zK<8k9_P732W&)oP1!BYY9fQt(0`bF?nHbcRm>A-em>A9~F)@J7lmg-TdQ1$UyM96U zSc2~40_{5log*b=#{@nL5Tt*m83V&5b0!AR{lB2QEkXBjf%Y9@Qzu}-#Bj-qiNVi; ziJ`}Wi2-y!Fz8M$&|X8(IiVnPpW8Bl&q@XDNd&1qYr(`IXvxF?y6Y2kSJWD7CI*mS zK=y+69)iNi%L*a}I{ym92eoBEZDvp#SwokJ0n~;A@j-1RkQm5c$meN+^uh2#OUT)t zurLML1(E~pK?I$p1!BK8WMTl(AU}e_4-}pt3m)x`7jI;2l*Ft4mQjV(Edr7JcvGN3~?*y zY$+K2Y0AU^(g)HH!=UqHK>h(?kU!Inm>582g49VHLc$l+cLJ$DX#g=3B!`ThO(AIv z7Iq-BU~JGnY*4xdrE$>SP4gHg2K`Vb2KF#WepnO6#Gn<<#E=vM!AGDpXx}YpU#EFI z69Z`O12oqGG6Uoe(4NhQ@=Oe%@oW$u6c?a<-yk=E>;|3l@{JL4Hkt<`gB`K!)Qw%Ch)m3Ao)vP2=>jt3=F^iLhf=A zU}9v@VPa(PV`5}TVM3S(Q*-e>1H&C=ggD6TNfrzY7lR?@f!Lruv!MJf=Kwjk4J4+> z1-VxS#0L2hM1#@|hz9u|M1%7De=jERd9|Q40}=zB_XZLJ(J=Es^p03aIRawC+yFb* z5@bHIIOtp*P?`XV9koQb370s?FCa5O_QTA^r52a?RZk{{-=2stc>)c4keML!VdnD0 zF)>KQF)>`^hlD9e{yHZk!y`^chEJS~41YNh;)Rh+4AUbKW`1%<$d&mrG0gWx$id7f zl}2|rC>_Aec!XsB)kr3W-$-t`5)H8%6j#V+34{E@<$-YLXGMrQkT^CrNWWMB6T=4+ zL_Gb0nhnz922Hmh_HG_VhD$sMvloRkG3*XUm|q&p!~ojsKE;QL0W|&u8gByCExoQx z450ncp!{~-6;dX^%1=<)14@r99+3PE%A=q&n?UISCI_PH-5_OAyayA*1P>id{PC)W7KZDG}R<cxc7Q@ZXA&!N8i4!P%OTq1qZ!wu050LeAEJ>4BYT2;-X>qsqhh zpmPU6=N3r$GBMjNObpzX zkn==R7#J90SmIe&Gnp7TPC~@e85kInSkhR&fy^^u1n=w2V_;w?V7$y2eU^~{bblEr ztUzMuXGVa;KxamHqp1UJc0oR86{HS+?gJ>TDKIdA#6agh%!x}gEXD-B zH&Yiyj2XP|o-YZc?giA%EZ}|Ui$Us&mV@_a7v-d2|l;^GguwWUM_|+3}+ZVq4^1D9LX~5V%Wvdf#Nx_3}}6&Pe0Wf|Xs#g;+E6d5!aH5e~|#bEKP#2^hCOHKx*A()sl zgAt<F{m@VW_Zo; zvJ_cN1AM2i4~jZXhBpjv80Mm=(_(na@RT6~MNFIF8^bq-W)v|Uh93++7$i`{bU|Gp zMne=aJq9L5CPrTrF?|LWMi#~gCCKhG0Pp4ajUr|U-Uo6RMa+l+w1*@cMa-BXjwz0* z2Sv<;A(bhWDG)`>lp&HSl4%)=m>EMpQ$EwTJY=_+Gqf_bGDYMgi&-#$=48}S#4N$* z#g!KztFvO5!8C*Ecp)RZ zikK_I38oWF4Jcx63VdGjwpt+OlO%QQS68Y$N6s* zy)g`ZOnpqdQT!VVzQ4)@MJ$eCH`8vW2o$k+hCNJsn5t3SoWM}aRLfMHjhu!O85T1y zX1c`5S}6tQFm&^q^}xyX7`81^#nWo|?fOJ&%@yoWg%MJ$bBH}h_0wj5-= z=?u%5moZO55zAm$&%B;l0Yxm6VL9`1<~S6wEQXcLE18d?*pba}fcXIP0~E0whJ(xp znLSX%av8QWZ)g6CVqP8tXfKQ+in@HT*aj4J1q_>*H!)vD5i10XRiKC!F|1);!>o-G ze#PKBw|=A8QNnP9`3SQ;ir!L&70fG`!%*U_i~+Rf-T+0coZ&e0apsR%$YEN+;LYOA z!h>ROC4(=EFUzhBCI&%c$oaH+3{?zqEO9IyATb-5ST#c|ODu~~CKH3;DVSIdLo!P; z%M_4UG)%0PA(bVSB^e}k8YWf;zBBJANNh4A_`aJwhI)oHmNb_8ATf8Cx(0@HmUI?b z6gM|AWU^$kn4^d_G32o1umquqH8bS0ZenS#nXt+8GL13RwPu-1h}$UI#-4O9o49G7|&)W>|gR3BC)DV-_O=`*T=Zxr?ES zrHZ8~nTdh%E#!W|Jcb^In=B7mKBX}+F!nKm*C^*P^f4S^Im5!an2~|e33Bdi9>WBN zMwUjFkLgSdjPGE2Co!yN+0Jq-g^7Vt9;SB+!z`91EY}w?GB93bWB{EVo5wJNp_iqP zB{YSJfn5#emYEDc8GbTwfW-Jx06j@YR z)|DaFIpr~IWZ-5IWnl*C1sy0T;J}c_u$AEj^GoL0=}ZjlyJ7Cz#_*K!DPzJmMh3>W zu=v=;z{$kLBmxq91{2%I@RRWuW7}Rv26hox*zae!%XF8i?j$1v<8qk$jxc;-`o?r= zG9v>cC|!Z=J;C74?7{2|a`QD<+Bm~t!feItl)=QnXaf_wz`)7O$2=Pp268aJU1q3Y zu3=6?@!NHVF6If$IiT=c3)6dxL55k8nG0l|8%*pTLo#zF^F>g)XM(x;KEqpvw+!;2 zFernC!2C5XZp8kjcQr5Y52Ekj=ov5X8X5 z5Wv910J-ari6M}Ii6Mo7iJ_2ziJ^#ri6N4Ki6NPRiJ^dji6Mf4X>&LO6GIpS6C>z! z{xk+AhFk_FhExV7h71NKhC~J?h6DyChIj_1S)ls_eHfTddowUGv@tL-a56BRu3}*F ztYKh!-@(A-QOm%@(8|EXP|d)^(9FQZ(89pP(8$2V(8R#R(7?dNP|3i=P{F{&P|m=_ zP{+W;P!C$0!NA1O#lXbS2|CH1fr+7vf$4N91Jjjm1}26c2Btea3``8u8JJGuQyG{TrZF%v%wk|-n90DzFoS{VP9FmkLoWl<9nfsgL#CI+qqCWa4*ka_#oBqoOPRg4Uv`}c0fGckbX^^=ky^Zuau`u#~v z44`}FK=b~f`Tv`VObn5;7#Y?jFfoAE2P{cqVgRiH0L_R0O=4mI&4~*oGcjlAX42WVaf#0HIlgVcfCjqFa?T|XeRL1R528l)fO zADA0JVjz2vF}i&qH6RQNGmjUH44`whk?jJF{h*r-8Y8-u1sUT9nF*2yjbVYtlR$IV zGn1JZK=XSb8Z;LCW)WoE7sLm-5k$kpVe?C%@iWjEm3;~m!?{#Q9BHO8F{Gt2F|0~s zV(3a`Vz5hPVgQYIJxXU{kk|w<6PX5?3F5PEW@Iqkj9VUNCul4Vq(^TXBSYtE1_qyP zkTG@;A9Q9mhz}Zv1F3m?jFDmTNyHo>Obj+>2;+n1c3^WlAU(+QHX#1C6v&u9h}}`f z#4xW6!EZ@Nu$42I7z{I*7(nBXpm9Xd5XLAT4S~@Rpl=AgF9VI^F&qGm3xWo}BpD>Z zbs>FSF>2dr2#kinK!m_EW(Lrl7Bv5ZuXSf&WdVr^fyePdZen3zVNe5!bw3B6WeE~v zWng7+2Z`xFUj`{VK=34yY^Dyu*=z+vQ_q9Xy@-px;_=Chi z3ZPwZ zt3hH&>U0=%7_Oj+=`!dt{6iDdW6)zz=R$RhK7&4kJDQjQg8@T2nwTMjAwvh6m=S{! z!x}U(V+Lb}OK4&y3?>Xe(8Np`Oc`XkQQcz3V8-BpCT7lH&JcqpX2D>=P=h9B$zaJa z4^7O9!HQuwnwT|%HN$N*G0^$af6>Hj8EhG3cu?JE$6&``hb9I(b2CskQh?@g6<)I4iZC(Ul#@!22NhoeB{dD%AgGrLsI9);Ktww5<@Z% zbe?u0NDN7x2ZIO0WRMt=I!^{qhOHnmBz0a4UJTbkVo2(|8N3;Og2a&2`7rn}Nb{k( z&zHfM!3rdXq|T4Qk0BZ)hGd>UgFizRNDN6G=&bcQATcC$fee8R`#@qy>OkjiKLCj# zsS9QZW?i6NPn#*oI)2ogh5m(GyRuoxtUqz-hKOgma2ZF?q%mdvSUJMdLQU|&Vd?82- zNge2p@ADurBz2%W6~2SSkkoDh3ab7?L{Bz28M3F(mV97-|@%fy9v1 z)iTsF>;#D+sjFkCV|WY_LsD1IP|v_CifS+Dt_ees7?Qe1hDL@EkQkDAO$<#8bs#Y$ zb)Y-aSAfKj)Pe3BKLZj&QrF7R%J3c}hNP~Ip^ZUO3^hJLcTG5h#E{f=Fmy1agT#=` z>tyI;=mLo$sROMU+6)pyQU|)%s=c5)%@sgmNa{fAgPcKPNapo3 z^fRP_#E{g1?r?1fi6N<*$S{#%6G#k69cbOuJ&+iZy2%Wa85kr`<6{cL6b3_(7?QfF z3{x2*Kw?PdO=FnGPz4f0Qa7DpI>Ty^7?Qdf3^N$+fW(m0&19I#z$=Mr?<|H{40a$f zBz2%WV6s7CNaoF9n8Pp|B!;AJF2h`gvmh}fb@LeJF}w$f86f%rp!;J)q)_bz-P>u2 zCbp1aAwxKt80ap~GBh#JJu@@W#Fj8DVc3r*wv=Hh!y_~?&>f<@(x`4(&aj-p5>0Fc z!wQCIG_jQoD;ZkR#8xq^V%UHt2D&TeCYl)NPGTk*RD0JltYy$f69eCSj3x%U_qY~K zYy-mvhGl4C8yPk-oJSJ_-Fy5SO>8s6W(IXxRJVZcDGfjq+sd$&p%P7O8^bn+MQCE6 z`)y94iS1z6!SD`EY$wA`1`#<_dqHc_9MQx;cMIjAiS1$7!!QF)475h?5SrLNhJ6fg zz+#ZQqd-Y>Kf`_oad}jG4=@~Ha6%J1$Z(J$3r*}0!y$%AXkwsye|DjXf$oTXfF^d7 z;V1(y=x~u32n%D(~3k>hk#4a*iWROrowf7RkB?cQb zvC9mX8Pd_jt}t9-n1m(U7a9%WQ}LF+*+Kw?PhZZh0t zNCAl<#m6m%TMU!HVzThD4A5H0{a`Uf|NIWa9fp@6F(mWuGTde0Q$e*Cbf>s6NDN8c zeTMrCksvW7dmk`7V5kF$A*p-F@Q`7J3TTW3W-sV04aU*2R#3Q&;sFbR231fR=Yi)B z(74%cP}*gH%?Uup1pk4>5b8kVe{a#mK;wkGXy&mourbJ?iGjuh_0YsXV}f>QVxTcW ze>5@Bm|#4b7-&o|A59E2COBCYl;2=(9?fq9mdHje9<(8FsvNS{2Q-Ec+Wp1F$ji7D zNsNVofq|b09d8F;@5NDMSSd>DdXEtuE2gJvor>$A8SSQ(Bm zU0{k(V_;x|o5#ig8mq|!i7`O(KQ{wA_|C~P6fq74P+xRCiWnyYsBdu>MU0C9)V{FL zVqjn^fYjfhGKY_ykKGkTjE8}rou54dMU0n0kX?}74@HcRL4aL=T@xe*cOO3kCp#y* z1d5md0|z??`*Rex2!i)UB%p{1F@VNQTtQ;+Fc4+{jZuoCh>0+O##I?m#6%fD$uaz9`_1+WMNFQ7iJgg^110SVcUozrozC$&cI%ZBBsjlkL@2@J4#rogYWUw zRYwjN4TgP8`PbwK~d+-kjs?IRPKzd&Xr*y(^94;l)UP}aF6K`Q@$0lI&X%nOgEWqP|WjV zc**pVi3KIz0vQyU6`7Mz)P*pB&Tp?qu{WII9}_3Dfi1Ef(G12+=1fe+3=E7*=7}&V zI52QC#4&g<`7?!>BCAVa&|=bK`doonH_pwF$iTzM!+0A-EQx`ek(==_NbLO9UG(2FRLeZiW;F0Y(AF$sjRKPELrrR0c6dF~(|;7+hT%gD9gY#`0WZVy z8IH0aWiQoZU|?f<0G`|BW+-NO!Ty4MIf}YchJ)+}*;PU682I6DYG}F#t<~mcsAo9NdYpAXG#x<1ni&qV9%L1=U|?Vb z^_v7han#PRi*+~a32R6kLDY3JgtLXS&4b1pM68z~n=OZJtr@bqi44hXDQtBp_D*Jq zVT)n=3r)`uz0(=I*u2=9p!o{!SEI#)Ny64~CR z3^i=EY&THUEob0l<79J%=1Yiqs~Ke3i%yA92&5Oo_F_}KW^9@!(S z+sdHErp}g%5(e8D7}*%vcG)1S+s&ZIrq4DTB@Fg6Y-Qcbx(`L{FvC2y`D|^Vy!xk5 z5Mu8UhUsk6*`&ewXdN>|>;%I#*6XY~C}DMm;T-FER!L}i1yOf_VItckw$&(pyTZ`P z*2T6Rqz)dxR~eevn%Iohk==X?yf>#6suz-1?=Uzq`ZC%={RR=c$6(6nz!(V1(+se- zzypSQ#$Lv$pm^iu;)JMs#E{Qe%h(5v4~W}2g^y#>|_vxAj!7VB)*$tdZM zgE50OgY_yjtwH?8#TdpK&B_3+XCU_SFeb1ju%>|G10H??j1kOn%yrN(g{Tu{bY*sB z7PVwxV26(Tax;iA9%nnw_6;0II?%Ks&G?+{1sek>OyT}jV7$wAkL?aLokHBA%&5+2 z%;L~EaMbtxIonDGtOmP$!Gx09}qDk z#(u`xjHOU}A^tF9)M3?OWdo&gxce*_U07XMf1|{&Eu$N&8*2h6{LXI;hUj%-v}bi- zbw!C^cSbK(Z`QjgWtcakEvqf-I;dM9di@zaSUp&MQN#inHCQ!RxuJf8sEcGYXSHB$ zLa`%}(TdfYl?fVF5OwK{My$rH2T;t*X7p$EXKg@Hm(OUxYQP$YB38(##j3^n2pWD6 z^GX?gS$$cHQT$QC=)~&8x(E~o43NDW+zd60daQb^OHsnAp3#)mlyy2Z?Lxx7iBXYN zjg=iG-M29&u_UpqLb11#v5cjRMFu6U^)fcFG_YJoDVruSPGFhH@)SjEI^#B$?JRE4 z^aAn6Y{s)JXIZRK!eu_=Tb8#h1t@wKGDfmQva~_dJw)$H#vd#{S!7W1$3{kORvuP% z6#s5#yvuTrWiKe+;Avwwqa>>&>p2vA_cI=4Im+?^oIhZB^&sOVmP;%bQS$0h#}UWQ#_oWU}e#bDO#hhwF;4;6 z0rwj_(=p~_%savAVCj^TiI0Vkr355qJx>G@zr0MKeUb}M>=0!7$o!Ex1||K8Fp02; zup9^Jg_k+vOlO&IG0%gB0VIt}F|n|4vaCnRt4d6PtU;`?D0ZkaeP#U0xE*Q-M6U)D z8xuEE8Yt}H;jF`Sn(;Iv3radLU^>Nkim?tQO`0%WV7$QC2z3j@Zx&4F8P79bMoFhO zOjjANGA2X)0a53`bcOK><7brm!-eTA<5|WZC~@h*bcXQ^;}eu{_F=ljc!|*j#lHbe z7a1=y`hxRTY7xYa5T@&l*BM(-(oh7`HO6a7{oAnGY2uJdLY-UNldHQ*04Q5 zadQUK7Pf6{nkZ=~o9P?lH%4QWvLuh`JL7l8qbOltz_f{d6FVnL*;K?N%dW^?ieg?l zQw)17dkoZl5PwuLNw7<>N1^z)h6!|+JsT+ej9}@io+*?)lwA$#W{BS!nQYh{*zKV9 zLd!LG?}gA(UGOor@+?2aIN;cc_YOd0H1?2l2@ z&0;ELFK2gwx&>nIJf`XFGuVruWduZQ5z_+ph3x$(dRH(tvNyByptx@xQ!jfz`+StN zv4LqB`!e<>u-^=sAm(jiTF$-mTFJhW-5H!-VC}UXOm`R` zF@8iz_XnB&GBPmTc3@y&2bHl3puW{1CSFEf#=lme?l)}wFqY&d!3uLh)OyZ2< zjK5I&B*&SKu^(ff1L~8&`!1)LKzEjifW&fEK>I0Ym>#n~W0*dMS9Y9o&s-C;V;ew_UP$h>ga7}-6h zSM0CYyHLz~#I&D%Kl^i#d2oB5F+F5|$eyAD8dHGv!Co<4VZXw@+kk4?*^V$``QMC#Li4=h;8%Gcd3PJcRc1zA=4b|HOU?#k^lkH`s5mXBr}#_mAl} z`)~I5AaxZmzcDf2WWUKi4MiOr^B?v<>>?;`=3>6ZevADyiaI{#zwCe6jX~-*tb~TW z5c6&J+w8wk)QK_wWB^Ii74 z?1?DqG?*DU7&vC3go_R{=nk1iP`JSDFkpVq{+@j+iaKNFv+QTtSAf*T!otst`2+h0 zc79N}OoGLw74t>*i|qC&@nOgOh5ZY=3P>H?4rk^|?3dV6P}F%ae`Wv5t^~3d-aq$Y zKEZy1{Wd7Q!1V?&zh-~Uo`Rw-nE4d@DRx7U`{3%rnBTI$Wv@q37s-5@{WNQb2Bu)ksV2l>NqA~fDIm@l(mW}k-Qj~wQ2 z?BCdbfXsuZzXIk9>=)Q2P}G$$e`f#8z8hp-3M~98n6I;6XLmwL2Q|#U*nhD%g4B7> zf!f=^e3ktw`wJBFT9|*Z|6rd7QU?!%4(4m@*Vsi-%NoYtQT&PAFG44`wNLFYGv&UXgs0i6#GVuQ|v z2B`&^2Rb7fbawPaHHe!)eer*e3=AMQfzCt#?XN^;Uo>K1_ytwVr4DgFNDQ00ohl3r zvg#0Xk=62J5kuDxv(o`dEf+N0KxSniiKFX{FvabDkeszE1NcnXmo5|Vqo~D#lTRlhss~0#lWyli-AE~4?^#Q@?D{P(7wqW69$GB z69$G$R*>^4k@?2v3=CQp3=ARW3=EbQ5cvzH5E`UzwwDn#gT!*&=I0< zt`h^pN+$+}txk|Ll|7uXo1bOLzyPwN5_-PrHzSCCkQm6lxcDG(kh{OyqnZm62l*G| zACMUrpl3RR_%Q#0^f{PA^nuPn1%)|C4@f=8PF!JxtOu7FptuE{vj{s&5u^^phS8vO z0^-AH(7DPWK8yybLv|~&yJkYq7HzhMgc-=KAo&Oj28L8_L2x{d=J5Kx~*> zU~(}2L1=g)tAUAu%m=yuH8j6~)PUp+Y#@F|78f^VV9+yVV1UU>Ix{e+IYZQe^r6d7 zv1MRbWDD_!kPQO^$SgSssZhpFSUW_2Z@8!f$WB<^RR^2 zjT|m8Ib?N<9U$s{n=vr3nP@1qwf8evUE34cNqB;in7@V~`q8^E69A1 zUqN94k^_a~Wp_k)!@}pFEdv8A4$s>%Fg&(pVEBZT2i&X~7~-M%^{g=i!*gi5DmP;Q zpQj8;e;~Wi`ID?r<0K5K43pd-=lR0K@|_{(faF1E(SvA^I*=LBb_lsp2L^^52Z)&>*;vYS&mWFo4WpuxDV1bz)#Ri)0S69Jf7oIgr^PJ78+j`K#@)>q8c|fz~P5XizxA z@-`?wL1p+qO9lpUD+UHFD+UG|D+UHXD+Y#mD+UJ8x)abk6VSR6Mr}x&3e>(@0&QP` z*iz6o)G25i?4}k2Lo8Gt#Lm@XU}%K4&DymX7>?+o^2MR%9*63ggr@!jn))0a1_oPg z28NB=3=EFi3=BsMQ2EcaQTgBXQTexY7#N&&7#Q4i7#KWt7#NBSQTe~o0fx!Yz4M?mBOO0ZoKceYhh9)nErvE&e{THC_hnc?sEk1YY zGBC_Qi&Kyos5?H2M?(NP1l%e?Yxp2*9`^x>f%dCD0*OJ_ z=7Ge(>wiIF|J8*->p?(bptZhCo`|tIW(LTb+vrNrx)vVr*@w*F)516zdQrrf89?jl zN>IdD!2AD0{Xk=pFgsWoKzm|OL_owi6hLc}*%(9^MHmGGAz~1>aDvY~7V<|H<7EKt zVdwz45AJ3G2GIUyUoT{JLJXk2%NGOnccmS)rm2H_A-n4Ad5*bfc7%W_#%r* zf!EyKM)8L<_-yXXAY^s24DT4;F=(KO$um4-c*al|4p9g3uL1)XBNwAmFhmUEUnPc* z3?CViP{dRiJ~4b^;DLq}M4cLVJ<=+u9T4->8QwFzXSk0dror%m;RC}u6!WwgK=)NL zh9KLk!|;XS3xiN3L=0k{E(2%`z9SSO2C-Kkd=BIFFo+mLodNg^D4?jbVF2xY zKM=*hz{0@8zy(fMwhY@C&N57mWME+VuPzJ`vtuY{*upR&ih+S0o`&ohKx@stQPepw z6fu-Cs6~V3w?KKzfq|L9i9w#hgkcJbmExiO?ME4S0w0|8g26nR#!xM%l42&pt1TaJ}Br}x4!~{Tg1Tld2w8O;|Kw=>b zFBq7am>#e)FqyG4Fh#S0_og79l~(7+!0B0j;_J9?ihOCawXl*Fhy1s1^s!3ozC{6=hIxU;x$d zatwOl@&S~_L1TZQ{vK$o0MzFLnKOz0|7iY)h2JPW8UjN(1hD1*YgqC> zcpWm1`X71jZzzYwsM|+FV5Efrw*0Rci`o7M?>WFx|BvSXk(O#k{X1Mj09*dg!IJ;M z`-^bY|Hx~5hD*4N`eQT%MnVW+%m3T4>oV!|7iXnPN`zlFC!%c zu;qWfcm@VGwEPb~=L=8$58Hb?Qo?Q2pQ9l#96|tF{;$N6|G{Va;i>;e^Z#&24WoV- zX(50u{~yMZ{~yLPFfhXFe-;K627LzI1kmmv&^dgdHNor*Mhw;9JprJ7aAFAz44`vZ zKy0T3$Qc_WEo?{qI~oFmJp{1j|B3|6`M>F)yng&HbpHz=o3a7@`^cK=!@{l^q~^*%`DLv>5iKp_VbR49N^0smNji3|knI z86!~CNiq~MwlapKBde2RNM$Tw6h+ai$dJmA&F}?9Oobtrp_oAlMXwseGKNhIYAAMS zF|;vEWO$r{Y=<7hT!tkKJt*po7$!5!X6Qn(!;GPnp@pFmB@E0NIv6J~g3e3^okIe{ zpmRt-xH^S_0l8fQYTMAG%>z2$0b~z|Mn4yo5Fc~~>dsWi*`}jyCs3Lmd>C8)f0>S% z|6gT*&PHMYpN+)8z{Ft4V9HR6A_mI;>I^cO$m&=av>EgnUZaSyGWakAGWep1u`vWQ zL@;n?Alu8%pvj=gpq7oCzqlBp7!nv_QN#ooHZnvoZqGy>i;!eUXRKoE%|g~I#}LJs z%J>;YOpzgpA%np=16i*MLl#2;!$A~vY7C1R)-&utQK!Yw%+SXWjiOGEVHU$e1__WD zD5}A2B_oCj3^N#NP~2z6P{h#4;FX132AVU}GPZ*A|I!Qw1{enAeGsVo-TNhz~lic6H`x{s$$6!HTiv|Gn9m?f?5IVk``y451A7a*@+7E5kjO$1M6N zVr&dgSzfW^<|F4rPKGxupID|9AdB%ch_cRRjmt$AlVDiIx|bDn-!5W|L6%`I>k8I2 zdC2M%7{0LlVzELIQ)c+X!ox8$q2_-{COM`jC}M033QVd@zNN_dm6Ji8Nta2u7+H*;A%N)`Q+*M# zm;}R9rXNg_D0*cXZZJJ&T8E-nfkB_ilxbrLvR-8db0%A+2ZhLD>J0WweoTQV>a-b7 zF+OBmhoVlOp^R}R<6{(cMhq-W;!G|m_L?#*WIV#ikK$%ahUbj`7-dlO+A`EKOlGJ= z(d)>Nz);4}jH1q!VHN`y<3kj6?hH|kd5oJ;?C@d`U<_n*LNV#CytlZTPb9O`)%R5MTuW6S@WOF`{$AqLP{tDu%Ks06rLik#P(7-Sig7}Uy; z#h4jX7&IA}P{cs}e*^HGAgF!;VSzGgxqQ@|(GVC70ZIY3{NGpx%Kwav$oYRk8FF39 z#309@2F}-;M)NbJQ8221Gz11L1jOr^7&yRl_@Fbz85s7n9A-f-6F}$sgU$s0gj6QL z&h^)+XJQZ(*AR9v0O@67IKXm%#RWx-nc*PIL6#U4F&2hHEQeTx${85gd?$eKb7W>< zXV75KV0c)IXitDH>wLugjQM8;vKS`=BYOu=U)DE7KBNU@c&<)EnZ zVyI@@$TkDPh?1DOlMq!oqy9JpA z;v7d0t2yhbR%9_522a)q z)`(_gF;#{_)_JT^ZOCF;3{kB4taeSvV!8~LtoE$I?Z{#V434bstRGSAHDNGg@L}jd zG0%b_m?4wl8H&Bu47XU`u{5KYXU|Z;@PJ_hir<_WIvJlbMl>MX>&9Tr+|0Zm#STw~ zMa=J+f1>!;m*Fe3HcK0d`}`TsF$poNpr{LCFl4b}nc9lnCJ1IIVJczThT`UM21k}6 zmNzKj63y_1MUJ%&MJ$$~j_CxGJc{0Uh5)7{rf>Dg{zzhY#-PrqisH9ahS!YlOkYv_ zmdOyq*vy!Zk`A&M7P78nWh!N6U@~E0V6ud?33MA77+@H=O|Y&Wa>oqljvG+>V0t5J z`vAEv1J%ESwY?zOLVSCnqk)0pU<0ImfXv>~gxWsX*@9>vgtsyd`gAbZm2SXPFa+?68 z4m2ikw;ghy8)%%66?)g-vIZsw!T;*uF#%QvCWd^5e1<+0F=mE5hCGHckQf64_)b7p z1{Q`~hFpgIAThXJR)zwG0*0F?Vr&eB422A4UC8#bGb~_O!0->nEgTFD3=Ir(JCN0J zGt6d~%`mGIS&W}y9>Y8aM-(w(hPe!L8N5;SiZRS$n8olOMNE=m4#OOV&nSAO8Rj$0 zXGlYFpA5rNhNTRXP{d>zmN6`2*oPt}$FQ7XIYakU#QG^#26+Y}26KiO6fp(xJj>rn z$m$dsv>6N-UZI$$#IS;41%p^OvVWBsRx+$)a6u7MVOYhmia~cW$UH{y`Yu)mRR&K6 ze+Fh0JJc8~8SEL}_afR)tPJW5jtuS$55RgMYr|L>G#HW@vKW3(0htFA(_{!_h+z2I zhpbnNA&Mc9p$Nq-+6?O%)-%jS5z}GVz_5Yg1d5n0!$yXU3`eJcW~V@D*MWhR!GK{e z(^00QeTX&zD}x!sO{N!2Mw1vA80#N`*QB#D*fV@*(q?`?6>;YtD}xKeE2ghZvq0+p z6bgdwxMF2+XE@Gup6Luoi~(kc7sExS>r4g{k^SM#;KW$VxCR^sjEtar0zoU>Rx=)9 z{5t_zoi9Th<5I?xC}MsLHyHRBcTHtrUj_X zL66ytnW>hIfytGXfoTd015*Jz1Cuoeczh|npMe2}b8HwGK>Lbrt1&R>buciT>Oib< zIo^q2gVwv`q46t_)XE^q$#+5Yfy|6kV_=BYWMF`;AqLSYS_}+M-3$x`-KgRqIT%LP zI}mMFm^)xJsBW4%5i-^`Wio^Y)lHywqQevhhSDhv3~haoHfc~Fq8$nn1GN=FVlXyn zyh>vNL_JIn)*gkafvHC~f5Q|=n|7-S1H;{31_rqvNH}`;Ffdf~Ffc6bVPLq_!@y9a z$-po{lYs#i)eI-?zyZC>l!bwTA)BFq!5mGjjiCdj{s*Z8)&Bw05OoU+wEmyi zh?o;#VPFE+^_3toXuZzDzznYI6H&xi7;+eL7*>JApz{eV46NX`!|CbBcCdl#>p~QJ z*%|5>>KI<5h;cE@WSGfNgrb)ZTwlAQhzWt)1p7dG8UFKw+A%B)q6{+_W-v&gsFMKK z|MOAAq`>Wj-zZ|z42u~SGpNr%cC!q_5{4xV!6;&~;5LEIB1HMY!XU?B$Y92BY96wf zJa|uq&O&4{1qLk!eTI4z^Ay4DiPb1#O5paybrdmWaGQW(4&qK*&`xd-20w-kC}OG% z77TU_vryck#^Au<#-NX)PMsl%A(J5n#eEtK0Sw^`KS6$j-kZz9pve%)kift^6FFS8 z7}heZWza(r(`H!5u#O=TMN9|WCNQ3jsIOTV^cnUs9b?Kw5i@1D#q^x%EQ**N!#5@^ z=3|SH^*S@WWctGNYayauVqtJ&IKgy*DRUmOm?y&}rW;I}bCJW|i@|}hnsMfAXEb7@|RL2G@}e z3@i*m3>%pCFeS`K)*H;w!O+2=xft1R;S7pQs!UOHkfan=&(9VPjxQU}a!RWMN=RUy>T!@5j18*e4=jYJhsnX}c$gZPdUW$)b-b1_ z14G}O;Z?_jx&pW`a=#v=22`(iE=IJwK|K!8`oC3+5#=Cg|BniT9>Yx(F=p_ZK#nEI z>R7=0gh1<3LGz{{Ji7i56w0G`Gz11m2w=;7xt@eNS^S7R_?SO5}( zpUnZv|0)bAATetO@Hi4^1jwAh8eA`e@;(TU=KsMF@1w354FOOHV9Wo1vE=`#rO5R< z6N4s$HG?)t3|=OH^1nKR97qf)|JyM*jplz)K#$_l5Ez6ZfGz)TS&CWzUs}q*zz9AQ z73`O3_1TJ_WxurBf^qVC8HrQ z8Ulkd1R(i87rNJ%fdMrBw-J>8L+63_=D^1P?ttwh-zYBkWjK4_f;ImC#K7}^pdf?f|Jqf^>X;ei8RQvcKw=;z;PY!i^MrB?TUR009y2g-F(@%?0GAV> zy)U4$B4pKQc>xNtQ9K#~^bP@R`JZ7mXpKE&KMbgb2lW6nKw{wi2p|_i@_*uL1_nmY zWg?I{0Zs-51|x932IXnc`f5=9U$L5j!PbL;p>s6@!;;mb_W*)IZxoM)z+edhZ2A8M zD6gaS|M}N2FtF`=fYSbV1&M+4Kgc)C3~~%|47F=e>v~0o72q-fRM&&*`O$I#6jq~n zGz11m2w=QjgJ2fj`$pP#b^kS5(3!rzw}zn z@qcHK7`#k?wEt_?GB7Y6-5LyO|BsIUkrM8sYDYt0FoXcM{C^yj*Cp>k+xnp1KO@6C zkQg(pO#sRNG3zkL|5QL?;4%T^JIMIoly#_m0wsp^;64FpUp#260Msu4?IQq<7mUsq zfWmDQkA?t!LI7L-zYog8|53;P*w=%`1YvjcLh`@EdeG>gD0EHm==dLfVr<6Ao>3VNQ?oL|3U77jQ=TYK&|T)8J5HAdQd$-I{pU=t5G}} z0)rz2u;u^c4Gauy@V-7I|4-P6+SXTMP-2MRge=C&pv<7m&;NtXV+I$7%OG{|egYqO?m!*I4nYP51_g#mTafLLX7Fb4X3*P=EGEmK!l1%%A4N=_ zL6t$3;m3C5vPhZXIl~`@1{5)MhBFLL83Iw<2fB$!n?YwAvR*BQ{|u~*XHmp-8Tc86 z8IPivXUHJOsLW`JB4)xM#wg8Lgre7ifrF8Uu^Gi)O9nGWSH>ONk;BT0L65@6crb=D8e1d#!w=Q7__!AFvM(zn9sWfLW9JHU_E<6ko=#s6FFTnF(@;rGThsNEXK^B&Y;O)gQAXwL7PFBp$?=jV5JD?Y-G?0 z$NCJ04C_E*@Uw&17>pTA8F*0ivNM=7STanuL{7h43^oj5;PeYRO9&eVooTn-l7Rtq zH`73d>!{tMAutp|09*b)x)U@1GuSaOFt&pF|DgFlP+Q*woDV_ccA)$=6#P2s#?cTM z4FS{;z?T0-cY)^rKB?dVvpv3`o!_5Eu$fT3t-Ft z$96L?u&qF?|6ibpu`xI?I58ycVPIff!N98@@;~cd z1_q%HSpH{V&|%PF;0K9;^EJc`1`GxaFZZCT(_+wK_>Lx~&7jR7wHI?dpxEYFqrN`h%MaDz!1Nmfgx!>14HV528N9N z3=En3Fva)|LG(;L%)l_?Fara~Y;5J<`ooYgA08D^n~ zaWI%Lm@v#k5#wYqWiVyf1rmeX%f;Zp;J~1O;udZOUj|=>^C)8c45f25W{Okl0+8_*qf+mA3XfbRSmEn7fgKZ=n<06qVM&i^Yqjye9%8DI0klpan+KWKuRqDaz`_W-Cq#%rlfjn37)4B&!JfgH zAr(ch7z1eC!IKlndc_%38PplJoB-`l0@(|x*DDz67&J~Ii^(v|W!S_J3p&RL>^_h> zc?LIzQijVYdX*XWG8|%HLeZWGd<~n=2C+f%$n)gL z>OgYH^W>oD8^t3x1hD1*+b0=KoX~l2F9h7+e`r z846LvxEM+pY8jMJ#CRDp7z!DFg7OmFJV6Ex1}BDqQw$6&(-37s14BPJFM-lD_bEu) zH$H_(^B^(gbdD}Jn$AJ-H;P9?0Cxx|b}}(=gYzNe9&tqmO_aNSLHCk_+60GBf!6=4 z3xm%8Vu#-K8{EmnAUKVI!NCBe7qliwnIRWNj2XN(uLDJl1-v$IDM*YFrk9mLjX{m! z5Q-QZgF1sc!+jJnb_USuJTs6O++GfFo8a*&1_pNMJ;v+|oD7-_nhaA;Bkm(*XW(Wq zVDMltKoR3*2xG`#h(Qq(WSGIQf`R`mqP$~g5M{__n987xA|}q@%@EAMG>emgNtl^| zDVl|WX&Wm8lQA0ulNmb$69eSlZ^<(Z49;g57z)lXFw8&0z;Nyi1H<1l3=A(%GcbU{ z9<+X<_cWwzb2<$<2PyY70|Q75v_=k8_JPHr>*HX2+%Y;TGa3TKhXA(vKlUtU{a=A1 z25JA#K@o$r{|}&uLE8Vk=a9{VwEsI$#Du`*#1RxRVQ@LYa2{E&2)LZEK@k%LmlKI7 zdL_VR!u#{c{RBw{Ee0KiRp*iW1kwy?3^@!ZQN-jJx)~NQXu2V*Q)JL*NM_iMqE3}z zHNyr5z6;3eG#C~$tYD}BsRNg(pth0@Lq0r=sYEtpA^J4LKijF{m@>Fqoi-aWm*K z7&ACsM_y0N!(hq~$Iy#no&b1^VH=7Vs7a#0zvZ_#dd8uwb~u@Q^_nBnBU!uwgjIaEW0PO1RiE{9)i>EJjgh z&+vxf6N3bb9Zn2i8GbSxzKR_7&J6sF^58K>&x??81;I-Y8dMG;um6v~#=ro=nb$G* z0X(<>(E}QjFug+DK7gB0dzvpp^n%(kkFG+>BiKFwP?@y#Dx}Qfy@ps522u;+gJ_r@ z5E~?hTyCMuA(vYq^-b3xW~*I?*bCYVFx2uZwcU#?|9`xWIsPwngMon!zORP^oNpv< zGBB{g_wWdU$L4)*A?p&DTej7$oWu@;RVAvaGJKi!N9|3l9IgpL2B z=YL6O1_m|fLFU;}=ZuEHXb7N$0Ji*}iY5Ou*&z4-*%{;*c7f}EQ2rOPfsFmh*)TA` z>VFhVMmeJ)Fd71bG6b;Y|IJwP{{fW#KWO~l3?=`60G;hQy8d@i#__15MneEs2w= zK-&kn+%hUY8UmvsK;IC+mj7!(`JWMX*Dq-FpOGOBl-J?we?a5^8sPdr$A*ESbadX2 zzL7R++h_<-DFm?P|5Kp+UlLORI_n2E|Mv)Vj~sYR5VZau)c$t?=YLTDA5^!4+W(-w zKb4#{YRqT|jD`RmLI7L-7k`M^{x1ft|AW{6p#6V_DEZ&Rk`9g?wPG{`MnizAA%HFa zCt}I}i$MGTQ0o8D{r^;rh*85vLtp?x09*cFg(d$lMcMxcs{hqc>i^NU{{TeZsFkB3 zKw$`A%m1IT>P9Ub4FQTn09*d=!jk_lJ2EgZ!t+09|3BjVA5i{> zo&S+zOtF(j4Hyl9(GZ|h2w=#K;PpRf{hu8?|AX59 zpnBhZH2)8ocpr7>Xb6Bp09*d&e8RxMhSvWtKxzMj*8d~U{~4|KK_NMcM?+xfg#fnv z9}dd@Xy^aS*de$7LFa!U&i?_`|FH8vVC?`syV3ithF)qIb@50G0c`nyDJcJ=_5a(< zk>~$F`QI6({g0mitxOph+(*v?7-`9A)W1V41hD1*&!GH|R{yhu*8jrS|AEf`iHGNZ zaT5jxP#?h5gny%%);AAJ1}X#5Xx{tqbs-?xOU z0UnWoIO^%q5E!B%fGz*`VafmJK;!@L`X7}4=fmrNQ2&30Ii&6%qQNlg?9mVyks*LB z|KG-v|6jN=Ffe{x4n6-1b^IT6*4Ky(yire&hQJUH0c`nS;~8fA|Dq-G_#deLN1Xoy zs{cXle^B3lhzG~0^G8EqM1=sh{9lSC|68Htf6)Fv#Q8s<{6BjB&xlGkqn;fmA%HFa z@5hq=gF)wi!rT9#`hRr)|1e1cquv<7A%HFab3Dgv|E~p|{{_$gp!y$i{tu}BA8q@O z;6ya)^&uMq*z$iMmi+$#wEqWX{l6)A{2z4I|LFNYLpJ(H9X`TC09*c_4a)y$`+w%R zBai=q>i^O6e@1xH8TI}!2mx&Q{{<-jqpkm209yY8um3^&|NY_hKdAjbdj8KaNDQN1 z7;zzhE&rRoz})|L3e^5bS^wt<&i|nMKalhPhzr0`508ex5Do!s`M(L2|IyC>Sp~ZP z1Ev1Y#hU*|#{q|MVipMum4f^|A6-X5BY!? z^}uKdjKC1UmjC~Q@;_Sr&uNN0|37;E&j?H^qh20{A%HFa`@X{L|4#tz|Ap88p!0v+ z;r)Nm`5&M*!07ou!!Uu2dTCgP0Ji);8%zF|Kw19>>i>_P|1+!;#;E5;LDj7#KvO85rD* z85l0TVPJUphJoS3n_(N&qaGU#fk77n*z$kCTLuO;wDo^K--7bLCOrSkGN>|?fyBW3 zgg|+nlR=%qoWbuMNS!TI9WR4FLjr>;Sj-qICd6RH;KPsw(hIf&q*s(7i=l?$Do6}o z#z-MUfGz91bu;u@)?=bVf?Ry3WMtFW@Wzc1aVqgY|f!qmh z6L2xeF=#Pd1?6>kn}ClYmSGBm=z9hRmjCL)TnZq?{0!3>5O;^Xd$ckdy2mKyFFHDfdcMni!1A%HFaTYq3+U<+{dVF1_Hj0_-{{(*sk@!@l5 z{%2y4W6%J%&09av-i@O+jE2By2+$@3u;u>?p!^SR>x1kB<$gwnKcM`7{VqoSm-+}& zGm1w;U^E1VVhCW%|M4F&+yAW}85kJh{dz?GzhE@~55;I7b@ONlfI|RV{(p!i|FeB! zU|_^j|0{d~8#79bhQMeD48ahMqAg6=Z|FAKrFcgFH`hhQqd=6?CfZ78fWutgB1V%$(aD@Q2{BQUbGyg|^ zMXuLJ`~QP07Drt(8Uo~n0Ji+U1eE{5>-s@vLgxR^fb#!n{~r_}qj)p~hD``y%m0Gk zF!%qqfW$z)2CoT(^#6@PV(@iBkpBPUZ^-QgHU>q872rO>rf&=kao-UAg3pdI3+eyQ`Od(=2yQ2U_V9uF|2g2iUi2N2&qw?Jpzs>S zqaiRjLjYU;e+ukIw%O z^>`n3|7Zw+LI7L-Ka3^+KLv@w+XPJDxqkhh$ZY~v1_g%M;P$`3Pel8Fw4V9Hv3GsrWn|BX8TugtKDVFrpAJHuLr zjo@}d`ftoN0i)*$fC70GkA?t!LI7L-{{YI@|Nrwt_WD5bzu+GR2DbDEq7X4A24x0i zhKxT942FV+e|KkK5b!|k{~z7^Ke*$3)ODjF01E+Z`M(ZJ{$Ki+ zfq^k}f(YXLZx3+(2c6Hq|1Sf>&A$u`zy2~X`ieWxj%ocjDFBd}$Ll%QB__iMQ8b^tVY zAjBZcpvZ6)qz*oxAj+W3puy0DA|}b8#bC%#$;8OO!Vt&^xjR&fp@E@`;TG6lcc{I} z4808V;A0V>+lM_E85uGd85wFA8Nug`g2X^~6CQ=$KMvw&FfcNdFfhXJEClsqK;keO zb{{E7Y&QcV_>S^zOpM^WhQBc~qKtP6FflUdFflUtF)=cvFfk6J)G_Ln;T{6m^1m=M zBLkbbhA?EU4=CR=G9d47ChKC}JYuGA0K_OdMRsY+(iYCm&jNNQ285WspA@qM>Ds3`0Fb zC&PXedzBb^7^Z{EnAxn147HIA7#LP=AeTL$JI6ug2erx?&|bAmj6B3G3);dcI0}PnL&<030xn7>OD|iCv4NGiqQ}l4S~TH z0@(8ZX;A(L_sv1Bh1CBaK=~g&{>R23$FK?||8sCKGN^DcGWczr26qN`hP5CukY}J`ZVYY=Q$S+yaRLSg7X}xGMQCEK46Y1k zL1IYe`7rn}97GfIX7FaX#ev!HFyKTMV`8vluw(dzqK=utn8BE#7DXKkg9M`lqZ5i4 zD}y+rIOBa@Mh3=^cxA}=Bsar8=F`mLATi~XREQWq!&>GY%(wVKxqWb1m~4kR8ZIm#uVyI`H%-oHl*M{LT%T1P2H_*rjEc_f9 zbXYA|;{-tA2NQE}aS_N~ zg=#K{9c>I;EFvt9DB;}8;LBRd`WWPooJ44ROkt>CozLn5+9Lo@r!yGNvfgJcvS46f z^eu(vk2wsFSU@#IT5UD=QC59Ias3!Fr0-iieSb#UI!G({J;gS^tLnI$$+#!gUk)eW@k)e$j z!k=Wpz_81Lfk9Y+kwIAiB35P3zyKPvh_+(@kMD!ji1HxhKz$sL8W;_l8vxk}QV*I_ zAXi+G3trZl2`Ez~C>y$Y5;Fz#!)UaVyAO`OXkFNFB^f5L?EHfdNE= z^uo*ubzoq~ae(+2BnJ~0jfSk@1o1&;PO(Rr33D6BPMCi|deOyUVF;o@@*uN7G`c!` z;vlzs@Xk2o0_K5;TK{N;p*gUsH|!^m(68do6x8fg47*fTK1 zIx#SuMT%2oIc|IGaxk~S)S~lO+hNxS6A$G9Rdk?CFf=f>`hS}MX8->ws4N55^`JTk z)c<#axBo%mJ~Vtg>dMg&7!3jB5WtrIodp>g*wFg_MS_e->wiG`KYBF(BM0Otdo%=w zU|3mKj0L}H@a2@f%I2r(>AuuFEzWeWoXXdfdp z13SZEhLa2hs-V4y3=E)kM$8Nx4C@&-GCV;M<7C*(u$7?-q?Z+@j*DSC!%hY{HAV)O z9WXI&hTRN%86rSpaCJNk`xy>0_$e`h?@!=R0QrrVVK4JuW(!$l_X#kxFt;$PNh6Di zFjO&DF-wRdi-|LsGng~fp@>N`STa~Lyh0I^X0T$gVwfm~tXG!7n!%c(L>yU6p23E} zhGDV0dhKz5%Q!y@KI%nDGqKIHJF-wN|%=4K;p<)n!STihOUclUeB4*35ka;1qH%h$O zGgvTKFua4RgP7;Qu!4C7^HY>Ou#YoalVKG@F-RS#)KUPc^JmCnY-HR5O5+T$^c=wOo~ev^y%KW%2xQpG z_?GFfG9v>!ST86&2Qlz4@GwjQrF*#EV1}iPn;BQAGBPm2-4ejjA=F!VC_GB<(N ze1hx{0GXErUWW`81L+0(Ernqsb1FL%BRd1r3Qh(lWe)J%#n(s%hJ}_43}9M{kwHR= zkpb8K-p>&X40*DQ49Y8(2?(t$&B!o42%;}Eh=CzFh=E~VI0J)!Fhpzul-{ZcQGX3&cQ6CP?O+Cm z|G^9l`XLb7E|P&^YbZnyb2tM-cL)Q+p%4ZJwor(CB$O8Qf~aW-V_@(@axZ9~vaB*A zcnu_oex=L^ULy%=+kyC?^@GUlcTtf2&!D;kv={oHBLhQhG~|8<5Dinyq|V5|te>-C@qlPI& z3|9XaGnO*m0Exlta88DD#!AM&=8Oz1a4{~1YQ|bdK}$vkmOZfYlAEEPv5_$Wq!(Te z@-Q?rwlaEy)WOAg8S)tO7%NO5^$nzq=VQ3Xe2+OvAK4#*3`?1pG6(1)i;05k$hj!t zCjo8~Fl!*IlLEI1@=?TOz-0|X z?`Cd75z}GV!@P%iEmSW=ogTw2=3C5fL3X%?ctFBWAKXrm1L^hfcY%l*FzjO9#k>_H zR-p;HvWkJ3!3f;;dJYy-u!5Lp!my8dAM*;7_%LO7$o!D`nGwXz5OwAZhnWvEdqLd- zvBQGl9P>G5DUiCf%shygCBuH^{mecfF;JTtoVTpNZH#)T7{ojqhJ(xpnKz+`*)beq zKE!+hC4L>iZ2}1tdmR~0GM{A5LQ&@eZWAoFK(2E=88$NPWjJCE%44wl)rWzT(SuRQ z3|TCY!H+SGu^dHR7(+5c7lS#-Ja8ESs$U}+jxyY0cw>pIH=d!NVGYAg6J)VehC2)l zj5|T;o(+~i(ijApr!zaCjTQwpxNP<_v93Ta1pn=vvZnnBtZ zAhFX4ka{1)2DL3<^2mBNm_yE7LKZ`2D_Jozm|HP2M3^!#fZ8u0vq0xig3ekoGluMC zfVERVbsQ+Xv9(h``apMAfXs%qOJFppT>=sZ(V(awju_n6hxY41{*z{qW+=1*&Hr^W zfXXP)jwn#BUTDq8z{ms=1I_=jFqkq-WO#%k#>ViSft~RqiWmpO3x+QYm#vWX@`KL~ z?nMz3W|+dToS`2@uQ|?mdun|Q}p5Y3^Q*e78)b5;Z#mI2Z8j{w) zY;y(%5Dkh)5dF}Kk>S4;BZGl8BZIRwBSSTkT2T4{?Nx!9gU*MgE0{ct4+^(YJQ@N+ zF$A#Xe=Qr(o?B2}2l)t;`xzOg+98(-Obo#c!3;sR$YRV4pmD-WDC*c4LK#9C_M@m{ zXYgh4W#~c?<6r>o364k6%gGSP5XexA;ubCj(7xlBATe-R1acoY1Gql{5(A%44ie*G z0PQ>81`>m-<7EK#Prjho%g5ly;K!heVlO{~KZ8GmJc>F21}_FLhHfWNSb*9npfXT| zp`Bp~L%buhm;}Q{hHDJ$j)?vQ1A`>PbjI0?sSe2MWEs*Jr!p=>(W}VtharXWvpsTI zsmf5uP|NTR#a<1DM-0ChSWv`t7;Z2;U~oqfGhmpf zm>EMNLn6a(6fsMN1cn5LXpozkIvF79Y#5Rmk{N7J#2mop1)+$!fX%Z*vDX7^-d~V9 z2GH0mDExfD=7IKe9=2m-Xt!l#_-hAg3%$2zWcX;y$gszjkzt}8Bg1AJMusXI2)?bx zz@TQw$Pi=4$lz}aIp0yMx_1!D zzw8L%gUnFMXJE)LfV53Oe2^KSdIQ8ZbYf&c=BGL_GE|}22fho>0iq5U8)hEJELW&o zK;{$62c>RmVr==}$C;6V4K&CP-s=xaw~P#@of#Pz!D67eV_`66@L}+BLl)y=NM?A! zAci6)z+ld}f-x6GuLy%OqbZ}SE3#fmh7g8C24fdwF=Yl>21AC!DC%?>co`KL1zZ^! zSePOG0tN;>hSv-~8G2B}^chw&?qUR`El^#};=;(F?gH5-obH0TPZ+e9_lGN{I4G`` zJEQI&2DLXUT_J7L4ESn4{o_K;FDJ&u}1-w?o-|JS=A*Xxk{f7t^$Z?Z6WF$6JO2IX~d{R%1* zxEMkhG8weok?Su3hDi*I7z#X*^@=dGFic=j0GS6$=iqutib0k^ogoFJ*M$*!cCZqI zCWAf04iqsB21f=D22&LC^cbocni!%z7#Ubx8NqXS3=H}VISiEy(@?|=7?v_@hW8VM zJP~CAuRCVm2bBrf#6e{ONH6l40w8st+!-0TJQx{5Kw}Kh{0l341e1o`9Bxh*Joe=_5bgAV&?xYZ_rsGpgsX8uY>OO zu3~WWLC)8F4E_w647?~}f(-Tyo(zAykoAf))G*9ohzE(m%MMwFBMf&K3{dP)WZ24Z zh~Ymdufx@8Feot?F`NMDWrVp!pTUH|mSHlAm>I(=hRqB&yph`p<_xnLRxp(MAd6Wr z+-GtCumthj@$=tMutA0(K2KB=VJ1G2+9ADbv+7cX4`%~h9HInh7%xl%rG&2h9rhk1_?hoSN z3^fdEKFC+~pjaKnqalDj1hD1*H-3x^Y+j&tI7knq{eRA%k%7gF5xj1Wfq{u3lOdmB ze*h?7!}{UO4519+40T{JSYBsgh-8Rn_y-n)sbgh`Wr%0!g__3&9%Eo*NMuN6um!7w z>1Ag~Wk_cb^JipW1iJ;)?%-ySWpHB%L=od>@L&jFunz>4MX<3sQHDZ>PKN40WcP_N zbTdp~;0OSzgOyKm43ilag3BFT>wc(N9)Zs92bD*v0gMcz=lFxt)+iq65WtrIUj<^e z|G9z~k?#LwX3%CZV~_)h^;HOC{)dnMf%3oSX#U3) zsH5VeAuvQj09*b)izWYm8O{GgBt}P_IT`}QhXA(x?-YVr|7V6EpZ|@!{vYl86Cd`Y zDn~kOa4Cr%Ks?!Klc1TTK^BqXdZRcXb4~h*z&)47-s!%4-&h6SCj#~ zUXO`EpFy9&ES!;ng$cG^kC{Q8L5m?9MGSOKfCaZbG?t|MHMPZB#ptBr67_{C1wEqr7H<&UoY!72(K)$;Yw054+6|sh2 zJe-k1J)DsNwC@JArv|k525Uf!3XX=r2n+#i`Tt5dBLf?FT^}ewAnSksf$}E2{s*n~ zQ(;JpU}Ru4hpoBgVo+zWVK9t9-uuqYV9($V&cmSmDjEUV9|u~m58~HEFfz=GK;%`g zh|#?&pb#I$qai@A5WtrI??oWaeS@9e<593oNkzb%6+ zJpcDZqUL|ONYwlv89AE&=@svz_Kb!ACgg9<|`NDSU4;Ab#l@M2gT#mK;74%`1Dz~IXe1}_spXKcaF(E_yz ze4-F#1n3Nv3XplOj11GG5bcDWQKRJqDDFn_Xb4am0@(6DTQp|=zYvSu*Jol-U@&LU z1*rqq{~%YeFl=Yo&M+S&1}+moVr&dM7eax_26<0bhcz_ zG~_(Z>rlEO2Ex~hh0seg7#NJr85lmA5~e}r9_T!%^f<_#<{T3Sh87bBhD%luy;>Fw z;B!VmX9R#kbQF(<0J$N6E&u1nGcvH1#8g1W`XK%PDJWu046+Qe3};cqSiolj+9n|D zWn&0o2w`}FBE|te6R;-{SsfQc7(*C?NfILiOG!)xWKS?RgFJ&bLwXV;10&cipf&~{ zgD*oM!+t9UBrzd|D2Dmqe0U_Dk%1)vlHW?8v~(hbe;7)G@*%$bMQ%8b>KhG#p%?<# z^8eW+%=%v`nUR4-TtgU=H$nMdf#EZXI%WnX1|^1&WaN9oSsCmYTp7Um60VnxL6yOV zVK%6K1-BDG`I?KtgP{nVhe7!hq#l+>L3Jyr-W;v-hGOa(b@N~k0c`nyS2Ae-Kd8+O zay_K}uS-MC|0;}XjQdlN)v+?%Vz|W+l8P+G!El@5Hp5F4F>Z!C40jmrq1YkFaEaj( z!@4x&wz)8a2BR_K32WrKUX($O;S9rH(0xDfHi0C=dj>AXCMRTdvJAY8N{q(N$YP2N zW{hQwA)vGU;pL7p!+C}`3_+I2cN?lRR5DHgpB)M+dp@K<+7Ddn3=FNQ2)0xjg3X`8 z$gn+ykzrQ~Bg0-K^{_GwG_G;M6mnLmxFZ9DiX#Jqp(BJp*NK5)r4s|gRwqc?-oqKu zwnx^NWy!z*>IYO>g5qQpkA?tsLI7L-mrBR1|7WJ7*6X0LK35bm(D;8mLw!2x_ z|2G3g3^M;G4iW?F1@-Ge^M4r(-kFRHEdSM^V+R5Z*$gG{G68-5Z*3-`i~zNtwL#{M z&i_#-vPVrB4FR+ez?T32WFpVkLHhqHS&R&f@O;g};KLBY@B$XQPgoT*fKaWw1C9mWd|377K1gzTF^Kg$Q|JIM0^aX45c{pI&vO| z76T^Ro8=!Im-o}88|39)v9~A2|<0+y4c~c@wh!{~bzx1&#luFW(9Zx6~F z%mt|9f1~67w2tjj^G8DfH3YEb|Ly|J{LfT~ng6$-lnJ2xAH?vg0J)vO%@E2E3(x-& zg{b-eBwGF-9sfs-n^E3q2+%qNu;u@>Ld^XC2QB}D#{Vy(h(X5x7ov!P#{aVzdJ2)t z1ObLzhBA1WfIj~J1gVSwjsI^3nKwHAPwQkbYW@ff0c`m{xd?Or|F0tC`k#d%iXn-i z6C?&cCjd0p$Hq{_Fq6Tf7+D<$LkdF?!!eLLc;B3hp@gA=!PO19Z_dXshhYuFZ6gK- zM!0#P@&5>TIRWZVn-)XH|3Pd}{{cjU$_UV284w@T&j#(20f~e7AbNyG>!`O!Lx89d zz?T2F7h~psu@XiG#@R2Sd;KBf|93%o9iCs=7#tYl89G7g;CY>c!HU6-ArK@6R|gvZ zw_wO}Mb7Jd3`x-S|FC?EoY#@_I4Dnp)F9_|qC7gPXfy;yLjWTL(DT0xgABvF5=I8L z4Ak}iLZ!%JOyGOM_rd4uLB_H%tY_TI*yawa*Fj?J3@aGdFb0+~GB9Q^K<^IaVo+t6 z$S@B@jF(|DgEV6=ikJX{EaOt}czv82WQ;wj6fu4Px?>Pj4uHf;N+In6Y;2G#M)7C} zjD`UA5P;)`qtqz5woFI0xyCV=FBmU38IAEb_%VItF1CI=KT zb_PWTb%uyCMrgYpq>hKdpQ)K?QW+xyOaC=S$bLdzhBl@?rc$V0Ch!@9LJXP=ml%G6 z^onZ;L&U@xt}t{mt^tYlUt@%b$uM*?`Y`QOVPF826H4WfvLK=yQC5J;iTpCmxdxE< z_A*9>^JR<-pfd%ZmqGLrBL?!xC>{-gp&kN|{LgRzIsfk{N6zbz{Qnq543hsfE0FUw zGs6_d8I0#q#31><07Z<4p@gxGacc!?{_kX*$hZos4wA1y`M;kb6-7*(VIsp{29`=l zxdTxr!|

5Z+F3uYly?=M|{=zr6xA|AXcl(DOg+Ttejhk4tQ*$NQ-JM?(M<0@(7u zOC=)%8~EHDkP1lt&jE>n`}H6(NdEV!g6-D@i7_)AU^>F|3zRqEdLj9LJ&G7FLpjq% zrpJ|x3@psBGr{;6wlM8w(uA4^$=AXRnhf_Dnoz_f7#=b#X6yoq!P^9~3`-e{;q`xd z6(s-jS0VC0X#C(X$PHNL5nyG2VHIW@fRGr-*Q0ne1cq`5pyz*S25E-VRhaqTxEhw% zL1X=p^*`T1`4F7fL1Li!e;bCZYUF&4dj79ZH6l-f@*RIQYMnf~{%0tsq*1pI#Sp-j z|Myj6=Koiq{0~0s50uv-`QN4nxl91%e=7#X8r1xceEu(U4Ql=msX@*Epf>qX48u`3 zkA}cd4FPQVe_ajc`XAL=`J*Z3o_Y*+n1Ze$_7sGW>nE*fk3;+4Q zMYV`B0@QA20oj42-9A*qd(_>dAuyOi09*b)T#K3i>*|p6KMR8;gF6FjJ+c@ZLk>eR z!=*ap`kx(qPVgI09)|Z5I2lSArZd=~=;dYzX2@c20NDXAJ9rs983GxkZIRF16=ayj zunE21xOql4O=q+I!AXf#lfgsMnhnrLI7L--&~KG|L>rP zfzJPwW#DUojKjn31dwOYWoQG5!SgyhLl8p-!yyzgP6kVc00tkB7(B0YGw3szGw6WM z@Pmu-Gh{O~gY!D*JWyDE2IY4c8yh{E#|J7UjoLdDLjYU;=ike~AjAY)|HHsw$Y99u zeGjUbCW9t}ej_6Tn>I`xWS*d1jRAa4Fl0WFi6NRHhC$LCR)>Q^h>d}RQH*glX#F2J zuY<(67=AObFm8vd1N9xa8B7@h8ICkU$`~f-IRP;YDGW0}V$7iRL?CrS4CxFN44Xk> z;5h-1m?%RvLkB}XNQ?=lPJ*GEVJ1TeTnuEd48uZ(?+l=|1EBRppmT;D%pv=DLGym- ze2|*Ujf@Pp8yOj%HbUkZ8X6fHmNzmo^q}!UWfMpaBn~nsxe?K?0ogo?M?+vRgaFR` z4?eF0;zD%>bx8h45>sYSX3%V6WMKRMpC6Lfk@7!W9TS5IgDFF36Y|+X%na8UZZVXg zh_N$hGZ-=)gNuRebTaUw1{H?n7En6@^*mAZeu4#qB|{I2 zI%Wn{230gM76xqwZ3dZENS^>U?r?$O3PS*j7$<{1gDJza7FfFjW(>frPL>4Au0hAp5wf#70d4D%T_GlZBhAe~t(#ZbuD z%$N(hPY7O)$uYDs&IRus0F`47?TiedeaE1AL}UyaQvjXg2P)@4>{D%w4AI9AR!PJ57<^-t)%}0RL%`}0WQQT||xyJ`|PQkEFSfidB5+Q&s|C@I( zGO#grLiYqh`t=nZj0}umF;JcZt^YG&ScxLW#bD0h$B@v$$iTwb$pG2c$ITGP5D9K4 zfbv3L2ckU<;_vG~?Wd29(+!CvGwR4;6av`tzi20B{x9i7&;Ke6b|5i$oeNt3Ys0X# z6E*+aGq}U^e^)1J{txa%&Htn0bi*iNje2EBgaEeu{}Gh`nNaKhQqVd)uo$TRXJL?I zux9YEU_fdUurt^(L^2!&t>J;U6Sx>+7^X2C2er-NVmu5p8CJl{ga``;hExkk+ZdS* zYe$3H2_W{62+UDOj)uSx3ju8T-=hn2|Nqf0)cXG%!(9f89^|ofHU=dIb%yC6F@|2~ zxgP8cIt+#kGrExX`g1UtF}O2ifz?$))p0U-GDIjt z4EYQV4BQ|w_;>;jLleVfhK=3GZsBE^%CL;V9V7dFohQqz6?SFrUaClw6ycf0opVy1p{vYlC4}t_S>Vy#$0@(7ua35y= z59>p&BSHCJg`pEg4AlR(VzBLFWME-JjQ=6;|IO_~&HwZJQ1kz2|9?a!y;08&f)K!# z|9@f0|91Vz`JatJfnf=Q8j6?z!*T{~aN8HuhW%~Ez|hdo$RHZczyMlH4-x~lX&GG^ z89@8*Kw{$Ij121Gj0}t185usgGcv4kXB-3}GU|lU5EwZjfGz)@?8mJCIVYgze^rJ_ z44*;y-yF0i7}Wk3V3^9l2G9SV6BtMH|Hw&3qdpy?A%HFa_fNpg{|hD}i!m`6F&HuY zKoMhRFlI1j*agxHE)zfj!oi@(pvb^G8M*A>Wzb=?VhossEGEQ|%W#L`7>bxU!#xHq zMn4q25)9`UFEOr1QK!UU%Xk`G?%bTn$Y3~$k>T?MMh2dn3=I4?85q{8F)(ncL*^Hz zPGV$OJPEZ;LX24IWXN8>(e?`{PDk-@3IS~Sf7N8r`d`qv9>}MV^*@(D`4Hv&FI)Jy z9tQ^_g9-;DgCECe`yCWwqj)p~hDr!DY++*HV1VRx(6JpH3_J|rG9mO1c>OO(%!9!L zA|~??F6PJJ$MDF5fkB7?a&|aK9V-JX!&{ITh@-&30HW9!*cfD{AleSh43P3<>J}yj z!K=?i9SlI~m>4)2I2n$E#Gb*#m>IYkxEa=g#2EhbL)5V_a4~Q(T%5_szy_Xk1L6;{dybogsiRfH7|lNbf?ZIxYrrMsdcN zSs=0LP%%CRUPfNVB9NP*?HFbTK?ZXMbA}rzV!{lT43-QoQ<429%3#G{#qb(MOq{`* z!J6URG-P#>3^oil3~#3+i%B!sGT1UGfZfsyb&CuGHzPOWvAH1k!Qx1cL5op~aSB*$ zHB_AfgA$_>WBUR|2Dbc)e29M)8Qd7%7-Qx!GO!6egT|XOgD#^kV;@Ki9_OkIdW?FE zJ3)Hm!~G!Pr_SKR=)?FEWXFMrq7d^m7_=F+8MUB#A!3>gI*dAu2SH+DFgvsv^cnRT zKZC^JcIYw~Fd8s!0mVm7VlhOo9z!r=Fyp8Bj0|j!L9P&c4H!%rO&P;LZVB^rg{U)R zaA0&`R0FA-`V#6EBL+i8L&gY@7{h;lh&p2iBSs^}Zje}BW(veSQwC#3W5#_TF;ACx zh?qHp38M+)Qk1x~WUyecU{C?s8y^I<*NVZK(VEd7qz*ji3rcIY3}y^w455n|8CYIC z1J6@4GuSblX5eJJ3=(7b&kvfrW@fNwC}cRv@N^*~1G`^pImBKE1|9|;200XUjtp50 z`3(At7#SFIQ=LI`$jl7R4Dt*n3^PGuFF|4Iz`)Gl%D~4U%fPvqk%93!Ow64jgdv8Z z9;6Nw&H^C!c``ULI6=gUopT`edNU|6DllG$sZ#)%=g$z&kj9V=5{t>qV-Ns|1v0oW zxIo0Jm6IWE31(1X>|tV>!^Xhm!NI^3%?_^fzeX}JEVN``0MQ(?7#WIYGBSLQU|?7> zhmk=!h=GA8kb$8el#T-#7&rqV{B53)w)i0p1_rLFjNo>88I+ct2H`VIhtTpfAavv` zMuzD@5PhLR3=GLZ3=H$a85sP7Az~At^y>u>_18dl2Qx6-4rXBZAI!j@9|EE6A{iLA zhC=i(hchsAhcGZ43SnSi3x&u>LTOPih?<5l1_nPQ_r8l_0MFlp%1Y2Y{y#?shS+EZ z@Y;V64I0~gvk1~hurY)5HDEMI9C-}1BN`$PqK8TyG3w6Y8v+VjnHV@gWdOL2WMJTc z)&Jmiy`VCMfdO9sBZ=Xy|B=*z>VK;xi1Wl?^}p#>CI-P`=Nw4A4ypgsL1Hga>wiCx z7+U@RekHPbkorFfMGR8^FWQJ&|1W1;&e*dCSuYnu9%CM3)hc8$K86&=6vhcCZidwV z-%!LL^?%Y*WWA93pK}?q7^MDxgCYj0|G8HntAo`4b|`L;Jioa~Z4FA?sCUXklz&T!SK}%FxQ#%6J{57peYV z%($3Q9I6gdziKcvF*Y%JponQQG&43c-iL}o>Kko_HpVta!S%@Y>N2!5wliJ=#RpRT zzlw1cqX5WWr24;yv4^n)B!*P~PiLIY=mIiNTtgV*79)lZ#tz0Z6ft9lPR35gl^`*s z`oD{@i}4Of45|L_X6$A>j1rfS`rip;FH-$KiE$EREQ&fv{a?R{k%6UJIT=#d+c9u5 zCNSRL%*eoU71k!OXJ}(!XEfc!$iNP+*Fo_HssCd^>fr4JM}}gC76yYYpf)k6eFv(C zA@%>JO~_)9`u_t+3|{|xGK4UsGKhinK6@t00IvVN!Sz2_4Adq7=V@Pta>jB-W{_TR zTLffBAVUU2K7;3GMh3dRo{2pt2HI{V%bJ zk%4tHBZKK??Ck)M{AfF1_|~IC)o0+oKC}-H@&oApkGWewwE%5W+BdE3!HshA@T%1}_vb(AgaJ3<4-(LJYkQW!#I`Xp z2u^zm9Xn(Oj~#k|#NNXC4lLlYLw%4KyzjsY9y=^WF^`SmBEv-n|Gmg|urs7GrZOHv zQO5!96U+mt14S{oUB$_e&X~@)`Y0m#ZC_r7bmnyC=6%Rw zf()_DvCNB6{3`+;W8~a{>=rTb7-K1lm;`u?QD!HyIw|lN<9`$}8SogR+-_uba^NvW zcNDkCGek2-Grv8E>^?|-FtVEs7#f%xm~VsPBh1+mVxA$xV&=unk|2BYQWYTf8Z)#q zw=&m)#6sPlsfl2A@E-BLqA? zDGzcVSTCrb5C$Hfya`fw4c4ECWLU+xnh`7pR~N(3&bE`#G8!}9K(Ql*!IaUJu^*%t)ZYP*W2Q5>GlnxZgTeqlR+`1Y%_zy}dJ@^qxeT8f zI2r3eV%K5z7BM_$_{g9Q5<77h+J7nm_n*LGV7Gw6rHr9~xq$g7$lfZL-zva;C9oJ+ z9ViT{7)qGy*m#bC!u|^Q`~zl&YKADrBu1taoD57H+zd<%T;Mhd=$>NG*ePrb6~u4b z%gFFy4v$q)HYCl#nG3t-T~?REQiv5J0X0-T@X58H-v83M_gY@=qN-z zt@=`+Gn6NsVq{oxijiTHNE{(;2OAAskPKw_+*xjv8>LoxK65C#So1{MZhka-Nca52#M zpBzXmu_zd32Rj2hgC0mMNeNsggUsV#;9#%=i6NaG2$~c02Z=$;P>?z<1}=tpG%;=l zZial27?M9gb1joq85r2$VxaPX5uE=(=8WRe5Eu;s28L(M4DdO8Pk5KZzJ4noSxd<#@gYtR?NDQ9m7#Ki#y%S9gl-F0GiGlL^X*4lVUVnoo2FmNa ztf=k-<#jzYF;F??k0!>)z{gO4CdSXe&oB`r)_)B=mktU80R{nvjc8(m41x@oKw{9j zV30Z?1|f#eATcDp!VJO;;%p2ILP+XF7(^JXL1IYiL>WXG;z42{gA_mn1A`cY7(+9f zm^gzt!*Y<=C01~|8KhEzL4x4~NDRb*>Xl@WWO#)pCdDAdz{3uT-vW4f3>x3j2a7@G z6F^4DFvu_jfy6jp!sAz#L6)HuBnDCdwL^|Uj$sCxm^_0#!)}n6orW+h9e@h;+aNK9 z8E|_+>p(dMogq6BB<6&$19Ud*Hjo&@ zMz|en3~CGyz+wnHKxbETaxyRodC!NZQw;_U24j%eb=Vmf3=E*NYhyrS3`gPSfzG{c z1d07&frmZl{MpqYF>ZFaIvoZbhASX37ty7#FwkYtW%vgY167Mqf9NsjF{pDfFbM4s zfveMJ&}VQ5i6N;oU@%}v2Z`P9Sq?J~bO%QVNDN6GXbtWfkl0OWxOt#8xR*d;Na{=& zOc;KE#AF_E!^|^fFlCVC2FC{rOboQP!2u-p_CO6x47Bbg1|)`L9%!vZ4MgHYGAsd!86eUIXsyICG%;reXNKo!VxV;q zoV*MSLP&aD8C)5((Zt*s+!*}O#M~L&84A(FK=Y}S(ZoC%JQ=p4iFq-2FO0CoNY9km_LI*Llv4BXzkP-kQgZ4f-nOEc#YLQu$Tip z-3KuQF+2c?2_VFR8G;#@_!$_4K=-vk^@cEnFsOjV5Mdw65X#_+CKkpJ#*hvYLkj0` zhH!>XG_eSV2!=IiVv!7y4Cg^&AUi>rfq@~4A&TK6SPbF5XohG8VF3mPAtX1)FvKvJ zg2a&A9Lo^P5DpeYxH*m?j-e7HhNL&1A)a9dnpgru0>e%;u|$SMh8t*NNeoF0zd&Lj z_ku7314A-HGJ}jDDEtuirZA*1*nz~5>`i4zWk^61OJhi5XhaiBXGmvQj3$=Bkil>S zO)Qfkli?YfSQbMT1BVc5y2@tAX3$0x%VEf2@I@2LWyod7M-$6q$YYp@CYH~T&#)Oy ztbn0_;S!oyAwwa&hMj0)bqsY3k3nJ}w}CJN14BJSJp->OxSWLN%Lax9217KlMutX) z5HztSh9-tOG_hueW`-4LVl50U3}?{9S{Ygy-lK`NF|;vAilMrtouQq<8BMH%p@ShE zO{|lllc5Vutc#(GVKbUoH$ykWJv6Z%h8_l1aa4PI8G0EM(8T%}`WT!+Vn}VXeujRA zRFIf4BEL;wn845u60<>wO=OtJun8n~3L!R$VG_eVkXSTAY%;@S1_lWR2BFgku_+8w z7z{yTlNsT0G?ig0Lj*|79ieU-!!(8}kQh?iXF9`lhSg|dGZ7$gq$h93<9I;IYMkT!)k_`ATc|H*cyg43`{Z%3_{NkVrv=JGH8RuE+fR& zF|1<<0f`wP#MU#cXQ%~+}z;J-U2_z(+sB>#1v7> zx-$%C7#u-jNb1fqoMp%Wi6NPHj^P}`G>{mQy7LU@8IFL&kknmZxWMopB!;98G*2d> zglg|4hD!`KV6o@$a_ut1WrlRH7{b3-7_Kl(0*fKkU1hk+up1=CxDMX$zQ%Bk;Q?4| zGh7Tb-^Zg2>QC>7i``(j!C(OvI}R7S$#9b)1uS+3E_RFI7Q-a4*m=0vZHC(n`@v#Y z;9{Wp$d_QT8*s6^40jp$K;xT?cj0398169`gT)@g#qKlQXNUxgJ%fvZ<}&NRVsGGL z4;daZtWaTKU}O9U6&oFo1SPpqJg^~U6jNi2zhfgzHmisjmNgx^va7#Lz$;#nGYAk0f=U|>jMNn`nz z0uck1<9Q4W3?6$y+soP zjl<1}XM)dJQOuKM0JSj> zfYdRhg6q&c1}O$mJK_$CdD0A^e$;dny)q1-_IM~rFFakzGJx7#9VqUTV*u589VqJL z89;5M`zY!Z7-Sh`8Q-FaDKcmILgEz2r6?77#Q*x)EQngyk-zX5z}CJ$?%e)5=Bgt;SIwZ zhEqq7^=dIZWq8Uk6-7*&;Tyv@h7BlUIt)J;elWPAi0LwbwkO7+i0LsfF)}e$p@``- zurRVP{y2yp5vHh~WX_1IAJmF=K`}rZ}d46fqNqRHjs> zXcRG1hDfGJrj;mSW(@gE`Aky#klkX=(8|=xRD&XB!O+gs&g6|EX35aT)W$S>KeApc zh8avVm|h=17PDs9!nB3yFp8KB!$zi!OtVqMY#BB%ZD8U$h^*I+VJp*CrUDdo_6+Np z)-$a|af<^(2dKP1gsj(*;WX1}rX&>iIWbIOn!;p-qRyG&6w@gtaTGBZhLcPunZBX8 z#g*X%(+Q?IC}M652bm5s9Y=ACJ3}W^CzCFUn>`qoGc9LgMRAKKLpM`5(_IuXFNOt7 z3z&YOhlFr8uAi(*Fz!(67hOixkNg)&@b zy38bu5-wp3OPH20UD}HrZ{ZA$OpQzdDC!~@Rxzz&dWI6tkqli-T}%s6?1*AG%XF5h z7R4>m;5e5@5sP8yW9nnNj^f`~hQmyUnF3J6;uv-_?Pe-L5sPQo!?cHKD~g*F7;2en znGWqj_D3QEX#JSVZe+0}hNa9)nLnebOJ-QYyoCA79%OYX411aPGG9OuOJ&%@yoY%c zidY)MZsy(0p(u8wGc03X#{3XPEQ4V^^Lpld6tPT(<;=^O*P@7JF|1@>$t;56w`_(3 z%m4l*BPo{r*{T!!t;+nIe(#PS$6GjC=tKoQFai~UEjw}4?2^Co5$6m^AQ zvEwM}iWt@~uVJo23BO{7`ONc~y-?g&!f=H72y-8b-cp7Y%qy5Dpr|WjIKg~^ISWOs zoZ&e0ab^b;J1Q8wS-e@IQN$`4d|7;1Om`s1TNOhbOB@R`idZ#6EK4lQS`@JwhGdpx z7XF>cdTSX{SyEZa76N*?9 zLk>$0%UKk$W`jm~QT*G=P{C5c!h|B$#!$>s%<=-oymp2HmI9Va z6tND543-R**kmRKc6fWElcA8QkO{O07$MfhP{mTk(v-}^z*rJf!KC28kjK!&aFgXB z%cnGCu|9?)EN582dzwM!34qj1U}$7%WciqmtZov+dY0`h$5N2RrZCK6S;7L|(+t-; zgQ1tDk0mq(*?lt^elq-I;6M?Z#o)){$6|;gHk%=zF`sdJDso)TVOYSpkdYNdY%W6y zV+o@`8nU{1467MeGy0&2&1cxbxPx&bir4~%i;R~T^HI!O$k4~w$EbuNwuqsXv5gV5 zuL=>Siy2NcpJqOZ5-v*_zBB)4_Cyg|&fvh}!cvYBRx23{Sxi~Ld&l5mwU*%)^Bv~T zC~>r&L6Jq3WnCF^IB#U&W)Wop?;V5d-OBKS`6cu0bmVZ}#_*K!DI<8V23*}P22Lg} zCh%Sjuo$Raw~yf`<1a?gT1SN6_A}gNy2}J!n+aA2N(V<6zA$}b0-rep7dye=&g{YL zjN;}q3?|H0%uX4|Zoa_4$;`(*8zl@bGgL6wFsGsT?K(pj^91G`l<>R7Aj7Q4%!Oj! zJ%(iFOy-Ly>Ha>$TZXp`@+e{OfPs~fm655~mVs##BLmZC8wRH5)(lLWtQeRk*fB8e zv}a)Y=)k~K?8v~h+KGWl-j#vrqca0jvDB8JHOI7?>D*8JHN-8JL`78JHO27?>C` z8JHNN8JHNd8JHM?7?>CW7?>FR8JHOS7?>CW8JHMS7?>Ce8JHM~7?>C$8JHN78JHXk z7?{i>7?{3ELby&0G++ZdSMb22bRS1~Ycu3=!}=wM)CsAXUZZ)IT0t!7|a+|0nl(89pP(8$2V z(8R#R(7?dtT*<)1P{F{&P|m=_P{+W;P|v``(9Xcb(8a*S(8<75T*AP#tBipux|D$_ zwwry#*-MBI3_bNG0bLQ3ZKHjlslDyY4J1$rleU6Oi42t zn385NF!l5?FfHn3VCwH@U^+dKfr()P15?8a1}28J3{25$7?_NgGca+iWME=g#lXa{ z8oVxWiwqOPCmALNtt2Lfy@^Z=_6bZ3F$qizn{5~we3F6(BQ)HMJZYDA@ zfX*~nm%zlJAj`zCB#DV3SeA()R+E9@ZxRy&XdSRnG82P#G82O!2NT0D4km`PuNfKY z7@5FhGMRrF8REDY8ARIW`OoAPi!I#$BR6L+&!v{l>`f@-zcj4M;BS4fi#Bj2hi2-H~NL_mt69dR?ApIb7U~<2HF@n`i@PN1#;}+S56m4P|G?Y;5(D`M8Kc_=QUk)UF!Ol9$dJLp1U|O{WDdwq(AW>iZOCSW z#)xiZLBa`SCP*GMh6Nf=3RY!en3>GPuuly_gVy_k&UgUn2Z_UIm^f_DCusZ(G)85g z!o+Yc72kJbEhaO~IKWJRvhclA%`ccq6LCBmQ9|HpeE4K@`%?X5?*+&$P<5sZ3=F#%Pcrg7Vq)NC z&|w7430N>NFzjbM%=i~c9q8oY>x|DBTOTknaO)K_fYdoNFfiO}dHe*>+1;yJ@}4Wy2-l?mjQp9~BPD|puMTnt3ai~MC^Ut?zvbPeP zh8P$b7-V@|c%-}$=7FZo^BKDs=Q|Yks?~Di+UPcCnW~LcTSHcnM1Q;0@R2hRAr#K?qEX2sb zAjM?JWC@z1VH5#}6-W#|mjjJ+kQit#haIF2NencXqX`m=6Xl=6uNDN6GXl-*9 zNDP`bK%Kw|KDAVxm8TR`(boU%*|Y;f}!8Se1k;Ww8-7Gq+#%72yrj5HGi z8^ddG8W&<@X1K_Ik$*Z!9o$|Ph8z4h_{&kmSQ)PKU+3Qr5`){p#&DDWCjTsud2lgy zhV%UA`ISL#ft$y{aF_os|6h86NOI;Gc>j#>eoG{~Br!xR1|{A)pCaJ}LTkN6+)M{+WO&LIS!$0o!m!4S$3 z%25OogPSMG5XlkAk%l5B#SqRB&asRI6u*$XAjBvQo)64m1BpTMv=E~V185CfBuETy zo-9K*LpQ@BkQm&*a^ShOT_7>I`{Wrw>$kkvnHbm@w}A7n5TgPEXpPQAkUGX{sF)%H zXkAt%SPZg8LWofbJZ~rm(#rsIi!yi~@&hY!I#mI$zZ3@Ph1;vj09y070HlsFA8Lmh zLn=cm!xI#B>frgdKCm6IFwkHCt*PNh5z}M4;5+JNU1v{1xs8B|zQSoWZZ*)c@3M6<+$#Nd9jXV7KQW$6Nm!R>Wm zaAa|02?MzWuFjDGv?l#2O8#(Sc+K^i>jy{-uFjd^4c8kkB`#$5xiGxrddI~J5`&i; zt_*Lv-g23P#Nd8&V|dT?p34U$1~<>0;RDwPt|cHl82zB>)PvzU*K@9ZkQiK@C&M$Y zXI$q&VsP`k7+!L{NddGnDX`@cZy1mwzb?HT*UFN@Acgwi6m} zsSGRlSMZC0>K?e>G=^jR$N2Z4xG$X{mp_+39b^aG%^3`Z{Du5SP~4ZvP|07(ZwGQ8 z+`m~2i}@Gx3xd?a(|tBWDSs({707+?^pe9+%U{c%1JVl@%Vk)?zl6U=3ONk&7!LCv z=66JKUp_+?e-{4>6tMz^JpMd>8<4$lw-hpz@t5%jfWm;`9W-qeF|6cY$v+9jZ^aBn z{6+kqQ1q5CRPk5w*MjuI%`0VC#lMO_2V^f?tc)R>Kbv0&#k_KceExj?OptkuZ=qpd z!BEa$&OZyqzm*J2`IqwV0qKRuM-@Xce=)y2IIK9KZmwpi=C9^I4%Q2+k7^i}@h{^) z4^jtrOD#h^e?9+ikQhAP>KGdM8~6hSki)c|p^3kVe-+4Y@HlE}_GF8@=(97S;&m#m9 zgZZP4p^v|hpG};Jflc5Acpsn;V>`oo{`LG_63A_?4u6usRHJNS3-yMWRa+#fv*hxiZicY@pp_eU>7H-9((MvxdhP4+SL@b~aP z0O^IR>t{I1f0Vyl7}*~a7^d@2=idnuW2}Y7`9y{p{4@B^fZPX<-$@Lc`8V?iNFwW< z%&?n(H~%w`Uby?FFwEqi$^QqW7cMrHVGI8j{sxdF6b5j0vl%-1JNdIfZh?pM z9EOej8~NXX!dUG1L&GoA;!fFllUj`KLLx0LEAJ-7$);i z=GOta5AK$w3|slP@^3(~cNxQ8{=NJHpm51J4?ZhEh;cc?6#gmv(ICBWH?LsW#=njK zK1eS-Tvjsd5L1OU!(Q1Z?{1f?;M3BqpH4Jn3=kQMeiNVcV z%P^OJF8^MT7~I}<4DALlRU2Gt)9(Db~OA(cOse?C~u z9V)hsA&ozc|1C%iZpU_p4E_xMS0MMn#da_(Q? zKa*bsrL5b{u!w&V|6>$?>|sdYPvHN9BDR+ykw1}N6l4e7Z~GXM_>=f8Kw@yW>}N>k zPv#E+iNWnXz>vb9!tZvLi2<}$6m&kU5aU6HV9sF9cW02r4lx9925@qts5{IM$Qj7F z0VGxuQvuO?gdvPGjPo=|jNtR-IA=I#4p@uP93n= zd#Jh-3_+YhoEJcD0gX2qfYzp;WbotkxvN29aKD{rc*FgMdj?1huJ;1N zTkf~qKT*UkGJN3vz%2=~1FrWH!$!tjdw75COt$ZomH zz{SJGa~mWE_uDlFZXRx)SdbVz46ZY<^RV+&fyChIZZL50aPX*r?0}2iWZ>oD<*^5e z!ToWIfscoehaDuwSkDBBx7!RnJUl$JLFU23{tg2t4=0a3NDOY?T?SSjR-SbynHU5a z&oe^w-eZX7iRO6?5`)`upCOhfmZuj*>;Xd*PZZB7kQie-)ZT{-F+4Fm${;)7dLM!H z>Vee3?S0G;!4tvb4HAQ^d%_UO6Umc$T`xvi-#Ng(AXV}BIhw=FXWPki%xW{;pQ4*vMZr)FZ`;7M)H-Xf_ z_5NbG%XpX38>|i%F2BKRH@AYs;OhP`JYjsoI0q!g_zarX{({$irhvrYdFvm;L&k@U zbs#agz5l^$MzcZoGU_oy(kTPuZN}S-ejqXDYf$qT8E-P)WbD2NN(Zl@ammDJ$7IK} z7bFIE3p1lVlReWrkQm$!7Dfjq2d16(L3%ZycCa$KF}X3dfW+YLV`Fq>a%FlA5@UD= zE$i4B-I?5(SU_%po5#WE!Q{bY1`>noqF)m|T#?*l##?J^^lc@soFWfBxjBA7JiNW10&Inq+Y5@{s?1k!;U<9pEj0B0n%SlPbqfAGc z>Of+Qx=?jejK`UdGyS*-iZ_0!m^7mfvkr62C1iVL81*5=7?Ni+8Eu$tm_=`b!s;y4&036Gn71&SfW+W>wHdcE zZ)LuTVxA5oXx-vhkQn24XnxaW1g&{gzl!V+J;re6aONtox>Zm+^cm+d&tn$3j_hUw zM$kEgdLS`IC1_eRWNc(^WbOr-2M;SF#(3s<=JjAPSbP{WCNL*3UqlfzVN7IBWac~% z@|zUYJX6M3Os|+MK;g%D59$^(#$x7T<~ESMaQ~V!g3cjaf+A)C7JC5_GlzwrB_rre zL^hD$;BjOH7E=X@Wy922Gqy3eF?-%Z_OA`&RpzVA>L4+A+OTE3!hD4}8zcrd&yMjL z^EGB=kU!vJ_KfeD-ZMpl#NcjrVEn-Jfl2i?6N4aJ%#ra9^BrbqkQm$!C&s(XcbQ*< z>|iW~hJiEVE#_Oy^Fiw1cDOJ;V1B@S07cA|@geg=<~1O_@cP4z@don^<}Q#J+zxlf z>&(}gAED^=V0^^ggFVM4zAaW@gDO%<^~ioZ^rw~_nFV3*x|!? zlldm|L{L70yV;jfpIM*z*ahUg>c_~$%*4DBB*u6bnoj*08JQWGIYD;7^#(BBX1>k* z2P6h}Um)XS=EuyuAiZ$0Ajbbp|C!W5VvNV3<^_Yr96@4me}sU=c7fsu9#)}@Kbd|q zO$Uj=%?o4v!SsV^J}AAw#ljgu>!R&I>fr8+0LOU+NDOXABsk7*g7P%uOK4n1F`6-( zF-L>k0yi(3k%5_kxfCSEI1Q>U1}xSO5`(LY1&if?(m34SI7ZMpoex3w!qvqy{$l#Y zbP`lXz}=F-c#-)c^HY!*TwNmLCFV=aY@m39izP8$X1>fE3{nTzo6HDWi(G*smcn?F z`6M$3s4RxNC6!T#S%_H|BnH=;1{V7c%KMBNP`{-!<}&9pOI<@t zlE-+8`4lrN$bE2s?1Cm=Dn`$`zSnZ22V!D00l+Ab+&lxLP_UWlTujM0^*)%B;$~8wB)elU;~LUeu9Qy9it_uC8rWd46d%8(TdZGGa5y#fzgK3 zhSLco2DhV;(VEkm^Ce0@w29H2)11>ej)?)Z9}~2GLx{1N(T~HALp+8FzD8S!v4t_4 zBb$RU6xnaBj1xH~aohum!R=^cyuxvfgE0hD&m=%aZkfb5nR7Cy0gBjU#z~x$IJp#%>z*l$t(>i#lN6D|U@GHO&Z(T+|l(7hW#wYS)8*t z-9YN#Zl29pz*)dK5k+hcV>M?r=j9kC(9#PA(0Y3z#(9iMTxneKJ|MC8P_YG!r#a7a z?u-M89f681V%)=dfb#=8BLgF7>`TCbL5OiV;|tDLoV(c=!Rz-ycY_Hru4WA53gF_p`{G|SKO2pD{mUjuQagNARB?V#j$#6Lu4JUM@xkM#eXc5V1>)f7t)9 zD}wwB-NPWnc!lvZ>vz`Kpzvc9VupmlHAZH3cJ@y$Obm?w|MNq{ZZLYX`Lb;Sg#ldb z7UMhSPs}esVE{MpF5?@P4=kD>^Wb9l8Kv3e*(`mL!|Ea9F_yC|pQ9}hQ z5`G^U*R!u@zsiRkR$mwwurFj^3NnweoC#vycgC0OFWF5&VG6h77vnAV+w7t7Ah*Em z_{%84BE#|xq!*sn{xeE&NN_0dAjcaM(_>S)>3{*64p^C**<0B2Q1o&zonb%2 zZUb^NXm2?oH_?gsLby-iL_*aO@k=2cLYcR6=M45gu|6`sHG7s(# zDW+VuJhmO2$nH~MYGG?-i$+NsDoiU`H?V5TA?FWurY6>Q)>xFd)Mh%xdXe=hD6HUl zMwiKw)snSH5S0Enpkb=d6vP_D`X3|)8iNP>&5&sU>jKtpA>?o|X3AsDV-*lacAqKJ zYu4AS(?DYIJY&w}z~;cFEP|}pl1Ye7h;2S7O~TWuEmJgW602qaa`-tg-C=#edJ4rK z&P)buCT#mbVZiVKn$O*tcCsE|-4l%*rd~{CtW~TPC~4A<={Cy)7FQIpK&F1yDXa+~ zF}-4_c_B={S^l$J1Eq0BbtXvO3TNVC!Tv3)jX?tEI?vRozON-G1DrZRXoffF?d_0 zglQ$uN}dc?P~8J>`!KcfwDIh52Z_PPrOKGr@T}pn1*wDUEoW-vY2?`m5`)(t6-<3R zeLNpQVvKUoHdiH6KTki;Cl6%zRWa@1*~4=dBnGd`s+o54?B)^lM6MfanD+AQ<*{-D zwHXwk^;Rv@9G*EmkHGGO^=s>xHu7xbkpP(ocS}9fCZ0_^iXgYZ#TuBZd8&C#Q0!=A zI?QvJrvfAfcS{q~QJ$kbAt++aOh^#SAG=r!n#H^6_#6Bj?rG zOy78Z@YI9E;APVSrgGj&-Y+0AczL>%NtaijH!}oT?<%Ht-cH_oC}QiG?0Fq|gF`{; z-b2gSEle`Ja=a%%V(@ZfCsQzQDDTq03=E8nOwh7vA5%JSCht^~Hs*e&AnqV;@gU?h zbbzUXyNdg5ASj)}(!oKdaPDyKMJVbHF|Fs`z%3SxtnM(=P43&=E}*;x@*C(3B*r65 z0z3jd$?l-M1)GCB%JiB0GdC9~{6KSj;BxXfQw3iIUq7fUfrs-crfj|fzB!=sp3x8* zA7`1~^M2u7M&tu5*ITkq#-ZI7W#Phg2fzr@^X#3?OQw~oqPp=`ex=&1Jn9eXgvPSmX z7p5@&F#c*ZJ=8^@7D7 zLhWT@{=)Z#uOFlrUca$1GxIa^9|5U@o5#g0%P-5n5hMmz$H#2QZ^+NBhuoIuX9k@o za6lKij1^$^Ve(;O_GMyVho=oeX3#y3f!@erD#YBv*vV)F5`&kC!py~t#f+sO^Fa23 z{VT$JlJO*CvJ<>1p#>xc@9Ro4i!zEcYJlPwl+VHLlVSeO z_?@vd0AwDlyq9I>V&Y>81Bt=SlVkqF_=oXj1hPNmnWr*NWi<2$>4lByD=@ES+`uRZ z5`*hiWS+%1i_umeIlU+`KVy8xSQm{P_R7pnOifJxoRRAQ73L{S)0u9A#26KzWuhuG z=&XrlDCtU#S%p!B@g=C=2#*hSW=%#-#^MN2I9o!)S%W!%F^G`|BnA%`O=cTLTgLaG zv;mJdE#^4JIK~g4a)?m}y4FCOS&~VT>8vBjzpye#hgpZofN3pA4DMfDW;rG~CeA=) zzv(gG0fr;rO0~6CH1}4T| z3{0`#8JHA*Fff_?WME=sWMu08!@#8Ymw}0gfsyI`Zw987{}`B<{xdK!axpS_u`n_z zvNAH6a56HzXJTYp$;`;a#KFkK#Ky?P#LmdXD8k5eM1YY=QIL^|M~IQ>Juf5EN^V9b zCO$?cCLTs6CSgXV&HRi^jG~N8rDBXsiV}=WCgO}tOp=UDj4F&wjLM8m(Hsm+404Q2 zD-{`;n3Ncqm=qY9nB*Cm7-Sil7^NARqGcGF81)#L7at{Hind^6V&!FET4}<_#AM3I#9+?I#9+qA z#Hi26w90^yDcX>ciP4ymsoaQ>iIJayDcp&XDcX^dDcpgPX{9|Q6O%0?lc*gd6QdO) z(+g`xrf3^RCPr6Ara5kmOwsO)OySOqOz&M7nHZ87nYQFGGDWvCGV$axGQDqOWMXP& zWD;#+WMb%HWD>1sWMXJwWMXJ!WMb%GWMb%KWMb%IWMZgcWMZghWMY`l$iy&-k%?h4 zBNM|SMka=(j7$td3``7Fj7$u|pgpFHOblU+Obk;QnHZ)qGBHeNWMWvt$i%Rik%?ge zBNM|yMkaGZ>iyyBV2+Qy7^-QW=>-XE8E`r!g``rZX}{WiT?ugfKG2hB7k6$1pNA zw=gobE@NbBi)3W#h+<^w3}TlbV+kV@cQGSVWhEn%e*q&CLoFjyTplA+Vm>2NZaE{9O$8%UP9Y=H=^{oZ zhEhhR+&V_4+%iTcMsG%@5)VeEXfH;la8E`i#sEg9GCxM9Xdgx<9)Cur_r8owjDd_y z>w+1XqJtQj7?(3LOr*K44O<#45~~_4AM+Y3{p%? z3^Ghi42n!l49ZMQ3`$H)j3P`-?7~b;e}$Ns7%Z5WR+uv}MOrd3MOra2&39vBQuAP9 zigagUVu)a3S`f~}#2CZGR2I#|#1PNKG&_!oDLR3Pi6NPZsXmE`i6M=NDLa*ki7|_b zX=Wx96GILYQ-2;4Q+O^DQ*jX!)5Jn1(EeV~KHz&A3=E)s#i0GaS7ewNZmThX_X)ec zU}OlEh3q5#B*VloNtTJh-Q(I{hX2E$a6-9xaW)vr!*PBW)yTYFnISs)E7Qy zWZ-(3d% zdy?gPAZ}XP!@vM?1HV55crUaM2NT0h4km_j4km_`983)HtPppC_B4akf%Z6q>;kz3 z#0H6j_#in@n1JxPcZ>{7?-?27-XmyrRwjmXEKCfbHOZe?AbX;NIGGsKIGGr1IGGp( zIGGsoS(zB>S(zC6S(zBN@-Q(Z@G>#%0&a z7K<@4fb2EpWn$>(V`4ZU%EWM=mx;lZpNZkEC=BDhPy&c44lGD3?ULs3^yd17)*tk7@8%R z7}%wl7&?TQ7&ZtoF?5PBF>DiIVt6dV#9$=C#1JjQ#4uT!iQx_x6T?j@CWdlpCWaZ@ zObq+EnHU6km>76PnHZjNGcj24Ffo{mLgEAz4~E>3cq!m!VlXymVECiL1m24d+Ap5H zi~%fmN0o^Iw1;|~0;(F&UUXzV3qCS1w0>X!@3Y>c0#S=B4>J>H9!L#n-#TbN_)lfX zesvHVw)Y#fA05OGQ)XgNQ(|I>Q(|H`tHi_r+Gh^J^Yxe*&Yojrn0tYdL8+XP0krQB zw7*)&j)}qK7i7=Ax1M%PMF)@I|K>h;lbBFDB2kC=h zkQgXjVDSX93nT~Hg9zI54r0GHgzSR{`4JR;pzs7?kUkKeX~F~!FHl&3{0EZ*g%cZ9OPfnSpzUTR$YRmFPIwG z*#kcOVgjG505V_N5E8ziz7t68Ndt(xKyt{~ z*%V?1EbKsL!Pu~L3rgdly_@DSObq&=ObqN{5cjSLV`9(>XJSYSf#4%h8no{gw6D`V zo{0f8_W_#g0GR=D2WZdcLwP0!(0De84~h$gPmnVlKz4)n<9}m>+Xbc zC4kIF7I!md0H+C%*ilP_n{bJP`~orqWIxPoTxxNNU-e{S`0a@ZlPA!y2bl>nA7(C3 z920{?923Juen^;tmG zVCIubqq`fF4q#@$&WZq;e>IYc;Wv_7u0%uJ1&S+B{K3wV0IB8jK)Ca>B19cX92*;? zUo3!$;e!bxp8i112I+BwrdtquHxDDjB_4#?i^7>0c84R(FO6kl0PS_3;={xM8h-+f zH-YMwURNfDYsVmE$#qvqnE)$4LFEr9J+eU0GXdpM&{-#-^Z=6s(e-W+{qY`544|`5 zKzee0A$b)<|BPc|0MVlH5cll=%fJB3L!kTx%4?u-MHUC;Epo-MnTJgbn;qEHfy6e% zFfmvMLCU$~K}-zR!AuOGGXX$n1%Sc>FNuK6OcU2&mi-#l`Y6>KyCx6 zQ4L^(moXsuMb3!y0OD_VLFHG(LEI=A&BV|h#l!$QqX6VCc?U*@R3}D;Dknw;(B6KK zo3p%_7(nM0z}O&lv#l5z9$GOn{I_CcFtBE1aJFV-sJ4cbzaaI`O(FM2|{A^htuObq^h5ceJE)px^@G?~;S)nHa&uU=YE?06zO6mWknwBSc;{kO?%pGKxn~ z2&{h0#K7@)_KarAozSOc%F-&fr$ZhpN9*I7&CaE_s=KD>R1>+_lO9hsAC16$sC2E zj*S6yFGMkl7(4iU<9-w|4hGPD4=Yf_I2k~9I~+j~;{u<*d>2KGn*nrZ!&T54bhtlw z7(n-Gd_fW81)q`4gQAy@VF$ww26YrMeg@Dv&Gsl_0t}#gFuFf6Fff9`Pr!kJpFxbF zim8U_ABvbPLmX2Ali?R+bqWmGOgT)iP{dRi{FwZiBEKT5(_%Qqc!u!|ikKn8I>rr* zkG~i2|=1`{R|ri?$x>XI2AF+OIjLJ>=0P+?MG0=4DYLGb}j_o)nCj6RI%ACUE? zfzQ7MwLKB)(iwyqMH&Bq)!hTnjqo#MFwA0_#RTftBGhFvs4%KBwthr5FNrW^qVCTl?kCM6*TCJ$i-rq7(^}`6!pmq+r8jzU02LnTu2Lpqx2Ll7B9$)6czyJ~#OJHEwW6i(-k_X9&d}d(q zh01}{fYgH2f!H8*AbAiUq<*NG2TETcx8w3NC|!Z%L4F1K8Eb&x6L`F& zo|y@JE}siC69Y&ss4TZ(WMTlR0hRS2y?ft7!u#EONE>7XRd=IaMGJwxr%VhSpo5$g zKo@8-Ff3!(#BkvsBV3Gwfq@~DVIHLZhpGdK!Rvo$n*byRs{i-=V`N~1tAo`42S9bW z6(hL*2hC7{?!mf&BE}3pzvTl+>@Q^Aj)Q>(d|$$1kQiJqD+B1REztN4yA>n2&BDRJ z#sInp%NA6=f$SAvVBlcj0^iB7gn@~H(Tb6QNdY9r!|;>gF9S1*Izfi>3>O%#zGGlu zgzFV$c*F3P;T8iE13O3ztXGTybZ6rIe~b)*aQBHbfbKJl_>U|m!2r5D?hlGONrq;I z7KSAtb#Q-3G0b6@%fPe_6dJ4yOjc|ROjhg+Oy~F+m{&|V_^9329ke4a=RFqz~d$$@h5H!41QJ&4DnWw{xC=k#(%*8=>rsk z-1DE2VfTN~sc&eBVw5{#LIAm45ArlTUxPT%J0?N-S`(D7;bM?{J@X%E#1OJhhJk^T z!Ii=KzIJW0g1uYaWR1I*=0x3%gq3~XEzR{4sHhz_-^1iC}O+} zpnHJTQ1tSF?}FL}QU|w#p8<3a@I{bVad8gBeFES!@tjcf3NnE1=q(3{F(`uDPXY`= z;5)5qL3-hC5eA?0_WUm+13T!(HgMRBFtjnWF(gGH%4h)wF$T~*m_{gK5)7cba-aQz ztP2FKvld{GVtB#uhJi7ffq^kc0K7g_fI$x2W?}!0tWJqxEyETDrW{5F@LC~beg-Bh zF$Sjh0t`$ZLJW{KH@pl?415es#exh>IU)>9dfcEE2m{kj4hE)HE(WIGoZxaFv>pJo zE&#M10C~Q0$6rQpdW4+`4w|n6jj4j>z+mI=lm0^HXF+nH^bC@Bi-NR$Ks0C`2tq}>FnYe0Ot-;4~Nzei@hp#GAHfdh2dt^xxC=>9)P1~-NSFA!p&v(n-iQW(JZ z+(FfW#N-&{P|5_57`#kCQU@v%oPIJgu))P3Z3ml|ObmjikhVS>0}})2Jh@mDF=hrA z1{a2M6fqXC*i}$|fa_&t0NuC#9z~3e0d(IwCyHKn@Og{bzZe6HO;5mPGkeC7k0~-S`gBybzgDQ$TA%7b2 z!&ioVATj8eCn#V4XJBKzj3fqXCvY>)VFdRbKxtorfdM22&;L-pATdz>*L=pvzy@tQ z@Iu=Jx1NLA36M4csD=RDxBD3^W(+>7m6w4Te4Z)K3q}Umd;%{63&UfE#|%m+Vyq0$ z7@jehfy6-30(J`<_^v={ka=+Tv4h9gwLxNV_i=#FQMCq%!S!;2=L!5kVsO1&450g- z6G39ou;OKa%n6i$#6Wc<*j^s+`KT=*F}ONj2GG6BQ$S*Hd-)hZ_bD#{iNWpQ2cIvy z1tbR7E5HD{|M)ma4DLQb@OiM-pfH7-C&U1{!_yli23IG{FqL5{Lo`SX?miK48IuhX zgWDkrJ{PzeMNABQw`4a+3~rt{1LzL-*(hQX;JKXDAThWdlHl>?-6&#G;Cn7lgT&x& zmImKrdK)AL*DC`a^LdRTCJR1O_%}!l9#(STc@}O^xWLVmX8_$nF87*=K`=)E+*aac zP+<7L@PWY!BnGW7co`HKJ~4b^2m*=0)hRK2Vfeyu{uO8)IzLpeG6N$cBjan37+jqS z12gEr1r)ui;Cp{mKI~70F^ro~#55RYGR|h43KE0cp~;ZV zn8WCTBBsTlG%7gV3Y?a*crVH9CZKvAc|V9jXFxS$L%*3ZkJ%K%yvpZ|i9fgK*s zdJJSb$%}lxp$YNOx>P+fPpf!lFx}TRJn<11b zoXKYyvbr1w(3u!_Kw_Z$A>hEk%aF^!$;`Fc&FD`2CW$ewVz@0HOOqc zmy8UTUotYxe8tFM{fdzR#0SkM%zFu0rv<7bKy?SGP64$ooDvuq1Uw*Z4$YMe3=S(9 z7$R0e){KGVKx(jwgUkepSFDE24Rx+&U|6ymVirC*T;|~t$7dEkIgoiE_k;X)?=>R> zC|!YY{|iR&y-1+60xC9#0-p04b^gDFv5ztQJwgmLuK$?vE#n6ybvz6V3{FfwOt(Q| z(EcWJ%h9azEbaB&6(hDXeAnWf$^ zF>r(OjsgRNJOcxR35zYuMvz{pmogJ+CFJR5o2cXX7pyf1QLVW%fjHx=*zetB=!c< zj?rddW$;(k$0f>4#dCO3>*xRjFF80KC2;;Z+pnCHUxZc!e z5M}6M>|zx7fGj4)(9PJ*r~?v%)?eBT;tV~EJ&ZR&df{Rc3>}OejGZWAk_;~yUotL6 z5tCwg#rTSGKZ=+%!)wOZj5#P`G7QfdpEI(9#28qi?vrHzonNO25_<#be`+(xF@Vpi z1Bt=iBF_Li)9%$fWPd0yfX>Z33lht($OnzvXfr5+?**;}iNWnq0@nr8L1J+8lo>>r zMVL2(#NhU-Fo-gXGADq<7-8Y3${@%r$gGDVrp8djT*SQlEna-a^XJcG{0~&9Gg_RD28H*W9 z14td*Z@LUNEH*43LF(Y<=`onIn6vPpsMBY#V6kA)L=iJ!uw=1haYGR^WUykfVo3&x z!NbLf!J5UIWfzJa#tfz`rY!m>VkQhBEFmnOC}O4zp)8>+^Fd=>S~JYmV+ z1#3Hi#GDzvuzX>W*o`da!NAPQ%(~++vY0P}D61&zY>*fz4}#6}V^CyOWYs&#KRAi6R!lV9jdH+Vc%D&Zo@~3LYmd|IP?sW2May#_)*Y5yKP|v2ajh zg>fZ{SOfzPBM+nD4@L$-cvwX;XftXv9t4TO!zzlwjnSR43?v4R^Js8e^C60PF$^+{ zGK`?H3D`KKHbX3fEsHJ74p4aoFYDqMiWrL+4}rwsWl20kIb%7amCCT0aWms(6m^*lXBf{gGJ({A>;Q*z4&)3|kQh8J3mBF% zE@g~-&&a?AiVp=)Toy81V7|bd4ibaAxrhOD&fT9+j0}jhQOxj``7LwXDP;GRGJI$L z&YXlIR>2^|BE(V%5(AkBc1sO|Hj5665=ad0zIp})76q1{Aosz=ni*JFSXe;&9uQ&L z!Vtw0#q#VMBY3SCXntFpp`D?NrH{qnG_qSd8D_A|V2MEy>t)!>vX|xg2hcb!D|l{P zn_(hD2}>;t|5;?cQyG@BEMrkd5t|Oa%lI59-r!+1gW)3MMaG*TF_4?V;Wv}v8sjxa zXHZO8U?a~ME-n@^&M&1Vo|5@Om85`)LlVg_v{Z6>}8$a!!Xg94KR zQw2yJ$PRFru3}(eVqtoQ;+EA6222J_pFv_E^T6&~!(hr}%2WVyAKV{n89@8Wb+#e9 zZ#_d8Qy9}(6tPX4RX4nT_@5K*FYaoAs-M61%D$`V^`5^bf#SSol&Kz9HZ&+93CV{04U4CD33o^EnjvU1ktx7H9r<6**k4GAJ@DGG9RvyTJfDtCQtAvbsAA zq0C{-U#=nN>H7?zv*46LV({>L%%I1t$7}_13&_7)8pW{zfdM-h9<06ItWFN*t~ zF@Vm;EC!he(hClk7Yq%|4a^cKZg~y9i(Cv8E+GGc)xBrf%e;>{0we}^%O{3)%{|15=3#1Jid!2By8!#|^Fl1n2 zF=Ak9ux4OtFkxUiZN|XFV$Q&%V!^<~V9CJ5V8y`1V9LN$Wy8SKXUo8J+Ma>Q*nxp5 z$&P`k(u;xVy*C3>oDTz2MgRkoCg{#!e+DKGKX5;D>KjIeJ#QEpp1olN@A45klc4ookoZUB|PpmGJ2cR~3BlmGUYQK0_gzVD0- zu0I$VZvS9p==s6O@Z&op1E`M!>X(E1@SwgI$ed^IA#Tk5zzAN`0~5Qsoq^%yb_Q_R zpv%Gh0opeUx_=ndp91Nd2sLX9l35@zWV6uaU}k~(TA*;uJ%>puNSQ{v=4xMX1|;e?#~aB!=uZbUB#YK=Xp2aS%{H6l7Kv z)U13Yvp{0VW}(Z$%mR&tRM{{xfcmc>vm&5rWI9rqfy9u_LYIS?1sYS?Y{SR^>i2@o z3WMH-%a3FhNDSF5bUBz=ps|^-_lyjn{xZm{T~I%2eMf{BNDSF5bUBz=3`By-|Cty# zRzmu(pz;56j8_?Vd_eT!LF50W%r(qeznK^~K9Z(hLj?sx0a(XTBrc0vbEm&vJr=0ZAQbDbrz=qb%RPA=H7! z6E3jaWYPN0#J~+2pHg68P-S3XxWaOcMFB~jCTM(u%aim}PErF}%$8_2-G z5XY9pb`HrcAq)%*8EiRh+y5cV1KoG}mhlVY6C`^<_nk&FB{6;Yi?Ab>fq@~5sgS7& zNer~iql&4KNd!qOnSp`fInz6)Wq%NMq%klsd}I2{WC0TU2uXjL3=9lx%)HF2t}(*X zWF7+pgC}DJquP0dSTO?wgCL^=qu^CW_#Lek3=9lSjJqM@K#Z#3IV6x6d>jZGejqW> zIMDU8j0|jWG02>>*dIjy8gx5-6>}ByuiwaG%nX&xmCScQV$d^yDi~N8%9+cVcY(y9 zeWMBnR)$XIPUd+aF#!kgxI+a48$$b#>n|n-LAYLS24)s!mTMp}xLzIx zRu)#4T_|F_;68-~NDS^iKF|VSmZLwB&EsbfVG&^w1F7?XjFnU{2r!7Th_U8$#9hAD9fYo$bOSz zILLC4B@#tUn&B$TRhCsKVloWZS+2A6p@_+X#{_s##N-$*v0P$l{)TLaJi~LA=PXxH z#1t4_vb<#3fg+~J@Pg$9iy4ZT5_pUu_bak_$_$mPm8>gK#8eonS*ux(qKK(7)UejD zGNG8K#!$yv$Jzx_2aj`ghAP%7*2f?*czkFu)UwvH`h&#a>NFWDSSwf`{6}_+7Q~Z;tbb6%j2OCEyIC_(#Eco*Sld{)enw7{CJa+q zr?P$oi7CL+xGBSQ*6FOgD08hmtQ%OJQN(N**0Zi>RRxK`?XYE7%et2J?I$J% zL3qBjW7yBSpY%_p##?2OvBIeA%$;Qbhk0R#6Ak8Mt#tagJo9D_P#U{n}^do5O^dR`$;|c~h1_?F^ zwyhvBxH@-+M7Bh>Ss*dEy&en+Yzb^NAh85ke0Va%v&FM{fyChIycn|Cve|S|#Jm}@ z*s|F8L1J(_d>As>GTDkiX%a5x3%++H97W6zd_Rj7NDOX=Klol47LXWRZvew5#!rkd z{~_mvK!%Tu9~sY}hy^jcXME2%4Mi-NA%Q7@sTw2(w0d(g6Zjcxg3;4{p3Wh`m(A@#8AThY!BnEC~ZsshI7~Fly44^aPeL-RjC!uvf z3Ihi-2lE@0`aBhUkI=txMBluEA(KIpNs7txG9v>!yxz|O-`$fI!N|Y}5)%N`zxfPS zOx8@Lk;r; z`8~4~$R8lTfz>T#xX*N-Nu>bUyp;?_%*M=SDCVtV_{;Q{>0Le}10%}}Xqc{N2xbmp zW-3IEkIf9~%o@x|caZ(Dh2b63JEkolJ3!$A_U}#x4`xs1izs^cGT1WPF+W4GcOL^U zGcWT(6m>@!5||U2L1zLX(#uhXUe;b#(D^^GG2jY@V+{4I^{k-teGp>D8D_K2W{m@d z0X(cuFl=Yp&cafT90n&DQdv`39ZE(GSZZ0)n;97x;b~W#aXQO%mNt+WNH5qtX~qDS zK$agM|H9oO!^qCU&T<1qog!l)OA(7qE3$u;7&owNU)*jw4;hPL?i~dQci-Is`47^cX!DJs6)|V?^qI=re-mjSqsv;B7qvMn6VBMuY3f z>I@mv7}FU!QN)ZGL384LATgFGX#dEVv5c{t@jWQ~7=569Iuk|#Mghj8^T_6zGD=MY-em|>;{P$!R)nVoX@y`F&!kP0P7FhF-~Hf z#P}E_25-aJGwx*E#drr4NANgzWt_}5g$;C$7CWdM2d5!7##XjAwr-R(>CX6{^*?Jx z2Xef5Gup7(vZ;gO4P+izuMeXvn=IQ(kUCHr0;j7$#vry}wvtZd^c>1)$Y#VA4AKiy z2i6O#9|qf*pk>vL2ib- zC5~}1>tfaky~u7(Vtl~*kaYnlO~UO>W<1DxkTn8DT?XSf*6*xgeaL!q7_YKkV^s## zjf|qu^peZCiFFfeCrBO0Jg|R@7+=~Foa5FHO z+c7XH*fKDg*f201b!K2X&C9@K?!>^v;K;z#?ZCiv+MR)E13v?kxf=tMjw=I`g$o0d zr5^*+A`b>8a~}pK4NnFp1}_FCJ6{H-aBl`Cw-N@X^TiBI=0yxlVG#^Wtw9V-=3xv> zI>8J~3?U3mcHs<6;h_vnN8%ZnHbpWpna46PX+$wFF+?*k*~Kw1g~u>3i6k*FZAxTd zicVl)ib`c*I+nt~6rIe#bTfm2X=OSCQ*;^w)BJ1(rqfvrOwpMPOf&Nsm{#U8Fh%4r zFgX=6Fr6-7V2a3RVER+ez?56Yz+_&^z_hoDf$38v1Cx0L15;Zq1Jmpp1}5`r1}5bO z1}43F2Bz(G3`~B_3{3x<7?|EPGB7c;F)-D(GBBNPVPNX$WMF#T0Xip^fywG315@$^ z2BwJ13``7{7?>EYFfh4aXJFcOje*JhCIeH(4F)FTTMSG)?=mnY-(g^ixX-|3b&r9` z_yKrM1$36#u7{8_0%2^>`FAij=&ZcZyNuv75kcdlpmXtH{AoX#z-Q{g_@MDlWc8qN zO=R_;@k@}|F!i8uN|1U`dll410=4%*^*^Yd1l1iNy&!koegttJs7(xNhk@FZpmqnS zE(XWM_C1C5V^)X7C+s`H6Lr~{3kg64cGKy7+gMuzE82s2^!Z%jw12aTtL%#BIMG6a%&3@3>H)xz3G~Nvg3s5|R%#0{U*aI4u2Z`mEp}GeY_aO1-6$rJU zv3`(Pdj+amP?`aW^H(9%Dtu!CpDA(})HX$P7sxFj^*+@I^`P->kQje8s@Whh<{E@L z(AYRgETjfgT~RGU9cXME6fP{FwkH<*VPVnRgwO+;8v&VpuL;#`SXj(&MyLhNw}8}s zXhu~F3yZW?gj&#C3dk+LL2WxUw@keVDT_dBTYaxX*sHEHGO%8OutDM{&qLU17Z@2z zE_1l_XW50AGcYisnV)tIGG7dGYhMS#O`tgokl4NsRQH3#x;hc+K=U0S zvEWWrb)dNn&>RP7Ju^stc`rf_Xx;=Qme-4_2PBr;hfoKaa{-CX@559F^9!te5D#Z$ zP!DHhSme&g06I%?4fH%kV$^}!0w8;cQA@14fGd>kTm0d{z#zoHZ~)XV1a(_L^Chb$ zGcvH{7UV$0K$KVIq|NA}?u9ua8mEkR@ zJV6p;V_;)&+0Muygk%S3U;jZ4RIvvP4;Xy6gVxAH=7O0SAmz@6J)m`&F!wQm_rq;u zU}g|xGy#wQGBYqUa58W*JO+zF)=)DuurP2la5J1j5o2ZGV&GyZMKO;JybsTRFR~r% z45^H%jE7LvaWJGXrZCP!QOC)U&X~@)`Y6QB9N=)_VpzbufO+ZxWb=3#(wWnloA)7$ z2{Obo$1*QQ@vjJjIfFR^=MH3bVholHmJFpRViF8i3|0&>JCW5%F<3KLGyF#plVPx7 zuwjtfjjRq-YTGinqqs#LyngQOL1cA`44}F1-6&$p;5F#$jxaK?IbUOh_*Vry2i<%K zS+5!c=)Ui*ATfA)(O{@!u48@x(hC>UVwl4`hgkunj?shxVxBfbHFGs{Ac~j{czpT= zNDQ=~1RTzK450hNr4EC_o)en>48UvoZiC}v6VyCIhQ-W_nI%E?nr{h)q-SFW&|TNH zATb68s5%pd3Ct6ieZl6z#7r4LcXro<#6V|2f$cS80NtOv2_%*UGtYtnbg%GJkQm%= zRt%tfx37WX7oP5I7%Uhp7`##JwFQsc7l72k^*S(^F_mPC5W{-L6O6$pknIRzkY_MqkVkP}7y}=JEW=Hh zIsuUTA{kaOu4aUbDS*Uc7~0u3vdP2LfyELSq#4y2Yf=1`#GuJ&%y@3#+0D5OpBXqA>rljs7@jkHWYC6*34p?&gu#iy2_Xg! zzcPjb<^txUFnhs%s{o%v02c%Mql%$~xsHwJ7;^YkGej{aF)}UXWME?CW?(wW1#UBe z*8d@&aRK7D?PX;6u!oW1@?J)U&k+m^rw=ePCU#3n## zp`#G>*Fbg$Gceo^W?=Xq%)p=@0-^0985p*PLi8|)Gca_AFfbenVPIejg~&%jX;CkT znuah220tYCg7ywE%5W+BdE3!HshA@T%1}_vbeg-QBdjJXAwn5Sfhz~k<6vQ7Y zaSe*!Q9K#~$RRM9k(q%5n%6;XeR%ty;W~K!1SE!N|0BfU?SGJA;ChmQ0p9*c(hF+; zTP*>#(_nfb?fMmr%nX9>BcW}0CU6`67K#`%xD9_0MT`a9hJU{jQ9dy0EN5KK*s}&A25Ad&F@WxktXhRE#s_ZePe5_AAh>P*4Mj{C z+%`{IimX=@+&1T2hAbuyZkxYB5t9VB&AC?~tCME1Ww2$iLvf1?LlR>W>f{(e z^N^cR#1t4R87mo=Zh)wR_*ao(F5_Irs&x=Ch<}wCS{Pdx*Pw{0GPE+bGG2%3g{V_! zSj@PXQ5>ocVx9&=6Jryj2a1>`Lo;JD<9(tdQ0%p00L{$Up!PqgefB|7xSILZ`H;^HNA)mo>Gt>@nn>HBSriF`v+q9t!)r{=SOtx$cOlBMm zOqo$e7WTi+I9tmE?-4l zo0W4TL_MwAtgyBxsI0`+_5`&tBsMWJux@5#Fx?DkAHdp#Fd8He+nWJW4{9UAXiyP4 zibq3WAVR>7iJ8Ls{|3CBzzQ4xL#zK~reN0p!AzL-e=CX@r2fxA5rfqK7iS`y2dV#E zP{bhhf6GFMI!K+t&Hy^+B5w{v3{pREF^DsYGset97UN^!W#nZnLUA*s{=b1D2C4sD zrXuTw)c>zh#31$mxoODiAoc&->BwS``dl~A%g>>1EU&L9YoBC!I06AF#<)*n8AqAh_M?g262ligE6Bq<31EIa|RPe6UL<| zaS5saRZ#4;0-tYSkD?Az|A#I{uIud>PBU;aUPckKXDDPi$?$X`=$r;vyBAXb%b}=q zWXNL3XV6~+Y7>LhfyT%n_5Vze7`W{K5_1KQuW>Gh*4N;=*_|PTA%>wIrVd>HdxGnK zuoyfKdNU|6DllG$sRQfvXNYG=W5@=Hfz*NP|3Gm44;KTg3uaJZ>|tWM%*McUjDvwG z8ngcAn8nCYG!s()FPVd=|NBAd7)SljH5F1{mqBUSX%IfcbO>3I7mHc{7*a#bN=5RBnB!gKx?HL zm>BdK^cl>;85vj@t}}w>89<}w>I_;8*(hQx45kbg3@5`7eT0If_R^ zU^E06p!52mwg)6MK>5Fa0%rbSFcHyCV_;xnFk&!b_yH0#hs@W5^1m^IF~cs9UT_`; zna9DP$e_r;3tBq_76avLUIraTE5-oO`f0FUkeCodF2fy$V<0iOI&p@33|frfwbyVl z35Iiwml(loui;`!47QA?8F#8MFx;HT$Y3~$k>T?MMh2dn3=I4?A#+e%>X3PvsgoEP z7EeMgFNhH%W!)CY*Q0ne1cpioK(+92HUH;KOjZ7kNyOo57zU9G?G?_hy0eKl;8buZYq7 zKOEB3s2_$-2te{bYX9G(i;;m1oUcLt0JZxW8IE>=XplP4cpWRlIflCo7Cp#$osB_> zL7ibbiWobC4uc`Xj4tFh0SAK_gF8bOiaJgPPlhOlY!r1|3^5G345v`kaWmvIG%#?Z zi19EqF-&II*p2KKUWTa*%NX22V(_*IAHxcUoecLtV(>W&eumu)XBhaqk^Lsbz{aS^ zSOO9QhXKgHVhr~gJ}}5zGcYj1#iSTi7%doYIe}J4!@@<5;WGmZxDN!{XY0_;$ndp` zk%6h35xjOCGqg1Z5Eu;sYK8zf z|1Vo60$MKxG8dHpMM3!=ZT~;`Y$(v(2k`y>Dh%Lrpx|Pl{=W^w(oW>Mo}0m*!5!ZI zM?TL1l&{gxav1IZgJNJ5kA?vKLI9lq`>&yl|Cx7S_W!}>%E9wGr2h{-Lk_8~H)rr; zNaz5y!&%|ue}N2<@cfT_?h7dYqo4UQ+W)6typP&68UmmY0O$XN6)5$;TpMVu59F>& zQ12GhI~HtbMC$vpFzjRqWAtf9uIpJDG#PXlp0pv0u`w7km@zCvQOC}p$6&}%i6X|q zV8LL`5Z(r|31ly*@4(IA#W07V4Ups zX~F71d6S(%jv)tJuY<<9K=}gwyf=txqvU7^jE2Bq4gqZWpMNjtOh8b*330g=gBF8V z3nPONd`y6WL773BAp#@@E)yW?G#NA*zVBgR5CWeQ2oY0ZP+>@J!7NYO)fm9*1R&!M zObiwbmJB^8>X;c+8C224SQxY!v>CwXn#0=!tPB?zt}uYlHHV9FGUzjyGJwx8hr17S z#>hbii&o_Ji2%b9hO^*u40L|XkrqaVYb}fn*v`%bm2=q6&D4g;_l zC?t6pOc_!c_BJDrC-5?4FciS^E4K4+L2YdGvv5bp6+z)Sibq2LGXyBf|C&w2<$v%! zDd2n!$^X|FZZSaaNddJnKw^;m555xxtPbQ(Q2sx`u(}B~|DR^K4A1}A&dvtqfAn*+ zN5>UG;W>&&LjW@bh{^wk42F>UpW!7Vq`l6-0BY;&H{!_u;C493F3@csF$|KR^Wfq6 znvH>jQH*i5D+6>q5u}cb;Wq;d<94_@P?^BZV9F54aHJ73?#Kk5cjRM;VMt+^0TN?i zWq^nYF{Cq8Fl+{inKMAeL>a0XIvDanVsLd54BZSf8A9Mb-xgK-=?+!=|o`;zjWEo@`_!^MM>scA(8FU%iP{i07 zf*3Lw4xxx~GFUPMF!-Q|aWm*Mm^0{r)((N~0OfyvhHQpraNax;56Npfb&L#q>JV&D z9s`LX)3C91(0vUc|BT|%5Eu;s+#vwY|GlXB|8Om4{;#V8ou>`j>krDCEDV+m?hLH; z$oZd*A%~%u;ZhxPd!3y@fx(>N4e0J0&@dUe4(DVjWth%jhoYC8A($bH!2!h%UItHw zKn7{hxDJz6&4P6wkhBQpfR`5&CWApQr{ z|LbZn^S>%e9%f}wV=!a@-=_-J3n~*h8RQsL7{GU@!o~O*Oc=ZvuGfIh#E0z(6kzaW z2!rS0=cWt{X2yuK*^%$g0*$$2yEkie%pDR}qvU7^P#OZ@{BHrO*C8f>^8dbS%={0& zcNwGvT!(|!|EVz8fbL0#=XKEfUn>ShP+n(%<#p8kzsUFJf$C@UyYoiJ=|KTJibq3$ zejxzP|DCAq|I<~N`5$~|JIGl``5$~gJ6sHu|7{qus*&q@)b;&i@^V{4c{G!{Abhng4S@VjyQh&;JCq6MU**{eO@IGs6LvZ5ErbMm!X_#Bh%wb6-7*(VIsp{ z1{P3x0?+?44F4Gl!E5+I`5(3>2>HHnP##CWD;(6<0EvV0`S~(P-UrS35i14?icvfo z0z*9nu;u^frI`6&sEm<;?a%}8oxq^;e?j@5r5rW?Ph^_PtOXi8^e0Wy^L+{$YSgaD;U=>29`qdKO_%xF{m<3WSEB{#>+67L7K4_MNEJ}mT@V( zUI)$bC6yxbG-xdjDF1@QN=hMZc5G~rlSlDr2#kgR_7FhN|Dbw(dogHTA1q&k@-8ET zSP6&*iGk+&SQum(G#Ks{gTy{FGJwYf*%%xc;u$(o)NwFaG1xH#qKI)ZXfaqYWP#TI zft&=^%g2z!Pz0Y7{AR?!0NRHO%HJS1sQ(VyV+-ShXxLmnNFHR&C>{-g(GVa#1hD1* zoz*#1M$^cN_M=l$X%LJG_=^-+zV>ARtP6%Mj|7nGo`TtKL za{h;`|G9`F23h~J5Je2M{wIr}rx3ZXFTjw?PzKM}=<9!;6e8OApuD{qWS%P{!}KUd z2GE*b&=?(P+Ppz%LzhP7tMeSJQLREAP`IdQ?1 zfgv#qGNun=&opCTm~Ra^BOJsBl^vkI{%%tS1`r?Qk5N1t0;3^7dI*5?e+^>&A87pl zPbOymSII)o>nsdD3?U3JP{i06@)`OVR-uS-FoZFrGnAl+aWP~vh7x$bMj!uMn~CTnfX4r{LFSE)|BajkIqFlo zh5$JKgKPw^>w&cY*|6mQ)(q7A58CVN4H7ek&GmuC|2!BBGm!H-H-k4rFg&l%%|PUB zQ2m^gF*^PS3i?qz8Uh0q0@(7uR61t;KQkRO|GT1yf%1PmLw!0Z|Nmv=0+%P;3`q=G z@ch3q9X0>Qq@(8l(eb~5N(H0#j?@sqmj8DpW6uBArGfG_Y`+c@g9@V>BV;^tt`h^pN+$+}txk~pJw2Qu z=MTc}4}s~+vV`0lQfUba*HJtg0@MisZ25n74ssp_Hkr) zMnhmEhXA(xpBs;v|EHjcLC*g@iz3Ft5X=zFV4HxfmyIEWA%x)xiWmn&C_^YiPa?89 zE`~6MFb0z(00A61_lGDPd-$z~ufb&1N-wg3PX#SrqnvsDGE(Xef zj0_iIk?+l70-x)vi=vK&VLQWihWRLBYz#XXb})FvAe+a*u#;gY!zUCmE{0tUyBOx6 z*ul+U$&kvB8wau<)}G*HNN31lxC|D9jT7)Qo5#6aEx zuUQsmsAXtjV2cNt2h%Ic(8kcmV1lAff?*@WR)*E!_6ba#48vXq21X$Zx*-O_*NTPEpmGP)jscxhOo+x;K7sU(wuL~EI*O?g0^s~#h&um& zCla}C2IUt<2IeS62FA~KMIn2AA@lzhATf|5!1)U@|DTE?2Aco(Vptr7T(9Fl|JNr9 zF-HK(2NfXmM(6)Qp*)I5LxAcb0M7pfsQLe11m^r-X(Xr|fYrm0_5U0wVxajyD+Y&1 z0ji&FB^j#g9kic@BhodaPuz%!>_*#4EZZT8b|SH2#kinPzV8R`F~+3 zX8-?0D5xBOwf{%+|4@kAQ8$i;0HF{7=l=}U{=W{E{2xqY{=fL1kd34AqaiRF0)r(4 z!1+HNHUDo9!L0x9g`n5}o}=ym!4iq1?idXLGD85I|3P}eeSOIIpA(k+pE;WUL7_B? zM?+v(g#fnve>NDi{{Iq8T>U@V{vTG!W7IRlJOr@i{|GGkzaEtT?UBd-u($t5^ZzhU zFr(fZRv`e+{~4fs4e=Ie{qOxC%=v!~Q2qxg0k8D~jsG`d?f;MFe^4Ne;?WQo8Xk25kBNRUjh+8@x>b%J+;6T%i09 zKkJK`L7TyhK@KDa3PW(40JJ7p16(G6?&brn2?DM81JNKQqj)p~Mnhom0dW40M4kV8 zS)Kj#lx*PForxxtz`%t7IR8hW=Kn`NnE9XE7daoYGRQInFjV;==Os>t zAch2n6CiaA>`ah-g8U3g45bVbexQ6P$ixMnV-#R0XQ*LV15yXi*OCnN3=_clkec}o zv=$kZ-#~p5KPEOWLx#gB>U0@+85J1?Tp1ZyycnT* zU60{4!%v1D6fu2<)r`BqXMKY5I*SV;ucy0U&+9*2F~vc7eYrCu19D!EFlAt%_p&;=;%<-Gz~1r3)j&aTi90+b)a@??8TnmIoj^xb5+)({N>ESn4{O z&p}CY6w^Kgu;qU(8%72;chvkp)ef{K5Of|E$W2V(v;Kl?85!6>X%$>{Ff({Fcr#o= zQO5>8>u*0u9Y`Bk9Xo?BgD*oDNDQu*gTaTvhan!U7u3f9DduDdWC&!aMR5xkgBybz z!%L8u3(S4o44w?04DKK?xSM$xTp3&$wt>Xp>UbGE7(5uhfb0bs4|WS5gCBz*gC>f- z{0#mK{tWUUb#V6yFnBR|F?2hD%0f^WfXYA-hIWP}4DpW0VxY6bt}(DXg8CTOp?4ri zGE8Tj&6w(dtWK68jd3dDG8Dav41X9>7(d%1t5antWT<6$hhnb=!y|@Y3@j*OIt(`$ z9x%A0h#4@I_a!(lr{hIU&*q!8RQsr8G2E~gc+tVENAFP z(JRidieWdy5fpXO4Eq=^GHgT`eCA!49<{gDR)gAlZw0I6eTU}XS{f!72>)Pd^Pw`l6v z7}yw2s-o%z*VpQZJ_a)bq>Py+%FH16K9a$~0AwB$11AF~!wD2IW(IBsZie+JVk`_? z3|tIzbr5A1GXpC_977yKK8hF{LjXenLxBY&1IznJ@H{3n13N=IV=tqIDWbk+X5e5b zW-MjA0TO#33GQPsGjKALGgdPGHHYX0jWIAYa4}Rf)-noOB8zb|)H60RCV=!ZK2vN|~iYX)nEpD1Dq3^oil z3=-PN>XaC48EhFuP~4)-Fq3&E^DYBqb*cxgIJ8G0%qKAoD@yO(fw;0}7GBPk4fZFOHJK`Do8P+h| zGy&yfNc)(XA(i0{0|VnulyslQAjmwO*#RXVr88V&>c z^ky;~V!Xh36~!&t4Dt*n46{s;?agK2V~}OIjN-QfhG~rZ7_-e8AmJhavZIK>iNT2h zE(XqnB@FAB*DNRMF8ZtG6ok07Y4YP0!XZaVH5L4cBUY92Bs~X3{1ux;P%JY zNCt+5mJAFa`m_!sgM<_#1Fm%ipmheHBN!NF=tJ7PJb?@h&7iy$$iToE$iM*NZ}VgT z-#v6lgMqqp*w_u;ZO(z16wFWJ`zfc zdO_4QgfTGqA-NaS-r_Z7WY}fFz~F7h$dG6TX_JA(PA5Rx*dR8tJhGk*=8!QKWHDs6 zk`*I^xfLS=XgmhA1_NXksJ)iKz{mh=m%WQ(0I%r))p4Nk{^!WR5F5<^Uc&*RLG3t@ zJ^>Gidu+^5>5ga!A4Jo$PNt__I%3QW9H8MQaQa88|B=Mt^*@pry#7ZLgV+B^V(|JO zNeoo~9};0?V1tW+@-HKUqZl)TAR_}x{a=hC2C4s}P{bhhf3Xy@d64@5l_atlr2cnT zVPs%oWPsQIhZ#;X6sSVPAoV&2!+M5|3{OzRI2krGY-Ol|>V>G|V%W~GlR-`mSuZ!k zZic-K5h!9j4Eq@lGWaP$+ybc!c)@j$g)Br2QWpp?v@o|Yt4Sk^i7-?#S20V7B8!QG z>-strF-dS;{|ZG+8eG>;6hqc43$E)+#F541!FBy)31l%va9#fjB}|nVDwr#nC&(eI zQ(>6SJe@fXMNEyMpShnoP!XaI;$L-!&CHvb)#M>!5dUg2%wnF!9DyRH4Q|^sL-j(` z>4NL^!%#aQ=IJraV4lJJ1w~9B+!pCZG0%`;4)Yx5y(nVF40D<1GS{KRhY7fD-lKr* zJ~M_z%!`;6pl*TKYtFEic`fq?sCf`E3x;{j^O%*OdLd$#4D*@iGlxROApWpsSiro1 zxdTPamSG|DLS}E2c(VuB_3xnSAm%wRtYBWj{1he6ID_kY3uQ(IMsPj?)l04nos0_^ zH=&4mGRQKDOPsf>BO5^@?3WZ261mg%oD zBLh3wUQk^c1g@_qp``m@hNX;~8CR$x+Zzh5uZ>W|!ol_RNi}43F$`B2gc#?8?(YKG z0j{s(!1Xm;3|w9%F!VC_GB<(l0|cuBg+UUyzJ`l|>+2MTiOi|&Ot$O{OlF)6Odgo^ z^+GB9^);xj&XYyd)sdilileUHAPT8lWyB!#VJN*!9Kt^;0il(piL0x(DniuLs;&mr zpR&r3`WZyOQijyqp!yNS2i4KYY*@VtsylGis~~+$>WmEB>WmB{xqhW*T~3Z&;PF3D z-T{w?L&pD#kjfd*sh^iZ23O}l>c)JazOnS zSpJ_TjA)-j>VL>yztQ|pPNYg z5Fk4Qu;qVeEcw3(l>fo=1faF=pz*)x(fm(#sE=wK4S~TC0@(8ZHUZ4~|EU0a{qHoI z{|84Dj=Ewr1jr5nZ25mX2P1(1cLuog`Wv=46zniy!E>>@NV&_2AgXkwtf zeh1OSKx+(dabV6n8gL?uF)`RN*fIPkLslotpw6hzn1v!H&tSsn%IJooSBXKL*^>D^iaJ#WQD#-&-;G#E0O z*qA4w_(Pk)g(;os35q&BhD_#K<~1mG7&2Hhdozcj_}7FXlsTQb5=EUk!&K%u%-Sen zV8u|+Jej#0MXwFRWtN*PrEbXUMI0G)SS?uNKy?T>U4hz=&I~VE7+GVSk=3~|NHZ!i z@}k(`$-u(O#TsRctj?PuktLgj%?Vk|k3p7IlhqEk77V=KF^GYeRf=^lid#Y$&N1>Z zb)eW0!NAXC#uROjY+f{j2V)SU5{lpA77ladSDt6qXq*^HIcV7(y9a7cE*E@i%{%sW8h*DVR1wW=UxV1)>78T zDE^qjP{BH%)x{mzZ!;LqvfgJcvOpG_!|;gpGiyJJ-bDkb(hRx+GpzRC>RFB+%DzyQKqI2jqLI3Z{3i11jxr zZl2`Ez~C>y$Y5;Fz#!)UaVyAO`OXkFNFB^f5L?EHfdNE=^uo*ubzoq~ae(+2BnJ~0 zjfU)P1o1&;PO(Rr33D6BPMCi|deOx}Yr#Na0-{0kAhSR;x;lK~AiH<)Gcp|FXJoj@ zj|iXZoQw>QI2jo}aWXRe<%EcX%-+qz$Z!c7S0Mfx3kL9>0|t8r2GE%dXOZF*Sq^j# z12#FB+hA(Z`JnTeu<3(|hw^|5I7q!Y6i96K|7mvQIv3RLXJq)m4x(Z6e{2kL46ESn z|8I+Mc3@RLq41VCv1Vh2+qi!4xfzc2E=YP=pJ*4%&o}m1Xw*IFAl>d>=|3+T_ z2g?7WAvqcXqaiT#LI7L-pUuX|zy>c9K=nQ&!)`VZ4XgiI8MGM!7=D4oK+PR+Ukh|6 z2xLtlsQm{j6V9_SGCXI4wADcTp%*%%E*=em;T;0l^1m=M=Jz8pn*p-#eH#;^+(f=VVD#RA;hi7p?K^Dwf8Kuv1~#EiBkj0=2I?D&HPJkhYp^oABe+DGILg2i46-AvWIBzzg zh)II;W+f9N0}H%NkYZ?H=wi5qVy`koFT*@=-h|~RIn4e-w{~z-R~z)(`;ae~{yl#{Vw=V_;x|i$U`L=YI?gjPUWl(fkhz zo>4p+0z*9n!1>=4bdDdyC!qU(DnR)kE(Xc}GeP+u+$I3E|3Ud*7vAO`t^XlmH%g9% zz)%YTZ28|1OaA|8iCq74F~~7^V&wmSmJAG|eSo2s0!H0Cl0yJn{%?KHz`%x9|F3$F zJcb8a|6>Nu|Df@;z3&+qKzG}M#@ImP03$g(NBuq;0z)YT!1+JFA|GX|091G z7}(%qkp6$F2Xg%n%KvHb{13|aRnWXY#e;!i*=YVBxe032=R+z4u;u>`zcKT_AgD|L z*Z&~zF)=7JC^KaI0nMa?#tuPaf@}f=Eh z0@(8Zjh~p~e+(#jot;5}L6boYMT~<%2YM$6Xifl>?_pyCpn4tD?r;4tXoF$YVWS~1 zB0~V2{}Vucc!>8w>wgMB`5!I@8ULI3lYxN|EC#CoSsCOQ{K0K_P+kY+ZBShgs^cN1 zjFO`vFd70wAq24H|HD5R7}&sh9pnQ@{(lM*1CQ&0#F!Xl8DtssL1hBGPr%Bcz%UzJ zCJ6jQ?bCyFjN;J{7!85J7Xsk?&xBh4hk^1sTK~W92Ll5mSRJVT=U|XyfUN%o)&IEq z`h(B6qb?c^fzc2^4gqZW|M7Rs{y#S;|AX5Ep!^S-|A*ZF0m}c_`ufOrjIu{VU^D~< zX9!@+|0C9L1v{ zFgQa1TmBdP#=yXamj7EoV&J|$$RA7$atv||#vn1cI%e>gz~gVI^Z$wrE5K#Krf-;Y z{UDP@@n{H)hQPpu0Ji+UHiyo$^`H_0nj`F=$z04;4*>X3j@QN z&xmpXv?g$Hhs>z!MnhouhXA(xf9(@y|Nq}7{6D&1fB2@2QJ)R}5WtrIFMPo4|Nr@bJ^zpH=O6xQWYmYlHw3Wd ze`_rHKOIN@AKlYGeAC9L&xU^pV9Wno-(mLuZBfquW@XT2h+<#{iGjxsKy!VdI{~y9 zuD(NVC-5=EGE89*eb0b&haW$~bcXrhIYH2UeJ|fJFnoB!zyLZo9L9g*2Dv{BSqyZa z7>KX=e)z}9s1HX&fL8!OZ`^-XO2*XJ$}g&|#I@7*HyId2Z!$2r-bBbH?Pp+cyT!nex}Sl;^A#?uJQp7Fo>HnFzA^w zFr2q#V0diH!0^eIfnkyD$W3>nJ|7$*fGz)vg4+LR`9H=OxnIwMa{srMF#|&m=x%_) z;iXYmjE2By2oMAA1OpfnWG^vbV2}I{(tcbv;9BC9KHSD1J3`j z`hSJ_X#GEQVtv%5qagqZ0c`nyHkSM^fl~j2+W(NdzCih3+=PJv)cyyJ0YFS0B}YSG zGz5l12w=NE`|H>u|45lWKHh{ayQ1JPv8%IN66kyB$|6gLZ z|2a*O+y9&latzM!{0|!cgUxS)<^e(Z-^!GM!F_Z-U^Ib^hQOc>0c`ny6PEmM?uMNI zQOEy4b^oCDqpP}cvlF~~7kf%89T{=dVRfnka<1H%Gi28Pw3vIM7XqY|SbFd71b zDFm?P|0XQ?f0Y$-{SV6jx#0W{n*Rfh|Ct#>+5n(_z+m#RzZ6UUx3WYY{{z+khT!}UtN%SfYX~WE z$f(}Y5Eu;sx`zNb|HJR~hOGb70OfzU7-aqLMU?yxn*SR;|A+38HEQ8#2v9i$u;u^T zPZ=24(DMHal>NV``+vY|1*z<=QR7BKU^E119|G9&e;=0of6gAc{ST`D5qJ22=Kn{} z|Dk|x1nl~B(^bP@R`Tz41%=SOK33B}p zI{zmgKK?g){tvxlZPdQe5TH&7V9WpESn|J&9diB$o&U24oc}@df1vh1`uRV4cBA*( zP$z~)O&JXV+JykN{J#`S{%=D${{xi&N6-JFU960nJQ@P@2?22a2kqGh@AZew|8auy zKU@ql|5xCMT>qnv|Bs&gL7%u9wPiE}s2u{>^8en)nCt(nF~EOT?HUb%(GZ|41hD1*E-d-~ zGDiJh2hRVn`M=TnpR#xu)jb*l0}%q)^1m&X{J+W?dHf%=|8MmCpMi+4Q9DONfSMtI zE&qRhh}r&Uw?NMSp!Wah{(ox5!>C!KAutdjfGz*8!jk`&qOAV~)&Gd|f3})1FdQ7c z^K&4gZ`97w5TGaou;u?mEct&C%K2ZY^?!pY14EA~14G2{z`)9&$Y9FQfKn!KGFULI2bT$; zH36VA!C?1+g4PIw+6Yr@M%xI~iM3HvMnix)A%HFaZ@!Ot{>K5({vV|LFUNp5|3}D% zfdSP12aN$z$5o@IjE2By2+$)0!1*8E*N3$KQ$hJ3E(U4;GojS=p!0urf$Mru-44qC zudNsuGt!DxSg9#J=H$7l#p90J(#|H*rp<9|)I$nAg7`5%b$e?V<}*!e%8bpW9J zKgD+R{2z)VXViev5TJ1gV9WpFSn7Xnl=DA9`QHRy|6|MllFkeaYR)uv{HXDxAut*O z6omjd|AW@yMo65;PpS~{GT*<{s-0nu>Jp_ zcEEsnX4K-*5Eu;sl0pDm{`bU^|9^w_|KX_rk@G)EmX9hP4S~@R7|;;FmjD0U!EFC0 zpzQwx)&Gd|e~|P4X#GE+(K%}QXb6xL0@(8ZdMx>$%^i9EAGH4uasCe||L?IT$=XrH zqaiRF0)rp~u;u?$Ecw6G6!-Z*qx=5{K}3!^VKfBD2mx^Zhp+X8tp82kfVuu}!baph z0n7|a3`z{~n~=p=8I&268Ja9}^f%G~vF@W`I zG5lv>WjqTK0~rVw(`Ddi6lOdMHZO?*qRx;(j!~J>6eI>$XTl)HD9u;|(#sGIHP3>9 zgOP`^8DuX!Tr3&P7+o26Y-eC#$?6G)xW$S=kHL^(1xPR4JR1fzMjb|1kR1$sPO%QtR1_p++8yFbQ zZ(v}!xPgH|VLJoEKQysmsGdU_3=D_2Ffd4MV_=Zk#=s!Aje$X78v}#VHUnQGiG3j+lCMW z$-&fu*dTQ`w=*!j+|Ix-(~N-uT@Gf(lx+xewnNPe-VU)7BnL9f&63(iWnsSr=sYEDT2$1 z!`B!X7{Pi$<%BB38iqp*O;?e{G#C;X`Wfo3gUSS0Ue{rm$gqmxABs9XhNBFp8Lps+ z88TdDxXHi*)(dhU$PQD6Ck!tczJTn7=V1$mI}8sQltE%}x7aY8W4Oey2^22yd~M6{ zhk=K&7)6~u!yATA3=$}II5B)>_{nhiDstF6Gw?IYGwxJjVDP*M$&Z4UAT)aZkH5yi z0K%EqG0TAm7a)2-<$&oG;>v-WP~>cfuc@_A)ldxVK$0ebQv}?90b?H zpnQj1hl-v+ty7OT-0B#)erkkx_Ykn_<<&MU*w@5(034BXK6KRW{hgCc__N}B*ACe0wt zaQGCW-ehNhlnJ3G%nX7?3=9qi3=HfHOyKr^K8hGKIA3?6h_Qh4^>P$3R&c&Pf+EHS z&eso7#Ml`?t#b<$F%EEEe|(C8fgSD-P6kZ|O@=9_5qXoHft$gA!Gpm7BnDRJz`)MH z%Miwp!4QKYCde>@VFd&KS!BJU4A~4*8I)1P#2LI9f*F{)IT@JLm>HN(voJ7iV`X64 z#>T+34HOz2;QTFlhJnHP3K83u;=XBZgHonc`3dxnAGXHaEOXV`KAxjd0%s9>mL&;XS&;C>9K&n?3+mthk_ ztSh2kXJC+LaAPQCxQwD#nPD%(AqFNCy=n|w8Fn!&0*S%<1X>J@46_&tL2ibRZD=zb zWw-<`v(Vf1myV;h+tJ(kzG&@!(D+;UN!0fIyAzNy@BozNKZz&{k=yeidE{~tSsh4j zv|I$G>ro5}0dW2Y=MfN(fkB2rhQaU%a(^9?|JR|2F)>&%STVR9MedukF!(X}G4!FR zV`VU8Fl3m7BF4sG#9+iQ4MmKd!I;6AVHS!Q2ZITN3Bx=TF-`_k22+MzATe-01i6`u z!GXbnK>@`r+zh@9z6|G4#P}If8B!TCQN)B8q8OqW7Ja7}{0~a2 zta}+4gy8vsfkB5shk+kW%z(jw;pHAwby^Hs4Byejv>CJ+r1oN#C+%vGIvg_Y$i%Re zVHtxhiaJ(?Aci1@Z75<~;QX4sAK5&9hGK?d28(^jVj>Jl3`q<(4kC+5FwA6_$#CK@ z0|O)2Z=g1TB!dlOIO7hu7$_CUF)U*+XPgZe1F4f|h+>Qb=go8G3=CO&85lO~WnkF6 zmx1BQUIqrEeGCky`w(Ia_apLQ>V5`>jQtD@nfoxs_zpqzOg+rNFyk--1IX;rJPL|~ zQB1E80Ox-O76wQ@gtY&^>;kpdVPcT_KWaB7qJ|zE(g7ZI2 z43hsXcY*RhNDPwyjTpQbCV|CZWda+6KSLZtHdqX%j+-Ho;V(GkhBL|tP-y9aXLD5z{0EfXN| zFiMVw06jtgoc}=Ow%85md?SfFe8L2G?f8Sd>s7Gq{mXV7G@K~cxTpv|DmP=}(9l|i4ukYOEI z3^v!##$e1~%D{u7mz}|!!IELJC8*qiwI{e3Y#748{fXL01_o?+p(O(Ys60A4S|$y( zq&Vu{0SEzX`TuY{X8wN|56Xw2J^`fvufm|upqqd!#?D~GPz}zTpf-V60s{kRPcVq> zl)%6s;4uK68?|yY1V%#uZwO$^|J~~`^ZzCkF(&Z({}(7?pgw^dgTe;nGJ%UhkzqNw zOjtOLfgxlSWb99KB?CjnY6b>d4+e(L)eHI|NB>Bw*Q}j#Nc&3B>&g0LT)EO z#{Xnc#318;TUQ~M6QJ?G4e&O>==k4IN-d*q9d022&j0Xy4XOX9uE5OydqHAwb&&io zv~qO(Z@8t0QU8pr5CG?Y24&L_($Djso!`Cez9^o+Ri_s7mi6H>a|B^Dv!|VUi{67-Y%BY`*UkG5!{~MQK*8g{wVXyzQmkqx#8THX<2#k~v0O$W{sP(@B zmi+Gn%KupE|Iz$EQc}vOKZj!ofb;(f)cn6?DFXu=Tnw`R=h9N-`X4l}*8%STgVyJp{n{AFclXyM%#(4K4=B|4~apXMMoV>tJHgWUyw?28peNi7_+C zGN?1ify5Y?q349KFxW9Tfy)WlSsemp!#zYt{Wlr{Lnj2V<$q@^`M+=p0|U!6SYBsh zP-8G*SO5}(-%AO~|0)bAAThW)76x+$>(Tr_bdtlUOGj7;V9WoVi!tl}Rf|#czY2pM z!%Y-1Q2tk9-~i=+c$vV$V8~!Pn*T>wni}=)&i^kaNO2AmaoeG0;BYfN2a2Y;ZA1KjE`2GlL)lVL2?%ww3xP>5nL zJ3}2q9m8vo7%12kK;w@5L}WthwG8%0c-VKKvE2K5=pZkAzK!mxxP7)4B$VJX8>2AxG9 zw?f)fpb-^A1~Z0J^N_{l8I&0`7<3jgFtD888VtG@jfFvhL5o43p&o2rA`|G078V9Y zhGh)P7*>PDvY}#149gjoGh7FYl|sdo8CEc?U|^WTz`$~m3EW3xVNhZ4VDMwu01~r- zxkZ)1g29eq7K&Tc7#tYf81zBvJ}^S{sxu@pWHQ8n+y^c5Sr{}J0vN&>euDgF05eaM zA(A11fq5n|`V9M+jxl9|#QriefX<|4VK8O5#q^x%EJ*AcOw5kq8DNNgnsk^tH--~T7nm~VF)%Q`dL{}n&y(R2(+wugxeN>};jpmsVsK!rW}G>j zfq}&i<~MJKm5hfNC!_e+hoOaWF{3F;`1vwiW8h)DKZk*V-45gyP(1rF6fhJpNG$-l z1tbP?UjRc9Lk&YT$j#vN3=#`s*ub=hDPcb7o?VbSkltX14u%c}&Be%m3ujPdQe}#o zi)>yDLn6~uChhsiV(|>pO!7?K;4lE02eKoXVGh$erk|iNfR6LCFk~>OGet2mfyEdO zK*A-PL4-+?sT;-31q??R*_qVLezKNH555Wei&xwlds85i4id#;}cnbru5yTUJjnB;8jqY-iZcU;q+h zNP^l?$*_ZA2SYSi3}#*x!%l{s3~gYs9H_c#hFuK17&d~%VCrfZ4lo>GxPu~A%W#n4 zAj1Msy8i=9_jL@q%%;ptGuRlIqFEW35?L6SjM>5MoPF~d7+@H5&jINEF3>qAr#cuI zcIh%OH0Lld9PdQ1TXPr~^3eDdNNQz}!G_&{?S&Y5Km-aa5F~8=_N8SxF#|%fYgA- zfD4ikav(8evqAD8F_1m)q8J#EF{u9WTL3X<%47%)s((QC?peUV@NoeH!{ND*^Q8Lc zBKDbs#6Ww`L1HjA=)U9w3nA)ZaxlNZ)WFoEo4;WSMVbr@6Ois=`=1EPq(c|C*fBG3K*#!685kIH7>XG3(Zo6!x=`wWkUCKP zf43b`|Fc5x1V0I?!>2*&byfx@a2>u8MT{BTCYXsL#sY2=JVFs;1(%I~P{i063Kf;|ACDvpSK*_`&T7M-(w(aJ}x0qE`%D|G!5O zlLWUXKBMTBW|+?~pCJv!eKO#>eiDk9EV#bjhax5iuCKeNGBB_}>rGY$c?Kf}bA}ic zF$D${22F;)lMwweRt7}|Z3Y8|S19Hwf$Ms)Ze;%|GpuA-$>4$_roym_VHJb!WMuPH z89W*M8JJP*P-C!UuxEJR3o4%>bssB(I)fvFJHrDMy&4S33|S1nry!fB$q>j8!SJ;Y zS+5pD6hk6I5sF*1!FByy6fqr!4GbF?PN0bCGHhhn$Z&KD0|O&C?K&{9G8i!IWje}q zv=33wu`-x3++=#eWHbp`ojt>MCT-^TQxWwhD}xKeE2ghZvryEzGaP3+&vXVw%!}b7 z({(0;iOBx&W^iJxWn6<220jd{8ILgjoq(*)m!XYuDdR~LF+YYI41A2crZOE(R?WzeO-8 zGpRGBqWB}0A(?49Q_=)vI}#XVnG~5m_alp?FwA3G%QPKDT_%GjQw)L( zMG>n2*Y#B>VwK>!emRO*6}YayiXv9cu$y5w0|UrjXxpEap@v}(!yX206tP-x`y>oS ztd8L@!(oQU{mAiK&!ER_#>^DN#=ta}m4PXNg@Gx7oq=gC2e@63-p{}Q!#Oq#44^s@ zR2PHJMW9vN0J)w;ZW|zrBeOy7fwe1;>u*q9IS_3FP~9|jBBV_KYa4*-CXjm^rZ6y+ zPGMkZ>w~lng8C3`1CSV~{s)P{*r2w7#sr9Zm>jHa08;}~k8VD!Z2;Qma<_MQwGC42 znHe}hZ5RaxP^+JzfT@HDJSK=F2CC~#>lqk8?Lbhwn;BZySK2c(2qr@6dS(VDhC-%7 zrimzG%nU_LMNBJE#8?=LnTnZ0QOsj!&|uJDXhad?VgTJI+SSa!z>)~5ZBTEs>8JXhO0Cn_f{R!U|?8Rk6?rPRnr?G{VmuWH>i9OH(_A7Z^^*GZqC3k z5M?Q-3=_#`U{K13^xHsg$}fPhn+hO(9my632G<%08`-@ewa9#sSse`w3~D_p=;k!B+o&D#NV*CYT9AxnWi9yE%m>F0Y4zV0! z5h_PE4^sa>tVOh^nHe}39x*>-{#k)sUvn}rvd6I7*CDIpVtCE`o_R+NvKTkRYWB_S zc9n=eC^G{O!&dfP?DH!TeJExIeuh2lhuH0_k;OzAuCPC5=dDBZTRMR*7+90=p5~c#E9pk`|!cfd` z1;xM440Bn3vpxga3s>jHAjMY7mV=_si=morBimdQJA4>qS!-AeP{P2UVLRIawuj}& zb$tNCVV1)z+9+WV!f>4J2OAHH-y#_5*;le3Mo|~VaF#`!wH4$(aGw_Bj~Iq;%uFnK zD0<@_*2BXEq%M&mnK7MlIf}XzhC-H&EHWtRDwRQp!-RvWkePugpM`;`0aDj5 zs%2n+VdT0VRKKfMqSo&VEg^jp(0C@O&Z0-(2xJeT`kc3h`1%}FzZyD1+5;f7S*jQq zY^xykJ2E@E0=0g>P=~1B7nd_IfXWY09Su^4T)$)EgVcfS1=$CpVSMy@ezaZ(WzJDN z8UnNr0pz+KWE-fj--uM#gK9z0%>IHhM4iUKfY|@LX>>g=DA-2vXb23+5WtrIHrnJ6Fz7RxGHonD)~n25&ScBpJj7J#xQQU0F@SO1< zqYR2(TZUSO$qbb!dL0=O7|Ix$QPjCI%wphTe2AjXogs=bk8v}K9bOCqjDd`fDBa(q{zq z`9OU=(AX_V9v2^34w((phdhoAayNRv7};EqJcy5M&S?Jv0tGv>7I|EMwu#LH4gcLk~+2%TE+_Mhque?y%&b*kR6~&CdXG0%yilA(*?K8ks63<(TH4BSvL&{!V>gBQa(hCaq?AoJk<@MD@?makAl7mVom=IBkJ)Kji%1m+8p)0o40v zWO$WCHsVA#kI!MHsWS)C+9I%5@MZx*tc977ai zD&uDqF-3+Xh71Ph4CJy%g&~WffZ-sDIyHvH4C@(ops3SgXlCeRh(=MT$1sawA%g^p zm=VJSh8YYsDDE?3C}L=2@XA6CD|3cg##Tm9-UN*~!!WE4x5&Ufk4)=&95lWS$~&O6 zPfYy{%8MZN$o2ndoeRldgN+2|e+JOneu&E?7$g|deLyRGU}7u`*$jOQ=TOAh8B`fH z7#D%Wj^7mptqEda;ARkIRAj6KiNVd|Wthk?pP>~+On~7P13TkR6fqG7E=EB{eH1YX z22%!ihWjXDG7Me}84Lm-vH$=1A@(XVEMj=hFvSNnv&e7&v`2=4L5V?|(UuXE2Bm$N z8APKI^Bf@lc~52rP`ePu2CZv{sfE#t+!+~=*~n_FeV7@deVF0$jINB}wec|ZYup(b zE?GhB^!8?En9MMnp(_gFg`qMPHUD=oP5|eBh#SgA>ES zWYD}mFL=Kh1A{z6F+(+YJaHiUw4-Tw@TK2T7f}`hko*tX(+V;P)c>zY0Ofy}7$pBs zPXOh0(E5Bt{%=f#)oCCxNdCVHQU`CFL-M~pN|^x3|A8oaA^BebMI9vne@q)O^l6! zje*G%(T4~1B0!}FhcjYdKQjXp11AF~gB6MxXk|Y)gCdF;3j-Ge7elBYs4N1tJ3#JZ zW$p5Z=kKX~6)3 z!6^1xGW=)w&!7NO2iI%EV8&p^a3BiNA7f^)W!T1WmSJinsQ!V>dowfGF_bfGVVDqw z*mK9sV9&tAz{B8;qRxS#h@q50EgCWY#LVEtAkSdJFa;#Wz{m*NOV7;U!obHM%a9a> ztj>)gjUkW02qXs1Z=kh}9t^$=p$z39G0>Q=04NQ4F*q?eA;iFW!H3}q!xIKZkR2d( z;B}w@3=s^;45ctJ0g!n?3@!{V2r;m_5QY~F%uGz}puKDC3``7c;CA-cNJzgEMA!K- zFno?+U~md#U{DTXVBiU4U~mBCu|Ng}&Oiu%n34la0Z6%5C(=rpmY-ok&lGZqEPoVgfTGqA-NaS?*{d^L1iL{{^!WR5E~6y6A7Zv znKLlBMM37WV6=@Hgb$)Yd-_1)u<-`actA%qL>@$gqH`3FhQMF~$aOu)U7+@VWjv&u z29>p-RzIi?Z*c~(Ky3n0Tc4FdjzI%lK7i6VXs=J4BLl++6Oaj`cr*k?LtvvPVnYC1{(l^YS^t~Z;?MtI%}48hV#9n?-Dn65mJq;}|7T#y z|4+nlTyzgDC{C<$pyi`M=Q$cmAJbHCq10c`od8%zFYvBaJK%gsjX|Dh7!qwX9H0pt+Cmj4~F`iy?qbP>!54ExfppFxjllyM>*hhM|U`3?v3_$AIkM0NVgd{t>>TXRL2iMEfgr%@Nf}l*vGJs;UOqK;9?RCpV>aMv1&3fuqgyV{UOQlmF+8AJV*?#PKx0# z+h4ZHC}PqK|JnYtokbCoVPIruWIuvphb+S>p9gQ)KwU_JvIWq!;dAC5B&Yzt}uc#FQESu>E1%2oi&vrvkcwo4phy z7UUWLi6d2pe{BEQ+EKzvonacoGzMLD1_m}JSbEW5*vGVw=@)1pjerCAj7Dw-ZH5x2 z3Z`n%*qQ=NOpn2a$(d<0XuU05%z&YmsfFn~$PRd18Z+cDO{Gi8{;G>56k zje&uY@ekAv3x*J;bfzOlko!(SXG3x`STS@mO=kM03Qo_A5Pw)RNHRz=NP*n!7@z?W zvt!6(%453j0J`G_a;_vdg9F1Vrfp0-Aa$t;U5zxvjJ$o0^Htc24g03CMIK0xV(pkOB{m-lRs04DM$#`0Z&8u z3`g0IvX|;1mz~87FW6tOF9)lGl@X;32iXs@tAfF zb_b9;&>5uQvZ#K&NdGeZy>jT_4YDkv*oa@1@%$kViOsX*;3f*K=y*l zPO!Sk3^8mmY=5EY8Dida1}`=*wkA+Mg6o~l;LqmIW(-PKpfVe*cRoW2TPa%z$PT!h z7cw}oIj{wR#>U`&Tgp(wR?Bt+qz-QHat2N|PBvFizKjoYh1k2AL6%L9Ez1?;-}ej< zvGok1Y+`J;L3tIfcOwHI8z0*vdt`N68PwR+*-}x$U^@dN8zb8;&^q0eI3b96yBYM@ z^x0;kgu#A>t*l#F_kqOR{evLt4l~SSo6pt;%B!IK2KMg}hUsk6*`z`F2$WvHVka1` zv0i7@K?$of4Ch$Svr2->E4aD~3=`QVv8_h&+ZBdRwl22qAa(HYyUNhS*2D(xTfoEq z7Q-HmkHM7DfiV!2rww3b$peOZ#$Lv$pm>9q2ag!? z8EYB)K=A?B`-EX9<59*%ATfA3`HW#T<95a^C~4yrLqBUjYY1rV1KfS@7#6TDWX(lM zlb;x-uuf$y1&7riXk30}C}J&Q^#G-3P+kCs-w%dz)^gUPpzwo-^KXVa);iYXAbUae z3|QS?hGy1gR(X&eObk%-7#TZRJ6Ugm^n%(OV0EmFvsh=dP6nkvxEKdx25ScERZv=E zfR%MzjA5+NtPG%f2A-aI7!z0%SW`gp0S_wy#t7y(<~mTA!tE7hbY*sB76sj935s8E zo)%*~&UT#b8z_$8>ZBQ;v%O$r0EH>s9}0|j+3vC3fu>VPy`apf&S=c&ffAQ$jFOD1 zjLl%ZFgI&5#xv$JZUV(6JbrZ;{TX8!r+~r*?q+?)xr{3r4M6$h|9^gn9Y&1(jI$X_ zLH2^&3=S(ZMjciiRyI%?hsUKQqYJAG>u*r}!o$Uu(T&xOH31ZU@I2_mXwT}v>I#Zq zxPRRly;!|j?}ExOxOv`;wyd_S>p*US$GJbF2df9GFGvh-ULd0es|G7K)NhbH7|CeP zYQfqBvIDLzkkD`oU$^<^yv`2+5^3PvYZC)P!vFo5UP8b&=e?8SSdv&)f$U`{fu`q9#xj;N78y`lgU3-XV*^VA%Vkj6 z1Q(mcIDus%%TtgTJkLyL+{Ut<#SN5R;QpA+c$VcXi!~@*;BKDJ_?G1@O94nP+;0mR zBUvI@+Cb?Z?!J|bKUjXU$bj+(+}@3h+^jsT>?r=-&UlyQ9?M=(yur=e%_zw#$$AcC zFI;Rt<58BQEH6O$1MZfCjF(t0v0Mb@Rd~D|Wn9a$mcj4zm9FwX&{dwBTWWNc<` zWNuJBSol~x7VE`|Oq?lM(I9b+%@+v%>m6!rqgIHrx>`-O;%J`LW zJID^WUJWKTCT=G1csks_I!vb-Pcwq&*x=>30n;hQQ;d*#cLivkF=4vEc!3eT76%?5 z7EI?E&ohG8=Yjgu;Iht!=_=z@M(~Ual81`897?ArEV0CR3 zlLWg2dlV>s;o)4vWX^8R&IYP~;r^{>3S|#vR|B~jUe`7<*|0mX+kxzb+tJG8$L`O* z7i2Fy&fA$h**)2#LFEQKj=GpM*frU0z~vAuP4+MuvKz8Hg6)O*Z8B2^dlvg+kUDs{ z%wj5KFK2fFxdm?CJf`XFGuVqjWdsAvZ;O}~urFlq2kC|9trbj-?9J>vAouwP1ViFu z9aArRKl^-8K8L$`1Jg40W$aBTe%r*foP9ZaHYi`h!*2`I3icK3>Y(xk?v`y#E7@1F zJA=w%c$;en(;db~j2}VeAKZ?EOn(^}m~J~TFtCI4g4-L1n0Og^8UI=_FtCHd9xQg4 zNeDD9Wq~Yqgb8%^*e_6@#4#iU(l@V3xKw_XY1UBys(_{9> z?8iZR;dY#7I>LU0Jrbl2ln%h^E-^i4f6kr;QU?lqu-G-GeeC<#_vj*zRo!BG!2W<; zP@92)4epOSOvl-evmXGN2g*laz4w@2vA<&P0+|Q5_Yu>6_WkV7LFR$d5Ln$aribhg z*;8~F7}!8z1r~e7bcOv2`)&hdd*3mAXaCOr5M(dheV>@lv!7@GsL#N_2KVnbrcdmj z*e`+1gWK_o=?41^_Dn+t1~w~&0!aA%WBSehoBchCIwt0u>^Iq`fz*NG9PAc0=0EIz z*hN5Y2BkHy7#H&`_FL?y!Rp{+U(A2m|FRo{)WO44i1{}AZT4Rvb?~qfWB$kfk39-S zoiy_u_B-r`M#%nEVE)hkpS=pC4(?wS=DX~7*%LwP;QrMB9dyVs3luK!u-9Qe!+wUn z5fm<fm~fna{GHWnTeO2Y0g>^9S}1?EIi`fybK_^F{WH?DnAe z2=H-)gr6Pr7xpjgDj;=m_c=3PV!yve$#u!TlS_e470frH~z_*I9?m7qpV>dN?*^F%59bQz>+ILrolw$24f8MdU+j$_b?~riV7|(J zmHh?CJh&Y#%s<$Fu+IajgZra{`5OB*c2SUdaIqfdpX@)`Pl4PAcgqCkbL{8XPoemC z3iC(ykL=Sy=?ZS|Oy+y+_t^VD=?ZS|JZ44?Mh>Q%P7F-OjtorUE(}b@&J0YJZVXID zt_(~s+!>fmy%?Cxy&0HHJQ$daJyGsx0-Zz8X3W44r-q4dL&Z|G7#LzTAsAU*h#CWf zx*7w608|}F{W}c?23bu8h9XS{hIN_@49_(g81896%x2Ysu$eR&7(i-4W}ebyV3?rE zz%Wq_a&8`|FAh5Q4&)|5W60Te$n1+o3=F@ZYPr-Q@*pvoKVW)5VxYS$WYr<&BCF-c zB8ILXW~T#^S}qNQSs6&;=z2l(kud$(KhuUiayHl>y^ zrWh!kK0?zOIvbRCKxTo&k=gUDAz=U#2eCo!0^RWdx(@;r_8>mU{yk82AT}s`LGcWe zgYgeS!xLEzOblc`NY864hA-N@kr zlS5Xw*a4yrbVm;8z8qNif#M1lejqk1yg=cH%+E1~xB;6OEc}$AVGL3OQtxg8u@hMw z7Cta}D^msrcT*&s6pL->K*3{!#YX*jRXns9w%)sy*ny!%7^nvU`=Ogd= z0m-BDk@p0HX{p^kamKc14P{<3kHT=77PrN z+#vV;fZPHS%Xdb|%Q!JGfW$!RKxRbSA>=|G7#MOKAZCKpfb>_{GcZiChlnAoT?4g? z!JdI3)`@}PERs3Ma@_XVN9C!QX?K0kqBpw626v8`7o%wXc>y+gBjA6toR>3fcy{ z32FyJ z6VT+#br~2e(A0p$n$Xl`p{bdV=FfICf9^(-Uymdwj23<_XyK=g=6@d@28J91R6l^k zG@<5$;=om#f#IVBB{3((?omo5Xt474}}iGjMn zqj)p~kVC-oEF*&ugESLpya^=Uz|g=D4Hnafi#0JcF?>4%QU_Vf1X2fDOUDjYrwd-w z1`?}fsAcE|iy_ptGPE*ig2a-Pz-!t->gpNl86-eriABLMd+QkL7`#DZ461N@8yOlI zvcO^p^O_l&8LH64S{Pa&_mkvT^4pc7>gCV0Q<7<#Q zP%wk$jTrbD3>i!rY{6pj&~itN!GfWYVIf!yX0J5EF$P`m9ll~W`=xEW`+h&W`;?gkh^<9a>#e}f}A*tM?+vF zg#a}FL-Qdd|7&|QGcejQLB&`YI2qL#4}tQv1*{#;&ajGM55q~2y1y_nE`~3R-x)W7 z#H<*hdifZhFn(Z+K+!9}pvmaXxEMv9FvDfW8;p%0b)W(UTuz8H+-7{h_y;5gFJq(_ zrZX&O-~j1`mql_6`x&k7@5F&O&AU_USPb1 zqRxyVj-h~I8j6@DgBL>tLl#KPmWctP*M`BC!3BJOc#0RIYy*{N7rmGnUVB0ACkM%a z$~n-u8jKAZQv<03@nJNq+yjY$*vM)?3DIYS<36d-IW(Ec1C>~@X0BQd-Ko9ff z462M8jEhjjxEVwl6&Wj0#CRDdGR$XaMG+HVc*VfZxD!Q8gn^4ukWn8bcKog=s0aX+ zM5YYx4EI4|3^03T7`zxV7z9wn6d4vVJZG5V!_2_Kz;J*IoHvyiv>9!|Z3k%|ME(Nh zBM={!r(kSYo&fPdX%|F;@)0r{S&g+1GefiwqzwU5%jn9;fGm%mUj|u}k2+^G1mGc{ z7tGAS4XwjLOPcO6K4jDl0__Qg)a#(C@-gEx#tDH4G0^zg3&z)sO9Mem>LBVs`+9${ z|6`B!M~Lw;FfbT$m~w#k1cPi;U|;}=!S@6siGlV6v+hOQF$_}ojPn_1urD+G-eHi~ zJI;5U{AlXla=zsR?Z;n(SjJW1nGUl`Gym`#~4W+Xq?a$WXF#$;Bp6~?kVR} zPVl~CxEM174+{?qc;7Jts7>I&z{kMKFoSssGkD)I+&nghEQTz|zGJu;JA)LX6yr5t zX85=x9|H%&WroWPZ@^;A;I?$8d<@5W^~v*cn#v{#8B(eun)F`x)kg#Ncig zVA#X3hhYj>tdkd19`i8>GVEm7$`^i!S@}jfW)|9 z;itsF$jHbj0TP4TtIY6^;U5DJikJ$+Z-(Ct3@Bo%;QNlj`?leF)fh?{OBs>(ZSygx zGc+(ZFuI`V)nL$L)MK;(iCyo6x>=J!g;9kOvcDS^rdkX+9621|{oQaov>Ea^@;H$9 zck?mmFqCnWaUk#S=3~%hsNksJfbQ=Gw=eh@^cbo*syLAMck?mmGh}mQbC`nmRKx8s zU?|}z;Q;UNz649Bh78pl)f|xh-7xnVG1PF>aDexB!_^rx z@9&0-nKG1elyV^N@8)ALW2oe)I}@_z0!OP?hGExKFr{K>hSW z5Xc>H_xBJf!To>yiXmjE|4LIxqunGPaQ56!l1!y%?#eB&cJX0wD*ROA&eoG zIh`50PaPVj;ovzN@IH089Z?KU%udYUed-K6P&dag)G>E4gZHV!)x|S7GCMMZ_o>6} zO=Ku#u4D%9Q-_PCFl=Jp#th!4ex5Y|;+AxVmCS3I!TZ$V=4CPLW!}pS-lq;1%Vqe= z{1viK9bV=XFq~sP#|+-5&eREYUopca=DU!6>Tr9@8Q7V*nZf(i;bK(`GR(@%;Cj`GQ47Z#droJ23Oa_@RIQ*qXCLoGXrQn zbq9)A3&S7wKkO?YVh14RwK9O#{rf<~pl)en0IluLKoM(a0PQyrLJ{j=FyS!axEqY@ z=1vA94kL~qU@@3~yBLf)j5)x2+~Hy0#}LgK%?aM)4v(Wr3=NzOoZvm~aIq;2VVq%{ z;63hev1ts|oYkD`QS#*shH%bs&YNH{Sl*h&P{Ucn3E2w|%Ug38A~+*B!F%DM?JGWp zc?`9jwVdF+@F4dIfZ9Wg7(jbzA$#E=dvy31mN6V;JIDs!3lGu@R=0{_7u#+&@LqVh z-Zc#2?BVR-z3_0c4Gh`rIqcxQ@F0JH^=@HEW=~-U?}dkpZDWXGk6{Pzg@^0i#o)#6 z#SY#J4_CL3!Jplq9lRGFE_R5aguRp<;YUz3_1JPB7H4*Rq56!o&5R z0-tjN-V4vk#SYqQ#K&-sL6%*P9lRGFuJ;myD7zRtcrQF$?-lTwE8xBGaIqT>0y6_WA7Kz3_0o&l#q( zPiF`3g$Ipofy4AQ!!@?+Y~a1{aJ}yt&as_m1Mh{0i+yI8$Ucc3ycZtS_5tht&d|x; z#SYmE&u{<|20s{@*qhjk{K5Tf@P0o&hTjZM98Mf60mx$i82mW=I0F2c8Q4K~fZNpn z8B94$IVPj%Wn#4Eu;y?@sgIZ$pL0IvL=|IUe9!rw6SVH1ks%doFDK&!<_XNZpyol! zKR(7!ocvtiefjWmNPtm{Ns$S>FCQ)@#K_4c!UW!z4;K?*3}#AX0`JR*i-|EhGX*k% z_vORIBp7>{W-@{I<-^6K80(q3nZWz<;qf8I*w5C_2Huws3IlMMDlsl#TgV39mk%0h z0*k3JPGOtM2HuwsSEtEX#8$)x-j@#-(_t)UD`x}m%isJ!6cQi$jCE{vY{>ia`4|it zo7tM#!29yydQBNS**e+4`|{ypmW;F5X0w6!<-_x@4Pypd1{-8wKCBO6#~8*I%?93= z57+C!n82362HuwsuYX+_by$p8!29yy>O2`GStMD&`|?3z;B?@{2--6R-j@#&1BZb> zqa24k2V`G9Gc0`JR*t4m`{X3A#@31VhoWXOlQC7UsxBax#x z5F`dGOL7^*Il?)>`}g7gC}b356J!JL-)DrWD`C`R(_{nh--oNKVAN*QW&`ivho_fX zMin+yHt_y^xL6aTKAQm>c>g|JZyTc$n-Uv%|30W)3=Y38MqM^tHt_y^xVj!jUN&B~ zR^uzToVw7i7U<2>zhl{OX6larQ1MlgF zi>+ZaVKZR^@9Bq&ZD15-6J-PM>1Wu-1hHciBR?BI+au6^Sh(M|F&eQMv4QvW!}acD zRA*CX1Mle|Dj9skVtl&NUGB2Qc z@DAfb)`hI#J^f6b(Dd?v5p+%rcuzmvyhn_>th%hu!N_Uo1>;}Vf2`nr{-E(ga9n<1 zJi~gH6}-|hP02AnZ5b)lAxH=Igdscf^ z@ZNv89pX$oSa-03_x>}qGePpD6jKgsA?pXwo?Ezo<(T%c>|p`#{fFySWC~{qX94g1 zXSm4=Nkghk2`mXL;JyEFby`dXEQKuKz5j4AeWn(cRu=Hyf4G=2Q!h&|3wZB8JdVtn zKC*m-?EQzUvt-)LvY7?E_a83i$i%_Q$qL^44;OQ1`or=UviDyhLK)&dZzj;$3E;i| zaCQDnvsh-aK=%H_(qACcBbG;yz5lL3ZVNoODWSyrjtx9C}mwW(_{80?BFv3;P%!r-D0}W1U@6cH;)6Nw~1*!(|jiI z83Ay6+nDAt&0~U`5daH=E~X_+OPIiC1i<~)$F!JfF%$TV0Jz>sOe>jIGJ($sfUBFv zw1Q~`6Znh(xVl+P3z-%&fzJp4^|8VEXdcr7rUgvkGXg+^fnc#kOv{*-F@etrfa_hx zw3KNn6Znh(xY#PD)l93Iz-I)&^Z7caRZOdxz-I)&!(bDWJc}BO2RKY&e%sCTiv2A+ z3n=`~!^+sBOc&WNvpa#xVz_yyneMRPWlsg2F95gqBGW4NHSFN?1>pX@&a{Pn8@n{P z+<@i5`%HV-_p{Fjna7X^EpwhRonSxB4nBtfZr)3#Q%t9rz~>NvT4LZZc*As>=`<7g z90Ir<@0i><-8sSM5U|4P{SQpjIA(Ex&mmyg2+f0EnXYnN;{cyS0Jq}@(?pJm98sWi z2;gGBm^N^1-~gXP0B?)_Wje=kjstQI0nCp7Oj|j2a)8evfa_&uKF)E11AGnvT#S|Z z5XT`7@Hqr}8vuK?6O1*;2Se$Dur5qw?&TwO483}*}{_`CwRSQv97XCo*0yaG@hf%Qf(S8-Nx zHh}w~us&xLvpa`72lxyFxZYUiD9$KO@EHb6@`NDcmT;NyIGZ@ZXBfc63YbGULpZ@_7{J9! zm@7CdIQO8qxq>;1GmG;RidYSEKW9HD_^bm^odUMEfjOHqn-hH20o=S6<_Vk=IKgKf zz{913Ih8Y&6MWWzx&d^IyN9`pvx^ga)&X4a1m=9sd`|FL2OO~Qo5DPWa|$Q;tOK~Z z8O#No1)Sis4&Y*Qn5S}1+av&N-bEeAa<&4R}2jAHzoGV$Nbt@L30NJGL>;;GDq;KI?#!0Xi1Gi@Aie zgcE$$0jPWiht)pjnVd5@!Dk)7?Ks4o#F@kiIqLxC-($?}ob8<8vku_uPBJHRCUdR; z?S+Snonh|a?BE2SbpRK;z?{yR&Ivy204{cgxreid6MWVITCJGm$eA;t%Nf^C#vu&NfcSSqHGOn{UkVobjCCvkpMzI5_-%F}HBGaDvY| z0QCpKV*i*kIWsxIXC1)pWn$^$?BfKVbpRJ*V@cyomTt~&PViX=aCLkv zd7OEiPDp1H@G%InOy-=-2|nupu1<_4hcky0eAWRx45U~la!%w#KI?#wL5?MtGnW(j ztOGsO-Zy#%1Nck{(3uMKJc9ughaLXR;I%L? zwnYFl187YEXuNWTKQjYpZ}yQEMuuxGjNtWepndP4y`r#v?x6j#hy9ruuKF`GJojg2 z`039KKEnbe4?05uM1$7xAk(n(8(=g@9q7yj*qIZcbv&T30G-(|*w1kQt*HRH7j%{Y z$d90PMYKN00Tx&JD;XF%S2Hl=2Qh>5<>>^-9%ja0Q(^018*w83D*= zKY+p&B#wM;Ltro@TtVWna0Q($0MbYFnGjGj#7!6&K=vb>4{{4g9CS_r=)4OMA7t0) zxeyEtpfCo72RY#bic4yr3js0{6gTMU0Qu|>*qI0*cZ1IC0p(@TUVqsBevtUtVSJuM zLI5*ERRA-?!~kZ7g#pYA+XI*xjs-9?+z4Q1coD!1KD$RGkeLA#CVGL)3=VW(InlmvO|88Rfi;-)Q{N z^E4pmfQ+7}fqEXsU$pZqnofy6-P@IcN9g6z!$iM27bLC*nKxYww&kh1z zN2}}w z6G6`og6f6rl{5|m?*V{{F)?gl*uan$241HOUiZwzz|1glY)#+%RSaP~3saV30FM z@n{H;69UHJp!^TXo4gDR4EYRg3?5K12gp(;h9ZVCNFIT%0T5t-+|3EjBZ@!3c^xDM z$|K8uF*30I{Q%xeC%^#7BRfH2ua}8{@~{8{6T>NnQw*O$`6e5(9zlSCnL(aWp79h& z9RtKI0t_q+ml!TF+(Z#$1@Do23epQL69gF8!29b;!$EoO7!zo(fdB(LLoq`!!*vuf z4u(>OQif$HVw?;m3?&STk<1K&shZ$@4+0Ea44|@&BLdkxZiX_3GKLKxF@+>^h#fo( zpt9{WNGvfo6(YvV04m#*Kw=7Rju0_EhH{2-h6IpUlCcg%jGv*Bp_1VhNUXRx9wH{d z04m3-Kw_@Gt`IRnhH8dthN&R2yu@6Hm=O3LQ#O#BtV&nngD|W!yJaW4D7!_>W+ceCJHd9 zFsxrAK4?Dp7Y7r=*GLBN90rKq z@s|;trvLw8WN`b-$dLAj5qvgG=3hpz8qoa5q`!>dF*}ePC{KXKzTBc9=NEuzP?-y& zL2AKtG~&Eh5MS;$BZKE}h#8mjT-A z%gg}E|EvrQ49^+fFw}w7LDmp}_8oj-_{mV3j?l}+z`*d2ft8UPNeon;++%#o_#+ab z4z%aUim8yPJpmyGx{h}hlOXdIs2IpzI|c@ZO-$REctQ4hLCzuxW?*1=!7Ra&9?Q(Y z5yJ#_Ul;=e!+Yk>%;q38(bZv{M-=9%)pkK zR|2t@iD4V-Hr8t(vC<^)*@guS%nZ9(ce8eY#ESAj)-e(@;NzS_WMdF*fjBzkEr^>ew01Gn{8wjG~T%;V{Et2Gs;)_i-{zVwl9>gd)bpFqL5{ zg9D0QZia0P+Zc3F?BD^H@1IfB@iLrYIK%J>B@Fl&x){0`?x3jSXE@1llA#vGUIB*L z46_+hQS1<8xWRCPAs$7Y5W@_H84SEAV!{l441EmyQS613pSdXZiZbkF*vsILVuu*R zRfek!8&S*?XIR9rh~X@Xm;`v=_Hq=xk_`74?lEjYu~!OQ4@jWcD-CW}K1VT6hG7-M zDux3n>SP&?F&tyKgJPZ>1E}3Q9YwD^!#sw04527`6&Q9g>|*EuxsL_1C%Aw?k>NJO zZH5jMbxI5e7!EMp2dM)!I20Hd3K*0bWEo`{-=c`AFlaDpFkV0rQ)Q55lxAc~Mow#L z3`UGbjN&L_>I|ApnoRm2F@I<9z0w5?8Vp)YT1dQako}DX3|ip( zv7^Ca%;0^71q|8@FBx7k>_ZXLVR*yvhJha}2Ggs{@RZ>x!>x2=^Yj?LF??hAiXx^D z-h15z7K7Pg0IEP47o&(7GB7bRG42P8!R#;s?*q35i^237GdyB^#2A4hX2S58@iC(U zikK+_XpiTvG-UUgF~l*&FFnE5jkCLrexJ>f9K9F#TZSMGGhr&ZLauW^ab8OjntHqp0&?*vYh$=`xD@d>PI$onv~3BId_%p6NVO z8%n(SGw?C<1QugJ$5Jc?Kl13NQ2^M9~^VS0lZ*qGUv z%~9+PVc5^KpJ^kCe?u8QFnwTBMiC2Rc*gXMX*Y^_;S3DS49q29F_>E-z;|_TMzJH3 z0kmHJHj26^21aH^W=@pwi)OgQbctza0&@JuFsx@<&*X-pE|%d2(+#FODB&E(u!Cs_ z({!*MF#pCg{AT*iRE*-51aR6AMG;E`-$i^D#lJ}mADKQfxuJ+9gYPTPLJ>=0c*XRJ zX%32;QyD;eAEv}IGYHBvLGwo%!w2RM%-=v_aWJuThEL3&n2&Mw9Kw^q8b*&6rShlcafy9o%#M&6Pv20^$0g1uYwKMEw*~u~=BnD5X9SplzcClE1 z?2V6y#&0LX8kRLIpF!&2;n&3g+FNx6BnH>p&2WI_0Lv~Eu^xuKEPGkJL1J*X^fGK^ z*~-$M3F;?8_J0&GOk`Nix`y>#21pFD|D%9mDnmDG535fUGXtYzfG4QmS->!xp^&wR z^#+Q%g$(|z0j#mfObqP)KB18I^CE^qra~r;S&R(q&~?oP42v0#vm9q>N@ikUOwLIJ z?WZeXSjwQrs>k{%jfsH~y8okqVL5{!t0XJuVo=`}=Dw8-=UC3Md`w4Hx0>M(3k&P9 z6lAfr49{6UvRq#T(hKv)MuuA~w^>3{m>AeS{lWc|0)|ZtKN)^9aDc@8Abs=#hRqDK zS!S~sg2eniq3X6Un3)wN;D^?3sC~kZ|6^Ai*NR zauOw6_A$7y_^^1Qh#g?)WtqrQ4hpOIU_VIMA7ZFuX=3@X2|28eF{ra>vU~=`kwSbt zMBNF7JeDGsb!Eume2O80C5eR@q}M0Z7m_y4F_^NLvCK|q07X zfZ-3rTZXp`)@g`w=mLhn40D<0Gs&Zb6{u&=%E*-Mz`$h2$iT#4&%hLF$G~K4%fPhE zk%7tBiGk^$GXs;E3j-5_D+5yo=$=D22B!D!3{0io3{0k;3{3C67?_xR7?`$HFfgg* zGcdhpXJBFoV_;&4WnfA#WME>5XJBF|VPIlNXJAT=U|=dPW?(W6U|`As?I%cJU}8uF z?;&7fh+|-40PQCTWnf|mW?*6nVqjtjWME zWnf~6W?*87Vql7nWMEN#k;K5X z$d`dh&7Xnky&nV9=57Wi22KX1_w@`+OpOdo4806Y=}inw3|$ON3=IrS3>^$ishtc= z#cd2srtJ(&8LbRV40Q}l47ChQ3^fc)49yHo3@r>y3_T1?4E+pD41Ektvnv^xSgRSB z-d8a&rA%O8VwlLlWX!|B#6E|C={+w4lfrZcCWaXdOz8_4m>6aN1C!}o2B!YW3{32k7?@0_Ffg%CV_C~ zGcYl10gsg(jbvtc70JvnFOr#IiwqOPCmALNtt2Lfy@^Z=_6bZ3F$qizn{5~we3FTZO2Cy2C+}T8C2I)K|@c1Ce z9ME{*rZNVGy5$TEQXd(>c?C3v2vV!_fssL{h>783F%tvKJdpbKEG7n!8$srP%!A2+ z#t=d52_6tPgWL~tC&(TU4I7^XnGG7_0@0xHNRYokYCvX##6a#w#>n=8)PvN3Ff8mm zUNACbu%M2Kg2uc+YLU$bjg8&Pf`k{yOprXtPSAKJY;8C${>AqU;Ps6uQOpcQQIPeI zAbsfKps_&ExLmL*6T{48CWd`#5E`_`?#&{|xGYE<pW*#>9}8#>B8HjftTvm5ISFm5Bi~Zulsji9uo$#7txwWG0Bux|xx|bTe*wn4O?8 zO^_bFZH(ac@jlxidlx`_&>Bh*A2gl`QuFp0Bg5pAj0`Fqj0}Dp5Op9ibiN-GBf}$K zCh#5zkbLiH28KT$5bC$3AmlpAm>A}jA^0un2)1$t6N6y}f*+U3%#fGK%m5nKWzJ*< zkI{mLX-4sA2w)3=W4(xRcu+exnlX-XQVBu~w7vfqCo@-aF+z-=fq_AgOO8t|8zCml zz`$^do0I25Awo=wfq`Ky&kh~|Bz4LR3=AiDuJZKeBh=|KFfd5+s_=5;AjFIq7#Q;S zEBG~f5Movg3=F#%PcoMDfaWI{z~le63=9nW84ojdbs^NbGB7Y)XMDzZtqY;fgMoqJ z4&wvH)((Wa00ssIYbGD2Sse&Y(=O8%`tE=OE8PIBGiHA7`T}EnEBffV%eZDWfoy}Y(eM+%?W5S zn=s$YMTnhbU|{fJj$?_cKgN`%-I1_p+i%nO(o)% z{>p4u3K0Xf({F?3cQ}MO9|R-jJDz~fZRLE=`Bx4h_KtypL4zxiOD+dt$43SRhA^%u zE-qJuI(9||22b93yxh46bzF=L3{|{!ycYuz>i8HL7$kTW@+e0k!~_``7#{I(@=AFl z#Dp0c81fmr7;TW!kSHSq!*Qm&O!J)(>cklt7?PPPn7;cW#H1J*7~V5TFxmwm#AFy5 z7=AGFGyU*Gh{-WBFid0I$oLs4oD~=u7+x^_W7_YGP^ZMmz|hPzgXu~*LQIvBfkBlq zm~o0DLQI{JfkBGNkO{nIhE)jM-vEih=Zjdw;bNfqBJlbcBz2$(9PqjqBr!z>MF#M? z7bGzy1|`UP79=rc24%=x6OtHwu8H9QxZMwO3uvy1Qx-7}ug=KGutQ*nfVm8^7!$)r zfsF!Zq>;s#8P*D{6_}2qj)h^1z!rgW6fstY%>tVRwxfu#F>DpsDliMhJa&fF0;>g- zQQX48uv1{Cz+V(~oDAy))(hC6sN-VTC9q3C2E`6;h7AH61g@iq@i1%?*d|bnqL-Ip zkH8**sVHK640{Fk3b4o_`ikpQP)(NZ= z*nlD?%&lxNF zYy_DHsz?RMG@0xC}b#P_<>@F4g+W%S1F2ly5RZL3n*fG3|APgFqoi- z=`(C+*v_yEMa%#^KdXddhavb}<7ptb!2N5)ki?M0(1)VVm|+^jG={q<=9w_uVz|W+ zhazSQJ{S5YikKP01BM3-Oep4=gV&U}gT&zWT7c&qjZwrb!Ru-cf!qfVKP!e@hFpfl zD0WygoMt%9Aj*Lpzcvh3%vQ`=C}Oq@b6DoE>_HK;W4O$6nI#@Y%${K>%Tksu6fpxi@q3 zg2X@vri1mmGHl}B#BB}|gR666*uuSq+Xo~DSLe>Km3u4q5)?Z;7}jvF;qC{C!PR*( ztma);I0LU!R_^D*vY+idYoGJ@$L-j3{E!47b>Cv8SQ9IffyKA&8+2MJ$#fgdv2X4Mi-D zA&eo6VFC|w+K6Yc6R;Do;YCi*2@FmGP6E^Tki`-iyac=izK9}=B{5VAR0=#p(VNWR zCg3LE!;h>kg~3n2Pe4fwSuB;IN}x(W45jW#V^}1xNMH}heegI+XRsHr7f463BZI+N zz**o3iu*Ddyal`k>`>g7#ZW3xDj1YUr|;OV)5!9l=5zy`(MLIw{34}k!bFeqZE7N{1OgyOei z1{VPrflnxUOBj3vd<1Gy^p-Nz2-FDVfb4~*`!WVw0b2nf6!Xd%90eQ&GEvN{VDJ?1 z6qtqL-%5sZfpUR8D0-_HTm@VOmXcTA^NXTM_pI@%d*ugMe zV7kCI6tPZ*nF2Efx+IYGb}@7cbP8Cb*wM|9D3B;%fnrAwLz6(0KsSncy$mx1W(Yh+ z5$j`^B``~14~iZA3|#_U0xl@&bOOUXfq4R*DE^(u5GxQXun|RU5<{FooWKJVy^|Rh z3M>@p7Do2R6oyQJOo5#!VpAEi1hNFqp!j1NL#sfmK!7B&-sudz0=)vyQ1s4V$QH;J z_=BQ%CPSM*n?M7K-dPNN0(}B}DDIohFjru%fDMXya~RSE(gl)G#O5+&2xJKSLrE|5 z7@`EC1awitU_L{%K(s&>idz;iGz&Bfyh91+g$&&S-2%}ldKWRo2*e1?M$x;Np+%rY zKpw>(OBi|tdIZ*@xMe9rgg}JA6%?^$43Pqn0^3p2%W{SkffRu!C}JxZQUy{4bWq&4 zlA&FoU0?%>y{j1d1^NX9P{L(3Lz+OEKs1WpH4GgB9Rl}J^sZ%?ATU873&q}b3`qh> z0{tjr>lu;-k_D1PkmGy$m+3mI9Un;wa_#0S0RUYk|)wb{u4wA}~e38pV!74ATUr35cMS#fKS6 z1WE)RqlC*51|tC@fj=NIxV=Xij0KDZL_uzWhu<*<69E$e3ly>A45k960wEwVxZV>C zW&&mc$4U_EUDO#*GW_HG$N3mV>=eU)&i|ZprO4_|Gca;7aUlHi(-B6glZluMLr3yRnU1~D!%u1FN~E;2}SNpqE;h+Sfk;gaDJ zMG?EqAju`kWrHGig+Yo-it8$h9akB|xx~3DQN*q>2y+Q@v7v}vXZXqelUo%<>;?l9 z4-=0Qir7sCb{=+~M@7i~y~S{j`y6)-ir8(2Ej(LzR8Yk3Fl^-6$m572c9&rj&nBKl zC}Q^*w(@M{IfNp1pJ5x%Hl8FDu?GyBc{cN~p@=mfAgnVjmggc;$HiqlkS1i_JnY?=#rE#VG2&Fi7)C z^FGZ(w&N>90e=BMGm5%z42Aqf{O%}X-x*5yOZk;i#C|Xo^B41HposlsDB~~Vzuk*$ z$1jFh##qK{J;-9e89;ZzaGjYt@d#rsiWn2)QO2W;Q7HB@Gwx&D$7qWp#=^LVaSx+KH?lui z8SgRPW6VMkV`IF}c%P9OMU0*CF5_LsIVfTrjG%R{Y$$ecf^H~be2b!vixIR&b}Nb) zHzVlm)$=G~JdB|AwR^gd-N(y#oAEZ|d=xQ0#+!^c8IN}$tK(<1W3prVi6SPzXwPKN zq}7S6PLR=o$${xBikJ|i8xVg#K>?c9p&W@SchW^U$E6fqS>&^p&;C}OINp!KkYZOD4n7=@XInQc(S)ER}C zg_w7th-om2FpDr>MiJ9w6lE4={)%FU7NY>O0P`CZb=r(#%wo(pP}J!#g4XNqYC(33 zE~6o{A@f}nF+E0OW@F|s6fu29ZDwueauhKGMqOrI<~b;0hK%~m`pkPOknJ#HoWeYX zIkXa4%$RXH^K@nf6fqOVY0T4@-=XL=Wt_@9mAM^7%#3j|^JHe9DrED_8Rsz1VSb7t zX2Ce0c|P+76fsN2dCc>eB~Zky7-uujX0AgKvu2#jJeT<~iu-IBXED!WK39uuuPq~J zjjTZ(vX~tsXszmh6m|BDpmnZ&^~mZR7};3ZSXQHmIWmIQuNqb(t8-#p$-I&|sR3Ec znNgEPlcf2=OA{Go5D?$+qVf@Yf zn|WFza=3&tda-!1l%R-(F?zCivg|++3up9Z@n*S>A{N2u!{Wp89K~;ujN#1T%(7+3 zc0@5oFh?+NYC;x^W(;BpV!41K7Q-0K63mj{jI1t}F@hz6Wetj09AhL)BufQ~-gw3U zmH-wV6mIu& zGRCmPu)Igno5mQz62iiZqBor}lqHlU8bw_Oqd$v3%UqN^n8`SUc?NS=IdT|eF=jDm zG3TO)Wiw_nXEIMiF)xQPkR_0X6~%qIjL|I7EEiGYBabniIi2}6ida5aj1|R>0C^MCL^1XcVy`#suaB<~Jy5tr&c74ik#H5^&nEK@lqjrwwtG@}P`y0rLW8c@(#l zGiESnFk7OCRe;5UQN$|2VmndtOcmn~<{!*UQS7Z|Okz%A7DGwTHH>a7ZY)M9VzrF! zEbc79C}MSt9xNU#3sB0OdPZ9oTb83JVhxOTEOsnsP~6wZSjAk${1HX02`uJ7b=2<9V(9Zas`8#t0iX9z{kC`7c z3!ubXC%AlhhvJVeMtc@}mLQa}uAA`~^D*WbC}KT~XPM73??DmkWdz;Hw*tk#eT+rS zMa+yS>iQY?Gw)|ML=l_7c!2o;vp7oKIFYfPxt;kwihn0D?qlA^ycb1mG9&2DKnoPT zQy6=hdzm><{5F+QfklBO7^MuG#`uoo9mhlzvFVJQoSd9%QN(623UUf^7NdyGWc


1BRM;wnhcIF_LYbzKdxgxn5 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 zjLZyo7?~L!GBPtfW@Kh~!pOv+2x>1gF)=7HF*7JJF)?gp;$k?!#Kdruk&EFTBQwKY zMj`N60I02hospN}1QQd(NhTq1d3c(Mo#7ml9(XSC0uw94MJ85;OH9lRmzlW0V?0lo zm>53xrF*7sV zU}R(fom6(4k%i$7BMZYrMi$UHR}4=WSr`O!0?Wdf#E$P1H%VK28NG}3=E$b85lk@GBA8$WMKHp$iVQ8k%8emBLl+^Mh1qT zj0_CF7#SFTGcqvzVPs(V%gDg+kCB1lKO+NpSrsE_n=}&x12Yo?0}B%a11l2)0~-?q z13MD~0|ygmr4s`K7ZU>mHxmN`4-*3eFB1a;9}@!uKNACk022d)AQJYd1QP>;BohOJ6cYo3G!p}Z3=;!`EE5BR91{bBJQD+h0uv*H zB53}MiGe|xiGe|diGe|tiGe|liGe|#iGe|biGe|riGe|jiGe|ziGe|fiGe|viGe|n ziGe|%iGjg@iGjh8iGjh0iGjhGiGjg{iGjhCiGjh4iGjhKiGjg_iGjhAiGjh2iGjhI ziGjg}iGjhEiGjh6iGjhMiGjg^iGjh9iGjh1iGjhHiGjg|iGjhDiGjh5iGjhLiGjg` ziGjhBiGjh3iGjhJiGjg~iGjhFiGjh7iGjhNiGd-2iGd-IiGd-AiGd-QiGd-6iGd-M ziGd-Ei2-!b2SWrC14ASe149%O14A?u149fG14Aqm14A4W14BF$149B614AMc149xM z14A+s149ZE14Akk149}U14B9!149NA14AYg149-Q14A|w149lI14Awo14AAY14BL& z1498514AJb149uL14A(r149WD14Ahj149`T14B6z149K914AVf149)P14A_v149iH z14Atn14A7X14BI%149E714APd149!N14A3vlGchpCVPasI%f!GikBNa{J`)4O0wxBAg-i?#i85k^?85pdX85pdY85nGs85nGt85r!C z85r!D85kUx85kUy85o?H85o?I85mrc85mrd85rD{85rD|85lg685lg785q2n85q2o z85n$+85n$-85sPS85sPT85jbX85jbY85n|@85n|?85lyD85qKu85km%85km&85p9N z85p9O85m-i85m-j85rW285rW385k0n85k0o85ok785ok885mNS85mNT85q)-85q); z85lB{85lB|85pvd85pve85nYy85nYz85r`I85r`J85jzf85jzg85oL~85oM085l~K z85l~L85qi#85qi$85k;<85k;=85pXV85pXW85nAq85nAr85ruA85ruB85kOv85kOw z85o+F85o+G85mla85mlb85r7_85r7`85la485la585p{l85p{m85nw)85nw*85sJQ z85sJR85kxoGcZhKW?-1a%)l_2nSo&nGXuj^W(J07%nS_EnHd;nFf%aBWM*KP#mvAk zhnaz4J~IQu0%it=h0F{LiC#O zGcz!pVP;@B%gn%Vj+uesJTn8sC1wWjn!GE_3=CJ989-+#F}85r&}GcY`0W?*>8%)s!7nE`ZxEyGi028L(M3=Gei85mwNGcdej zW?*>D%)s!5nStRgGXujrW(J1$%nS@4m>C#8GBYrIVrF3Y%*@E}g_()r3o|3bS7s)L zugnY#-TOg7%nn1Fx+NlU{Ggf zV9;P@V9)~D0V>Ow85rg=Gce3%W?%?mW(1FAe`jW3mR*n(-KuGQ(#kS@1Z^ zXC?`TFHCVv*BP6^b4}M7pD>(e`UC2xF@oCdpf=?LW*vslOlk~Yn2Z>{F&Qy@W%6da z&X@ygzcPGeWMg>1ti-sVDG}T*WMg7vIL7SDaF5ZK;R@4JhU<(U!0To{GifkR3>&lC@qS7%~m zSj?=?@R>;yR6a89XR>EJ#^ld%kI^4=wj{%K#yJe9nbtAfXM6@~i!ttJa%2RJ5k6tm zWdP0Ze`aD~_`<}_u!5N#ymsj`lQ_7Y-p|C$z|U;R@Ptu|;S2LDhU<*;L1Und`fMvT*2;CV`5}j!n};( zI^$}F(@beh*BQIPW3sGF%nZkwSr|StGBJE&WMcTt$i(o4k%gg$iGy)JlRM)vrc|cu zj9pBib;mtS?BKrj6Gm+YP@C}|GdsgyW=4jOjEoGQ7#SHpGcq!KVPs!^F(+ znTZ)ZPV|ljWmaWU>^@?<>5w3y*O;}y`|2@L;0>&BTi822-!GlIrj zpD=1LfZEQiOpFZ2nfn>8Gfn}IN!6Ekrzd}HEZ_{tQ>u%D>{Jbv+wiIw3i6DPwrCQgR0OzaHb znAjP0W&YdHzr<&uS|jr-`oyrGNssXulOw}7CP#*^ zOjZovn5-DSGC6_ndSdv>q|5M)NtfX(Qxem4#&)LDOj{VPGwx(K&GZvA{=^6xkNC!9 z2=@OSMjnRCOrnhYnL-$kF>PnK&bSXe&SB5Q$WYHL&A6W_3Y_ji{iBmi#th$>j2XT% zon*MqcnO>~ZZonnoMaMZ_{Jp4@RiAc;Tw|yI6QANvNN1y5@+1c6b9~(-e%-rILTDZ zbe(ZF(`lwN4A&X2g2U}LqYT4ICQXKKOqvW|nIsv$F-d}G#{EnYjK`RsfX-h6k1^XZ zF)}nT%P`z#lw&x_B*yTKNsQqulLW&zCJBbGO#4A+zk<>M({)Bw@O;lVCOy!a8OHrg zJ|O#(;g^l$n+3I-?4B z?%*2}Kf_lhafWY9;tXGzv>3iIX@S$(J4Qx^r_6Rt*BRrOPBW=9?q^D4JjP_s@Qulw z;VaW6&^;~;r}RrL1kD${V`O4@%6ygKI^#X?9Km%)dC<5F<9?<%u)Hl36GJ1j z1=DrL2&U6aTS4dOgT~Dm_cH~6%w@XH7|wK>$&}$6lPSYjrX38|84og?W)f!H&lJRX zj7gi}8$L{;0hn1B-ZC;XJYznNs)0sQv%~LCM%}vj8ROdnJzP2XS@TllW{+j11JwO z1T!--1Tix+STQj%bTYFrEM{V6_{nsQ;X31eaGJGZVr1xKW@g;ax#wGTmdi&iEV@mJByRWB*K>7_T#) zV+8GexydNWaFNM`;X0!wI1DA27#X%O7clH+ng^cev|wUl=w)_bxX$PbmJeWJWbkJe zWVp#F&2W*4iD3Z~Bf}pi76uC@W`$!x<(=hU<)O;JomPk%{3YGZRBGXx$bwBLg!tBLfGs z9%xTHSf3~pBg1y)bqv=Sw=cQdgt2!d`HVPa-D%go7elTjEvcGk_r${@(h#?Z~g#vsVd&d|-o&LGIl z#L&pZ$RNYa!O+db!63+N$8ep|8N9Zqn~9e}keQF6n~4vsj**Fx;Vd%~!(1jthW||b z4BbrpVDWG!Mg|XNCWdY%Ca}G)7?~MfGIKNBWE5q%$Rxnf%_P7e$jr&m&BVzd$ZW-M zozWibei0@{h8@h?7_T#4Vm!@c&2XL30X*-1lTm`Y zOdJfSnQa-aGdh9ww=gj>NHTLVbTe^*-C@kc$S{qWh2bS5Gs7!pXNK#H9^mk}!N>+4 zX9IPR&oMJG2s1G<>||zRU;&LaGBYu}WMpJ`#mvmm&BP3LKLZmJ!#QRfhU<)uAonm` zXVe9^Z$b75F!L}7GJj{h&L|3QQ@mtk0_$a9Vq`eS+{&<@X)`zv8Zj|4OlLM^xWSkK zn%`u)&KM1@%ce6iGO#kMfX?dy`$33_kzp5e4%2nUDNLuC1emTf8Zez^asr)I4&E;Z z3Nz4tIzeV;hS^L^42;Z742DdM3^SPXn65KU1Dl!4#K>UC%nY927iZ39y3RNm+|J}; zW@iv*W@F%D=3o$K=3(Gq;$i^pf7;8$$Z!L+_LPy4;We`_({;u?rqfLA4Eve3g5562 z#K^FlnVBJlnT4T{xrkvu(*lNLOwJ4s8TA>yGZ!=LXIjW`j7fswI-@khX{KDJ>x@&u zbBoMOObn-(kAUve1Mjm*Vdi8gWM*QBWnyG-V!pw6o$(7;oRf)-;WRTRLkcq&Lm~4C z#_Nnv7(x5~Qkc2H>Jyk48SI%I86Gm~g4V+`+-G!RJkP|+kiyKyP{@3Y@jBxpM$kSb zP@DNKa|+XS#!j&PDa`C({VB}M428@m8Lu-w1?QU=jEoF#nAsUpm^l~816DkGMr($&3K*hJNQ1)>x}mqPct}OgBo+r7>D8+Dw={)0g#@CFX z^r*;W$gq-Gg5fTsH0VAahAbvV1~XeG40jm?7|t-sGF)d=U;vGEA7o-+ILgGwaFM1QC<2b7yNsd?XPEXdUT3_)27#U_Ve_+_pq{DcONsr+MVtVG?Dy%P7HchG_%Cex}FZIW~SKW`@1YYz%i9Ilx{mjwg|&rMlOakOk50IOq>it%)1${GhSyr&D6xOpJ@ZbF{Va_>x^ySI)$H! ziD54@2g6-PZiX{V?o8Ji)0seZTo)4$gAnr}#_Nptz-c3yiIKsEnG>{M9dxGw!*#|E zP}_!~i;06lh?$GwE+a3)875u^4km5}&>FPAj4TY7n3=)j?yH!OGhSzW47UF|V>_s9 zWawhzWe{REX1L2}1CB2RCMJee%nc0J8C${e$uJ5=Lx8Lh08KWLrEyf#Xb6mkz>p0A zz9H-KQHPI)z-S0i8Up{`{{t;lVOUhm!oc8c6%$aDpI(%htKgQIlUf|(o0(jcU!0#- zq7ar@T$-4p5L{B4l9{id=jR%tU}Rum921so9#fWFkeHmEn4Vf3Q&5zeRGOJnqL-JP z#1Lf_xx~fT1xdn! zp|ISspa85l4MIYVgNwo#L8*BusYMK-1u2OosbHlLCfGS3Q$2!QgF}5n7*N6mnPX*D zfg)*TRf)#0LgOdr=j0bLxP5HJD1FH-Z8@%th*FB!itzzXoWp&&IkB{dmaRHP>BrzXcI z=H$fZ8k!PNU~Gt6L9&slsi9?jCO$)8YKSlguVbL*?Yi9PDxEmEX^sw zt)Rfj)C_;PKvdv!NI_9%ZYut8fhxggN^xp3$f_bdF#u9xY+*u3iK&qx9wjNoiSdag zML2^5Bo7U?_~Oj;y!gc8Jlt-=P+gQ*PL$DQMQN498x2-X$mmQ%)A*#!l488}gA@_x zEx1Zz>;*fJU`T(fq)H22a)l~CAp>GN({Z40?FzlsWCRfX%&(xGZO-;3X*dO zTUbzDWP#J1+!U-OG1$GiDW=64iCD87M7}hqBooBKX*yo*#Tki4Ntx;RG#eG?Cgxxb z(9FCNeNZA!Ou-syFzKYslAP2$Y*xTjq@*V2=HoRZB^A^LAz(&PDqb^E^9Y%dmYbi4 zwR(U#G_$xWwJ0B-Gjj7&3i7cQdN4B}DzK(Kgpxd5i5RY=G$%0`YYmUA0)NEhW#*M( zufJht6s4w=CS%QTa23TFnQ3^#thh7@Ux1b14Rd3|czme~QZV96UB-s-1X347MScoy zZ$ebyOI^l>@dQ$rv0*&^)MacKPat&}8^%M@4$k0&tH7PQz)J9^E|3!ZsSBzCPwFx@ zj0dGI>`feS+A%haCy=^8D)6T+P(_9(br~DR6G&Y~_*0h=sM^Jwx{L^>F0cx`sSB(E zZ|X9NPsuF9UR^=L(uiR4Ga{7yj0h$_BZA2fq=G=&GK$Y7khUNy@TDyyNZP`a$c+f5 zEu(mR<&v=xfs|tg@+zpL$LfgO#AN-9+(fL!GfXZ%8EdIol$e(S)*GKvl!UcjE-Fsc zFDg!qhc(L!vXhG;O+Req0(RA)wi;2Yi!#fIQinYk!Yl_h5{PpqLM0(5f>jc59#{<<-nIhGT|x- zIt`?fkkdeF@H-72nehdQSet{eM2S#Xnnyrsad8f)oG+>@z?x@4<75RzY1o1RDix2X z84pteYKohh;WMN-BhlCbYj*@>2FQ`g$*Dyp@x_^W={c$K*av{HDlIC;+AV{t&B;u~ z-Y`a00WXt^iW709AT$kWrP#X`FlDKE>6v+0TV|*#;5H|w7AGfREqHNjNKeki73`ou zg}4E3Lvlu9K|a?05DptsNOcnah(mKuYH|wx$U{?KRGf$_C&Jth>Q1I&9XNrjD2`7i zm?koctQ5;)|K0)Z};qu?<#2FvdWt2&95y;)zk|=BAb2IZ&jqv6csF`4eSeqlTs6r@ABi6(;BO*;KB35B3u?ov@ zD6Gs)&Me4CEz(a+EsjshOa~<|93$z)*wm)xVGm7Awb%z;F%2c!cA~6K&d<%w$2t~+ zYBTo6DY_c$V`G@Ahz`Z%5;GH!V&eP)R!mGdf{i6AAi*k$v>oJ7A`Jy8CE8Ttd<1Hc zU@aR_l3H>JsAou69j@_7)VKtx0(pffU&9m=RN1a?9gMx#7;yrx>eBwO<0vNEbUxBW30O^6RYKTwD z$xqG(t&V{$gNO$;iBSYVZFIy0Q#@p}2T7nHH5WxaxPOQw4;tq|Q2=hRAt@*>2CvV7 zy8z@@WDVez86aodF~GbEqd~sKxx6DLGcOMmdki+kB}JKe>0mQ+GIPOGrFINT$@zI{ zpa~%*1|@jdC^2~Y`MCzgd&I{xI0eP~I!43?1v|zEdq%l3m>5`^Aq%=WI*0fNF=%L@ zDOAu_Ff-9qu(MMz)P$*bb%vN>YGeTtGBaT?1kpbJzM(!KhNEk6e1wIWpC<|@-rd<5 zBoG2x2^7K*AD>uKQk0ogT9O(cuc1+rSd^YxqQS_hsj10O0a6Dy1*9?F-^T?c7~mfc zT3+N76c1s=JGn9#fFwNqLJT3!@o|k0^>g&`boX<0VQ_b4@beGRa1YU7WYSRpna)tj z;1j}t5Mb~@C}Gr5U}VzNWN>!&4~S$)DvAfMonZiZOGBeHGY`~qDbWNuQb9`rSpcNT zH`K@2kO5g8SYZuBA!uk))1bn_00J~o4bWg@(p12uQda@lP)0^g1sfX$V?#{^Gzli` z5{4kI_$H55OZyFq{^gJV#z2c~^?b_yW>f<3IE zi|!gbJCNVNUePc%0{IaXC7PNHd7x+p6%EcFj(+a0@y?zB9-r@vpki(`l*gOM>z%EQ&i$3H&E zH89jQI0Po>?BnU`7ZMMagNX&Z28DsL7Dzn<++=6hpb$?tklC&bhHy7P)q1-|#=Ay9 zT+d*LO%L2+L%4&Wdck(byZHOLG8me`+<;_Te3)yHr&}b0p($Jv;%HP$!C4*@EN-5D zp1~fj;5_By8s_Q~AMP0B=jrDT(hd=Da}03=XJ=3UcsEB+ABbX4|9DS7kRnh2c>hpv z5P^k2Y-5I;in4N(3Mdt?!3fS!Itq-;nhX^s3`L0yMM(_BB@jhW8dX(NN?sKMhyV#| zGNk3_GbE)Jf-poNCzBy36T}4PREDAohO)$*(o}}Tl$1;`0h5DRnwgu+kepkPladLg zVA7flxh2UZMGz7ssL4=PT#!?e1f@ViAS)oologdQlocg0lxF5a^fmbrcv`G#ScD7|IeE%90q0 zGe9PSFq;0vl$6r)T!u0TjV4)KnpBzu3O_K7MG~YFq^LX>U9t!iZbj$;1nKfKltE}T zJrKd1#NrZ|0uUQbQ65AULm8BTT^ghjt^~wEQ&x~#l*>>CB9SGaVV2BLR*+jb$pnk%WWt1@jsj@{ z#QU-N2B!_|(LYQbuK}LbID_9Ab1ycc%f@EB<9E1sz1X+O^JYe~9gwk>X zNw&DDO&Kk0aCm`906t%P+Xo1F&R?y;8R=#OF2dOA`nuhK+J@&@t6rw z04`L(E=KV2Xo8hiU>#5nVdV%*pjtozc(j2ECWtRUEbI!AqY_fgL3MzOJnVWvnE_Vp zfmOpe*p(w$;T~eZ0BVJU8l()Fc_koPp#s!S2Mzlsm&Ah>j^<=0r^aXIl?8*UPMB&1 ztwIJr*Fd;#g$e|-5@bLoWU)|wN-9D^tAZgpKd-n%0kn@nL94hZnE|wpF}_40Cp8bG zDJ3--v}7E_%mle5KOVFwsuHRTVRtS_MM`E_QED#2^o&ddJ0~B(PC+oWia;83VM_($ zK@0go3;WSU^GZ@HN))tGic6qYCl!H~Yd{tl#wX`PGcy4x zFN4KYUMW}|$W+K$M6eykuw@`HC&3(?oRL_hpp^>KoeGL*kd>g=RnRIi1X}^+7=e10 z2!Z619FW=2l$c*sl93PMgKSPrfkZ0AD~T{mGxJIyB1s^H5RGOgh(w%{nhct{Mp6#( z95~oOu7Yq2LAt@)8!Us+5#?@OU#gIKWP;VsH&K04V`^58^uLsAy^msPF?xfpn)8<>x}nous08Na(|Y z8B%&GSgFwOX5L0-k|DGOCqp!P(_(3uwqFI>KTwvA&W7gNfBf< zB&HKVrkCUt#}|NxK%vq}Mc@I^_~e|#;$j7@l+1Lf1SAO;rzRJrmcT55@W9~)aT+Ay zL;4I55tz1AxXX%DQ&YfNd_Da@E&!E&(13#{PH?T6gIv!-lciBSINHE@1eU*{3j#rA zfdU(pSYhP=#P*cL60l!EHbILeh~q$E0V#RF#TGQ(7#m@WWFwIIpkxi2DS%}LkQiuj z4>(^!sxWA9!HZT%kR+9+A<~*wSt7U|0GXCt0*+|pgaL`2;%tx@$O7<|up~%efYS%q zv7m^BCff9p3|Nd*K%*TL5a3h?FB;(`o}no$z|aE$9!MxvKO}&VtA2`E1mx2pXPy~S14jY<+0|TTN&VV%1Kq@fGI*>YrDo{{>3WE$-u8&74 zGa)`k2~33lAVG?ftw7}>G%>)F9k_!3fg@trdQ9Q`$&~h#e27+vW zgd{lgLmB``fd;J{(vx%JGxMN+ODcl2CP8zWuo5dNIUd~p1$&`H0n%BDN2;1I%}h>8 z2G=&Arf6>%j6@g~pL7PrNjt8Z4)QT1qm5_!1AbBKv^HR&> za}z7#(~1()!9^kNfPt4I5XYhF0a<`)B`E(SCxfg6ISIsrw;Z7Ld2$ITK)|gSaQ=ft zBTDu_a&2->elejagxH6qDWf>PD784X1k&2n(8?$VtmxT&RFz z2$4kK4uF^1uudv8;*jedkYZ3>2P=)BO2Er4kkx^#fb?rXi~K<@L=u5E4V--gK+OnH zIshp^ipTWSlK6liH;^c}sQ_wZ zGXs`sp?*M*1W;2D6mTH-DQJ}=Vgxxt3Jn?DAu$a~5U>!4FU`vYx5Ge!psE|S8;V-= zLkb;G7aW@AAZ07qK4>8fDMFzfa4ds@0qkIym0;zNIL4Kw(h@UsKmo3hT2#c~6Jh|G zb~84N&jEJ_k&+FhJ^>eq5GJVBLXAx1dIwZMgSTK{OX4P0R>`1NEDpK+BG4fRSQ^YG zR#sp+a6yG#K0P%rwJ5P9zX*rfaCuy27+YDDV$*AEWtD{1tx}B!mF)Rx;AuxtC~L-I z(`kgmL?Z$wf|3|^6Af{gXh^_BP+HN91!bVz6jNv$5uVNwJyN7R1nzo3(jq9n;jJ-H zqBI8YZULDFN_UVxA1vX4Y9o*gDElU7k?jS=BI(<9kja$ zZFdATNZ<_(NQb33GacIWQz*`aG*X}y7;5hm)O7@H?S?4^^FggsH1ojX(6ocOdPIH)NYRG7Pg);fR|e`qogYmXZadti|cS%rdb4bjF2<1ijv z@`B<7ZoZL)rh>MDL4})zra~NqCfXLzq8y?XgMAEMGGIV_FnRig7!hp)IPSnUm}}}N zkQ5VOU8K3om<)Frnvmcy`g+HN4DT2jlI5L2915mHhXOceGILTDGz>HuG7A`r3K)uW@=J)0eiv6a zSHF;;NXV!LBO`Q_Be|qPQ=yvZz=Ds5K@zvELUKt3DA1EjDs=5K3&=|!2C>$}IUvL! z9-N9bz_x=d)KP#kiwZ!?+%&BfY8gP2DMSa0pKC-2gNBxd7AOKWLGj8^Vvt!-K(qlq z{?3j*AQOrT6m%7gzzaRWi+_ntzybaN3>sRxx(X=;#J3j$`~xyUmcmvKXlZIdOd!Ds zS66S45h);d8sXs`#QXwpgnB_dE{SSzFyC}?Y=Cj2s@<0T+8*dr5a zrUoLI@EcEToCU!nt%!t31L;B!FIB-m%#Wbc3=vKP2Lpbmp?idaKnw76 z_QnXcl+=Qf3{W~`WYi?S`T^xW4Pp~afUB#wMu`E~CQVS)gj9nQYlgEw#O3MvCHbIM zNNPo933__<*$kB6 zl4GD_)wm3DadkE{b8;o#D9F*b*aqUjM)?qJ6lm2Y9#`hardqI`ES;TZqfUAhY2Xxx4xiZ%0yPNh&yMhz>1K_!5!pQJe(M z1&&50L}y;yWhcleL(6ziB8pF#6Trm>B=Z_sm^nEUn}NalK;9)fIe~S6To@k!t)<|j zM4)aPF<}fg0_1X{QzTdi*iujk6Kw}r2azQc*b3tFAy_#g$AhNeiOum~t)MU`A$x)K z5S!}3ioxLvU7Ukdpb@BxK)OJ=3}FOl*BQ|P4)qnNK|!=0lCme*T_9VCFWuo$ z$F4BzC>UrmBr*_HgCUtyTv(b|luAs=jHC%t&>}2n(g7V^L$sG6d5~!3MCWjb3qeT@ znoS`MIz;3U?@h>pviP*jyu=)E6cMkL$Se$O%aADmU`-&W5nlp= zwUAePfVJkN8XLfJI5GJOtO*<#B*kZLX$}dI2?_$Ds~v=kU^$&=e}L>Ep-2SV1k!^j z-wC$*KwCJ#0|l7l+2HZsc<0cdFjue&f&*dT5mJcKsSss80ykD-f4}b|gVHp|}t2Zx zL!SJ#G_$ZUPfZ0)C*w&3=q7r#saxaJPV?!E$ zFf@&gHZs69Q4eW1AsGTrU-(CokW_=2kPS0 z1Lr(_d~Rk%DtKR4YH~bSFqgmpJxo!2ay$`TDkRmQlmTt1!Otx*fS0+T zOQeyC9dMC@Raqt0BHPNUide6^kr1dLH$w+2h)glyXuvOq#g2Mj&T6a5EKBoZxSBBe@ZxoY>L_Yy(&~adi+vJtE!$ zh_8dNYDYfxCCSjpz{0@D6x7mz=P`sJT2{0~-hqs)3OOetixZO*!EOYX#E>>0Qq~8x zI1DX_X>ouJAt4Ka)q@H>BC{M=Jvg}&)1m>Z1{D~PLJrcL2gf?-XcEH32UtH?Jt<8$ zgf67CLPSxB&_{H09jpabGr>k)iK(B!8bKjLbWsY{L1aMl^d7Q}pD_A{v^o!8QN#jp1!U`t=EAY6`u@N@8jx+xCR1x z)q{ezf{~@Bg1&;GDXuLy&_)H!UGd5BzQL{`3>pR%pc@Yqv=ty*{cLO$z#GaT+W~EC z6ije#;=y8~ql*j3L_-4u11gyq9O?uz(TI8`f^Um3s4ymABFO!W%%phU(=QCNj z91;aG*A&BC;-lKt&joa%0{*fIDQN^466imosI4TyTmsE6WOI#3aD!1L1FjA5n8`H2 zsEPsqIxplr7eInDNC*ky1ER!`fj~P3Dbz}g7|e-|juK-A0-b(jlT8>1^gxgmn=%;U zpC&;L;t~@4M}qH2@EZv}Bf($AsU`9Gd6;J!;@X9aC8-))m=IcPi5!vz`JmO~;Bz|h zR<1}6FlPp+Gn1aTdbg!oJ@4O168>M+dfE63@|k^1cw5=KWJ)^n3R@e zY7vjzbA$^bZ@EGUT3Ho9CoMqzImnt#q~RK5g-JNXL2Jt}-C$^CRbY^bLklEE5G%gn zu|;%fK};aNL5mb{$Z<<-tU|0Krge{G5kwOyaSGbP6i=cpU_Hqhsma+y2Od}p!GR4V zpJam1lL9AgXlfxg;J|v|*@0*m!s3W%4FRAsfk5X3$wSc0MoJh!Vw0HO2AVyP!3AOi z4CFGxEpH?%zzus)9>g~ThO8bGQUp2zNXn6-9z5F$8T^3^l|UjlB{fY!i|B}gq&*_0 zxscodF6xMPa#3j>_&^e(-2_W*3R=XC*&#U%NvjbwYaj|zkY9;*1SsN(9CSdk9~?Bq zr+Y{uCMDT}lNa$8fRz&;Rge@^kXV$MTTD_&L5IMI>~i868i#Z_i5VM*ggUsp3tE+q zqswV#2-BxPW*El;Gdr1#RJh9Z*7G zb{#3BmEd3giDD{IeO-tHi0bGi5M9WD z-Ah!R3U)7QB?<3pr5dCfrzKk&gXRPYxBVa{fvx}`vi1jSfV3BgZ}fsSA+?F1O(J4z z3S^%W+j$0C32`T}U3{<>aM~okuLafvN}I$s&cPbMF-=_K9HJhy*pK*>0r55|ITE6S zL~p|)6sb24PkhK@4RAqF=N}sNpw=)XzhKi1KC2pWJ`Az}pisk-)}g}+L?(Eo-V4+{ zge{feO+d?^!Ll;C10kV<0<6Z|eWwlIOZ9CS>3YH|Ts z2i{}{Hy7j$&=?9~Z-5PjDfc7F<)%i4_+4&lWQgi=unvMQ2de@(1vF}me{BrNqbSPV z3AsF_I59r4qzFe+0Uh|_7!rh7F%MQ=oM#wck{@4`SWb-T(Dn84ptGyM2g2a73${W( z*wfuF-Z9t@l0v~FRv??B*5+|N-Rfl4uR|m@&_zP z%8Jq|i4BslAh$>?K>{}d#SQQv0ZEe*Bp~&mh$SLOzz)I)5|{xf&LJX5Kvywza2yb6BshjZ#|aTI7d64*DZ@e02XZUi;P~Wt@a7cI{R!CCF_>$D7E>B) zLJsD@&<<_dfFlfi*_477X!8j|7<}0Q_%;azt&B9NIOJ3}uoUDzdgP(qf}+f_#FA9d zwM?Kp0f~uzxR3DX22c!uLkbq{#0C^7k04fikftlZ-_s9#I|YM=A!reUhK5s6ysu+K zJYuZ~ER4a2GUH$3fD!=^XCa~w91G|whz&n*$|oYJf%6T#Y$GBp;0DJh$GdsD`nZ6T z8j4%tN-)v~Q~<0xzMwQICo>t6FbcAvQjoMn#5r5AfB{=ZIH7?3NkT$_8H=}uv>|ZUYI)|5d|B9CltM?x)9Mznm%mV8_8s1g9V&C31x3%!+3DACnXNy z2II)y#)k25B_uhPa2$f&NyQpm?}J@yYSd9-!?Hpxq7%aSEVI4Kx+h6hNCGK=;pp`3w;Zkqo%z zK`_kob@T!m$jAgShglP{i2`gv4XOpWCYmtJ4Dt^N0vQS$kpZ8^4XW)lj3Fo4gSKBN z)F^0R-lqey7iX1-VUbg?yHUIW1CFDUF_eSc1wQ%22ozY@^CfOghQ{RRGBP63JBFlt z$BZ0@85)wK%gB^??*x+>JLcp#%n*D56HeIf%Aa2rr?#Uy2A-P+E|ZSdxllPFYDJXb&H}lLYoWxK9OBWNLHMke5^ec{GHtwVMtk@4$|=>szpWG@t#Ao;-54AWlhE;KcZhx(OBhk(2Q zxpx&c&`izZJ;PvuV`LH!nn;7V3F3Qbr=cVXyhj(bGf)9?OFhZ2tSsToKQjv+X3GC@%f8awp&bRk;3AxWm2 z8XA$L9+V)7b`9vlP>^EW11BKw#(=yFx|9P?AP0L!5jr^?Y*adkj887fEzL1D!eO2} zxZUO);v4E?Y(yyPPz;Puj!y!c3`(UaGSHKwE1`J|l2kMB#TknB_~iJa)G}iuLa7l+ zlbH!&@0po^y_ZxJkD`%CXPKEmoMnbot=U)=fXl;q}S=9Ls>=7DblEl1%c z7nEkEfW;9?P_9S-Cx1vL2ypiC4fO#BDxTsC;#7$J@yYQ{&4l3mV_jcXkeQrd!B900eO8ESKB zUO{4Vc1}LXA~O>WM$kcwpetJ#S)d9kP@Kldgm%+PwgE#nu7yb0ToCLN58BHQz9^58 z5o!nA3I(v&b8<3a&S3-{%cuhpEI)<;BMU@DF;X~!-3YpU6D18|1UHM0f)P{|nr?H@0Rq+v@GwNO4-}P1Tu^xe z5<&|iP&7i^g`^gnI=BN+gV+@00&4|$QbIC?krAuG$SRm2Dv&(|j%%oAk(7d+gcNej z*n@;wM*-v@P@@_%Z-c`X$xKFQoFNAZG+9F2Re>6r=<2Wq3A2s@G)RzJ@5C2P!GWQU zLCA?MK0epb$Rbmr%0Ne<%1}q4%1B3{%Gg?=3e=+lg$lS(O)bbYGeIiCKw)oCVF&Fe%kd~QFwnGCs4{>mL@oP3mV(PZYlSLs&j_P*tTNV7fT|$Dqu_!_1JzqN@2Vn@ zFDWr5z{wk~oe@<0GNTo-Ddh|);M+D(YLWER5_lU5&WMMU^n`0!h`RV>sD^mNHRA+Y znou{C7g>PoQJmFcc#s8=m12331*l34iVyG)cMXbn4EBxpb#xB$4`%RiGGOp@ zGGg#>GGp*?GG_=0F<=M@F=Pk{F=B8E4rhn}5hexgVF==*Li2kXn=ruDn6{0fe1`!!;QyDj1;EU|DfaN`9tB zNC?cypaftDazPGUn}-uvpa`N0s?;2+29#cyK;8wZ0r?(e2?&RT7-%ve*Bs!m0T~a* z%pmMIP2*_5jB~WWYmMDM?4gn9eKnRdNR8=6yL3|1_8HB;{ zV`vJpAx8tO86pY}eUJ#;PLN)(Y0NqbV1*$eAPb5qc0A}JT(H~00m1|_-9QtMZx}&W zpn_BxYBE%SkAp(w1*8lJO3t9XNgyBPrkLW$K)x>cF1-O4M4(<_a=aV9Yz|T44jO(2 zx6VO>M34$_BvKRS}@JQ*OH_v4^j`fC*Gz{B!* zML_xiEv`lR+0r#e>X*jVL0m zr8PG-Fi1^Fw2U_d#|B&z*sUNB!9@@OR|2lU5f*^_j!0eDHGsy~GE?woa)d_k${lcw z#6xaG$Le4!D`+&p?S}XSX??7&F0zKjHB3He^7WHZ`a)b+j-tx3sh*#tLsERJ~@dE|#uN zjyQJ^B8Q*1F{)k*H$x{UXBTIp>@`8v>+EP|md$1) z8p37@U|d+C16Gexgn~s-${DZ-HZ!r+g{H8H4a0bFu|jBw4U|QbGShLVbR#EEcS2nP zs3DN~ef){QC@C`?bbOGb7lA|wRS25&1~n=`W0aurPQ+w9(piY`$#{ecPmera9`cwPh?^jc+!IY_M-Xj2bTQ-E4Q=#>FT46`}_i6Yf1ATD-A(8`J^ z7kh?*T3C=)C#(cUUH|}Ubs<>_;v!p0q#d9}A5ltS0SF2aMEF4JIV65+3AFBmh=E)M z(gE=XLX2dWA}=HW$DC@k1~>w4ye7Cks->WTp;J?Xkp;Al2CEEsWe!#uHndqwP!MZsfLsAu2xVphmS)lf zJ0>%)1S}1bMV+k4$YjXLXDBmdD8sea4{InG(LEG!gd7{rkOQwx!WwcM;Gkhd4H}X| zuF{a9lK3$5bqw}4gSE)PabZwl?1l<(HNG%oz&F&#%qTu5AG4_k3MN==gNDRFV`10} z3oNFB-AKGEKzRdn9TL2#(@KP{Ye0xV7U6(rx06e9jEN7h-2A+fO3)T$gjp#VrdMEy zz*bfubmbzdj$F{mVOTe)Vg^Q9QGPDi4G8U86?nP_;Bv>%6m;z-X72!8<`|mBJG!`l zI|l@cFGEw%O8=bHJlrNZd4~A7`VnbZN@{X$ehO~GTwI-f{fTuMWY<1k!~9(cEy96? zR!VAeQ7V3y1-TOIGRXE|+%9wV10BpsWSFIaA|JO|ZodA0klT6)$7N0$Fxu%M`vde z3`@b2(tJaGV7U`dd1(l~0u*$ra&ml1W?4~cuAvzbg+g9tUYQ}5sSsGX;OFTV2E9(4 zaFjs~UdJ6Q(D^XXFfb8@6=!6omEbWf*u&F}*o0nOnuOb=;7}(bqpAdd)(asv>lqv3 zDUFQ{i7kyG`>t@8#*j@{M3%tv0*&%rLnPLJigM{*f5^x(%9HA9&c%EY#2{`X>4prpqF86NJ?o8Hx74f z5?>mF4Z~L&gWX1SX$&$BUug_7jp))CY8cMa7-|@CZ6#yFcu?tz?I=EQ>1u2k4=P=u zC-D&|5RDDv@s_T}hVjIgt{}tkm98Meh%Q}0y8>~RuAnWC#FehbhVl4HS7XC?;!9T} ze5I=q(WR>q{yRXG6z}3023@mGD8(BQD5#A{DX5L`7t}^16x2op3Th)#3ToJJ5U!FHHX1}s1H~9* z7~YZW21Ob)0DV&F34@AIf=MSR)}FlmaImQk`>n&nz0e2WQ7c& z5l(0LOI9ONN>-zI+)Yhmqj(~lnxIh$JWWkwBcck!+{EOVjNHWJ_+%{2XkSO?cn=Wa z3~57S?^=L#Lyd?}hAhYc?Q;Q*a)X8QOG}(XphF!=Me$%U#Bgj$1p`QRe2GGCW?nq# z^m7#C3%g;C`X4aI5@UCKK~a8k zYH=~>2nZy~8O$bOIz z^dK39>95!QoFC?Y1E zfQ~4_o<>kjAjwKlEa47zgq7$i0AVG_1Vn)g4tcQ8AvvfZn^@=IjeoF1U~!MV90u78 z!eEybWtPP!$A>a#7=h1Kf*z{`ibpp`=MeuO1#Jb;G7Ru7T)1W|K!$-Zl7XN>a|R6y z1uYyq1rzRBARhjK`6hQA{AoN>EzFlbYdHVx(rcl^_#{wGw}d1zAR9 ziUrwDM2a;wfF9ycFvTJagv2-zDHfpxDaAqsiA=E|)p%1ZC`gD)u@Iw(ORLA3$u1HHrr{lptj+ z`0P5&BG%4M0dxQiw4%&3hG-!+Eg6B1bR!Tl(6oeX1JT8l87%xjhl1g;#|#z&;8Ven z+CZS`YeYc@YmlLef?7w!#0}grpvWY~F&N1K#RRamuuwsfA=WYY6ACCyh)gIT+hIi; zfm#Zo6jEq`swtwiAQf6rb3o@rg7z38hXc_~LU1(VEz3Y*08M{HI1;J$HNsc>Vk^r) z{(&TGWUqilz!6QjEdfua@db%k<}g9cA`pgG$MFG;H#4uy2unv6)ZqhT*Pt-hpm<+Tzc3?se-=qUsEZ0U1e8&cWDwoj zWJDvj!qmVrJ~_3hBr`2DIk6;FK`S{UF*6S~P6Fl-=z@bhP*9YHnU_J%4G3}rcVckI z98^1KR~BeNI&Ndo_9vC(6dM}E7Zj!8$>=b%L5t)}&2SqHI&#j`4D8UPqIi(WMzDir zh_=Ak0?YX!upkKba0IQ%gO;gq3qWFoEda$~GANGXi!<}mL5DzKnd%4G1j5eFu0bL3 z!JdBZKCYm{RY6u_&$S?9K^V>G_~iKHF}$-V2cZphBU}D64$8~pr8R^tihO^ zk)L0TH0%Oa2o1;lypq(467XgY&>Aez7^^~JX-P(WNo7H5F)Z^YLsg?@(frKhR9yFU zf$RWbtPV=a2X$7#yU)OCAf|&iiontqy3NS$gas!k!V+_G^2<|G;!BGY(^Jug8NsPF zv$(i4wFqP%*h`4il$s1XBsmp4DwvuKI_4GBI#I|3vvI7D2e}x8vH2{us06kb20j=E zRtxbV$U)E|4w7mKlp0{IAWg75S5%ycz5Kw)bfEf$#9RmJGbhJ`_aypzx`0l=1TBvy zA)#U#06J9#v>3QJCmx!FkRrLLI1v=fAYJfUEl(k{s5lW638aKR$Ov$O0Zr*7yBS{A zkgJoVdJ?C2032{x$+QIKi12Pd@bVbcHT9L{0lesl}-!&@h8k1<>YJUSe)4xcVtdEiTPX zjW13uF3!x)1LY2ch4G+OiNq8bVCR9ZDM>8NDFF@07hr2xgGvk#c80hXHryH%>=*!T zW}`YDlyRYh;ZQS)cS~An4&;O@l#@9?wu3O#1#Y1}kRz*5?FBa_K?Z1A z!`0D+!2;I}d7#h$VHB;Neh8h$M&Rw)NNPaoC#f_oEw!jPJ}EOL6FN1RnN*qvixUtV z+}?uDfFeodCzYmwrJ#ueYH?alX>kTP=cMHqC8rYW(c;v+l%mw+c#s8Xg%>E5p|~2N zGBG(DO(ruhD>b{j8y^~d%TM(a-n3qzV zk(doBEfbSVkV;8t0D@eTSWp1=03-}SZUfEXf`b-Y^9-RNv6xVM7HUf}C}`nP46!F3 zDhEpG#if}gsm0K;9@Mag+^G%~F3zk8o+bR;KGGSr{pGP zr^XkhCZ<$^57Q-GS0=n_hlUj>*O3?=AT6Mz0186Xzy-;G36xwsNaDyd|o67Wz5(TT*>8FY^uXkY<%f(4sMdaM)`Ct{zC0re3; z7%hne1v?_o%HT+_P*aI;4ru5v70Y!!Age(b)KPRLbYmDS^=A}A2Rv|xtVeJ>wC4i~ zPW(k7+&It-twDU4Q)GxMffgN_7B|wh1e31C(=UWj7aW_rz{iak;F@Iz#ViP;>Gbpq z!L>aVq#A_Lbbx~mY?nFcELE&KOF`N|7)>iU_`q7pa3-#EbwT!kFq&NmXBwK2>Q01S z`g#%9S>hn?fiO-l8X1!B#i0{Cg!<8F!2`~DptD+ZaIAX*1t|!l=|jZ+a1T~jKhPFZ&{gZ;72DCIX-iB=DT)Rk$DvDFcJKuG z5)wkOv0#UTd;mJnndqXw#2~&Pv8XuJ+%+B+L>g+a5CES`!K4Ygrv@H6T95-qwYA~L zRe(ZIQv;Nn6?DlCF@sp}!5L6%K-YB{nt`ncABzEV5b9YW#D{W-LA;Bro2y?)P$Z<+ z#>l7v8G}nMsnArYCL!3t@eCeiP|$*8I$MS0k_u4hCzn*{+GQ3{kZufOtx0f7h(SC! zooj&I0kT?00m>{Y0G*o)I?|f7eBe2=q!yH9fDSie1YP7oQqcqoNgTHbf-(aLqh|z{8KA;Vb9_Iw%0pTONd$!XO73*hHuiM9jTo zXazY2G-8&S9G{w;g6n=HkUK#bt9GzHSQV=P8X*LU5Sr0JHVPb?;F<^N0NzxS6f+C6 zRM4@=#78`+r;q3MERY{S7};`|7SJR#Xwd`lmVulNYT;mYw3Ss#0S<{GToRcDB%~!Q z?HdwwBm0_^em|0}pyZZHXhs2NNE?yT??iSj;YAa;>?FJ<23co`K|E*&8>v~mEVU>z ztuj8?+ZD7l4LrdK8lD0(N{drL6Y#{0Xcfmp78u|igbIeN+7NW*J&@>P+^ns#-sF5Oc9i&=9)bI+5CB%)cAZr1Q`;gX< z1nD5rC*WZpQf(o_FGP(LA^V=Vks@RrM2-6(Yani<2w4X;Mv73(3k~)lJW_G=r=gXTUkw%jE_Z`>2- z%t6EzXpFxku?Tu(KruLUkXICE=Ep-89TSeXoT5_P5$6*W3SQKT-<3H_)V7YIXi`8o!NxCX@syE+HChJZDiSP)3b5RFLI5zb~1EvR-8 zt1HYk2<$JAdJ6-h+~({V-~sYfsAq_4JXjy0)pigE`gjJ1#0LbqhCwtD8k0lP1nM$D zG!YkiAwjOL@jk9@Az)3G#5oVFDag~^1FDPA!WpRhfNKV$ZD=x_|N>$KSr~sYY1-eoW zw1x!LQt(O;(7J09EJU)rEHMYPge0j5baE|Ddvz2*>Z}!N8S>N8h)STjiN)FRnczE* zL7|2<3>ZMp&Ph!x0pAJ&T8RU)1}vJFT2aCP3dW+$^o$asYy?G2PJSZnUK2<`2-~a) z4Sd+ym!Jt)xB~E*8t`%*R_j5|bwqZ1L1Iy2ZfZ$tQL%y+m|YBZDrqhRy8va24>l)) zy$%ioV#>v|%)FHNqSS(%#N^am(Ef|<2lgW{*4 zD7B0z)4_3_nU{@lS7J^DH~_&$z+0f7PUZap7$MXOObYJkV|n6tjyVo9c={ zC+ZUG3#c*R6aYydI1GnGCAcKiN=gQuCIL$v5FW^#2uFgu>)?E-pp}xD4nAiBDhn|J zbb@epY9-7JC>Lx9)Egin(56L@Z;&m|EQ2;4ksOMC{A+P>4w5X`9mI!xJ}9T>gKru~ z%M+lTT!=sdIW9RV8Sj2dQ0#+laVFY!n4xG90uzQ8p~=Za8wqkFY}X*M$pWMYbk$L1 zK?xDl?4YoQY(>J|2nA;`#GWQ190J}i1cM@eEjxT8UanV@_KF&`H5$r*{s8Hq*)pq_(5CWHq{`33nom4?O!rVw!ukC>DI zF&oA0FpH2f3q%#3+yqeo$xw)h0H;of6b`*eDj=Fkk0`vQAv8Kj%pMRYCxiB|#zRd2 z2MXzqL#+sitC8?-O$22Z*k(k+&Ph+sjfcc7hz0foB6dJR$N`g76rT<%pB2(GAmuXA z<|pTZTCkwA8;D49U~9oa3u1xYM65-bdGRFc0cn605yaX9(t{dvkctL(*b!@TN`8ED zNfAnomzSTHoC+-{D)Ng!Wd*_>sE={v9;hs_IS1seWN-+gQjWxpyW?%FoOsu3|~4L~)4)f07`tSjE*WK)gOi4Wx5%)B(> zeCmeRr)ebmG>y1}bKUUzG>t@`77=G@5ME1*NVK$+I7>tET3U+V(#qWA%z}*6q8LzD z58Uy~#C9`laHKDE!Xm)mClag~qC!o=Cx1y|{Z zODDpGd3mX@)-Pz>A9D6n5vk@SRhFa{mnRk&nt`f5gz1Lh&M!*qIx!J`WNl(%3V0j| zN5zNB@d2PPBh`gLM)7Wt26s)B!Jn|e}gX5h%-9e*~E{O6LRX_ZC zCp6*g)XHK7E$FyAnjCtA54;}(>K;h@7Zk*3nu<#Epn;rJ6pto{unaPwmsv(?NTlXr zD}}LzgsUICAVzXUYF;vE3w=iQ7u~SkMpB!J24?95*9$qCyn8~IDd@3-OG*eQ9BVNDIrBjeh}EO`^{15mGPC`Y2(4CuE z5uco&Q<|GsOj7L(TF5|D2?EPfM280`10<8>D~L|im?69YaO~ z25KU)%@?S0kON?C7mx#BZ5A>bD^L@OZK^<(gB$>Brhps(YoL(PFab^c!x zLwtEnbdvVC&7n;>joraOW+gUdQlKY$@VKG)F5 zA`{$AOsyzL%u9(cE=esgGBt}gLP(YvBC(AbkQ9QNO>i?xjF6>3W*8z1fLcdTwQ%FI z5iH_65D-5=8mh$k9H|QdEq#&Ah(~G+V3S5J8d3BiN?~l;P-`L-jTki%iY&rdVlyFJ zI}!O1k`|EK;OK4#C1X4x0+PlWA|MHb)3KR~BSb(Nafb*<7GW%jAp)(NZHjYqGxJJ{ zGV{P!aTk}QFC{U_n)Zi^C!kvaO8W;$hutXz@CBy_aWQVqqL40xvzP#w{ z;ppt)Xk-xY90D$fl0ci%pgX;jOTg`0Vr&E7wu#pw7uR5z9hh}+d};;GOA_D}BgBq) z@L><&(USO5&|zJKQUF{VbaOnUGY`=Vnqq{s0}65wr<7-#QLtdw4flrh+viu4h;zK4}z2(#2Q_am_#T+gg82Ziz8w(cS&LrXqpb^ zeF`Yq5UQBC>;X}XmT8N#k&24qY~qRvh)JO61U2sQa91Y;|hL}{2 zS?(e9W0qG)a-hTn-(Cgx8`xg>)*3Wnd|F5>9-s~(qVxl0Wz<$JlB+;v7Sv{F35PHk zn=e4>arpuyhf$Uy8HdnEOhE(-XnrLo>=A zm5{a;2sI^ued!qNZDPcrfmoJpP+8~!e?`1X#1jEhG$j_{>sIJAIo z<-!p!IJAJTRw7Lco=eSeSORtz{!7hp=)`lW84ewYJD+gh_=Q6&Mb5<42*+U;!kKt( z?INg`zFx$&c9Ebn@!Y;eQ18$Q9$d|Q99{(HJW%C_>ryiu`Vc8+xCblZnlhxa7IDg? zrUs%-0a?j1nEDw=wCp<%O%%)8LA83m4KGVemeX&&?vzMBIccJ011P7eHR)o9VFj{hQlD7 zccI}>kNYk(Y#I<{CDM&tmL?`irpBphpliDF3rga1GLwqqol+Bvf`fhHi;I#W{Y}*7 zLp)M71v>386>^sZa?1tO69yf-hb#u}tmYLfHefT;t~ zc_Pqt#?(rYGx3fNVA_RnCZX;xKE3qyBHkVhK4%i@#^TdEbb<%(=m4e{!8woM=m4fZ zM9LZN!3rN8Kn(;)Ph3HZ$k738nu!@5K-CwIK01IZ4RI66{4186$Q934P21*zEuYYfqBbO6(8nvD*i zSw+d{0Gd&t2!o_%(r-!!8wDm%69BADMQC&YO)JHt1DNI!8XdsYL2z^cQwxF70jwJE zc6YJpATTa z2#gM3Y9KT^fT@GB(E%*x5f~l7qJzBA0ZfDNj}Bm}2aOKECX8Wa7_6_1sv1^Cg3f>@ ztvZD0MC#!t8Jngh8JMKvA5TEF9yFc+?J46Pg22>*ZD0UJ6==W#a&wM`R$@UxYFn7Av-U>JTE)765o;sZ$JNVKhR19&~gVt zVGJ`6wAMU39ujBJ9r&;)gKkp>A8$^Yam6KxMJ1s7z3>lMfkOt>AyA#EMM$@&=A`C< zu45$437}mh1)#$N;A^45wt<8|n`>d4*TI5Nk3v*}y$fq2DuB22l@=$arxwFwAMRps z^n-4~fQ1-b24x5h#W1{PrGiiO2D=Gv6m;nz#Bnf-z%C|OUBb;sj?d1H2jyYVJy7Im z%K!~M5|d7IGxI>pbHK^erX({r6=SChcr*-5z?SF`lU$+ZLV7*mt}j7vplAV)>5!%c z+%YFj3sFO2nC>EWNDM_MQA1)VI>5mOwu_kYA{4FQ-~($lz_peQoNB=YicU|z5W+)Z zC^`_%Bx=kDhhF-6k?@ch4rdZIc7sFj&c^mgHol zHP|`cKQtuX-_1=^K}`W&*w-=GoAja*J`iYzYxfS=ps3oCr2r-B!Y9J8d_z;75;sydyv=B28h^~R~$QG&&Vg>>+bdYKZF$009mJl^~ zhN1;DtVdcLf^?AR6XFH}(cDFbUx*n9M6rdafj|@;#0&(YXdr4J5Jd+S1_DvdBW55F zRR;wFfhYzMF%XEN9(f=TCIRh{$H$lE7Tp54~xH~~UCwf=|p^Ml>NobZKYC;mcT#*YKTq8bS zklHBFAwuHyR^)=VR>gzHxiI3Dn6XzxD3zraWu{fegIthUQd$IyG}sUn$OZ+if@}<1 zz@uVB4T>V{LZo2uNE6Hsm;#WI&_t3{1Zk9mN5B-cklW}a#0n@XL9I{{wZI30iH{GY zxP&#yNw74vFex)VGp_{dd6)?bkj$542s^+tCp8b2i_p~=A*mrJYk?y~DJeCvsJJ*s zFQY(-0f|$fgnfM+RCx?|7olDT($Kw`Nph-Dig`-B306TXtK`z6vQ!*$`9&$IMfl_( zw~)fiV1#8>R_UpEsYQt;`MC7M<#Cx|jLl+WE2~l*;z`)VK_^?mstvg7jBprYWMzfb z5YUlW7={?)FvJjK2-cxnSR_Gdy$pEFg0q-j1|q8CGjbD?Q3Q$-^HNX*3X0ND_~1Dk z6cO;{(@185u4P5yf|C~#A5{9H=r2gk1@WDN;$cT8dBn%#Pk&IaLC(X`%K#0N!1Ox# z_&a;YgG_*)XOxtg9uE-=_KX7W`~jWX3ElyVMLf9#tDu<)7GcP#N0?@VPXt93hMgOL zDT-ksOey3rGVr--NGZYgS?WSng=?~1$5vb=$rtoiVa|jA#Mg8 zK8j1Np(#i$IGRDmf{rEt7s~NCgsrTgvm)`unN_Jc6+sNdt0X5s9TKDXO#;^%;5LSa zma3)(q#=`31l5|Hlni&Wf|izojsiphSc4W~QWL9&cq=PVWeQeH*l>u!AS=Kcv~(0; zG{~FrC7PhX0L2jGS{sPNa0WX#ia?Q1OnjQdjE1CRsHbt6Z30sbjePoLCTQK|zmGE!Y{5bO24<;Dp6cTvAk;T!Q_~X>h6og&{ao5%4GEc59Goa2P@l z9>ba;3}Hb6i5omh4UG^=K^X#HKC=KRh58V5W*g|tUrg`8WZ-@S6;Xt|1~M7sGe|h# zb1&EtAf=$_!=um=W+XHX;ZX{{H5_Cl)TQ{s03KZ6I3SSJ;BJ7YOngQgf>RL49Z)Aj zj*P*T;J|4U8XFLI;7o6zbPJXQ#|bDsqn*BjH4z!XmQuirAy@$bDH>or7!4^Fu$M@P z!UOpnyQ0!O9nfSoMp1${nBa*U99?+g6`a$dA%v1D(Zz5U@^D>NRuDZPKY|h#ga@i< zAmM6dg|m1^GJ`R`lp4x;U3Ze@ir+JhpS9AA=%+(t)}OfJD%9++Vl z#cP?Fl@%_l%&e?%SY(RVNK-2-(C#$wxia7>A=PM0vskQdGqth;T@nGlzpfao3KP6m znLw?=7RV+9%{InswlN;FjR~44K+umuWO5?p&>4Q;SA zj!1{fnIZSE5$O^v3$8_R8w_eYV3jq%>mdVt9s*0^_7GSahlikYI6MTF#qA-mG}uGX zejbQTsC{N=iO-`TS)4Hkk;Lgyh;(uZs9*&(P(W=jNSgy!>jb6)yZ0foIK2;%26-7< zd>UHd^`?cD6_%uFXn``$4NqAh!*D1EWum-Hv@3s9qYcfp3{A0?Hz2dXMH5y73FSLO zbF7}lTbLV~WB05%4$tCN4)rWHmz#s+QY&$}4u1)2Xofek%&@!P42S!1D+jqTFB7X9 z%|LQE+;2uOR`6CvhNjrvZ;HeHxRrz4h{OG`3J+V{5Uk-0@z!u4S!~9d;BdbQcJG?R z8{%<4o>~-SKY{dvw-z-t#_k~0Ni9TX$E_TX`|;G&Ao~fpA8$=<2&<_Fc#9xBr31kxHr}!U zPqro8zQ$K+!SXDYq(V54;xiarh~mgaD5(N^A}{(76fyH9@u2w&$cVwv9O1sfLEB2JzsL(9~q`LQ`z=#)uv|>OconkAfDip+d+YQc_Vo$PuMUIho*_C2*;f74)3^)RcIz*O2@Fa6cF$&#*$QMVpBRJ3TY61U9vzpoPmm^l4sXODgiy(qJ>% z#G9B~igchoSR0z-V2*+XBu?qfyb@f_&MnPJPt8Md9ELGiLk3|ve$x|EQqWQYspb=~ zo`5ti*BN2X+QXyF$jYh$Te1R)=cMLglR}=}hMNN#wm@4MfGk&t)gUXYLXaKk=^rJE zAby4@$;>UtL1YfJr6#bX0UJL=)`*nBLHZ#|G>My=2Cc$Eotg%%FNaknAU1fdxu*;C zjA>BYO%t>`LczucW!br>3wSX)LuLx7EJM-=5=IvStxsn#sBm*bk?;={ z(KTb(1X2yP${f|I;1I_US3;J76@d)ZM6n4jj71b|8}e#=A1BD_e^|R0YuJGmK`hEC zMllsGgGCf>UjngUYZ;0&5)GlkU?!5dk&y{P2E;*@Gc`k!Gc}7xk~6kI z(g)%o$(b4&A@qSbU^z4Jyj*UIDcA{cM}m1^1;*eB#Nv!ZkTamm1>hGz!1SSu7iT1b zY$z>ANh|@cD}V}MQD=xaR2HCMYAr%ttDY;KqRGFtHf`Hyy(>OJWTu zEdBxqb}roM#i=Er0uZ{^46XD7%V04Bd5{_5Q!6Xb#kZ)nlWMe~kp*&x99emCerX=^ zTnVyVSz=DSu@R!?Q;jx488t*#Yi0sg3mpV7M48b*RtxqLJkTJq2bzdi&{B=YuE_#h zv|{TF!>zHfvdT>{#i0$9?r}>Q8DR}uQ1=>~Byj6Aw!ov))DU?M8k$4FE&`=zXcmR0 zb8J>2ch%vhVC$+QOJYkEW+qq@g*j-h5=Wu{S(BIp%Ddp01{IhJs?j*j0VN=?&tO%6 zf@(DO6ohR=0PcRQ(TJ_9kI(_h2UxO=DIVW}j7)^ISD|Sbd$z$g7y!2#d9@-!5KEsK zSrQaISR8AN$FZP+1E^!6(SY5tSQ8z#5k0tjK&u~1)37ByPyvqF$bG2Y-4(G z%Rs9nv0Daec;d1QWMpCvsH%mO9{ITii6yW?86*rXri)WcKr8g&wG*g7hh{AW@OcC9 zQV68M$OL8tL=vSWMp`8Vu@h8c#UrgRfwVobH&$VCpqYK>dIUuApN?MqgR%^UOQ3Zt z!biwX2UWu;{zBAW7_~E`LPPNzcuftGuRzHTd_XmPoga!MXh$X}kWmD2EjU0Z0xdKE zH=C>c8aa#uTzz3( zMiA4<)!oxC-rva!qy{A5>gR&O4GQuP0%e|p)ZBR32}hvaOi&j?HW;8QC{8U&Ni8mc zl{O$Yac2U7RDzEKLJH)>G!qj`V^HfFn;`ORR1#b%%48Zs7?)zSoma$YKsiB}7!9DE zTJQ}A$QqIhkaq?k%cK;5YJ=o#M0LM0@1VPTN@R+o+N-ayxD?wcofI}rDU1lT}DPZ&=kUa(RE_#>4 z$P}fahpfDy1afZ{QU)L`3xYO0fU*~?mXj|Z=Y1J|##ZL}Io`OiD>JuuMiNZV-a-Ry4#M6n7|S zAthpDE#5f9!*Ga0D+zFffy!af4xIRuqNH?KlMGc5blw%H0Rk<*VU-H926$@{5gbUZ zNrWJgduqVjc~BBtup>CFf!ZtJz5qB6pyo)7%#c(RUsRkJUw||@0d5DO3L=G3QnG1s zYLdADO5DH&k-HfPK`X1g_@vAdv_cPNkdc*D0X7Rj;<&XSk2oXS1RillBqe026kOJ% z6yUZe1(!uBcx=kVr707aCeXSCY=Hn0$Kg0bD=XxUdT^hD#6emJqyu>70Y^1rh72?> zgsK&yl0ZTtAdMxR=^$>qgcQD-hzc2;baB{=Ll{!T!3uDgeaQa8Vj-q7;wBBio8^!* zALz~r&}KHLpm-3|Dbx)#pc?P#7XTX4H#9T0Fj3G}Fg7v;k0>K6@ed6_QDcFr#Mj@? zA7mM_HYZOPPX-Na)+uO%rX`ToLaczkoH9s2}(o#`uuP0Jxq|Ki7x= zSLYB{7nnAXDbCKp$XrJs*Psw&0S`w%mtYS^Z@4l3VAn>ux`2k(LCXw+g5tpjc?Nj6 z2E_-5dWOK&g2nxP1A<(G(f#Zef zKTnt{kR2YbK0f~OF8+RSn|(ZeJwxJMBb;4bT~Iyj=IQ4d?12yqat#jkb&dD+4EA*l zafS!Er(c+(kEct#qmR3PkY|VoJZM4o1$(;tIfjG=!L17q^7nI(2OWDE8tjOOCO`jp zXCF^jzmRyxP(*Bc`ZE}VlNl%`gIt}%;@uoW9DU*;VQ*v#Sp^Uj6dw%gFCojB8iJFf zuVX~KGg5GaW6(b!B;M7}%|FQ5H9puiD9kk|J|M`|%{9o?&)GE?V-m;!oDo2pK#2zw z?EWF1jv=6wi9P{j2v-{7@8cTe7~&d_<}q{~MsOW&j-Ed8{(kX}J^_A+Fh*Bz3|0@y ztj<3E!LBZ#tY%;U4kM5tC>(-Zogt#&5CDmSLJlqpUS$Ci1*vrm2!N;sukZkgg4Du9 z4Z&F+6e01h&Mx2x2Xlgg9YJXd%yxBlf$)NZeY{;GBjTZwFfK@=D|SH)tsu47l!9!B zTjJ{H9B=I68XWKJ1kTmL!9E}%N7rCOBMVGH(AXVTmF~{qgo@A(Qi&?)?BVF_;b;U7 zh2UTx(6ET3t0TBjfO3O99ARM(k`4B7geFRaJZN+uQtW~{94IQF0#FqpKEd&Rp*}wG z;hrHL5Eh6Fi65{VKq`WQ9g!6Hx`0>6U`hmgfTIYj1jvb?%ao0sK(UCTB*@tWG_x6x z&0Lrq$Y_vu15B&I@#5;@3W|n!xH?RiIJyRdt#Nj8hAT4y&&r~>2BZuWE6B=>F>M7Y zgT_6`G`RP`$pfE(aFyUF1*vrLh<6DNh6FHn&mb#>#|4H`r=WOPuxVVF;MHq|bdvJ0wh9?&n4^W1JcnGUXaPoziiR4zSO2Op`Oex%{Sd}9A3e}|; z(TVIQ6f-eYf>(CItcS-E$a)N=;L;4H6u+t9RbUXMs4m5pqQJEnR56ON*c8Llvx^7r zkcA~d6Qmde7nfM045r!)DJ)Q3jT97c#Ymxnni#MtMhXu!S7TER&)OhAqJ#)G)$sDh z#Unm3FFz0BM_9Q6Ds#Ze9NE1HWf*x3tQNbGphSTbC6GJ;uK1vlhcFhT6v?d+rAXdF zawteClBw|Ug_koZ-U6vcG8nEJUVwmWJ8&Hc2?tPN4=TSH3@V(VRXWJE=*nQh1u0&g z4GiGf5?v*h5OX##fM-o~t@?Q3p?xsERPW22VGr>ahC@HQAtKHH=7u z7gMMPg8~4W!K&VPks}od&TEbHnMi~xrD^xYyTzJ~TP>s!Oc;@$rkULOX16W+`2rnZsRAVz6UPK}{2SEg zx_|>DO5h8WL(+S9BMCySj6_8Je)B{f~ZjL@a zPL9sr@xji)VGITpre=^aWAJEQJb1h+-p@b8(=8G-?f?-*47JAlx(35W1R-*u@xvfj zXa69Vc<2Z&L>wvx8eVnt@efBB2D-EtK7<+%8c>4{JVNxr2WT;+Kvp@s28DRKc{+pE zxto9!5kwpEkTi-KaPbLIgCrgw81co$bcPmo>UWD1c1 zg_4VFyeoJ~i7B|!g-ZlQg2qN6GT^2hL?$4}Kg8eJ-v>SKq#684}50j-=hwFT^#-&(Q~Jr&ADQ02g#8LQuT3qo1>@kE;uVC6bvKBdrKMND~Bz z0dGS{3l-v8KmT~gfB+v*OnUnJ#lsxWU}yy1;8k3l6Q7!wo|%^#4_X!nJK+a3KMRs7 zPAw`+Es8J5&&f=#1Z~8EtujDN5?WZMnwT0|8pj)g4_ZRfm7I~EnVgEe;|ie`e0o!H zaZXWcay)416J)9waY!1v6nNUdxHu;>A3lYQ%?aSsus}{o&dE&8gD+=<>5fMewz5ji zONaRt8VoQWf|mak=V0o{&CG)eW~Aoigz+ zfyC014A`nG$Rr+`rKv?FnQ58Hpsjk~z*NxE!f7Vhu#(CG$c_VSz67~EJ`-}mJ2rW2 zfsfNVY>F}0As`14re{bryf`y2Jtq}3J&&#t$!O5zEurYf?slm0kUOt%I6O5Oo>bAI zDj%{i)XEAeZqc0ySCd&(oLEqr1e1rRQcz|sC`yZmY{>vgmgE%2gG4|(0~A06(u_DF z--<_u6ez~P#b#7vYG?8qTml%J2XPX;arT8Iz2DG}+MZcwIzmXFZd2U@CO zbv0;}Klrd`cq~))|&Cv4E7_I8vDf9&f

cWoW{Tu;5GuA!6>U~kzIvdG1i_3s2>XM*d-PhV{a;;9GZu)1$5?FauWFN zTWFsZWK0sG?T^h7$a_9ejY?0>1vTcOMx`g`;%l?wb5cfPK|XkQAJnL1umAzma7GL^ zPoQjnLihrQ-w+K4coPQdGI;l&v~UNtHF8oD!TTUkOiE2GBH&HzzOk}GjYqJ%$csoL zD=Sb$VzUQ#@IYb+M=r#jBN7V=azNdFP8au)|L}YGdm6%+TnU8$D60%Pdb5e_NwP%uZ@{3bJ zjhWQUveXnD;$L{gMrlAoNP6AvofilJR+a2cnC%drJ0TH^5)n>ne;C8;U#FdaCYSWuK^ zh_!cWZe;};j|80xV2XTbJaS}06@aF5vHLI+e9koZkZBzD!&IbT?`$sid#qj8`h2Pwg2H%N|vc1T+Ym)D_9 zS^Un28iC6ZP-z10z@4UwiWAF<(r`u`&T%!YIRSKDD|AFT6Kk=Bq5xNM0y+Q&(g4Gj z)Ib+45E#NTv$D!fEG_|!a-}90rJ`+c2DQRa&qslkfhdQ|zy-0kbWxAQhNpFu6R{DZ zpw1QOSVBk&23H?g%QZaOvA0C=XaFS`EcqC8uno?EPtdWrsmR+F5niye%0@ZM6; z45JZ+qlP!NvdY9=ihyKsl_FTDHBb)lhPw#$xNn3o)`$cj_6>>~EMbMycq=RH(Sb(; zj_5$l%V4*^7<+W!vIy&7H%`Uy5d`dZV-t-xva(9VJ{N9cWtD_=q{zg|DjoUyN#q#8 zl60^)zd>_7n5hhV_XlgU8!hE`<)|mJBZRRgF=J5n$GF0V7)>}r z8mF7AtWvPYjWMpcF$NWtSYr($gR6`NO~+szX*0I6O059(JfwKER_1N9^Fyfg^T6r)*)310$TV1ChZMJD_PGtg&N6 zFm{j+>47Iv&>35hN(0e;$}cU6hqr)W3sXQ1D^v+kQJI&DKDvd_2$Ii)pJoHUn+=CO z$VW#YE}24H2L{{u4XI)gXZj`;#e-Y6sPf=L4v?CnNbNDCLm99uK=v`H8H=PBpA^Wu zsKEi!3~B*FM_5212ogdz52Oii7@=u^gc8QpbV=X^P?g|SlHj}QkeegeLna{X8y@I7 z=oKLGi8-)qq9K7|8IK%lpuj1{p0YqG02VB;g>0bXL?G>NNN#{d26Unvt{fUiFk$e@ z7-;CDYk@D-0nIBx$1rg#1uqJLR$P#@0(S^_P!M(52z;3qhI^o6k&qEluyvrx=lGJM z#Ju91#FEq$P?Ovs7A#YogVW6r{ot-X+#TR$eF&d}dasCuYM2fI4M)OKCZ;{m1sd3W z47LfX0@~Zc?PJhXDfj|s(EKJY$6~4JV9NU z0UD%e3ZSC#SZiI-eGib;YKY}zm@xpF$dAuR%uC6ER|=S(g^clnIvnT&!{&IB30xPr zTErD5@bU?sqAN@dV1*Y>|CS`ehNZA)Y@8ZF_vwH%<8n@NX;FL%Xh1S0wF0Lh5Jd!} z@%kE+G2)%Wa2f%XC&moSBn>L4pm`i*4k80W7v+I!5AfJkQZix~26De8WV{MCG6`Dl z7oVDkO%>8Ll3-P!F)V19BH4mvdIBEJkd;`Ff(tQyp`cYz01Xwynp_2~WY|n7EO8?F z5xmY7UWy>u4jo>D8V6ln3to?mSo;XdT#$p76hLb#Fjqu^ECPih%oM2k(5$BbKB^Sr zaadCUG`ELbe_)7XR;i!{16&(O8gF%qtQu04!UGi^i%9W<+LS;v!r+=f-h)LsF2%)} zRjKhMsIsv38gj^DTgD8ZZv%}uL&6GHr{*LUm&B(Q73ITPq%gBU!44~}K(z!c_+es@ zb*!kBH!N*H;|5+KL!%62BxK46)eZ3MP*Q}E9S}`fP%4Ky0zE=eU4br(%^Ah1=!4*x zPJ*=15H7;r?p4qNISku~CT61xtP(WvfoU1MT?1ysgN7g#po{n*iebLOmaxHMmC& z0@nuSp>|b32X7$)034+7e2U~4R0&W9#?oYlYXr&T&EP1;;mYCgYqvqSYe2k->ULOW z1)Y1BSe!vo4u@tTP*#D>+d#V&5SyWsLy-9*NPxkzI7kn?1p-Y*i2f#0AZF$vbznhZ zgc^nz(s+XqSvB?$L}YDPK%oa8zFsO?iy3@M8gxy85xnIL4K+}~gVwl*%7DTKG{Oq% z142UrIoKd`V3@%PDzIV7p#>tyB=D+nlmY|3J^(BQO95KY7B$phs0q;4Cb%sPFSD@8 zVa@5VvKPe^(5k`w{9>fl_K?(q+hVk+g0vC9O?_yg4od8(+M(Nl5IGfxQ&RFlYoRN^ zF@-pakvIpziwHD6A!5dLG>~?Bp_UmV5{9tq5veJG?0vX)Dg@8JfD#^<0omCJ zbpVno*m4xunY`J_#fH${A(9lnDiqaquzY|~m!mr|F(n1sN_(9G=`!&Bc(0848j>?u1}!Lzac^R{tN1sqv24nCc8*sHDL7{%2 z13JLxl)yz@eFH)w?Ydq@F(_q&_Ph$3Q^>y`wpAHR{L7a5LU;;iH18$<9 ze@MKuzh7`jP$=@5(_md7xqu+h5zU@q;Dc7+x&j=7LOdOP;+-NxP$fWKbMp81adm_r zoeee$`MeakDImozsOmsMA)dadh9Vt;f)b9{Pmc!MhdAju1nF#TuoTFOVED<X%avNi=DvI4g`+||)LJ|NV|$I}_4 zh`|hez6o3!WNt`MXfWuMaWilTfE^U#2tCHd+cgptZlL3lKp_s}x`L1Of$=~mE;ATZ zKu$k_34%hF!Jq)rE z6l^_;do3X~aXeTKM zV-~DOjcE>KjDi?5Ant+pmLLv8>4>5@5H$2aobxap1=b6ii$?9k;tMZKLqI75oR%RD zhb0P-kOJCl0K(zOT~N4JL5T)(_Z&)=0$Bh`Q&L&>)+!x5ME%Ejus2JP(w*p_w0>{ownC!GF(8ftWHklIFqk?J z8+?=mEM$>gSCW~ViWpl>NvteJ@QPED^Yc=`Q?y`pisjWU$}LkEY3%^0!J~4%caN*E0K-C<{HpCUX-hFh|z$u+l&|uD7(#&HK6V` zLzcm^+YDJ6%SCL+(x`j` zp6|g$oNBbO7TT6LxSKSaV2W?xzk$_P4Tf?nFy#){ z$>!ykB&DY17p2C7%P4Fc41-9f@UB`VQdLTb{f7i+zkDk7G#ak0TWQa1xJ{I5(vgoRmeu*$~WMR zX^=((wve;30yQ*2MJ=dFk6i_5r5{KY@(yuit8t}yGu&w&lz^}oJD_k%jR&PJNR5Ks zNrdD<&W(pAeNfPW8(Y|of+>ZpYRyO4-iPc^q{B#FEYmN@Ra;`^qtqp{>LX*l2i;1J{+!0$p;mxpdtvDf;_PH zc+gA?ekC|$lS_+=K*x!uKn%j6DlfI7gn&yxlOibu)PS;Sd}>Y!xET)RfX5ne7M7qK z1XWmqE1E!yCULkMx_%6Mw4ojz2ahpRD=Qpn+0@Dkban^0g@(LY6Im;c#0lC)S&~>% ziq#L;cKpH3G{IeCm{?iiF4>H&tgzSD##UC4#THmX#Td6`M!1`uMpjlhybZdkJGByg z!Vx!NQ{hdj|{RTzDT8xsM1SdGHRbC+Fv-Wv1(8FgW}Bxp}&SZ*Rq`At^PnsJJ*M22={@WfT+;by;N$ zR2T6YK*q;p=H;ap=^=04G%`yuGD%8FL^<08E{MEK7cPk0FNF&t?=yo7npjyuW>65R z64(eXGQ-%)3i&Q^xY?ksmDubw!l53t z*$QPYW;?kahuWS?uI-?0Az=TL6?7@7X^EvdC1mL>09}a! z^ERSDH%~M)GB>a^KxslD1g)%)&!$5bM?UTaS-gsbiUyJpAufZ4D8gmQMy848=B7y~ zE<*^Sx(rzy*=5M$WVoy-GdC5UQV~u|O*1o1NwG9RIrb4Qh}0peARSTHp=N=ZpHO+)c2ToBo-2tib@B8ww? z6h4 z3~~tA5K0_kY)Dy%8XHocUNd2aQ0NhGU{DmI#*l@k@uWKhG-MY8Iv=n&H!&xN!~_b~ zoRXOypP!jRu2#@k1UY)aOL60qOL9wdjEyKXz|4d~1IX82keriSN>;c-0-&J0$buZ( zb5lrdfrBGEH^sC#Baze+9-_50rz8`^0y`Jcs4*}zPc%$SL7l=y2*MAFz^22>DmMlB zG(ee;tndV7+9c5E8?nP^ z;DL$+bB(4>Slwrp;-&`FW)FykOy#SzMJ`luxF`l%)`eZnCY;1C{IK>MqSm zOoj{~lAgqJOLNFi+sei>qHNJ%XN*G*2+ z1ZyU{3<2pTy9|M9Ca;1tHjD?AA<)qf5=$>*!+7$`5RhiF%MegMh`chy*f5^_GQ^1N zGQqND^diYK!n0XkQMjD|#RVscDIZentL zGN}z8m`)NCMp0s33dF{gqNH?EH5VtwfR}s~=YYx&(2ZbZngAPbEdXyY28|0+#URiq z6r~0gWtLHD1j+SC5j0>y!-^CK3BnKxf&**_`9T5JPJS>L8^%)}3~)mz2?mfM6a)iE zI|adDM2%p88A4Go7{!C`P$e^CWEvaA7myzeW-uR6P)>lxiy%pgl3)P2go4xn(oS|T zKwMv(nI2z|Na`pKtb9S3QJP1(DWFwvNQW=vX6BU{ky?d-%qS>IBQYUCb;Xl6bPLlB z8f`Q+BhzZg4e4ZP28CEMbUiirGI{92FyebgAopXKQdCUp(iONd;H&A#^$A#WJgokP z9IQ&2S!tytPujq|0y%PmOzR<<;a*8hEly4%b;u3XA;@N>C+AYfU66A@sbf|O75zwd zGDZt`@JcM|cn^B)2$_a~W-?Mqo!^EffQ(}3Q8!@A5%WBzhL$Eq$(9x z>qs>sw)hkwyh~q*1{gMN}}OlyoyHbCbb$&BeeD&4n*0Bq5!_ z4FR2jpOl#%pPZBoTb)m#F{ybZClgH9ki2TG7{d%|c!yHIBZP;=mj|hWDdn)QetKjpG;u{gB?R@41*1!+&iS!btow{xdarZl=}o^3gup*LcD+m zK`9LpNMf{26qW@LQz(rph$)o% zsKUZ5FO#C=4>o}su>?1WDt@9U^+B#zH8LQ5MhB5C!57((Iw6FvozifHI09q}C4mYu zrMR@9Aisz*|CA(>y1oZBJW3LiKwhCF=YYHdHHMN9fj4EzTlb6b7OFvHXGBzE3Q05v zbiP*%hyeAPz-RG+I&$O~f_(BCSU+MA#mLaWGR@L56=e_wA&53efh>VCNP#Rt(jW!M ze-KYX7GOfQnIPO}U}l(Nm}s1a;y#2Rn){F?P~3+sL8kj)2f~2^koe9G!h_Il_+b4A z4_X*nni`lS8=-g*A&BNdWC;`xB1>czFxWsh#p^?9kfnAEN>Cm`REZ%z-Y+>Rpg6TO zB|jt)d}wn#Xo+%qW=Tv%Qhr5#I#f?gPG%B}nVFZIQ<{}{7F}QXMY$}mAyTMf=-w+QMw8W+z2qPaOfe;0sZB(2{lJQnnC?`W846{PJ>>ODJkth+OC>!h$!Z=(CI$WcG6o(q2 z4aO2<1In>Y$Qn?O-b0qba&j87G?rtVkfl*iPD7SKJNO7i3iT)vWGT?md)UGn95?8P zj38?S9b}Y}Sb{YvK+nv>7Whyp@CHmQ_Ck*z!=@AEz&p50(Dq`$G8In6Xk{3}9IUAb zd^#RV*+z^8?1=*7I6Y*e@FfcD$LS&K#*rvMfr)ai6|x>k6^DGB96 zhAafYJg$U{c}5Y!i~Xg0?HYA*fNuq z70S7HIBY^ugLXC^vd6HTjfX6ael{Mm9G0{3kfpJnjfbKDa-<#l*?3r#;P4~vv+2o;Su_&k6Av9sH`*12oKP(Sn5Z21i5LEeL?-D_rOR(Px>wXp&=b-dH zlT3_~%}vac;ti2w1R;vt)kKIwE}$sRfv#+chaNJIa{W9)HRvQi(Bw7RjW@_XMJR^v zhz4EHK&%Z`R>hDD?m=g~lcf=HKO1z4oj5NMr5N2yL~6qH5@{My(hEF*kp~pug2*ER za6zn5k366NSBW+0AP*?ORU#KKa6v&rN?T%LC5f3ixC}1J&o99$XAI9Ih}sO{ zA7jw{!HJp32cKg~;tVchE34vcT(&0W}ZRj3w#+M1cg#iiKWnkZ_~8&fEf zsHfecOQoQUlObe{@P>{NzR-b5;tU-loS|c6Wkp2j7+G0?8a&CkQZrN@)EmVb2ZmNw zkfl8F;7iqTsY%R9&qwXXB7z5G1o+ArY-tB3i8BBUuv%$=H^>d}1vyL-w~aW1+<>Sc zH?XoICM_CRS>aBLATzMn5QY#b9BI)KU$|J}2^N?fu28YW6)2XF1coaCA&+~*lZ1tp zRbpvL26`(FSsqmW;Yd&xc)S6V!{rTg^mFpzcA8sRWr7Z_#*#?Qt*pQoC}Nia>B3_j zNGBd?&{e!?MTzNnl;q^6#}lEfAT_lpo=CNs70AQ9C}B{6d|n-@Oft5t2nrmWrsd-_ zEx!VnX_@)C`6*bdUQiU}L9P_W9u>tIr6no(<$3W%smWzH99xu{oL`gzPI~d!t1Qs) zERrJ7eYx1JgWcSW(-@cn+(uwC7^Sm<90S-DZca#l_eR#MCSq-};nS0ZD8UqyB(xCK%ikGqtHDgfQ_iro%q7Y#H-gu~0wUNFcz`MEgM zKusx1%uC6~t)>`sIW!IvkZ--k?ox<~0?^r}c+CK-z*Bh?rRJsLieAWwTUusbW^qO; z^28Bxprc=dfGmg2=_m)>6IP5ieMgK2lxYTHG@wi~AZtiQxrzr_2Fo-9vNV=CU1Vw0 zfpugV&_F%zY6mQfJ3m9>i-01~Jy3XT$VttM$8AGKaZxGOZk)N5Rbn!zAi58?F%$*3G8$+iJGBT`bqJcU18)|>J;GpSWtE#) z47$IsI5oK_6>C9*ygmz_piQwh5K(XPAgtKRDm@izsfg2fD=X~j0FMS7Ny8Lh^B#0z zQfeW#h%*JxSL2Y$#M(D9wX(vKaX_-TGL8w>P&UEdkHM)JXDH**fjyM*XuuK5c!z^Q z1HRZp8J9&^N6c|5#uvkQG$p2Dt#VAPtg!b;OsuTZk#8h|r+X7CE9@x(G?I)h3E>?L z1`X$84=rP?$;23YGQp`BUufacgd?=@=t#jHzMy-HuvU%6ph60d46f4A7+3HcTUn)6 zfO>G5CGnnN*dhXNKNmD|j6EWZuto&xB4K#yz^NEtMBvecBO>tVz!4Fk3!$(Ew-L^W zfXLvA2+&YC){@bPU_=IAHR#th? zvjnjjWQ2Mp1+umR)HW@$6mo5XB92=N$~rM*Jt=tXNx@}NN+E8WGI43j#HGp5$_lyW zhPw_Vj>8^9D=XyDM`SIjAT314aAIBx%4EKgiK(HfQ5tH2hY*A(Aw*XOS<)LRj*-QY z3kGEIl+5(h;*xmqHM>NwKLDTbL%izLToeylm>VaXC8wZnr$7iImpTYhl;R&Dj7u@v zcmXjQP{s?0(SR~ufUE&^yZ~7S%Xk5@G?wuKWNFl8iO4db&OTDaqey`gBO zvP#KB9@|2e$u7=Eax1b-erX9>4FH!#UQ>Y(1X~kd2D!u<5#Y!QvWt;#Cqk9UCptfY zPSHSiw6R&LQL2S0s_$Wf$g4UGVS*?gfC++HWRRVFsVVW`dm@n=j&Qxk;08FxWsk`6 z=od*M%T?s3rD1bCs998syy5^^Q*LPvYS#))GBE{tSQ0J?8WIQHDu&HIBh*W>ko8oc z<`}pXXbu{eafVh_$dwMV9&nvQblOfV&Ok}qMk(f|2Bt=+2Moalk(cMd1(DYQ!3B}m zx4;FF69-%nd2JC~5P5zUE@%n4!xxd(k!6zeOHqmlWVy1$oOom8#tOQm8CK_l=8$s> zkP``9p9QvR5f*e7=yz}+YeTz(15FC`4i0ollsh=kBvHrC&?G^3a9{~Gh(mF?2sAx{ zUb?`|HOCnjprKV@LBY(y?{Q;4T1lT1t`2Nn{zEVF5A{ zy9*E<4=kz95NFZ>m3X+k3ohv-TxDJMTU8>M7RPBu?AGBQewH$pCk5TeL~*Kkoo z+DMJ`$3f+*`|;i5*M?17%bQDl?jOA?V6LZC?|Be#(da>xZVk|>rU z3`G`~RiKek>=t1SEF(~s!R;&1U?J*`A%r7Lt*k&x=Zo@7^HPu-2M85dL)QpfRz%VR zS~HZ2ay2D9X_yeS5tQw4`v%mg!Q~rcf@ULUT!ec;*$lUhpz#!3HX0GM5xHfCuo0Bk zaN7vVrSVB9O}gH;yWx;%uVKuhm% zdI&6u+e2V!93Fzop)@YgY{l&%ux4ByGDL2O!HqP;w#*JiHW`;UL0a*|8$=qrH(_$v zy$O-U=}m|}J(4hJF;a1M9&!f?NfvhzVrW4q z(-~r|Ck*ix{vcUwzCzuWjBp^z${-|RyuLEW<12H5zQS6|7-DO*A>4zq2@^>eM_l1n z4stn;xB|@u;wT_NuESr!fc6t$bg>Z*MVUB562{?v+{*E|A5R4davcHpW33_r!iIP&VUR2~_oI$*A{>e`*@7gD*Zp`ZdXW7D zVg+kOZ-}>|2g!oYw82)tf#e9-h_#|O#9PsWWO3RE8mTVLjmO2fI&tjQSrRJQuvS8N>mUo%M{C0)Vcy8h&IoI zEP*nggDe3#dy5jMq94OWiCK{ISkR9gOHN5POg1+}JrWHeh~{l%2^4Q5OHkx(P`v{> z4mCd|72T<+i7BQ=CP}E%c?dx?ry@(BI2BofT&H3=JTDV**(vF|U9|HoDRmj-SY)IlC8=W|6~hj3 zIUOZVgRG`SIT@7_<3Njp!NU~D$F)+)K=8U{Y9tpVN1_}$PZf7k%Yop*GSKaq)HRSw z2@n*75EmjHq)uu0K@Fs8Jj2bTqQ^l4ZPZNP5c8<&ZJ3c%_BFNAVsZ&JQ+9F*sF6cO zw^1=oQ?(ue1Er-5*uRh+D%49dASY6_E&;icdd{Po zNhsHeP#P1UYhS3;!UE+Cka1MZ7a-%PSP+1XqiPusHIXte7w5!)&WD2TdPTiGl8pGp zFb?T{A!-j6=GGi8{u?ZyutCaY%PnQO7vyxej!md^~uWdqDxg)g)MlkYHEE zK~o;sK+qaV>X=7Cfd@;%;QgV9gTSb4A~n1Uy6q0>vO4n92*@DF7DdW^2{sFHWheQL zLb^kcd_xd77?N*BMsYkOk%9vUG016QY-DO?VS+k&j1WW{LPM578A3yrAbSW6nrLxd zcxjnvVv%N;WQj7PiV#F|DzXHMQ;{Voc4}gA2I68*@?!_>;!@~lSa4L4H;4ueN;Gr9 zyJ%@(D%Fidy-k*C;YzLI0WDY)Q;Vrmf?*nqbcraXfk1g2K@T1QRdQ4_4Et@*J=xBi@M44Y60XF1!D^n%Df6S#|UwEIr;8EyFs07gUI(0>@IpxUmztFd<+-m zhT*u_o^)$PB5J%8U);3#b%ihVhWRM5R;)av3-Zs1#&|rc??t zkU`W5GLT7NFH$MU;O0>$$Y8Ajs+4DN!>AH;aMP$5e5htp7=(#=DKVh!sqraAN$KR5 zk-3S<5MwBrnS~ibzB4lON@742Qf_`qL4LUrg$5ZL#h2vf=fUrZB)yUZyT{llzL=7l z7G_9MYD#HxD&>C4%gigIWbp>fJ-MYhi76B`MUc%&reJsuZcct)Np5KlryDO5;5DVbDBKA@&{Dix9sWH}n;p`4PMoSRPt_atSO%o2vC@l+`Z4Na+15*nIPrzA8qrA|o*F^BS!5MmDHC841ybxJ}*(|C$X zLeR}4F`z?~!RtcFPlIrCk}@e6F@TvuK?4kIL~dzLNhXK|_7Ktxb()cpp<$8%%CxTq zToB8CBxK3l6y%*|$TDbW%b-c2p1y-FiE{c5nk4G!J7|)i(|5?4(FFxe48>C{FjK%m zOujq7M_b2(mgiE(pyV8inz>+KLEHr1BV$IvtQfjkl#H*Sn?+$@rDUeZ7iU&c(D4U5 z2xLrtCI$WD)Z`fOLW20Bl0@>o1UDtq7&1>3UzAu*P2&=a^C&2iP@D%Enx&%iz{XM0 zc}bZi#ncEnLsRgC9kqN4Gmct51vT0;)AOk4JgP+6TE(YR@Qq9Gs+DrD9X%D zjn6cOcnzu5Wnyk*ZkC9;wblYAh?R~8`qK52jMixAd|cmxsV8h z`U=_=M)=A&**MYM(98toz*4v%@`iVWAgZsB#gUI+Ll#Hz6|zKu0rD9_C^DdHl)#6+ zQjkmwj7-hqb1|aQB+0u`G6VkD2u(Cow z03BH$SPtCCK$J$v^69C07>BE4mB(cU@@YtLjmB11rPv$`x~2x3IBJs+>T4q$hJa2h z#%2g|Qx5JDLmY;H8>ob;FX*)>dKm;8Kgs!dX`lgBhT@XMlFa0?{LB<6GdVx6xI`hT zC>}Hr1G)G@K?`J_duB;YL{ff*zq?avVo`9gPfSi`64b_+;-ci3#MH!;nB?SKy<~=@ zqWI+G-1wr@;?xotCpkZ_B(*~Pwe<)~aC4t-y)ta7K0yeqIDu%eANlmPP1WjsUMLf)6 z5E~_AQu5=|GV>C1K&}EwLam7}DJsna2P{Ys9I){PMXB+Li75y-gQP$anyR2x3=RX3 zKyqS1Noi3kswxyKlZxU&3Ndto0|Y7wwh`tgFeknszqkZ!KU4{7@PkZ*9;gQi`=p|H zPzr%0DY!|cc?|iviOKQBC5c5P45fLXj(Tc}LS|lxLRn%CLrQ*pa#Au#L2^cEUN%EY zerZxpYJ7T{p^*j53}^_!xXG|MM-4K#Fvv{M)uKel8))AQIOIV$6M}B`Oe%^8G10>i zBnA#LxPRek2;ym^1Oy%lR!GkPIU1x7HS9nluml2PBl!@-g$66k8JPYBDT3-j1OiA9 z5eQJt;Fu&Tcf(5zV!|ym4^m;+R9Kj0=9Ls>=ILeFG1z40<|24bLGiwxe(^!Uj`6{s zQLYS5LGhW!7G@wiF*n7`1jKN6c7{^%rttD>T?OJ`}|9_l0rYT|->`LW2AQB4Hw-ex4EWA)daj4B#tf)4&BEDCZRC z!Ipr4gwjhgH2gw+d~_5T88tyl8In?}Ksa6lBv6)^l9F6n&H$xBf;tL}OgajT%$i_T z3`#L2Nhwt^B}xiRj0#GswlR51aMd75s7{yy9VG=OCIuxB#jKzNQtT8IAL1C~?ivyt zA7Nn@9~uDi0kVjTf4Cngbte^ z#t=!V02zo_=Nq42P!gY53>uCCNr3$Xbuq|3xEP3|Pynu6ii#6K%Hy+BE7Mc+;=!2% zQ5+Y5?gxieFrZt+lZrqazQH>X5=&A+x)ijEv!MZzom83zmI7G>GPs~LDJL@-qN)H@ zRcR7xfeNZX5gslmO-ii*yAL$G0a=C$_FPG2L8?M-fw3XXiu}aXf_PAo2`|{t+zhLN zAhD2>n3S5s0J1E;L;=hJ#U)H2rMM(MFR=nysJJK@%mtN6sU?sRiFkic7m)qA>1l@X z75T__3&WEPa#Id2Xadp&+Fb?RsaRZ|S(2OqZjNN;AwnHqG$U2-pj&G}7pOp;UYwem z0={V&?(LGC;&||OG>{CqLQ>EIslt|?!6_aTLEz9U%>#uWsGT02d)>b#{(Bf>)arVqYN>_igUDn3|u{|A49OoT%1}`l9`uY3~4fhS~HLq z2qFtZ_@LC2nV+Yi1(Hb1gthcRjdXAy2PUr?9m|lJmy?+Xx|R^iAk?4A%u9}e_Hgtv z7?hyQ`0SK4y$mG;AJnV`2{;ACySX}sga*0BN0=H|g6r{kXGb3&Cr4-GiwDyT3{2CK zlZ{XYyAgs`R%my`Axo7d=9H!~!je`M7}$FG$UWuC)RMZE=YLB-bS+f*NVlTu(x`VBBFmuN zVTdAyR{p>P-^vQyZbB+T(4^4rFhn*K{SHH9IkfbNEQNYA6tWC4cNijNxcCZF153RO zP_xq2&)MI_6`WE*y@epha0aEIU`K_3AkQ$z5LX3n*GMHab*|3wU}dh(_*4aWI|o}Z zD502x2&}Z!R8vFCG>drT)md;s%*90vw3~y zG;I-|f_x!0vKtZ$3R3e@;#2a_>Nc!uaM*w=hnZVhW#GtRpeVqXQ$V*~WTxk(7J+)| zII|l<6}ShNi8a=cFTsHO3fmmQD`0}0^&b$Y@U?jDuEVU>etyP2wOe-r;$|x;POi#s{ z!$2;@k@>);hC^#gKByGM zV|Gd&SbIF^<`Z0IK$PH+O)f1eO3f=FU`<|X1tBHHiDjwaG9Qm?LD@4tHKznufP?Z0 zAvKvLpp}TANkHt80hR~#ok5+Kc!*-q^b8LFXX0pKn^{?9f|sx3(ucjBZE9tOBLkSC z-(d?coG`|=kYzwKf~8o)3whcft^?Z*M#z$&VgZ|vOsuSM7mmn-yl}&et*o#&0F14y z(8nT>HQ{oB5$<-Z5&GaC+&n`_xsI#pY>2gEWr)3I#i#-kKEdGW#&FLNk9bGd z;CMqLi+E>eUj~B;X9G*{lplr?&`MCa67W18h7zbL@fKin9Kq9q7>c0gz!VvR#w$RI zT%BD!T;pAxU4k9svAW93YP*1+7@+#oI0 zJl+tw6hMfAXFiIHb3g~wX6AusUcl2^@u0}WCT?W~nG%CcI$&r6NoSTo=D)zn5i%Ko zUA2OimI7=(0LLm0m^3U^gDUFy66~VLQw0bgnn8UM4>`&)9=Z}B9y!M&RFkCG$_g>N z51N4?$_6Vd#PP`_+6L8_3SQt)T$)*u8edYBm{**WSdyBepc-vr5eqXBayBoKo+U~# zx@U>h1a&j0@`NM;=&`{BoCXgil=2ZCPvBuXX!6W2Ey12{Q6)erGcUCW8bF|giz$yc z<)SF3deVgk4s0Sc6?A(?T4HHVNj&Hj|K#LcteG0rgwIQd%#)Pnfm%c<@$f(bT|t|Z zUmjnSiZb4SA`g;-MFlP!KxUK|WtM;@W3XBRmc(lc@~AArer(q>qR1AP<^Rd`doeiV8DSK$>v{yQ!5` zNn&OWE=!B@^GmSGVQaD>oCKP{%t*{c9%{jq#2H-RJ1cS7nwXQ5U!Iy0kJ0c$wE)z+ z%`7f1#XfF=q87cUgCd!UJRV&A#mLGkIkO-mwJ0837vNHpn3J9#k1{%i2p*6T zI0FDCi8BC@XHXDkV!QYkMHY9E8$#m)w~aW1+>odsH?*=MCWRVWS>aBhATw~JP>56t z%2W)(>jqe3$N+B&HGqZ)F0J6O#2H-Rn~-s71*JV)X$yI(3hn_*E33rPk__|#QDk{g zfr%rnS>o{tOb(YvEYL^v;C5PAS!JS5V$TImjP0Pn=T7CsC(=zjO^HZ?a z)u1TK10SA^EhU2Pv(6|jNy#tIi!Vw|F2kXwC^b31CpsBn*2yE}uz?N%fP9xvz?7oIyp(+0YKlRH6b_H2CZ}YiLYAK5RZ#%i1x{E6o{Fw0 zH7_+ChY65@{Itxx%;JnxbqfBNZ%V1eff-H??_7Yhdb@>Of3~2rjcl`&J#htw&@kKxpXwDpu4d9&)rC9r? z7FJdn#h@)W*aF_lDlr*UuHXpz#GKS3T!tp+l@(}s8+958 zIY_}RXdKQ0%i+l#;2Fl`Qe2e=SQ>Tm5!vQ~qWqHl34Q@qfbBo9di&Jw_ zlS@)l;$g<(@KZrinjzMnh=r9Ec)ff^q7lk*WXP646`&qThO8hHJX)2MoSKKLodQ#l zg1rv~YAu4zD8Ut~5CckzKusa|=rXn~0yqL76Lf1kBwD)2ZFyeABocF6VNxMU0R zbCA!NKnXq21_zuKUM5HuclOQ%Z5qR^86=BGGvq2O+&MoJssNu6$+;l?@Hl~v&t@V` zD=28;3KdX`5o9*HZnRNXT-tFbCg|N~xHaPFt|PA*g~t(S%}*-0X2#LWMNxpOh%0Jt5%HfFmK` zojd?d4`5FSrr?DD*pi5;l~pFz-~~zGF494=xQcYFbFL;>gWd#t(Bo8$GwAW?z#jB? zG~ft&yb}?inFQ=XkIN#gc@U>!e0dO$CQu&4QkQ;AM;nu4H0jWrbA( z)((v^K5u{~7O)4QG1jz$x^)NcQk;qj*o`Haj6q{hID!z5H7O`-D3Kk8y@WFc)oWNA zju07KMI30R1Z&ncwz5jC01awnmc)C8VaxSc6Cd6YBqN-aj1kt@F~Xj+aVo|aJ9sqV zh#fpSaKsMi2o$VwV1zSvATqdO#|T%BF(Mc{*k_pFA%r<;4w@)OZ$f6GG(bTMAh9)5 z^O2VkC}@F|fyzIK9ia6B$mTEU(#%C(J%eH{rZyC5n7;U8Xd^Q@F*zeO zKBuTOJ}ti}9dbSkXr&2gO>SyML4HvQ%DyDnkZW;fRcd?*Xd^D@6c=#3K)ex;w7vk; z9Dy`Npl0A$f&&T(lC~>?Zt(^!nR0cG_jU?(iwAAliuZMlfE*oR4nArDE*I*AkTNs@ zA1sgx-XRZaV!~q*Z4Y}oY#kbComo+48TPIBNZH*i)hx|2**pbhvl3j;7}Pog83kHM zm1|}c4-ILAkO`6y?7%xSh#;c0gqsK6O`Vz?4_Aq7Vsd_NL1{@U=qf*$wWy~8U@;I> zA(R$?qB}JOGVF)ka)jG!3~m%)9Jz!n4?eO9Tfi7wSykkxrQwjuEk&LWKsGS9GzSz@ z*c}bI00*0ypb_fQqB7(OBeq4cl!~_JT~jHh!oW19!pJG6!oW4A!oWDD!oVn|!q8Dk z6O=)a4FR1GkIxv(mV*LB1gYlvwq zXaI;(*BW6OYiejjv1^SX#)3AVB1#|dp*0$&3R(&p8lY2G6too#O*Iwl>=aBi!BK%w z9_j=sr!-6yv=OS!!HSJF!Ruu~i*Z4RIe^bo2JLo-9`6at&&YBxKIm8oShmm2PbtkQ zErzU+)B+!e1=0dKVF9KDao7h)1||yC2r7u;(d)kKY+@>ON*Y>Kf=)UC&DMho1el{hmys41 zgO4zWX@^@3K92>jy=TMOC?#RD2DLUq)&j1Luxm-dWlc%}ZhKOYt370kQt;T6iAz%^E=`73R>*^aaEn0V zI2>naWrbYxBWplcYE1z$9b^i&@)=|@ z*mc-~7R`HD!i0nXhGkqx!HQnmAvJY1ag`p}EW>Xqau)zmbU<97paqXENahCx1A1+d zX$-A^U=ah=OF{a>?_#8IKzA@K$WRS{djb^y@L0wco6vNEl7!*9ky9n!fIv@mW=7CD z8>9<4J;STSqRcW-3j=CBsIY}O6GaQGaK>T*NIfW_A{!5hGm`qBkRyIT4QwY@$DrU~ zpLj=CN0)eycyRX`bk-%TpNuGM(@fJ6O$|&y2l<0eu1if!fgA$~)&epR%7u)ygHi{` zkth<7;~BxRhMH^;s*raLfEB`z#R5kVLSej>73wLIC{p0#Cc*mgS%hgMXmXyQHXYD; zp6F>3(=1T47j!l&5$1uFKyo39HxLJ0;z-5_)tCW?(?!rjG{KhQ3m(E=gu4%FBpI%R z6{TR;f>ItR*g!Fxn}|Hb22Xv+69x!D&=_?|1^!VQeoyjQk=qNJavs#gwHOP`B ziRqw&7;(sgR#aihJ0@0EsJkuDOau=^VbO;?LJrpg8uLIpWENaqt415gMjM);90~x> zxbRUyc>Rx@ez5rjJknW$ym}07yOEWZ4|0nTMFMLq8Ch9@Pe{gLQ3mR65M=XkL=k9+ z1ZNb1oL-7NT7zsLjz~ZrOoc1Qwpt%q5`2m>JVfEkEFi_9f)>_fXJ}=Wjyx5DY#uK0 zEY$n>khS1QZH87>$m=MObz~W!4D_K$Va<1-@uU3GJjfBrSW+ll9u!xg{kMq~pwlW! zQbDx?mwdDFcr?RH^LL%3=lZ@!sH)QVVi&Go}$B4?|UyfH%*9i~-%$2eSjT-V>$`SsY;j zI1q~C!Iw+IbYZv*MHZnK5f^Ze8X>Q2fQuSh!W@xY0<#2U3{rMPs721%a8YCAY>gxe zFITX*#Tc~fD!wEUdG$St*5vqP*cB?>}m9Sfc-LKeYxDd_& zO>v=Z-s%IX=I7dHz3(!9N`C&BVeNiwlr%5S`%H8n3RLuaYneu!pbT+J}DD?&?G2_ zCS`)=NI+}kK+SgK*#a~@;Cu(mI$#c=+yin6u4E09GXtOO3vx(uiJ1v;CRSLOQL z0_G5>4^-&Dw1L}ym8%in$`vGwEioG5@D<7e4n!ar;f*Ui6*$O#0u>O}3fu@=PXXZ`lp}7CgmL%^ zw{kpjg{P4KavcF*AuoDII1q2s!N>r6MnUbXpcsZNY7Owl6`tk^$bS63GQ`^u0m))< zkf9~^Siz$lcdURk;cD!FJ63%=c62TiX@CLt%2;o=__-BzQW$|!rRUOok4=rMl*so zVy*HG@mBdDS)4YS60{L(?F%}30(#UBwkQHEdBstOfOHbb0a$BBL%cO3NEW9b3D#PM zc!Xd3|z+X$8)P{mMT&eREg(^p z;6ai@aW%*|l+Zznb|gJWqR8QeLl|T`G<1=jiliFJXr!EhBb2ZRTUkM;U*cgC^H>!@ z1o0{X9mGR~GH}#@XGKtFm?2sri|XMsWbh*{!5UC!{4q7eTUo)v0IZ&{1(28poumoY zpoN&&hVemOjxPbvL1VQLDWPMP2SpXwEJ_?h$Pu7qLbfH4FaT>u4Pa1;Mox9Gu!SZ_ zq?Csg2p~-;*#I?;K^Ym_r@1j7MG;vLf3IX!cYrzW+!s{CdD+#(hPK7 zFS=DwcVbhE(j0>sfVGo{Bw37ntw{=!L^ARWIa~s3dkdz^(8>z=&NO6A$eZqv#ZxlV zQ;SO=p-WOy0AJ{aytvET#SOf+%PA<{1H|_8j}LbA31QGs16_=rost%xmmd$hED@X> zGC%@|i>JX{XwWKXWh6r*2a*{wvvXlkfn-1i440fj^I_4;M=%Wqm4|l8jjp2hZ~DB0*equ8AC$| zBaee3L_uRs8Q=?_QC86)6yVlYP?Qbc#D&FIXx9-Un+6I}>^g7+o}rahN+$Z&cw`g7 zH-mzYRRQgg%Sg;lMP9s73>H8n7YHAoUWy?nF+&w)mVis7;?(5QqRf)Y_?*J04^DqD4d9XtQd&V&gAzE%Y={eC zhC_I8_hulu7iJ|XwGSw+A;mC=1)5m~E$xhlP0%a8rLJ%A$Se08@ zWf$k;kjXCvU!HX{`sYDq&feE4vI=}=`#s*-5C<8q( zL6os3n4l&4eG~|Hfg0YWc_`~nkaU$L=ENJL)J zIO77e$N;p04JmuToeDBCF()2J=s;z0xd-cT9LzmfgB$CR8e9iXAAn}XarppbWFqnw zRJh-;j;O&b!#V(lB#By`z|90Lro!bCkdfG3f;FzOw!&a8z*xiycL8YaCoUI&jKuB& ztZg)yWuVJ^QC5t?ErTs?#FlhGMkeN9Z=mI77K2Xrk0~xm$;>O!%K+7WpoR!Te0*kJ ziJ1vQaRz9EI%wInMLg0{UYInzZ3Mm{7tVv|%FHVPX#(wKNlgLYW(#rz!JCLd*XJe2 z6r|>+<|Tt}BQ`SuwX+$(M3q$xk@}NC*VgGJlVD>?YOL*GFT@Zoqru3iqhO#3;(Pjq7=dW8RJ_GIG2D=vF26Byd4vApU&;X4bq~^w_fN$R{f^`5Cv@|s! zjcZK}4S4YcDoPZzG)oMUODYs}74p;4ic?GS({PxfqmW!ss;LPJbl0GOAlDFA7m!z6 z{X$%W7*g^TszC>J6qhKVSy5sTpO;#mSzryn%1NQbAU-FrG}ju$0Lv-ZDyWqh#Dhvb z@Q6h;h?AI-QWUMh$gHWL3yM-tkUbD!P{DAXXE!fgb8)1sfX$Lo=|U zj3C_z&($iFXJqE2Dri6woQtcQt6xY^BxHj;BO^2hl1nNy6{Tq8n2w2!~DqYsD? z;2!{`GQqT~t2c~>2!sZEfCWN>J-`A%P#qu|Dgady6aZJ_?*leGINT9zdXPWZQa>mi z;OXoQNf)pnRwyw@Ni8VJ00lcEqbArxAk#EL4B`V^UA;A+@|qxjpoXWjKgfAOt|1I1 z2Jx`yhSaJc5zsNu;FN<@`KMVLnkOZqk14_hL05HRRgHGEF2WcqtIPtBW$ZGQlnl zFz{q>clBcc3C1U;q%b%enVQB288P?=xwr;Fgo{g)7?LVWQj5zI3n20V5DCz!E@1VJ zMkWl&U}@r=4zkhEGCq?$*F(ZN4dhsmD`1TD)I4zI!^otgz{m`)t-w;ng{6r_sSIE? zB=8Z+m~<2jHQ`e6iAE+2dHF@ThQanqukOQONN|OsL93#Q0IZfj13^x zS&(72nUP*HgRf(-w<+ix8gQu$YJ_VVf{I*ILr^7vB&f*{>Kp1~Y6vY~@*pLF0=P+T zXk?*Knp>I^Uy=)|bf7FynFGtCaCMsC>P1TdQ7ytu(9~dLK@{@{n>Ao2gAQFWH3TbR z0@VZvC2$pL3K0KTDfA_7U(pdDMt$1#x; z%qGxaHZx|>&_FmE9L#3M7{QEYr3ookf=)6rGBq`{B&l409tuN}9?0%$lC%_n56J=- zK44}_eko{E3YeXhn4F)KnV6@b703Vk#?{$Byl4KH_-9Z zU|~?n0A?V`Lkt4tUr02AvZNVA5T**La!NHyPPMQ|0!@#>l*96|8N5_TO0{4}g5^s? zV}<~b51k-pmgL7Lrlo-{SOaB;G?3HW%QN#Jl92WyM7=v!TTxH4LbwKX>mssv6~t)B zJ(@Ve2wHMLybgA)A45)les*a=Ji>9X&`{6{ffxxb;fOEc!9kx3F1s9qf<3|+ic6Cq zb|OZ+Owy85Q!P?KCs2ao8XQ15sgUvv6t37*q6P}W1k^x57Oz6YkFfy>ISJwea0%(; z8Nz^`Z9)AAO>o(1V!@!{cFi zARBZ{3MjPWbMx~`DnU5~5!B|1re=v|7NFsGuo7ru0;d$Gcwc|NkVu&Eu+kLdCh%<$ z@leHJjbO7OwI~B*H+*q&Vh+kBDG0kj(F!k}Rija+qL5V~Z}LMHuR_W}aB<{8TZACU zDlFaw?+8W;X-Fui73JrGJp$ntBo>uqCg#LL$^(d4Nj{PSXp_JUTIEC4K>`PwBl~BLE@>$*~Z&f>vT$ z8bknLPF7+vxS)&=g7^SbAd;H1%|KNeQZS~bB&8%8C!$Q+n8O7@VU85NCdf05$f{7H z7fClt^uokZq8Ba*vI>j4z|o5m+@#d11x1;;sqv6jv!|hHypO9NgKw~F2!pSqiwlEq zaHtc5uWzUigRiGw7=v#}6oadui?hFrD?@-`1w(*gB}0H=6+?hg1w(*QB}0Hw6+=J; zLqH`%KovuYAw!7~Ly0j%i3vlADMN`FLy0*Sjsf=W(EngK;2B7)%+B$5!UP(U_OK`S{Kn&_Z4F_H#`0AmZ2_y7i&5K<0r>;oFF3xu!;bN%oI>k1v>+pp22LWCl$0H>Yb3)fll0k zl!^fmQ=Aw;-9cFGT2z_`9>u`sLPIMn~9DA-Ld!3Ra~SLx8`hUkKQz z#A_~2O$HT~MWl6-LAs1BOu)LpnZO;ACjCfgJ%G$GH8O;l0m>SFkd*6AycsFQiSdag zMWi&aL0X_q`FK$8EFLtVL6HGPiRI+#2c5=5kpsX6kl_H(DOX9ECB>vV9Hb99)WE|a zq@_4e1i+0U)9GMuLnF@3)78g?JSTvSA;$^EhM-dmNe?|^L-Nxc==eEs(39z4uxFuR zMs)E2jx1wC@FAV?#9ItHVlDji6zpykZ@{1d;(&*l zj5HPE6yQ8VV-&8D5$FV2kQPHEEoLZc3=L7ZMy8sY48b5R$hMfHs4=tvalzvZNQ3Nl zb_$>~Xu*1stusW^Y>7j&A*fpu?BQq>9~|Nu038I%%qsy|p%7xIqYz?btq@|UV5`8$ zp`fh*4hcgIMpn>JzO#o0Bdd-ABb$x_BRfdIJDQO*RzX{#97J0ygcvE#kCk}n;!1=7=s0$7q6%Md{DKyK zKxPn zBHHf|7ZfDtC4-h{y81af`MAb=`h^5}`UQJB2Qz>sB|%dj@h+~;J_uewkZS+~ zc$!Dk04@qin(^_uhDH{d3b4^@LmfEN$QsTBC09_2Lx_MKr$cps ze5+uq0CqUUc#z@7M#ye5s4#Iwn+|gFW(aWdW(W=pbqsQicQZ7yKn><91097bLmh=G zBOQe*V{3&fQ0PG7v@oU6&=8WDLGw>l#tOCya2W$ohSyO5&rDSrV09SCSc3`!kc+C| zv4i6DDq|f5sES~pcq3CY4OHi7S}O#(x`aAI9F8d&;N%S#gcmr-1qgK-uxdutWDr&5EGy0g!AE;2-W96z>@98}IAr9ONHNyh*t!ps6TNP@Uw% z;2S`aM$lp|Qi`G6^fY4I*WjWew=}0D6U5R>W&mAj1!BUc&5^ofX2})?=7uJqjrpK8 zl*J{Wldd5%=2%r>*+Gaf0)2TOvJA+-I7|dpA4bUQBGL4LhIA2KEHp{f<$Y+9pyho; z7my$q>LoL{L-G)KdP|eR+mONAh{4;K!JC9)8swp*%ydxl3U)U|ZK!}74e*wVu?eUd zfZ$p}S}LGhz7UNYLsUhOb_ZOKi6Nw^f@%+Ha|UcFxTOM~c!Deku(MMzhiOG=seqd% zaP!T;Mq$xx2GZ=|XyoMSj@DKIS%ST-Vj53sTg5aURCIwFGi0?@Ji|Z<1R5cbUGd1zF-ayfuOtR^f^KepNuAW}=Idw#9B(|;xyUWlNG+IPt z@dDG4lv$FKnn$9hl+@(hd{6_9=rA)hg|6Zu-KL^cQf-0^m6K>w8YsX?)RS2Z8h9d6 zQ*M4rN@kfJXiE!pusc3CKLxZ%6WrP_NJKD`;LJjVXkiiqQNFe157FanK!l3FMjky9vuHIZ5X`3 zWR`))h=@-KM&uMEMr0HuM&uMEMxcVEAfMRD2}pqo(nNB7Zfpcz&PiH*4%Gy%&q)b# zaE=8v*-6nvMvgU#C$UBbHQzwR9g!tuc1jv(h&&rq;Z@`p#Y2_}gW7@MB3;W7wiX4v zJGr1JKRLCy7^*7BnW*v}WCdt5ENHl~C?3Ru?bQY~EYX+56J=y>VsZ><)23cB1I$UF z6P&<~ha3+=OtipEiBAT#lE9-IppjjoTmU+&AO`6;0Ep+11mdAvQi*X0*f5ZPz$Xh3 z8FOGw#g)ZHd7x1O$YBYfjk>9MB}MrKmC&#SZF(rmONVU1SI`2V1rJqQo|$KC!~o?K zrGU(fFV8H=h)+w*$w^8~&PJ7EfGR-@mpKK+hd2hgyM_eEM_8D}yZDFufvy#SX)6Vp zn4e2ra26-VfG!UMU3;36np{*_0E!Z#!VanvHk(S)V#gvh&Ct8oh>Za>-Qa6?D04m7 z26&0R`nS!Qu&eqJ#{QfV4^zX4=_RgxiOyN_0q5d&mVBIPym zL$I%-j}PcFVPDr^hTP1YoYbQDqQs=kJd%nLP}q={mq9wgnUK7E4A)Lx9tLSAJO3gy zlaYwQnj!f%lpzGPY)->MK}#W2ljLwGFAIb1ColWLw36#;E9nESTcsJ zs6$)KTL9XA4$UjzYaFqvN?}&joZtFQiP- zRxpH>3ZUJ6p!L!b8m5LuItmbl8blQ*pcw#t1!F_dCP`A=M`lJgHiX;{N@hleX(uxy z8ym)xpON93$w|^6&5(>tYCw~jb3qo8nRB69$@M1bITvIhEa#FIJkYBn$xTgA?c}B= zBT7;eOfy-*Y!nYl7NoXKj3F2Hf>w%=sg+#ElAb2umtK;D- z*Gx_@gET`*7!4CL+6W-+WR@3Dt>ikIDL(ZV=;Q zkY3QinZzCF0#yw2OZ#60a60eWdvgw5|xZW zPRDRXQ88!-zK3J52WaJFe6WWjXz>FwA9T_dG9R>l0+|n5jf2cLWPtHVb5%}eY96uU zL~yTwHGwv&B$nos#1|DO77$%5pqY_Yngdz}No>La1!QVodS)JItku^sBHlkVB;G&F zHORx&(FN2$kN5OL@QYHD%L;N*;z8X95W6Tf8O+Wq%`J$}NX$zCpZdp;oRgYZ1eyQ< z4Vf`yBo@bm6qe){r{<+FfCvy5Y(^gRWK@tK%-~$mNr*+Mi7A!wphYV%dmv+fc_|=e zX*s3E84Ms95Dz8;G8M!|G9WV#Y#&S&#HaCK_krvOGvad-E8+`s5;MUk>M_7>mCjDB zgbpc_9+vQ!1dY8W5j&R;i%F;}VS|StGm>*j%%YfPq*H1}azt;5UwaHP9&-H&M1zD zRP%bth>(Vepa+AcF{FYBaCC|HcXMM%$p?Ej6|@zx#1IxP&SBtS0o8;hi6yWAK~ZbO z01C+XWbj^Lq@Xb{G%-jswM5;BhY&;y8e|ESph1?%EPy!^M1$rwpj}6j0x2_JFPQAHl=zV5vDfwKBD$AioGyK^B*0mZTPgnk}HJn3N2iQ&g&#%nkRVsrcpq1{5CkvC)7=BY^$7}%2OlH_-g)Kd;t~|^7wY4~0Gg9> z4PgLXZXTbR!cdf&n_re1pO>GK3R>-!5?_>Bkdv4UIzO-kNfa!fQ&b9>ECcTV&B@Hm zW&jE02tz<2i`(H) zS%|x#9JqvbI}YCIkeybdkmruVmX8j3lXRum~%kRgeU+j zMzRFVhpI*i4pMypX{CVfHAhW|AiF@KV2e`n<4Y3L89;oPOEdH0L0qsj$Ww3*h=Jmw zlzh-NCt%Gmf05$IVvN2|aVoq+17U)zxZ>3Kg8ZD! z*+xLBR>*Z9$QLWYhCuS6l@era5b~`(WCj`}#4>}E@+({`N(>k@GJ}hA4WbztV>KCI zqJ|6_MfoK~2q_%}3r&Qy5vH^uXe$g%yD_G`k%^`z1ISG9;dLM)g&{K-L??lWR0gms z$n+8<7K0fOenNN&DhBfrOakH|s3gok2uZMapt3OEAY{Rw0ddK2FQn}bYLk{Gh36Ng zFa#y%6Sp{^7$pIN?h68$67Cq_#{k-}Y6K?zGz= zCPCVb(Ev!hGaArQFhbRC0oQKeh6+L2(S!_i6ig7>K?in~gF=GzJOl~^P@5Ezrpeb2 zNkHW42bTlnYep#nAU-N70=0{wMF5#5L&798uPh$Ck0QP(zq}Z=RMFU@#3L0!BCsCJ}nSciIK)cv8E8wOhSxk;6V96UPNrMs-EG1(kVdTUM zQV2`47>O065SBtVK#zU_eqJ zsL&^Jj}dwa2Tf9>TMpgXOrAziG(enAzJ79}5#(@C(32IBFwKyt^znCei4P8S@^+03 zjtA|cRYH>uDtHqud0jZRLE1yRM>v6>2rDJhv6a3Qdap_!%vOuaEkAy`y3ni%ya zB&s(hQN0<7>di@1Z$YAZOVZSv7?7ymkVN(9@ymdk5-g3-1dJ>QqyQ5VQ-BG23P80G zG<$~bBtkAAF^!m@rx6AxAAe`>cvnB?pvZs_aCRuG$S;EIa|d5IpilDmAuv=DKqp@tZl9~5=i^8aYmDImuaH2jc-ppk+cPf%6JLQqwR zc)}8Oh+K$>Hn=iFWHG2|NW~dK9U|*Mq8z3cky#+(P)8bK6nzm!po5AqtAf#_Fm#gw zB55I#0V2sDi@}l$a;XVRDhM%15`w8kl${W9n0m|#!i2aA0-V&CVYg){Kq_Ju9R)@f zaw-t0L5Pf@0Wt@Kk%ge1K@JP3Kaho>W+4kf-GwX!H4715@UTV}f|`Xa1T_m;2x=B0 zjNxV>3qj377J{0EECe+RxfX-^5m^Xo7P1i3EMy_5S;%!A)GTBns9DHDP_vMQpk^T# zt5CC$g`j333qj377J{0ET=+uGLKcFWg)9U$3t0$i7J*V5Y8J98s96XhNXCGghg6nB z#Gwwv5QmzKAr3VjOEqp1Z%9lvKAOQWTA|4K1R5X6LeQu{7J|kCvJf8y#9-zjR}xT!20uyr`1@ORjW=e%o zQfjOwLs>y;Q7*in0=m`J&{PwCbaDi;Jj^jj^6^2g?hHB#(NN#tpT?w&=!Pnb4B!~gB z!dd}*jzMxsQ9L7~24r<4+Gg+KY#sCqUXx2e>sv5{lSG$H2Pr^S|-p59s}?U z7{q_E@aZlS=yZ-DR#{VU8c$9(!Y&J)sxd~Dg*i(DG^>W-m?Ipl0XonYA!DhjkXw>m zQlz08jS{vXS0*N<=4j;P=ND+gJ*Z)1paZ(M7D>QRM*(!&J}d|{jEr;?Kz1MmjCB+Y zE#ba4g-)12!X&9Q4P+H$zR(mpe+CHY*G^o8~XbIA< zqhJKG2U@6+5=X@)kPt#mP!PYu<)Gn!9C|Q0)Wn3U&lDvoLFCF3^HMZG{shIh5x8Ih z37G3B7#V`FrUFETg^mI!zKuY23s{S#j)IXf2*c-kK?Z`R6(O{liKaqQN?sK-UBTmt zg!BsY6KYt%GZ$PMB{(poQ9}e%8YNKR(pCzf>1+ihZBQMNoUEy%5DoGdR3ND|4J4AB zY!C|-NlrF^h!`S7K$m_;gYq?8jS)nRF+z>8rh=6MXbK!s8x?1RRe;OKScnkBNg!d= zd<&695d$fL)KsAQ2ciJZM`Qv}J*Z%%pj2j{q@$ozW(X#Yz@#ylGy#*QVA2dsnuAFT zFlh-U4WXJLx(y-P4I%msAqE&iOfZBPVF)q95MqcS#1tclDMk=ej3A~MK}<1%m|_Gm z#Ry`G5yTWDh$%)8Q;fl;B$pI{T$Y=fn_pC^qyV}C08~{uIr};~qt;eQ$+?Nipj=OM zg$353gZ;X4?9~=hodv3TAoUaZ6%VXQ1T7sQl>yjQv51HT7c`iqJgD47D&k>AL9-3m zC{Wr)HV4#{2N!3cViANv#TiPm$;b${4Z6+)q#u#@L3tck-iPN}tUe)}?XYDRNH{># zJD3B?35cu#%}EFWgjYvYUVtuDK+O!0b%BhGpoLMO4YQ=Q;xL+U$>7k(5T;8Ofwe=x z?Q-;n890?EmlT2W0hqh}>VrDcw2)gUj00VR7xTG9a3pDtg+xZX9;RDfj^Q{`#vWn;mnnfzKwTOWVFW5{L9Gl>0}^Zr*?z}a;9vv_ zQV9g{Bf`&MCm{P1)xDsy4OHOaY`?+c2G%k`N?mX%tjUYK@~xx@T7o5)6oE=MXlf;; zz|&EPhO`6_CS~R&Bhv1ODhFL$!ArJql!MT1S)=73Xg~&B$-@dK4N&&QTBJZS7^Djc zZC?;7A~5nGfs%8;3lT&pfJ$|E*<`e_Ep(RBOP*tF7_@IRiOvum@azuJ% zK?&SmBMU5MfcA%B8!CevWMlzr&@p7@B^QAffWzf1!N;S6T?eTYKr)$m$?+8?AQot! z2*_=zdEi5b$=JIAzFd-$HScf($X)afHGs@*G;rOJW$)1VMizxdIO)szA*Mh!1EhoQ zQ!h#d-Az*lI@CNKe4ifK0S*Z)(B3C<&8e_3%gZEdqX1YZBFZ5>Yiy@sCqWNXhpL4h zEI@iV!YzdOnm7wn^O7mG5S*llv8|+ta;s3%AJoT?4jXhM7jX^&C|UK&H7k0EFSS`I^C5Ru1u!S^jetb`^@lJfvUHzYlh7FZzN&_m?OvbiJ?bVX6H zF++f}QBh`kMhQc(5ks&kh?|p|R>BZ$#t>}65NyE^Y{(F7PGSKAa$HGb5+xx6)lN>( zz&Cy)?usQXY*7s$Ie1aE7wRR0E}#SLee!h-_BMgsN@rri09OV+GdLbx%A*S=Wu_Aq z^cAKCmN6g#blP8LZekAjYy%=)4$>C`x=ot+zy@o9-02pdnjBw{ZIO~n?A7gPdW#av z$@> zjt7gw6hZZ*7L||~2f3Mfpd1f701O;_P%+Bl0L>719Ju&_51IrYZ?EAT5}|9Ck{1s; zD=t1Ww;)H?E+w@%S;5Xu!6_&nq|n7R*coz4qnjJ(eob^?P^qZNP?3ugYN>^J`N@gJ zsUUH9kRjB7La8Db5`a)PH1xslNXbLW5=I88$)?5zNhk>gA&8bxkR?zO3bI6I0mxm5 z=!2dq2Rhg$v81#pl_9k-DKkAYuLL$=6d#|Nmy?;7ssO*F0pux0MsVIQ&WSHhEe2io z5TBfwoRJ!zQ&g&;1zNcPS6u;`94bmJDJ{waoeh}}% z3=e8L`xYKeYk9+;b0RFJ3-5&-d(AVCLqxe|jC+!sm= z!LC7Ju0ioZ!HzJdt22z{>lxwd!Vv838VR}pRw1z{JsEUDS&@QPVo`cobSy(+a&l@x zNj&7#NU$2H7t&G~JVHVO;)7g+897 zL5QyMqRbK;XXZidjE99)h+}cQU#Krbh+{F-tfZoNaLOtvDlIOFPs~fs$S+b*jW&v9 z2yrxsckzR`COJPZFEzOYECz}pS2)X$A;i%Tqz**6I>+OPv*gm^lKfoI0d8rTIiT}- zQ!5g43vyDSM^wTj7+}IscNY}pgVZzFlxOCF0tggIFm?qp#|XqJF3zkr7keQ#%keLq}Nknbbszy5n#Rmub#5;w$1$#!h#yfesc*Zgm zCo@3Onjr%?9akiS6B; zLgr_tD1eUAi_c3fDbFv;28$vKFeK&Y=P(4hI)}vv`#XEPhJc*v20A|z4J~pY zMP&wqjU9s$s*n=)>L@c8l!A-(G8mK~OuY;x7_%6}23rp;@xi7;90V09Ni8m6Ku(X) zA`x6qXn~9dv%riDeFg@*N(P3tiA+7GBRv;VPeoc%D@m8%f#U0%*b%^AtS@R`-}{6 z_ZS(zF)}h3?qXz+yU)ll?*Su&qyZDd8#xAs-;bFYTAnj9Y*J)lxT4O&V57vq5W1KV z>?U;LvLgdS+g|K)AhqjfGB9Kcp!(fMfr;UPJOe{~0>qynb;vkc7$Uw>5<(-(<*#I5 z&{@R5ARCA(ce|L0A$k$AN(P4gD6H}VfI-@hEFF^{RNW)(V6=|Bm@_2gV4xiOdmw=M@wW;1pDGu zCI%y62w&$Z6T|v;1_r(ch`V?mFf+X2gt+NoJ~M-i1`ET_ClI-YFa`#bEM|ry1rT|N z2@DK@{s{lV#6Yx_970`pFT_o+|1dBtoXf;8(~N;3ZVyBZq!xw^CNeWfJYZ&sXJulT zD8#_vaG8l=%LxVsQvn8s?Ws%*y|b7Zz8_;|*!_^1!N!l7;qpUfhW{!Edvqr=Fg!TJ zz+hg%#GtX5nZZtpiJ>=(f#FIt6T@eFMuyN#h}vDrsBX5MgmBBzuS^V#iOdWpN)WX$ zw}I%16POtc86o0g(o75it&9vd*$}<$_m~;_7BVv&ddtke?ZCni*Lbtoj)ks_%hJXJ9CIWMWut0ts*Ps}MDO4G_1Q zTw!8p(q&+<&SGZJKFiF|EWyl>5WviEa61!&NFX!AmLO(^)6Eb)ZOx1fJr+z1{p>6Z z-&Qa%+?Hlx&{ASysP z!GW29!SfX}gG(qg1Cu%n!&x~NhR_ryh8t!~41PzM86xr_?uF=rkQ}ohZWccPF?UTF zl+VM&@OLLO!>eNualJ z1BpxwFTGj11fMF*E$U#K^GR4dOnKs_9T>a}f)} z6nh4Sm|8}LUxo|}{~STG5NsI1$e_dqF$*M8lEBDtd><2oZ671Us|*H)pT5itDS^xk zrH7dqoQ0qUGB7Y)&&G5oNdFQYCI;CD2=hQLhRnrG3{Om$ z80ua#GW2FJGyLL#xTpLD6T>%E28P^nh}jQzGBfN}gRtjrVPs%i#>{Y1jgjH*bBNfF zNM?rKCPs!FCT527uOMOL2sI02wXQk?!z)z=h7Efe7=D>CG04a;G3ZDzGx$7WW(ey; zihGb^G;C1B$natf6T{TQ3=Bu?nHZjEF)*0)F*E#*gxCX8-r~o^V8z48@NOBzJvtv5 z81~FS$fqrUh=bIE@Pt5Sh69HnV&#Ppb=wpnbW#FD9Hb70r~hSQ=zq${a3P6_ArdJq z!Q_$YuW1Ynp4toy>y9uoX#Qhl_@%|bpnRT*;mR~jbCLCZR%BwRI>*Ei+{wt0Xod)r z7d#Mm!PG8sU}E4lXJlZ_WMbGF%D}+8g@Iw#M^rUYV$2Mi#2FZ3<}ovnsL_o^KGhBrRoRxW&)NPN@K6N5Vo1H*R#CWcMIObqN&5OXF=Gclw=>xKMi76$bq z76wr@28Q2(nBno;49e*85tH>F)>VcVPH_mVPfE& z%*b%HLz#4uf#f#JasMuuMt85pKDF*C?A zvoNrmFfg1jVqn;k$HFirgn_}}GXulvnM@3)s~8!M?`C4CXJukYOJ-)cWyQi^ZO6hO zRL;OKcMk(Y5HB-B(;Fs+8Pd!Q-}0CkrZBQFOjl!J_*BNg&|${NF#Q7qL-7nI2KF!} zhF~owhQ=fY2K8Dd1`S;%1{O^whW}d`8TyPE7{Xf_7?Ls=8F-#BFvI4 zI0G3Nko14EZBBg3v1W(K{JObor- zm>JF}voNe=Vq!R%&cv`chmql|1rvjBDFcJ|RVIdQW=srwe=#sTn8U=d>MSF}CS^tj zofu{Yrx#2Nr>`(GFyCTkV7$Z3z@fszaA_g~!;NN8>W4TcMHxa{IWse?EM{VubrF(Z z43ilc+AlCNnA~JyxO9b)LE#c3gWyF*hG-8)hSirD83fKVGQ51pz;OB^Bg2JDj0`oG z85vgHWn`#+#>g$85!)?F)^qKGBMm2W@0cDXJV)nU|`rR#K2G! z!N@RWGb6)ab4G^zR3-*5b!G-zS0;vi^2`hoMNACp7a19T6tFOa$S^RJWHB;SLE9h8 zWI!fEaIFjj!w+o+2HgWp3>{Y>etvAnz;N7wfkDBAiD8!+Bf}JH28I=<7#Yr-Vr0-~ zXJ9a}XJF8lVPM!9%FJ+6nt?&mnSr4)m4PAnA|u1`ASMR!CT50X0n7|1+?W^&EEpNw zj2Rf@a+n!pG8q^?uro3|e8a$C@rapW-d{$BWq+6$PCQ{|2*_t)XomJHgN{Jl1|lDR zg}4dC2I0;=Mh0OKCWd2^7#V)OVPIIWgn?nD3nN2VAtc=`S7l&`EN5bHj$>ljaF&Td zTRXFnmsAV$iz8#E@Ra$Y3=GRj-Q_6N6nU z6GOEf1H(jlCI-I z->l#PGs9#{1_n_MCWh(nAZ|P}nVF$3c^xyucYOv1$@R<({IbjpyCyI)WX@(_IA_bm5Iu{5p?E4Y!~6Bj4Cd3B z8IEpXW@y~O%n)zQ#9;NFk)bk-k>TZDW`^~TnHd~cGBfBVF)_#`vM}gF>w1`bkm=<8 z%nWIqOboxyLE>qVJrl#lkIW3WY9MYyRtsY9Qej}wC}(1@>t|%>dIS<-VA!^RnW6bI zgq_F5$lx2#z)(`d#BlN+1H%phW`+_bCWcA8j0`sdm>EoyA?XpK8b5i<2_pab9V5dJ zXnz_a!oU#K#=vmqH3P#BCI$wLSSE(~Xy*30K;mGh2m?ciC<<1sVCPDO;3xL%0kTb<6vaisLjCO2sIa^&LWqY;f^2^gIOmN z1N(1Ah97K93_MIs3^y5>7_1eU8QxejGVFTK$Z%*E6GJdG4E8|FnEFi+J3!`ua7a1> z!`B-SH*LECaT7=!8LR(5760&xnW4y^nPK*EW`+avnHlCBV`i|=VPbd$%{L&uQi&`K zt8Oqed`VzounS;fxFgEKaN{5YLzNc;gF-knLtOzgL*pxEhNnLm7|tuOFr?|QFc^OW z>11G-ejef;cOe!A^M?!!)qPA1A7Ypoa(y9g&vIp8kXz2kP^QGp;Ix5};p87i2L7`Q z3{7Vk7z%xv8O)3s80P6PFw8xR>TZzfn~NA2>Y14sLW39>9&s`<{B>YpsNK)R5cPzK z;dKTR!=F!#4F3fg8FW4{GPGnfGDMd#Gbq(CGn_onz~H99!qA|?!Z7PIGs8Ji7KZ6( znHjj%85vf7WnwsKz{J4i!N{Pm2Z=Y3T^9qH7@jX>VA$Ej#BjWxnL+tKGlTYLOgDkl zhVe5p*m^K9Ou5a>@Z&HOgTfnThJb&}49>00463Zm40}#9GW=zLn7!B=VTR{sNSHh* z1et=s_ct>#u*gBe@y;xW`2ShV47^;749$lidO)H{rHl+yW0)ASP9V$#iG%PZJ4S|v z9ZU>M@);P~vzQpdWFh9Av}0!Acn(s*z~CLj%&^EABJKih_s>#An8k0y#Bkr2nc-9h z3qxQD1H*n>h}{ld%nXJZObib-7#JR1Wnd`IW@ZpZ>fc=vV`ez>8etB|w&b@=3?HCn zF^K;-j)9>*n318>hJnG@nt|a11~*YixPnx*ePLqQ`k9F#%ZrKOGGjTr+&lO@FM zA!ZB=UnVd!WWI**uN{NKk#hWE=E7`_NHGdNo_GWhE- zF!1XzF#Hl@VVEY(!f^0EGsB*Lj0`uRdNOiY7(OR6F{J0RFgV>~Vo2D=$nejSf#H1_ z6T`YA3=DrWAZ~ibi?A1BD+5C@v~2?7XUT&|1kSQ$VrcVbX84l{aW_b2!X5^OH@`qE z1m>+{V7R6WF}qL-Vi!m@GmV*n)0BbXM+hUs)~gH*7nUIUbVrG#1%gi7n z#>mhd!pP9GoQYv(Fe3xYawdlNTr3OTf)Tf z+>?RfP9hUSrw#)HA0s2fnx~8mas~_x;U}0Gte--{-S8g+!>9R-3>}^f3{zs68R9Q8 zGkjuaVdykxX0U8xW+-ogr~~;68GDN|GQ7@YVEF!unIS`+f#KUX1_r^|Obl6{7#W;? zGB8NYVPepD%gFFFjF~|{gn?mcJPX6)?+gspDGUq(H<%gTYcMfbKV)VQynzT~kol4N z3=B{9GB9+dGBK=$=2?*Vw2Mp(tr@6lLE`xEC37Z*u6K+KVp~x48P8^5I4p(`yA;L9 zkiU|NVdE?YhC^};40@&zQ|q-E7|xw$X5i0bVR!;P47K3gHQ}J!@qDwhJ~Sw4EI1|ViTDe z4EHfJRDEJ*m^umJ51A>93_GD?p&+wBxMw#5L(g&shRMxL4Bgw97@FA_7(CxFF`U1{ zz@XC2#4snAi9z!jBSQ^014BtFGXv`tMuvO&%nVA<{0uS!gl!!l{sytpaUv@t!-gpg z3`e^d8Rn`pGCWdcW;kEL$S|9gkwLVCnPGPk6GI^{0|V!ICWgy(%nZJNA#Uc0LzwwN zo{=H?FoZut4&4Uq{K9Dr3`{l*3{qyy43UwH43b9}8PN^-OLP+A22hdy@aU02(=@F zfsvt1je)`S2gE#xECa*GL(D}~H-~{axs0N_gC(^>muxA4k!%h}RT!73v$_r7W zyMuw@VLLO!dnYD_1sW_2vD%1m0I36E&9@8;?|(2cluT!0NR47-U|7w-z}>^hApePp z;guvK!^BTa3>%j*FbFU)GQ9o7#1Q|PiQz9NBg30EW(JO%sQ!4emXTrhDQ1Qv=b0H+ z1~D>JEkn2oWEV1C@syciCOad8{sJb3w~v?@7@>2MFg0Z#A%3`~fZGh`U}lC0GbV^%q$GN3NRBG7!D{fFvNR7%z=rjUqvJw#3SRR}G3iGg9hH3NgdRz?QtJ4_5yY#11Hm>_a6{m8VlE)&DiJVpkY zRz`-k0tkN{ILyp2xs#b8t&owydmj_S!3WF?Pj)ge7`G$TfXtbg%*;?F0b(&Q)O#^8 zf@F|9oLClbuK{uL_VSY3t!~0@p2J^$r40dmr8MFhL7&fXS?8wq%V$e@!Vo*wE zWYC|(z;Nma6N88@BSTLMBg4!aj0`FI%nTw=85r_jF)$poXJ+V|$i#4ADigygO=gA! zK?a83Zx|VD+L##@Co(a_TSNQ|BfFYmECvRt*NhBK@yrb6`HT#bYnT|O8G_n;Obkae znHU&57#UhOGBLb&U}7kaU}89>#LS>lz{tQJ&CKAI%*=2&kD1}}eFld1UM2={c?Je< z==?v-^mHW#1{dgj1x)NTJ0pXWAp^tJ943Z0Zp;jx>5#a2_6rjJFm=dutR4e{EH|I4g6K%}LR*#9{!G9)( zQ(6oR!aJB5EG-xqej?39!wfbIVq`EyDhE#=U}Pwq#mw*`0OEg;I?oA=3=eWq9n|Z} z#E{3v$gpfa6N8{JNEIe_aAaZ#Q%2}>-;Xd8U3GviB1{&YWMH`Yi;=bU4DHjH7@STsFr32DPCLg3i6@vDxhx3&{E5sAdsJ8$lwL40?7stX z1KTHNhAm4O7-R$)820foFz`NPWLPW2$Z&5VL>^?$qq)osHs=`_?y4~`OmAdhV21X6 zZZRVKSH{oGAbfy{p>78QL&0}u28E*x3~&4p@*s1t;kt)R4Du%!86vw- zAv8?y8l*W>keEd)b~~2*XJj~(&&1F@kD1{ymN^5EUKoBV!pP7m$i%?@o{8b%31)^B zj0m@^FkoU3aAjop?!e3t&jbleT`YMBX4Y;41_nEEh&qticjy|Ye>yA-u5Jtr&e1Fk zB6182yKER3j-Fs-IHJqI5PqMDVM8NGH3P%$ON!&@CeU&%52@K}V2;dBHugNYCmLkKAU`!F&vgflTTTQe|pK-YTcFJfe9 zMjJcRn83g=J%ov&)Q6Fw2--$b4ubgOcmae)CTB}RcxGJ;3{5-?47VRKGC0ICFkGl& zVkiw@VmLdSf#LFAMg~7#1_t*(j10lf%nXrNnHgp|Gc)AgVP@D|z{0Q-Iz|pLiGhI) zn*X1dBH|1tcTSCgA?pw`LzN#R16w-8-_s{BFnpcQ%+Pw5nL!HFFHOVLmnzP{@YRTk zVXGe_!^Wjd43nW@wnvABfjy0dVM{s_!_GYn3}4!r7&7A#`Wtc}>}?kq7>-6VGhB;d zU|1^1%%B*{z`(SNi6N?onStjNL=DJ|7Jrx+u0=94$fLPoRtH4Q5@^{CQv3P<6T`l0 zMuzbJObpk87#P~s7#QA5GB9kr%fKM|o`KIm>Ss0X7GBYe|Wo9tvVrJ-=!ptCC z%)sEYhl#<@i;S`v2tuqmFAbrp&2oRHD+hb-1aYqIQ4kHGJ1<@$6j;ObnBG85r^nnHV%&m>E8IGB9jl zWnt)(XJHUcLio!rmxW>WGl;(fOBflJu`n`NbTczJK4oC=X=h}JSkBC_$d-XYZ3Q#K zDG)oJnIU2yLjM~_M0^)TLBww{GBfl7er867jwB|AVk;(wCnp#f_GK_L>|$qP_;1C?u;B<3gDSM&4GKRH z-rLN`@cJ1e1M?LIh9(sz1{df!D@YCv6UEHn zeT0!=NiQ=)By?REb2l?XY#b9q4I?AN)dU6x3uOj|`*Ro=c1&PqIEb|N>z)D&gZf4W z1_?&^^S=AOT&62(#>(0}}&(7BfSr1`C6z9Rq`T5;Mc? z!%Pf$PaysQse5q{!oK$a;$DFykSKO6Va&+z7&J%6%*=2Ysl2KcV`8}ehKXTs2_r+^ zS|)}US&R&FwGeY*Cf!hGV$jxNWGHN7W|+~)$Z+~GGsBFVj0|6HGBRAe!N_296Jq}^ zXgW^4z`(G}f`Q>s5iIx&n_H&F3nHL!u zY%el0q&#F|*m8l9!RrPigR%%C!#*tr21_3%2GH{CSY`%>fJuxDz99NCBf}Zc_~K(` zhDi>L40}5n8SKg#7|t0mGYD>CVz|AHfnjeTBg2oSObj-hOblFnObinIObjRZnHUy7 zWn$RY%)qcdi<#jvBMU?ORAvT!W)=n}9u|g&yeteW%o!LQ+87!1J~1#j&SYYkq`<(i z^&}%h1v?{ya|Q#$9BtGcoM=z{Id=Jp)6PE&~ID5fj7R56lc7LGu@C zEDV-knHUtlF)`TPU}l(ni<#jgBNKyYA`8P*J4Oa+J_d%Cg^Ub3#~B&ciZCE`sD6P&@^;FfdfCW?-0}z{Fs9gn>bgfr+87gOQ;VI&UofoRQ%KwBM3q0Mfz0 zP}0fB@Jx__AH0jYTIkD3lZV!5Xo82+_`SP*Q0G=>}z3`qx{ zg&7$-^O+ddJYZ&sL7V%7=we{7FkxnJJ;KD01YIi*5OqK1*d!;*nPY&{c0 zDLW+GIUSf8H0Loha6sErlcSg!=5|2zfXMz6j0|?rc~%e~hD+x$Go+kkW?;U@z#!2B zF$*U5(}0N~cRLfq<5kQITu&Gowyb7mn7xLXVeUz02BRnjhV9U{@e?5?hHfE7hCAsj z3<~~`H162Rz`(E0z)-5o#PDP##4mTUAT(1mBZKVwPa=x^I>3E z)yK?WCIj)~{33)sAU!ZFvW=0!S)75vDTtY2u>~W;oo5UTKPNFU^cpfTynM~T@NXIu zL*`KihG#8|44)1|?3@a%>tJT^szO**>lhhIk@D;ns5nHHfgvXr#$sR)p3TgV4_yMXCWeVGnHU!E zF*0y&WMt?(#>{Xum4V@r2LnT%78An@0|o}`56lcb{~_VAt$>-q5Sng2KV)E7_K$&K z{yZjz6JCrA$998Ehv1LU`7#KPfr0%o6GNpW6N5S{6T`Y43=BfaObn*NObqUN%nS^3 z7#PmgGBfZTWoCGe*5_FGiGiVQCc@7!^FZ{AmrM-t&~VR!?uq#=%)%hz&djjZk%>W# zg@M6qFB8Kha|VW(PKf(K`p|I$mh!dNpOL|4IYbZF3TB3N%b6L1k;Ws?%`p6eDk9Fz zz@P%{TbR9LV3-@u$S`*W69aS`48t^}F*T6RcNGx3Kx`Q1iif0U7=LF0A{;oOdqQAx zAbKk=6NBkl28M?`ObmZI5o$ql*zn{E>}sYYGBdaaGBM;p$10KaZWd!;sI_5as7BJ; zy%3_}B~qSVwFe@W@Q#ULZZ`u17j!HZA_^h>k1{aac7UW?nQI9DJFI75xG09{w(Fmn z8MtIv7?h#wmy4lmDi%Y_ZSi#wvpTa`7@D(L777nnHZiM zGcY{6#K=%m3UMQ{>iqT04CkTq3Ol19^4UKb8SX&$cJV|&+);gtfx%-PBZK!5W`+o8 zTlo7P1_s|hObqR3nHip3fT&vmEkBU$0I`{0GciP0GBNyYM1=LU0tN=TVkU;miy0Ys z!0pw!1IEUfm@G>VWA}h!$K)WhMg`944a_q7+TLm^n+|TD~8BR z-O%~fjjT)z|Mi&|l%Va9z0fseAoU>Z$ zON@cxX%#cWG^Dm8NUxz2Bg3joObj7G%nZz*7#SLD7#LI>85kI$^OcqgX z(uslLb1pN(@?Q)L%Nm#%?3x%D?(;G+Jif!ka7Lbm;kGd|!&YBrhGi^F3`Zpx8D8@- zF?@AnV(7iVz#x{x!fR9U<`zV&lR-Rg4S`f0-Hfzhz`7>Ska#_mPp|R4W6+B`+q1yX_1Ng{L4oCw_s% z&y-9ihExj%23{2=24*WJhW}zr3_2+gH6T*Woq-`-AK?zQbIc4AplhK2PGDg8rN+P@ zs}52L!KJZG49}S%?hNop=!3{2$am0rhTD1!3{2gO3@W=JYF|R@$`uLHpHzU zHa2Vk)f1M-#PCgnnZflY1B1jzW(MPMW`-~4AZ~%_^MLNrk#A>a*t(3FA=!zE!Muct zfi;zhVcixc2G<$}hI`$N45Hr53`aB=7&w%e7}kAZWU%#QW-wr8VDPeHV&G+GWQaJ# z#PGg`ks-~2nc?w#CI;DQj0|2&nHl7kGc!zB&dl&;IWt4@6J~~jU(5_U{xUKciL)?N z1u!#A%4J~)`@qO>z>NCm6N59-T3dt+1A{Yky{##9zYt9BsU;JG zk~RYae>Wto8vK|U{=Z~ka2ID`IPJ~I@Zu07gHZ=F!+$j<22Ct;g8f2F40lwS7W(K)9L>>l-zC6vq@I{}Q!N8l5!E6HqLwy?)16vO>19Ltz!?!Jr z45prp4A%q^dT#t=U?}HgVd#9%#Grs>|EpCz3j;f}90r*W!jq~P8Cups(glcLbew^~ z!XCk&k2c@pb%U9~)0crk^)?g32QvnSDdr3e>xvl|KDID0gx_Ok*rm?GpxVH|@b(Kc zgKHuK1CJX6!wEMQhJE5J3?gbw3{z#97_>h!GF;SPVyH=GVR$~DfuXgUk>Tt*CWd9< z%nbja`#M2x0pa`W7#O-^85nq~nHc1e=I1+?GBDINF)^(2WoFoXk&&Syfq_AdlZm1J z2s48-(zvwGEs!Y)Ty=zrA!HQ;gXBXdhA*iM40Ga{7+T_)8S4BP7QBbVpO|8_JQ!@3lKMf z*dQ!27epd(v?>e39uA0J?URfQlNp&A8liKh_Gsfvhx-{AGNAKz$^wiGXQBOnuxZm7 z8BSO;Fw{c#Vt-0wVz>bvi@1bV$AHx{FfbJBGBX%J>v@=%)Hz0m1<-kGkXVa5#BCt< zRexrN9B6&WzlMQfu>d5Umq6=wUwe=$1_qyPj119D%nZ*B85x$WW?-mvWn`$o!o7jhtqcqrXBZf+Jz{2yD9!^n^<#Kgb>U1Kfm191~2O@jFOv@gqhCXHzBy-p9-g*7ghx3!!QC$9ZOk zeg-CnpQcO{85sm_F*5wQ!N?GClab-=K}Lq3a~T=T zqL~@a|7Bv>FoT(4T@51x*KtOM*IvvFT_(&7raKrI_OvlE_%t#x6k0Jdyena3hz(|D za8zVq5Z%SVz!A&D@EzJ`1=$J1qVt#;-azxX);varrGFV1Y%-Y{c29)3{Vwz@g6lP? zesI{u#GnMt&oHwXq3stCe~SYH16wEqLmoE^!_5XJhFh{M496sy87h$Wb)U>*Vc^`s z$WXe2kwIoBBg6llj0|$S85wqf8h9W>&~PVOn-U~FCl=LRATeZI0=1&_!_$eNcuyID3{|}Ib$brbY4;UC2`yJl#!uk1vA4=6$S>8&kPJI z_m~*CpEEKrc``6?yk=nVn#RQN?=2%k0xuK8$(u|Jk1H7&1UQ)(4)`)NuoW{i@F+7d z{0U)ZxUI&(5U0k#5Ua_+kfO!F;MC2)P|(f5AlJjd;N8Q(AQH;VP|?G{u(XGPVbMoM zhQx;q3`(aM7!LL^GAM6mV%U9yiQ%CYGeh$+Mh3^vj120AObor77#ITAGBc>JV`lif zj+x=|dS-@|8<-iAA22gqP-kRNddkeO<^wZB#cyVYzTeCYDjbXqm!W;A83GIp%2yZ} z7U(iCToPhnn6i?YVbf`5hQn7G7^KCR7&7u%7(x{wVKnU&1H+RJCWhu528Pxg1_r5Z z3=F$;85m@?F)+w&V_;C&#=xMoje$XB8v}#dHUkt!@!X0 zz{p@UiGktZ7Dk4>DU1wpg$xYozZn?*2Qx67eaFPGR*ivyOPzt?>;?vg^BWi#E^c68 zxOsz#;o@^9hQrqx7{axg7z(wS7>eF7GT3S}G1T2*V$eR$z`)4B%#h#3#L&jd#IP%a ziGf3bnPD~)14H9ACI-nf3=E$6j11*3nHXYUGBJFQVq$1|&A`Bzz|8Omv^PeTfkCZ- znSsBJnL&9kGsD8Y%nW%~m>C?OF)?I`Gcmk=&CGE712e-078ZtG>?{l!oGc8xxmXyg zUNACrC@?ZSOkrYZ;9+4%P-kIyo5sSxrOM2pD$2r;Q_0AXlf%NmZpOs09eRe#*}ssm zR6WnY-~&B3cq zI5`;@m{u_}ynVsIFn_!<$TI zhD*m874{NGcq{JF)$p^V_+!y!oYCvHUmT9V+MxX zPZ=02&oVN^IWjPuW?^8st-`<{e4Ux$=}l&a!u!k&yKXZuoVm@wF#SF=!yh|lhV}QE z8KzETU^te-#PC~&f#EuIpB>0`j7WROKztBBdybJI@;xI%cm)$fS{O4!m?I=y#VQyW z-s>=q0R=b-Jd#m|@-f*cqbjzZV+rr0wxyj#n_;M>g1@T!P~A>ImPG6Zku zU}PxiW@NbhkAdMi^eh;N41^R4V`gZ9j{kQTFfy1&F*7j5GcZ`xFfp)-Gca`XGBHHk zGcauBVPbH8%*gO^DlIObqJKaELt5#840I zS4Es*W{8w#WLRqq2{VvAAS{v(A{iL$qnH>x#h4gAPhe!2^_!7F{16kv?O+Cm`O_H~ zmON)<(0&5ZC&84NcwGc4ZB%pkgjnW23P zGsDj<%nYGhnHgFFnHg?sGcg?B%FJN7jhR8|Ix~a%J!XbeZ_ znHXlEjeRad8{IBiSs1=S z`}5n8_Nz%i$IZbSu@HY97#VV%85vliYip2|)Tcw@0$D8Dfsx?=w9a<-W?ZQDNffbdw!jKD^ zh-YA6FpFejNasf6AJ1D%C`O4}F)%3HXJY6$2N7PA2cbcvZUO_t-p33K{c{-@&b^hwv<5YafuU22iDBMDMutQ885x=$FfusZV`N~u&&a^d z%fz6xgoz>QBO^l)ClkXRE+&SP=NTC;axpX188a~Kv1VXUvtnXsY-MC%+Q`K4@*^X| zdQoPEY&2Dt}}44HgP43(YC z4402GGdTTZWY}_rnPKU3W`+uOL>R74U|~p$Wnm~rD*p~Z%b3FzObqiPnHl!pV`8{+ zn~_0>frUX%orU3M5etLhdPau-yO|gqOqdviRx&Vbv|?l^k6~i?BFD(EFpq(uG=qV` zFolU>bp;bchcz>Uk_#^0=57+QEA)K%vaQVCc`p@Q90r!4H~N z;%+c8Tux$U*o5R(h)M`4j-}039mvSwd69u(!yZP4d}tr;1a#jmNY{dij11+{Obm6W zm>D)cV`5lyjF~~yi-F<9Vn`g@8Za~5y3EL6aU7AZR(@w>sDZBa1DVnDg_$AX3L}F8 z(z>jaXcmS^ZVU|B_Dl?X7Z?}{92pqmV-RNKL(l92>HqJ=#PDnZGsA7PJw+fnZ1~ax zsM|Cl^nu4r45pxoH7tsosu&sa8yOkYp?U(}LeeEjDOV69!x?cVhI|=jhO!@w3^ogy z8Q7c{7?Oh+7$Ovy8D2OrF!=T`Fia9*Wca;^iQyIpBZGSZ3&XM3Obn-IFf#;iXJBCa z1#tt&yt_}B8IExy{Ky9#V*ts4uxUL5!y9NaTL-O!LE^}GPX-G^NH#Nr`(tK?{eKx4 zb~!OIoQCcbMpoy0n32Jsm4V^hJ4ObnG)9IbM{o$TaIlh+AW$85sU$GBFsNGca6+j!lEqSna04drHO%IXA1*EgdGzDvo8~ad@}=sWD5g>`Uxh6bTNn;5cz&3Bg0#08DRC2 zf#Jg&28LD!28J{Lm>2>cFfbhHWn#E4!^E)Y5fg*K5hjL)Eldpi_T{cFByTyzQO?Ma=o_8@Z zj0|h6nHZSn zF)*liF*8&mtx1?70`bG7Ees6L3Yi!J1(+DFgflW!GBGfOnlLj+c{4HmTE@WO)y%}u z&&R^hAp}u>T$YL9RTl$;ST_TMOE<&~FV8~K6o^+C4k96V&U1wLd2?ol3NJ_)*?nbX z;Pz!?(3;A?u+Nc!;l~9=hSodG40G==Gh~-AF>HnIH`m_H%&^9SiJ|d2GebJkSw0}s z(_~l}-djM-SLgwWFfeS|$;5DJFEhgmRYr#DUyKZO%!~{QbC?-EEM{Uzh0X^+R3gY% z)r<@uelsvUOlD@deT$i48}y7CgbLiO!&?{_%6yp^1U5jze+qOh{Ml#*hGmsZ41$)7 z43pk6GCZqcVAy?-i9vA}#JzdPA?jbOW?*P^hlB~pmYdME{vfua69dBv6GjG80Y(O~ z?~Du=GMO1{?=dqRhR%V3)RY{AnD^{2#EeH$AW;PV2+dC*k)A?EhNEQ+47ci-7&e?_ zU|89~#845(#Gu!~z#y@kfgw7Jfg%4Z1B2oZ28P~QObkqD;pMjwnx`&BF zh=GCeFf&8>HD(5Ww0SOwE(V6l&~>^nK01A8JtM=PtBec=AnQ<)hYi*F zWM(jxVqp-0&YQi1?osw|W?(qU#K2(snt>s$i-BQM7X!n-E(V4Oc}9kJNz4qtFF?Wr zFWy85t(BfRVyJuv(O---=2`uUi6QO^GlTM5MuyL^Obnm985pJ@ zt+iP{iIGA4J}B=oGO!+DW;hH@0}zuCWMeM_!)oX}(-w0`I^bBsz~Bm9_XkpWKa+`J z%47zHKew3}QhzZpAV;l083V(^?~Dxgu}lnIXBZh81sNFF5*Zkn_!$_MS2HkZ&u3tG z&&SA6+{euD5tSRWS*Y}wis;wCr{zLaSm6|dzT!xMj za3k#}m;*gW!2&vtUVEI8A!ZgM!+9A725TQ?1{EzP2Jbv(2A^dN3|00F4DlXJ3=g## z7*6>xF<1vNF(^ES#1kiUonFWUW`@M`3=C5gSs41V85kbcGBKo?F*7`a_TT>|LBa$S z4qf+{8SX?fGCT=oW+=JG%wST)#PH-S1B3VkW`_EE%nZ*f7#WsA+gltQj0~%xXOe>S zIz!JE4fSJS_;QVbL9>aGK@jb{n2SaX3|Z=o3?9(_I!K?QGsL|&o+8`<5{F?6BL;?L z;)pT;CO!wWmK{2l;Kk0wAaxj_=I{Z8S*MCv82%!)oniVx^ns^L3~Ns zIB}SPK`)q@;p`n|hTDpeFag=bB*VbK;=#o5;yDAu$ucH}4blt@2Tm|BFwbOQxOs<} zp&q)=B&U*rLED>|;kg9^!?R`v1~cf|5s(=my!AH3Ofl&G_M|8VhMVsg8Td0G;vh93 zeCh}@1KT+!20x^=7Vb8T3=C!r46(ilKO`fq&C)r`#4!656T{Ba5cxvr9*l)wm>J5y zGBX%_g@o}2E+&T4I*bgnpEEExWiT=19%g3X>tkjx_h4pFn#REJvw?}hW+wx~Jtl}b zAoswqATtxg7HE8f#8$pxU|9ZwnZXB1tQ9(E43d}kU}livVPLTIWnx%r$jq?oJQKsL zL`WI5Uy6YNRP5b{jyH+QvoPfCLJbFy8R%I1Iz-JH3xtfS9s|RN6o~(X1sEBe&OzLs zavCDW@)M#5q@zBXnIQ&g4z;_SiGdZ`o_@;7#1OB^z)(7cf#LQxh#8O4nHZi4Gcn{N z?O6hu1H)%Mm>9YYAbtXgtn;<+d1yMCvW|hlIuhb$-fIjDCkt2@mRmA2XlFAq%)ZCKFcE1D^KvZ) zhM0PYnO+~673>^h1mN9 zP2LDPHXZkziD7d+BZEXD6NAQ5Muxy`3=Bq@OblBlF*CG$V_?|zkC{P`jhTU4n1w;z ziG@L!m5E`sGBd-BE=C5uL9-jf-ritjIChJX;Yk7`!|xI%hKchT7JG{GBcE1WMcSg&%m%Gn~8xRT9$y+!|+<9@d%h0i2f1G%#aT~b1&)z zBSW_w#N8mdV(59kEu{<$@pViLtG$>RexaRvETY52z|hOUum@VV3PQ(PLHa>B-wtA) z_d_Oz)(;E}`-LHX3GrlNh=iW?3{rPz83Tjndk_nOUqjat`Xn$gyslwl_*urtpl-&% zFzqe_!&?JJ1|R4+0GSor$*C9+~V2D4?$Z+Hj0|Nte zui~yNj11qBSQ!3?F*8Uiu`o=6wtb_PGB8{*Wn$oAXJA-=j)}qI4iiI`HzUKma0Z5K zUWgwSK!9bE zOopC`^%}ZIavOBbIZO|XmKS7UNP>>fmw#tuD4GtFLC}FEkUR(yS%b8$a@G%KhAMt0 zhS_;640oY*{rw;YhJDi*7*g+p_AxRuOnlGC(07-aVc!jAhM&9)3?&hv&z*&#E)Alt3tAp%ykTaz%D~7FAQBc!%Pedk@lK}LdW$ZXCll-W(nCbF`Rn9z_7NLfk9y_6NB41Muw%GObi~+7#Nx+ zF){3a#=yXC&cJZrl7S(|n1NvpHzR{EGb6)>Xl4dZ1||lXWy}nQjtmT6%^4V$=`b+7 zsb^-W-Nek$(9g)=CC$XpH-~{CxRHTDrImp}w2^_qx{-n5!%}93mv%<#^Mks;BYnc+qTGeh$i zMg}b#MuwMLnHlt!Ff$ZJGBKRq$;=?Pl!4(h3kyTM2n)l}oeT^IZ5bG@w=pt2`p(3_ z^PP#I;wKY>2O~4X>1T`#i+(UMSo~sQ;QP(Q(D0jy;m&U+hO3}C>g~)7=dLm{q{gr? zn0;enND5(M@c+uhAP!yA2?{&T>xeMF?#jea`iz0WD*_<~T9P%t5~PxWVe2~vhMFn{ zhKoVW3@^_yFl>uvVd#L41FV8%QHVk)`KSm|7D2fTOFl6&ywYM~aJkCNAQsHTzzuCb zfaK@>XJFX&oQZ)igpt8xITHitOC|=DU`B=m&@(&KRxvXCHeg{;MVl8|fV7{T?=r&O zATvSuSUnTNy?Q2wZ}m(Jhp#X(oY!Vxi1^0Hkkrr2@HmBm!So6P!! zn16q0FE2GBJRPHrxA546Pp-7(AfsUqI?WIAT5{ z!yQuw20Lh*03@~_wxI*WVPIfTb7o*zHlLZ{<3eTzjq}V5+btOwJZu;kKvm({c!--b zSeO`$zc4cF(FL7p2hpgO&A>2oHUmT4IYtI61qKF*DrN?IbtZ<-77PpuNbQnfXqyM5 z>+^F)hMkj{8EVnSX*RuLVo98j zWJueMh_9TJObnC#nHkbRZ9Yy01~F(G6=DJdL-juM1yY=`OLgzi-jZf9ULmw zC@nKFF*JoSG3>d*%y8-kGeeyt1H(Nr28KjU76#V+ObncbOblvv%naroj0`0`%nWi@ znHf&XvM}sG+8Y{xW&R#y*V-LS4BEQP4D*gLF{mJo6}tXmW>|d`;yz;+Muq?e28M^w zeI_7%t*H<>5F3P9-$2}dGK`TyN1U1A=`BWvZMPX2<~)RmgVezAg*_0lN%xo;7DL-r zcUl=4wnE$LFm;wld-Y&q$n@>o%nX8_Obm~rnHUtg7#X7GGB9j(Wnxf@VrI}UWMELJ zV`BKDz{0R;EhEDfX!&*Gm_FfhnHV`gwEhNxYChk;>_0wY6f4FkghRwjnoaZC(uptH`O zFfn*MU}i8vnwy>ky$1%QbAvR*-Pz_03}SgK49Sg*3?ZqE4AO2)40X``Gaz*!+*roI z;K;+okg3MN&<~v_2Z`5TVP?iozHfUbr$a7??3J*d{PCeDG#ukbBL?L($OlB-botW{7BJU^th`#E@>p#NcwBnIRK8Mp19t{U2Lr=(s9PXB(4Kxq zhRQ}J29Z=m7>HUjFt|d`E4b~<#IW-hBg51;j0{^3LEJX$2s6X_t4s{;Y)lNiri={H z?;zqZGePvxDIk)8K~98$p}3TpVRi}=Llt!V|MFR81{r8y-(nvFgE44L);T5yc}XUQ zSt%?GM?m8|IZOGt3M}tymb6vk>XR04<)`3K$r^F)=Zy z88b0V6J=)Dn#95ovl(O?1b0U|8UWzmZc@A2xfXp!tV`iv>&U@`sV`5O; ziR!mEix?TiO&J)HG8q{hBbXWbxR@BuaxgN)^PsAmcMlS_ZqTuOKJ)|L7#JAJkix(Q zdd>>S4I+P;7%o~eFjyeXae&0{LC*{Uv5CPU3``6gq5GUc>P7Py8J;8EMR%--kwF2v z_Tc&@CWiB87#S4qqWS}*&(;7E&biRL{TM@-7-pPiVyHUB#K3))iDBj$CWZ+-Obj{c zObp++7#U{%V_;CZ%*YU8&cG0z!OZZ?h>_uRKQn_!3_cJq;$}=;_N+Ik(R(}k7=if2tzD;Dgv)dRLPND5rDUU){0bwWSGBGS`XJoM6 z#=sz>#=>xa9y3Ec7Zbx#Ck6%~EoO%KzRV0JNsJ83k=6@U@G>&+N;5EI2{AF;VrOAs zhVHL~n1~=JfDXe!aIv!F+87zGgflV3{bOS2`pU>~kc)|767>Arb0)AdbBLKC7`jiw8+IWY)Esmw&5VITU515Wwjc|`b2dhXztT($ z3*DI+#1k19)VUZK#1t7AmN_yqEPTSq(B#X^P$$gH@ZuE%LjrWYCAxWAPBAh}IK{|t z0JN7&hnXQph>^h+dbZbIrGca^t zWo8I^!_08QfQdngiG|_!6b6PpHOvf_94rj#Tr3RVA2Be5zF=UOq{zhZsGo^JZ3+{^ z(I*THSM-<}0wyvs$iHG>m^77%LC1-K!PT9a;q^mC2KPsd3@fi@WEQy8TJU;`& zQz1r%+b0s@HqzK9NRN3E3q!RY1H-K>CWeSIMh5#Sj12O93=G~Gj12mF zA?XaH4jW$Q&cHBh5(7h;6Enj%Z6<~aXg~LpJ2S&&=ov|mp>baIhnc|~Iz9+8>ppa! zxmOkg!@(bn3}x#X89>8hpzEDL@(tyT4Byu>F&IsSgvTxD+JHo~wMFaOnHjpCFf+`3 z!OZXpdj9`H==$5XH_-AEx_;+2JIG`No+-t^aMGKZq1K3*A)S|r;dnnYgI+Hq!^2vL znqAN{ai>7n4}wIGJZEHxoW;nnu^ZGsV_*n-&&aUAn1Nx63=_lFawZ0q1&j1wBt}%`GMd!9WIv%WjMe z^ZOVXZZ2kESnbHb5FpLWaMF;8!3}!uJ4g=*PkqL~uzwO0L;3_}hDEO#7>7d2vH za7Q}}1Edy&lO{7W>`P-{Sjx!6kW~%w-*GL}bjz*J#E{m?$gmhXK6n#p?8-%nTDem>4Ad7#X%cWMVM8 z#K>T($-waB0~3P+4hiG@MT4dQ-Cs4y_3@-Q)2@h~yy zJz-|(X=7l}KF-Xr;~NvhG65zAb5SOSbS?&l6A=syDL(UU3_8D=7SHE`m`h9y&ovnsw#YCsa3?V_uv9THd|+i_ zsN!T~5Nu~;SQW&;a6OEHVK(&4tha$o3>zYt8S0B5W-@(XV9=Vu#BlK?GeaPjHK9|q zSQu0-85nLGF))bpGBSvBLejRd4g*8ZStf>^3m6$ZQW+TBpyLY=Qz7JLXn6?Y39~UV zwC8|W3=C4xGx9;a14w7Oyo0t6OUyv~av=HnqctN#^fN{V?`Mn*yTh3nDmoY${I)VN zn7&|OP+?+XFnh|#P*TIpaM^@`q3aPdLsuswL;6cbhIc0z7!p=6FzEU*F-W&CG3?=G zVz}^+kzvbQW(L_L7KVk>K(?deW6*mFkVT81Ffkne4-qL=V`ebE$;_~WpON9jI*9u~ zGH;p~7#_GYFxWXTFnsc0W|(u3iD91yGsD&jMh3Si28KgSObllyK-4?vF)+A8`#2r% z7#LPhXJQaL%ES=-m61XH4kLq12?N8%P0S2ZzDx{X`xqDw@iQ_oLH8nn>_W!pmoP9m zG(qA6CLVp3ks@pbREEIq__d;{m{tB zptXUC;pt&UhJD`|8T_U(Gnj=lGW`3?$S}c}i9s};iGj(Ofx)7JnL&I$GsC;P%nZA< z7#J#`bCgq}L8dS;Y>s1Q(C%emh_hi}xR10}<-ivPhRiRF4BlvGoI!L!$Q>CB467b8 zFw{P0Vpy-l$na(|BZI>hCWanYMh5FgObli!%nTRHm>FJ|F*78A&cbM8U|=n0X4nwP z%%BK8Un&)?{V#=drbH(qYcZ^^VqlPZ!OY-0kC}l>fr;VoOD2ZzY77iZOpp|T?$32# zV0dW7$Z)NTnPJmmMuzO^%nV^a7#JofBh-aJ*?qc93AH%HK0G z-1lT=VAWz^xZK9faBc@P!*Nz-hAT2m3|dJ{3?E&Y7?h$Ba$tVVf=nG5?r5BhO`Y$jsOblRV=niFOa4=_J zs25;jIAG7fpi{`i&|Jd6a4(dJLA9TO!Dc5jgE~Jm!+li-hAeMp24OiChUD+e49rR_ z4Ev#FD#-rmxd`_>WoKc?*I{JPNMd1dgx66^XG$(&Vkj14X0Y7F!0?BGnZb1jGlR%=CWgnS z7#LiA85tVBF*B5EGBCWiXJimHWMJrNWMo+0$jH#p$jFclUDxt5m674nO9qCDCkzb2 z6PXx7r!q0P$ulwR|H#PT&c(oxlgGet`W6F2^D<_Jn#arx+oA0!kiTT0?b6UDMh3-m z%nV7;v0;#$0@^ytz(8h(#nCJbxxXQCaghz;&k$()5~SxlbWh{@LC%s@-s1{=rAzs z^kHUrD9X(6zL$YvksAZURiyL;GE1JHiD9E469a!0BZC{#nlYZ83=Ab37#aH5m>AaX zW@6BI#=sy3J-a#5jfo*sgPGwibpJod91vcp$->Z5z`~FNZQp^!X6$5Qc#brV{kMUU z;l+9;hW${#l}a%&%+z3Fc)OR0p*oL=;jst9k@GcouiF)=(eLF5;ZTd?5=7Z?~e zLf2w|Sv4$Z}V6fCP4FllPv?oPZ<`5wa~TF!4XTH4|40-olFe6f{=6w;v-`}3nqqpxyT}@?CHB17`C=EG5mz? zXX$&&#GtLl%iGsB^Gj0}^o++}TX4B|(aiLDQq7`l>K7!=<#F=${p z%ProKk)Z=Ru6#tBnW1tUBg1xci0;W13=9+BFf-WxV`8YnvF5&N6(fUU90S9}_lyiJ z)l3XVs*DV;A2Ks!yk%tQ^<`uLEx~Sm&%mG`%EYj$k%__PA0xy20w#ui`b-QxX$%Zn zr@JELoTt1bCPjxTZ2P z$U8AJ{5`|KP$9s?z$?ncu%&>JA-9u>q4G8(1IvFVh84FM85X!QFbMfGFihFTz_3Y| zg+bndk-@Quf#LQkNIWlggU}EgFi98a9*S3ikT`nj!obi_$iU#C$;hx|4kLpAwBMu| zz{KF14pAerosr?-RwjmuvkVM#&N47;f5X6V;4A}!trQaj?>PpBIz}djiFS+(^(Pq^ z9L1O!ShScJYNVJLVoxzLG`BM_c>QBwNSw#Sa4?yHVM9C;CMVFnxXcV|+!-0BSur!1IWRN$IWRL^cVS}q7RSus@r#jReLph; z>s|(ir?Z$DeqCc``23TRVWurJL+l%72G_654Bn9p43XcN7dp?GwefJy90`ih%`i-OH7%Cp&q(73nT}^byds^7v?fEsN7*@I5m%fA$~st z!Ny41v)MlQp3n_ z2|8yFk~jFpz%Y9b#BLBDgr^BZ(#$=id4G`jdp#zGO-;-UZ`4>AOxT$i_&h=PBQr5X zR5LT^G&3_eIx;g@K=(NMKW1iNfu0rad+k{^X)nHg54F)<_;F*3}Co<$B) zvG^?mgYPQ_h86zI45`q0-!BiD7&=QB8Ttd67(P#DW^jmPWY{y8nIR&bg<)|n3&T(7 z+Tpf728P$Km>Ar=m>4wOnHe%SGBZq&V`Ru+V`Av?W@ND6#LOVNnVF$|Gc&`wrwj}n zlb9F`tC<q{9Kr1ml}tY6E-a4a4Yeu}P447t#`tu231;|>&#FuY|o1H;P}CI&6& zn&Jgz3=CPv7#Sw?GcYWI?sNX!&%huDDqQ857z8<(7zCV|7=F%UU^o)b$nd_Ek-=>v z6GQAHW`-QlT;FOYhQvqA45^Qp8Qy6yFx+BiV$gid%uuAsz|gRdkztZ76T>=Co4|*W zAy}4)LHQFi1N$i^247u92CYtJ2KB#;3~4)<7-Upg7;>TeI$&;1N?~H?>SAV?8OOq4 z3LTGt$${v3qAUzTo{S9Nq4#g>Vnp?K1=9JZvDqLU5InC8p>Fm8CWgEl%nX4@_Xs>& z$-t1S$i$#w%E-VO$i(p6mWhFL0wcq=rOXVb`xqE>wlOfwe8kMK;}bK3_H#xC>*tIN zzrHXs_`PFbIP!^^!7vF@76{#BUeV5ob<%#b3$!jN|xVt>+p28M-xObpM~Ffh!> zWMs%~WnyUmz{s#xmWjdb76Zd9Z3c$d(-;^W5}6q0hA}f3eq~?~%VK7*DPv}kpTW#< z6nbCq%X3T&xgQuAZn!cq*q&#E7|y`Ju<0H%gE{mJ6p-N2tIQ1P9E=QwpnK|)m>6~< zoofb?$A*=lb0u>tnHh?p=TjbD0R5LNSzG7ymdBDu@I+ukZlAW1hMmz(<;V+B~8)}#s zcFuz20f;FGa*;bDLz6p#kIV|Y2Jy?D3TB2!p^OX>DBYGJbnnC+FD;OF67O*h5{bgjx>|kd2R?on2 zU?Bs;Or*Oq=an)th=)P^;}gQn(4xh_@bm~XLvB1H!{dGi1~(lBh6El4hOLSaHEVnr z8M2o$F|5jBWU!EAVaU10%&?%GiD9-D3qx-$BSXx3CI(eGCWbAX5cMDzX(ux=6h2~R zxF^oQkokz2A@>n8!`CiGh9{qy8ESShFodWvFfeH{FjUzvG89=bFig;7VA!9;#BeQ^ zi6OFx>Mqr!q3kV`66bWXr&?@Fo+(6+0#dm#K^lH>NN$99ho5z_^WxVNE|X!{#Z>3|do} z8Els_Gw{D>WSIMinc>?BW(LMMMh15i1_sH;%nWItnHipnvM?yhvoJio$jG3e$ii?v zg@xf=DhtB~=)9%j4@QQ)&I}B*plf>k7Jz(>z*Ck&!s6(528QGJnHhF}VrICn!NMSX zjftTRdM72ws2ztH7#`U%GiTt;Mut^8nHg9QGBY%ZGcz1y1kI~L(j&qJ*jav_3=F4`_R{?M2XSZpMMeg} zr%Vhnax4s>Che+q3=H2|nHYYRF)`d>Vq}P)&&06bih)5Xoq-{(jEN!RJ0ruBLPmzV zdr86`1H83%(;bLI8`j&xV)-+~@$80PNKE*5y=d2kS{AMyU_^UE7Ol)Lg zSmwdNV0oF5!TT&D!}elE2IaF145FzF3|n~_7`C2bVkm21Vz_*oiNOtN|1Sdr14AQp zzhquD14BM^%r750-wu+8;R#U;4EOUG7;KI+Gg#X(F+A2`X1MsCfnog-W`_JG28QTs z%nVxZnHg>sF)_H>GBBuKWoGDD%*gOhfQjMN7X}6m=$RTkcFYXlUobN8OkiekuV7@j zmchbc2i?!N_$LEH*c>K?4}X~$6ys6D{u~Pv!}btHhHL6f3`boV7(CRN80M)kF<2-w zF7&Sm>4#PF*E!zV`jL(&cq;khLNFb6*EKh zYGwwfHOve>=a?Dd1Q;2jRx&dL+b}Tbo?&FLTEfU6`i6l)2ih)VLR#nBcZ7jq(h&xR zX-60s%&iz11RR(c+^m=xW*uQ*n0JJMVS4~GLtPUCL%S9O!q zV2G$o3=Ae;nHes`GBRAxXJI&;3-PO*tlp7bh7R1dCZ1)&(;#++ks2kkEwGrBk8p#z12R2EEM;4EHxPFnrEr zX4q-M!cbzy!ccF)!f*?^9>ytwf#L3cNF16LGcu$;N7N5Y?-?1UBHc&%8@g{&>LUZg z`+OFLXy^EL`Zk&Sn3zi0NyFmDMPK*ruJ~1=Io3Su(E@ou#LOKHnq;_d869Zoo z3q!>}28Q(?85sW0U}9*2_WwchAS`3Yz`z*7z>u*Y#A9G^f!;d`;bAA6OPLr>LHn67 z74zRPF-%lrU{F5A#E_!TcBHB5FFgdv(Muxf@j0_tYm>KqEGcvqOV`kU{ zy*F+jv>m7hJ)61o93#UVw6)DD>lhf`WiT^*e9OdeJ(`ihc{?P$6Cxn)$bUpq$Li@M$eGgPR-+!xzxP1eik@7#R4g85y#n`$Ld~F_;e;85ok)nHct`Gc(M~ zgxJ&V$jqRU#mFG{l93_vIs*d>(wN(_Rm=Q7+TVq z82YX=GGyLmV3^m<#IQz*iNQ#Yg<nj-7-0b)!HRT0b#-Ozp>NKOWHZ-osbL&*{*23cJOhQ!Cr z3^Jz~8IoHV8D1V?Vz`pP%)sW(z)%v*%)nT~%<$nh14AF$8Um0xi)5J@Rzcf*ApV5& z5I6cEjZ=cek+FCM69fNeMuy(g3=CWMGBMouVP^1SVq~Z`W@Kp6WM<$@W@h+vhnayF zdX^-zUS#$a=-ra~cNiEx_cJmm6fiR^M`}}E`NqT`6vM(WTbzmE`a>oLXLDwT3#JSV zizhKMH2h#HE!*!7!F*EVP^P#lbIo#k%b|ai-n=10d!>sGlNGsGsABa28Pfw28MZcOboG07#Wh?nHa7q zGBGUFU}Si9jgev7Ze|8HaTbQ;A{GWU0Val|VkU+MB}@$b8Y~QF5*Zk>idh&Oq2t?5 z@(c{1Ys0HggT|1U7;4TiF}yp l3k%2j!f#LXbMh2;LMutEp28OdK%nb1{3=A?= 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 zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?3PwXRZa z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7zLvtFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;6Cw1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtqq)hQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk zz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By z2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mg(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!83@Fd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?3PwXRZa(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7zLvtFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;6Cw1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtqq)hQMeDjE2By2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk zz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By z2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mg(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!83@Fd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z3PwXRZa(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7zLvtFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;6Cw1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtqq)hQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk zz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By z2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mg(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 wfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fq@JG05MLWaR2}S literal 0 HcmV?d00001 diff --git a/BearSSL-OG/XboxOGBearSSL.sln b/BearSSL-OG/XboxOGBearSSL.sln new file mode 100644 index 0000000..490d6ce --- /dev/null +++ b/BearSSL-OG/XboxOGBearSSL.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XboxOGBearSSL", "XboxOGBearSSL.vcproj", "{021C5334-2823-495E-9E54-2DEC11E06040}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Profile = Profile + Profile_FastCap = Profile_FastCap + Release = Release + Release_LTCG = Release_LTCG + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {021C5334-2823-495E-9E54-2DEC11E06040}.Debug.ActiveCfg = Debug|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Debug.Build.0 = Debug|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Profile.ActiveCfg = Profile|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Profile.Build.0 = Profile|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Profile_FastCap.ActiveCfg = Profile_FastCap|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Profile_FastCap.Build.0 = Profile_FastCap|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Release.ActiveCfg = Release|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Release.Build.0 = Release|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Release_LTCG.ActiveCfg = Release_LTCG|Xbox + {021C5334-2823-495E-9E54-2DEC11E06040}.Release_LTCG.Build.0 = Release_LTCG|Xbox + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/BearSSL-OG/XboxOGBearSSL.suo b/BearSSL-OG/XboxOGBearSSL.suo new file mode 100644 index 0000000000000000000000000000000000000000..82488490ebb5ccde2c4dee936f661d5128b9b552 GIT binary patch literal 23040 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 YSO#_2f({CSjQr@*xby)Rd4q`n0CF#x_W%F@ literal 0 HcmV?d00001 diff --git a/BearSSL-OG/XboxOGBearSSL.vcproj b/BearSSL-OG/XboxOGBearSSL.vcproj new file mode 100644 index 0000000..0db671b --- /dev/null +++ b/BearSSL-OG/XboxOGBearSSL.vcproj @@ -0,0 +1,1381 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BearSSL-OG/bearssl.c b/BearSSL-OG/bearssl.c new file mode 100644 index 0000000..6e0af46 --- /dev/null +++ b/BearSSL-OG/bearssl.c @@ -0,0 +1,1640 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * BearSSL TLS backend for libcurl + * Designed for Xbox (Visual Studio 2003 / C89 compatible) + * + * This file implements the libcurl vtls interface using BearSSL. + * BearSSL is ideal for Xbox because: + * - Written in C89/C90 (VS 2003 compatible) + * - No dynamic memory allocation + * - Small footprint + * - No external dependencies + * + * Xbox-specific enhancements: + * - Trust anchors loaded from embedded CA database (750+ CAs) + * - Session caching for TLS resumption + * - Descriptive error messages + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_BEARSSL + +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "vtls.h" +#include "connect.h" +#include "select.h" +#include "multiif.h" + +/* Xbox-specific BearSSL integration */ +#ifdef _XBOX +#include "bearssl_xbox.h" +#define BEARSSL_XBOX_INTEGRATION 1 +#else +#define BEARSSL_XBOX_INTEGRATION 0 +#endif + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Xbox time validation callback for X.509 certificate checking. + * + * The Xbox's internal RTC is unreliable: no NTP (Xbox Live for original Xbox + * is defunct), CMOS battery may be dead after 20+ years, and the clock can + * reset to 2000-01-01 or similar. A wrong system clock causes BearSSL's + * time(NULL)-based date validation to reject perfectly valid certificates. + * + * We skip date validation entirely. Trust anchor verification and optional + * certificate pinning provide the real security guarantees. + * + * Return: 0 = within validity period (always) + */ +#ifdef _XBOX +static int bearssl_xbox_time_check(void *tctx, + uint32_t not_before_days, uint32_t not_before_seconds, + uint32_t not_after_days, uint32_t not_after_seconds) +{ + (void)tctx; + (void)not_before_days; + (void)not_before_seconds; + (void)not_after_days; + (void)not_after_seconds; + return 0; +} +#endif + +/* Secure cipher suites - ECDHE with AEAD only */ +static const uint16_t bearssl_secure_suites[] = { + BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +}; +#define BEARSSL_SECURE_SUITES_COUNT 6 + +/* + * ALPN protocol names for HTTP/1.1 + * + * ALPN (Application-Layer Protocol Negotiation) is a TLS extension that allows + * the client and server to negotiate which application protocol to use over + * the encrypted connection. Modern HTTPS servers (especially CDNs like + * Cloudflare) require ALPN to be present in the TLS handshake. + * + * Without ALPN, many servers will: + * - Reject the connection outright + * - Assume HTTP/2 and fail when receiving HTTP/1.1 + * - Reset the connection after handshake completes + * + * We advertise "http/1.1" since this libcurl build doesn't support HTTP/2. + */ +static const char *bearssl_alpn_protocols[] = { "http/1.1" }; +#define BEARSSL_ALPN_PROTOCOLS_COUNT 1 + +/* + * "No Anchor" X509 validator - wraps br_x509_minimal but accepts all certs. + * + * This approach uses BearSSL's proven certificate parsing code (br_x509_minimal) + * but overrides the validation result to always succeed. This is safer than + * implementing our own certificate decoder. + * + * Used when SSL_VERIFYPEER is disabled. + * + * NOTE: We use a POINTER to the minimal context (not embedded) to avoid + * memory layout issues with the union in ssl_backend_data. + */ +typedef struct { + const br_x509_class *vtable; + br_x509_minimal_context *minimal; /* Pointer to minimal validator */ + /* Certificate pinning: hash the leaf (first) certificate */ + br_sha256_context pin_sha256; /* SHA-256 running hash of leaf cert */ + unsigned char leaf_hash[32]; /* Final SHA-256 of leaf certificate */ + int cert_index; /* 0 = leaf cert, increments per cert */ + int leaf_hash_valid; /* 1 if leaf_hash has been computed */ + char pin_hostname[256]; /* Hostname for pin lookup */ +} br_x509_noanchor_context; + +/* Forward the call to minimal validator */ +static void xc_noanchor_start_chain(const br_x509_class **ctx, + const char *server_name) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: start_chain called, ctx=%p, xc=%p, minimal=%p\n", + (void*)ctx, (void*)xc, (void*)xc->minimal); + OutputDebugStringA(dbg); + if(xc->minimal) { + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: server=%s, minimal->vtable=%p\n", + server_name ? server_name : "(null)", + (void*)xc->minimal->vtable); + OutputDebugStringA(dbg); + } + } +#endif + if(!xc->minimal || !xc->minimal->vtable) { + OutputDebugStringA("BearSSL noanchor X509: ERROR - minimal or vtable is NULL!\n"); + return; + } + + /* Reset pinning state for this new chain */ + xc->cert_index = 0; + xc->leaf_hash_valid = 0; + memset(xc->leaf_hash, 0, sizeof(xc->leaf_hash)); + if(server_name) { + strncpy(xc->pin_hostname, server_name, sizeof(xc->pin_hostname) - 1); + xc->pin_hostname[sizeof(xc->pin_hostname) - 1] = '\0'; + } + else { + xc->pin_hostname[0] = '\0'; + } + + xc->minimal->vtable->start_chain(&xc->minimal->vtable, server_name); + OutputDebugStringA("BearSSL noanchor X509: start_chain forwarded OK\n"); +} + +static void xc_noanchor_start_cert(const br_x509_class **ctx, uint32_t length) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL noanchor X509: start_cert[%d], length=%u\n", + xc->cert_index, (unsigned)length); + OutputDebugStringA(dbg); + } +#endif + /* For the leaf certificate (index 0), start hashing for pin check */ + if(xc->cert_index == 0) { + br_sha256_init(&xc->pin_sha256); + } + xc->minimal->vtable->start_cert(&xc->minimal->vtable, length); +} + +static void xc_noanchor_append(const br_x509_class **ctx, + const unsigned char *buf, size_t len) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; + /* Feed leaf certificate bytes into SHA-256 for pinning */ + if(xc->cert_index == 0) { + br_sha256_update(&xc->pin_sha256, buf, len); + } + xc->minimal->vtable->append(&xc->minimal->vtable, buf, len); +} + +static void xc_noanchor_end_cert(const br_x509_class **ctx) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; +#ifdef _XBOX + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL noanchor X509: end_cert[%d]\n", + xc->cert_index); + OutputDebugStringA(dbg); + } +#endif + xc->minimal->vtable->end_cert(&xc->minimal->vtable); + + /* Finalize the SHA-256 hash of the leaf certificate */ + if(xc->cert_index == 0) { + br_sha256_out(&xc->pin_sha256, xc->leaf_hash); + xc->leaf_hash_valid = 1; +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: leaf cert SHA-256: " + "%02X%02X%02X%02X%02X%02X%02X%02X...\n", + xc->leaf_hash[0], xc->leaf_hash[1], + xc->leaf_hash[2], xc->leaf_hash[3], + xc->leaf_hash[4], xc->leaf_hash[5], + xc->leaf_hash[6], xc->leaf_hash[7]); + OutputDebugStringA(dbg); + } +#endif + } + xc->cert_index++; + +#ifdef _XBOX + /* Log the minimal validator's state after processing certificate */ + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: minimal->err=%d, pkey.key_type=%d\n", + xc->minimal->err, xc->minimal->pkey.key_type); + OutputDebugStringA(dbg); + + if(xc->minimal->pkey.key_type == BR_KEYTYPE_RSA) { + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: RSA key - n=%p nlen=%u e=%p elen=%u\n", + (void*)xc->minimal->pkey.key.rsa.n, + (unsigned)xc->minimal->pkey.key.rsa.nlen, + (void*)xc->minimal->pkey.key.rsa.e, + (unsigned)xc->minimal->pkey.key.rsa.elen); + OutputDebugStringA(dbg); + } + else if(xc->minimal->pkey.key_type == BR_KEYTYPE_EC) { + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: EC key - curve=%d q=%p qlen=%u\n", + xc->minimal->pkey.key.ec.curve, + (void*)xc->minimal->pkey.key.ec.q, + (unsigned)xc->minimal->pkey.key.ec.qlen); + OutputDebugStringA(dbg); + } + } +#endif +} + +static unsigned xc_noanchor_end_chain(const br_x509_class **ctx) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; + unsigned result; + + /* Call the minimal validator's end_chain */ + result = xc->minimal->vtable->end_chain(&xc->minimal->vtable); + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: end_chain, minimal returned %u (err=%d)\n", + result, xc->minimal->err); + OutputDebugStringA(dbg); + } +#endif + + /* + * Override the result: accept certificates in insecure mode. + * + * When SSL_VERIFYPEER is disabled, we accept all validation errors: + * - BR_ERR_X509_OK (32) - success + * - BR_ERR_X509_EXPIRED (54) - certificate expired or not yet valid + * - BR_ERR_X509_DN_MISMATCH (55) - issuer/subject DN mismatch + * - BR_ERR_X509_BAD_SERVER_NAME (56) - server name doesn't match cert + * - BR_ERR_X509_NOT_TRUSTED (62) - no matching trust anchor + * + * We only fail on actual parsing errors (33-52) which indicate a + * malformed certificate that cannot be used. + */ + if(result == BR_ERR_X509_OK || + result == BR_ERR_X509_EXPIRED || + result == BR_ERR_X509_DN_MISMATCH || + result == BR_ERR_X509_BAD_SERVER_NAME || + result == BR_ERR_X509_CRITICAL_EXTENSION || + result == BR_ERR_X509_NOT_CA || + result == BR_ERR_X509_FORBIDDEN_KEY_USAGE || + result == BR_ERR_X509_WEAK_PUBLIC_KEY || + result == BR_ERR_X509_NOT_TRUSTED) { + + /* + * Certificate pinning check: if a pin is registered for this hostname, + * verify the leaf certificate hash matches. This runs even in insecure + * mode because pinning is an explicit trust decision by the application. + */ +#if BEARSSL_XBOX_INTEGRATION + if(xc->leaf_hash_valid && xc->pin_hostname[0] != '\0') { + if(!bearssl_xbox_pin_verify_hash(xc->pin_hostname, xc->leaf_hash)) { +#ifdef _XBOX + OutputDebugStringA("BearSSL noanchor X509: CERTIFICATE PIN MISMATCH - rejecting!\n"); +#endif + return BR_ERR_X509_NOT_TRUSTED; + } + } +#endif + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: accepting certificate (insecure mode, result=%u)\n", + result); + OutputDebugStringA(dbg); + } +#endif + return 0; /* Success */ + } + + /* For actual parsing errors (bad certificate format, etc.), we still fail */ +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: certificate parsing error %u\n", result); + OutputDebugStringA(dbg); + } +#endif + return result; +} + +static const br_x509_pkey *xc_noanchor_get_pkey( + const br_x509_class *const *ctx, unsigned *usages) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; + const br_x509_pkey *pk; + + /* Get the public key from the minimal validator */ + pk = xc->minimal->vtable->get_pkey(&xc->minimal->vtable, usages); + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: get_pkey returned %p (err=%d, key_type=%d)\n", + (void*)pk, xc->minimal->err, xc->minimal->pkey.key_type); + OutputDebugStringA(dbg); + } +#endif + + /* + * The minimal validator only returns the key if err is OK (32) or + * NOT_TRUSTED (62). For other validation errors like BAD_SERVER_NAME (56), + * EXPIRED (54), etc., it returns NULL even though the key was parsed. + * + * In insecure mode, we need to return the key for any validation error + * as long as the key itself was successfully parsed. + */ + if(!pk) { + /* + * Minimal validator didn't return key. Check if the key was parsed + * successfully - if so, return it directly. This handles validation + * errors like BAD_SERVER_NAME where the cert is valid but doesn't + * match requirements we're choosing to ignore. + */ + if(xc->minimal->pkey.key_type == BR_KEYTYPE_RSA || + xc->minimal->pkey.key_type == BR_KEYTYPE_EC) { +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: returning key directly (err=%d bypassed)\n", + xc->minimal->err); + OutputDebugStringA(dbg); + } +#endif + if(usages) + *usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN; + return &xc->minimal->pkey; + } +#ifdef _XBOX + OutputDebugStringA("BearSSL noanchor X509: ERROR - no valid key available!\n"); +#endif + } + + return pk; +} + +static const br_x509_class br_x509_noanchor_vtable = { + sizeof(br_x509_noanchor_context), + xc_noanchor_start_chain, + xc_noanchor_start_cert, + xc_noanchor_append, + xc_noanchor_end_cert, + xc_noanchor_end_chain, + xc_noanchor_get_pkey +}; + +/* + * Legacy insecure validator kept for reference but not used. + * The noanchor approach above is preferred. + */ +#if 0 /* DISABLED - using noanchor instead */ + +typedef struct { + const br_x509_class *vtable; + br_x509_decoder_context decoder; + br_x509_pkey pkey; + unsigned char pkey_data[BR_EC_KBUF_PUB_MAX_SIZE]; + unsigned char rsa_n[512]; + unsigned char rsa_e[8]; + int first_cert; + int pkey_valid; + uint32_t expected_len; + uint32_t received_len; +} br_x509_insecure_context; + +static void xc_insecure_start_chain(const br_x509_class **ctx, + const char *server_name) +{ + br_x509_insecure_context *xc = (br_x509_insecure_context *)ctx; + (void)server_name; + xc->first_cert = 1; + xc->pkey_valid = 0; +} + +/* ... rest of insecure implementation ... */ + +#endif /* DISABLED */ + +/* BearSSL backend data structure */ +struct ssl_backend_data { + br_ssl_client_context sc; + br_x509_minimal_context xc_minimal; /* Minimal X509 validator */ + br_x509_noanchor_context xc_noanchor; /* Noanchor wrapper (small, just vtable + pointer) */ + int using_noanchor; /* Are we using the noanchor (no-verify) validator? */ + unsigned char iobuf[BR_SSL_BUFSIZE_BIDI]; + br_sslio_context ioc; + int active; /* Is the SSL connection active? */ + int session_resumed; /* Was session resumed? */ + int io_error; /* Have we had a socket I/O error? Skip graceful close if so */ + unsigned char leaf_cert_hash[32]; /* SHA-256 of leaf cert (from X.509 callback) */ + int leaf_cert_hash_valid; /* 1 if hash was captured */ + char hostname[256]; /* Hostname for session caching */ +#if BEARSSL_XBOX_INTEGRATION + br_x509_trust_anchor *file_anchors; /* Per-connection CAs from CURLOPT_CAINFO */ + size_t file_anchor_count; +#endif +}; + +#define BACKEND connssl->backend + +/* Forward declarations for send/recv functions */ +static Curl_recv bearssl_recv; +static Curl_send bearssl_send; + +/* Global state for trust anchor initialization */ +static int bearssl_trust_anchors_loaded = 0; +#if BEARSSL_XBOX_INTEGRATION +static int bearssl_trust_store_updated = 0; +#endif + +/* Low-level socket read callback for BearSSL */ +static int +sock_read(void *ctx, unsigned char *buf, size_t len) +{ + curl_socket_t fd = *(curl_socket_t *)ctx; + ssize_t rlen; + + /* + * Simple blocking read - no retry loop. + * The socket should already be in blocking mode, and libcurl manages + * timeouts at a higher level. We just do a single recv() call. + */ + rlen = recv(fd, (char *)buf, (int)len, 0); + + if(rlen > 0) { + /* Success - got data */ +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL sock_read: got %d bytes\n", (int)rlen); + OutputDebugStringA(dbg); + } +#endif + return (int)rlen; + } + + if(rlen == 0) { + /* Connection closed by peer */ +#ifdef BEARSSL_VERBOSE_DEBUG + OutputDebugStringA("BearSSL sock_read: connection closed by peer\n"); +#endif + return -1; + } + + /* rlen < 0 - error */ + { + int err = SOCKERRNO; +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL sock_read: recv error %d\n", err); + OutputDebugStringA(dbg); + } +#endif + + /* For EINTR, we could retry, but it's simpler to let the caller handle it */ + if(err == EWOULDBLOCK || err == EAGAIN) { + /* Would block - return 0 to indicate no data available yet */ + /* BearSSL will handle this appropriately */ + return 0; + } + + /* Real error - return -1 */ + return -1; + } +} + +/* Low-level socket write callback for BearSSL */ +static int +sock_write(void *ctx, const unsigned char *buf, size_t len) +{ + curl_socket_t fd = *(curl_socket_t *)ctx; + ssize_t wlen; + + /* + * Simple blocking write - no retry loop. + * The socket should already be in blocking mode, and libcurl manages + * timeouts at a higher level. We just do a single send() call. + */ + wlen = send(fd, (const char *)buf, (int)len, 0); + + if(wlen > 0) { + /* Success - data sent */ +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL sock_write: sent %d bytes\n", (int)wlen); + OutputDebugStringA(dbg); + } +#endif + return (int)wlen; + } + + if(wlen == 0) { + /* No data sent - treat as would-block */ + return 0; + } + + /* wlen < 0 - error */ + { + int err = SOCKERRNO; +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL sock_write: send error %d\n", err); + OutputDebugStringA(dbg); + } +#endif + + if(err == EWOULDBLOCK || err == EAGAIN) { + /* Would block - return 0 to indicate no data sent yet */ + return 0; + } + + /* Real error - return -1 */ + return -1; + } +} + +/* Get descriptive error message for BearSSL error code */ +static const char * +bearssl_error_string(int err) +{ +#if BEARSSL_XBOX_INTEGRATION + return bearssl_xbox_error_string(err); +#else + /* Fallback error messages for non-Xbox builds */ + switch(err) { + case BR_ERR_OK: return "Success"; + case BR_ERR_BAD_PARAM: return "Bad parameter"; + case BR_ERR_BAD_STATE: return "Invalid state"; + case BR_ERR_UNSUPPORTED_VERSION: return "Unsupported TLS version"; + case BR_ERR_BAD_VERSION: return "Bad TLS version"; + case BR_ERR_TOO_LARGE: return "Record too large"; + case BR_ERR_BAD_MAC: return "MAC verification failed"; + case BR_ERR_NO_RANDOM: return "No random seed"; + case BR_ERR_UNKNOWN_TYPE: return "Unknown record type"; + case BR_ERR_UNEXPECTED: return "Unexpected message"; + case BR_ERR_BAD_CCS: return "Bad ChangeCipherSpec"; + case BR_ERR_BAD_ALERT: return "Bad alert"; + case BR_ERR_BAD_HANDSHAKE: return "Bad handshake message"; + case BR_ERR_OVERSIZED_ID: return "Oversized ID"; + case BR_ERR_BAD_CIPHER_SUITE: return "Bad cipher suite"; + case BR_ERR_BAD_COMPRESSION: return "Bad compression"; + case BR_ERR_BAD_FRAGLEN: return "Bad fragment length"; + case BR_ERR_BAD_SECRENEG: return "Bad secure renegotiation"; + case BR_ERR_EXTRA_EXTENSION: return "Extra extension"; + case BR_ERR_BAD_SNI: return "Bad SNI"; + case BR_ERR_BAD_HELLO_DONE: return "Bad HelloDone"; + case BR_ERR_LIMIT_EXCEEDED: return "Limit exceeded"; + case BR_ERR_BAD_FINISHED: return "Bad Finished message"; + case BR_ERR_RESUME_MISMATCH: return "Session resume mismatch"; + case BR_ERR_INVALID_ALGORITHM: return "Invalid algorithm"; + case BR_ERR_BAD_SIGNATURE: return "Bad signature"; + case BR_ERR_WRONG_KEY_USAGE: return "Wrong key usage"; + case BR_ERR_NO_CLIENT_AUTH: return "No client auth"; + case BR_ERR_IO: return "I/O error"; + default: + if(err >= 256 && err < 512) + return "Received fatal alert from server"; + if(err >= 512) + return "Sent fatal alert to server"; + return "Unknown SSL error"; + } +#endif +} + +static int Curl_bearssl_init(void) +{ +#if BEARSSL_XBOX_INTEGRATION + /* Initialize trust anchors from Xbox certificate store */ + if(!bearssl_trust_anchors_loaded) { + bearssl_xbox_init_trust_anchors(); + bearssl_xbox_session_init(); + bearssl_trust_anchors_loaded = 1; + } +#endif + return 1; +} + +static void Curl_bearssl_cleanup(void) +{ +#if BEARSSL_XBOX_INTEGRATION + if(bearssl_trust_anchors_loaded) { + bearssl_xbox_session_shutdown(); + bearssl_xbox_cleanup_trust_anchors(); + bearssl_trust_anchors_loaded = 0; + bearssl_trust_store_updated = 0; + } +#endif +} + +static size_t Curl_bearssl_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "BearSSL/0.6-Xbox"); +} + +static CURLcode Curl_bearssl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ + br_hmac_drbg_context rng; + br_prng_seeder seeder; + + (void)data; + + seeder = br_prng_seeder_system(NULL); + if(!seeder) { + return CURLE_SSL_CONNECT_ERROR; + } + + br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0); + if(!seeder(&rng.vtable)) { + return CURLE_SSL_CONNECT_ERROR; + } + + br_hmac_drbg_generate(&rng, entropy, length); + return CURLE_OK; +} + +static CURLcode +bearssl_connect_step1(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + br_x509_trust_anchor *trust_anchors = NULL; + size_t trust_anchor_count = 0; + int session_resume = 0; +#if BEARSSL_XBOX_INTEGRATION + br_ssl_session_parameters session_params; +#endif + + /* + * NOTE: BACKEND memory is pre-allocated by the vtls layer in url.c as part + * of a single contiguous block for all SSL contexts. We must NOT allocate + * or free it ourselves - that would corrupt the heap. + * + * See url.c:allocate_conn() which does: + * conn->ssl[0].backend = (void *)ssl; + * conn->ssl[1].backend = (void *)(ssl + sslsize); + * conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize); + * conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize); + */ + DEBUGASSERT(BACKEND != NULL); + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL step1: Using pre-allocated backend at %p, size=%u bytes\n", + (void*)BACKEND, (unsigned)sizeof(struct ssl_backend_data)); + OutputDebugStringA(dbg); + } +#endif + + /* Clear the backend structure for fresh initialization */ + memset(BACKEND, 0, sizeof(struct ssl_backend_data)); + + /* Store hostname for session caching */ + strncpy(BACKEND->hostname, hostname, sizeof(BACKEND->hostname) - 1); + BACKEND->hostname[sizeof(BACKEND->hostname) - 1] = '\0'; + BACKEND->session_resumed = 0; + +#if BEARSSL_XBOX_INTEGRATION + /* Auto-download cacert.pem on first connection if not on disk. + * Done here (not in Curl_bearssl_init) because XNet needs time + * after DHCP before TCP connects work reliably. */ + if(!bearssl_trust_store_updated) { + bearssl_trust_store_updated = 1; + bearssl_xbox_update_trust_store(); + } +#endif + + /* Check if certificate verification is disabled */ + if(!SSL_CONN_CONFIG(verifypeer)) { + /* + * No verification - use the "noanchor" validator that wraps br_x509_minimal + * but accepts all certificates. This leverages BearSSL's proven certificate + * parsing code while bypassing the trust validation. + */ + OutputDebugStringA("BearSSL: Certificate verification DISABLED - using noanchor validator\n"); + BACKEND->using_noanchor = 1; + +#ifdef _XBOX + { + char dbg[512]; + msnprintf(dbg, sizeof(dbg), + "BearSSL: BACKEND=%p, sizeof(ssl_backend_data)=%u\n", + (void*)BACKEND, (unsigned)sizeof(struct ssl_backend_data)); + OutputDebugStringA(dbg); + msnprintf(dbg, sizeof(dbg), + "BearSSL: sizeof(br_ssl_client_context)=%u\n", + (unsigned)sizeof(br_ssl_client_context)); + OutputDebugStringA(dbg); + msnprintf(dbg, sizeof(dbg), + "BearSSL: sizeof(br_x509_minimal_context)=%u\n", + (unsigned)sizeof(br_x509_minimal_context)); + OutputDebugStringA(dbg); + msnprintf(dbg, sizeof(dbg), + "BearSSL: &BACKEND->sc=%p, &BACKEND->xc_minimal=%p\n", + (void*)&BACKEND->sc, (void*)&BACKEND->xc_minimal); + OutputDebugStringA(dbg); + } +#endif + + OutputDebugStringA("BearSSL: Calling br_ssl_client_init_full...\n"); + + /* + * Initialize the SSL client with the minimal X509 validator. + * We pass NULL trust anchors - the minimal validator will fail with + * NOT_TRUSTED, but our noanchor wrapper overrides that to accept anyway. + */ + br_ssl_client_init_full(&BACKEND->sc, &BACKEND->xc_minimal, NULL, 0); + + OutputDebugStringA("BearSSL: br_ssl_client_init_full done\n"); + +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL: xc_minimal at %p, xc_minimal.vtable = %p\n", + (void*)&BACKEND->xc_minimal, + (void*)BACKEND->xc_minimal.vtable); + OutputDebugStringA(dbg); + } +#endif + + /* Set up the noanchor wrapper to point to the minimal validator */ + BACKEND->xc_noanchor.vtable = &br_x509_noanchor_vtable; + BACKEND->xc_noanchor.minimal = &BACKEND->xc_minimal; + + OutputDebugStringA("BearSSL: Setting X509 engine to noanchor wrapper...\n"); + +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL: xc_noanchor at %p, vtable=%p, minimal=%p\n", + (void*)&BACKEND->xc_noanchor, + (void*)BACKEND->xc_noanchor.vtable, + (void*)BACKEND->xc_noanchor.minimal); + OutputDebugStringA(dbg); + } +#endif + + /* Replace the X509 engine with our noanchor validator wrapper */ + br_ssl_engine_set_x509(&BACKEND->sc.eng, &BACKEND->xc_noanchor.vtable); + OutputDebugStringA("BearSSL: Noanchor X509 validator installed\n"); + } + else { +#if BEARSSL_XBOX_INTEGRATION + { + /* Check for CURLOPT_CAINFO or default Xbox CA path */ + const char *cafile = SSL_CONN_CONFIG(CAfile); + + /* If no explicit CA file, try the default Xbox TDATA path */ + if(!cafile || !cafile[0]) { + cafile = BEARSSL_XBOX_DEFAULT_CA_FILE; + } + + /* Try loading CA bundle from PEM file */ + if(bearssl_xbox_load_ca_file(cafile, + &BACKEND->file_anchors, &BACKEND->file_anchor_count) == 0) { + trust_anchors = BACKEND->file_anchors; + trust_anchor_count = BACKEND->file_anchor_count; + infof(data, "BearSSL: Loaded %zu trust anchors from %s\n", + trust_anchor_count, cafile); + } + + /* Fall back to compiled-in trust anchors */ + if(!trust_anchors) { + trust_anchors = bearssl_xbox_get_trust_anchors(); + trust_anchor_count = bearssl_xbox_get_trust_anchor_count(); + } + } + + if(!trust_anchors || trust_anchor_count == 0) { + failf(data, "BearSSL: No trust anchors available for certificate verification"); + return CURLE_SSL_CACERT_BADFILE; + } + infof(data, "BearSSL: Using %zu trust anchors for verification\n", + trust_anchor_count); +#else + /* No trust anchors available - cannot verify */ + failf(data, "BearSSL: Certificate verification requested but no trust anchors available"); + return CURLE_SSL_CACERT_BADFILE; +#endif + + BACKEND->using_noanchor = 0; + /* Initialize the BearSSL client context with trust anchors */ + br_ssl_client_init_full(&BACKEND->sc, &BACKEND->xc_minimal, + trust_anchors, trust_anchor_count); + +#ifdef _XBOX + /* Skip certificate date validation - Xbox clock is unreliable */ + br_x509_minimal_set_time_callback(&BACKEND->xc_minimal, + NULL, bearssl_xbox_time_check); +#endif + } + + OutputDebugStringA("BearSSL: Setting protocol versions...\n"); + + /* Set protocol versions based on CURLOPT_SSLVERSION */ + { + /* + * Default to TLS 1.2 minimum for security. + * TLS 1.0 and 1.1 are deprecated and have known vulnerabilities. + */ + int min_ver = BR_TLS12; + int max_ver = BR_TLS12; + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + /* Default: TLS 1.2 only (most compatible + secure) */ + min_ver = BR_TLS12; + break; + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + /* Allow TLS 1.0 if explicitly requested (legacy support) */ + min_ver = BR_TLS10; + break; + case CURL_SSLVERSION_TLSv1_1: + min_ver = BR_TLS11; + break; + case CURL_SSLVERSION_TLSv1_2: + min_ver = BR_TLS12; + break; + case CURL_SSLVERSION_TLSv1_3: + /* BearSSL doesn't support TLS 1.3 */ + failf(data, "BearSSL does not support TLS 1.3"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unsupported SSL version"); + return CURLE_SSL_CONNECT_ERROR; + } + + br_ssl_engine_set_versions(&BACKEND->sc.eng, min_ver, max_ver); + } + OutputDebugStringA("BearSSL: Protocol versions set\n"); + + /* Use secure cipher suites only */ + br_ssl_engine_set_suites(&BACKEND->sc.eng, + bearssl_secure_suites, BEARSSL_SECURE_SUITES_COUNT); + OutputDebugStringA("BearSSL: Cipher suites set\n"); + + /* + * Set ALPN (Application-Layer Protocol Negotiation) protocols. + * + * This tells the server we want to speak HTTP/1.1. Without ALPN, modern + * servers like Cloudflare may reset the connection after handshake because + * they don't know what protocol the client expects. + */ + br_ssl_engine_set_protocol_names(&BACKEND->sc.eng, + bearssl_alpn_protocols, + BEARSSL_ALPN_PROTOCOLS_COUNT); + OutputDebugStringA("BearSSL: ALPN protocols set (http/1.1)\n"); + + /* Set I/O buffer */ + br_ssl_engine_set_buffer(&BACKEND->sc.eng, BACKEND->iobuf, + sizeof(BACKEND->iobuf), 1); + OutputDebugStringA("BearSSL: I/O buffer set\n"); + +#if BEARSSL_XBOX_INTEGRATION + /* Try to resume previous session */ + if(bearssl_xbox_session_get(hostname, &session_params)) { + br_ssl_engine_set_session_parameters(&BACKEND->sc.eng, &session_params); + session_resume = 1; + infof(data, "BearSSL: Attempting session resumption for %s\n", hostname); + } +#endif + + OutputDebugStringA("BearSSL: Calling br_ssl_client_reset...\n"); + + /* Reset the client context for the new connection */ + br_ssl_client_reset(&BACKEND->sc, hostname, session_resume); + + OutputDebugStringA("BearSSL: br_ssl_client_reset done\n"); + +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL step1: hostname=%s, socket=%d, sockindex=%d\n", + hostname, (int)conn->sock[sockindex], sockindex); + OutputDebugStringA(dbg); + + /* Verify socket is valid */ + if(conn->sock[sockindex] == CURL_SOCKET_BAD) { + OutputDebugStringA("BearSSL step1: ERROR - socket is INVALID!\n"); + } + } +#endif + + OutputDebugStringA("BearSSL: Calling br_sslio_init...\n"); + + /* Initialize the I/O wrapper */ + br_sslio_init(&BACKEND->ioc, &BACKEND->sc.eng, + sock_read, &conn->sock[sockindex], + sock_write, &conn->sock[sockindex]); + + OutputDebugStringA("BearSSL: br_sslio_init done\n"); + + /* Note: BACKEND->active is set in step3 after handshake completes */ + connssl->connecting_state = ssl_connect_2; + + OutputDebugStringA("BearSSL step1: complete, moving to step2\n"); + return CURLE_OK; +} + +static CURLcode +bearssl_connect_step2(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned state; + int err; + + state = br_ssl_engine_current_state(&BACKEND->sc.eng); + +#ifdef _XBOX + { + static int step2_call_count = 0; + char dbg[256]; + step2_call_count++; + msnprintf(dbg, sizeof(dbg), + "BearSSL step2 [%d]: state=0x%x (CLOSED=%d SENDREC=%d RECVREC=%d SENDAPP=%d)\n", + step2_call_count, state, + (state & BR_SSL_CLOSED) ? 1 : 0, + (state & BR_SSL_SENDREC) ? 1 : 0, + (state & BR_SSL_RECVREC) ? 1 : 0, + (state & BR_SSL_SENDAPP) ? 1 : 0); + OutputDebugStringA(dbg); + } +#endif + + /* Check for errors */ + err = br_ssl_engine_last_error(&BACKEND->sc.eng); + if(err != BR_ERR_OK) { +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: engine error %d\n", err); + OutputDebugStringA(dbg); + } +#endif + failf(data, "BearSSL: %s (error %d)", bearssl_error_string(err), err); + return CURLE_SSL_CONNECT_ERROR; + } + + /* Check if handshake is complete */ + if(state & BR_SSL_SENDAPP) { + /* Handshake complete, application data can be sent */ + connssl->connecting_state = ssl_connect_3; + return CURLE_OK; + } + + /* Handshake still in progress */ + if(state & BR_SSL_SENDREC) { + /* Need to send data */ + int ret; + OutputDebugStringA("BearSSL step2: flushing send buffer...\n"); + ret = br_sslio_flush(&BACKEND->ioc); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: flush returned %d\n", ret); + OutputDebugStringA(dbg); + } +#endif + if(ret < 0) { + err = br_ssl_engine_last_error(&BACKEND->sc.eng); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: flush error, engine err=%d\n", err); + OutputDebugStringA(dbg); + } +#endif + if(err != BR_ERR_OK) { + failf(data, "BearSSL handshake: %s (error %d)", + bearssl_error_string(err), err); + return CURLE_SSL_CONNECT_ERROR; + } + } + } + + if(state & BR_SSL_RECVREC) { + /* Need to receive data - handled by sslio layer */ + unsigned char tmp[1]; + int ret; + OutputDebugStringA("BearSSL step2: attempting to receive...\n"); + ret = br_sslio_read(&BACKEND->ioc, tmp, 0); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: read returned %d\n", ret); + OutputDebugStringA(dbg); + } +#endif + if(ret < 0) { + err = br_ssl_engine_last_error(&BACKEND->sc.eng); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: read error, engine err=%d\n", err); + OutputDebugStringA(dbg); + } +#endif + if(err != BR_ERR_OK && err != BR_ERR_IO) { + failf(data, "BearSSL handshake: %s (error %d)", + bearssl_error_string(err), err); + return CURLE_SSL_CONNECT_ERROR; + } + } + } + + /* Check state again */ + state = br_ssl_engine_current_state(&BACKEND->sc.eng); + if(state & BR_SSL_SENDAPP) { + connssl->connecting_state = ssl_connect_3; + return CURLE_OK; + } + + /* Still connecting */ + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static CURLcode +bearssl_connect_step3(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + br_ssl_session_parameters session_params; + unsigned version; + const char *version_str; + + /* Get negotiated TLS version */ + version = br_ssl_engine_get_version(&BACKEND->sc.eng); + switch(version) { + case BR_TLS10: version_str = "TLS 1.0"; break; + case BR_TLS11: version_str = "TLS 1.1"; break; + case BR_TLS12: version_str = "TLS 1.2"; break; + default: version_str = "Unknown"; break; + } + + /* Log ALPN negotiation result */ + { + const char *alpn_protocol; + alpn_protocol = br_ssl_engine_get_selected_protocol(&BACKEND->sc.eng); + if(alpn_protocol) { + infof(data, "BearSSL: ALPN negotiated protocol: %s\n", alpn_protocol); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL: ALPN selected: %s\n", alpn_protocol); + OutputDebugStringA(dbg); + } +#endif + } + else { + infof(data, "BearSSL: ALPN not negotiated (server may not support it)\n"); +#ifdef _XBOX + OutputDebugStringA("BearSSL: ALPN not negotiated by server\n"); +#endif + } + } + + /* Check if session was resumed */ + br_ssl_engine_get_session_parameters(&BACKEND->sc.eng, &session_params); + if(session_params.session_id_len > 0) { + /* Check if this was a resumed session */ + /* Note: BearSSL doesn't have a direct "was resumed" flag, + but we can infer from session ID presence on a fresh context */ + infof(data, "BearSSL: %s connection using %s\n", + BACKEND->session_resumed ? "Resumed" : "New", version_str); + } + else { + infof(data, "BearSSL: New connection using %s\n", version_str); + } + +#if BEARSSL_XBOX_INTEGRATION + /* Store session for future resumption. + * Store if we have a session ID or a session ticket (RFC 5077). */ + if(session_params.session_id_len > 0 + || session_params.session_ticket_len > 0) { + bearssl_xbox_session_store(BACKEND->hostname, &session_params); + } + + /* Copy captured leaf certificate hash from X.509 callback */ + if(BACKEND->using_noanchor && BACKEND->xc_noanchor.leaf_hash_valid) { + memcpy(BACKEND->leaf_cert_hash, BACKEND->xc_noanchor.leaf_hash, 32); + BACKEND->leaf_cert_hash_valid = 1; +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL step3: Leaf cert SHA-256: " + "%02X%02X%02X%02X %02X%02X%02X%02X " + "%02X%02X%02X%02X %02X%02X%02X%02X " + "%02X%02X%02X%02X %02X%02X%02X%02X " + "%02X%02X%02X%02X %02X%02X%02X%02X\n", + BACKEND->leaf_cert_hash[0], BACKEND->leaf_cert_hash[1], + BACKEND->leaf_cert_hash[2], BACKEND->leaf_cert_hash[3], + BACKEND->leaf_cert_hash[4], BACKEND->leaf_cert_hash[5], + BACKEND->leaf_cert_hash[6], BACKEND->leaf_cert_hash[7], + BACKEND->leaf_cert_hash[8], BACKEND->leaf_cert_hash[9], + BACKEND->leaf_cert_hash[10], BACKEND->leaf_cert_hash[11], + BACKEND->leaf_cert_hash[12], BACKEND->leaf_cert_hash[13], + BACKEND->leaf_cert_hash[14], BACKEND->leaf_cert_hash[15], + BACKEND->leaf_cert_hash[16], BACKEND->leaf_cert_hash[17], + BACKEND->leaf_cert_hash[18], BACKEND->leaf_cert_hash[19], + BACKEND->leaf_cert_hash[20], BACKEND->leaf_cert_hash[21], + BACKEND->leaf_cert_hash[22], BACKEND->leaf_cert_hash[23], + BACKEND->leaf_cert_hash[24], BACKEND->leaf_cert_hash[25], + BACKEND->leaf_cert_hash[26], BACKEND->leaf_cert_hash[27], + BACKEND->leaf_cert_hash[28], BACKEND->leaf_cert_hash[29], + BACKEND->leaf_cert_hash[30], BACKEND->leaf_cert_hash[31]); + OutputDebugStringA(dbg); + } +#endif + } +#endif + + /* Connection is now established - mark SSL as active for proper cleanup */ + /* + * CRITICAL: Register our SSL send/recv functions with libcurl. + * + * libcurl uses conn->recv[sockindex] and conn->send[sockindex] for all + * data transfer. If we don't set these to our BearSSL functions, libcurl + * will send raw unencrypted data over the TLS connection, causing the + * server to reset the connection. + * + * This was the root cause of the "connection reset after handshake" bug. + */ + conn->recv[sockindex] = bearssl_recv; + conn->send[sockindex] = bearssl_send; + +#ifdef _XBOX + OutputDebugStringA("BearSSL: Registered send/recv handlers with libcurl\n"); +#endif + + BACKEND->active = 1; + connssl->connecting_state = ssl_connect_done; + connssl->state = ssl_connection_complete; + + return CURLE_OK; +} + +static CURLcode +bearssl_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* Check if already connected */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + timeout_ms = Curl_timeleft(data, NULL, TRUE); + if(timeout_ms < 0) { + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + result = bearssl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state) { + timeout_ms = Curl_timeleft(data, NULL, TRUE); + if(timeout_ms < 0) { + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* Check socket readiness */ + what = Curl_socket_check(sockfd, CURL_SOCKET_BAD, sockfd, + nonblocking ? 0 : timeout_ms); + if(what < 0) { + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + + result = bearssl_connect_step2(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_3 == connssl->connecting_state) { + result = bearssl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + *done = TRUE; + } + else { + *done = FALSE; + } + + return CURLE_OK; +} + +static CURLcode +Curl_bearssl_connect_blocking(struct connectdata *conn, int sockindex) +{ + bool done = FALSE; + CURLcode result; + + result = bearssl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + return CURLE_OK; +} + +static CURLcode +Curl_bearssl_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + return bearssl_connect_common(conn, sockindex, TRUE, done); +} + +static void Curl_bearssl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL close: sockindex=%d, state=%d, backend=%p\n", + sockindex, (int)connssl->state, (void*)BACKEND); + OutputDebugStringA(dbg); + } +#endif + + /* Only cleanup if SSL was actually initialized on this connection */ + if(connssl->state == ssl_connection_none) + return; + + if(BACKEND) { + if(BACKEND->active) { + /* + * Attempt graceful TLS close only if the connection is still healthy. + * br_sslio_close() sends a close_notify alert, which calls sock_write(). + * If the socket is dead, sock_write() fails and BearSSL's I/O state + * becomes inconsistent, causing heap corruption. Guard against this by + * checking io_error (set by bearssl_send/recv on failure), the engine + * error code, and the engine closed flag. + */ + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + unsigned state = br_ssl_engine_current_state(&BACKEND->sc.eng); + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL close: io_error=%d, err=%d, state=0x%x\n", + BACKEND->io_error, err, state); + OutputDebugStringA(dbg); + } +#endif + + if(!BACKEND->io_error && err == BR_ERR_OK && !(state & BR_SSL_CLOSED)) { + br_sslio_close(&BACKEND->ioc); + } + BACKEND->active = 0; + } + /* + * NOTE: Do NOT free BACKEND! The vtls layer allocates all backend memory + * as a single block in url.c:allocate_conn(). Freeing BACKEND here would + * corrupt the heap because it's an offset into a larger allocation. + * + * Just clear the backend data to prepare for potential reuse. + */ +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL: Clearing backend at %p (NOT freeing - vtls manages memory)\n", + (void*)BACKEND); + OutputDebugStringA(dbg); + } +#endif + + /* Free per-connection file-loaded trust anchors before clearing */ +#if BEARSSL_XBOX_INTEGRATION + if(BACKEND->file_anchors) { + bearssl_xbox_free_loaded_anchors(BACKEND->file_anchors, + BACKEND->file_anchor_count); + } +#endif + + /* Clear backend data but do NOT free (vtls owns the memory) */ + memset(BACKEND, 0, sizeof(struct ssl_backend_data)); + } + + /* Reset state */ + connssl->state = ssl_connection_none; + connssl->connecting_state = ssl_connect_1; +} + +static void Curl_bearssl_close_all(struct Curl_easy *data) +{ + (void)data; +} + +static int Curl_bearssl_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL shutdown: sockindex=%d, state=%d, backend=%p\n", + sockindex, (int)connssl->state, (void*)BACKEND); + OutputDebugStringA(dbg); + } +#endif + + /* Only shutdown if SSL was actually initialized */ + if(connssl->state == ssl_connection_none) + return 0; + + /* Check BACKEND exists before accessing it */ + if(!BACKEND) + return 0; + + if(BACKEND->active) { + /* + * Only attempt graceful TLS close if no I/O errors occurred. + * Avoid trying to send close_notify on a dead socket. + */ + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + unsigned state = br_ssl_engine_current_state(&BACKEND->sc.eng); + + if(!BACKEND->io_error && err == BR_ERR_OK && !(state & BR_SSL_CLOSED)) { + br_sslio_close(&BACKEND->ioc); + } + BACKEND->active = 0; + } + + return 0; +} + +static ssize_t bearssl_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int ret; + int flush_ret; + + /* Defensive check - BACKEND must be valid */ + if(!BACKEND || !BACKEND->active) { + OutputDebugStringA("bearssl_send: BACKEND invalid, returning error\n"); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL send: len=%u, active=%d\n", + (unsigned)len, BACKEND->active); + OutputDebugStringA(dbg); + } +#endif + + ret = br_sslio_write(&BACKEND->ioc, mem, len); + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + unsigned state = br_ssl_engine_current_state(&BACKEND->sc.eng); + msnprintf(dbg, sizeof(dbg), "BearSSL send: write returned %d, err=%d, state=0x%x\n", + ret, err, state); + OutputDebugStringA(dbg); + } +#endif + + if(ret < 0) { + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + /* Mark that we've had an I/O error - skip graceful close later */ + BACKEND->io_error = 1; + if(err == BR_ERR_OK || err == BR_ERR_IO) { + *curlcode = CURLE_AGAIN; + } + else { + *curlcode = CURLE_SEND_ERROR; + } + return -1; + } + + /* Flush the data to ensure it's sent immediately */ + flush_ret = br_sslio_flush(&BACKEND->ioc); + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL send: flush returned %d\n", flush_ret); + OutputDebugStringA(dbg); + } +#endif + + if(flush_ret < 0) { + BACKEND->io_error = 1; + } + + return (ssize_t)ret; +} + +static ssize_t bearssl_recv(struct connectdata *conn, int sockindex, + char *buf, size_t buffersize, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int ret; + + /* Defensive check - BACKEND must be valid */ + if(!BACKEND || !BACKEND->active) { + OutputDebugStringA("bearssl_recv: BACKEND invalid, returning error\n"); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL recv: buffersize=%u, active=%d\n", + (unsigned)buffersize, BACKEND->active); + OutputDebugStringA(dbg); + } +#endif + + ret = br_sslio_read(&BACKEND->ioc, buf, buffersize); + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + unsigned state = br_ssl_engine_current_state(&BACKEND->sc.eng); + msnprintf(dbg, sizeof(dbg), "BearSSL recv: read returned %d, err=%d, state=0x%x\n", + ret, err, state); + OutputDebugStringA(dbg); + } +#endif + + if(ret < 0) { + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + /* Mark that we've had an I/O error - skip graceful close later */ + BACKEND->io_error = 1; +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL recv: ERROR - setting io_error=1, err=%d\n", err); + OutputDebugStringA(dbg); + } +#endif + if(err == BR_ERR_OK || err == BR_ERR_IO) { + *curlcode = CURLE_AGAIN; + } + else { + *curlcode = CURLE_RECV_ERROR; + } + return -1; + } + + return (ssize_t)ret; +} + +static bool Curl_bearssl_data_pending(const struct connectdata *conn, + int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned state; + + /* Check if SSL was initialized before accessing BACKEND */ + if(connssl->state == ssl_connection_none) + return FALSE; + + if(!BACKEND || !BACKEND->active) + return FALSE; + + state = br_ssl_engine_current_state(&BACKEND->sc.eng); + return (state & BR_SSL_RECVAPP) ? TRUE : FALSE; +} + +static int Curl_bearssl_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + int err; + + /* Check if SSL was initialized before accessing BACKEND */ + if(connssl->state == ssl_connection_none) + return 0; + + if(!BACKEND || !BACKEND->active) + return 0; + + err = br_ssl_engine_last_error(&BACKEND->sc.eng); + return (err == BR_ERR_OK) ? 1 : 0; +} + +static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) +{ + (void)info; + /* Check if SSL was initialized before accessing BACKEND */ + if(connssl->state == ssl_connection_none) + return NULL; + return BACKEND ? &BACKEND->sc : NULL; +} + +static void Curl_bearssl_session_free(void *ptr) +{ + (void)ptr; + /* BearSSL session handling is different; no dynamic session objects */ +} + +const struct Curl_ssl Curl_ssl_bearssl = { + { CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */ + SSLSUPP_CA_PATH | + SSLSUPP_SSL_CTX, /* supports */ + sizeof(struct ssl_backend_data), + + Curl_bearssl_init, /* init */ + Curl_bearssl_cleanup, /* cleanup */ + Curl_bearssl_version, /* version */ + Curl_bearssl_check_cxn, /* check_cxn */ + Curl_bearssl_shutdown, /* shutdown */ + Curl_bearssl_data_pending, /* data_pending */ + Curl_bearssl_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_bearssl_connect_blocking, /* connect_blocking */ + Curl_bearssl_connect_nonblocking, /* connect_nonblocking */ + Curl_bearssl_get_internals, /* get_internals */ + Curl_bearssl_close, /* close_one */ + Curl_bearssl_close_all, /* close_all */ + Curl_bearssl_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + NULL /* sha256sum */ +}; + +#endif /* USE_BEARSSL */ diff --git a/BearSSL-OG/bearssl_xbox.cpp b/BearSSL-OG/bearssl_xbox.cpp new file mode 100644 index 0000000..bd73a56 --- /dev/null +++ b/BearSSL-OG/bearssl_xbox.cpp @@ -0,0 +1,150 @@ +/* + * BearSSL Xbox Integration Implementation + * C-compatible wrappers for Xbox-specific SSL functionality + */ + +#include "bearssl_xbox.h" +#include "certificates.h" +#include "ca_loader.h" +#include "session_cache.h" +#include "ssl_errors.h" +#include "cert_pinning.h" + +extern "C" { + +/* + * Trust Anchor Management + */ +void bearssl_xbox_init_trust_anchors(void) +{ + certificates::initialize_trust_anchors(); +} + +void bearssl_xbox_cleanup_trust_anchors(void) +{ + certificates::close_trust_anchors(); +} + +br_x509_trust_anchor* bearssl_xbox_get_trust_anchors(void) +{ + return certificates::get_trust_anchors(); +} + +size_t bearssl_xbox_get_trust_anchor_count(void) +{ + return (size_t)certificates::get_num_trust_anchors(); +} + +/* + * Session Cache Management + */ +void bearssl_xbox_session_init(void) +{ + session_cache::initialize(); +} + +void bearssl_xbox_session_shutdown(void) +{ + session_cache::shutdown(); +} + +int bearssl_xbox_session_get(const char* hostname, br_ssl_session_parameters* params) +{ + return session_cache::get(hostname, params) ? 1 : 0; +} + +void bearssl_xbox_session_store(const char* hostname, const br_ssl_session_parameters* params) +{ + session_cache::store(hostname, params); +} + +void bearssl_xbox_session_remove(const char* hostname) +{ + session_cache::remove(hostname); +} + +void bearssl_xbox_session_clear(void) +{ + session_cache::clear(); +} + +/* + * Error Message Utilities + */ +const char* bearssl_xbox_error_string(int error) +{ + return ssl_errors::error_to_string(error); +} + +const char* bearssl_xbox_alert_string(int alert_code) +{ + return ssl_errors::alert_to_string(alert_code); +} + +/* + * CA Loader + */ +int bearssl_xbox_load_ca_file(const char *path, + br_x509_trust_anchor **anchors_out, size_t *count_out) +{ + return ca_loader::load_pem_file(path, anchors_out, count_out); +} + +void bearssl_xbox_free_loaded_anchors(br_x509_trust_anchor *anchors, + size_t count) +{ + ca_loader::free_trust_anchors(anchors, count); +} + +int bearssl_xbox_update_trust_store(void) +{ + return ca_loader::update_trust_store( + BEARSSL_XBOX_DEFAULT_CA_FILE, + certificates::get_trust_anchors(), + (size_t)certificates::get_num_trust_anchors()); +} + +/* + * Certificate Pinning + */ +void bearssl_xbox_pin_init(void) +{ + cert_pinning::initialize(); +} + +void bearssl_xbox_pin_shutdown(void) +{ + cert_pinning::shutdown(); +} + +int bearssl_xbox_pin_add(const char* hostname, const unsigned char* sha256_hash) +{ + return cert_pinning::add_pin(hostname, sha256_hash) ? 1 : 0; +} + +void bearssl_xbox_pin_remove(const char* hostname) +{ + cert_pinning::remove_pin(hostname); +} + +void bearssl_xbox_pin_clear(void) +{ + cert_pinning::clear(); +} + +int bearssl_xbox_pin_has(const char* hostname) +{ + return cert_pinning::has_pin(hostname) ? 1 : 0; +} + +int bearssl_xbox_pin_verify_hash(const char* hostname, const unsigned char* cert_sha256) +{ + return cert_pinning::verify_hash(hostname, cert_sha256) ? 1 : 0; +} + +int bearssl_xbox_pin_get_hash(const char* hostname, unsigned char* hash_out) +{ + return cert_pinning::get_pin_hash(hostname, hash_out) ? 1 : 0; +} + +} /* extern "C" */ diff --git a/BearSSL-OG/bearssl_xbox.h b/BearSSL-OG/bearssl_xbox.h new file mode 100644 index 0000000..6b86866 --- /dev/null +++ b/BearSSL-OG/bearssl_xbox.h @@ -0,0 +1,85 @@ +/* + * BearSSL Xbox Integration Header + * C-compatible wrappers for Xbox-specific SSL functionality + * + * This provides a C interface to the C++ classes for use by libcurl's bearssl.c + */ + +#ifndef BEARSSL_XBOX_H +#define BEARSSL_XBOX_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default CA bundle path on Xbox HDD. + * T:\ maps to E:\TDATA\\ (title-persistent storage). + * Drop cacert.pem there to use updated root CAs without recompiling. + */ +#define BEARSSL_XBOX_DEFAULT_CA_FILE "T:\\cacert.pem" + +/* + * Trust Anchor Management + * Wraps certificates.cpp functionality + */ +void bearssl_xbox_init_trust_anchors(void); +void bearssl_xbox_cleanup_trust_anchors(void); +br_x509_trust_anchor* bearssl_xbox_get_trust_anchors(void); +size_t bearssl_xbox_get_trust_anchor_count(void); + +/* + * Session Cache Management + * Wraps session_cache.cpp functionality + */ +void bearssl_xbox_session_init(void); +void bearssl_xbox_session_shutdown(void); +int bearssl_xbox_session_get(const char* hostname, br_ssl_session_parameters* params); +void bearssl_xbox_session_store(const char* hostname, const br_ssl_session_parameters* params); +void bearssl_xbox_session_remove(const char* hostname); +void bearssl_xbox_session_clear(void); + +/* + * Error Message Utilities + * Wraps ssl_errors.cpp functionality + */ +const char* bearssl_xbox_error_string(int error); +const char* bearssl_xbox_alert_string(int alert_code); + +/* + * CA Loader - Runtime PEM certificate loading + * Wraps ca_loader.cpp functionality + */ +int bearssl_xbox_load_ca_file(const char *path, + br_x509_trust_anchor **anchors_out, size_t *count_out); +void bearssl_xbox_free_loaded_anchors(br_x509_trust_anchor *anchors, + size_t count); + +/* + * CA Auto-Update + * Downloads cacert.pem from curl.se if not already present on disk. + * Uses the compiled-in trust anchors (must be initialized first). + * Returns 0 on success (file existed or was downloaded), -1 on failure. + */ +int bearssl_xbox_update_trust_store(void); + +/* + * Certificate Pinning + * Wraps cert_pinning.cpp functionality + */ +void bearssl_xbox_pin_init(void); +void bearssl_xbox_pin_shutdown(void); +int bearssl_xbox_pin_add(const char* hostname, const unsigned char* sha256_hash); +void bearssl_xbox_pin_remove(const char* hostname); +void bearssl_xbox_pin_clear(void); +int bearssl_xbox_pin_has(const char* hostname); +int bearssl_xbox_pin_verify_hash(const char* hostname, const unsigned char* cert_sha256); +int bearssl_xbox_pin_get_hash(const char* hostname, unsigned char* hash_out); + +#ifdef __cplusplus +} +#endif + +#endif /* BEARSSL_XBOX_H */ diff --git a/BearSSL-OG/ca_loader.cpp b/BearSSL-OG/ca_loader.cpp new file mode 100644 index 0000000..457154a --- /dev/null +++ b/BearSSL-OG/ca_loader.cpp @@ -0,0 +1,861 @@ +#include "ca_loader.h" +#include "debug_utility.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DOWNLOAD_BUF_SIZE 8192 +#define CA_DNS_TIMEOUT_MS 30000 + +/* ------------------------------------------------------------------ */ +/* Inline socket/network helpers (avoids dependency on BearSSL-OG */ +/* socket_utility / network_utility which aren't in libbearssl) */ +/* ------------------------------------------------------------------ */ + +/* DNS resolution via Xbox XNet async API */ +static uint32_t ca_resolve_host(const char *host) +{ + XNDNS *dns = NULL; + WSAEVENT event_handle; + uint32_t result = 0; + + if (host == NULL || host[0] == '\0') + { + return 0; + } + + event_handle = WSACreateEvent(); + if (event_handle == NULL) + { + return 0; + } + + if (XNetDnsLookup(host, event_handle, &dns) != 0) + { + WSACloseEvent(event_handle); + return 0; + } + + if (WaitForSingleObject(event_handle, CA_DNS_TIMEOUT_MS) == WAIT_TIMEOUT) + { + WSACloseEvent(event_handle); + XNetDnsRelease(dns); + return 0; + } + + WSACloseEvent(event_handle); + + if (dns->iStatus == 0 && dns->cina > 0) + { + result = dns->aina[0].S_un.S_addr; + } + + XNetDnsRelease(dns); + return result; +} + +/* TCP connect to host:port, returns socket or INVALID_SOCKET. + * IMPORTANT: Xbox SOCKET handles are kernel pointers (e.g. 0xD001A828) + * which are negative as signed int -- never check < 0, always use + * INVALID_SOCKET. */ +static SOCKET ca_connect(uint32_t host_ip, uint16_t port) +{ + sockaddr_in addr; + SOCKET sock; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.S_un.S_addr = host_ip; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == INVALID_SOCKET) + { + return INVALID_SOCKET; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) + { + closesocket(sock); + return INVALID_SOCKET; + } + + return sock; +} + +/* BearSSL I/O callback: read from socket with 2-second select timeout */ +static int ca_sock_read(void *ctx, unsigned char *buf, size_t len) +{ + SOCKET sock = *(SOCKET *)ctx; + fd_set fds; + struct timeval tv; + int n; + + while (1) + { + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = 2; + tv.tv_usec = 0; + + if (select(0, &fds, NULL, NULL, &tv) == 0) + { + return -1; /* timeout */ + } + + n = recv(sock, (char *)buf, (len > 0x7FFFFFFF) ? 0x7FFFFFFF : (int)len, 0); + if (n == SOCKET_ERROR) + { + if (WSAGetLastError() == WSAEINTR || + WSAGetLastError() == WSAEWOULDBLOCK) + { + continue; + } + return -1; + } + return n; /* 0 = peer closed, >0 = bytes read */ + } +} + +/* BearSSL I/O callback: write to socket */ +static int ca_sock_write(void *ctx, const unsigned char *buf, size_t len) +{ + SOCKET sock = *(SOCKET *)ctx; + int n; + + while (1) + { + n = send(sock, (const char *)buf, + (len > 0x7FFFFFFF) ? 0x7FFFFFFF : (int)len, 0); + if (n == SOCKET_ERROR) + { + if (WSAGetLastError() == WSAEINTR || + WSAGetLastError() == WSAEWOULDBLOCK) + { + continue; + } + return -1; + } + return n; + } +} + +/* Dynamic byte buffer used for accumulating DER and DN data */ +struct byte_buffer +{ + unsigned char *data; + size_t len; + size_t cap; + int error; /* set to 1 if any append failed (OOM) */ +}; + +static void byte_buffer_init(byte_buffer *bb) +{ + bb->data = NULL; + bb->len = 0; + bb->cap = 0; + bb->error = 0; +} + +static void byte_buffer_reset(byte_buffer *bb) +{ + bb->len = 0; + bb->error = 0; +} + +static void byte_buffer_free(byte_buffer *bb) +{ + free(bb->data); + bb->data = NULL; + bb->len = 0; + bb->cap = 0; + bb->error = 0; +} + +static int byte_buffer_append(byte_buffer *bb, const void *src, size_t len) +{ + if (len == 0) + { + return 0; + } + if (bb->len + len > bb->cap) + { + size_t new_cap = (bb->cap == 0) ? 4096 : bb->cap * 2; + while (new_cap < bb->len + len) + { + if (new_cap > ((size_t)-1) / 2) + { + return -1; + } + new_cap *= 2; + } + unsigned char *new_data = (unsigned char *)realloc(bb->data, new_cap); + if (new_data == NULL) + { + return -1; + } + bb->data = new_data; + bb->cap = new_cap; + } + memcpy(bb->data + bb->len, src, len); + bb->len += len; + return 0; +} + +/* PEM decoder callback: accumulates decoded DER bytes */ +static void pem_dest_callback(void *dest_ctx, const void *src, size_t len) +{ + byte_buffer *bb = (byte_buffer *)dest_ctx; + if (byte_buffer_append(bb, src, len) != 0) + { + bb->error = 1; + } +} + +/* X.509 decoder callback: accumulates subject DN bytes */ +static void dn_append_callback(void *ctx, const void *buf, size_t len) +{ + byte_buffer *bb = (byte_buffer *)ctx; + if (byte_buffer_append(bb, buf, len) != 0) + { + bb->error = 1; + } +} + +/* + * Deep-copy a decoded certificate into a new trust anchor entry. + * Returns 0 on success, -1 on allocation failure. + */ +static int add_trust_anchor( + br_x509_trust_anchor **anchors, size_t *count, size_t *cap, + byte_buffer *dn, br_x509_decoder_context *dc) +{ + br_x509_pkey *pk = br_x509_decoder_get_pkey(dc); + if (pk == NULL) + { + return -1; + } + + /* Grow anchor array if needed */ + if (*count >= *cap) + { + size_t new_cap = (*cap == 0) ? 32 : *cap * 2; + br_x509_trust_anchor *new_arr = (br_x509_trust_anchor *)realloc( + *anchors, new_cap * sizeof(br_x509_trust_anchor)); + if (new_arr == NULL) + { + return -1; + } + *anchors = new_arr; + *cap = new_cap; + } + + br_x509_trust_anchor *ta = &(*anchors)[*count]; + memset(ta, 0, sizeof(*ta)); + + /* Deep-copy DN */ + ta->dn.data = (unsigned char *)malloc(dn->len); + if (ta->dn.data == NULL) + { + return -1; + } + memcpy(ta->dn.data, dn->data, dn->len); + ta->dn.len = dn->len; + + /* Set CA flag */ + ta->flags = br_x509_decoder_isCA(dc) ? BR_X509_TA_CA : 0; + + /* Deep-copy public key */ + ta->pkey.key_type = pk->key_type; + if (pk->key_type == BR_KEYTYPE_RSA) + { + ta->pkey.key.rsa.n = (unsigned char *)malloc(pk->key.rsa.nlen); + ta->pkey.key.rsa.e = (unsigned char *)malloc(pk->key.rsa.elen); + if (ta->pkey.key.rsa.n == NULL || ta->pkey.key.rsa.e == NULL) + { + free(ta->pkey.key.rsa.n); + free(ta->pkey.key.rsa.e); + free(ta->dn.data); + return -1; + } + memcpy(ta->pkey.key.rsa.n, pk->key.rsa.n, pk->key.rsa.nlen); + ta->pkey.key.rsa.nlen = pk->key.rsa.nlen; + memcpy(ta->pkey.key.rsa.e, pk->key.rsa.e, pk->key.rsa.elen); + ta->pkey.key.rsa.elen = pk->key.rsa.elen; + } + else if (pk->key_type == BR_KEYTYPE_EC) + { + ta->pkey.key.ec.q = (unsigned char *)malloc(pk->key.ec.qlen); + if (ta->pkey.key.ec.q == NULL) + { + free(ta->dn.data); + memset(ta, 0, sizeof(*ta)); + return -1; + } + memcpy(ta->pkey.key.ec.q, pk->key.ec.q, pk->key.ec.qlen); + ta->pkey.key.ec.qlen = pk->key.ec.qlen; + ta->pkey.key.ec.curve = pk->key.ec.curve; + } + else + { + /* Unknown key type */ + free(ta->dn.data); + memset(ta, 0, sizeof(*ta)); + return -1; + } + + (*count)++; + return 0; +} + +int ca_loader::load_pem_file(const char *path, + br_x509_trust_anchor **anchors_out, size_t *count_out) +{ + *anchors_out = NULL; + *count_out = 0; + + /* Read entire PEM file into memory */ + FILE *f = fopen(path, "rb"); + if (f == NULL) + { + debug_utility::debug_print("ca_loader: cannot open %s\n", path); + return -1; + } + + fseek(f, 0, SEEK_END); + long file_size = ftell(f); + fseek(f, 0, SEEK_SET); + + if (file_size <= 0 || file_size > 2 * 1024 * 1024) + { + debug_utility::debug_print("ca_loader: file too large or empty (%ld bytes)\n", file_size); + fclose(f); + return -1; + } + + unsigned char *file_data = (unsigned char *)malloc((size_t)file_size); + if (file_data == NULL) + { + debug_utility::debug_print("ca_loader: malloc failed for file data\n"); + fclose(f); + return -1; + } + + size_t bytes_read = fread(file_data, 1, (size_t)file_size, f); + fclose(f); + + if (bytes_read != (size_t)file_size) + { + debug_utility::debug_print("ca_loader: short read (%u of %ld)\n", + (unsigned)bytes_read, file_size); + free(file_data); + return -1; + } + + /* Parse PEM, collecting DER blobs for each CERTIFICATE */ + br_pem_decoder_context pem; + br_pem_decoder_init(&pem); + + br_x509_trust_anchor *anchors = NULL; + size_t anchor_count = 0; + size_t anchor_cap = 0; + + byte_buffer der_buf; + byte_buffer_init(&der_buf); + + byte_buffer dn_buf; + byte_buffer_init(&dn_buf); + + int in_cert = 0; + int certs_parsed = 0; + int certs_failed = 0; + + const unsigned char *pos = file_data; + size_t remaining = bytes_read; + + while (remaining > 0) + { + size_t consumed = br_pem_decoder_push(&pem, pos, remaining); + pos += consumed; + remaining -= consumed; + + int event = br_pem_decoder_event(&pem); + switch (event) + { + case BR_PEM_BEGIN_OBJ: + if (strcmp(br_pem_decoder_name(&pem), "CERTIFICATE") == 0) + { + in_cert = 1; + byte_buffer_reset(&der_buf); + br_pem_decoder_setdest(&pem, pem_dest_callback, &der_buf); + } + else + { + /* Skip non-certificate objects (private keys, etc.) */ + in_cert = 0; + br_pem_decoder_setdest(&pem, NULL, NULL); + } + break; + + case BR_PEM_END_OBJ: + if (in_cert && der_buf.len > 0 && !der_buf.error) + { + /* Decode the DER certificate */ + br_x509_decoder_context dc; + byte_buffer_reset(&dn_buf); + br_x509_decoder_init(&dc, dn_append_callback, &dn_buf); + br_x509_decoder_push(&dc, der_buf.data, der_buf.len); + + int err = br_x509_decoder_last_error(&dc); + if (err == 0 && !dn_buf.error) + { + if (add_trust_anchor(&anchors, &anchor_count, &anchor_cap, + &dn_buf, &dc) == 0) + { + certs_parsed++; + } + else + { + certs_failed++; + } + } + else + { + certs_failed++; + } + } + else if (in_cert && (der_buf.error || dn_buf.error)) + { + certs_failed++; + } + in_cert = 0; + break; + + case BR_PEM_ERROR: + in_cert = 0; + break; + + case 0: + /* No event yet, decoder needs more data but push returned 0. + * This shouldn't happen with complete files, but guard against + * infinite loop by breaking if no progress was made. */ + if (consumed == 0) + { + remaining = 0; + } + break; + } + } + + byte_buffer_free(&der_buf); + byte_buffer_free(&dn_buf); + free(file_data); + + debug_utility::debug_print("ca_loader: loaded %d trust anchors from %s (%d failed)\n", + certs_parsed, path, certs_failed); + + if (anchor_count == 0) + { + free(anchors); + return -1; + } + + *anchors_out = anchors; + *count_out = anchor_count; + return 0; +} + +void ca_loader::free_trust_anchors(br_x509_trust_anchor *anchors, size_t count) +{ + size_t i; + + if (anchors == NULL) + { + return; + } + + for (i = 0; i < count; i++) + { + free(anchors[i].dn.data); + if (anchors[i].pkey.key_type == BR_KEYTYPE_RSA) + { + free(anchors[i].pkey.key.rsa.n); + free(anchors[i].pkey.key.rsa.e); + } + else if (anchors[i].pkey.key_type == BR_KEYTYPE_EC) + { + free(anchors[i].pkey.key.ec.q); + } + } + free(anchors); +} + +/* ------------------------------------------------------------------ */ +/* Auto-update: download CA bundle from curl.se over HTTPS */ +/* ------------------------------------------------------------------ */ + +/* Time check callback: always returns 0 (valid). + * This lets the compiled-in CAs work even if the Xbox clock is wrong. */ +static int download_time_check(void *tctx, + uint32_t not_before_days, uint32_t not_before_seconds, + uint32_t not_after_days, uint32_t not_after_seconds) +{ + (void)tctx; + (void)not_before_days; + (void)not_before_seconds; + (void)not_after_days; + (void)not_after_seconds; + return 0; +} + +/* Find \r\n in a buffer, return offset or -1 */ +static int find_line_end(const unsigned char *buf, size_t len) +{ + size_t i; + if (len < 2) return -1; + for (i = 0; i < len - 1; i++) + { + if (buf[i] == '\r' && buf[i + 1] == '\n') + { + return (int)i; + } + } + return -1; +} + +/* Case-insensitive prefix match */ +static int prefix_icmp(const char *str, const char *prefix) +{ + while (*prefix) + { + char a = *str; + char b = *prefix; + if (a >= 'A' && a <= 'Z') a += 32; + if (b >= 'A' && b <= 'Z') b += 32; + if (a != b) return 0; + str++; + prefix++; + } + return 1; +} + +int ca_loader::download_https(const char *host, const char *path, + uint16_t port, const char *save_path, + br_x509_trust_anchor *anchors, size_t anchor_count, + int max_redirects) +{ + int result = -1; + + /* DNS resolve */ + uint32_t host_ip = ca_resolve_host(host); + if (host_ip == 0) + { + debug_utility::debug_print("ca_loader: DNS failed for %s\n", host); + return -1; + } + + /* TCP connect */ + SOCKET sock = ca_connect(host_ip, port); + if (sock == INVALID_SOCKET) + { + debug_utility::debug_print("ca_loader: connect failed to %s:%u\n", + host, (unsigned)port); + return -1; + } + + /* Allocate BearSSL I/O buffer on the heap (too large for Xbox stack) */ + unsigned char *iobuf = (unsigned char *)malloc(BR_SSL_BUFSIZE_BIDI); + if (iobuf == NULL) + { + closesocket(sock); + return -1; + } + + /* Set up BearSSL with compiled-in CAs + time check bypass */ + br_ssl_client_context sc; + br_x509_minimal_context xc; + br_ssl_client_init_full(&sc, &xc, anchors, anchor_count); + br_x509_minimal_set_time_callback(&xc, NULL, download_time_check); + br_ssl_engine_set_buffer(&sc.eng, iobuf, BR_SSL_BUFSIZE_BIDI, 1); + br_ssl_client_reset(&sc, host, 0); + + br_sslio_context ioc; + br_sslio_init(&ioc, &sc.eng, + ca_sock_read, &sock, + ca_sock_write, &sock); + + /* Send HTTP GET */ + char request[512]; + _snprintf(request, sizeof(request) - 1, + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Accept-Encoding: identity\r\n" + "Connection: close\r\n" + "\r\n", + path, host); + request[sizeof(request) - 1] = '\0'; + + br_sslio_write_all(&ioc, request, strlen(request)); + br_sslio_flush(&ioc); + + /* Read response into accumulation buffer */ + unsigned char *readbuf = (unsigned char *)malloc(DOWNLOAD_BUF_SIZE); + if (readbuf == NULL) + { + free(iobuf); + closesocket(sock); + return -1; + } + + /* Accumulate headers */ + byte_buffer hdr; + byte_buffer_init(&hdr); + + int status_code = 0; + int64_t content_length = -1; + char redirect_host[256]; + char redirect_path[512]; + int has_redirect = 0; + int headers_done = 0; + + redirect_host[0] = '\0'; + redirect_path[0] = '\0'; + + while (!headers_done) + { + int n = br_sslio_read(&ioc, readbuf, DOWNLOAD_BUF_SIZE); + if (n < 0) break; + byte_buffer_append(&hdr, readbuf, (size_t)n); + + /* Parse complete lines from the accumulated buffer */ + while (hdr.len > 0) + { + int crlf = find_line_end(hdr.data, hdr.len); + if (crlf < 0) break; + + /* Null-terminate the line for string operations */ + char *line = (char *)malloc((size_t)crlf + 1); + if (line == NULL) break; + memcpy(line, hdr.data, (size_t)crlf); + line[crlf] = '\0'; + + /* Remove the line + CRLF from the buffer */ + { + size_t remove_len = (size_t)crlf + 2; + if (remove_len < hdr.len) + { + memmove(hdr.data, hdr.data + remove_len, + hdr.len - remove_len); + } + hdr.len -= remove_len; + } + + /* Empty line = end of headers */ + if (line[0] == '\0') + { + free(line); + headers_done = 1; + break; + } + + /* Parse status line: "HTTP/1.x 200 OK" */ + if (status_code == 0 && strncmp(line, "HTTP/", 5) == 0) + { + char *sp = strchr(line, ' '); + if (sp) status_code = atoi(sp + 1); + } + + /* Parse Content-Length (cap at 10MB - CA bundles are ~250KB) */ + if (prefix_icmp(line, "content-length:")) + { + const char *val = line + 15; + while (*val == ' ') val++; + content_length = 0; + while (*val >= '0' && *val <= '9') + { + content_length = content_length * 10 + (*val - '0'); + if (content_length > 10 * 1024 * 1024) + { + content_length = -1; + break; + } + val++; + } + } + + /* Parse Location for redirects */ + if (prefix_icmp(line, "location:")) + { + const char *url = line + 9; + while (*url == ' ') url++; + + /* Parse "https://host/path" */ + if (strncmp(url, "https://", 8) == 0) + { + const char *hstart = url + 8; + const char *slash = strchr(hstart, '/'); + if (slash) + { + size_t hlen = (size_t)(slash - hstart); + if (hlen < sizeof(redirect_host)) + { + memcpy(redirect_host, hstart, hlen); + redirect_host[hlen] = '\0'; + _snprintf(redirect_path, + sizeof(redirect_path) - 1, "%s", slash); + redirect_path[sizeof(redirect_path) - 1] = '\0'; + has_redirect = 1; + } + } + } + } + + free(line); + } + } + + /* Handle redirect */ + if ((status_code == 301 || status_code == 302 || status_code == 307) + && has_redirect && max_redirects > 0) + { + debug_utility::debug_print("ca_loader: redirect %d -> %s%s\n", + status_code, redirect_host, redirect_path); + + byte_buffer_free(&hdr); + free(readbuf); + free(iobuf); + closesocket(sock); + + return download_https(redirect_host, redirect_path, port, + save_path, anchors, anchor_count, max_redirects - 1); + } + + if (status_code != 200) + { + debug_utility::debug_print("ca_loader: HTTP %d from %s%s\n", + status_code, host, path); + byte_buffer_free(&hdr); + free(readbuf); + free(iobuf); + closesocket(sock); + return -1; + } + + /* Write body to a temp file, then rename on success */ + char temp_path[280]; + _snprintf(temp_path, sizeof(temp_path) - 1, "%s.tmp", save_path); + temp_path[sizeof(temp_path) - 1] = '\0'; + + FILE *fp = fopen(temp_path, "wb"); + if (fp == NULL) + { + debug_utility::debug_print("ca_loader: cannot create %s (err=%lu)\n", + temp_path, GetLastError()); + byte_buffer_free(&hdr); + free(readbuf); + free(iobuf); + closesocket(sock); + return -1; + } + + /* Write any leftover data that was read past the headers */ + int64_t total_written = 0; + int write_error = 0; + if (hdr.len > 0) + { + if (fwrite(hdr.data, 1, hdr.len, fp) != hdr.len) + { + write_error = 1; + } + total_written += (int64_t)hdr.len; + } + byte_buffer_free(&hdr); + + /* Stream the rest of the body to disk */ + while (!write_error) + { + int n = br_sslio_read(&ioc, readbuf, DOWNLOAD_BUF_SIZE); + if (n < 0) break; + if (fwrite(readbuf, 1, (size_t)n, fp) != (size_t)n) + { + write_error = 1; + break; + } + total_written += (int64_t)n; + + if (content_length > 0 && total_written >= content_length) + { + break; + } + } + + fclose(fp); + free(readbuf); + free(iobuf); + closesocket(sock); + + /* Check for disk write errors */ + if (write_error) + { + debug_utility::debug_print("ca_loader: write error saving to %s\n", + temp_path); + remove(temp_path); + return -1; + } + + /* Sanity check: CA bundles are typically 200-300 KB */ + if (total_written < 1024) + { + debug_utility::debug_print("ca_loader: download too small (%I64d bytes)\n", + total_written); + remove(temp_path); + return -1; + } + + /* Atomic-ish replace: delete old, rename temp */ + remove(save_path); + if (rename(temp_path, save_path) != 0) + { + debug_utility::debug_print("ca_loader: rename %s -> %s failed\n", + temp_path, save_path); + remove(temp_path); + return -1; + } + + debug_utility::debug_print("ca_loader: downloaded %I64d bytes to %s\n", + total_written, save_path); + result = 0; + return result; +} + +int ca_loader::update_trust_store(const char *save_path, + br_x509_trust_anchor *anchors, size_t anchor_count) +{ + /* If the CA file already exists on disk, nothing to do */ + FILE *f = fopen(save_path, "rb"); + if (f != NULL) + { + fclose(f); + debug_utility::debug_print("ca_loader: %s already exists, skipping download\n", + save_path); + return 0; + } + + if (anchors == NULL || anchor_count == 0) + { + debug_utility::debug_print("ca_loader: no trust anchors for download\n"); + return -1; + } + + debug_utility::debug_print("ca_loader: downloading CA bundle from %s...\n", + CA_BUNDLE_HOST); + + return download_https(CA_BUNDLE_HOST, CA_BUNDLE_PATH, CA_BUNDLE_PORT, + save_path, anchors, anchor_count, 3); +} diff --git a/BearSSL-OG/ca_loader.h b/BearSSL-OG/ca_loader.h new file mode 100644 index 0000000..6ed4416 --- /dev/null +++ b/BearSSL-OG/ca_loader.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include + +/* + * Runtime CA certificate loader. + * + * Parses PEM-encoded CA bundle files (e.g. cacert.pem from curl.se) + * into br_x509_trust_anchor arrays that BearSSL can use for certificate + * verification. + * + * Also provides auto-update: downloads a fresh CA bundle over HTTPS + * using the compiled-in trust anchors (with time validation bypassed) + * and saves it to title-persistent storage on the Xbox HDD. + */ + +/* Where to download the CA bundle from */ +#define CA_BUNDLE_HOST "curl.se" +#define CA_BUNDLE_PATH "/ca/cacert.pem" +#define CA_BUNDLE_PORT 443 + +class ca_loader +{ +public: + /* + * Load trust anchors from a PEM CA bundle file. + * Returns 0 on success, -1 on failure. + */ + static int load_pem_file(const char *path, + br_x509_trust_anchor **anchors_out, size_t *count_out); + + /* + * Free trust anchors that were loaded from a PEM file. + * Deep-frees DN data and key data, then frees the array. + */ + static void free_trust_anchors(br_x509_trust_anchor *anchors, + size_t count); + + /* + * Auto-update the trust store. + * + * If save_path does not exist, downloads a fresh CA bundle from + * curl.se over HTTPS (using the provided trust anchors with time + * validation disabled) and saves it to save_path. + * + * Returns 0 on success (file already existed or was downloaded). + * Returns -1 on failure (download failed, file I/O error, etc.). + */ + static int update_trust_store(const char *save_path, + br_x509_trust_anchor *anchors, size_t anchor_count); + +private: + /* + * Download an HTTPS resource and save to a file. + * Uses BearSSL with the given trust anchors (time check disabled). + * Follows up to max_redirects HTTP 301/302 redirects. + * Returns 0 on success, -1 on failure. + */ + static int download_https(const char *host, const char *path, + uint16_t port, const char *save_path, + br_x509_trust_anchor *anchors, size_t anchor_count, + int max_redirects); +}; diff --git a/BearSSL-OG/cert-ee-ec+rsa.pem b/BearSSL-OG/cert-ee-ec+rsa.pem new file mode 100644 index 0000000..07f5457 --- /dev/null +++ b/BearSSL-OG/cert-ee-ec+rsa.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICcTCCAVmgAwIBAgIUbmO7Sc5BfgOM9Ubyiq5hCDWwlLMwDQYJKoZIhvcNAQELBQAwJzELMAkG +A1UEBhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEy +MzEyMzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIB +BggqhkjOPQMBBwNCAARfOJ2n/02Kr/Y0OUYa/Drf9COqqer7xQjeAI6+eaU3WExt3QHKq0ffibbH +Fx84/B0gFN1FwOCPk044C/zpmaFJo2YwZDAfBgNVHSMEGDAWgBR8z6PGKffzxaoZ0MAW6+BAD85E +pzAdBgNVHQ4EFgQUww6GqnW0FcDllQkyvl6SdankRJswDAYDVR0TAQH/BAIwADAUBgNVHREEDTAL +gglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEBAI6JY6ebqBCOnhjQpHrdLIIWjwsO1cpXu19v +/FcowCG6rZSoF0JF1zH3hFcZRiQ8x0k4P0h6CRrrUbrFdY5MsiWwxyI+5+VG27E2/BuFUbDtgxbw +OnnaXShq7mogTLBwXrDtem0tGsm0ccLEox0lhjBUsZgmwVHg+DGtZ0id5qFSOyBHyXDagLWk9D9y +azcwVzksRptE8dlOu6Zf45rFf2y2Zcu/QHKS0Gj2rnl+JMFbaDAoU3FhevQ2ezvCtuwf3DBABA3q +swrPddO9nqtxcWh/pUFSAOmzruQe8btpxjvV3tLCJWkIPDfM94Jq5ah7agLavaQBMzPz3kYA7HXP +4H0= +-----END CERTIFICATE----- diff --git a/BearSSL-OG/cert-ee-ec.pem b/BearSSL-OG/cert-ee-ec.pem new file mode 100644 index 0000000..ff8ddbc --- /dev/null +++ b/BearSSL-OG/cert-ee-ec.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBsDCCAVagAwIBAgIUHE0AkWniRqyQfGRcU/H/t8HLbnowCgYIKoZIzj0EAwIwJzELMAkGA1UE +BhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEy +MzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggq +hkjOPQMBBwNCAARfOJ2n/02Kr/Y0OUYa/Drf9COqqer7xQjeAI6+eaU3WExt3QHKq0ffibbHFx84 +/B0gFN1FwOCPk044C/zpmaFJo2YwZDAfBgNVHSMEGDAWgBTw0PEi+XpIFwZ7Pb249c1VnFw+cDAd +BgNVHQ4EFgQUww6GqnW0FcDllQkyvl6SdankRJswDAYDVR0TAQH/BAIwADAUBgNVHREEDTALggls +b2NhbGhvc3QwCgYIKoZIzj0EAwIDSAAwRQIhAJH79ATQ5S4B1IzwF2IP3MyAyhjEQHwnA8s0Aw2b +yFlNAiAFVWni2KFAMzQOfkkyZB0/ax/QLbcvUgRWr9M3j4eZog== +-----END CERTIFICATE----- diff --git a/BearSSL-OG/cert-ee-rsa.pem b/BearSSL-OG/cert-ee-rsa.pem new file mode 100644 index 0000000..ef33e40 --- /dev/null +++ b/BearSSL-OG/cert-ee-rsa.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIIDPDCCAiSgAwIBAgIUWNq6Ns3toNpcEDNzjgxkknmSrwMwDQYJKoZIhvcNAQELBQAwJzELMAkG +A1UEBhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEy +MzEyMzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDUeh0nuis6Z7KRavvng0TK7Rx1rd1Ng2LWqmiVsiQhexWuKplo +Fe1m8LhY59P1LsbZKl7nDi7n/GdZwMhhfUukb92f2ciFh2THuhoPKdSWqHiaa2IgqTLQ7qmMKGFH +olAqY/Yh3trY1fB/xQCCcOajv1yJJ09RkncDw7DMLjvsI/IvU0GviZP/0oCxQ5fe1hmgkhJ6PWZ5 +4cG84Xdwoos9RoRTP+ROQkE3kh4f/Tiz9++HOYDTVs/04BPeZLBypAOExEHtb/o+4soEINLX3CyC +K3ribaEcSNvPiU80lz0oqFPa58HhcxWjMHZ/jyNCFD1RNNJarTyby8j+f26OQPO9AgMBAAGjZjBk +MB8GA1UdIwQYMBaAFMUBrXzmY8mcF1/FoqfhUF/o9ajGMB0GA1UdDgQWBBTFAa185mPJnBdfxaKn +4VBf6PWoxjAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsF +AAOCAQEAcbNdIcIO19DG+Epzh00iAifQx/j9Gm1iWIIIdiAHwEiS8+mYWusNTlaVY2hNq9QAduA3 +zwsRYVlc3valFFnZJZ9Z2dNehqwdpiwyQhkyE0ALVM1nJra9tJakyh9/N9aodes6gVEwuflKAW/R +1u1P3z8wYAZnko5hhV8atYyzD2Gp+t9dxGQA6oexM199y6OFJG4sZTvqcz+G0/3o5ALGYWomF1IB +JVx/qM5pH6xhLLcEr/2kepnLJhVM/3TUcwxXDCbr1yrcXMNBu8Lzzha9jnv76d+rIQ2Rs43Yz8j0 +SbnQ4xZwP7Pe1Acl+kZEUolNicjiyrUzf8chvSjv/mZ0Aw== +-----END CERTIFICATE----- diff --git a/BearSSL-OG/cert-ica-ec.pem b/BearSSL-OG/cert-ica-ec.pem new file mode 100644 index 0000000..204ab76 --- /dev/null +++ b/BearSSL-OG/cert-ica-ec.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBqTCCAU6gAwIBAgIUINPr4oz+2uajLF478mY6KzZ7sMowCgYIKoZIzj0EAwIwHDELMAkGA1UE +BhMCQ0ExDTALBgNVBAMTBFJvb3QwHhcNMTAwMTAxMDAwMDAwWhcNMzcxMjMxMjM1OTU5WjAnMQsw +CQYDVQQGEwJDQTEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0D +AQcDQgAEcC6SggEXbG2r4dFjCUhJ0qY1UtM8c7uyiDeYh/GN4Oxlmg4T9e2RYci2bTOEbq6OVYDN +SZ4Hv9CunebQsycWoaNjMGEwHwYDVR0jBBgwFoAUlUG04meq8X+8j3nzaBRaa5IWokAwHQYDVR0O +BBYEFPDQ8SL5ekgXBns9vbj1zVWcXD5wMA4GA1UdDwEB/wQEAwIAhjAPBgNVHRMBAf8EBTADAQH/ +MAoGCCqGSM49BAMCA0kAMEYCIQCF40ZomdYCellmHLdPNS0INjhhfgVI2GlDH+tW6a0GDgIhAIJw +tGIDSUbIVFkF2XjbUxzgbmb1DxQ7yS04EnCRVvmp +-----END CERTIFICATE----- diff --git a/BearSSL-OG/cert-ica-rsa.pem b/BearSSL-OG/cert-ica-rsa.pem new file mode 100644 index 0000000..058ffab --- /dev/null +++ b/BearSSL-OG/cert-ica-rsa.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIUcA9g7vAHmpxprJdiJk9dBbb5j0gwDQYJKoZIhvcNAQELBQAwHDELMAkG +A1UEBhMCQ0ExDTALBgNVBAMTBFJvb3QwHhcNMTAwMTAxMDAwMDAwWhcNMzcxMjMxMjM1OTU5WjAn +MQswCQYDVQQGEwJDQTEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAs+hrr5wWUuOBDFCrJc7MDcfyH39Q3yxcNdZiLmMnQafkU6hLJ/oTkaP6 +CUovO17Pd7OKwc1JlZx1DWR07+TXS7mhm2jSMHFI6vdLFN8/R6nYu+yPKMz637QflHyW/AgFKPno +9C8v7mKcijrghVhgtg8tMLTAQVSRTB9frfEZ8MAipn3YP3k0WUJ7W7VBxGR/Us88NyKhL3kllCRB +wj/6x3X7SLUNGKf0VPMubthDWMSrUOgFrZG2HgF1s1Sc3qCZFfus8VyXSVHM71gSb3NrszQUAQ9a +nfqq1pPT4urDq7xO7cxRobj4lLa0LKiGKx/2UUMpUl4TibNqeGBOTsAbpQIDAQABo2MwYTAfBgNV +HSMEGDAWgBTDCry0kGOWkkW8J6DwWIkq1XgAEjAdBgNVHQ4EFgQUfM+jxin388WqGdDAFuvgQA/O +RKcwDgYDVR0PAQH/BAQDAgCGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFQ7 +9OrG5OjAWxKyrfq9qfRiA61XTG8Hp0c1dT5IoltxEAGPk5mdp0fjjj6vLboG/tTkl7wQjaalOjzm +Ics72hPjSiPrvLqlkJGtVW7V3YVLayfSOXYGLtQjW7tVtUk/fS8hy5Z1GZmpmfELuz7HEKeLelK5 +SeQUCHjnPdmYV9r/2rmNZnWAtV2532ll2xbnHsRA5EaKHnYyFueDZ9p4VqsPTFzxcNpmIPT4D/bc +L3KXa3hAeZ1bbb4DznBCqCpxEd8ugQHqhhKRT9AY7YSkSDC5uXtWPu+N4R/9kLJEhVhvpzB0fPGu +jJk/8U1XxZVowjay7MJoesCBqVUF58+vUKw= +-----END CERTIFICATE----- diff --git a/BearSSL-OG/cert-root-ec.pem b/BearSSL-OG/cert-root-ec.pem new file mode 100644 index 0000000..1bfd578 --- /dev/null +++ b/BearSSL-OG/cert-root-ec.pem @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBijCCATCgAwIBAgIBCTAKBggqhkjOPQQDAjAcMQswCQYDVQQGEwJDQTENMAsGA1UEAxMEUm9v +dDAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEyMzU5NTlaMBwxCzAJBgNVBAYTAkNBMQ0wCwYDVQQD +EwRSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcXS6q7kwLoHV5Vf58yBoDJz5ZNu0IA1t +6kDQSm5C/baaaCVE9t97xPze3Xu7xdt8dj9BZkBu26eHwuXYxfN/jaNjMGEwHwYDVR0jBBgwFoAU +lUG04meq8X+8j3nzaBRaa5IWokAwHQYDVR0OBBYEFJVBtOJnqvF/vI9582gUWmuSFqJAMA4GA1Ud +DwEB/wQEAwIAhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQCz1GCIAoRtqU2h +x62hec7E+/XxnUGDORWnkliiGrcmxQIgNPq9NHD7ts0xYjTwZsd0bN62+iY93lM4LHbkNV9q/gA= +-----END CERTIFICATE----- diff --git a/BearSSL-OG/cert-root-rsa.pem b/BearSSL-OG/cert-root-rsa.pem new file mode 100644 index 0000000..6b5ebd0 --- /dev/null +++ b/BearSSL-OG/cert-root-rsa.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIDFjCCAf6gAwIBAgIBCDANBgkqhkiG9w0BAQsFADAcMQswCQYDVQQGEwJDQTENMAsGA1UEAxME +Um9vdDAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEyMzU5NTlaMBwxCzAJBgNVBAYTAkNBMQ0wCwYD +VQQDEwRSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAttk01FD9s696c/HOOL9d +b0Xh/U6xmMZggybSF9HFt5qjwd5jOZec8F5cyBwXuYgZbfC2LjBQoVRuk8DbzzDLnx4nefHDmVI1 +qj2237CtfMtJzcDt52YQKunOKB8hUPp3TC3a7zxY606/zun7Gtqjg6PNo8qTgNza8xfMeqszgJyy +1H9GP8U83GGUtycpbiq8Wwk21MY7Deu+ztsdHLwQanFxs/LKKJp38orsQu+xSo7i8hoyKs3ApkYs +msKFN5F/RqGTgaF0Zt+6szkgkZP6HaGohefk+Qf2EPaoJwG2fxLDQMPJ4rCrSRg6ZLZZt5W1ljbf +ImmqcmpUTicpow6XFQIDAQABo2MwYTAfBgNVHSMEGDAWgBTDCry0kGOWkkW8J6DwWIkq1XgAEjAd +BgNVHQ4EFgQUwwq8tJBjlpJFvCeg8FiJKtV4ABIwDgYDVR0PAQH/BAQDAgCGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA7SaR2V1Gx71RiL5Cdfr15jkU88snnm+v+0PvIfQrNP +4RzKJkaD3j//oZf6Hr2yH6c7Bi3OhCxBFNbXjDXiAXVRoTjOSxNSwVq43utl9Z4IKAZzQlEYW5S5 +U0oskEq2q6jDEWoj8lUtQW4GAVuZhq7lNs0jJJu84IBsxHJFgZJ/7+LHFLXs+vQkz3hjzMZ7gIt+ +lwXI/gdY9ld1QB6WLLIzxs7zid+Z0LZTYi851vbmMwUqgL8V5Np0Q0EVHHy1c6LQ0hj1kVLay2ZN +d2dsUMCQJI5EF2kWon+xFDpAtv0vUT2xuMkYFhjS/aBxzevWCsXuUQphBYaIGli8P68NNPo= +-----END CERTIFICATE----- diff --git a/BearSSL-OG/cert_pinning.cpp b/BearSSL-OG/cert_pinning.cpp new file mode 100644 index 0000000..51fc3c9 --- /dev/null +++ b/BearSSL-OG/cert_pinning.cpp @@ -0,0 +1,163 @@ +#include "cert_pinning.h" +#include "ssl_debug.h" + +#include +#include + +/* Constant-time comparison for cryptographic material. + Returns 0 if equal, non-zero otherwise. */ +static int ct_memcmp(const unsigned char *a, const unsigned char *b, size_t n) +{ + unsigned char diff = 0; + size_t i; + for (i = 0; i < n; i++) { + diff |= a[i] ^ b[i]; + } + return diff; +} + +cert_pinning::pin_entry cert_pinning::pins[MAX_PINNED_HOSTS]; +bool cert_pinning::initialized = false; + +void cert_pinning::initialize() +{ + if (initialized) return; + + memset(pins, 0, sizeof(pins)); + initialized = true; + ssl_debug::log_verbose("Certificate pinning initialized\n"); +} + +void cert_pinning::shutdown() +{ + clear(); + initialized = false; +} + +int cert_pinning::find_pin(const char* hostname) +{ + for (int i = 0; i < MAX_PINNED_HOSTS; i++) { + if (pins[i].valid && _stricmp(pins[i].hostname, hostname) == 0) { + return i; + } + } + return -1; +} + +bool cert_pinning::add_pin(const char* hostname, const unsigned char* sha256_hash) +{ + if (!initialized) initialize(); + + // Check if already exists + int idx = find_pin(hostname); + if (idx >= 0) { + // Update existing + memcpy(pins[idx].sha256_hash, sha256_hash, 32); + ssl_debug::log_info("Certificate pin updated for %s\n", hostname); + return true; + } + + // Find free slot + for (int i = 0; i < MAX_PINNED_HOSTS; i++) { + if (!pins[i].valid) { + strncpy(pins[i].hostname, hostname, 255); + pins[i].hostname[255] = '\0'; + memcpy(pins[i].sha256_hash, sha256_hash, 32); + pins[i].valid = true; + ssl_debug::log_info("Certificate pin added for %s\n", hostname); + return true; + } + } + + ssl_debug::log_error("Certificate pin table full, cannot add %s\n", hostname); + return false; +} + +void cert_pinning::remove_pin(const char* hostname) +{ + int idx = find_pin(hostname); + if (idx >= 0) { + pins[idx].valid = false; + ssl_debug::log_info("Certificate pin removed for %s\n", hostname); + } +} + +void cert_pinning::clear() +{ + memset(pins, 0, sizeof(pins)); + ssl_debug::log_verbose("All certificate pins cleared\n"); +} + +bool cert_pinning::has_pin(const char* hostname) +{ + return find_pin(hostname) >= 0; +} + +bool cert_pinning::get_pin_hash(const char* hostname, unsigned char* hash_out) +{ + int idx = find_pin(hostname); + if (idx < 0) { + return false; + } + memcpy(hash_out, pins[idx].sha256_hash, 32); + return true; +} + +void cert_pinning::get_cert_hash(br_ssl_engine_context* engine, unsigned char* hash_out) +{ + /* + * This legacy function is kept for API compatibility but is not the + * recommended path. Use verify_hash() with a hash captured by the + * custom X.509 callback in bearssl.c instead. + */ + (void)engine; + memset(hash_out, 0, 32); +} + +bool cert_pinning::verify_hash(const char* hostname, const unsigned char* cert_sha256) +{ + if (!initialized) initialize(); + + int idx = find_pin(hostname); + if (idx < 0) { + /* No pin for this host - allow connection */ + return true; + } + + /* Compare the captured certificate hash against the stored pin. + Uses constant-time comparison to prevent timing side channels. */ + if (ct_memcmp(pins[idx].sha256_hash, cert_sha256, 32) == 0) { + ssl_debug::log_info("Certificate pin MATCH for %s\n", hostname); + return true; + } + + /* Pin mismatch */ + ssl_debug::log_error("Certificate pin MISMATCH for %s!\n", hostname); + ssl_debug::log_error(" Expected: %02X%02X%02X%02X...\n", + pins[idx].sha256_hash[0], pins[idx].sha256_hash[1], + pins[idx].sha256_hash[2], pins[idx].sha256_hash[3]); + ssl_debug::log_error(" Got: %02X%02X%02X%02X...\n", + cert_sha256[0], cert_sha256[1], cert_sha256[2], cert_sha256[3]); + return false; +} + +bool cert_pinning::verify(const char* hostname, br_ssl_engine_context* engine) +{ + if (!initialized) initialize(); + + int idx = find_pin(hostname); + if (idx < 0) { + /* No pin for this host - allow connection */ + return true; + } + + /* + * Legacy path: try to use the engine directly. + * The preferred path is verify_hash() called from the X.509 callback + * in bearssl.c, which captures the leaf cert hash during the handshake. + */ + ssl_debug::log_info("Certificate pin check for %s (via engine - use verify_hash for best results)\n", hostname); + + (void)engine; + return true; +} diff --git a/BearSSL-OG/cert_pinning.h b/BearSSL-OG/cert_pinning.h new file mode 100644 index 0000000..58c25b5 --- /dev/null +++ b/BearSSL-OG/cert_pinning.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +#define MAX_PINNED_HOSTS 8 + +class cert_pinning +{ +public: + static void initialize(); + static void shutdown(); + + // Add a pin: hostname + SHA-256 hash of certificate + static bool add_pin(const char* hostname, const unsigned char* sha256_hash); + + // Remove a pin + static void remove_pin(const char* hostname); + + // Clear all pins + static void clear(); + + // Verify certificate hash matches pin (returns true if no pin exists or if pin matches) + static bool verify(const char* hostname, br_ssl_engine_context* engine); + + // Verify a pre-computed SHA-256 hash against stored pin + // Returns true if no pin exists for hostname, or if pin matches the hash + static bool verify_hash(const char* hostname, const unsigned char* cert_sha256); + + // Check if hostname has a pin + static bool has_pin(const char* hostname); + + // Get the stored pin hash for a hostname (returns false if no pin) + static bool get_pin_hash(const char* hostname, unsigned char* hash_out); + + // Get hash of current certificate (for setting up pins) + static void get_cert_hash(br_ssl_engine_context* engine, unsigned char* hash_out); + +private: + struct pin_entry { + char hostname[256]; + unsigned char sha256_hash[32]; + bool valid; + }; + + static pin_entry pins[MAX_PINNED_HOSTS]; + static bool initialized; + + static int find_pin(const char* hostname); +}; diff --git a/BearSSL-OG/certificates.cpp b/BearSSL-OG/certificates.cpp new file mode 100644 index 0000000..8c4020a --- /dev/null +++ b/BearSSL-OG/certificates.cpp @@ -0,0 +1,858 @@ +#include "certificates.h" +#include "ca_loader.h" +#include +#include + +#include "trust_anchors.h" + +#define NUM_TRUST_ANCHORS 750 + +namespace +{ + br_x509_trust_anchor* trust_anchors = NULL; + int trust_anchor_count = 0; + int loaded_from_file = 0; /* 1 = heap-allocated per-anchor data */ +} + +void certificates::initialize_trust_anchors() +{ + if (trust_anchors != NULL) + { + return; + } + trust_anchors = (br_x509_trust_anchor*)malloc(NUM_TRUST_ANCHORS * sizeof br_x509_trust_anchor); + if (trust_anchors == NULL) + { + OutputDebugStringA("certificates: FATAL - malloc failed for trust anchors!\n"); + return; + } + trust_anchor_count = NUM_TRUST_ANCHORS; + loaded_from_file = 0; + trust_anchors[0] = make_rsa_trust_anchor((unsigned char *)TA0_DN, sizeof TA0_DN, (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E); + trust_anchors[1] = make_ec_trust_anchor((unsigned char *)TA1_DN, sizeof TA1_DN, BR_EC_secp384r1, (unsigned char *)TA1_EC_Q, sizeof TA1_EC_Q); + trust_anchors[2] = make_rsa_trust_anchor((unsigned char *)TA2_DN, sizeof TA2_DN, (unsigned char *)TA2_RSA_N, sizeof TA2_RSA_N, (unsigned char *)TA2_RSA_E, sizeof TA2_RSA_E); + trust_anchors[3] = make_rsa_trust_anchor((unsigned char *)TA3_DN, sizeof TA3_DN, (unsigned char *)TA3_RSA_N, sizeof TA3_RSA_N, (unsigned char *)TA3_RSA_E, sizeof TA3_RSA_E); + trust_anchors[4] = make_ec_trust_anchor((unsigned char *)TA4_DN, sizeof TA4_DN, BR_EC_secp384r1, (unsigned char *)TA4_EC_Q, sizeof TA4_EC_Q); + trust_anchors[5] = make_rsa_trust_anchor((unsigned char *)TA5_DN, sizeof TA5_DN, (unsigned char *)TA5_RSA_N, sizeof TA5_RSA_N, (unsigned char *)TA5_RSA_E, sizeof TA5_RSA_E); + trust_anchors[6] = make_rsa_trust_anchor((unsigned char *)TA6_DN, sizeof TA6_DN, (unsigned char *)TA6_RSA_N, sizeof TA6_RSA_N, (unsigned char *)TA6_RSA_E, sizeof TA6_RSA_E); + trust_anchors[7] = make_ec_trust_anchor((unsigned char *)TA7_DN, sizeof TA7_DN, BR_EC_secp384r1, (unsigned char *)TA7_EC_Q, sizeof TA7_EC_Q); + trust_anchors[8] = make_rsa_trust_anchor((unsigned char *)TA8_DN, sizeof TA8_DN, (unsigned char *)TA8_RSA_N, sizeof TA8_RSA_N, (unsigned char *)TA8_RSA_E, sizeof TA8_RSA_E); + trust_anchors[9] = make_ec_trust_anchor((unsigned char *)TA9_DN, sizeof TA9_DN, BR_EC_secp384r1, (unsigned char *)TA9_EC_Q, sizeof TA9_EC_Q); + trust_anchors[10] = make_rsa_trust_anchor((unsigned char *)TA10_DN, sizeof TA10_DN, (unsigned char *)TA10_RSA_N, sizeof TA10_RSA_N, (unsigned char *)TA10_RSA_E, sizeof TA10_RSA_E); + trust_anchors[11] = make_ec_trust_anchor((unsigned char *)TA11_DN, sizeof TA11_DN, BR_EC_secp384r1, (unsigned char *)TA11_EC_Q, sizeof TA11_EC_Q); + trust_anchors[12] = make_rsa_trust_anchor((unsigned char *)TA12_DN, sizeof TA12_DN, (unsigned char *)TA12_RSA_N, sizeof TA12_RSA_N, (unsigned char *)TA12_RSA_E, sizeof TA12_RSA_E); + trust_anchors[13] = make_ec_trust_anchor((unsigned char *)TA13_DN, sizeof TA13_DN, BR_EC_secp384r1, (unsigned char *)TA13_EC_Q, sizeof TA13_EC_Q); + trust_anchors[14] = make_ec_trust_anchor((unsigned char *)TA14_DN, sizeof TA14_DN, BR_EC_secp384r1, (unsigned char *)TA14_EC_Q, sizeof TA14_EC_Q); + trust_anchors[15] = make_ec_trust_anchor((unsigned char *)TA15_DN, sizeof TA15_DN, BR_EC_secp256r1, (unsigned char *)TA15_EC_Q, sizeof TA15_EC_Q); + trust_anchors[16] = make_rsa_trust_anchor((unsigned char *)TA16_DN, sizeof TA16_DN, (unsigned char *)TA16_RSA_N, sizeof TA16_RSA_N, (unsigned char *)TA16_RSA_E, sizeof TA16_RSA_E); + trust_anchors[17] = make_rsa_trust_anchor((unsigned char *)TA17_DN, sizeof TA17_DN, (unsigned char *)TA17_RSA_N, sizeof TA17_RSA_N, (unsigned char *)TA17_RSA_E, sizeof TA17_RSA_E); + trust_anchors[18] = make_rsa_trust_anchor((unsigned char *)TA18_DN, sizeof TA18_DN, (unsigned char *)TA18_RSA_N, sizeof TA18_RSA_N, (unsigned char *)TA18_RSA_E, sizeof TA18_RSA_E); + trust_anchors[19] = make_rsa_trust_anchor((unsigned char *)TA19_DN, sizeof TA19_DN, (unsigned char *)TA19_RSA_N, sizeof TA19_RSA_N, (unsigned char *)TA19_RSA_E, sizeof TA19_RSA_E); + trust_anchors[20] = make_ec_trust_anchor((unsigned char *)TA20_DN, sizeof TA20_DN, BR_EC_secp384r1, (unsigned char *)TA20_EC_Q, sizeof TA20_EC_Q); + trust_anchors[21] = make_rsa_trust_anchor((unsigned char *)TA21_DN, sizeof TA21_DN, (unsigned char *)TA21_RSA_N, sizeof TA21_RSA_N, (unsigned char *)TA21_RSA_E, sizeof TA21_RSA_E); + trust_anchors[22] = make_ec_trust_anchor((unsigned char *)TA22_DN, sizeof TA22_DN, BR_EC_secp384r1, (unsigned char *)TA22_EC_Q, sizeof TA22_EC_Q); + trust_anchors[23] = make_ec_trust_anchor((unsigned char *)TA23_DN, sizeof TA23_DN, BR_EC_secp256r1, (unsigned char *)TA23_EC_Q, sizeof TA23_EC_Q); + trust_anchors[24] = make_rsa_trust_anchor((unsigned char *)TA24_DN, sizeof TA24_DN, (unsigned char *)TA24_RSA_N, sizeof TA24_RSA_N, (unsigned char *)TA24_RSA_E, sizeof TA24_RSA_E); + trust_anchors[25] = make_ec_trust_anchor((unsigned char *)TA25_DN, sizeof TA25_DN, BR_EC_secp384r1, (unsigned char *)TA25_EC_Q, sizeof TA25_EC_Q); + trust_anchors[26] = make_ec_trust_anchor((unsigned char *)TA26_DN, sizeof TA26_DN, BR_EC_secp384r1, (unsigned char *)TA26_EC_Q, sizeof TA26_EC_Q); + trust_anchors[27] = make_rsa_trust_anchor((unsigned char *)TA27_DN, sizeof TA27_DN, (unsigned char *)TA27_RSA_N, sizeof TA27_RSA_N, (unsigned char *)TA27_RSA_E, sizeof TA27_RSA_E); + trust_anchors[28] = make_rsa_trust_anchor((unsigned char *)TA28_DN, sizeof TA28_DN, (unsigned char *)TA28_RSA_N, sizeof TA28_RSA_N, (unsigned char *)TA28_RSA_E, sizeof TA28_RSA_E); + trust_anchors[29] = make_rsa_trust_anchor((unsigned char *)TA29_DN, sizeof TA29_DN, (unsigned char *)TA29_RSA_N, sizeof TA29_RSA_N, (unsigned char *)TA29_RSA_E, sizeof TA29_RSA_E); + trust_anchors[30] = make_rsa_trust_anchor((unsigned char *)TA30_DN, sizeof TA30_DN, (unsigned char *)TA30_RSA_N, sizeof TA30_RSA_N, (unsigned char *)TA30_RSA_E, sizeof TA30_RSA_E); + trust_anchors[31] = make_rsa_trust_anchor((unsigned char *)TA31_DN, sizeof TA31_DN, (unsigned char *)TA31_RSA_N, sizeof TA31_RSA_N, (unsigned char *)TA31_RSA_E, sizeof TA31_RSA_E); + trust_anchors[32] = make_rsa_trust_anchor((unsigned char *)TA32_DN, sizeof TA32_DN, (unsigned char *)TA32_RSA_N, sizeof TA32_RSA_N, (unsigned char *)TA32_RSA_E, sizeof TA32_RSA_E); + trust_anchors[33] = make_rsa_trust_anchor((unsigned char *)TA33_DN, sizeof TA33_DN, (unsigned char *)TA33_RSA_N, sizeof TA33_RSA_N, (unsigned char *)TA33_RSA_E, sizeof TA33_RSA_E); + trust_anchors[34] = make_rsa_trust_anchor((unsigned char *)TA34_DN, sizeof TA34_DN, (unsigned char *)TA34_RSA_N, sizeof TA34_RSA_N, (unsigned char *)TA34_RSA_E, sizeof TA34_RSA_E); + trust_anchors[35] = make_rsa_trust_anchor((unsigned char *)TA35_DN, sizeof TA35_DN, (unsigned char *)TA35_RSA_N, sizeof TA35_RSA_N, (unsigned char *)TA35_RSA_E, sizeof TA35_RSA_E); + trust_anchors[36] = make_ec_trust_anchor((unsigned char *)TA36_DN, sizeof TA36_DN, BR_EC_secp384r1, (unsigned char *)TA36_EC_Q, sizeof TA36_EC_Q); + trust_anchors[37] = make_rsa_trust_anchor((unsigned char *)TA37_DN, sizeof TA37_DN, (unsigned char *)TA37_RSA_N, sizeof TA37_RSA_N, (unsigned char *)TA37_RSA_E, sizeof TA37_RSA_E); + trust_anchors[38] = make_rsa_trust_anchor((unsigned char *)TA38_DN, sizeof TA38_DN, (unsigned char *)TA38_RSA_N, sizeof TA38_RSA_N, (unsigned char *)TA38_RSA_E, sizeof TA38_RSA_E); + trust_anchors[39] = make_ec_trust_anchor((unsigned char *)TA39_DN, sizeof TA39_DN, BR_EC_secp384r1, (unsigned char *)TA39_EC_Q, sizeof TA39_EC_Q); + trust_anchors[40] = make_rsa_trust_anchor((unsigned char *)TA40_DN, sizeof TA40_DN, (unsigned char *)TA40_RSA_N, sizeof TA40_RSA_N, (unsigned char *)TA40_RSA_E, sizeof TA40_RSA_E); + trust_anchors[41] = make_ec_trust_anchor((unsigned char *)TA41_DN, sizeof TA41_DN, BR_EC_secp384r1, (unsigned char *)TA41_EC_Q, sizeof TA41_EC_Q); + trust_anchors[42] = make_rsa_trust_anchor((unsigned char *)TA42_DN, sizeof TA42_DN, (unsigned char *)TA42_RSA_N, sizeof TA42_RSA_N, (unsigned char *)TA42_RSA_E, sizeof TA42_RSA_E); + trust_anchors[43] = make_rsa_trust_anchor((unsigned char *)TA43_DN, sizeof TA43_DN, (unsigned char *)TA43_RSA_N, sizeof TA43_RSA_N, (unsigned char *)TA43_RSA_E, sizeof TA43_RSA_E); + trust_anchors[44] = make_rsa_trust_anchor((unsigned char *)TA44_DN, sizeof TA44_DN, (unsigned char *)TA44_RSA_N, sizeof TA44_RSA_N, (unsigned char *)TA44_RSA_E, sizeof TA44_RSA_E); + trust_anchors[45] = make_ec_trust_anchor((unsigned char *)TA45_DN, sizeof TA45_DN, BR_EC_secp384r1, (unsigned char *)TA45_EC_Q, sizeof TA45_EC_Q); + trust_anchors[46] = make_rsa_trust_anchor((unsigned char *)TA46_DN, sizeof TA46_DN, (unsigned char *)TA46_RSA_N, sizeof TA46_RSA_N, (unsigned char *)TA46_RSA_E, sizeof TA46_RSA_E); + trust_anchors[47] = make_rsa_trust_anchor((unsigned char *)TA47_DN, sizeof TA47_DN, (unsigned char *)TA47_RSA_N, sizeof TA47_RSA_N, (unsigned char *)TA47_RSA_E, sizeof TA47_RSA_E); + trust_anchors[48] = make_rsa_trust_anchor((unsigned char *)TA48_DN, sizeof TA48_DN, (unsigned char *)TA48_RSA_N, sizeof TA48_RSA_N, (unsigned char *)TA48_RSA_E, sizeof TA48_RSA_E); + trust_anchors[49] = make_rsa_trust_anchor((unsigned char *)TA49_DN, sizeof TA49_DN, (unsigned char *)TA49_RSA_N, sizeof TA49_RSA_N, (unsigned char *)TA49_RSA_E, sizeof TA49_RSA_E); + trust_anchors[50] = make_rsa_trust_anchor((unsigned char *)TA50_DN, sizeof TA50_DN, (unsigned char *)TA50_RSA_N, sizeof TA50_RSA_N, (unsigned char *)TA50_RSA_E, sizeof TA50_RSA_E); + trust_anchors[51] = make_rsa_trust_anchor((unsigned char *)TA51_DN, sizeof TA51_DN, (unsigned char *)TA51_RSA_N, sizeof TA51_RSA_N, (unsigned char *)TA51_RSA_E, sizeof TA51_RSA_E); + trust_anchors[52] = make_ec_trust_anchor((unsigned char *)TA52_DN, sizeof TA52_DN, BR_EC_secp384r1, (unsigned char *)TA52_EC_Q, sizeof TA52_EC_Q); + trust_anchors[53] = make_rsa_trust_anchor((unsigned char *)TA53_DN, sizeof TA53_DN, (unsigned char *)TA53_RSA_N, sizeof TA53_RSA_N, (unsigned char *)TA53_RSA_E, sizeof TA53_RSA_E); + trust_anchors[54] = make_rsa_trust_anchor((unsigned char *)TA54_DN, sizeof TA54_DN, (unsigned char *)TA54_RSA_N, sizeof TA54_RSA_N, (unsigned char *)TA54_RSA_E, sizeof TA54_RSA_E); + trust_anchors[55] = make_rsa_trust_anchor((unsigned char *)TA55_DN, sizeof TA55_DN, (unsigned char *)TA55_RSA_N, sizeof TA55_RSA_N, (unsigned char *)TA55_RSA_E, sizeof TA55_RSA_E); + trust_anchors[56] = make_rsa_trust_anchor((unsigned char *)TA56_DN, sizeof TA56_DN, (unsigned char *)TA56_RSA_N, sizeof TA56_RSA_N, (unsigned char *)TA56_RSA_E, sizeof TA56_RSA_E); + trust_anchors[57] = make_ec_trust_anchor((unsigned char *)TA57_DN, sizeof TA57_DN, BR_EC_secp384r1, (unsigned char *)TA57_EC_Q, sizeof TA57_EC_Q); + trust_anchors[58] = make_rsa_trust_anchor((unsigned char *)TA58_DN, sizeof TA58_DN, (unsigned char *)TA58_RSA_N, sizeof TA58_RSA_N, (unsigned char *)TA58_RSA_E, sizeof TA58_RSA_E); + trust_anchors[59] = make_rsa_trust_anchor((unsigned char *)TA59_DN, sizeof TA59_DN, (unsigned char *)TA59_RSA_N, sizeof TA59_RSA_N, (unsigned char *)TA59_RSA_E, sizeof TA59_RSA_E); + trust_anchors[60] = make_ec_trust_anchor((unsigned char *)TA60_DN, sizeof TA60_DN, BR_EC_secp384r1, (unsigned char *)TA60_EC_Q, sizeof TA60_EC_Q); + trust_anchors[61] = make_rsa_trust_anchor((unsigned char *)TA61_DN, sizeof TA61_DN, (unsigned char *)TA61_RSA_N, sizeof TA61_RSA_N, (unsigned char *)TA61_RSA_E, sizeof TA61_RSA_E); + trust_anchors[62] = make_ec_trust_anchor((unsigned char *)TA62_DN, sizeof TA62_DN, BR_EC_secp384r1, (unsigned char *)TA62_EC_Q, sizeof TA62_EC_Q); + trust_anchors[63] = make_rsa_trust_anchor((unsigned char *)TA63_DN, sizeof TA63_DN, (unsigned char *)TA63_RSA_N, sizeof TA63_RSA_N, (unsigned char *)TA63_RSA_E, sizeof TA63_RSA_E); + trust_anchors[64] = make_rsa_trust_anchor((unsigned char *)TA64_DN, sizeof TA64_DN, (unsigned char *)TA64_RSA_N, sizeof TA64_RSA_N, (unsigned char *)TA64_RSA_E, sizeof TA64_RSA_E); + trust_anchors[65] = make_rsa_trust_anchor((unsigned char *)TA65_DN, sizeof TA65_DN, (unsigned char *)TA65_RSA_N, sizeof TA65_RSA_N, (unsigned char *)TA65_RSA_E, sizeof TA65_RSA_E); + trust_anchors[66] = make_rsa_trust_anchor((unsigned char *)TA66_DN, sizeof TA66_DN, (unsigned char *)TA66_RSA_N, sizeof TA66_RSA_N, (unsigned char *)TA66_RSA_E, sizeof TA66_RSA_E); + trust_anchors[67] = make_rsa_trust_anchor((unsigned char *)TA67_DN, sizeof TA67_DN, (unsigned char *)TA67_RSA_N, sizeof TA67_RSA_N, (unsigned char *)TA67_RSA_E, sizeof TA67_RSA_E); + trust_anchors[68] = make_rsa_trust_anchor((unsigned char *)TA68_DN, sizeof TA68_DN, (unsigned char *)TA68_RSA_N, sizeof TA68_RSA_N, (unsigned char *)TA68_RSA_E, sizeof TA68_RSA_E); + trust_anchors[69] = make_ec_trust_anchor((unsigned char *)TA69_DN, sizeof TA69_DN, BR_EC_secp384r1, (unsigned char *)TA69_EC_Q, sizeof TA69_EC_Q); + trust_anchors[70] = make_rsa_trust_anchor((unsigned char *)TA70_DN, sizeof TA70_DN, (unsigned char *)TA70_RSA_N, sizeof TA70_RSA_N, (unsigned char *)TA70_RSA_E, sizeof TA70_RSA_E); + trust_anchors[71] = make_rsa_trust_anchor((unsigned char *)TA71_DN, sizeof TA71_DN, (unsigned char *)TA71_RSA_N, sizeof TA71_RSA_N, (unsigned char *)TA71_RSA_E, sizeof TA71_RSA_E); + trust_anchors[72] = make_rsa_trust_anchor((unsigned char *)TA72_DN, sizeof TA72_DN, (unsigned char *)TA72_RSA_N, sizeof TA72_RSA_N, (unsigned char *)TA72_RSA_E, sizeof TA72_RSA_E); + trust_anchors[73] = make_rsa_trust_anchor((unsigned char *)TA73_DN, sizeof TA73_DN, (unsigned char *)TA73_RSA_N, sizeof TA73_RSA_N, (unsigned char *)TA73_RSA_E, sizeof TA73_RSA_E); + trust_anchors[74] = make_ec_trust_anchor((unsigned char *)TA74_DN, sizeof TA74_DN, BR_EC_secp384r1, (unsigned char *)TA74_EC_Q, sizeof TA74_EC_Q); + trust_anchors[75] = make_rsa_trust_anchor((unsigned char *)TA75_DN, sizeof TA75_DN, (unsigned char *)TA75_RSA_N, sizeof TA75_RSA_N, (unsigned char *)TA75_RSA_E, sizeof TA75_RSA_E); + trust_anchors[76] = make_rsa_trust_anchor((unsigned char *)TA76_DN, sizeof TA76_DN, (unsigned char *)TA76_RSA_N, sizeof TA76_RSA_N, (unsigned char *)TA76_RSA_E, sizeof TA76_RSA_E); + trust_anchors[77] = make_ec_trust_anchor((unsigned char *)TA77_DN, sizeof TA77_DN, BR_EC_secp384r1, (unsigned char *)TA77_EC_Q, sizeof TA77_EC_Q); + trust_anchors[78] = make_rsa_trust_anchor((unsigned char *)TA78_DN, sizeof TA78_DN, (unsigned char *)TA78_RSA_N, sizeof TA78_RSA_N, (unsigned char *)TA78_RSA_E, sizeof TA78_RSA_E); + trust_anchors[79] = make_rsa_trust_anchor((unsigned char *)TA79_DN, sizeof TA79_DN, (unsigned char *)TA79_RSA_N, sizeof TA79_RSA_N, (unsigned char *)TA79_RSA_E, sizeof TA79_RSA_E); + trust_anchors[80] = make_rsa_trust_anchor((unsigned char *)TA80_DN, sizeof TA80_DN, (unsigned char *)TA80_RSA_N, sizeof TA80_RSA_N, (unsigned char *)TA80_RSA_E, sizeof TA80_RSA_E); + trust_anchors[81] = make_rsa_trust_anchor((unsigned char *)TA81_DN, sizeof TA81_DN, (unsigned char *)TA81_RSA_N, sizeof TA81_RSA_N, (unsigned char *)TA81_RSA_E, sizeof TA81_RSA_E); + trust_anchors[82] = make_rsa_trust_anchor((unsigned char *)TA82_DN, sizeof TA82_DN, (unsigned char *)TA82_RSA_N, sizeof TA82_RSA_N, (unsigned char *)TA82_RSA_E, sizeof TA82_RSA_E); + trust_anchors[83] = make_rsa_trust_anchor((unsigned char *)TA83_DN, sizeof TA83_DN, (unsigned char *)TA83_RSA_N, sizeof TA83_RSA_N, (unsigned char *)TA83_RSA_E, sizeof TA83_RSA_E); + trust_anchors[84] = make_rsa_trust_anchor((unsigned char *)TA84_DN, sizeof TA84_DN, (unsigned char *)TA84_RSA_N, sizeof TA84_RSA_N, (unsigned char *)TA84_RSA_E, sizeof TA84_RSA_E); + trust_anchors[85] = make_ec_trust_anchor((unsigned char *)TA85_DN, sizeof TA85_DN, BR_EC_secp384r1, (unsigned char *)TA85_EC_Q, sizeof TA85_EC_Q); + trust_anchors[86] = make_ec_trust_anchor((unsigned char *)TA86_DN, sizeof TA86_DN, BR_EC_secp384r1, (unsigned char *)TA86_EC_Q, sizeof TA86_EC_Q); + trust_anchors[87] = make_ec_trust_anchor((unsigned char *)TA87_DN, sizeof TA87_DN, BR_EC_secp384r1, (unsigned char *)TA87_EC_Q, sizeof TA87_EC_Q); + trust_anchors[88] = make_rsa_trust_anchor((unsigned char *)TA88_DN, sizeof TA88_DN, (unsigned char *)TA88_RSA_N, sizeof TA88_RSA_N, (unsigned char *)TA88_RSA_E, sizeof TA88_RSA_E); + trust_anchors[89] = make_ec_trust_anchor((unsigned char *)TA89_DN, sizeof TA89_DN, BR_EC_secp384r1, (unsigned char *)TA89_EC_Q, sizeof TA89_EC_Q); + trust_anchors[90] = make_rsa_trust_anchor((unsigned char *)TA90_DN, sizeof TA90_DN, (unsigned char *)TA90_RSA_N, sizeof TA90_RSA_N, (unsigned char *)TA90_RSA_E, sizeof TA90_RSA_E); + trust_anchors[91] = make_rsa_trust_anchor((unsigned char *)TA91_DN, sizeof TA91_DN, (unsigned char *)TA91_RSA_N, sizeof TA91_RSA_N, (unsigned char *)TA91_RSA_E, sizeof TA91_RSA_E); + trust_anchors[92] = make_rsa_trust_anchor((unsigned char *)TA92_DN, sizeof TA92_DN, (unsigned char *)TA92_RSA_N, sizeof TA92_RSA_N, (unsigned char *)TA92_RSA_E, sizeof TA92_RSA_E); + trust_anchors[93] = make_rsa_trust_anchor((unsigned char *)TA93_DN, sizeof TA93_DN, (unsigned char *)TA93_RSA_N, sizeof TA93_RSA_N, (unsigned char *)TA93_RSA_E, sizeof TA93_RSA_E); + trust_anchors[94] = make_rsa_trust_anchor((unsigned char *)TA94_DN, sizeof TA94_DN, (unsigned char *)TA94_RSA_N, sizeof TA94_RSA_N, (unsigned char *)TA94_RSA_E, sizeof TA94_RSA_E); + trust_anchors[95] = make_rsa_trust_anchor((unsigned char *)TA95_DN, sizeof TA95_DN, (unsigned char *)TA95_RSA_N, sizeof TA95_RSA_N, (unsigned char *)TA95_RSA_E, sizeof TA95_RSA_E); + trust_anchors[96] = make_ec_trust_anchor((unsigned char *)TA96_DN, sizeof TA96_DN, BR_EC_secp384r1, (unsigned char *)TA96_EC_Q, sizeof TA96_EC_Q); + trust_anchors[97] = make_ec_trust_anchor((unsigned char *)TA97_DN, sizeof TA97_DN, BR_EC_secp384r1, (unsigned char *)TA97_EC_Q, sizeof TA97_EC_Q); + trust_anchors[98] = make_rsa_trust_anchor((unsigned char *)TA98_DN, sizeof TA98_DN, (unsigned char *)TA98_RSA_N, sizeof TA98_RSA_N, (unsigned char *)TA98_RSA_E, sizeof TA98_RSA_E); + trust_anchors[99] = make_rsa_trust_anchor((unsigned char *)TA99_DN, sizeof TA99_DN, (unsigned char *)TA99_RSA_N, sizeof TA99_RSA_N, (unsigned char *)TA99_RSA_E, sizeof TA99_RSA_E); + trust_anchors[100] = make_rsa_trust_anchor((unsigned char *)TA100_DN, sizeof TA100_DN, (unsigned char *)TA100_RSA_N, sizeof TA100_RSA_N, (unsigned char *)TA100_RSA_E, sizeof TA100_RSA_E); + trust_anchors[101] = make_rsa_trust_anchor((unsigned char *)TA101_DN, sizeof TA101_DN, (unsigned char *)TA101_RSA_N, sizeof TA101_RSA_N, (unsigned char *)TA101_RSA_E, sizeof TA101_RSA_E); + trust_anchors[102] = make_rsa_trust_anchor((unsigned char *)TA102_DN, sizeof TA102_DN, (unsigned char *)TA102_RSA_N, sizeof TA102_RSA_N, (unsigned char *)TA102_RSA_E, sizeof TA102_RSA_E); + trust_anchors[103] = make_rsa_trust_anchor((unsigned char *)TA103_DN, sizeof TA103_DN, (unsigned char *)TA103_RSA_N, sizeof TA103_RSA_N, (unsigned char *)TA103_RSA_E, sizeof TA103_RSA_E); + trust_anchors[104] = make_rsa_trust_anchor((unsigned char *)TA104_DN, sizeof TA104_DN, (unsigned char *)TA104_RSA_N, sizeof TA104_RSA_N, (unsigned char *)TA104_RSA_E, sizeof TA104_RSA_E); + trust_anchors[105] = make_rsa_trust_anchor((unsigned char *)TA105_DN, sizeof TA105_DN, (unsigned char *)TA105_RSA_N, sizeof TA105_RSA_N, (unsigned char *)TA105_RSA_E, sizeof TA105_RSA_E); + trust_anchors[106] = make_rsa_trust_anchor((unsigned char *)TA106_DN, sizeof TA106_DN, (unsigned char *)TA106_RSA_N, sizeof TA106_RSA_N, (unsigned char *)TA106_RSA_E, sizeof TA106_RSA_E); + trust_anchors[107] = make_ec_trust_anchor((unsigned char *)TA107_DN, sizeof TA107_DN, BR_EC_secp384r1, (unsigned char *)TA107_EC_Q, sizeof TA107_EC_Q); + trust_anchors[108] = make_ec_trust_anchor((unsigned char *)TA108_DN, sizeof TA108_DN, BR_EC_secp384r1, (unsigned char *)TA108_EC_Q, sizeof TA108_EC_Q); + trust_anchors[109] = make_ec_trust_anchor((unsigned char *)TA109_DN, sizeof TA109_DN, BR_EC_secp384r1, (unsigned char *)TA109_EC_Q, sizeof TA109_EC_Q); + trust_anchors[110] = make_rsa_trust_anchor((unsigned char *)TA110_DN, sizeof TA110_DN, (unsigned char *)TA110_RSA_N, sizeof TA110_RSA_N, (unsigned char *)TA110_RSA_E, sizeof TA110_RSA_E); + trust_anchors[111] = make_rsa_trust_anchor((unsigned char *)TA111_DN, sizeof TA111_DN, (unsigned char *)TA111_RSA_N, sizeof TA111_RSA_N, (unsigned char *)TA111_RSA_E, sizeof TA111_RSA_E); + trust_anchors[112] = make_rsa_trust_anchor((unsigned char *)TA112_DN, sizeof TA112_DN, (unsigned char *)TA112_RSA_N, sizeof TA112_RSA_N, (unsigned char *)TA112_RSA_E, sizeof TA112_RSA_E); + trust_anchors[113] = make_rsa_trust_anchor((unsigned char *)TA113_DN, sizeof TA113_DN, (unsigned char *)TA113_RSA_N, sizeof TA113_RSA_N, (unsigned char *)TA113_RSA_E, sizeof TA113_RSA_E); + trust_anchors[114] = make_rsa_trust_anchor((unsigned char *)TA114_DN, sizeof TA114_DN, (unsigned char *)TA114_RSA_N, sizeof TA114_RSA_N, (unsigned char *)TA114_RSA_E, sizeof TA114_RSA_E); + trust_anchors[115] = make_rsa_trust_anchor((unsigned char *)TA115_DN, sizeof TA115_DN, (unsigned char *)TA115_RSA_N, sizeof TA115_RSA_N, (unsigned char *)TA115_RSA_E, sizeof TA115_RSA_E); + trust_anchors[116] = make_rsa_trust_anchor((unsigned char *)TA116_DN, sizeof TA116_DN, (unsigned char *)TA116_RSA_N, sizeof TA116_RSA_N, (unsigned char *)TA116_RSA_E, sizeof TA116_RSA_E); + trust_anchors[117] = make_rsa_trust_anchor((unsigned char *)TA117_DN, sizeof TA117_DN, (unsigned char *)TA117_RSA_N, sizeof TA117_RSA_N, (unsigned char *)TA117_RSA_E, sizeof TA117_RSA_E); + trust_anchors[118] = make_rsa_trust_anchor((unsigned char *)TA118_DN, sizeof TA118_DN, (unsigned char *)TA118_RSA_N, sizeof TA118_RSA_N, (unsigned char *)TA118_RSA_E, sizeof TA118_RSA_E); + trust_anchors[119] = make_rsa_trust_anchor((unsigned char *)TA119_DN, sizeof TA119_DN, (unsigned char *)TA119_RSA_N, sizeof TA119_RSA_N, (unsigned char *)TA119_RSA_E, sizeof TA119_RSA_E); + trust_anchors[120] = make_ec_trust_anchor((unsigned char *)TA120_DN, sizeof TA120_DN, BR_EC_secp384r1, (unsigned char *)TA120_EC_Q, sizeof TA120_EC_Q); + trust_anchors[121] = make_ec_trust_anchor((unsigned char *)TA121_DN, sizeof TA121_DN, BR_EC_secp384r1, (unsigned char *)TA121_EC_Q, sizeof TA121_EC_Q); + trust_anchors[122] = make_ec_trust_anchor((unsigned char *)TA122_DN, sizeof TA122_DN, BR_EC_secp384r1, (unsigned char *)TA122_EC_Q, sizeof TA122_EC_Q); + trust_anchors[123] = make_rsa_trust_anchor((unsigned char *)TA123_DN, sizeof TA123_DN, (unsigned char *)TA123_RSA_N, sizeof TA123_RSA_N, (unsigned char *)TA123_RSA_E, sizeof TA123_RSA_E); + trust_anchors[124] = make_rsa_trust_anchor((unsigned char *)TA124_DN, sizeof TA124_DN, (unsigned char *)TA124_RSA_N, sizeof TA124_RSA_N, (unsigned char *)TA124_RSA_E, sizeof TA124_RSA_E); + trust_anchors[125] = make_ec_trust_anchor((unsigned char *)TA125_DN, sizeof TA125_DN, BR_EC_secp384r1, (unsigned char *)TA125_EC_Q, sizeof TA125_EC_Q); + trust_anchors[126] = make_rsa_trust_anchor((unsigned char *)TA126_DN, sizeof TA126_DN, (unsigned char *)TA126_RSA_N, sizeof TA126_RSA_N, (unsigned char *)TA126_RSA_E, sizeof TA126_RSA_E); + trust_anchors[127] = make_ec_trust_anchor((unsigned char *)TA127_DN, sizeof TA127_DN, BR_EC_secp384r1, (unsigned char *)TA127_EC_Q, sizeof TA127_EC_Q); + trust_anchors[128] = make_ec_trust_anchor((unsigned char *)TA128_DN, sizeof TA128_DN, BR_EC_secp384r1, (unsigned char *)TA128_EC_Q, sizeof TA128_EC_Q); + trust_anchors[129] = make_rsa_trust_anchor((unsigned char *)TA129_DN, sizeof TA129_DN, (unsigned char *)TA129_RSA_N, sizeof TA129_RSA_N, (unsigned char *)TA129_RSA_E, sizeof TA129_RSA_E); + trust_anchors[130] = make_rsa_trust_anchor((unsigned char *)TA130_DN, sizeof TA130_DN, (unsigned char *)TA130_RSA_N, sizeof TA130_RSA_N, (unsigned char *)TA130_RSA_E, sizeof TA130_RSA_E); + trust_anchors[131] = make_rsa_trust_anchor((unsigned char *)TA131_DN, sizeof TA131_DN, (unsigned char *)TA131_RSA_N, sizeof TA131_RSA_N, (unsigned char *)TA131_RSA_E, sizeof TA131_RSA_E); + trust_anchors[132] = make_ec_trust_anchor((unsigned char *)TA132_DN, sizeof TA132_DN, BR_EC_secp384r1, (unsigned char *)TA132_EC_Q, sizeof TA132_EC_Q); + trust_anchors[133] = make_rsa_trust_anchor((unsigned char *)TA133_DN, sizeof TA133_DN, (unsigned char *)TA133_RSA_N, sizeof TA133_RSA_N, (unsigned char *)TA133_RSA_E, sizeof TA133_RSA_E); + trust_anchors[134] = make_rsa_trust_anchor((unsigned char *)TA134_DN, sizeof TA134_DN, (unsigned char *)TA134_RSA_N, sizeof TA134_RSA_N, (unsigned char *)TA134_RSA_E, sizeof TA134_RSA_E); + trust_anchors[135] = make_ec_trust_anchor((unsigned char *)TA135_DN, sizeof TA135_DN, BR_EC_secp384r1, (unsigned char *)TA135_EC_Q, sizeof TA135_EC_Q); + trust_anchors[136] = make_ec_trust_anchor((unsigned char *)TA136_DN, sizeof TA136_DN, BR_EC_secp384r1, (unsigned char *)TA136_EC_Q, sizeof TA136_EC_Q); + trust_anchors[137] = make_rsa_trust_anchor((unsigned char *)TA137_DN, sizeof TA137_DN, (unsigned char *)TA137_RSA_N, sizeof TA137_RSA_N, (unsigned char *)TA137_RSA_E, sizeof TA137_RSA_E); + trust_anchors[138] = make_rsa_trust_anchor((unsigned char *)TA138_DN, sizeof TA138_DN, (unsigned char *)TA138_RSA_N, sizeof TA138_RSA_N, (unsigned char *)TA138_RSA_E, sizeof TA138_RSA_E); + trust_anchors[139] = make_ec_trust_anchor((unsigned char *)TA139_DN, sizeof TA139_DN, BR_EC_secp384r1, (unsigned char *)TA139_EC_Q, sizeof TA139_EC_Q); + trust_anchors[140] = make_ec_trust_anchor((unsigned char *)TA140_DN, sizeof TA140_DN, BR_EC_secp384r1, (unsigned char *)TA140_EC_Q, sizeof TA140_EC_Q); + trust_anchors[141] = make_rsa_trust_anchor((unsigned char *)TA141_DN, sizeof TA141_DN, (unsigned char *)TA141_RSA_N, sizeof TA141_RSA_N, (unsigned char *)TA141_RSA_E, sizeof TA141_RSA_E); + trust_anchors[142] = make_rsa_trust_anchor((unsigned char *)TA142_DN, sizeof TA142_DN, (unsigned char *)TA142_RSA_N, sizeof TA142_RSA_N, (unsigned char *)TA142_RSA_E, sizeof TA142_RSA_E); + trust_anchors[143] = make_ec_trust_anchor((unsigned char *)TA143_DN, sizeof TA143_DN, BR_EC_secp384r1, (unsigned char *)TA143_EC_Q, sizeof TA143_EC_Q); + trust_anchors[144] = make_rsa_trust_anchor((unsigned char *)TA144_DN, sizeof TA144_DN, (unsigned char *)TA144_RSA_N, sizeof TA144_RSA_N, (unsigned char *)TA144_RSA_E, sizeof TA144_RSA_E); + trust_anchors[145] = make_ec_trust_anchor((unsigned char *)TA145_DN, sizeof TA145_DN, BR_EC_secp384r1, (unsigned char *)TA145_EC_Q, sizeof TA145_EC_Q); + trust_anchors[146] = make_ec_trust_anchor((unsigned char *)TA146_DN, sizeof TA146_DN, BR_EC_secp384r1, (unsigned char *)TA146_EC_Q, sizeof TA146_EC_Q); + trust_anchors[147] = make_ec_trust_anchor((unsigned char *)TA147_DN, sizeof TA147_DN, BR_EC_secp256r1, (unsigned char *)TA147_EC_Q, sizeof TA147_EC_Q); + trust_anchors[148] = make_rsa_trust_anchor((unsigned char *)TA148_DN, sizeof TA148_DN, (unsigned char *)TA148_RSA_N, sizeof TA148_RSA_N, (unsigned char *)TA148_RSA_E, sizeof TA148_RSA_E); + trust_anchors[149] = make_rsa_trust_anchor((unsigned char *)TA149_DN, sizeof TA149_DN, (unsigned char *)TA149_RSA_N, sizeof TA149_RSA_N, (unsigned char *)TA149_RSA_E, sizeof TA149_RSA_E); + trust_anchors[150] = make_rsa_trust_anchor((unsigned char *)TA150_DN, sizeof TA150_DN, (unsigned char *)TA150_RSA_N, sizeof TA150_RSA_N, (unsigned char *)TA150_RSA_E, sizeof TA150_RSA_E); + trust_anchors[151] = make_ec_trust_anchor((unsigned char *)TA151_DN, sizeof TA151_DN, BR_EC_secp384r1, (unsigned char *)TA151_EC_Q, sizeof TA151_EC_Q); + trust_anchors[152] = make_rsa_trust_anchor((unsigned char *)TA152_DN, sizeof TA152_DN, (unsigned char *)TA152_RSA_N, sizeof TA152_RSA_N, (unsigned char *)TA152_RSA_E, sizeof TA152_RSA_E); + trust_anchors[153] = make_ec_trust_anchor((unsigned char *)TA153_DN, sizeof TA153_DN, BR_EC_secp384r1, (unsigned char *)TA153_EC_Q, sizeof TA153_EC_Q); + trust_anchors[154] = make_rsa_trust_anchor((unsigned char *)TA154_DN, sizeof TA154_DN, (unsigned char *)TA154_RSA_N, sizeof TA154_RSA_N, (unsigned char *)TA154_RSA_E, sizeof TA154_RSA_E); + trust_anchors[155] = make_rsa_trust_anchor((unsigned char *)TA155_DN, sizeof TA155_DN, (unsigned char *)TA155_RSA_N, sizeof TA155_RSA_N, (unsigned char *)TA155_RSA_E, sizeof TA155_RSA_E); + trust_anchors[156] = make_rsa_trust_anchor((unsigned char *)TA156_DN, sizeof TA156_DN, (unsigned char *)TA156_RSA_N, sizeof TA156_RSA_N, (unsigned char *)TA156_RSA_E, sizeof TA156_RSA_E); + trust_anchors[157] = make_rsa_trust_anchor((unsigned char *)TA157_DN, sizeof TA157_DN, (unsigned char *)TA157_RSA_N, sizeof TA157_RSA_N, (unsigned char *)TA157_RSA_E, sizeof TA157_RSA_E); + trust_anchors[158] = make_rsa_trust_anchor((unsigned char *)TA158_DN, sizeof TA158_DN, (unsigned char *)TA158_RSA_N, sizeof TA158_RSA_N, (unsigned char *)TA158_RSA_E, sizeof TA158_RSA_E); + trust_anchors[159] = make_rsa_trust_anchor((unsigned char *)TA159_DN, sizeof TA159_DN, (unsigned char *)TA159_RSA_N, sizeof TA159_RSA_N, (unsigned char *)TA159_RSA_E, sizeof TA159_RSA_E); + trust_anchors[160] = make_rsa_trust_anchor((unsigned char *)TA160_DN, sizeof TA160_DN, (unsigned char *)TA160_RSA_N, sizeof TA160_RSA_N, (unsigned char *)TA160_RSA_E, sizeof TA160_RSA_E); + trust_anchors[161] = make_ec_trust_anchor((unsigned char *)TA161_DN, sizeof TA161_DN, BR_EC_secp384r1, (unsigned char *)TA161_EC_Q, sizeof TA161_EC_Q); + trust_anchors[162] = make_ec_trust_anchor((unsigned char *)TA162_DN, sizeof TA162_DN, BR_EC_secp384r1, (unsigned char *)TA162_EC_Q, sizeof TA162_EC_Q); + trust_anchors[163] = make_rsa_trust_anchor((unsigned char *)TA163_DN, sizeof TA163_DN, (unsigned char *)TA163_RSA_N, sizeof TA163_RSA_N, (unsigned char *)TA163_RSA_E, sizeof TA163_RSA_E); + trust_anchors[164] = make_rsa_trust_anchor((unsigned char *)TA164_DN, sizeof TA164_DN, (unsigned char *)TA164_RSA_N, sizeof TA164_RSA_N, (unsigned char *)TA164_RSA_E, sizeof TA164_RSA_E); + trust_anchors[165] = make_rsa_trust_anchor((unsigned char *)TA165_DN, sizeof TA165_DN, (unsigned char *)TA165_RSA_N, sizeof TA165_RSA_N, (unsigned char *)TA165_RSA_E, sizeof TA165_RSA_E); + trust_anchors[166] = make_ec_trust_anchor((unsigned char *)TA166_DN, sizeof TA166_DN, BR_EC_secp384r1, (unsigned char *)TA166_EC_Q, sizeof TA166_EC_Q); + trust_anchors[167] = make_rsa_trust_anchor((unsigned char *)TA167_DN, sizeof TA167_DN, (unsigned char *)TA167_RSA_N, sizeof TA167_RSA_N, (unsigned char *)TA167_RSA_E, sizeof TA167_RSA_E); + trust_anchors[168] = make_rsa_trust_anchor((unsigned char *)TA168_DN, sizeof TA168_DN, (unsigned char *)TA168_RSA_N, sizeof TA168_RSA_N, (unsigned char *)TA168_RSA_E, sizeof TA168_RSA_E); + trust_anchors[169] = make_rsa_trust_anchor((unsigned char *)TA169_DN, sizeof TA169_DN, (unsigned char *)TA169_RSA_N, sizeof TA169_RSA_N, (unsigned char *)TA169_RSA_E, sizeof TA169_RSA_E); + trust_anchors[170] = make_rsa_trust_anchor((unsigned char *)TA170_DN, sizeof TA170_DN, (unsigned char *)TA170_RSA_N, sizeof TA170_RSA_N, (unsigned char *)TA170_RSA_E, sizeof TA170_RSA_E); + trust_anchors[171] = make_ec_trust_anchor((unsigned char *)TA171_DN, sizeof TA171_DN, BR_EC_secp384r1, (unsigned char *)TA171_EC_Q, sizeof TA171_EC_Q); + trust_anchors[172] = make_rsa_trust_anchor((unsigned char *)TA172_DN, sizeof TA172_DN, (unsigned char *)TA172_RSA_N, sizeof TA172_RSA_N, (unsigned char *)TA172_RSA_E, sizeof TA172_RSA_E); + trust_anchors[173] = make_ec_trust_anchor((unsigned char *)TA173_DN, sizeof TA173_DN, BR_EC_secp256r1, (unsigned char *)TA173_EC_Q, sizeof TA173_EC_Q); + trust_anchors[174] = make_rsa_trust_anchor((unsigned char *)TA174_DN, sizeof TA174_DN, (unsigned char *)TA174_RSA_N, sizeof TA174_RSA_N, (unsigned char *)TA174_RSA_E, sizeof TA174_RSA_E); + trust_anchors[175] = make_ec_trust_anchor((unsigned char *)TA175_DN, sizeof TA175_DN, BR_EC_secp384r1, (unsigned char *)TA175_EC_Q, sizeof TA175_EC_Q); + trust_anchors[176] = make_rsa_trust_anchor((unsigned char *)TA176_DN, sizeof TA176_DN, (unsigned char *)TA176_RSA_N, sizeof TA176_RSA_N, (unsigned char *)TA176_RSA_E, sizeof TA176_RSA_E); + trust_anchors[177] = make_rsa_trust_anchor((unsigned char *)TA177_DN, sizeof TA177_DN, (unsigned char *)TA177_RSA_N, sizeof TA177_RSA_N, (unsigned char *)TA177_RSA_E, sizeof TA177_RSA_E); + trust_anchors[178] = make_ec_trust_anchor((unsigned char *)TA178_DN, sizeof TA178_DN, BR_EC_secp384r1, (unsigned char *)TA178_EC_Q, sizeof TA178_EC_Q); + trust_anchors[179] = make_rsa_trust_anchor((unsigned char *)TA179_DN, sizeof TA179_DN, (unsigned char *)TA179_RSA_N, sizeof TA179_RSA_N, (unsigned char *)TA179_RSA_E, sizeof TA179_RSA_E); + trust_anchors[180] = make_rsa_trust_anchor((unsigned char *)TA180_DN, sizeof TA180_DN, (unsigned char *)TA180_RSA_N, sizeof TA180_RSA_N, (unsigned char *)TA180_RSA_E, sizeof TA180_RSA_E); + trust_anchors[181] = make_rsa_trust_anchor((unsigned char *)TA181_DN, sizeof TA181_DN, (unsigned char *)TA181_RSA_N, sizeof TA181_RSA_N, (unsigned char *)TA181_RSA_E, sizeof TA181_RSA_E); + trust_anchors[182] = make_ec_trust_anchor((unsigned char *)TA182_DN, sizeof TA182_DN, BR_EC_secp384r1, (unsigned char *)TA182_EC_Q, sizeof TA182_EC_Q); + trust_anchors[183] = make_ec_trust_anchor((unsigned char *)TA183_DN, sizeof TA183_DN, BR_EC_secp384r1, (unsigned char *)TA183_EC_Q, sizeof TA183_EC_Q); + trust_anchors[184] = make_rsa_trust_anchor((unsigned char *)TA184_DN, sizeof TA184_DN, (unsigned char *)TA184_RSA_N, sizeof TA184_RSA_N, (unsigned char *)TA184_RSA_E, sizeof TA184_RSA_E); + trust_anchors[185] = make_rsa_trust_anchor((unsigned char *)TA185_DN, sizeof TA185_DN, (unsigned char *)TA185_RSA_N, sizeof TA185_RSA_N, (unsigned char *)TA185_RSA_E, sizeof TA185_RSA_E); + trust_anchors[186] = make_rsa_trust_anchor((unsigned char *)TA186_DN, sizeof TA186_DN, (unsigned char *)TA186_RSA_N, sizeof TA186_RSA_N, (unsigned char *)TA186_RSA_E, sizeof TA186_RSA_E); + trust_anchors[187] = make_rsa_trust_anchor((unsigned char *)TA187_DN, sizeof TA187_DN, (unsigned char *)TA187_RSA_N, sizeof TA187_RSA_N, (unsigned char *)TA187_RSA_E, sizeof TA187_RSA_E); + trust_anchors[188] = make_rsa_trust_anchor((unsigned char *)TA188_DN, sizeof TA188_DN, (unsigned char *)TA188_RSA_N, sizeof TA188_RSA_N, (unsigned char *)TA188_RSA_E, sizeof TA188_RSA_E); + trust_anchors[189] = make_rsa_trust_anchor((unsigned char *)TA189_DN, sizeof TA189_DN, (unsigned char *)TA189_RSA_N, sizeof TA189_RSA_N, (unsigned char *)TA189_RSA_E, sizeof TA189_RSA_E); + trust_anchors[190] = make_rsa_trust_anchor((unsigned char *)TA190_DN, sizeof TA190_DN, (unsigned char *)TA190_RSA_N, sizeof TA190_RSA_N, (unsigned char *)TA190_RSA_E, sizeof TA190_RSA_E); + trust_anchors[191] = make_ec_trust_anchor((unsigned char *)TA191_DN, sizeof TA191_DN, BR_EC_secp384r1, (unsigned char *)TA191_EC_Q, sizeof TA191_EC_Q); + trust_anchors[192] = make_rsa_trust_anchor((unsigned char *)TA192_DN, sizeof TA192_DN, (unsigned char *)TA192_RSA_N, sizeof TA192_RSA_N, (unsigned char *)TA192_RSA_E, sizeof TA192_RSA_E); + trust_anchors[193] = make_rsa_trust_anchor((unsigned char *)TA193_DN, sizeof TA193_DN, (unsigned char *)TA193_RSA_N, sizeof TA193_RSA_N, (unsigned char *)TA193_RSA_E, sizeof TA193_RSA_E); + trust_anchors[194] = make_rsa_trust_anchor((unsigned char *)TA194_DN, sizeof TA194_DN, (unsigned char *)TA194_RSA_N, sizeof TA194_RSA_N, (unsigned char *)TA194_RSA_E, sizeof TA194_RSA_E); + trust_anchors[195] = make_rsa_trust_anchor((unsigned char *)TA195_DN, sizeof TA195_DN, (unsigned char *)TA195_RSA_N, sizeof TA195_RSA_N, (unsigned char *)TA195_RSA_E, sizeof TA195_RSA_E); + trust_anchors[196] = make_ec_trust_anchor((unsigned char *)TA196_DN, sizeof TA196_DN, BR_EC_secp384r1, (unsigned char *)TA196_EC_Q, sizeof TA196_EC_Q); + trust_anchors[197] = make_rsa_trust_anchor((unsigned char *)TA197_DN, sizeof TA197_DN, (unsigned char *)TA197_RSA_N, sizeof TA197_RSA_N, (unsigned char *)TA197_RSA_E, sizeof TA197_RSA_E); + trust_anchors[198] = make_rsa_trust_anchor((unsigned char *)TA198_DN, sizeof TA198_DN, (unsigned char *)TA198_RSA_N, sizeof TA198_RSA_N, (unsigned char *)TA198_RSA_E, sizeof TA198_RSA_E); + trust_anchors[199] = make_rsa_trust_anchor((unsigned char *)TA199_DN, sizeof TA199_DN, (unsigned char *)TA199_RSA_N, sizeof TA199_RSA_N, (unsigned char *)TA199_RSA_E, sizeof TA199_RSA_E); + trust_anchors[200] = make_ec_trust_anchor((unsigned char *)TA200_DN, sizeof TA200_DN, BR_EC_secp256r1, (unsigned char *)TA200_EC_Q, sizeof TA200_EC_Q); + trust_anchors[201] = make_ec_trust_anchor((unsigned char *)TA201_DN, sizeof TA201_DN, BR_EC_secp384r1, (unsigned char *)TA201_EC_Q, sizeof TA201_EC_Q); + trust_anchors[202] = make_rsa_trust_anchor((unsigned char *)TA202_DN, sizeof TA202_DN, (unsigned char *)TA202_RSA_N, sizeof TA202_RSA_N, (unsigned char *)TA202_RSA_E, sizeof TA202_RSA_E); + trust_anchors[203] = make_rsa_trust_anchor((unsigned char *)TA203_DN, sizeof TA203_DN, (unsigned char *)TA203_RSA_N, sizeof TA203_RSA_N, (unsigned char *)TA203_RSA_E, sizeof TA203_RSA_E); + trust_anchors[204] = make_ec_trust_anchor((unsigned char *)TA204_DN, sizeof TA204_DN, BR_EC_secp384r1, (unsigned char *)TA204_EC_Q, sizeof TA204_EC_Q); + trust_anchors[205] = make_rsa_trust_anchor((unsigned char *)TA205_DN, sizeof TA205_DN, (unsigned char *)TA205_RSA_N, sizeof TA205_RSA_N, (unsigned char *)TA205_RSA_E, sizeof TA205_RSA_E); + trust_anchors[206] = make_rsa_trust_anchor((unsigned char *)TA206_DN, sizeof TA206_DN, (unsigned char *)TA206_RSA_N, sizeof TA206_RSA_N, (unsigned char *)TA206_RSA_E, sizeof TA206_RSA_E); + trust_anchors[207] = make_ec_trust_anchor((unsigned char *)TA207_DN, sizeof TA207_DN, BR_EC_secp256r1, (unsigned char *)TA207_EC_Q, sizeof TA207_EC_Q); + trust_anchors[208] = make_rsa_trust_anchor((unsigned char *)TA208_DN, sizeof TA208_DN, (unsigned char *)TA208_RSA_N, sizeof TA208_RSA_N, (unsigned char *)TA208_RSA_E, sizeof TA208_RSA_E); + trust_anchors[209] = make_rsa_trust_anchor((unsigned char *)TA209_DN, sizeof TA209_DN, (unsigned char *)TA209_RSA_N, sizeof TA209_RSA_N, (unsigned char *)TA209_RSA_E, sizeof TA209_RSA_E); + trust_anchors[210] = make_rsa_trust_anchor((unsigned char *)TA210_DN, sizeof TA210_DN, (unsigned char *)TA210_RSA_N, sizeof TA210_RSA_N, (unsigned char *)TA210_RSA_E, sizeof TA210_RSA_E); + trust_anchors[211] = make_ec_trust_anchor((unsigned char *)TA211_DN, sizeof TA211_DN, BR_EC_secp384r1, (unsigned char *)TA211_EC_Q, sizeof TA211_EC_Q); + trust_anchors[212] = make_ec_trust_anchor((unsigned char *)TA212_DN, sizeof TA212_DN, BR_EC_secp384r1, (unsigned char *)TA212_EC_Q, sizeof TA212_EC_Q); + trust_anchors[213] = make_rsa_trust_anchor((unsigned char *)TA213_DN, sizeof TA213_DN, (unsigned char *)TA213_RSA_N, sizeof TA213_RSA_N, (unsigned char *)TA213_RSA_E, sizeof TA213_RSA_E); + trust_anchors[214] = make_rsa_trust_anchor((unsigned char *)TA214_DN, sizeof TA214_DN, (unsigned char *)TA214_RSA_N, sizeof TA214_RSA_N, (unsigned char *)TA214_RSA_E, sizeof TA214_RSA_E); + trust_anchors[215] = make_rsa_trust_anchor((unsigned char *)TA215_DN, sizeof TA215_DN, (unsigned char *)TA215_RSA_N, sizeof TA215_RSA_N, (unsigned char *)TA215_RSA_E, sizeof TA215_RSA_E); + trust_anchors[216] = make_ec_trust_anchor((unsigned char *)TA216_DN, sizeof TA216_DN, BR_EC_secp256r1, (unsigned char *)TA216_EC_Q, sizeof TA216_EC_Q); + trust_anchors[217] = make_rsa_trust_anchor((unsigned char *)TA217_DN, sizeof TA217_DN, (unsigned char *)TA217_RSA_N, sizeof TA217_RSA_N, (unsigned char *)TA217_RSA_E, sizeof TA217_RSA_E); + trust_anchors[218] = make_rsa_trust_anchor((unsigned char *)TA218_DN, sizeof TA218_DN, (unsigned char *)TA218_RSA_N, sizeof TA218_RSA_N, (unsigned char *)TA218_RSA_E, sizeof TA218_RSA_E); + trust_anchors[219] = make_ec_trust_anchor((unsigned char *)TA219_DN, sizeof TA219_DN, BR_EC_secp384r1, (unsigned char *)TA219_EC_Q, sizeof TA219_EC_Q); + trust_anchors[220] = make_rsa_trust_anchor((unsigned char *)TA220_DN, sizeof TA220_DN, (unsigned char *)TA220_RSA_N, sizeof TA220_RSA_N, (unsigned char *)TA220_RSA_E, sizeof TA220_RSA_E); + trust_anchors[221] = make_rsa_trust_anchor((unsigned char *)TA221_DN, sizeof TA221_DN, (unsigned char *)TA221_RSA_N, sizeof TA221_RSA_N, (unsigned char *)TA221_RSA_E, sizeof TA221_RSA_E); + trust_anchors[222] = make_rsa_trust_anchor((unsigned char *)TA222_DN, sizeof TA222_DN, (unsigned char *)TA222_RSA_N, sizeof TA222_RSA_N, (unsigned char *)TA222_RSA_E, sizeof TA222_RSA_E); + trust_anchors[223] = make_rsa_trust_anchor((unsigned char *)TA223_DN, sizeof TA223_DN, (unsigned char *)TA223_RSA_N, sizeof TA223_RSA_N, (unsigned char *)TA223_RSA_E, sizeof TA223_RSA_E); + trust_anchors[224] = make_ec_trust_anchor((unsigned char *)TA224_DN, sizeof TA224_DN, BR_EC_secp384r1, (unsigned char *)TA224_EC_Q, sizeof TA224_EC_Q); + trust_anchors[225] = make_rsa_trust_anchor((unsigned char *)TA225_DN, sizeof TA225_DN, (unsigned char *)TA225_RSA_N, sizeof TA225_RSA_N, (unsigned char *)TA225_RSA_E, sizeof TA225_RSA_E); + trust_anchors[226] = make_rsa_trust_anchor((unsigned char *)TA226_DN, sizeof TA226_DN, (unsigned char *)TA226_RSA_N, sizeof TA226_RSA_N, (unsigned char *)TA226_RSA_E, sizeof TA226_RSA_E); + trust_anchors[227] = make_rsa_trust_anchor((unsigned char *)TA227_DN, sizeof TA227_DN, (unsigned char *)TA227_RSA_N, sizeof TA227_RSA_N, (unsigned char *)TA227_RSA_E, sizeof TA227_RSA_E); + trust_anchors[228] = make_rsa_trust_anchor((unsigned char *)TA228_DN, sizeof TA228_DN, (unsigned char *)TA228_RSA_N, sizeof TA228_RSA_N, (unsigned char *)TA228_RSA_E, sizeof TA228_RSA_E); + trust_anchors[229] = make_rsa_trust_anchor((unsigned char *)TA229_DN, sizeof TA229_DN, (unsigned char *)TA229_RSA_N, sizeof TA229_RSA_N, (unsigned char *)TA229_RSA_E, sizeof TA229_RSA_E); + trust_anchors[230] = make_rsa_trust_anchor((unsigned char *)TA230_DN, sizeof TA230_DN, (unsigned char *)TA230_RSA_N, sizeof TA230_RSA_N, (unsigned char *)TA230_RSA_E, sizeof TA230_RSA_E); + trust_anchors[231] = make_rsa_trust_anchor((unsigned char *)TA231_DN, sizeof TA231_DN, (unsigned char *)TA231_RSA_N, sizeof TA231_RSA_N, (unsigned char *)TA231_RSA_E, sizeof TA231_RSA_E); + trust_anchors[232] = make_ec_trust_anchor((unsigned char *)TA232_DN, sizeof TA232_DN, BR_EC_secp384r1, (unsigned char *)TA232_EC_Q, sizeof TA232_EC_Q); + trust_anchors[233] = make_rsa_trust_anchor((unsigned char *)TA233_DN, sizeof TA233_DN, (unsigned char *)TA233_RSA_N, sizeof TA233_RSA_N, (unsigned char *)TA233_RSA_E, sizeof TA233_RSA_E); + trust_anchors[234] = make_rsa_trust_anchor((unsigned char *)TA234_DN, sizeof TA234_DN, (unsigned char *)TA234_RSA_N, sizeof TA234_RSA_N, (unsigned char *)TA234_RSA_E, sizeof TA234_RSA_E); + trust_anchors[235] = make_rsa_trust_anchor((unsigned char *)TA235_DN, sizeof TA235_DN, (unsigned char *)TA235_RSA_N, sizeof TA235_RSA_N, (unsigned char *)TA235_RSA_E, sizeof TA235_RSA_E); + trust_anchors[236] = make_rsa_trust_anchor((unsigned char *)TA236_DN, sizeof TA236_DN, (unsigned char *)TA236_RSA_N, sizeof TA236_RSA_N, (unsigned char *)TA236_RSA_E, sizeof TA236_RSA_E); + trust_anchors[237] = make_rsa_trust_anchor((unsigned char *)TA237_DN, sizeof TA237_DN, (unsigned char *)TA237_RSA_N, sizeof TA237_RSA_N, (unsigned char *)TA237_RSA_E, sizeof TA237_RSA_E); + trust_anchors[238] = make_ec_trust_anchor((unsigned char *)TA238_DN, sizeof TA238_DN, BR_EC_secp384r1, (unsigned char *)TA238_EC_Q, sizeof TA238_EC_Q); + trust_anchors[239] = make_rsa_trust_anchor((unsigned char *)TA239_DN, sizeof TA239_DN, (unsigned char *)TA239_RSA_N, sizeof TA239_RSA_N, (unsigned char *)TA239_RSA_E, sizeof TA239_RSA_E); + trust_anchors[240] = make_ec_trust_anchor((unsigned char *)TA240_DN, sizeof TA240_DN, BR_EC_secp384r1, (unsigned char *)TA240_EC_Q, sizeof TA240_EC_Q); + trust_anchors[241] = make_rsa_trust_anchor((unsigned char *)TA241_DN, sizeof TA241_DN, (unsigned char *)TA241_RSA_N, sizeof TA241_RSA_N, (unsigned char *)TA241_RSA_E, sizeof TA241_RSA_E); + trust_anchors[242] = make_rsa_trust_anchor((unsigned char *)TA242_DN, sizeof TA242_DN, (unsigned char *)TA242_RSA_N, sizeof TA242_RSA_N, (unsigned char *)TA242_RSA_E, sizeof TA242_RSA_E); + trust_anchors[243] = make_rsa_trust_anchor((unsigned char *)TA243_DN, sizeof TA243_DN, (unsigned char *)TA243_RSA_N, sizeof TA243_RSA_N, (unsigned char *)TA243_RSA_E, sizeof TA243_RSA_E); + trust_anchors[244] = make_rsa_trust_anchor((unsigned char *)TA244_DN, sizeof TA244_DN, (unsigned char *)TA244_RSA_N, sizeof TA244_RSA_N, (unsigned char *)TA244_RSA_E, sizeof TA244_RSA_E); + trust_anchors[245] = make_ec_trust_anchor((unsigned char *)TA245_DN, sizeof TA245_DN, BR_EC_secp384r1, (unsigned char *)TA245_EC_Q, sizeof TA245_EC_Q); + trust_anchors[246] = make_rsa_trust_anchor((unsigned char *)TA246_DN, sizeof TA246_DN, (unsigned char *)TA246_RSA_N, sizeof TA246_RSA_N, (unsigned char *)TA246_RSA_E, sizeof TA246_RSA_E); + trust_anchors[247] = make_rsa_trust_anchor((unsigned char *)TA247_DN, sizeof TA247_DN, (unsigned char *)TA247_RSA_N, sizeof TA247_RSA_N, (unsigned char *)TA247_RSA_E, sizeof TA247_RSA_E); + trust_anchors[248] = make_rsa_trust_anchor((unsigned char *)TA248_DN, sizeof TA248_DN, (unsigned char *)TA248_RSA_N, sizeof TA248_RSA_N, (unsigned char *)TA248_RSA_E, sizeof TA248_RSA_E); + trust_anchors[249] = make_rsa_trust_anchor((unsigned char *)TA249_DN, sizeof TA249_DN, (unsigned char *)TA249_RSA_N, sizeof TA249_RSA_N, (unsigned char *)TA249_RSA_E, sizeof TA249_RSA_E); + trust_anchors[250] = make_rsa_trust_anchor((unsigned char *)TA250_DN, sizeof TA250_DN, (unsigned char *)TA250_RSA_N, sizeof TA250_RSA_N, (unsigned char *)TA250_RSA_E, sizeof TA250_RSA_E); + trust_anchors[251] = make_ec_trust_anchor((unsigned char *)TA251_DN, sizeof TA251_DN, BR_EC_secp384r1, (unsigned char *)TA251_EC_Q, sizeof TA251_EC_Q); + trust_anchors[252] = make_rsa_trust_anchor((unsigned char *)TA252_DN, sizeof TA252_DN, (unsigned char *)TA252_RSA_N, sizeof TA252_RSA_N, (unsigned char *)TA252_RSA_E, sizeof TA252_RSA_E); + trust_anchors[253] = make_rsa_trust_anchor((unsigned char *)TA253_DN, sizeof TA253_DN, (unsigned char *)TA253_RSA_N, sizeof TA253_RSA_N, (unsigned char *)TA253_RSA_E, sizeof TA253_RSA_E); + trust_anchors[254] = make_ec_trust_anchor((unsigned char *)TA254_DN, sizeof TA254_DN, BR_EC_secp256r1, (unsigned char *)TA254_EC_Q, sizeof TA254_EC_Q); + trust_anchors[255] = make_ec_trust_anchor((unsigned char *)TA255_DN, sizeof TA255_DN, BR_EC_secp384r1, (unsigned char *)TA255_EC_Q, sizeof TA255_EC_Q); + trust_anchors[256] = make_rsa_trust_anchor((unsigned char *)TA256_DN, sizeof TA256_DN, (unsigned char *)TA256_RSA_N, sizeof TA256_RSA_N, (unsigned char *)TA256_RSA_E, sizeof TA256_RSA_E); + trust_anchors[257] = make_ec_trust_anchor((unsigned char *)TA257_DN, sizeof TA257_DN, BR_EC_secp384r1, (unsigned char *)TA257_EC_Q, sizeof TA257_EC_Q); + trust_anchors[258] = make_rsa_trust_anchor((unsigned char *)TA258_DN, sizeof TA258_DN, (unsigned char *)TA258_RSA_N, sizeof TA258_RSA_N, (unsigned char *)TA258_RSA_E, sizeof TA258_RSA_E); + trust_anchors[259] = make_rsa_trust_anchor((unsigned char *)TA259_DN, sizeof TA259_DN, (unsigned char *)TA259_RSA_N, sizeof TA259_RSA_N, (unsigned char *)TA259_RSA_E, sizeof TA259_RSA_E); + trust_anchors[260] = make_rsa_trust_anchor((unsigned char *)TA260_DN, sizeof TA260_DN, (unsigned char *)TA260_RSA_N, sizeof TA260_RSA_N, (unsigned char *)TA260_RSA_E, sizeof TA260_RSA_E); + trust_anchors[261] = make_ec_trust_anchor((unsigned char *)TA261_DN, sizeof TA261_DN, BR_EC_secp384r1, (unsigned char *)TA261_EC_Q, sizeof TA261_EC_Q); + trust_anchors[262] = make_rsa_trust_anchor((unsigned char *)TA262_DN, sizeof TA262_DN, (unsigned char *)TA262_RSA_N, sizeof TA262_RSA_N, (unsigned char *)TA262_RSA_E, sizeof TA262_RSA_E); + trust_anchors[263] = make_rsa_trust_anchor((unsigned char *)TA263_DN, sizeof TA263_DN, (unsigned char *)TA263_RSA_N, sizeof TA263_RSA_N, (unsigned char *)TA263_RSA_E, sizeof TA263_RSA_E); + trust_anchors[264] = make_rsa_trust_anchor((unsigned char *)TA264_DN, sizeof TA264_DN, (unsigned char *)TA264_RSA_N, sizeof TA264_RSA_N, (unsigned char *)TA264_RSA_E, sizeof TA264_RSA_E); + trust_anchors[265] = make_rsa_trust_anchor((unsigned char *)TA265_DN, sizeof TA265_DN, (unsigned char *)TA265_RSA_N, sizeof TA265_RSA_N, (unsigned char *)TA265_RSA_E, sizeof TA265_RSA_E); + trust_anchors[266] = make_rsa_trust_anchor((unsigned char *)TA266_DN, sizeof TA266_DN, (unsigned char *)TA266_RSA_N, sizeof TA266_RSA_N, (unsigned char *)TA266_RSA_E, sizeof TA266_RSA_E); + trust_anchors[267] = make_rsa_trust_anchor((unsigned char *)TA267_DN, sizeof TA267_DN, (unsigned char *)TA267_RSA_N, sizeof TA267_RSA_N, (unsigned char *)TA267_RSA_E, sizeof TA267_RSA_E); + trust_anchors[268] = make_ec_trust_anchor((unsigned char *)TA268_DN, sizeof TA268_DN, BR_EC_secp384r1, (unsigned char *)TA268_EC_Q, sizeof TA268_EC_Q); + trust_anchors[269] = make_rsa_trust_anchor((unsigned char *)TA269_DN, sizeof TA269_DN, (unsigned char *)TA269_RSA_N, sizeof TA269_RSA_N, (unsigned char *)TA269_RSA_E, sizeof TA269_RSA_E); + trust_anchors[270] = make_ec_trust_anchor((unsigned char *)TA270_DN, sizeof TA270_DN, BR_EC_secp384r1, (unsigned char *)TA270_EC_Q, sizeof TA270_EC_Q); + trust_anchors[271] = make_rsa_trust_anchor((unsigned char *)TA271_DN, sizeof TA271_DN, (unsigned char *)TA271_RSA_N, sizeof TA271_RSA_N, (unsigned char *)TA271_RSA_E, sizeof TA271_RSA_E); + trust_anchors[272] = make_rsa_trust_anchor((unsigned char *)TA272_DN, sizeof TA272_DN, (unsigned char *)TA272_RSA_N, sizeof TA272_RSA_N, (unsigned char *)TA272_RSA_E, sizeof TA272_RSA_E); + trust_anchors[273] = make_rsa_trust_anchor((unsigned char *)TA273_DN, sizeof TA273_DN, (unsigned char *)TA273_RSA_N, sizeof TA273_RSA_N, (unsigned char *)TA273_RSA_E, sizeof TA273_RSA_E); + trust_anchors[274] = make_ec_trust_anchor((unsigned char *)TA274_DN, sizeof TA274_DN, BR_EC_secp384r1, (unsigned char *)TA274_EC_Q, sizeof TA274_EC_Q); + trust_anchors[275] = make_rsa_trust_anchor((unsigned char *)TA275_DN, sizeof TA275_DN, (unsigned char *)TA275_RSA_N, sizeof TA275_RSA_N, (unsigned char *)TA275_RSA_E, sizeof TA275_RSA_E); + trust_anchors[276] = make_rsa_trust_anchor((unsigned char *)TA276_DN, sizeof TA276_DN, (unsigned char *)TA276_RSA_N, sizeof TA276_RSA_N, (unsigned char *)TA276_RSA_E, sizeof TA276_RSA_E); + trust_anchors[277] = make_rsa_trust_anchor((unsigned char *)TA277_DN, sizeof TA277_DN, (unsigned char *)TA277_RSA_N, sizeof TA277_RSA_N, (unsigned char *)TA277_RSA_E, sizeof TA277_RSA_E); + trust_anchors[278] = make_ec_trust_anchor((unsigned char *)TA278_DN, sizeof TA278_DN, BR_EC_secp384r1, (unsigned char *)TA278_EC_Q, sizeof TA278_EC_Q); + trust_anchors[279] = make_ec_trust_anchor((unsigned char *)TA279_DN, sizeof TA279_DN, BR_EC_secp384r1, (unsigned char *)TA279_EC_Q, sizeof TA279_EC_Q); + trust_anchors[280] = make_rsa_trust_anchor((unsigned char *)TA280_DN, sizeof TA280_DN, (unsigned char *)TA280_RSA_N, sizeof TA280_RSA_N, (unsigned char *)TA280_RSA_E, sizeof TA280_RSA_E); + trust_anchors[281] = make_rsa_trust_anchor((unsigned char *)TA281_DN, sizeof TA281_DN, (unsigned char *)TA281_RSA_N, sizeof TA281_RSA_N, (unsigned char *)TA281_RSA_E, sizeof TA281_RSA_E); + trust_anchors[282] = make_rsa_trust_anchor((unsigned char *)TA282_DN, sizeof TA282_DN, (unsigned char *)TA282_RSA_N, sizeof TA282_RSA_N, (unsigned char *)TA282_RSA_E, sizeof TA282_RSA_E); + trust_anchors[283] = make_ec_trust_anchor((unsigned char *)TA283_DN, sizeof TA283_DN, BR_EC_secp384r1, (unsigned char *)TA283_EC_Q, sizeof TA283_EC_Q); + trust_anchors[284] = make_rsa_trust_anchor((unsigned char *)TA284_DN, sizeof TA284_DN, (unsigned char *)TA284_RSA_N, sizeof TA284_RSA_N, (unsigned char *)TA284_RSA_E, sizeof TA284_RSA_E); + trust_anchors[285] = make_ec_trust_anchor((unsigned char *)TA285_DN, sizeof TA285_DN, BR_EC_secp384r1, (unsigned char *)TA285_EC_Q, sizeof TA285_EC_Q); + trust_anchors[286] = make_rsa_trust_anchor((unsigned char *)TA286_DN, sizeof TA286_DN, (unsigned char *)TA286_RSA_N, sizeof TA286_RSA_N, (unsigned char *)TA286_RSA_E, sizeof TA286_RSA_E); + trust_anchors[287] = make_rsa_trust_anchor((unsigned char *)TA287_DN, sizeof TA287_DN, (unsigned char *)TA287_RSA_N, sizeof TA287_RSA_N, (unsigned char *)TA287_RSA_E, sizeof TA287_RSA_E); + trust_anchors[288] = make_rsa_trust_anchor((unsigned char *)TA288_DN, sizeof TA288_DN, (unsigned char *)TA288_RSA_N, sizeof TA288_RSA_N, (unsigned char *)TA288_RSA_E, sizeof TA288_RSA_E); + trust_anchors[289] = make_rsa_trust_anchor((unsigned char *)TA289_DN, sizeof TA289_DN, (unsigned char *)TA289_RSA_N, sizeof TA289_RSA_N, (unsigned char *)TA289_RSA_E, sizeof TA289_RSA_E); + trust_anchors[290] = make_rsa_trust_anchor((unsigned char *)TA290_DN, sizeof TA290_DN, (unsigned char *)TA290_RSA_N, sizeof TA290_RSA_N, (unsigned char *)TA290_RSA_E, sizeof TA290_RSA_E); + trust_anchors[291] = make_ec_trust_anchor((unsigned char *)TA291_DN, sizeof TA291_DN, BR_EC_secp384r1, (unsigned char *)TA291_EC_Q, sizeof TA291_EC_Q); + trust_anchors[292] = make_rsa_trust_anchor((unsigned char *)TA292_DN, sizeof TA292_DN, (unsigned char *)TA292_RSA_N, sizeof TA292_RSA_N, (unsigned char *)TA292_RSA_E, sizeof TA292_RSA_E); + trust_anchors[293] = make_rsa_trust_anchor((unsigned char *)TA293_DN, sizeof TA293_DN, (unsigned char *)TA293_RSA_N, sizeof TA293_RSA_N, (unsigned char *)TA293_RSA_E, sizeof TA293_RSA_E); + trust_anchors[294] = make_ec_trust_anchor((unsigned char *)TA294_DN, sizeof TA294_DN, BR_EC_secp384r1, (unsigned char *)TA294_EC_Q, sizeof TA294_EC_Q); + trust_anchors[295] = make_rsa_trust_anchor((unsigned char *)TA295_DN, sizeof TA295_DN, (unsigned char *)TA295_RSA_N, sizeof TA295_RSA_N, (unsigned char *)TA295_RSA_E, sizeof TA295_RSA_E); + trust_anchors[296] = make_ec_trust_anchor((unsigned char *)TA296_DN, sizeof TA296_DN, BR_EC_secp384r1, (unsigned char *)TA296_EC_Q, sizeof TA296_EC_Q); + trust_anchors[297] = make_rsa_trust_anchor((unsigned char *)TA297_DN, sizeof TA297_DN, (unsigned char *)TA297_RSA_N, sizeof TA297_RSA_N, (unsigned char *)TA297_RSA_E, sizeof TA297_RSA_E); + trust_anchors[298] = make_rsa_trust_anchor((unsigned char *)TA298_DN, sizeof TA298_DN, (unsigned char *)TA298_RSA_N, sizeof TA298_RSA_N, (unsigned char *)TA298_RSA_E, sizeof TA298_RSA_E); + trust_anchors[299] = make_rsa_trust_anchor((unsigned char *)TA299_DN, sizeof TA299_DN, (unsigned char *)TA299_RSA_N, sizeof TA299_RSA_N, (unsigned char *)TA299_RSA_E, sizeof TA299_RSA_E); + trust_anchors[300] = make_rsa_trust_anchor((unsigned char *)TA300_DN, sizeof TA300_DN, (unsigned char *)TA300_RSA_N, sizeof TA300_RSA_N, (unsigned char *)TA300_RSA_E, sizeof TA300_RSA_E); + trust_anchors[301] = make_ec_trust_anchor((unsigned char *)TA301_DN, sizeof TA301_DN, BR_EC_secp384r1, (unsigned char *)TA301_EC_Q, sizeof TA301_EC_Q); + trust_anchors[302] = make_rsa_trust_anchor((unsigned char *)TA302_DN, sizeof TA302_DN, (unsigned char *)TA302_RSA_N, sizeof TA302_RSA_N, (unsigned char *)TA302_RSA_E, sizeof TA302_RSA_E); + trust_anchors[303] = make_ec_trust_anchor((unsigned char *)TA303_DN, sizeof TA303_DN, BR_EC_secp384r1, (unsigned char *)TA303_EC_Q, sizeof TA303_EC_Q); + trust_anchors[304] = make_rsa_trust_anchor((unsigned char *)TA304_DN, sizeof TA304_DN, (unsigned char *)TA304_RSA_N, sizeof TA304_RSA_N, (unsigned char *)TA304_RSA_E, sizeof TA304_RSA_E); + trust_anchors[305] = make_rsa_trust_anchor((unsigned char *)TA305_DN, sizeof TA305_DN, (unsigned char *)TA305_RSA_N, sizeof TA305_RSA_N, (unsigned char *)TA305_RSA_E, sizeof TA305_RSA_E); + trust_anchors[306] = make_rsa_trust_anchor((unsigned char *)TA306_DN, sizeof TA306_DN, (unsigned char *)TA306_RSA_N, sizeof TA306_RSA_N, (unsigned char *)TA306_RSA_E, sizeof TA306_RSA_E); + trust_anchors[307] = make_rsa_trust_anchor((unsigned char *)TA307_DN, sizeof TA307_DN, (unsigned char *)TA307_RSA_N, sizeof TA307_RSA_N, (unsigned char *)TA307_RSA_E, sizeof TA307_RSA_E); + trust_anchors[308] = make_ec_trust_anchor((unsigned char *)TA308_DN, sizeof TA308_DN, BR_EC_secp384r1, (unsigned char *)TA308_EC_Q, sizeof TA308_EC_Q); + trust_anchors[309] = make_ec_trust_anchor((unsigned char *)TA309_DN, sizeof TA309_DN, BR_EC_secp384r1, (unsigned char *)TA309_EC_Q, sizeof TA309_EC_Q); + trust_anchors[310] = make_ec_trust_anchor((unsigned char *)TA310_DN, sizeof TA310_DN, BR_EC_secp256r1, (unsigned char *)TA310_EC_Q, sizeof TA310_EC_Q); + trust_anchors[311] = make_ec_trust_anchor((unsigned char *)TA311_DN, sizeof TA311_DN, BR_EC_secp384r1, (unsigned char *)TA311_EC_Q, sizeof TA311_EC_Q); + trust_anchors[312] = make_rsa_trust_anchor((unsigned char *)TA312_DN, sizeof TA312_DN, (unsigned char *)TA312_RSA_N, sizeof TA312_RSA_N, (unsigned char *)TA312_RSA_E, sizeof TA312_RSA_E); + trust_anchors[313] = make_rsa_trust_anchor((unsigned char *)TA313_DN, sizeof TA313_DN, (unsigned char *)TA313_RSA_N, sizeof TA313_RSA_N, (unsigned char *)TA313_RSA_E, sizeof TA313_RSA_E); + trust_anchors[314] = make_rsa_trust_anchor((unsigned char *)TA314_DN, sizeof TA314_DN, (unsigned char *)TA314_RSA_N, sizeof TA314_RSA_N, (unsigned char *)TA314_RSA_E, sizeof TA314_RSA_E); + trust_anchors[315] = make_ec_trust_anchor((unsigned char *)TA315_DN, sizeof TA315_DN, BR_EC_secp384r1, (unsigned char *)TA315_EC_Q, sizeof TA315_EC_Q); + trust_anchors[316] = make_rsa_trust_anchor((unsigned char *)TA316_DN, sizeof TA316_DN, (unsigned char *)TA316_RSA_N, sizeof TA316_RSA_N, (unsigned char *)TA316_RSA_E, sizeof TA316_RSA_E); + trust_anchors[317] = make_rsa_trust_anchor((unsigned char *)TA317_DN, sizeof TA317_DN, (unsigned char *)TA317_RSA_N, sizeof TA317_RSA_N, (unsigned char *)TA317_RSA_E, sizeof TA317_RSA_E); + trust_anchors[318] = make_rsa_trust_anchor((unsigned char *)TA318_DN, sizeof TA318_DN, (unsigned char *)TA318_RSA_N, sizeof TA318_RSA_N, (unsigned char *)TA318_RSA_E, sizeof TA318_RSA_E); + trust_anchors[319] = make_ec_trust_anchor((unsigned char *)TA319_DN, sizeof TA319_DN, BR_EC_secp384r1, (unsigned char *)TA319_EC_Q, sizeof TA319_EC_Q); + trust_anchors[320] = make_rsa_trust_anchor((unsigned char *)TA320_DN, sizeof TA320_DN, (unsigned char *)TA320_RSA_N, sizeof TA320_RSA_N, (unsigned char *)TA320_RSA_E, sizeof TA320_RSA_E); + trust_anchors[321] = make_ec_trust_anchor((unsigned char *)TA321_DN, sizeof TA321_DN, BR_EC_secp384r1, (unsigned char *)TA321_EC_Q, sizeof TA321_EC_Q); + trust_anchors[322] = make_rsa_trust_anchor((unsigned char *)TA322_DN, sizeof TA322_DN, (unsigned char *)TA322_RSA_N, sizeof TA322_RSA_N, (unsigned char *)TA322_RSA_E, sizeof TA322_RSA_E); + trust_anchors[323] = make_rsa_trust_anchor((unsigned char *)TA323_DN, sizeof TA323_DN, (unsigned char *)TA323_RSA_N, sizeof TA323_RSA_N, (unsigned char *)TA323_RSA_E, sizeof TA323_RSA_E); + trust_anchors[324] = make_rsa_trust_anchor((unsigned char *)TA324_DN, sizeof TA324_DN, (unsigned char *)TA324_RSA_N, sizeof TA324_RSA_N, (unsigned char *)TA324_RSA_E, sizeof TA324_RSA_E); + trust_anchors[325] = make_rsa_trust_anchor((unsigned char *)TA325_DN, sizeof TA325_DN, (unsigned char *)TA325_RSA_N, sizeof TA325_RSA_N, (unsigned char *)TA325_RSA_E, sizeof TA325_RSA_E); + trust_anchors[326] = make_ec_trust_anchor((unsigned char *)TA326_DN, sizeof TA326_DN, BR_EC_secp384r1, (unsigned char *)TA326_EC_Q, sizeof TA326_EC_Q); + trust_anchors[327] = make_rsa_trust_anchor((unsigned char *)TA327_DN, sizeof TA327_DN, (unsigned char *)TA327_RSA_N, sizeof TA327_RSA_N, (unsigned char *)TA327_RSA_E, sizeof TA327_RSA_E); + trust_anchors[328] = make_rsa_trust_anchor((unsigned char *)TA328_DN, sizeof TA328_DN, (unsigned char *)TA328_RSA_N, sizeof TA328_RSA_N, (unsigned char *)TA328_RSA_E, sizeof TA328_RSA_E); + trust_anchors[329] = make_rsa_trust_anchor((unsigned char *)TA329_DN, sizeof TA329_DN, (unsigned char *)TA329_RSA_N, sizeof TA329_RSA_N, (unsigned char *)TA329_RSA_E, sizeof TA329_RSA_E); + trust_anchors[330] = make_rsa_trust_anchor((unsigned char *)TA330_DN, sizeof TA330_DN, (unsigned char *)TA330_RSA_N, sizeof TA330_RSA_N, (unsigned char *)TA330_RSA_E, sizeof TA330_RSA_E); + trust_anchors[331] = make_ec_trust_anchor((unsigned char *)TA331_DN, sizeof TA331_DN, BR_EC_secp384r1, (unsigned char *)TA331_EC_Q, sizeof TA331_EC_Q); + trust_anchors[332] = make_rsa_trust_anchor((unsigned char *)TA332_DN, sizeof TA332_DN, (unsigned char *)TA332_RSA_N, sizeof TA332_RSA_N, (unsigned char *)TA332_RSA_E, sizeof TA332_RSA_E); + trust_anchors[333] = make_rsa_trust_anchor((unsigned char *)TA333_DN, sizeof TA333_DN, (unsigned char *)TA333_RSA_N, sizeof TA333_RSA_N, (unsigned char *)TA333_RSA_E, sizeof TA333_RSA_E); + trust_anchors[334] = make_rsa_trust_anchor((unsigned char *)TA334_DN, sizeof TA334_DN, (unsigned char *)TA334_RSA_N, sizeof TA334_RSA_N, (unsigned char *)TA334_RSA_E, sizeof TA334_RSA_E); + trust_anchors[335] = make_rsa_trust_anchor((unsigned char *)TA335_DN, sizeof TA335_DN, (unsigned char *)TA335_RSA_N, sizeof TA335_RSA_N, (unsigned char *)TA335_RSA_E, sizeof TA335_RSA_E); + trust_anchors[336] = make_ec_trust_anchor((unsigned char *)TA336_DN, sizeof TA336_DN, BR_EC_secp384r1, (unsigned char *)TA336_EC_Q, sizeof TA336_EC_Q); + trust_anchors[337] = make_rsa_trust_anchor((unsigned char *)TA337_DN, sizeof TA337_DN, (unsigned char *)TA337_RSA_N, sizeof TA337_RSA_N, (unsigned char *)TA337_RSA_E, sizeof TA337_RSA_E); + trust_anchors[338] = make_rsa_trust_anchor((unsigned char *)TA338_DN, sizeof TA338_DN, (unsigned char *)TA338_RSA_N, sizeof TA338_RSA_N, (unsigned char *)TA338_RSA_E, sizeof TA338_RSA_E); + trust_anchors[339] = make_rsa_trust_anchor((unsigned char *)TA339_DN, sizeof TA339_DN, (unsigned char *)TA339_RSA_N, sizeof TA339_RSA_N, (unsigned char *)TA339_RSA_E, sizeof TA339_RSA_E); + trust_anchors[340] = make_rsa_trust_anchor((unsigned char *)TA340_DN, sizeof TA340_DN, (unsigned char *)TA340_RSA_N, sizeof TA340_RSA_N, (unsigned char *)TA340_RSA_E, sizeof TA340_RSA_E); + trust_anchors[341] = make_rsa_trust_anchor((unsigned char *)TA341_DN, sizeof TA341_DN, (unsigned char *)TA341_RSA_N, sizeof TA341_RSA_N, (unsigned char *)TA341_RSA_E, sizeof TA341_RSA_E); + trust_anchors[342] = make_ec_trust_anchor((unsigned char *)TA342_DN, sizeof TA342_DN, BR_EC_secp384r1, (unsigned char *)TA342_EC_Q, sizeof TA342_EC_Q); + trust_anchors[343] = make_rsa_trust_anchor((unsigned char *)TA343_DN, sizeof TA343_DN, (unsigned char *)TA343_RSA_N, sizeof TA343_RSA_N, (unsigned char *)TA343_RSA_E, sizeof TA343_RSA_E); + trust_anchors[344] = make_ec_trust_anchor((unsigned char *)TA344_DN, sizeof TA344_DN, BR_EC_secp384r1, (unsigned char *)TA344_EC_Q, sizeof TA344_EC_Q); + trust_anchors[345] = make_rsa_trust_anchor((unsigned char *)TA345_DN, sizeof TA345_DN, (unsigned char *)TA345_RSA_N, sizeof TA345_RSA_N, (unsigned char *)TA345_RSA_E, sizeof TA345_RSA_E); + trust_anchors[346] = make_ec_trust_anchor((unsigned char *)TA346_DN, sizeof TA346_DN, BR_EC_secp384r1, (unsigned char *)TA346_EC_Q, sizeof TA346_EC_Q); + trust_anchors[347] = make_rsa_trust_anchor((unsigned char *)TA347_DN, sizeof TA347_DN, (unsigned char *)TA347_RSA_N, sizeof TA347_RSA_N, (unsigned char *)TA347_RSA_E, sizeof TA347_RSA_E); + trust_anchors[348] = make_rsa_trust_anchor((unsigned char *)TA348_DN, sizeof TA348_DN, (unsigned char *)TA348_RSA_N, sizeof TA348_RSA_N, (unsigned char *)TA348_RSA_E, sizeof TA348_RSA_E); + trust_anchors[349] = make_ec_trust_anchor((unsigned char *)TA349_DN, sizeof TA349_DN, BR_EC_secp384r1, (unsigned char *)TA349_EC_Q, sizeof TA349_EC_Q); + trust_anchors[350] = make_rsa_trust_anchor((unsigned char *)TA350_DN, sizeof TA350_DN, (unsigned char *)TA350_RSA_N, sizeof TA350_RSA_N, (unsigned char *)TA350_RSA_E, sizeof TA350_RSA_E); + trust_anchors[351] = make_rsa_trust_anchor((unsigned char *)TA351_DN, sizeof TA351_DN, (unsigned char *)TA351_RSA_N, sizeof TA351_RSA_N, (unsigned char *)TA351_RSA_E, sizeof TA351_RSA_E); + trust_anchors[352] = make_rsa_trust_anchor((unsigned char *)TA352_DN, sizeof TA352_DN, (unsigned char *)TA352_RSA_N, sizeof TA352_RSA_N, (unsigned char *)TA352_RSA_E, sizeof TA352_RSA_E); + trust_anchors[353] = make_ec_trust_anchor((unsigned char *)TA353_DN, sizeof TA353_DN, BR_EC_secp384r1, (unsigned char *)TA353_EC_Q, sizeof TA353_EC_Q); + trust_anchors[354] = make_rsa_trust_anchor((unsigned char *)TA354_DN, sizeof TA354_DN, (unsigned char *)TA354_RSA_N, sizeof TA354_RSA_N, (unsigned char *)TA354_RSA_E, sizeof TA354_RSA_E); + trust_anchors[355] = make_rsa_trust_anchor((unsigned char *)TA355_DN, sizeof TA355_DN, (unsigned char *)TA355_RSA_N, sizeof TA355_RSA_N, (unsigned char *)TA355_RSA_E, sizeof TA355_RSA_E); + trust_anchors[356] = make_ec_trust_anchor((unsigned char *)TA356_DN, sizeof TA356_DN, BR_EC_secp384r1, (unsigned char *)TA356_EC_Q, sizeof TA356_EC_Q); + trust_anchors[357] = make_rsa_trust_anchor((unsigned char *)TA357_DN, sizeof TA357_DN, (unsigned char *)TA357_RSA_N, sizeof TA357_RSA_N, (unsigned char *)TA357_RSA_E, sizeof TA357_RSA_E); + trust_anchors[358] = make_rsa_trust_anchor((unsigned char *)TA358_DN, sizeof TA358_DN, (unsigned char *)TA358_RSA_N, sizeof TA358_RSA_N, (unsigned char *)TA358_RSA_E, sizeof TA358_RSA_E); + trust_anchors[359] = make_rsa_trust_anchor((unsigned char *)TA359_DN, sizeof TA359_DN, (unsigned char *)TA359_RSA_N, sizeof TA359_RSA_N, (unsigned char *)TA359_RSA_E, sizeof TA359_RSA_E); + trust_anchors[360] = make_rsa_trust_anchor((unsigned char *)TA360_DN, sizeof TA360_DN, (unsigned char *)TA360_RSA_N, sizeof TA360_RSA_N, (unsigned char *)TA360_RSA_E, sizeof TA360_RSA_E); + trust_anchors[361] = make_rsa_trust_anchor((unsigned char *)TA361_DN, sizeof TA361_DN, (unsigned char *)TA361_RSA_N, sizeof TA361_RSA_N, (unsigned char *)TA361_RSA_E, sizeof TA361_RSA_E); + trust_anchors[362] = make_rsa_trust_anchor((unsigned char *)TA362_DN, sizeof TA362_DN, (unsigned char *)TA362_RSA_N, sizeof TA362_RSA_N, (unsigned char *)TA362_RSA_E, sizeof TA362_RSA_E); + trust_anchors[363] = make_rsa_trust_anchor((unsigned char *)TA363_DN, sizeof TA363_DN, (unsigned char *)TA363_RSA_N, sizeof TA363_RSA_N, (unsigned char *)TA363_RSA_E, sizeof TA363_RSA_E); + trust_anchors[364] = make_rsa_trust_anchor((unsigned char *)TA364_DN, sizeof TA364_DN, (unsigned char *)TA364_RSA_N, sizeof TA364_RSA_N, (unsigned char *)TA364_RSA_E, sizeof TA364_RSA_E); + trust_anchors[365] = make_rsa_trust_anchor((unsigned char *)TA365_DN, sizeof TA365_DN, (unsigned char *)TA365_RSA_N, sizeof TA365_RSA_N, (unsigned char *)TA365_RSA_E, sizeof TA365_RSA_E); + trust_anchors[366] = make_rsa_trust_anchor((unsigned char *)TA366_DN, sizeof TA366_DN, (unsigned char *)TA366_RSA_N, sizeof TA366_RSA_N, (unsigned char *)TA366_RSA_E, sizeof TA366_RSA_E); + trust_anchors[367] = make_rsa_trust_anchor((unsigned char *)TA367_DN, sizeof TA367_DN, (unsigned char *)TA367_RSA_N, sizeof TA367_RSA_N, (unsigned char *)TA367_RSA_E, sizeof TA367_RSA_E); + trust_anchors[368] = make_ec_trust_anchor((unsigned char *)TA368_DN, sizeof TA368_DN, BR_EC_secp384r1, (unsigned char *)TA368_EC_Q, sizeof TA368_EC_Q); + trust_anchors[369] = make_rsa_trust_anchor((unsigned char *)TA369_DN, sizeof TA369_DN, (unsigned char *)TA369_RSA_N, sizeof TA369_RSA_N, (unsigned char *)TA369_RSA_E, sizeof TA369_RSA_E); + trust_anchors[370] = make_rsa_trust_anchor((unsigned char *)TA370_DN, sizeof TA370_DN, (unsigned char *)TA370_RSA_N, sizeof TA370_RSA_N, (unsigned char *)TA370_RSA_E, sizeof TA370_RSA_E); + trust_anchors[371] = make_rsa_trust_anchor((unsigned char *)TA371_DN, sizeof TA371_DN, (unsigned char *)TA371_RSA_N, sizeof TA371_RSA_N, (unsigned char *)TA371_RSA_E, sizeof TA371_RSA_E); + trust_anchors[372] = make_rsa_trust_anchor((unsigned char *)TA372_DN, sizeof TA372_DN, (unsigned char *)TA372_RSA_N, sizeof TA372_RSA_N, (unsigned char *)TA372_RSA_E, sizeof TA372_RSA_E); + trust_anchors[373] = make_ec_trust_anchor((unsigned char *)TA373_DN, sizeof TA373_DN, BR_EC_secp384r1, (unsigned char *)TA373_EC_Q, sizeof TA373_EC_Q); + trust_anchors[374] = make_rsa_trust_anchor((unsigned char *)TA374_DN, sizeof TA374_DN, (unsigned char *)TA374_RSA_N, sizeof TA374_RSA_N, (unsigned char *)TA374_RSA_E, sizeof TA374_RSA_E); + trust_anchors[375] = make_ec_trust_anchor((unsigned char *)TA375_DN, sizeof TA375_DN, BR_EC_secp256r1, (unsigned char *)TA375_EC_Q, sizeof TA375_EC_Q); + trust_anchors[376] = make_ec_trust_anchor((unsigned char *)TA376_DN, sizeof TA376_DN, BR_EC_secp384r1, (unsigned char *)TA376_EC_Q, sizeof TA376_EC_Q); + trust_anchors[377] = make_rsa_trust_anchor((unsigned char *)TA377_DN, sizeof TA377_DN, (unsigned char *)TA377_RSA_N, sizeof TA377_RSA_N, (unsigned char *)TA377_RSA_E, sizeof TA377_RSA_E); + trust_anchors[378] = make_rsa_trust_anchor((unsigned char *)TA378_DN, sizeof TA378_DN, (unsigned char *)TA378_RSA_N, sizeof TA378_RSA_N, (unsigned char *)TA378_RSA_E, sizeof TA378_RSA_E); + trust_anchors[379] = make_rsa_trust_anchor((unsigned char *)TA379_DN, sizeof TA379_DN, (unsigned char *)TA379_RSA_N, sizeof TA379_RSA_N, (unsigned char *)TA379_RSA_E, sizeof TA379_RSA_E); + trust_anchors[380] = make_ec_trust_anchor((unsigned char *)TA380_DN, sizeof TA380_DN, BR_EC_secp384r1, (unsigned char *)TA380_EC_Q, sizeof TA380_EC_Q); + trust_anchors[381] = make_rsa_trust_anchor((unsigned char *)TA381_DN, sizeof TA381_DN, (unsigned char *)TA381_RSA_N, sizeof TA381_RSA_N, (unsigned char *)TA381_RSA_E, sizeof TA381_RSA_E); + trust_anchors[382] = make_rsa_trust_anchor((unsigned char *)TA382_DN, sizeof TA382_DN, (unsigned char *)TA382_RSA_N, sizeof TA382_RSA_N, (unsigned char *)TA382_RSA_E, sizeof TA382_RSA_E); + trust_anchors[383] = make_rsa_trust_anchor((unsigned char *)TA383_DN, sizeof TA383_DN, (unsigned char *)TA383_RSA_N, sizeof TA383_RSA_N, (unsigned char *)TA383_RSA_E, sizeof TA383_RSA_E); + trust_anchors[384] = make_rsa_trust_anchor((unsigned char *)TA384_DN, sizeof TA384_DN, (unsigned char *)TA384_RSA_N, sizeof TA384_RSA_N, (unsigned char *)TA384_RSA_E, sizeof TA384_RSA_E); + trust_anchors[385] = make_ec_trust_anchor((unsigned char *)TA385_DN, sizeof TA385_DN, BR_EC_secp256r1, (unsigned char *)TA385_EC_Q, sizeof TA385_EC_Q); + trust_anchors[386] = make_rsa_trust_anchor((unsigned char *)TA386_DN, sizeof TA386_DN, (unsigned char *)TA386_RSA_N, sizeof TA386_RSA_N, (unsigned char *)TA386_RSA_E, sizeof TA386_RSA_E); + trust_anchors[387] = make_ec_trust_anchor((unsigned char *)TA387_DN, sizeof TA387_DN, BR_EC_secp384r1, (unsigned char *)TA387_EC_Q, sizeof TA387_EC_Q); + trust_anchors[388] = make_ec_trust_anchor((unsigned char *)TA388_DN, sizeof TA388_DN, BR_EC_secp384r1, (unsigned char *)TA388_EC_Q, sizeof TA388_EC_Q); + trust_anchors[389] = make_rsa_trust_anchor((unsigned char *)TA389_DN, sizeof TA389_DN, (unsigned char *)TA389_RSA_N, sizeof TA389_RSA_N, (unsigned char *)TA389_RSA_E, sizeof TA389_RSA_E); + trust_anchors[390] = make_rsa_trust_anchor((unsigned char *)TA390_DN, sizeof TA390_DN, (unsigned char *)TA390_RSA_N, sizeof TA390_RSA_N, (unsigned char *)TA390_RSA_E, sizeof TA390_RSA_E); + trust_anchors[391] = make_ec_trust_anchor((unsigned char *)TA391_DN, sizeof TA391_DN, BR_EC_secp384r1, (unsigned char *)TA391_EC_Q, sizeof TA391_EC_Q); + trust_anchors[392] = make_rsa_trust_anchor((unsigned char *)TA392_DN, sizeof TA392_DN, (unsigned char *)TA392_RSA_N, sizeof TA392_RSA_N, (unsigned char *)TA392_RSA_E, sizeof TA392_RSA_E); + trust_anchors[393] = make_rsa_trust_anchor((unsigned char *)TA393_DN, sizeof TA393_DN, (unsigned char *)TA393_RSA_N, sizeof TA393_RSA_N, (unsigned char *)TA393_RSA_E, sizeof TA393_RSA_E); + trust_anchors[394] = make_rsa_trust_anchor((unsigned char *)TA394_DN, sizeof TA394_DN, (unsigned char *)TA394_RSA_N, sizeof TA394_RSA_N, (unsigned char *)TA394_RSA_E, sizeof TA394_RSA_E); + trust_anchors[395] = make_ec_trust_anchor((unsigned char *)TA395_DN, sizeof TA395_DN, BR_EC_secp384r1, (unsigned char *)TA395_EC_Q, sizeof TA395_EC_Q); + trust_anchors[396] = make_rsa_trust_anchor((unsigned char *)TA396_DN, sizeof TA396_DN, (unsigned char *)TA396_RSA_N, sizeof TA396_RSA_N, (unsigned char *)TA396_RSA_E, sizeof TA396_RSA_E); + trust_anchors[397] = make_rsa_trust_anchor((unsigned char *)TA397_DN, sizeof TA397_DN, (unsigned char *)TA397_RSA_N, sizeof TA397_RSA_N, (unsigned char *)TA397_RSA_E, sizeof TA397_RSA_E); + trust_anchors[398] = make_rsa_trust_anchor((unsigned char *)TA398_DN, sizeof TA398_DN, (unsigned char *)TA398_RSA_N, sizeof TA398_RSA_N, (unsigned char *)TA398_RSA_E, sizeof TA398_RSA_E); + trust_anchors[399] = make_rsa_trust_anchor((unsigned char *)TA399_DN, sizeof TA399_DN, (unsigned char *)TA399_RSA_N, sizeof TA399_RSA_N, (unsigned char *)TA399_RSA_E, sizeof TA399_RSA_E); + trust_anchors[400] = make_rsa_trust_anchor((unsigned char *)TA400_DN, sizeof TA400_DN, (unsigned char *)TA400_RSA_N, sizeof TA400_RSA_N, (unsigned char *)TA400_RSA_E, sizeof TA400_RSA_E); + trust_anchors[401] = make_ec_trust_anchor((unsigned char *)TA401_DN, sizeof TA401_DN, BR_EC_secp384r1, (unsigned char *)TA401_EC_Q, sizeof TA401_EC_Q); + trust_anchors[402] = make_rsa_trust_anchor((unsigned char *)TA402_DN, sizeof TA402_DN, (unsigned char *)TA402_RSA_N, sizeof TA402_RSA_N, (unsigned char *)TA402_RSA_E, sizeof TA402_RSA_E); + trust_anchors[403] = make_rsa_trust_anchor((unsigned char *)TA403_DN, sizeof TA403_DN, (unsigned char *)TA403_RSA_N, sizeof TA403_RSA_N, (unsigned char *)TA403_RSA_E, sizeof TA403_RSA_E); + trust_anchors[404] = make_ec_trust_anchor((unsigned char *)TA404_DN, sizeof TA404_DN, BR_EC_secp256r1, (unsigned char *)TA404_EC_Q, sizeof TA404_EC_Q); + trust_anchors[405] = make_ec_trust_anchor((unsigned char *)TA405_DN, sizeof TA405_DN, BR_EC_secp384r1, (unsigned char *)TA405_EC_Q, sizeof TA405_EC_Q); + trust_anchors[406] = make_rsa_trust_anchor((unsigned char *)TA406_DN, sizeof TA406_DN, (unsigned char *)TA406_RSA_N, sizeof TA406_RSA_N, (unsigned char *)TA406_RSA_E, sizeof TA406_RSA_E); + trust_anchors[407] = make_ec_trust_anchor((unsigned char *)TA407_DN, sizeof TA407_DN, BR_EC_secp384r1, (unsigned char *)TA407_EC_Q, sizeof TA407_EC_Q); + trust_anchors[408] = make_rsa_trust_anchor((unsigned char *)TA408_DN, sizeof TA408_DN, (unsigned char *)TA408_RSA_N, sizeof TA408_RSA_N, (unsigned char *)TA408_RSA_E, sizeof TA408_RSA_E); + trust_anchors[409] = make_rsa_trust_anchor((unsigned char *)TA409_DN, sizeof TA409_DN, (unsigned char *)TA409_RSA_N, sizeof TA409_RSA_N, (unsigned char *)TA409_RSA_E, sizeof TA409_RSA_E); + trust_anchors[410] = make_rsa_trust_anchor((unsigned char *)TA410_DN, sizeof TA410_DN, (unsigned char *)TA410_RSA_N, sizeof TA410_RSA_N, (unsigned char *)TA410_RSA_E, sizeof TA410_RSA_E); + trust_anchors[411] = make_ec_trust_anchor((unsigned char *)TA411_DN, sizeof TA411_DN, BR_EC_secp384r1, (unsigned char *)TA411_EC_Q, sizeof TA411_EC_Q); + trust_anchors[412] = make_rsa_trust_anchor((unsigned char *)TA412_DN, sizeof TA412_DN, (unsigned char *)TA412_RSA_N, sizeof TA412_RSA_N, (unsigned char *)TA412_RSA_E, sizeof TA412_RSA_E); + trust_anchors[413] = make_rsa_trust_anchor((unsigned char *)TA413_DN, sizeof TA413_DN, (unsigned char *)TA413_RSA_N, sizeof TA413_RSA_N, (unsigned char *)TA413_RSA_E, sizeof TA413_RSA_E); + trust_anchors[414] = make_rsa_trust_anchor((unsigned char *)TA414_DN, sizeof TA414_DN, (unsigned char *)TA414_RSA_N, sizeof TA414_RSA_N, (unsigned char *)TA414_RSA_E, sizeof TA414_RSA_E); + trust_anchors[415] = make_rsa_trust_anchor((unsigned char *)TA415_DN, sizeof TA415_DN, (unsigned char *)TA415_RSA_N, sizeof TA415_RSA_N, (unsigned char *)TA415_RSA_E, sizeof TA415_RSA_E); + trust_anchors[416] = make_rsa_trust_anchor((unsigned char *)TA416_DN, sizeof TA416_DN, (unsigned char *)TA416_RSA_N, sizeof TA416_RSA_N, (unsigned char *)TA416_RSA_E, sizeof TA416_RSA_E); + trust_anchors[417] = make_rsa_trust_anchor((unsigned char *)TA417_DN, sizeof TA417_DN, (unsigned char *)TA417_RSA_N, sizeof TA417_RSA_N, (unsigned char *)TA417_RSA_E, sizeof TA417_RSA_E); + trust_anchors[418] = make_ec_trust_anchor((unsigned char *)TA418_DN, sizeof TA418_DN, BR_EC_secp384r1, (unsigned char *)TA418_EC_Q, sizeof TA418_EC_Q); + trust_anchors[419] = make_rsa_trust_anchor((unsigned char *)TA419_DN, sizeof TA419_DN, (unsigned char *)TA419_RSA_N, sizeof TA419_RSA_N, (unsigned char *)TA419_RSA_E, sizeof TA419_RSA_E); + trust_anchors[420] = make_ec_trust_anchor((unsigned char *)TA420_DN, sizeof TA420_DN, BR_EC_secp384r1, (unsigned char *)TA420_EC_Q, sizeof TA420_EC_Q); + trust_anchors[421] = make_rsa_trust_anchor((unsigned char *)TA421_DN, sizeof TA421_DN, (unsigned char *)TA421_RSA_N, sizeof TA421_RSA_N, (unsigned char *)TA421_RSA_E, sizeof TA421_RSA_E); + trust_anchors[422] = make_rsa_trust_anchor((unsigned char *)TA422_DN, sizeof TA422_DN, (unsigned char *)TA422_RSA_N, sizeof TA422_RSA_N, (unsigned char *)TA422_RSA_E, sizeof TA422_RSA_E); + trust_anchors[423] = make_rsa_trust_anchor((unsigned char *)TA423_DN, sizeof TA423_DN, (unsigned char *)TA423_RSA_N, sizeof TA423_RSA_N, (unsigned char *)TA423_RSA_E, sizeof TA423_RSA_E); + trust_anchors[424] = make_ec_trust_anchor((unsigned char *)TA424_DN, sizeof TA424_DN, BR_EC_secp384r1, (unsigned char *)TA424_EC_Q, sizeof TA424_EC_Q); + trust_anchors[425] = make_rsa_trust_anchor((unsigned char *)TA425_DN, sizeof TA425_DN, (unsigned char *)TA425_RSA_N, sizeof TA425_RSA_N, (unsigned char *)TA425_RSA_E, sizeof TA425_RSA_E); + trust_anchors[426] = make_rsa_trust_anchor((unsigned char *)TA426_DN, sizeof TA426_DN, (unsigned char *)TA426_RSA_N, sizeof TA426_RSA_N, (unsigned char *)TA426_RSA_E, sizeof TA426_RSA_E); + trust_anchors[427] = make_rsa_trust_anchor((unsigned char *)TA427_DN, sizeof TA427_DN, (unsigned char *)TA427_RSA_N, sizeof TA427_RSA_N, (unsigned char *)TA427_RSA_E, sizeof TA427_RSA_E); + trust_anchors[428] = make_ec_trust_anchor((unsigned char *)TA428_DN, sizeof TA428_DN, BR_EC_secp384r1, (unsigned char *)TA428_EC_Q, sizeof TA428_EC_Q); + trust_anchors[429] = make_ec_trust_anchor((unsigned char *)TA429_DN, sizeof TA429_DN, BR_EC_secp384r1, (unsigned char *)TA429_EC_Q, sizeof TA429_EC_Q); + trust_anchors[430] = make_rsa_trust_anchor((unsigned char *)TA430_DN, sizeof TA430_DN, (unsigned char *)TA430_RSA_N, sizeof TA430_RSA_N, (unsigned char *)TA430_RSA_E, sizeof TA430_RSA_E); + trust_anchors[431] = make_rsa_trust_anchor((unsigned char *)TA431_DN, sizeof TA431_DN, (unsigned char *)TA431_RSA_N, sizeof TA431_RSA_N, (unsigned char *)TA431_RSA_E, sizeof TA431_RSA_E); + trust_anchors[432] = make_rsa_trust_anchor((unsigned char *)TA432_DN, sizeof TA432_DN, (unsigned char *)TA432_RSA_N, sizeof TA432_RSA_N, (unsigned char *)TA432_RSA_E, sizeof TA432_RSA_E); + trust_anchors[433] = make_ec_trust_anchor((unsigned char *)TA433_DN, sizeof TA433_DN, BR_EC_secp384r1, (unsigned char *)TA433_EC_Q, sizeof TA433_EC_Q); + trust_anchors[434] = make_rsa_trust_anchor((unsigned char *)TA434_DN, sizeof TA434_DN, (unsigned char *)TA434_RSA_N, sizeof TA434_RSA_N, (unsigned char *)TA434_RSA_E, sizeof TA434_RSA_E); + trust_anchors[435] = make_ec_trust_anchor((unsigned char *)TA435_DN, sizeof TA435_DN, BR_EC_secp384r1, (unsigned char *)TA435_EC_Q, sizeof TA435_EC_Q); + trust_anchors[436] = make_rsa_trust_anchor((unsigned char *)TA436_DN, sizeof TA436_DN, (unsigned char *)TA436_RSA_N, sizeof TA436_RSA_N, (unsigned char *)TA436_RSA_E, sizeof TA436_RSA_E); + trust_anchors[437] = make_rsa_trust_anchor((unsigned char *)TA437_DN, sizeof TA437_DN, (unsigned char *)TA437_RSA_N, sizeof TA437_RSA_N, (unsigned char *)TA437_RSA_E, sizeof TA437_RSA_E); + trust_anchors[438] = make_rsa_trust_anchor((unsigned char *)TA438_DN, sizeof TA438_DN, (unsigned char *)TA438_RSA_N, sizeof TA438_RSA_N, (unsigned char *)TA438_RSA_E, sizeof TA438_RSA_E); + trust_anchors[439] = make_rsa_trust_anchor((unsigned char *)TA439_DN, sizeof TA439_DN, (unsigned char *)TA439_RSA_N, sizeof TA439_RSA_N, (unsigned char *)TA439_RSA_E, sizeof TA439_RSA_E); + trust_anchors[440] = make_rsa_trust_anchor((unsigned char *)TA440_DN, sizeof TA440_DN, (unsigned char *)TA440_RSA_N, sizeof TA440_RSA_N, (unsigned char *)TA440_RSA_E, sizeof TA440_RSA_E); + trust_anchors[441] = make_ec_trust_anchor((unsigned char *)TA441_DN, sizeof TA441_DN, BR_EC_secp384r1, (unsigned char *)TA441_EC_Q, sizeof TA441_EC_Q); + trust_anchors[442] = make_rsa_trust_anchor((unsigned char *)TA442_DN, sizeof TA442_DN, (unsigned char *)TA442_RSA_N, sizeof TA442_RSA_N, (unsigned char *)TA442_RSA_E, sizeof TA442_RSA_E); + trust_anchors[443] = make_rsa_trust_anchor((unsigned char *)TA443_DN, sizeof TA443_DN, (unsigned char *)TA443_RSA_N, sizeof TA443_RSA_N, (unsigned char *)TA443_RSA_E, sizeof TA443_RSA_E); + trust_anchors[444] = make_ec_trust_anchor((unsigned char *)TA444_DN, sizeof TA444_DN, BR_EC_secp384r1, (unsigned char *)TA444_EC_Q, sizeof TA444_EC_Q); + trust_anchors[445] = make_rsa_trust_anchor((unsigned char *)TA445_DN, sizeof TA445_DN, (unsigned char *)TA445_RSA_N, sizeof TA445_RSA_N, (unsigned char *)TA445_RSA_E, sizeof TA445_RSA_E); + trust_anchors[446] = make_ec_trust_anchor((unsigned char *)TA446_DN, sizeof TA446_DN, BR_EC_secp384r1, (unsigned char *)TA446_EC_Q, sizeof TA446_EC_Q); + trust_anchors[447] = make_rsa_trust_anchor((unsigned char *)TA447_DN, sizeof TA447_DN, (unsigned char *)TA447_RSA_N, sizeof TA447_RSA_N, (unsigned char *)TA447_RSA_E, sizeof TA447_RSA_E); + trust_anchors[448] = make_rsa_trust_anchor((unsigned char *)TA448_DN, sizeof TA448_DN, (unsigned char *)TA448_RSA_N, sizeof TA448_RSA_N, (unsigned char *)TA448_RSA_E, sizeof TA448_RSA_E); + trust_anchors[449] = make_rsa_trust_anchor((unsigned char *)TA449_DN, sizeof TA449_DN, (unsigned char *)TA449_RSA_N, sizeof TA449_RSA_N, (unsigned char *)TA449_RSA_E, sizeof TA449_RSA_E); + trust_anchors[450] = make_rsa_trust_anchor((unsigned char *)TA450_DN, sizeof TA450_DN, (unsigned char *)TA450_RSA_N, sizeof TA450_RSA_N, (unsigned char *)TA450_RSA_E, sizeof TA450_RSA_E); + trust_anchors[451] = make_ec_trust_anchor((unsigned char *)TA451_DN, sizeof TA451_DN, BR_EC_secp384r1, (unsigned char *)TA451_EC_Q, sizeof TA451_EC_Q); + trust_anchors[452] = make_rsa_trust_anchor((unsigned char *)TA452_DN, sizeof TA452_DN, (unsigned char *)TA452_RSA_N, sizeof TA452_RSA_N, (unsigned char *)TA452_RSA_E, sizeof TA452_RSA_E); + trust_anchors[453] = make_ec_trust_anchor((unsigned char *)TA453_DN, sizeof TA453_DN, BR_EC_secp384r1, (unsigned char *)TA453_EC_Q, sizeof TA453_EC_Q); + trust_anchors[454] = make_rsa_trust_anchor((unsigned char *)TA454_DN, sizeof TA454_DN, (unsigned char *)TA454_RSA_N, sizeof TA454_RSA_N, (unsigned char *)TA454_RSA_E, sizeof TA454_RSA_E); + trust_anchors[455] = make_rsa_trust_anchor((unsigned char *)TA455_DN, sizeof TA455_DN, (unsigned char *)TA455_RSA_N, sizeof TA455_RSA_N, (unsigned char *)TA455_RSA_E, sizeof TA455_RSA_E); + trust_anchors[456] = make_rsa_trust_anchor((unsigned char *)TA456_DN, sizeof TA456_DN, (unsigned char *)TA456_RSA_N, sizeof TA456_RSA_N, (unsigned char *)TA456_RSA_E, sizeof TA456_RSA_E); + trust_anchors[457] = make_rsa_trust_anchor((unsigned char *)TA457_DN, sizeof TA457_DN, (unsigned char *)TA457_RSA_N, sizeof TA457_RSA_N, (unsigned char *)TA457_RSA_E, sizeof TA457_RSA_E); + trust_anchors[458] = make_ec_trust_anchor((unsigned char *)TA458_DN, sizeof TA458_DN, BR_EC_secp384r1, (unsigned char *)TA458_EC_Q, sizeof TA458_EC_Q); + trust_anchors[459] = make_ec_trust_anchor((unsigned char *)TA459_DN, sizeof TA459_DN, BR_EC_secp384r1, (unsigned char *)TA459_EC_Q, sizeof TA459_EC_Q); + trust_anchors[460] = make_ec_trust_anchor((unsigned char *)TA460_DN, sizeof TA460_DN, BR_EC_secp256r1, (unsigned char *)TA460_EC_Q, sizeof TA460_EC_Q); + trust_anchors[461] = make_ec_trust_anchor((unsigned char *)TA461_DN, sizeof TA461_DN, BR_EC_secp384r1, (unsigned char *)TA461_EC_Q, sizeof TA461_EC_Q); + trust_anchors[462] = make_rsa_trust_anchor((unsigned char *)TA462_DN, sizeof TA462_DN, (unsigned char *)TA462_RSA_N, sizeof TA462_RSA_N, (unsigned char *)TA462_RSA_E, sizeof TA462_RSA_E); + trust_anchors[463] = make_rsa_trust_anchor((unsigned char *)TA463_DN, sizeof TA463_DN, (unsigned char *)TA463_RSA_N, sizeof TA463_RSA_N, (unsigned char *)TA463_RSA_E, sizeof TA463_RSA_E); + trust_anchors[464] = make_rsa_trust_anchor((unsigned char *)TA464_DN, sizeof TA464_DN, (unsigned char *)TA464_RSA_N, sizeof TA464_RSA_N, (unsigned char *)TA464_RSA_E, sizeof TA464_RSA_E); + trust_anchors[465] = make_ec_trust_anchor((unsigned char *)TA465_DN, sizeof TA465_DN, BR_EC_secp384r1, (unsigned char *)TA465_EC_Q, sizeof TA465_EC_Q); + trust_anchors[466] = make_rsa_trust_anchor((unsigned char *)TA466_DN, sizeof TA466_DN, (unsigned char *)TA466_RSA_N, sizeof TA466_RSA_N, (unsigned char *)TA466_RSA_E, sizeof TA466_RSA_E); + trust_anchors[467] = make_rsa_trust_anchor((unsigned char *)TA467_DN, sizeof TA467_DN, (unsigned char *)TA467_RSA_N, sizeof TA467_RSA_N, (unsigned char *)TA467_RSA_E, sizeof TA467_RSA_E); + trust_anchors[468] = make_rsa_trust_anchor((unsigned char *)TA468_DN, sizeof TA468_DN, (unsigned char *)TA468_RSA_N, sizeof TA468_RSA_N, (unsigned char *)TA468_RSA_E, sizeof TA468_RSA_E); + trust_anchors[469] = make_ec_trust_anchor((unsigned char *)TA469_DN, sizeof TA469_DN, BR_EC_secp384r1, (unsigned char *)TA469_EC_Q, sizeof TA469_EC_Q); + trust_anchors[470] = make_rsa_trust_anchor((unsigned char *)TA470_DN, sizeof TA470_DN, (unsigned char *)TA470_RSA_N, sizeof TA470_RSA_N, (unsigned char *)TA470_RSA_E, sizeof TA470_RSA_E); + trust_anchors[471] = make_ec_trust_anchor((unsigned char *)TA471_DN, sizeof TA471_DN, BR_EC_secp384r1, (unsigned char *)TA471_EC_Q, sizeof TA471_EC_Q); + trust_anchors[472] = make_rsa_trust_anchor((unsigned char *)TA472_DN, sizeof TA472_DN, (unsigned char *)TA472_RSA_N, sizeof TA472_RSA_N, (unsigned char *)TA472_RSA_E, sizeof TA472_RSA_E); + trust_anchors[473] = make_rsa_trust_anchor((unsigned char *)TA473_DN, sizeof TA473_DN, (unsigned char *)TA473_RSA_N, sizeof TA473_RSA_N, (unsigned char *)TA473_RSA_E, sizeof TA473_RSA_E); + trust_anchors[474] = make_rsa_trust_anchor((unsigned char *)TA474_DN, sizeof TA474_DN, (unsigned char *)TA474_RSA_N, sizeof TA474_RSA_N, (unsigned char *)TA474_RSA_E, sizeof TA474_RSA_E); + trust_anchors[475] = make_rsa_trust_anchor((unsigned char *)TA475_DN, sizeof TA475_DN, (unsigned char *)TA475_RSA_N, sizeof TA475_RSA_N, (unsigned char *)TA475_RSA_E, sizeof TA475_RSA_E); + trust_anchors[476] = make_ec_trust_anchor((unsigned char *)TA476_DN, sizeof TA476_DN, BR_EC_secp384r1, (unsigned char *)TA476_EC_Q, sizeof TA476_EC_Q); + trust_anchors[477] = make_rsa_trust_anchor((unsigned char *)TA477_DN, sizeof TA477_DN, (unsigned char *)TA477_RSA_N, sizeof TA477_RSA_N, (unsigned char *)TA477_RSA_E, sizeof TA477_RSA_E); + trust_anchors[478] = make_rsa_trust_anchor((unsigned char *)TA478_DN, sizeof TA478_DN, (unsigned char *)TA478_RSA_N, sizeof TA478_RSA_N, (unsigned char *)TA478_RSA_E, sizeof TA478_RSA_E); + trust_anchors[479] = make_rsa_trust_anchor((unsigned char *)TA479_DN, sizeof TA479_DN, (unsigned char *)TA479_RSA_N, sizeof TA479_RSA_N, (unsigned char *)TA479_RSA_E, sizeof TA479_RSA_E); + trust_anchors[480] = make_rsa_trust_anchor((unsigned char *)TA480_DN, sizeof TA480_DN, (unsigned char *)TA480_RSA_N, sizeof TA480_RSA_N, (unsigned char *)TA480_RSA_E, sizeof TA480_RSA_E); + trust_anchors[481] = make_ec_trust_anchor((unsigned char *)TA481_DN, sizeof TA481_DN, BR_EC_secp384r1, (unsigned char *)TA481_EC_Q, sizeof TA481_EC_Q); + trust_anchors[482] = make_rsa_trust_anchor((unsigned char *)TA482_DN, sizeof TA482_DN, (unsigned char *)TA482_RSA_N, sizeof TA482_RSA_N, (unsigned char *)TA482_RSA_E, sizeof TA482_RSA_E); + trust_anchors[483] = make_rsa_trust_anchor((unsigned char *)TA483_DN, sizeof TA483_DN, (unsigned char *)TA483_RSA_N, sizeof TA483_RSA_N, (unsigned char *)TA483_RSA_E, sizeof TA483_RSA_E); + trust_anchors[484] = make_rsa_trust_anchor((unsigned char *)TA484_DN, sizeof TA484_DN, (unsigned char *)TA484_RSA_N, sizeof TA484_RSA_N, (unsigned char *)TA484_RSA_E, sizeof TA484_RSA_E); + trust_anchors[485] = make_rsa_trust_anchor((unsigned char *)TA485_DN, sizeof TA485_DN, (unsigned char *)TA485_RSA_N, sizeof TA485_RSA_N, (unsigned char *)TA485_RSA_E, sizeof TA485_RSA_E); + trust_anchors[486] = make_ec_trust_anchor((unsigned char *)TA486_DN, sizeof TA486_DN, BR_EC_secp384r1, (unsigned char *)TA486_EC_Q, sizeof TA486_EC_Q); + trust_anchors[487] = make_rsa_trust_anchor((unsigned char *)TA487_DN, sizeof TA487_DN, (unsigned char *)TA487_RSA_N, sizeof TA487_RSA_N, (unsigned char *)TA487_RSA_E, sizeof TA487_RSA_E); + trust_anchors[488] = make_rsa_trust_anchor((unsigned char *)TA488_DN, sizeof TA488_DN, (unsigned char *)TA488_RSA_N, sizeof TA488_RSA_N, (unsigned char *)TA488_RSA_E, sizeof TA488_RSA_E); + trust_anchors[489] = make_rsa_trust_anchor((unsigned char *)TA489_DN, sizeof TA489_DN, (unsigned char *)TA489_RSA_N, sizeof TA489_RSA_N, (unsigned char *)TA489_RSA_E, sizeof TA489_RSA_E); + trust_anchors[490] = make_rsa_trust_anchor((unsigned char *)TA490_DN, sizeof TA490_DN, (unsigned char *)TA490_RSA_N, sizeof TA490_RSA_N, (unsigned char *)TA490_RSA_E, sizeof TA490_RSA_E); + trust_anchors[491] = make_rsa_trust_anchor((unsigned char *)TA491_DN, sizeof TA491_DN, (unsigned char *)TA491_RSA_N, sizeof TA491_RSA_N, (unsigned char *)TA491_RSA_E, sizeof TA491_RSA_E); + trust_anchors[492] = make_ec_trust_anchor((unsigned char *)TA492_DN, sizeof TA492_DN, BR_EC_secp384r1, (unsigned char *)TA492_EC_Q, sizeof TA492_EC_Q); + trust_anchors[493] = make_rsa_trust_anchor((unsigned char *)TA493_DN, sizeof TA493_DN, (unsigned char *)TA493_RSA_N, sizeof TA493_RSA_N, (unsigned char *)TA493_RSA_E, sizeof TA493_RSA_E); + trust_anchors[494] = make_ec_trust_anchor((unsigned char *)TA494_DN, sizeof TA494_DN, BR_EC_secp384r1, (unsigned char *)TA494_EC_Q, sizeof TA494_EC_Q); + trust_anchors[495] = make_rsa_trust_anchor((unsigned char *)TA495_DN, sizeof TA495_DN, (unsigned char *)TA495_RSA_N, sizeof TA495_RSA_N, (unsigned char *)TA495_RSA_E, sizeof TA495_RSA_E); + trust_anchors[496] = make_ec_trust_anchor((unsigned char *)TA496_DN, sizeof TA496_DN, BR_EC_secp384r1, (unsigned char *)TA496_EC_Q, sizeof TA496_EC_Q); + trust_anchors[497] = make_rsa_trust_anchor((unsigned char *)TA497_DN, sizeof TA497_DN, (unsigned char *)TA497_RSA_N, sizeof TA497_RSA_N, (unsigned char *)TA497_RSA_E, sizeof TA497_RSA_E); + trust_anchors[498] = make_rsa_trust_anchor((unsigned char *)TA498_DN, sizeof TA498_DN, (unsigned char *)TA498_RSA_N, sizeof TA498_RSA_N, (unsigned char *)TA498_RSA_E, sizeof TA498_RSA_E); + trust_anchors[499] = make_ec_trust_anchor((unsigned char *)TA499_DN, sizeof TA499_DN, BR_EC_secp384r1, (unsigned char *)TA499_EC_Q, sizeof TA499_EC_Q); + trust_anchors[500] = make_rsa_trust_anchor((unsigned char *)TA500_DN, sizeof TA500_DN, (unsigned char *)TA500_RSA_N, sizeof TA500_RSA_N, (unsigned char *)TA500_RSA_E, sizeof TA500_RSA_E); + trust_anchors[501] = make_rsa_trust_anchor((unsigned char *)TA501_DN, sizeof TA501_DN, (unsigned char *)TA501_RSA_N, sizeof TA501_RSA_N, (unsigned char *)TA501_RSA_E, sizeof TA501_RSA_E); + trust_anchors[502] = make_rsa_trust_anchor((unsigned char *)TA502_DN, sizeof TA502_DN, (unsigned char *)TA502_RSA_N, sizeof TA502_RSA_N, (unsigned char *)TA502_RSA_E, sizeof TA502_RSA_E); + trust_anchors[503] = make_ec_trust_anchor((unsigned char *)TA503_DN, sizeof TA503_DN, BR_EC_secp384r1, (unsigned char *)TA503_EC_Q, sizeof TA503_EC_Q); + trust_anchors[504] = make_rsa_trust_anchor((unsigned char *)TA504_DN, sizeof TA504_DN, (unsigned char *)TA504_RSA_N, sizeof TA504_RSA_N, (unsigned char *)TA504_RSA_E, sizeof TA504_RSA_E); + trust_anchors[505] = make_rsa_trust_anchor((unsigned char *)TA505_DN, sizeof TA505_DN, (unsigned char *)TA505_RSA_N, sizeof TA505_RSA_N, (unsigned char *)TA505_RSA_E, sizeof TA505_RSA_E); + trust_anchors[506] = make_ec_trust_anchor((unsigned char *)TA506_DN, sizeof TA506_DN, BR_EC_secp384r1, (unsigned char *)TA506_EC_Q, sizeof TA506_EC_Q); + trust_anchors[507] = make_rsa_trust_anchor((unsigned char *)TA507_DN, sizeof TA507_DN, (unsigned char *)TA507_RSA_N, sizeof TA507_RSA_N, (unsigned char *)TA507_RSA_E, sizeof TA507_RSA_E); + trust_anchors[508] = make_rsa_trust_anchor((unsigned char *)TA508_DN, sizeof TA508_DN, (unsigned char *)TA508_RSA_N, sizeof TA508_RSA_N, (unsigned char *)TA508_RSA_E, sizeof TA508_RSA_E); + trust_anchors[509] = make_rsa_trust_anchor((unsigned char *)TA509_DN, sizeof TA509_DN, (unsigned char *)TA509_RSA_N, sizeof TA509_RSA_N, (unsigned char *)TA509_RSA_E, sizeof TA509_RSA_E); + trust_anchors[510] = make_rsa_trust_anchor((unsigned char *)TA510_DN, sizeof TA510_DN, (unsigned char *)TA510_RSA_N, sizeof TA510_RSA_N, (unsigned char *)TA510_RSA_E, sizeof TA510_RSA_E); + trust_anchors[511] = make_rsa_trust_anchor((unsigned char *)TA511_DN, sizeof TA511_DN, (unsigned char *)TA511_RSA_N, sizeof TA511_RSA_N, (unsigned char *)TA511_RSA_E, sizeof TA511_RSA_E); + trust_anchors[512] = make_rsa_trust_anchor((unsigned char *)TA512_DN, sizeof TA512_DN, (unsigned char *)TA512_RSA_N, sizeof TA512_RSA_N, (unsigned char *)TA512_RSA_E, sizeof TA512_RSA_E); + trust_anchors[513] = make_rsa_trust_anchor((unsigned char *)TA513_DN, sizeof TA513_DN, (unsigned char *)TA513_RSA_N, sizeof TA513_RSA_N, (unsigned char *)TA513_RSA_E, sizeof TA513_RSA_E); + trust_anchors[514] = make_rsa_trust_anchor((unsigned char *)TA514_DN, sizeof TA514_DN, (unsigned char *)TA514_RSA_N, sizeof TA514_RSA_N, (unsigned char *)TA514_RSA_E, sizeof TA514_RSA_E); + trust_anchors[515] = make_rsa_trust_anchor((unsigned char *)TA515_DN, sizeof TA515_DN, (unsigned char *)TA515_RSA_N, sizeof TA515_RSA_N, (unsigned char *)TA515_RSA_E, sizeof TA515_RSA_E); + trust_anchors[516] = make_rsa_trust_anchor((unsigned char *)TA516_DN, sizeof TA516_DN, (unsigned char *)TA516_RSA_N, sizeof TA516_RSA_N, (unsigned char *)TA516_RSA_E, sizeof TA516_RSA_E); + trust_anchors[517] = make_rsa_trust_anchor((unsigned char *)TA517_DN, sizeof TA517_DN, (unsigned char *)TA517_RSA_N, sizeof TA517_RSA_N, (unsigned char *)TA517_RSA_E, sizeof TA517_RSA_E); + trust_anchors[518] = make_ec_trust_anchor((unsigned char *)TA518_DN, sizeof TA518_DN, BR_EC_secp384r1, (unsigned char *)TA518_EC_Q, sizeof TA518_EC_Q); + trust_anchors[519] = make_rsa_trust_anchor((unsigned char *)TA519_DN, sizeof TA519_DN, (unsigned char *)TA519_RSA_N, sizeof TA519_RSA_N, (unsigned char *)TA519_RSA_E, sizeof TA519_RSA_E); + trust_anchors[520] = make_rsa_trust_anchor((unsigned char *)TA520_DN, sizeof TA520_DN, (unsigned char *)TA520_RSA_N, sizeof TA520_RSA_N, (unsigned char *)TA520_RSA_E, sizeof TA520_RSA_E); + trust_anchors[521] = make_rsa_trust_anchor((unsigned char *)TA521_DN, sizeof TA521_DN, (unsigned char *)TA521_RSA_N, sizeof TA521_RSA_N, (unsigned char *)TA521_RSA_E, sizeof TA521_RSA_E); + trust_anchors[522] = make_rsa_trust_anchor((unsigned char *)TA522_DN, sizeof TA522_DN, (unsigned char *)TA522_RSA_N, sizeof TA522_RSA_N, (unsigned char *)TA522_RSA_E, sizeof TA522_RSA_E); + trust_anchors[523] = make_ec_trust_anchor((unsigned char *)TA523_DN, sizeof TA523_DN, BR_EC_secp384r1, (unsigned char *)TA523_EC_Q, sizeof TA523_EC_Q); + trust_anchors[524] = make_rsa_trust_anchor((unsigned char *)TA524_DN, sizeof TA524_DN, (unsigned char *)TA524_RSA_N, sizeof TA524_RSA_N, (unsigned char *)TA524_RSA_E, sizeof TA524_RSA_E); + trust_anchors[525] = make_ec_trust_anchor((unsigned char *)TA525_DN, sizeof TA525_DN, BR_EC_secp256r1, (unsigned char *)TA525_EC_Q, sizeof TA525_EC_Q); + trust_anchors[526] = make_ec_trust_anchor((unsigned char *)TA526_DN, sizeof TA526_DN, BR_EC_secp384r1, (unsigned char *)TA526_EC_Q, sizeof TA526_EC_Q); + trust_anchors[527] = make_rsa_trust_anchor((unsigned char *)TA527_DN, sizeof TA527_DN, (unsigned char *)TA527_RSA_N, sizeof TA527_RSA_N, (unsigned char *)TA527_RSA_E, sizeof TA527_RSA_E); + trust_anchors[528] = make_rsa_trust_anchor((unsigned char *)TA528_DN, sizeof TA528_DN, (unsigned char *)TA528_RSA_N, sizeof TA528_RSA_N, (unsigned char *)TA528_RSA_E, sizeof TA528_RSA_E); + trust_anchors[529] = make_rsa_trust_anchor((unsigned char *)TA529_DN, sizeof TA529_DN, (unsigned char *)TA529_RSA_N, sizeof TA529_RSA_N, (unsigned char *)TA529_RSA_E, sizeof TA529_RSA_E); + trust_anchors[530] = make_ec_trust_anchor((unsigned char *)TA530_DN, sizeof TA530_DN, BR_EC_secp384r1, (unsigned char *)TA530_EC_Q, sizeof TA530_EC_Q); + trust_anchors[531] = make_rsa_trust_anchor((unsigned char *)TA531_DN, sizeof TA531_DN, (unsigned char *)TA531_RSA_N, sizeof TA531_RSA_N, (unsigned char *)TA531_RSA_E, sizeof TA531_RSA_E); + trust_anchors[532] = make_rsa_trust_anchor((unsigned char *)TA532_DN, sizeof TA532_DN, (unsigned char *)TA532_RSA_N, sizeof TA532_RSA_N, (unsigned char *)TA532_RSA_E, sizeof TA532_RSA_E); + trust_anchors[533] = make_rsa_trust_anchor((unsigned char *)TA533_DN, sizeof TA533_DN, (unsigned char *)TA533_RSA_N, sizeof TA533_RSA_N, (unsigned char *)TA533_RSA_E, sizeof TA533_RSA_E); + trust_anchors[534] = make_rsa_trust_anchor((unsigned char *)TA534_DN, sizeof TA534_DN, (unsigned char *)TA534_RSA_N, sizeof TA534_RSA_N, (unsigned char *)TA534_RSA_E, sizeof TA534_RSA_E); + trust_anchors[535] = make_ec_trust_anchor((unsigned char *)TA535_DN, sizeof TA535_DN, BR_EC_secp256r1, (unsigned char *)TA535_EC_Q, sizeof TA535_EC_Q); + trust_anchors[536] = make_rsa_trust_anchor((unsigned char *)TA536_DN, sizeof TA536_DN, (unsigned char *)TA536_RSA_N, sizeof TA536_RSA_N, (unsigned char *)TA536_RSA_E, sizeof TA536_RSA_E); + trust_anchors[537] = make_ec_trust_anchor((unsigned char *)TA537_DN, sizeof TA537_DN, BR_EC_secp384r1, (unsigned char *)TA537_EC_Q, sizeof TA537_EC_Q); + trust_anchors[538] = make_ec_trust_anchor((unsigned char *)TA538_DN, sizeof TA538_DN, BR_EC_secp384r1, (unsigned char *)TA538_EC_Q, sizeof TA538_EC_Q); + trust_anchors[539] = make_rsa_trust_anchor((unsigned char *)TA539_DN, sizeof TA539_DN, (unsigned char *)TA539_RSA_N, sizeof TA539_RSA_N, (unsigned char *)TA539_RSA_E, sizeof TA539_RSA_E); + trust_anchors[540] = make_rsa_trust_anchor((unsigned char *)TA540_DN, sizeof TA540_DN, (unsigned char *)TA540_RSA_N, sizeof TA540_RSA_N, (unsigned char *)TA540_RSA_E, sizeof TA540_RSA_E); + trust_anchors[541] = make_ec_trust_anchor((unsigned char *)TA541_DN, sizeof TA541_DN, BR_EC_secp384r1, (unsigned char *)TA541_EC_Q, sizeof TA541_EC_Q); + trust_anchors[542] = make_rsa_trust_anchor((unsigned char *)TA542_DN, sizeof TA542_DN, (unsigned char *)TA542_RSA_N, sizeof TA542_RSA_N, (unsigned char *)TA542_RSA_E, sizeof TA542_RSA_E); + trust_anchors[543] = make_rsa_trust_anchor((unsigned char *)TA543_DN, sizeof TA543_DN, (unsigned char *)TA543_RSA_N, sizeof TA543_RSA_N, (unsigned char *)TA543_RSA_E, sizeof TA543_RSA_E); + trust_anchors[544] = make_rsa_trust_anchor((unsigned char *)TA544_DN, sizeof TA544_DN, (unsigned char *)TA544_RSA_N, sizeof TA544_RSA_N, (unsigned char *)TA544_RSA_E, sizeof TA544_RSA_E); + trust_anchors[545] = make_ec_trust_anchor((unsigned char *)TA545_DN, sizeof TA545_DN, BR_EC_secp384r1, (unsigned char *)TA545_EC_Q, sizeof TA545_EC_Q); + trust_anchors[546] = make_rsa_trust_anchor((unsigned char *)TA546_DN, sizeof TA546_DN, (unsigned char *)TA546_RSA_N, sizeof TA546_RSA_N, (unsigned char *)TA546_RSA_E, sizeof TA546_RSA_E); + trust_anchors[547] = make_rsa_trust_anchor((unsigned char *)TA547_DN, sizeof TA547_DN, (unsigned char *)TA547_RSA_N, sizeof TA547_RSA_N, (unsigned char *)TA547_RSA_E, sizeof TA547_RSA_E); + trust_anchors[548] = make_ec_trust_anchor((unsigned char *)TA548_DN, sizeof TA548_DN, BR_EC_secp384r1, (unsigned char *)TA548_EC_Q, sizeof TA548_EC_Q); + trust_anchors[549] = make_rsa_trust_anchor((unsigned char *)TA549_DN, sizeof TA549_DN, (unsigned char *)TA549_RSA_N, sizeof TA549_RSA_N, (unsigned char *)TA549_RSA_E, sizeof TA549_RSA_E); + trust_anchors[550] = make_rsa_trust_anchor((unsigned char *)TA550_DN, sizeof TA550_DN, (unsigned char *)TA550_RSA_N, sizeof TA550_RSA_N, (unsigned char *)TA550_RSA_E, sizeof TA550_RSA_E); + trust_anchors[551] = make_rsa_trust_anchor((unsigned char *)TA551_DN, sizeof TA551_DN, (unsigned char *)TA551_RSA_N, sizeof TA551_RSA_N, (unsigned char *)TA551_RSA_E, sizeof TA551_RSA_E); + trust_anchors[552] = make_ec_trust_anchor((unsigned char *)TA552_DN, sizeof TA552_DN, BR_EC_secp384r1, (unsigned char *)TA552_EC_Q, sizeof TA552_EC_Q); + trust_anchors[553] = make_rsa_trust_anchor((unsigned char *)TA553_DN, sizeof TA553_DN, (unsigned char *)TA553_RSA_N, sizeof TA553_RSA_N, (unsigned char *)TA553_RSA_E, sizeof TA553_RSA_E); + trust_anchors[554] = make_rsa_trust_anchor((unsigned char *)TA554_DN, sizeof TA554_DN, (unsigned char *)TA554_RSA_N, sizeof TA554_RSA_N, (unsigned char *)TA554_RSA_E, sizeof TA554_RSA_E); + trust_anchors[555] = make_rsa_trust_anchor((unsigned char *)TA555_DN, sizeof TA555_DN, (unsigned char *)TA555_RSA_N, sizeof TA555_RSA_N, (unsigned char *)TA555_RSA_E, sizeof TA555_RSA_E); + trust_anchors[556] = make_rsa_trust_anchor((unsigned char *)TA556_DN, sizeof TA556_DN, (unsigned char *)TA556_RSA_N, sizeof TA556_RSA_N, (unsigned char *)TA556_RSA_E, sizeof TA556_RSA_E); + trust_anchors[557] = make_rsa_trust_anchor((unsigned char *)TA557_DN, sizeof TA557_DN, (unsigned char *)TA557_RSA_N, sizeof TA557_RSA_N, (unsigned char *)TA557_RSA_E, sizeof TA557_RSA_E); + trust_anchors[558] = make_ec_trust_anchor((unsigned char *)TA558_DN, sizeof TA558_DN, BR_EC_secp384r1, (unsigned char *)TA558_EC_Q, sizeof TA558_EC_Q); + trust_anchors[559] = make_rsa_trust_anchor((unsigned char *)TA559_DN, sizeof TA559_DN, (unsigned char *)TA559_RSA_N, sizeof TA559_RSA_N, (unsigned char *)TA559_RSA_E, sizeof TA559_RSA_E); + trust_anchors[560] = make_rsa_trust_anchor((unsigned char *)TA560_DN, sizeof TA560_DN, (unsigned char *)TA560_RSA_N, sizeof TA560_RSA_N, (unsigned char *)TA560_RSA_E, sizeof TA560_RSA_E); + trust_anchors[561] = make_rsa_trust_anchor((unsigned char *)TA561_DN, sizeof TA561_DN, (unsigned char *)TA561_RSA_N, sizeof TA561_RSA_N, (unsigned char *)TA561_RSA_E, sizeof TA561_RSA_E); + trust_anchors[562] = make_rsa_trust_anchor((unsigned char *)TA562_DN, sizeof TA562_DN, (unsigned char *)TA562_RSA_N, sizeof TA562_RSA_N, (unsigned char *)TA562_RSA_E, sizeof TA562_RSA_E); + trust_anchors[563] = make_rsa_trust_anchor((unsigned char *)TA563_DN, sizeof TA563_DN, (unsigned char *)TA563_RSA_N, sizeof TA563_RSA_N, (unsigned char *)TA563_RSA_E, sizeof TA563_RSA_E); + trust_anchors[564] = make_ec_trust_anchor((unsigned char *)TA564_DN, sizeof TA564_DN, BR_EC_secp384r1, (unsigned char *)TA564_EC_Q, sizeof TA564_EC_Q); + trust_anchors[565] = make_ec_trust_anchor((unsigned char *)TA565_DN, sizeof TA565_DN, BR_EC_secp384r1, (unsigned char *)TA565_EC_Q, sizeof TA565_EC_Q); + trust_anchors[566] = make_rsa_trust_anchor((unsigned char *)TA566_DN, sizeof TA566_DN, (unsigned char *)TA566_RSA_N, sizeof TA566_RSA_N, (unsigned char *)TA566_RSA_E, sizeof TA566_RSA_E); + trust_anchors[567] = make_rsa_trust_anchor((unsigned char *)TA567_DN, sizeof TA567_DN, (unsigned char *)TA567_RSA_N, sizeof TA567_RSA_N, (unsigned char *)TA567_RSA_E, sizeof TA567_RSA_E); + trust_anchors[568] = make_rsa_trust_anchor((unsigned char *)TA568_DN, sizeof TA568_DN, (unsigned char *)TA568_RSA_N, sizeof TA568_RSA_N, (unsigned char *)TA568_RSA_E, sizeof TA568_RSA_E); + trust_anchors[569] = make_rsa_trust_anchor((unsigned char *)TA569_DN, sizeof TA569_DN, (unsigned char *)TA569_RSA_N, sizeof TA569_RSA_N, (unsigned char *)TA569_RSA_E, sizeof TA569_RSA_E); + trust_anchors[570] = make_ec_trust_anchor((unsigned char *)TA570_DN, sizeof TA570_DN, BR_EC_secp384r1, (unsigned char *)TA570_EC_Q, sizeof TA570_EC_Q); + trust_anchors[571] = make_rsa_trust_anchor((unsigned char *)TA571_DN, sizeof TA571_DN, (unsigned char *)TA571_RSA_N, sizeof TA571_RSA_N, (unsigned char *)TA571_RSA_E, sizeof TA571_RSA_E); + trust_anchors[572] = make_rsa_trust_anchor((unsigned char *)TA572_DN, sizeof TA572_DN, (unsigned char *)TA572_RSA_N, sizeof TA572_RSA_N, (unsigned char *)TA572_RSA_E, sizeof TA572_RSA_E); + trust_anchors[573] = make_rsa_trust_anchor((unsigned char *)TA573_DN, sizeof TA573_DN, (unsigned char *)TA573_RSA_N, sizeof TA573_RSA_N, (unsigned char *)TA573_RSA_E, sizeof TA573_RSA_E); + trust_anchors[574] = make_rsa_trust_anchor((unsigned char *)TA574_DN, sizeof TA574_DN, (unsigned char *)TA574_RSA_N, sizeof TA574_RSA_N, (unsigned char *)TA574_RSA_E, sizeof TA574_RSA_E); + trust_anchors[575] = make_rsa_trust_anchor((unsigned char *)TA575_DN, sizeof TA575_DN, (unsigned char *)TA575_RSA_N, sizeof TA575_RSA_N, (unsigned char *)TA575_RSA_E, sizeof TA575_RSA_E); + trust_anchors[576] = make_ec_trust_anchor((unsigned char *)TA576_DN, sizeof TA576_DN, BR_EC_secp384r1, (unsigned char *)TA576_EC_Q, sizeof TA576_EC_Q); + trust_anchors[577] = make_rsa_trust_anchor((unsigned char *)TA577_DN, sizeof TA577_DN, (unsigned char *)TA577_RSA_N, sizeof TA577_RSA_N, (unsigned char *)TA577_RSA_E, sizeof TA577_RSA_E); + trust_anchors[578] = make_rsa_trust_anchor((unsigned char *)TA578_DN, sizeof TA578_DN, (unsigned char *)TA578_RSA_N, sizeof TA578_RSA_N, (unsigned char *)TA578_RSA_E, sizeof TA578_RSA_E); + trust_anchors[579] = make_rsa_trust_anchor((unsigned char *)TA579_DN, sizeof TA579_DN, (unsigned char *)TA579_RSA_N, sizeof TA579_RSA_N, (unsigned char *)TA579_RSA_E, sizeof TA579_RSA_E); + trust_anchors[580] = make_rsa_trust_anchor((unsigned char *)TA580_DN, sizeof TA580_DN, (unsigned char *)TA580_RSA_N, sizeof TA580_RSA_N, (unsigned char *)TA580_RSA_E, sizeof TA580_RSA_E); + trust_anchors[581] = make_rsa_trust_anchor((unsigned char *)TA581_DN, sizeof TA581_DN, (unsigned char *)TA581_RSA_N, sizeof TA581_RSA_N, (unsigned char *)TA581_RSA_E, sizeof TA581_RSA_E); + trust_anchors[582] = make_rsa_trust_anchor((unsigned char *)TA582_DN, sizeof TA582_DN, (unsigned char *)TA582_RSA_N, sizeof TA582_RSA_N, (unsigned char *)TA582_RSA_E, sizeof TA582_RSA_E); + trust_anchors[583] = make_rsa_trust_anchor((unsigned char *)TA583_DN, sizeof TA583_DN, (unsigned char *)TA583_RSA_N, sizeof TA583_RSA_N, (unsigned char *)TA583_RSA_E, sizeof TA583_RSA_E); + trust_anchors[584] = make_ec_trust_anchor((unsigned char *)TA584_DN, sizeof TA584_DN, BR_EC_secp384r1, (unsigned char *)TA584_EC_Q, sizeof TA584_EC_Q); + trust_anchors[585] = make_rsa_trust_anchor((unsigned char *)TA585_DN, sizeof TA585_DN, (unsigned char *)TA585_RSA_N, sizeof TA585_RSA_N, (unsigned char *)TA585_RSA_E, sizeof TA585_RSA_E); + trust_anchors[586] = make_ec_trust_anchor((unsigned char *)TA586_DN, sizeof TA586_DN, BR_EC_secp384r1, (unsigned char *)TA586_EC_Q, sizeof TA586_EC_Q); + trust_anchors[587] = make_rsa_trust_anchor((unsigned char *)TA587_DN, sizeof TA587_DN, (unsigned char *)TA587_RSA_N, sizeof TA587_RSA_N, (unsigned char *)TA587_RSA_E, sizeof TA587_RSA_E); + trust_anchors[588] = make_rsa_trust_anchor((unsigned char *)TA588_DN, sizeof TA588_DN, (unsigned char *)TA588_RSA_N, sizeof TA588_RSA_N, (unsigned char *)TA588_RSA_E, sizeof TA588_RSA_E); + trust_anchors[589] = make_rsa_trust_anchor((unsigned char *)TA589_DN, sizeof TA589_DN, (unsigned char *)TA589_RSA_N, sizeof TA589_RSA_N, (unsigned char *)TA589_RSA_E, sizeof TA589_RSA_E); + trust_anchors[590] = make_rsa_trust_anchor((unsigned char *)TA590_DN, sizeof TA590_DN, (unsigned char *)TA590_RSA_N, sizeof TA590_RSA_N, (unsigned char *)TA590_RSA_E, sizeof TA590_RSA_E); + trust_anchors[591] = make_rsa_trust_anchor((unsigned char *)TA591_DN, sizeof TA591_DN, (unsigned char *)TA591_RSA_N, sizeof TA591_RSA_N, (unsigned char *)TA591_RSA_E, sizeof TA591_RSA_E); + trust_anchors[592] = make_ec_trust_anchor((unsigned char *)TA592_DN, sizeof TA592_DN, BR_EC_secp384r1, (unsigned char *)TA592_EC_Q, sizeof TA592_EC_Q); + trust_anchors[593] = make_ec_trust_anchor((unsigned char *)TA593_DN, sizeof TA593_DN, BR_EC_secp384r1, (unsigned char *)TA593_EC_Q, sizeof TA593_EC_Q); + trust_anchors[594] = make_ec_trust_anchor((unsigned char *)TA594_DN, sizeof TA594_DN, BR_EC_secp384r1, (unsigned char *)TA594_EC_Q, sizeof TA594_EC_Q); + trust_anchors[595] = make_rsa_trust_anchor((unsigned char *)TA595_DN, sizeof TA595_DN, (unsigned char *)TA595_RSA_N, sizeof TA595_RSA_N, (unsigned char *)TA595_RSA_E, sizeof TA595_RSA_E); + trust_anchors[596] = make_rsa_trust_anchor((unsigned char *)TA596_DN, sizeof TA596_DN, (unsigned char *)TA596_RSA_N, sizeof TA596_RSA_N, (unsigned char *)TA596_RSA_E, sizeof TA596_RSA_E); + trust_anchors[597] = make_rsa_trust_anchor((unsigned char *)TA597_DN, sizeof TA597_DN, (unsigned char *)TA597_RSA_N, sizeof TA597_RSA_N, (unsigned char *)TA597_RSA_E, sizeof TA597_RSA_E); + trust_anchors[598] = make_ec_trust_anchor((unsigned char *)TA598_DN, sizeof TA598_DN, BR_EC_secp384r1, (unsigned char *)TA598_EC_Q, sizeof TA598_EC_Q); + trust_anchors[599] = make_rsa_trust_anchor((unsigned char *)TA599_DN, sizeof TA599_DN, (unsigned char *)TA599_RSA_N, sizeof TA599_RSA_N, (unsigned char *)TA599_RSA_E, sizeof TA599_RSA_E); + trust_anchors[600] = make_rsa_trust_anchor((unsigned char *)TA600_DN, sizeof TA600_DN, (unsigned char *)TA600_RSA_N, sizeof TA600_RSA_N, (unsigned char *)TA600_RSA_E, sizeof TA600_RSA_E); + trust_anchors[601] = make_ec_trust_anchor((unsigned char *)TA601_DN, sizeof TA601_DN, BR_EC_secp384r1, (unsigned char *)TA601_EC_Q, sizeof TA601_EC_Q); + trust_anchors[602] = make_rsa_trust_anchor((unsigned char *)TA602_DN, sizeof TA602_DN, (unsigned char *)TA602_RSA_N, sizeof TA602_RSA_N, (unsigned char *)TA602_RSA_E, sizeof TA602_RSA_E); + trust_anchors[603] = make_ec_trust_anchor((unsigned char *)TA603_DN, sizeof TA603_DN, BR_EC_secp384r1, (unsigned char *)TA603_EC_Q, sizeof TA603_EC_Q); + trust_anchors[604] = make_rsa_trust_anchor((unsigned char *)TA604_DN, sizeof TA604_DN, (unsigned char *)TA604_RSA_N, sizeof TA604_RSA_N, (unsigned char *)TA604_RSA_E, sizeof TA604_RSA_E); + trust_anchors[605] = make_rsa_trust_anchor((unsigned char *)TA605_DN, sizeof TA605_DN, (unsigned char *)TA605_RSA_N, sizeof TA605_RSA_N, (unsigned char *)TA605_RSA_E, sizeof TA605_RSA_E); + trust_anchors[606] = make_ec_trust_anchor((unsigned char *)TA606_DN, sizeof TA606_DN, BR_EC_secp384r1, (unsigned char *)TA606_EC_Q, sizeof TA606_EC_Q); + trust_anchors[607] = make_rsa_trust_anchor((unsigned char *)TA607_DN, sizeof TA607_DN, (unsigned char *)TA607_RSA_N, sizeof TA607_RSA_N, (unsigned char *)TA607_RSA_E, sizeof TA607_RSA_E); + trust_anchors[608] = make_ec_trust_anchor((unsigned char *)TA608_DN, sizeof TA608_DN, BR_EC_secp384r1, (unsigned char *)TA608_EC_Q, sizeof TA608_EC_Q); + trust_anchors[609] = make_rsa_trust_anchor((unsigned char *)TA609_DN, sizeof TA609_DN, (unsigned char *)TA609_RSA_N, sizeof TA609_RSA_N, (unsigned char *)TA609_RSA_E, sizeof TA609_RSA_E); + trust_anchors[610] = make_rsa_trust_anchor((unsigned char *)TA610_DN, sizeof TA610_DN, (unsigned char *)TA610_RSA_N, sizeof TA610_RSA_N, (unsigned char *)TA610_RSA_E, sizeof TA610_RSA_E); + trust_anchors[611] = make_rsa_trust_anchor((unsigned char *)TA611_DN, sizeof TA611_DN, (unsigned char *)TA611_RSA_N, sizeof TA611_RSA_N, (unsigned char *)TA611_RSA_E, sizeof TA611_RSA_E); + trust_anchors[612] = make_rsa_trust_anchor((unsigned char *)TA612_DN, sizeof TA612_DN, (unsigned char *)TA612_RSA_N, sizeof TA612_RSA_N, (unsigned char *)TA612_RSA_E, sizeof TA612_RSA_E); + trust_anchors[613] = make_rsa_trust_anchor((unsigned char *)TA613_DN, sizeof TA613_DN, (unsigned char *)TA613_RSA_N, sizeof TA613_RSA_N, (unsigned char *)TA613_RSA_E, sizeof TA613_RSA_E); + trust_anchors[614] = make_rsa_trust_anchor((unsigned char *)TA614_DN, sizeof TA614_DN, (unsigned char *)TA614_RSA_N, sizeof TA614_RSA_N, (unsigned char *)TA614_RSA_E, sizeof TA614_RSA_E); + trust_anchors[615] = make_rsa_trust_anchor((unsigned char *)TA615_DN, sizeof TA615_DN, (unsigned char *)TA615_RSA_N, sizeof TA615_RSA_N, (unsigned char *)TA615_RSA_E, sizeof TA615_RSA_E); + trust_anchors[616] = make_rsa_trust_anchor((unsigned char *)TA616_DN, sizeof TA616_DN, (unsigned char *)TA616_RSA_N, sizeof TA616_RSA_N, (unsigned char *)TA616_RSA_E, sizeof TA616_RSA_E); + trust_anchors[617] = make_rsa_trust_anchor((unsigned char *)TA617_DN, sizeof TA617_DN, (unsigned char *)TA617_RSA_N, sizeof TA617_RSA_N, (unsigned char *)TA617_RSA_E, sizeof TA617_RSA_E); + trust_anchors[618] = make_rsa_trust_anchor((unsigned char *)TA618_DN, sizeof TA618_DN, (unsigned char *)TA618_RSA_N, sizeof TA618_RSA_N, (unsigned char *)TA618_RSA_E, sizeof TA618_RSA_E); + trust_anchors[619] = make_rsa_trust_anchor((unsigned char *)TA619_DN, sizeof TA619_DN, (unsigned char *)TA619_RSA_N, sizeof TA619_RSA_N, (unsigned char *)TA619_RSA_E, sizeof TA619_RSA_E); + trust_anchors[620] = make_rsa_trust_anchor((unsigned char *)TA620_DN, sizeof TA620_DN, (unsigned char *)TA620_RSA_N, sizeof TA620_RSA_N, (unsigned char *)TA620_RSA_E, sizeof TA620_RSA_E); + trust_anchors[621] = make_ec_trust_anchor((unsigned char *)TA621_DN, sizeof TA621_DN, BR_EC_secp384r1, (unsigned char *)TA621_EC_Q, sizeof TA621_EC_Q); + trust_anchors[622] = make_rsa_trust_anchor((unsigned char *)TA622_DN, sizeof TA622_DN, (unsigned char *)TA622_RSA_N, sizeof TA622_RSA_N, (unsigned char *)TA622_RSA_E, sizeof TA622_RSA_E); + trust_anchors[623] = make_rsa_trust_anchor((unsigned char *)TA623_DN, sizeof TA623_DN, (unsigned char *)TA623_RSA_N, sizeof TA623_RSA_N, (unsigned char *)TA623_RSA_E, sizeof TA623_RSA_E); + trust_anchors[624] = make_ec_trust_anchor((unsigned char *)TA624_DN, sizeof TA624_DN, BR_EC_secp256r1, (unsigned char *)TA624_EC_Q, sizeof TA624_EC_Q); + trust_anchors[625] = make_rsa_trust_anchor((unsigned char *)TA625_DN, sizeof TA625_DN, (unsigned char *)TA625_RSA_N, sizeof TA625_RSA_N, (unsigned char *)TA625_RSA_E, sizeof TA625_RSA_E); + trust_anchors[626] = make_ec_trust_anchor((unsigned char *)TA626_DN, sizeof TA626_DN, BR_EC_secp384r1, (unsigned char *)TA626_EC_Q, sizeof TA626_EC_Q); + trust_anchors[627] = make_ec_trust_anchor((unsigned char *)TA627_DN, sizeof TA627_DN, BR_EC_secp384r1, (unsigned char *)TA627_EC_Q, sizeof TA627_EC_Q); + trust_anchors[628] = make_ec_trust_anchor((unsigned char *)TA628_DN, sizeof TA628_DN, BR_EC_secp384r1, (unsigned char *)TA628_EC_Q, sizeof TA628_EC_Q); + trust_anchors[629] = make_rsa_trust_anchor((unsigned char *)TA629_DN, sizeof TA629_DN, (unsigned char *)TA629_RSA_N, sizeof TA629_RSA_N, (unsigned char *)TA629_RSA_E, sizeof TA629_RSA_E); + trust_anchors[630] = make_rsa_trust_anchor((unsigned char *)TA630_DN, sizeof TA630_DN, (unsigned char *)TA630_RSA_N, sizeof TA630_RSA_N, (unsigned char *)TA630_RSA_E, sizeof TA630_RSA_E); + trust_anchors[631] = make_ec_trust_anchor((unsigned char *)TA631_DN, sizeof TA631_DN, BR_EC_secp384r1, (unsigned char *)TA631_EC_Q, sizeof TA631_EC_Q); + trust_anchors[632] = make_rsa_trust_anchor((unsigned char *)TA632_DN, sizeof TA632_DN, (unsigned char *)TA632_RSA_N, sizeof TA632_RSA_N, (unsigned char *)TA632_RSA_E, sizeof TA632_RSA_E); + trust_anchors[633] = make_ec_trust_anchor((unsigned char *)TA633_DN, sizeof TA633_DN, BR_EC_secp384r1, (unsigned char *)TA633_EC_Q, sizeof TA633_EC_Q); + trust_anchors[634] = make_rsa_trust_anchor((unsigned char *)TA634_DN, sizeof TA634_DN, (unsigned char *)TA634_RSA_N, sizeof TA634_RSA_N, (unsigned char *)TA634_RSA_E, sizeof TA634_RSA_E); + trust_anchors[635] = make_ec_trust_anchor((unsigned char *)TA635_DN, sizeof TA635_DN, BR_EC_secp384r1, (unsigned char *)TA635_EC_Q, sizeof TA635_EC_Q); + trust_anchors[636] = make_ec_trust_anchor((unsigned char *)TA636_DN, sizeof TA636_DN, BR_EC_secp384r1, (unsigned char *)TA636_EC_Q, sizeof TA636_EC_Q); + trust_anchors[637] = make_rsa_trust_anchor((unsigned char *)TA637_DN, sizeof TA637_DN, (unsigned char *)TA637_RSA_N, sizeof TA637_RSA_N, (unsigned char *)TA637_RSA_E, sizeof TA637_RSA_E); + trust_anchors[638] = make_rsa_trust_anchor((unsigned char *)TA638_DN, sizeof TA638_DN, (unsigned char *)TA638_RSA_N, sizeof TA638_RSA_N, (unsigned char *)TA638_RSA_E, sizeof TA638_RSA_E); + trust_anchors[639] = make_rsa_trust_anchor((unsigned char *)TA639_DN, sizeof TA639_DN, (unsigned char *)TA639_RSA_N, sizeof TA639_RSA_N, (unsigned char *)TA639_RSA_E, sizeof TA639_RSA_E); + trust_anchors[640] = make_ec_trust_anchor((unsigned char *)TA640_DN, sizeof TA640_DN, BR_EC_secp384r1, (unsigned char *)TA640_EC_Q, sizeof TA640_EC_Q); + trust_anchors[641] = make_rsa_trust_anchor((unsigned char *)TA641_DN, sizeof TA641_DN, (unsigned char *)TA641_RSA_N, sizeof TA641_RSA_N, (unsigned char *)TA641_RSA_E, sizeof TA641_RSA_E); + trust_anchors[642] = make_rsa_trust_anchor((unsigned char *)TA642_DN, sizeof TA642_DN, (unsigned char *)TA642_RSA_N, sizeof TA642_RSA_N, (unsigned char *)TA642_RSA_E, sizeof TA642_RSA_E); + trust_anchors[643] = make_rsa_trust_anchor((unsigned char *)TA643_DN, sizeof TA643_DN, (unsigned char *)TA643_RSA_N, sizeof TA643_RSA_N, (unsigned char *)TA643_RSA_E, sizeof TA643_RSA_E); + trust_anchors[644] = make_ec_trust_anchor((unsigned char *)TA644_DN, sizeof TA644_DN, BR_EC_secp256r1, (unsigned char *)TA644_EC_Q, sizeof TA644_EC_Q); + trust_anchors[645] = make_rsa_trust_anchor((unsigned char *)TA645_DN, sizeof TA645_DN, (unsigned char *)TA645_RSA_N, sizeof TA645_RSA_N, (unsigned char *)TA645_RSA_E, sizeof TA645_RSA_E); + trust_anchors[646] = make_rsa_trust_anchor((unsigned char *)TA646_DN, sizeof TA646_DN, (unsigned char *)TA646_RSA_N, sizeof TA646_RSA_N, (unsigned char *)TA646_RSA_E, sizeof TA646_RSA_E); + trust_anchors[647] = make_rsa_trust_anchor((unsigned char *)TA647_DN, sizeof TA647_DN, (unsigned char *)TA647_RSA_N, sizeof TA647_RSA_N, (unsigned char *)TA647_RSA_E, sizeof TA647_RSA_E); + trust_anchors[648] = make_ec_trust_anchor((unsigned char *)TA648_DN, sizeof TA648_DN, BR_EC_secp384r1, (unsigned char *)TA648_EC_Q, sizeof TA648_EC_Q); + trust_anchors[649] = make_rsa_trust_anchor((unsigned char *)TA649_DN, sizeof TA649_DN, (unsigned char *)TA649_RSA_N, sizeof TA649_RSA_N, (unsigned char *)TA649_RSA_E, sizeof TA649_RSA_E); + trust_anchors[650] = make_ec_trust_anchor((unsigned char *)TA650_DN, sizeof TA650_DN, BR_EC_secp384r1, (unsigned char *)TA650_EC_Q, sizeof TA650_EC_Q); + trust_anchors[651] = make_rsa_trust_anchor((unsigned char *)TA651_DN, sizeof TA651_DN, (unsigned char *)TA651_RSA_N, sizeof TA651_RSA_N, (unsigned char *)TA651_RSA_E, sizeof TA651_RSA_E); + trust_anchors[652] = make_rsa_trust_anchor((unsigned char *)TA652_DN, sizeof TA652_DN, (unsigned char *)TA652_RSA_N, sizeof TA652_RSA_N, (unsigned char *)TA652_RSA_E, sizeof TA652_RSA_E); + trust_anchors[653] = make_rsa_trust_anchor((unsigned char *)TA653_DN, sizeof TA653_DN, (unsigned char *)TA653_RSA_N, sizeof TA653_RSA_N, (unsigned char *)TA653_RSA_E, sizeof TA653_RSA_E); + trust_anchors[654] = make_rsa_trust_anchor((unsigned char *)TA654_DN, sizeof TA654_DN, (unsigned char *)TA654_RSA_N, sizeof TA654_RSA_N, (unsigned char *)TA654_RSA_E, sizeof TA654_RSA_E); + trust_anchors[655] = make_rsa_trust_anchor((unsigned char *)TA655_DN, sizeof TA655_DN, (unsigned char *)TA655_RSA_N, sizeof TA655_RSA_N, (unsigned char *)TA655_RSA_E, sizeof TA655_RSA_E); + trust_anchors[656] = make_rsa_trust_anchor((unsigned char *)TA656_DN, sizeof TA656_DN, (unsigned char *)TA656_RSA_N, sizeof TA656_RSA_N, (unsigned char *)TA656_RSA_E, sizeof TA656_RSA_E); + trust_anchors[657] = make_rsa_trust_anchor((unsigned char *)TA657_DN, sizeof TA657_DN, (unsigned char *)TA657_RSA_N, sizeof TA657_RSA_N, (unsigned char *)TA657_RSA_E, sizeof TA657_RSA_E); + trust_anchors[658] = make_ec_trust_anchor((unsigned char *)TA658_DN, sizeof TA658_DN, BR_EC_secp384r1, (unsigned char *)TA658_EC_Q, sizeof TA658_EC_Q); + trust_anchors[659] = make_rsa_trust_anchor((unsigned char *)TA659_DN, sizeof TA659_DN, (unsigned char *)TA659_RSA_N, sizeof TA659_RSA_N, (unsigned char *)TA659_RSA_E, sizeof TA659_RSA_E); + trust_anchors[660] = make_rsa_trust_anchor((unsigned char *)TA660_DN, sizeof TA660_DN, (unsigned char *)TA660_RSA_N, sizeof TA660_RSA_N, (unsigned char *)TA660_RSA_E, sizeof TA660_RSA_E); + trust_anchors[661] = make_rsa_trust_anchor((unsigned char *)TA661_DN, sizeof TA661_DN, (unsigned char *)TA661_RSA_N, sizeof TA661_RSA_N, (unsigned char *)TA661_RSA_E, sizeof TA661_RSA_E); + trust_anchors[662] = make_rsa_trust_anchor((unsigned char *)TA662_DN, sizeof TA662_DN, (unsigned char *)TA662_RSA_N, sizeof TA662_RSA_N, (unsigned char *)TA662_RSA_E, sizeof TA662_RSA_E); + trust_anchors[663] = make_rsa_trust_anchor((unsigned char *)TA663_DN, sizeof TA663_DN, (unsigned char *)TA663_RSA_N, sizeof TA663_RSA_N, (unsigned char *)TA663_RSA_E, sizeof TA663_RSA_E); + trust_anchors[664] = make_ec_trust_anchor((unsigned char *)TA664_DN, sizeof TA664_DN, BR_EC_secp384r1, (unsigned char *)TA664_EC_Q, sizeof TA664_EC_Q); + trust_anchors[665] = make_rsa_trust_anchor((unsigned char *)TA665_DN, sizeof TA665_DN, (unsigned char *)TA665_RSA_N, sizeof TA665_RSA_N, (unsigned char *)TA665_RSA_E, sizeof TA665_RSA_E); + trust_anchors[666] = make_rsa_trust_anchor((unsigned char *)TA666_DN, sizeof TA666_DN, (unsigned char *)TA666_RSA_N, sizeof TA666_RSA_N, (unsigned char *)TA666_RSA_E, sizeof TA666_RSA_E); + trust_anchors[667] = make_rsa_trust_anchor((unsigned char *)TA667_DN, sizeof TA667_DN, (unsigned char *)TA667_RSA_N, sizeof TA667_RSA_N, (unsigned char *)TA667_RSA_E, sizeof TA667_RSA_E); + trust_anchors[668] = make_ec_trust_anchor((unsigned char *)TA668_DN, sizeof TA668_DN, BR_EC_secp384r1, (unsigned char *)TA668_EC_Q, sizeof TA668_EC_Q); + trust_anchors[669] = make_rsa_trust_anchor((unsigned char *)TA669_DN, sizeof TA669_DN, (unsigned char *)TA669_RSA_N, sizeof TA669_RSA_N, (unsigned char *)TA669_RSA_E, sizeof TA669_RSA_E); + trust_anchors[670] = make_ec_trust_anchor((unsigned char *)TA670_DN, sizeof TA670_DN, BR_EC_secp256r1, (unsigned char *)TA670_EC_Q, sizeof TA670_EC_Q); + trust_anchors[671] = make_ec_trust_anchor((unsigned char *)TA671_DN, sizeof TA671_DN, BR_EC_secp384r1, (unsigned char *)TA671_EC_Q, sizeof TA671_EC_Q); + trust_anchors[672] = make_rsa_trust_anchor((unsigned char *)TA672_DN, sizeof TA672_DN, (unsigned char *)TA672_RSA_N, sizeof TA672_RSA_N, (unsigned char *)TA672_RSA_E, sizeof TA672_RSA_E); + trust_anchors[673] = make_rsa_trust_anchor((unsigned char *)TA673_DN, sizeof TA673_DN, (unsigned char *)TA673_RSA_N, sizeof TA673_RSA_N, (unsigned char *)TA673_RSA_E, sizeof TA673_RSA_E); + trust_anchors[674] = make_rsa_trust_anchor((unsigned char *)TA674_DN, sizeof TA674_DN, (unsigned char *)TA674_RSA_N, sizeof TA674_RSA_N, (unsigned char *)TA674_RSA_E, sizeof TA674_RSA_E); + trust_anchors[675] = make_ec_trust_anchor((unsigned char *)TA675_DN, sizeof TA675_DN, BR_EC_secp384r1, (unsigned char *)TA675_EC_Q, sizeof TA675_EC_Q); + trust_anchors[676] = make_rsa_trust_anchor((unsigned char *)TA676_DN, sizeof TA676_DN, (unsigned char *)TA676_RSA_N, sizeof TA676_RSA_N, (unsigned char *)TA676_RSA_E, sizeof TA676_RSA_E); + trust_anchors[677] = make_rsa_trust_anchor((unsigned char *)TA677_DN, sizeof TA677_DN, (unsigned char *)TA677_RSA_N, sizeof TA677_RSA_N, (unsigned char *)TA677_RSA_E, sizeof TA677_RSA_E); + trust_anchors[678] = make_rsa_trust_anchor((unsigned char *)TA678_DN, sizeof TA678_DN, (unsigned char *)TA678_RSA_N, sizeof TA678_RSA_N, (unsigned char *)TA678_RSA_E, sizeof TA678_RSA_E); + trust_anchors[679] = make_rsa_trust_anchor((unsigned char *)TA679_DN, sizeof TA679_DN, (unsigned char *)TA679_RSA_N, sizeof TA679_RSA_N, (unsigned char *)TA679_RSA_E, sizeof TA679_RSA_E); + trust_anchors[680] = make_rsa_trust_anchor((unsigned char *)TA680_DN, sizeof TA680_DN, (unsigned char *)TA680_RSA_N, sizeof TA680_RSA_N, (unsigned char *)TA680_RSA_E, sizeof TA680_RSA_E); + trust_anchors[681] = make_rsa_trust_anchor((unsigned char *)TA681_DN, sizeof TA681_DN, (unsigned char *)TA681_RSA_N, sizeof TA681_RSA_N, (unsigned char *)TA681_RSA_E, sizeof TA681_RSA_E); + trust_anchors[682] = make_ec_trust_anchor((unsigned char *)TA682_DN, sizeof TA682_DN, BR_EC_secp384r1, (unsigned char *)TA682_EC_Q, sizeof TA682_EC_Q); + trust_anchors[683] = make_ec_trust_anchor((unsigned char *)TA683_DN, sizeof TA683_DN, BR_EC_secp384r1, (unsigned char *)TA683_EC_Q, sizeof TA683_EC_Q); + trust_anchors[684] = make_ec_trust_anchor((unsigned char *)TA684_DN, sizeof TA684_DN, BR_EC_secp384r1, (unsigned char *)TA684_EC_Q, sizeof TA684_EC_Q); + trust_anchors[685] = make_rsa_trust_anchor((unsigned char *)TA685_DN, sizeof TA685_DN, (unsigned char *)TA685_RSA_N, sizeof TA685_RSA_N, (unsigned char *)TA685_RSA_E, sizeof TA685_RSA_E); + trust_anchors[686] = make_ec_trust_anchor((unsigned char *)TA686_DN, sizeof TA686_DN, BR_EC_secp384r1, (unsigned char *)TA686_EC_Q, sizeof TA686_EC_Q); + trust_anchors[687] = make_rsa_trust_anchor((unsigned char *)TA687_DN, sizeof TA687_DN, (unsigned char *)TA687_RSA_N, sizeof TA687_RSA_N, (unsigned char *)TA687_RSA_E, sizeof TA687_RSA_E); + trust_anchors[688] = make_rsa_trust_anchor((unsigned char *)TA688_DN, sizeof TA688_DN, (unsigned char *)TA688_RSA_N, sizeof TA688_RSA_N, (unsigned char *)TA688_RSA_E, sizeof TA688_RSA_E); + trust_anchors[689] = make_rsa_trust_anchor((unsigned char *)TA689_DN, sizeof TA689_DN, (unsigned char *)TA689_RSA_N, sizeof TA689_RSA_N, (unsigned char *)TA689_RSA_E, sizeof TA689_RSA_E); + trust_anchors[690] = make_rsa_trust_anchor((unsigned char *)TA690_DN, sizeof TA690_DN, (unsigned char *)TA690_RSA_N, sizeof TA690_RSA_N, (unsigned char *)TA690_RSA_E, sizeof TA690_RSA_E); + trust_anchors[691] = make_rsa_trust_anchor((unsigned char *)TA691_DN, sizeof TA691_DN, (unsigned char *)TA691_RSA_N, sizeof TA691_RSA_N, (unsigned char *)TA691_RSA_E, sizeof TA691_RSA_E); + trust_anchors[692] = make_rsa_trust_anchor((unsigned char *)TA692_DN, sizeof TA692_DN, (unsigned char *)TA692_RSA_N, sizeof TA692_RSA_N, (unsigned char *)TA692_RSA_E, sizeof TA692_RSA_E); + trust_anchors[693] = make_ec_trust_anchor((unsigned char *)TA693_DN, sizeof TA693_DN, BR_EC_secp384r1, (unsigned char *)TA693_EC_Q, sizeof TA693_EC_Q); + trust_anchors[694] = make_rsa_trust_anchor((unsigned char *)TA694_DN, sizeof TA694_DN, (unsigned char *)TA694_RSA_N, sizeof TA694_RSA_N, (unsigned char *)TA694_RSA_E, sizeof TA694_RSA_E); + trust_anchors[695] = make_rsa_trust_anchor((unsigned char *)TA695_DN, sizeof TA695_DN, (unsigned char *)TA695_RSA_N, sizeof TA695_RSA_N, (unsigned char *)TA695_RSA_E, sizeof TA695_RSA_E); + trust_anchors[696] = make_ec_trust_anchor((unsigned char *)TA696_DN, sizeof TA696_DN, BR_EC_secp384r1, (unsigned char *)TA696_EC_Q, sizeof TA696_EC_Q); + trust_anchors[697] = make_rsa_trust_anchor((unsigned char *)TA697_DN, sizeof TA697_DN, (unsigned char *)TA697_RSA_N, sizeof TA697_RSA_N, (unsigned char *)TA697_RSA_E, sizeof TA697_RSA_E); + trust_anchors[698] = make_rsa_trust_anchor((unsigned char *)TA698_DN, sizeof TA698_DN, (unsigned char *)TA698_RSA_N, sizeof TA698_RSA_N, (unsigned char *)TA698_RSA_E, sizeof TA698_RSA_E); + trust_anchors[699] = make_rsa_trust_anchor((unsigned char *)TA699_DN, sizeof TA699_DN, (unsigned char *)TA699_RSA_N, sizeof TA699_RSA_N, (unsigned char *)TA699_RSA_E, sizeof TA699_RSA_E); + trust_anchors[700] = make_rsa_trust_anchor((unsigned char *)TA700_DN, sizeof TA700_DN, (unsigned char *)TA700_RSA_N, sizeof TA700_RSA_N, (unsigned char *)TA700_RSA_E, sizeof TA700_RSA_E); + trust_anchors[701] = make_ec_trust_anchor((unsigned char *)TA701_DN, sizeof TA701_DN, BR_EC_secp384r1, (unsigned char *)TA701_EC_Q, sizeof TA701_EC_Q); + trust_anchors[702] = make_rsa_trust_anchor((unsigned char *)TA702_DN, sizeof TA702_DN, (unsigned char *)TA702_RSA_N, sizeof TA702_RSA_N, (unsigned char *)TA702_RSA_E, sizeof TA702_RSA_E); + trust_anchors[703] = make_rsa_trust_anchor((unsigned char *)TA703_DN, sizeof TA703_DN, (unsigned char *)TA703_RSA_N, sizeof TA703_RSA_N, (unsigned char *)TA703_RSA_E, sizeof TA703_RSA_E); + trust_anchors[704] = make_rsa_trust_anchor((unsigned char *)TA704_DN, sizeof TA704_DN, (unsigned char *)TA704_RSA_N, sizeof TA704_RSA_N, (unsigned char *)TA704_RSA_E, sizeof TA704_RSA_E); + trust_anchors[705] = make_rsa_trust_anchor((unsigned char *)TA705_DN, sizeof TA705_DN, (unsigned char *)TA705_RSA_N, sizeof TA705_RSA_N, (unsigned char *)TA705_RSA_E, sizeof TA705_RSA_E); + trust_anchors[706] = make_rsa_trust_anchor((unsigned char *)TA706_DN, sizeof TA706_DN, (unsigned char *)TA706_RSA_N, sizeof TA706_RSA_N, (unsigned char *)TA706_RSA_E, sizeof TA706_RSA_E); + trust_anchors[707] = make_ec_trust_anchor((unsigned char *)TA707_DN, sizeof TA707_DN, BR_EC_secp384r1, (unsigned char *)TA707_EC_Q, sizeof TA707_EC_Q); + trust_anchors[708] = make_rsa_trust_anchor((unsigned char *)TA708_DN, sizeof TA708_DN, (unsigned char *)TA708_RSA_N, sizeof TA708_RSA_N, (unsigned char *)TA708_RSA_E, sizeof TA708_RSA_E); + trust_anchors[709] = make_rsa_trust_anchor((unsigned char *)TA709_DN, sizeof TA709_DN, (unsigned char *)TA709_RSA_N, sizeof TA709_RSA_N, (unsigned char *)TA709_RSA_E, sizeof TA709_RSA_E); + trust_anchors[710] = make_rsa_trust_anchor((unsigned char *)TA710_DN, sizeof TA710_DN, (unsigned char *)TA710_RSA_N, sizeof TA710_RSA_N, (unsigned char *)TA710_RSA_E, sizeof TA710_RSA_E); + trust_anchors[711] = make_rsa_trust_anchor((unsigned char *)TA711_DN, sizeof TA711_DN, (unsigned char *)TA711_RSA_N, sizeof TA711_RSA_N, (unsigned char *)TA711_RSA_E, sizeof TA711_RSA_E); + trust_anchors[712] = make_ec_trust_anchor((unsigned char *)TA712_DN, sizeof TA712_DN, BR_EC_secp384r1, (unsigned char *)TA712_EC_Q, sizeof TA712_EC_Q); + trust_anchors[713] = make_rsa_trust_anchor((unsigned char *)TA713_DN, sizeof TA713_DN, (unsigned char *)TA713_RSA_N, sizeof TA713_RSA_N, (unsigned char *)TA713_RSA_E, sizeof TA713_RSA_E); + trust_anchors[714] = make_ec_trust_anchor((unsigned char *)TA714_DN, sizeof TA714_DN, BR_EC_secp384r1, (unsigned char *)TA714_EC_Q, sizeof TA714_EC_Q); + trust_anchors[715] = make_rsa_trust_anchor((unsigned char *)TA715_DN, sizeof TA715_DN, (unsigned char *)TA715_RSA_N, sizeof TA715_RSA_N, (unsigned char *)TA715_RSA_E, sizeof TA715_RSA_E); + trust_anchors[716] = make_ec_trust_anchor((unsigned char *)TA716_DN, sizeof TA716_DN, BR_EC_secp384r1, (unsigned char *)TA716_EC_Q, sizeof TA716_EC_Q); + trust_anchors[717] = make_rsa_trust_anchor((unsigned char *)TA717_DN, sizeof TA717_DN, (unsigned char *)TA717_RSA_N, sizeof TA717_RSA_N, (unsigned char *)TA717_RSA_E, sizeof TA717_RSA_E); + trust_anchors[718] = make_ec_trust_anchor((unsigned char *)TA718_DN, sizeof TA718_DN, BR_EC_secp384r1, (unsigned char *)TA718_EC_Q, sizeof TA718_EC_Q); + trust_anchors[719] = make_rsa_trust_anchor((unsigned char *)TA719_DN, sizeof TA719_DN, (unsigned char *)TA719_RSA_N, sizeof TA719_RSA_N, (unsigned char *)TA719_RSA_E, sizeof TA719_RSA_E); + trust_anchors[720] = make_ec_trust_anchor((unsigned char *)TA720_DN, sizeof TA720_DN, BR_EC_secp384r1, (unsigned char *)TA720_EC_Q, sizeof TA720_EC_Q); + trust_anchors[721] = make_rsa_trust_anchor((unsigned char *)TA721_DN, sizeof TA721_DN, (unsigned char *)TA721_RSA_N, sizeof TA721_RSA_N, (unsigned char *)TA721_RSA_E, sizeof TA721_RSA_E); + trust_anchors[722] = make_rsa_trust_anchor((unsigned char *)TA722_DN, sizeof TA722_DN, (unsigned char *)TA722_RSA_N, sizeof TA722_RSA_N, (unsigned char *)TA722_RSA_E, sizeof TA722_RSA_E); + trust_anchors[723] = make_rsa_trust_anchor((unsigned char *)TA723_DN, sizeof TA723_DN, (unsigned char *)TA723_RSA_N, sizeof TA723_RSA_N, (unsigned char *)TA723_RSA_E, sizeof TA723_RSA_E); + trust_anchors[724] = make_rsa_trust_anchor((unsigned char *)TA724_DN, sizeof TA724_DN, (unsigned char *)TA724_RSA_N, sizeof TA724_RSA_N, (unsigned char *)TA724_RSA_E, sizeof TA724_RSA_E); + trust_anchors[725] = make_rsa_trust_anchor((unsigned char *)TA725_DN, sizeof TA725_DN, (unsigned char *)TA725_RSA_N, sizeof TA725_RSA_N, (unsigned char *)TA725_RSA_E, sizeof TA725_RSA_E); + trust_anchors[726] = make_rsa_trust_anchor((unsigned char *)TA726_DN, sizeof TA726_DN, (unsigned char *)TA726_RSA_N, sizeof TA726_RSA_N, (unsigned char *)TA726_RSA_E, sizeof TA726_RSA_E); + trust_anchors[727] = make_ec_trust_anchor((unsigned char *)TA727_DN, sizeof TA727_DN, BR_EC_secp384r1, (unsigned char *)TA727_EC_Q, sizeof TA727_EC_Q); + trust_anchors[728] = make_rsa_trust_anchor((unsigned char *)TA728_DN, sizeof TA728_DN, (unsigned char *)TA728_RSA_N, sizeof TA728_RSA_N, (unsigned char *)TA728_RSA_E, sizeof TA728_RSA_E); + trust_anchors[729] = make_rsa_trust_anchor((unsigned char *)TA729_DN, sizeof TA729_DN, (unsigned char *)TA729_RSA_N, sizeof TA729_RSA_N, (unsigned char *)TA729_RSA_E, sizeof TA729_RSA_E); + trust_anchors[730] = make_rsa_trust_anchor((unsigned char *)TA730_DN, sizeof TA730_DN, (unsigned char *)TA730_RSA_N, sizeof TA730_RSA_N, (unsigned char *)TA730_RSA_E, sizeof TA730_RSA_E); + trust_anchors[731] = make_rsa_trust_anchor((unsigned char *)TA731_DN, sizeof TA731_DN, (unsigned char *)TA731_RSA_N, sizeof TA731_RSA_N, (unsigned char *)TA731_RSA_E, sizeof TA731_RSA_E); + trust_anchors[732] = make_ec_trust_anchor((unsigned char *)TA732_DN, sizeof TA732_DN, BR_EC_secp384r1, (unsigned char *)TA732_EC_Q, sizeof TA732_EC_Q); + trust_anchors[733] = make_rsa_trust_anchor((unsigned char *)TA733_DN, sizeof TA733_DN, (unsigned char *)TA733_RSA_N, sizeof TA733_RSA_N, (unsigned char *)TA733_RSA_E, sizeof TA733_RSA_E); + trust_anchors[734] = make_ec_trust_anchor((unsigned char *)TA734_DN, sizeof TA734_DN, BR_EC_secp256r1, (unsigned char *)TA734_EC_Q, sizeof TA734_EC_Q); + trust_anchors[735] = make_ec_trust_anchor((unsigned char *)TA735_DN, sizeof TA735_DN, BR_EC_secp384r1, (unsigned char *)TA735_EC_Q, sizeof TA735_EC_Q); + trust_anchors[736] = make_rsa_trust_anchor((unsigned char *)TA736_DN, sizeof TA736_DN, (unsigned char *)TA736_RSA_N, sizeof TA736_RSA_N, (unsigned char *)TA736_RSA_E, sizeof TA736_RSA_E); + trust_anchors[737] = make_rsa_trust_anchor((unsigned char *)TA737_DN, sizeof TA737_DN, (unsigned char *)TA737_RSA_N, sizeof TA737_RSA_N, (unsigned char *)TA737_RSA_E, sizeof TA737_RSA_E); + trust_anchors[738] = make_rsa_trust_anchor((unsigned char *)TA738_DN, sizeof TA738_DN, (unsigned char *)TA738_RSA_N, sizeof TA738_RSA_N, (unsigned char *)TA738_RSA_E, sizeof TA738_RSA_E); + trust_anchors[739] = make_rsa_trust_anchor((unsigned char *)TA739_DN, sizeof TA739_DN, (unsigned char *)TA739_RSA_N, sizeof TA739_RSA_N, (unsigned char *)TA739_RSA_E, sizeof TA739_RSA_E); + trust_anchors[740] = make_rsa_trust_anchor((unsigned char *)TA740_DN, sizeof TA740_DN, (unsigned char *)TA740_RSA_N, sizeof TA740_RSA_N, (unsigned char *)TA740_RSA_E, sizeof TA740_RSA_E); + trust_anchors[741] = make_rsa_trust_anchor((unsigned char *)TA741_DN, sizeof TA741_DN, (unsigned char *)TA741_RSA_N, sizeof TA741_RSA_N, (unsigned char *)TA741_RSA_E, sizeof TA741_RSA_E); + trust_anchors[742] = make_rsa_trust_anchor((unsigned char *)TA742_DN, sizeof TA742_DN, (unsigned char *)TA742_RSA_N, sizeof TA742_RSA_N, (unsigned char *)TA742_RSA_E, sizeof TA742_RSA_E); + trust_anchors[743] = make_rsa_trust_anchor((unsigned char *)TA743_DN, sizeof TA743_DN, (unsigned char *)TA743_RSA_N, sizeof TA743_RSA_N, (unsigned char *)TA743_RSA_E, sizeof TA743_RSA_E); + trust_anchors[744] = make_rsa_trust_anchor((unsigned char *)TA744_DN, sizeof TA744_DN, (unsigned char *)TA744_RSA_N, sizeof TA744_RSA_N, (unsigned char *)TA744_RSA_E, sizeof TA744_RSA_E); + trust_anchors[745] = make_ec_trust_anchor((unsigned char *)TA745_DN, sizeof TA745_DN, BR_EC_secp384r1, (unsigned char *)TA745_EC_Q, sizeof TA745_EC_Q); + trust_anchors[746] = make_rsa_trust_anchor((unsigned char *)TA746_DN, sizeof TA746_DN, (unsigned char *)TA746_RSA_N, sizeof TA746_RSA_N, (unsigned char *)TA746_RSA_E, sizeof TA746_RSA_E); + trust_anchors[747] = make_ec_trust_anchor((unsigned char *)TA747_DN, sizeof TA747_DN, BR_EC_secp384r1, (unsigned char *)TA747_EC_Q, sizeof TA747_EC_Q); + trust_anchors[748] = make_rsa_trust_anchor((unsigned char *)TA748_DN, sizeof TA748_DN, (unsigned char *)TA748_RSA_N, sizeof TA748_RSA_N, (unsigned char *)TA748_RSA_E, sizeof TA748_RSA_E); + trust_anchors[749] = make_rsa_trust_anchor((unsigned char *)TA749_DN, sizeof TA749_DN, (unsigned char *)TA749_RSA_N, sizeof TA749_RSA_N, (unsigned char *)TA749_RSA_E, sizeof TA749_RSA_E); +} + +void certificates::close_trust_anchors() +{ + if (trust_anchors == NULL) + { + return; + } + if (loaded_from_file) + { + ca_loader::free_trust_anchors(trust_anchors, (size_t)trust_anchor_count); + } + else + { + free(trust_anchors); + } + trust_anchors = NULL; + trust_anchor_count = 0; + loaded_from_file = 0; +} + +br_x509_trust_anchor* certificates::get_trust_anchors() +{ + return trust_anchors; +} + +int certificates::get_num_trust_anchors() +{ + return trust_anchor_count; +} + +int certificates::load_from_file(const char *path) +{ + br_x509_trust_anchor *file_anchors = NULL; + size_t file_count = 0; + + if (ca_loader::load_pem_file(path, &file_anchors, &file_count) != 0) + { + return -1; + } + + /* Release any existing trust anchors */ + close_trust_anchors(); + + trust_anchors = file_anchors; + trust_anchor_count = (int)file_count; + loaded_from_file = 1; + return 0; +} + +// Private + +br_x509_trust_anchor certificates::make_rsa_trust_anchor(unsigned char *dn, size_t dn_len, unsigned char *n, size_t n_len, unsigned char *e, size_t e_len) +{ + br_x509_trust_anchor ta; + ta.dn.data = dn; + ta.dn.len = dn_len; + ta.flags = BR_X509_TA_CA; + ta.pkey.key_type = BR_KEYTYPE_RSA; + ta.pkey.key.rsa.n = n; + ta.pkey.key.rsa.nlen = n_len; + ta.pkey.key.rsa.e = e; + ta.pkey.key.rsa.elen = e_len; + return ta; +} + +br_x509_trust_anchor certificates::make_ec_trust_anchor(unsigned char *dn, size_t dn_len, int curve, unsigned char *q, size_t q_len) +{ + br_x509_trust_anchor ta; + ta.dn.data = dn; + ta.dn.len = dn_len; + ta.flags = BR_X509_TA_CA; + ta.pkey.key_type = BR_KEYTYPE_EC; + ta.pkey.key.ec.curve = curve; + ta.pkey.key.ec.q = q; + ta.pkey.key.ec.qlen = q_len; + return ta; +} diff --git a/BearSSL-OG/certificates.h b/BearSSL-OG/certificates.h new file mode 100644 index 0000000..def3705 --- /dev/null +++ b/BearSSL-OG/certificates.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +class certificates +{ +public: + static void initialize_trust_anchors(); + static void close_trust_anchors(); + static br_x509_trust_anchor* get_trust_anchors(); + static int get_num_trust_anchors(); + + /* + * Try to load trust anchors from a PEM CA bundle file. + * If successful, replaces the compiled-in trust store. + * Returns 0 on success, -1 on failure (compiled-in CAs unchanged). + */ + static int load_from_file(const char *path); + +private: + static br_x509_trust_anchor make_rsa_trust_anchor(unsigned char *dn, size_t dn_len, unsigned char *n, size_t n_len, unsigned char *e, size_t e_len); + static br_x509_trust_anchor make_ec_trust_anchor(unsigned char *dn, size_t dn_len, int curve, unsigned char *q, size_t q_len); +}; diff --git a/BearSSL-OG/chain-ec+rsa.h b/BearSSL-OG/chain-ec+rsa.h new file mode 100644 index 0000000..de9792e --- /dev/null +++ b/BearSSL-OG/chain-ec+rsa.h @@ -0,0 +1,171 @@ +#ifndef CHAIN_EC_RSA_H__ +#define CHAIN_EC_RSA_H__ + +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 "bearssl.h" + +/* + * A sample server certificate chain with a single intermediate CA. + * Certificate key type: EC + * Signing algorithm for both certificates: RSA + */ + +static const unsigned char CERT0[] = { + 0x30, 0x82, 0x02, 0x71, 0x30, 0x82, 0x01, 0x59, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x6E, 0x63, 0xBB, 0x49, 0xCE, 0x41, 0x7E, 0x03, 0x8C, + 0xF5, 0x46, 0xF2, 0x8A, 0xAE, 0x61, 0x08, 0x35, 0xB0, 0x94, 0xB3, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + 0x05, 0x00, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, + 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, + 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, + 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, + 0x35, 0x39, 0x5A, 0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, + 0x73, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0x5F, 0x38, 0x9D, 0xA7, 0xFF, 0x4D, 0x8A, + 0xAF, 0xF6, 0x34, 0x39, 0x46, 0x1A, 0xFC, 0x3A, 0xDF, 0xF4, 0x23, 0xAA, + 0xA9, 0xEA, 0xFB, 0xC5, 0x08, 0xDE, 0x00, 0x8E, 0xBE, 0x79, 0xA5, 0x37, + 0x58, 0x4C, 0x6D, 0xDD, 0x01, 0xCA, 0xAB, 0x47, 0xDF, 0x89, 0xB6, 0xC7, + 0x17, 0x1F, 0x38, 0xFC, 0x1D, 0x20, 0x14, 0xDD, 0x45, 0xC0, 0xE0, 0x8F, + 0x93, 0x4E, 0x38, 0x0B, 0xFC, 0xE9, 0x99, 0xA1, 0x49, 0xA3, 0x66, 0x30, + 0x64, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, + 0x80, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA, 0x19, + 0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30, 0x1D, + 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC3, 0x0E, 0x86, + 0xAA, 0x75, 0xB4, 0x15, 0xC0, 0xE5, 0x95, 0x09, 0x32, 0xBE, 0x5E, 0x92, + 0x75, 0xA9, 0xE4, 0x44, 0x9B, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, + 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55, + 0x1D, 0x11, 0x04, 0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61, + 0x6C, 0x68, 0x6F, 0x73, 0x74, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, + 0x00, 0x8E, 0x89, 0x63, 0xA7, 0x9B, 0xA8, 0x10, 0x8E, 0x9E, 0x18, 0xD0, + 0xA4, 0x7A, 0xDD, 0x2C, 0x82, 0x16, 0x8F, 0x0B, 0x0E, 0xD5, 0xCA, 0x57, + 0xBB, 0x5F, 0x6F, 0xFC, 0x57, 0x28, 0xC0, 0x21, 0xBA, 0xAD, 0x94, 0xA8, + 0x17, 0x42, 0x45, 0xD7, 0x31, 0xF7, 0x84, 0x57, 0x19, 0x46, 0x24, 0x3C, + 0xC7, 0x49, 0x38, 0x3F, 0x48, 0x7A, 0x09, 0x1A, 0xEB, 0x51, 0xBA, 0xC5, + 0x75, 0x8E, 0x4C, 0xB2, 0x25, 0xB0, 0xC7, 0x22, 0x3E, 0xE7, 0xE5, 0x46, + 0xDB, 0xB1, 0x36, 0xFC, 0x1B, 0x85, 0x51, 0xB0, 0xED, 0x83, 0x16, 0xF0, + 0x3A, 0x79, 0xDA, 0x5D, 0x28, 0x6A, 0xEE, 0x6A, 0x20, 0x4C, 0xB0, 0x70, + 0x5E, 0xB0, 0xED, 0x7A, 0x6D, 0x2D, 0x1A, 0xC9, 0xB4, 0x71, 0xC2, 0xC4, + 0xA3, 0x1D, 0x25, 0x86, 0x30, 0x54, 0xB1, 0x98, 0x26, 0xC1, 0x51, 0xE0, + 0xF8, 0x31, 0xAD, 0x67, 0x48, 0x9D, 0xE6, 0xA1, 0x52, 0x3B, 0x20, 0x47, + 0xC9, 0x70, 0xDA, 0x80, 0xB5, 0xA4, 0xF4, 0x3F, 0x72, 0x6B, 0x37, 0x30, + 0x57, 0x39, 0x2C, 0x46, 0x9B, 0x44, 0xF1, 0xD9, 0x4E, 0xBB, 0xA6, 0x5F, + 0xE3, 0x9A, 0xC5, 0x7F, 0x6C, 0xB6, 0x65, 0xCB, 0xBF, 0x40, 0x72, 0x92, + 0xD0, 0x68, 0xF6, 0xAE, 0x79, 0x7E, 0x24, 0xC1, 0x5B, 0x68, 0x30, 0x28, + 0x53, 0x71, 0x61, 0x7A, 0xF4, 0x36, 0x7B, 0x3B, 0xC2, 0xB6, 0xEC, 0x1F, + 0xDC, 0x30, 0x40, 0x04, 0x0D, 0xEA, 0xB3, 0x0A, 0xCF, 0x75, 0xD3, 0xBD, + 0x9E, 0xAB, 0x71, 0x71, 0x68, 0x7F, 0xA5, 0x41, 0x52, 0x00, 0xE9, 0xB3, + 0xAE, 0xE4, 0x1E, 0xF1, 0xBB, 0x69, 0xC6, 0x3B, 0xD5, 0xDE, 0xD2, 0xC2, + 0x25, 0x69, 0x08, 0x3C, 0x37, 0xCC, 0xF7, 0x82, 0x6A, 0xE5, 0xA8, 0x7B, + 0x6A, 0x02, 0xDA, 0xBD, 0xA4, 0x01, 0x33, 0x33, 0xF3, 0xDE, 0x46, 0x00, + 0xEC, 0x75, 0xCF, 0xE0, 0x7D +}; + +static const unsigned char CERT1[] = { + 0x30, 0x82, 0x03, 0x34, 0x30, 0x82, 0x02, 0x1C, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x70, 0x0F, 0x60, 0xEE, 0xF0, 0x07, 0x9A, 0x9C, 0x69, + 0xAC, 0x97, 0x62, 0x26, 0x4F, 0x5D, 0x05, 0xB6, 0xF9, 0x8F, 0x48, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + 0x05, 0x00, 0x30, 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, + 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x5A, 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, + 0x39, 0x35, 0x39, 0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, + 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, + 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB3, 0xE8, 0x6B, 0xAF, 0x9C, 0x16, + 0x52, 0xE3, 0x81, 0x0C, 0x50, 0xAB, 0x25, 0xCE, 0xCC, 0x0D, 0xC7, 0xF2, + 0x1F, 0x7F, 0x50, 0xDF, 0x2C, 0x5C, 0x35, 0xD6, 0x62, 0x2E, 0x63, 0x27, + 0x41, 0xA7, 0xE4, 0x53, 0xA8, 0x4B, 0x27, 0xFA, 0x13, 0x91, 0xA3, 0xFA, + 0x09, 0x4A, 0x2F, 0x3B, 0x5E, 0xCF, 0x77, 0xB3, 0x8A, 0xC1, 0xCD, 0x49, + 0x95, 0x9C, 0x75, 0x0D, 0x64, 0x74, 0xEF, 0xE4, 0xD7, 0x4B, 0xB9, 0xA1, + 0x9B, 0x68, 0xD2, 0x30, 0x71, 0x48, 0xEA, 0xF7, 0x4B, 0x14, 0xDF, 0x3F, + 0x47, 0xA9, 0xD8, 0xBB, 0xEC, 0x8F, 0x28, 0xCC, 0xFA, 0xDF, 0xB4, 0x1F, + 0x94, 0x7C, 0x96, 0xFC, 0x08, 0x05, 0x28, 0xF9, 0xE8, 0xF4, 0x2F, 0x2F, + 0xEE, 0x62, 0x9C, 0x8A, 0x3A, 0xE0, 0x85, 0x58, 0x60, 0xB6, 0x0F, 0x2D, + 0x30, 0xB4, 0xC0, 0x41, 0x54, 0x91, 0x4C, 0x1F, 0x5F, 0xAD, 0xF1, 0x19, + 0xF0, 0xC0, 0x22, 0xA6, 0x7D, 0xD8, 0x3F, 0x79, 0x34, 0x59, 0x42, 0x7B, + 0x5B, 0xB5, 0x41, 0xC4, 0x64, 0x7F, 0x52, 0xCF, 0x3C, 0x37, 0x22, 0xA1, + 0x2F, 0x79, 0x25, 0x94, 0x24, 0x41, 0xC2, 0x3F, 0xFA, 0xC7, 0x75, 0xFB, + 0x48, 0xB5, 0x0D, 0x18, 0xA7, 0xF4, 0x54, 0xF3, 0x2E, 0x6E, 0xD8, 0x43, + 0x58, 0xC4, 0xAB, 0x50, 0xE8, 0x05, 0xAD, 0x91, 0xB6, 0x1E, 0x01, 0x75, + 0xB3, 0x54, 0x9C, 0xDE, 0xA0, 0x99, 0x15, 0xFB, 0xAC, 0xF1, 0x5C, 0x97, + 0x49, 0x51, 0xCC, 0xEF, 0x58, 0x12, 0x6F, 0x73, 0x6B, 0xB3, 0x34, 0x14, + 0x01, 0x0F, 0x5A, 0x9D, 0xFA, 0xAA, 0xD6, 0x93, 0xD3, 0xE2, 0xEA, 0xC3, + 0xAB, 0xBC, 0x4E, 0xED, 0xCC, 0x51, 0xA1, 0xB8, 0xF8, 0x94, 0xB6, 0xB4, + 0x2C, 0xA8, 0x86, 0x2B, 0x1F, 0xF6, 0x51, 0x43, 0x29, 0x52, 0x5E, 0x13, + 0x89, 0xB3, 0x6A, 0x78, 0x60, 0x4E, 0x4E, 0xC0, 0x1B, 0xA5, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC3, 0x0A, 0xBC, 0xB4, + 0x90, 0x63, 0x96, 0x92, 0x45, 0xBC, 0x27, 0xA0, 0xF0, 0x58, 0x89, 0x2A, + 0xD5, 0x78, 0x00, 0x12, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + 0x16, 0x04, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA, + 0x19, 0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, + 0x02, 0x00, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, + 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x54, 0x3B, 0xF4, 0xEA, 0xC6, 0xE4, 0xE8, 0xC0, + 0x5B, 0x12, 0xB2, 0xAD, 0xFA, 0xBD, 0xA9, 0xF4, 0x62, 0x03, 0xAD, 0x57, + 0x4C, 0x6F, 0x07, 0xA7, 0x47, 0x35, 0x75, 0x3E, 0x48, 0xA2, 0x5B, 0x71, + 0x10, 0x01, 0x8F, 0x93, 0x99, 0x9D, 0xA7, 0x47, 0xE3, 0x8E, 0x3E, 0xAF, + 0x2D, 0xBA, 0x06, 0xFE, 0xD4, 0xE4, 0x97, 0xBC, 0x10, 0x8D, 0xA6, 0xA5, + 0x3A, 0x3C, 0xE6, 0x21, 0xCB, 0x3B, 0xDA, 0x13, 0xE3, 0x4A, 0x23, 0xEB, + 0xBC, 0xBA, 0xA5, 0x90, 0x91, 0xAD, 0x55, 0x6E, 0xD5, 0xDD, 0x85, 0x4B, + 0x6B, 0x27, 0xD2, 0x39, 0x76, 0x06, 0x2E, 0xD4, 0x23, 0x5B, 0xBB, 0x55, + 0xB5, 0x49, 0x3F, 0x7D, 0x2F, 0x21, 0xCB, 0x96, 0x75, 0x19, 0x99, 0xA9, + 0x99, 0xF1, 0x0B, 0xBB, 0x3E, 0xC7, 0x10, 0xA7, 0x8B, 0x7A, 0x52, 0xB9, + 0x49, 0xE4, 0x14, 0x08, 0x78, 0xE7, 0x3D, 0xD9, 0x98, 0x57, 0xDA, 0xFF, + 0xDA, 0xB9, 0x8D, 0x66, 0x75, 0x80, 0xB5, 0x5D, 0xB9, 0xDF, 0x69, 0x65, + 0xDB, 0x16, 0xE7, 0x1E, 0xC4, 0x40, 0xE4, 0x46, 0x8A, 0x1E, 0x76, 0x32, + 0x16, 0xE7, 0x83, 0x67, 0xDA, 0x78, 0x56, 0xAB, 0x0F, 0x4C, 0x5C, 0xF1, + 0x70, 0xDA, 0x66, 0x20, 0xF4, 0xF8, 0x0F, 0xF6, 0xDC, 0x2F, 0x72, 0x97, + 0x6B, 0x78, 0x40, 0x79, 0x9D, 0x5B, 0x6D, 0xBE, 0x03, 0xCE, 0x70, 0x42, + 0xA8, 0x2A, 0x71, 0x11, 0xDF, 0x2E, 0x81, 0x01, 0xEA, 0x86, 0x12, 0x91, + 0x4F, 0xD0, 0x18, 0xED, 0x84, 0xA4, 0x48, 0x30, 0xB9, 0xB9, 0x7B, 0x56, + 0x3E, 0xEF, 0x8D, 0xE1, 0x1F, 0xFD, 0x90, 0xB2, 0x44, 0x85, 0x58, 0x6F, + 0xA7, 0x30, 0x74, 0x7C, 0xF1, 0xAE, 0x8C, 0x99, 0x3F, 0xF1, 0x4D, 0x57, + 0xC5, 0x95, 0x68, 0xC2, 0x36, 0xB2, 0xEC, 0xC2, 0x68, 0x7A, 0xC0, 0x81, + 0xA9, 0x55, 0x05, 0xE7, 0xCF, 0xAF, 0x50, 0xAC +}; + +static const br_x509_certificate CHAIN[] = { + { (unsigned char *)CERT0, sizeof CERT0 }, + { (unsigned char *)CERT1, sizeof CERT1 } +}; + +#define CHAIN_LEN 2 + +#endif /* CHAIN_EC_RSA_H__ */ diff --git a/BearSSL-OG/chain-ec.h b/BearSSL-OG/chain-ec.h new file mode 100644 index 0000000..97059bb --- /dev/null +++ b/BearSSL-OG/chain-ec.h @@ -0,0 +1,122 @@ +#ifndef CHAIN_EC_H__ +#define CHAIN_EC_H__ + +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 "bearssl.h" + +/* + * A sample server certificate chain with a single intermediate CA. + * Certificate key type: EC + * Signing algorithm for both certificates: ECDSA + */ + +static const unsigned char CERT0[] = { + 0x30, 0x82, 0x01, 0xB0, 0x30, 0x82, 0x01, 0x56, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x1C, 0x4D, 0x00, 0x91, 0x69, 0xE2, 0x46, 0xAC, 0x90, + 0x7C, 0x64, 0x5C, 0x53, 0xF1, 0xFF, 0xB7, 0xC1, 0xCB, 0x6E, 0x7A, 0x30, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, + 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, + 0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x30, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, + 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, + 0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, 0x30, + 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, + 0x00, 0x04, 0x5F, 0x38, 0x9D, 0xA7, 0xFF, 0x4D, 0x8A, 0xAF, 0xF6, 0x34, + 0x39, 0x46, 0x1A, 0xFC, 0x3A, 0xDF, 0xF4, 0x23, 0xAA, 0xA9, 0xEA, 0xFB, + 0xC5, 0x08, 0xDE, 0x00, 0x8E, 0xBE, 0x79, 0xA5, 0x37, 0x58, 0x4C, 0x6D, + 0xDD, 0x01, 0xCA, 0xAB, 0x47, 0xDF, 0x89, 0xB6, 0xC7, 0x17, 0x1F, 0x38, + 0xFC, 0x1D, 0x20, 0x14, 0xDD, 0x45, 0xC0, 0xE0, 0x8F, 0x93, 0x4E, 0x38, + 0x0B, 0xFC, 0xE9, 0x99, 0xA1, 0x49, 0xA3, 0x66, 0x30, 0x64, 0x30, 0x1F, + 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xF0, + 0xD0, 0xF1, 0x22, 0xF9, 0x7A, 0x48, 0x17, 0x06, 0x7B, 0x3D, 0xBD, 0xB8, + 0xF5, 0xCD, 0x55, 0x9C, 0x5C, 0x3E, 0x70, 0x30, 0x1D, 0x06, 0x03, 0x55, + 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC3, 0x0E, 0x86, 0xAA, 0x75, 0xB4, + 0x15, 0xC0, 0xE5, 0x95, 0x09, 0x32, 0xBE, 0x5E, 0x92, 0x75, 0xA9, 0xE4, + 0x44, 0x9B, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, + 0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, + 0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, + 0x73, 0x74, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, + 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x91, 0xFB, + 0xF4, 0x04, 0xD0, 0xE5, 0x2E, 0x01, 0xD4, 0x8C, 0xF0, 0x17, 0x62, 0x0F, + 0xDC, 0xCC, 0x80, 0xCA, 0x18, 0xC4, 0x40, 0x7C, 0x27, 0x03, 0xCB, 0x34, + 0x03, 0x0D, 0x9B, 0xC8, 0x59, 0x4D, 0x02, 0x20, 0x05, 0x55, 0x69, 0xE2, + 0xD8, 0xA1, 0x40, 0x33, 0x34, 0x0E, 0x7E, 0x49, 0x32, 0x64, 0x1D, 0x3F, + 0x6B, 0x1F, 0xD0, 0x2D, 0xB7, 0x2F, 0x52, 0x04, 0x56, 0xAF, 0xD3, 0x37, + 0x8F, 0x87, 0x99, 0xA2 +}; + +static const unsigned char CERT1[] = { + 0x30, 0x82, 0x01, 0xA9, 0x30, 0x82, 0x01, 0x4E, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x20, 0xD3, 0xEB, 0xE2, 0x8C, 0xFE, 0xDA, 0xE6, 0xA3, + 0x2C, 0x5E, 0x3B, 0xF2, 0x66, 0x3A, 0x2B, 0x36, 0x7B, 0xB0, 0xCA, 0x30, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, + 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x30, 0x30, + 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, + 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, + 0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69, + 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, + 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x70, 0x2E, 0x92, + 0x82, 0x01, 0x17, 0x6C, 0x6D, 0xAB, 0xE1, 0xD1, 0x63, 0x09, 0x48, 0x49, + 0xD2, 0xA6, 0x35, 0x52, 0xD3, 0x3C, 0x73, 0xBB, 0xB2, 0x88, 0x37, 0x98, + 0x87, 0xF1, 0x8D, 0xE0, 0xEC, 0x65, 0x9A, 0x0E, 0x13, 0xF5, 0xED, 0x91, + 0x61, 0xC8, 0xB6, 0x6D, 0x33, 0x84, 0x6E, 0xAE, 0x8E, 0x55, 0x80, 0xCD, + 0x49, 0x9E, 0x07, 0xBF, 0xD0, 0xAE, 0x9D, 0xE6, 0xD0, 0xB3, 0x27, 0x16, + 0xA1, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x95, 0x41, 0xB4, 0xE2, 0x67, 0xAA, + 0xF1, 0x7F, 0xBC, 0x8F, 0x79, 0xF3, 0x68, 0x14, 0x5A, 0x6B, 0x92, 0x16, + 0xA2, 0x40, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xF0, 0xD0, 0xF1, 0x22, 0xF9, 0x7A, 0x48, 0x17, 0x06, 0x7B, 0x3D, + 0xBD, 0xB8, 0xF5, 0xCD, 0x55, 0x9C, 0x5C, 0x3E, 0x70, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x00, + 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, + 0x21, 0x00, 0x85, 0xE3, 0x46, 0x68, 0x99, 0xD6, 0x02, 0x7A, 0x59, 0x66, + 0x1C, 0xB7, 0x4F, 0x35, 0x2D, 0x08, 0x36, 0x38, 0x61, 0x7E, 0x05, 0x48, + 0xD8, 0x69, 0x43, 0x1F, 0xEB, 0x56, 0xE9, 0xAD, 0x06, 0x0E, 0x02, 0x21, + 0x00, 0x82, 0x70, 0xB4, 0x62, 0x03, 0x49, 0x46, 0xC8, 0x54, 0x59, 0x05, + 0xD9, 0x78, 0xDB, 0x53, 0x1C, 0xE0, 0x6E, 0x66, 0xF5, 0x0F, 0x14, 0x3B, + 0xC9, 0x2D, 0x38, 0x12, 0x70, 0x91, 0x56, 0xF9, 0xA9 +}; + +static const br_x509_certificate CHAIN[] = { + { (unsigned char *)CERT0, sizeof CERT0 }, + { (unsigned char *)CERT1, sizeof CERT1 } +}; + +#define CHAIN_LEN 2 + +#endif /* CHAIN_EC_H__ */ diff --git a/BearSSL-OG/chain-rsa.h b/BearSSL-OG/chain-rsa.h new file mode 100644 index 0000000..0a695dd --- /dev/null +++ b/BearSSL-OG/chain-rsa.h @@ -0,0 +1,188 @@ +#ifndef CHAIN_RSA_H__ +#define CHAIN_RSA_H__ + +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 "bearssl.h" + +/* + * A sample server certificate chain with a single intermediate CA. + * Certificate key type: RSA + * Signing algorithm for both certificates: RSA + */ + +static const unsigned char CERT0[] = { + 0x30, 0x82, 0x03, 0x3C, 0x30, 0x82, 0x02, 0x24, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x58, 0xDA, 0xBA, 0x36, 0xCD, 0xED, 0xA0, 0xDA, 0x5C, + 0x10, 0x33, 0x73, 0x8E, 0x0C, 0x64, 0x92, 0x79, 0x92, 0xAF, 0x03, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + 0x05, 0x00, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, + 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, + 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, + 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, + 0x35, 0x39, 0x5A, 0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, + 0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xD4, + 0x7A, 0x1D, 0x27, 0xBA, 0x2B, 0x3A, 0x67, 0xB2, 0x91, 0x6A, 0xFB, 0xE7, + 0x83, 0x44, 0xCA, 0xED, 0x1C, 0x75, 0xAD, 0xDD, 0x4D, 0x83, 0x62, 0xD6, + 0xAA, 0x68, 0x95, 0xB2, 0x24, 0x21, 0x7B, 0x15, 0xAE, 0x2A, 0x99, 0x68, + 0x15, 0xED, 0x66, 0xF0, 0xB8, 0x58, 0xE7, 0xD3, 0xF5, 0x2E, 0xC6, 0xD9, + 0x2A, 0x5E, 0xE7, 0x0E, 0x2E, 0xE7, 0xFC, 0x67, 0x59, 0xC0, 0xC8, 0x61, + 0x7D, 0x4B, 0xA4, 0x6F, 0xDD, 0x9F, 0xD9, 0xC8, 0x85, 0x87, 0x64, 0xC7, + 0xBA, 0x1A, 0x0F, 0x29, 0xD4, 0x96, 0xA8, 0x78, 0x9A, 0x6B, 0x62, 0x20, + 0xA9, 0x32, 0xD0, 0xEE, 0xA9, 0x8C, 0x28, 0x61, 0x47, 0xA2, 0x50, 0x2A, + 0x63, 0xF6, 0x21, 0xDE, 0xDA, 0xD8, 0xD5, 0xF0, 0x7F, 0xC5, 0x00, 0x82, + 0x70, 0xE6, 0xA3, 0xBF, 0x5C, 0x89, 0x27, 0x4F, 0x51, 0x92, 0x77, 0x03, + 0xC3, 0xB0, 0xCC, 0x2E, 0x3B, 0xEC, 0x23, 0xF2, 0x2F, 0x53, 0x41, 0xAF, + 0x89, 0x93, 0xFF, 0xD2, 0x80, 0xB1, 0x43, 0x97, 0xDE, 0xD6, 0x19, 0xA0, + 0x92, 0x12, 0x7A, 0x3D, 0x66, 0x79, 0xE1, 0xC1, 0xBC, 0xE1, 0x77, 0x70, + 0xA2, 0x8B, 0x3D, 0x46, 0x84, 0x53, 0x3F, 0xE4, 0x4E, 0x42, 0x41, 0x37, + 0x92, 0x1E, 0x1F, 0xFD, 0x38, 0xB3, 0xF7, 0xEF, 0x87, 0x39, 0x80, 0xD3, + 0x56, 0xCF, 0xF4, 0xE0, 0x13, 0xDE, 0x64, 0xB0, 0x72, 0xA4, 0x03, 0x84, + 0xC4, 0x41, 0xED, 0x6F, 0xFA, 0x3E, 0xE2, 0xCA, 0x04, 0x20, 0xD2, 0xD7, + 0xDC, 0x2C, 0x82, 0x2B, 0x7A, 0xE2, 0x6D, 0xA1, 0x1C, 0x48, 0xDB, 0xCF, + 0x89, 0x4F, 0x34, 0x97, 0x3D, 0x28, 0xA8, 0x53, 0xDA, 0xE7, 0xC1, 0xE1, + 0x73, 0x15, 0xA3, 0x30, 0x76, 0x7F, 0x8F, 0x23, 0x42, 0x14, 0x3D, 0x51, + 0x34, 0xD2, 0x5A, 0xAD, 0x3C, 0x9B, 0xCB, 0xC8, 0xFE, 0x7F, 0x6E, 0x8E, + 0x40, 0xF3, 0xBD, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x66, 0x30, 0x64, + 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0xC5, 0x01, 0xAD, 0x7C, 0xE6, 0x63, 0xC9, 0x9C, 0x17, 0x5F, 0xC5, + 0xA2, 0xA7, 0xE1, 0x50, 0x5F, 0xE8, 0xF5, 0xA8, 0xC6, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC5, 0x01, 0xAD, 0x7C, + 0xE6, 0x63, 0xC9, 0x9C, 0x17, 0x5F, 0xC5, 0xA2, 0xA7, 0xE1, 0x50, 0x5F, + 0xE8, 0xF5, 0xA8, 0xC6, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, + 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55, 0x1D, + 0x11, 0x04, 0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, + 0x68, 0x6F, 0x73, 0x74, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, + 0x71, 0xB3, 0x5D, 0x21, 0xC2, 0x0E, 0xD7, 0xD0, 0xC6, 0xF8, 0x4A, 0x73, + 0x87, 0x4D, 0x22, 0x02, 0x27, 0xD0, 0xC7, 0xF8, 0xFD, 0x1A, 0x6D, 0x62, + 0x58, 0x82, 0x08, 0x76, 0x20, 0x07, 0xC0, 0x48, 0x92, 0xF3, 0xE9, 0x98, + 0x5A, 0xEB, 0x0D, 0x4E, 0x56, 0x95, 0x63, 0x68, 0x4D, 0xAB, 0xD4, 0x00, + 0x76, 0xE0, 0x37, 0xCF, 0x0B, 0x11, 0x61, 0x59, 0x5C, 0xDE, 0xF6, 0xA5, + 0x14, 0x59, 0xD9, 0x25, 0x9F, 0x59, 0xD9, 0xD3, 0x5E, 0x86, 0xAC, 0x1D, + 0xA6, 0x2C, 0x32, 0x42, 0x19, 0x32, 0x13, 0x40, 0x0B, 0x54, 0xCD, 0x67, + 0x26, 0xB6, 0xBD, 0xB4, 0x96, 0xA4, 0xCA, 0x1F, 0x7F, 0x37, 0xD6, 0xA8, + 0x75, 0xEB, 0x3A, 0x81, 0x51, 0x30, 0xB9, 0xF9, 0x4A, 0x01, 0x6F, 0xD1, + 0xD6, 0xED, 0x4F, 0xDF, 0x3F, 0x30, 0x60, 0x06, 0x67, 0x92, 0x8E, 0x61, + 0x85, 0x5F, 0x1A, 0xB5, 0x8C, 0xB3, 0x0F, 0x61, 0xA9, 0xFA, 0xDF, 0x5D, + 0xC4, 0x64, 0x00, 0xEA, 0x87, 0xB1, 0x33, 0x5F, 0x7D, 0xCB, 0xA3, 0x85, + 0x24, 0x6E, 0x2C, 0x65, 0x3B, 0xEA, 0x73, 0x3F, 0x86, 0xD3, 0xFD, 0xE8, + 0xE4, 0x02, 0xC6, 0x61, 0x6A, 0x26, 0x17, 0x52, 0x01, 0x25, 0x5C, 0x7F, + 0xA8, 0xCE, 0x69, 0x1F, 0xAC, 0x61, 0x2C, 0xB7, 0x04, 0xAF, 0xFD, 0xA4, + 0x7A, 0x99, 0xCB, 0x26, 0x15, 0x4C, 0xFF, 0x74, 0xD4, 0x73, 0x0C, 0x57, + 0x0C, 0x26, 0xEB, 0xD7, 0x2A, 0xDC, 0x5C, 0xC3, 0x41, 0xBB, 0xC2, 0xF3, + 0xCE, 0x16, 0xBD, 0x8E, 0x7B, 0xFB, 0xE9, 0xDF, 0xAB, 0x21, 0x0D, 0x91, + 0xB3, 0x8D, 0xD8, 0xCF, 0xC8, 0xF4, 0x49, 0xB9, 0xD0, 0xE3, 0x16, 0x70, + 0x3F, 0xB3, 0xDE, 0xD4, 0x07, 0x25, 0xFA, 0x46, 0x44, 0x52, 0x89, 0x4D, + 0x89, 0xC8, 0xE2, 0xCA, 0xB5, 0x33, 0x7F, 0xC7, 0x21, 0xBD, 0x28, 0xEF, + 0xFE, 0x66, 0x74, 0x03 +}; + +static const unsigned char CERT1[] = { + 0x30, 0x82, 0x03, 0x34, 0x30, 0x82, 0x02, 0x1C, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x70, 0x0F, 0x60, 0xEE, 0xF0, 0x07, 0x9A, 0x9C, 0x69, + 0xAC, 0x97, 0x62, 0x26, 0x4F, 0x5D, 0x05, 0xB6, 0xF9, 0x8F, 0x48, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + 0x05, 0x00, 0x30, 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, + 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x5A, 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, + 0x39, 0x35, 0x39, 0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, + 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, + 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB3, 0xE8, 0x6B, 0xAF, 0x9C, 0x16, + 0x52, 0xE3, 0x81, 0x0C, 0x50, 0xAB, 0x25, 0xCE, 0xCC, 0x0D, 0xC7, 0xF2, + 0x1F, 0x7F, 0x50, 0xDF, 0x2C, 0x5C, 0x35, 0xD6, 0x62, 0x2E, 0x63, 0x27, + 0x41, 0xA7, 0xE4, 0x53, 0xA8, 0x4B, 0x27, 0xFA, 0x13, 0x91, 0xA3, 0xFA, + 0x09, 0x4A, 0x2F, 0x3B, 0x5E, 0xCF, 0x77, 0xB3, 0x8A, 0xC1, 0xCD, 0x49, + 0x95, 0x9C, 0x75, 0x0D, 0x64, 0x74, 0xEF, 0xE4, 0xD7, 0x4B, 0xB9, 0xA1, + 0x9B, 0x68, 0xD2, 0x30, 0x71, 0x48, 0xEA, 0xF7, 0x4B, 0x14, 0xDF, 0x3F, + 0x47, 0xA9, 0xD8, 0xBB, 0xEC, 0x8F, 0x28, 0xCC, 0xFA, 0xDF, 0xB4, 0x1F, + 0x94, 0x7C, 0x96, 0xFC, 0x08, 0x05, 0x28, 0xF9, 0xE8, 0xF4, 0x2F, 0x2F, + 0xEE, 0x62, 0x9C, 0x8A, 0x3A, 0xE0, 0x85, 0x58, 0x60, 0xB6, 0x0F, 0x2D, + 0x30, 0xB4, 0xC0, 0x41, 0x54, 0x91, 0x4C, 0x1F, 0x5F, 0xAD, 0xF1, 0x19, + 0xF0, 0xC0, 0x22, 0xA6, 0x7D, 0xD8, 0x3F, 0x79, 0x34, 0x59, 0x42, 0x7B, + 0x5B, 0xB5, 0x41, 0xC4, 0x64, 0x7F, 0x52, 0xCF, 0x3C, 0x37, 0x22, 0xA1, + 0x2F, 0x79, 0x25, 0x94, 0x24, 0x41, 0xC2, 0x3F, 0xFA, 0xC7, 0x75, 0xFB, + 0x48, 0xB5, 0x0D, 0x18, 0xA7, 0xF4, 0x54, 0xF3, 0x2E, 0x6E, 0xD8, 0x43, + 0x58, 0xC4, 0xAB, 0x50, 0xE8, 0x05, 0xAD, 0x91, 0xB6, 0x1E, 0x01, 0x75, + 0xB3, 0x54, 0x9C, 0xDE, 0xA0, 0x99, 0x15, 0xFB, 0xAC, 0xF1, 0x5C, 0x97, + 0x49, 0x51, 0xCC, 0xEF, 0x58, 0x12, 0x6F, 0x73, 0x6B, 0xB3, 0x34, 0x14, + 0x01, 0x0F, 0x5A, 0x9D, 0xFA, 0xAA, 0xD6, 0x93, 0xD3, 0xE2, 0xEA, 0xC3, + 0xAB, 0xBC, 0x4E, 0xED, 0xCC, 0x51, 0xA1, 0xB8, 0xF8, 0x94, 0xB6, 0xB4, + 0x2C, 0xA8, 0x86, 0x2B, 0x1F, 0xF6, 0x51, 0x43, 0x29, 0x52, 0x5E, 0x13, + 0x89, 0xB3, 0x6A, 0x78, 0x60, 0x4E, 0x4E, 0xC0, 0x1B, 0xA5, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC3, 0x0A, 0xBC, 0xB4, + 0x90, 0x63, 0x96, 0x92, 0x45, 0xBC, 0x27, 0xA0, 0xF0, 0x58, 0x89, 0x2A, + 0xD5, 0x78, 0x00, 0x12, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + 0x16, 0x04, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA, + 0x19, 0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, + 0x02, 0x00, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, + 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x54, 0x3B, 0xF4, 0xEA, 0xC6, 0xE4, 0xE8, 0xC0, + 0x5B, 0x12, 0xB2, 0xAD, 0xFA, 0xBD, 0xA9, 0xF4, 0x62, 0x03, 0xAD, 0x57, + 0x4C, 0x6F, 0x07, 0xA7, 0x47, 0x35, 0x75, 0x3E, 0x48, 0xA2, 0x5B, 0x71, + 0x10, 0x01, 0x8F, 0x93, 0x99, 0x9D, 0xA7, 0x47, 0xE3, 0x8E, 0x3E, 0xAF, + 0x2D, 0xBA, 0x06, 0xFE, 0xD4, 0xE4, 0x97, 0xBC, 0x10, 0x8D, 0xA6, 0xA5, + 0x3A, 0x3C, 0xE6, 0x21, 0xCB, 0x3B, 0xDA, 0x13, 0xE3, 0x4A, 0x23, 0xEB, + 0xBC, 0xBA, 0xA5, 0x90, 0x91, 0xAD, 0x55, 0x6E, 0xD5, 0xDD, 0x85, 0x4B, + 0x6B, 0x27, 0xD2, 0x39, 0x76, 0x06, 0x2E, 0xD4, 0x23, 0x5B, 0xBB, 0x55, + 0xB5, 0x49, 0x3F, 0x7D, 0x2F, 0x21, 0xCB, 0x96, 0x75, 0x19, 0x99, 0xA9, + 0x99, 0xF1, 0x0B, 0xBB, 0x3E, 0xC7, 0x10, 0xA7, 0x8B, 0x7A, 0x52, 0xB9, + 0x49, 0xE4, 0x14, 0x08, 0x78, 0xE7, 0x3D, 0xD9, 0x98, 0x57, 0xDA, 0xFF, + 0xDA, 0xB9, 0x8D, 0x66, 0x75, 0x80, 0xB5, 0x5D, 0xB9, 0xDF, 0x69, 0x65, + 0xDB, 0x16, 0xE7, 0x1E, 0xC4, 0x40, 0xE4, 0x46, 0x8A, 0x1E, 0x76, 0x32, + 0x16, 0xE7, 0x83, 0x67, 0xDA, 0x78, 0x56, 0xAB, 0x0F, 0x4C, 0x5C, 0xF1, + 0x70, 0xDA, 0x66, 0x20, 0xF4, 0xF8, 0x0F, 0xF6, 0xDC, 0x2F, 0x72, 0x97, + 0x6B, 0x78, 0x40, 0x79, 0x9D, 0x5B, 0x6D, 0xBE, 0x03, 0xCE, 0x70, 0x42, + 0xA8, 0x2A, 0x71, 0x11, 0xDF, 0x2E, 0x81, 0x01, 0xEA, 0x86, 0x12, 0x91, + 0x4F, 0xD0, 0x18, 0xED, 0x84, 0xA4, 0x48, 0x30, 0xB9, 0xB9, 0x7B, 0x56, + 0x3E, 0xEF, 0x8D, 0xE1, 0x1F, 0xFD, 0x90, 0xB2, 0x44, 0x85, 0x58, 0x6F, + 0xA7, 0x30, 0x74, 0x7C, 0xF1, 0xAE, 0x8C, 0x99, 0x3F, 0xF1, 0x4D, 0x57, + 0xC5, 0x95, 0x68, 0xC2, 0x36, 0xB2, 0xEC, 0xC2, 0x68, 0x7A, 0xC0, 0x81, + 0xA9, 0x55, 0x05, 0xE7, 0xCF, 0xAF, 0x50, 0xAC +}; + +static const br_x509_certificate CHAIN[] = { + { (unsigned char *)CERT0, sizeof CERT0 }, + { (unsigned char *)CERT1, sizeof CERT1 } +}; + +#define CHAIN_LEN 2 + +#endif /* CHAIN_RSA_H__ */ diff --git a/BearSSL-OG/client.cpp b/BearSSL-OG/client.cpp new file mode 100644 index 0000000..f99eed3 --- /dev/null +++ b/BearSSL-OG/client.cpp @@ -0,0 +1,461 @@ +#include "client.h" +#include "url_utility.h" +#include "debug_utility.h" +#include "network_utility.h" +#include "string_utility.h" +#include "socket_utility.h" +#include "certificates.h" +#include "ca_loader.h" +#include "data_store.h" + +#include +#include +#include +#include +#include +#include +#include "ssl_config.h" +#include "ssl_debug.h" +#include "session_cache.h" +#include "cert_pinning.h" + +#define READ_BUFFER_SIZE 65536 + +int client::download_file(const char* url, uint16_t port, const char* file_path) +{ + char *host = NULL; + char *path = NULL; + if (url_utility::parse_url(url, &host, &path) == false) + { + return -1; + } + + uint32_t host_ip = network_utility::resolve_host(host); + if (host_ip == 0) + { + ssl_debug::log_error("DNS resolution failed for host: %s\n", host); + free(host); + free(path); + return -3; /* DNS resolution failed */ + } + + int socket = socket_utility::connect_to_host(host_ip, port); + if (socket < 0) + { + ssl_debug::log_error("Failed to connect to %s:%d\n", host, port); + free(host); + free(path); + return -4; /* Connection failed */ + } + + /* Try loading CAs from PEM file on Xbox HDD */ + if (certificates::load_from_file(SSL_DEFAULT_CA_FILE) != 0) + { + /* No file on disk — load compiled-in CAs and auto-download */ + certificates::initialize_trust_anchors(); + ca_loader::update_trust_store(SSL_DEFAULT_CA_FILE, + certificates::get_trust_anchors(), + (size_t)certificates::get_num_trust_anchors()); + + /* If download succeeded, switch to the fresh CAs */ + certificates::load_from_file(SSL_DEFAULT_CA_FILE); + } + + br_ssl_client_context client_context; + br_x509_minimal_context cert_context; + br_ssl_client_init_full(&client_context, &cert_context, certificates::get_trust_anchors(), certificates::get_num_trust_anchors()); + + // Enforce TLS 1.2 minimum +#if SSL_ENFORCE_TLS12 + br_ssl_engine_set_versions(&client_context.eng, SSL_MIN_VERSION, SSL_MAX_VERSION); +#endif + + // Restrict to secure cipher suites +#if SSL_RESTRICT_CIPHERS + br_ssl_engine_set_suites(&client_context.eng, SSL_SECURE_SUITES, SSL_SECURE_SUITES_COUNT); +#endif + + unsigned char io_buffer[BR_SSL_BUFSIZE_BIDI]; + br_ssl_engine_set_buffer(&client_context.eng, io_buffer, BR_SSL_BUFSIZE_BIDI, 1); + + // Try to resume previous session + br_ssl_session_parameters session_params; + int resume = 0; +#if SSL_ENABLE_SESSION_CACHE + if (session_cache::get(host, &session_params)) { + br_ssl_engine_set_session_parameters(&client_context.eng, &session_params); + resume = 1; + } +#endif + + br_ssl_client_reset(&client_context, host, resume); + + br_sslio_context io_context; + br_sslio_init(&io_context, &client_context.eng, socket_utility::socket_read, &socket, socket_utility::socket_write, &socket); + + // Verify certificate pin if configured +#if SSL_ENABLE_CERT_PINNING + if (!cert_pinning::verify(host, &client_context.eng)) { + ssl_debug::log_error("Connection rejected due to certificate pin mismatch\n"); + closesocket(socket); + certificates::close_trust_anchors(); + free(host); + free(path); + return -2; // Pin verification failed + } +#endif + + char* request = string_utility::format_string("GET %s HTTP/1.1\r\nHost: %s\r\nAccept-Encoding: identity\r\nConnection: close\r\n\r\n", path, host); + if (request == NULL) + { + ssl_debug::log_error("Failed to allocate HTTP request string\n"); + closesocket(socket); + certificates::close_trust_anchors(); + free(host); + free(path); + return -5; + } + br_sslio_write_all(&io_context, request, strlen(request)); + br_sslio_flush(&io_context); + free(request); + + data_store* data = new data_store(); + pointer_vector* headers = new pointer_vector(false); + populate_headers(&io_context, data, headers); + + int64_t content_length = -1; + char* redirect_url = NULL; + + bool has_redirect = false; + for (uint32_t i = 0; i < headers->count(); i++) + { + pointer_vector* parts = string_utility::split_first(headers->get(i), ":", true); + if (parts->count() != 2) + { + continue; + } + if (strcmp(parts->get(0), "Content-Length") == 0) + { + content_length = string_utility::string_to_int64(parts->get(1)); + } + if (strcmp(parts->get(0), "Location") == 0) + { + has_redirect = true; + redirect_url = strdup(parts->get(1)); + } + delete parts; + } + + delete headers; + + if (has_redirect == true) + { + closesocket(socket); + certificates::close_trust_anchors(); + delete data; + free(host); + free(path); + + int result = download_file(redirect_url, port, file_path); + if (redirect_url != NULL) + { + free(redirect_url); + } + return result; + } + + if (redirect_url != NULL) + { + free(redirect_url); + } + + if (content_length < 0) + { + chunk_download(&io_context, data, file_path); + } + else + { + download(&io_context, data, file_path, content_length); + } + + // Cache session for future resumption +#if SSL_ENABLE_SESSION_CACHE + br_ssl_engine_get_session_parameters(&client_context.eng, &session_params); + session_cache::store(host, &session_params); +#endif + + closesocket(socket); + certificates::close_trust_anchors(); + delete data; + + int result = EXIT_FAILURE; + if (br_ssl_engine_current_state(&client_context.eng) == BR_SSL_CLOSED) + { + int error = br_ssl_engine_last_error(&client_context.eng); + if (error == 0) + { + ssl_debug::log_info("Connection closed cleanly\n"); + ssl_debug::log_handshake_result(&client_context.eng); + result = EXIT_SUCCESS; + } + else + { + ssl_debug::log_ssl_error(error); + result = EXIT_FAILURE; + } + } + else + { + ssl_debug::log_error("Socket closed without proper SSL termination\n"); + result = EXIT_FAILURE; + } + + /* Clean up allocated host and path */ + free(host); + free(path); + + return result; +} + +// Private + +/* Helper to check if character is linear whitespace (space or tab) */ +static bool is_lws(char c) +{ + return (c == ' ' || c == '\t'); +} + +void client::populate_headers(br_sslio_context* io_context, data_store* data, pointer_vector* headers) +{ + unsigned char* read_buffer = (unsigned char*)malloc(READ_BUFFER_SIZE); + if (read_buffer == NULL) + { + ssl_debug::log_error("Failed to allocate read buffer\n"); + return; + } + char* pending_header = NULL; /* For handling line continuations */ + + while (true) + { + int bytes_read = br_sslio_read(io_context, read_buffer, READ_BUFFER_SIZE); + if (bytes_read < 0) + { + break; + } + + data->add_range(read_buffer, 0, bytes_read); + + bool eof_headers = false; + while (true) + { + unsigned char* data_buffer = data->get_all(); + int offset = string_utility::find_crlf(data_buffer, data->count()); + if (offset < 0) + { + break; + } + + char* header_line = (char*)malloc(offset + 1); + if (header_line == NULL) + { + break; + } + memcpy(header_line, data_buffer, offset); + header_line[offset] = 0; + data->remove_range(0, offset + 2); + + /* Empty line signals end of headers */ + if (header_line[0] == 0) + { + free(header_line); + /* Flush any pending header */ + if (pending_header != NULL) + { + debug_utility::debug_print("Header Line: %s\n", pending_header); + headers->add(pending_header); + pending_header = NULL; + } + eof_headers = true; + break; + } + + /* RFC 7230: Line continuation - line starts with whitespace */ + if (is_lws(header_line[0]) && pending_header != NULL) + { + /* Skip leading whitespace on continuation line */ + char* continuation = header_line; + while (*continuation && is_lws(*continuation)) + { + continuation++; + } + + /* Append to pending header with single space separator */ + size_t pending_len = strlen(pending_header); + size_t cont_len = strlen(continuation); + char* merged = (char*)malloc(pending_len + 1 + cont_len + 1); + if (merged == NULL) + { + free(header_line); + free(pending_header); + pending_header = NULL; + break; + } + memcpy(merged, pending_header, pending_len); + merged[pending_len] = ' '; + memcpy(merged + pending_len + 1, continuation, cont_len + 1); + + free(pending_header); + free(header_line); + pending_header = merged; + } + else + { + /* New header - flush pending if any */ + if (pending_header != NULL) + { + debug_utility::debug_print("Header Line: %s\n", pending_header); + headers->add(pending_header); + } + pending_header = header_line; + } + } + + if (eof_headers == true) + { + break; + } + } + + /* Flush any remaining pending header */ + if (pending_header != NULL) + { + debug_utility::debug_print("Header Line: %s\n", pending_header); + headers->add(pending_header); + } + + free(read_buffer); +} + +void client::chunk_download(br_sslio_context* io_context, data_store* data, const char* file_path) +{ + unsigned char* read_buffer = (unsigned char*)malloc(READ_BUFFER_SIZE); + if (read_buffer == NULL) + { + ssl_debug::log_error("Failed to allocate read buffer\n"); + return; + } + + FILE* file = fopen(file_path, "wb"); + if (file == NULL) + { + ssl_debug::log_error("Failed to open file for writing: %s\n", file_path); + free(read_buffer); + return; + } + + int64_t chunk_size = 0; + bool looking_for_chunk_header = true; + + int64_t bytes_written = 0; + while (true) + { + int bytes_read = br_sslio_read(io_context, read_buffer, READ_BUFFER_SIZE); + if (bytes_read < 0) + { + break; + } + + data->add_range(read_buffer, 0, bytes_read); + + if (looking_for_chunk_header == true) + { + unsigned char* data_buffer = data->get_all(); + int offset = string_utility::find_crlf(data_buffer, data->count()); + if (offset < 0) + { + continue; + } + + char* chunk_hex = (char*)malloc(offset + 1); + if (chunk_hex == NULL) + { + break; + } + memcpy(chunk_hex, data_buffer, offset); + chunk_hex[offset] = 0; + + if (chunk_hex[0] != 0) + { + chunk_size = string_utility::hex_to_int64(chunk_hex); + looking_for_chunk_header = false; + } + + free(chunk_hex); + data->remove_range(0, offset + 2); + } + + if (looking_for_chunk_header == false) + { + int64_t bytes_to_get = min(chunk_size, (int64_t)data->count()); + if (bytes_to_get != chunk_size) + { + continue; + } + if (file != NULL) + { + fwrite(data->get_all(), 1, bytes_to_get, file); + } + + bytes_written += data->count(); + debug_utility::debug_print("Written %lld bytes of unknown bytes\n", bytes_written); + + data->remove_range(0, bytes_to_get); + looking_for_chunk_header = true; + } + } + + fclose(file); + free(read_buffer); +} + +void client::download(br_sslio_context* io_context, data_store* data, const char* file_path, int64_t content_length) +{ + unsigned char* read_buffer = (unsigned char*)malloc(READ_BUFFER_SIZE); + if (read_buffer == NULL) + { + ssl_debug::log_error("Failed to allocate read buffer\n"); + return; + } + + FILE* file = fopen(file_path, "wb"); + if (file == NULL) + { + ssl_debug::log_error("Failed to open file for writing: %s\n", file_path); + free(read_buffer); + return; + } + + int64_t bytes_written = 0; + while (true) + { + int bytes_read = br_sslio_read(io_context, read_buffer, READ_BUFFER_SIZE); + if (bytes_read < 0) + { + break; + } + + data->add_range(read_buffer, 0, bytes_read); + if (file != NULL) + { + fwrite(data->get_all(), 1, data->count(), file); + } + + bytes_written += data->count(); + debug_utility::debug_print("Written %lld bytes of ", bytes_written); + debug_utility::debug_print("%lld bytes\n", content_length); + data->remove_range(0, data->count()); + } + + fclose(file); + free(read_buffer); +} \ No newline at end of file diff --git a/BearSSL-OG/client.h b/BearSSL-OG/client.h new file mode 100644 index 0000000..0488e17 --- /dev/null +++ b/BearSSL-OG/client.h @@ -0,0 +1,17 @@ +#pragma once + +#include "pointer_vector.h" +#include "data_store.h" + +#include +#include + +class client +{ +public: + int download_file(const char* url, uint16_t port, const char* file_path); +private: + void populate_headers(br_sslio_context* io_context, data_store* data, pointer_vector* headers); + void chunk_download(br_sslio_context* io_context, data_store* data, const char* file_path); + void download(br_sslio_context* io_context, data_store* data, const char* file_path, int64_t content_length); +}; \ No newline at end of file diff --git a/BearSSL-OG/data_store.cpp b/BearSSL-OG/data_store.cpp new file mode 100644 index 0000000..b48cc20 --- /dev/null +++ b/BearSSL-OG/data_store.cpp @@ -0,0 +1,108 @@ +#include "data_store.h" + +#include +#include + +data_store::data_store() +{ + mSize = 0; + mMaxSize = DATA_SIZE_INCREMENT; + mValueContainer = (unsigned char*)malloc(mMaxSize); + if (mValueContainer == NULL) + { + mMaxSize = 0; + return; + } +} + +data_store::~data_store() +{ + free(mValueContainer); +} + +void data_store::add(unsigned char value) +{ + if (mSize == mMaxSize) + { + unsigned char* reallocedValueContainers = (unsigned char*)realloc(mValueContainer, (mMaxSize + DATA_SIZE_INCREMENT)); + if (reallocedValueContainers == NULL) + { + return; + } + mMaxSize += DATA_SIZE_INCREMENT; + mValueContainer = reallocedValueContainers; + } + + mValueContainer[mSize] = value; + mSize++; +} + +void data_store::add_range(unsigned char* buffer, uint32_t offset, uint32_t length) +{ + if (buffer == NULL || length == 0) + { + return; + } + for (uint32_t i = 0; i < length; i++) + { + add(buffer[offset + i]); + } +} + +void data_store::remove(uint32_t index) +{ + if (index >= mSize) + { + return; + } + for (uint32_t j = index; j < mSize - 1; j++) + { + mValueContainer[j] = mValueContainer[j + 1]; + } + mSize--; +} + +void data_store::remove_range(uint32_t index, uint32_t count) +{ + if (count == 0) + { + return; + } + if (index + count > mSize) + { + /* Clamp: remove everything from index onward */ + mSize = index; + return; + } + for (uint32_t j = index; j < mSize - count; j++) + { + mValueContainer[j] = mValueContainer[j + count]; + } + mSize -= count; +} + +unsigned char data_store::get(uint32_t index) +{ + if (index >= mSize) + { + return 0; + } + return mValueContainer[index]; +} + +unsigned char* data_store::get_all() +{ + return mValueContainer; +} + +uint32_t data_store::count() +{ + return mSize; +} + +void data_store::clear() +{ + mSize = 0; +} + + diff --git a/BearSSL-OG/data_store.h b/BearSSL-OG/data_store.h new file mode 100644 index 0000000..1524cbe --- /dev/null +++ b/BearSSL-OG/data_store.h @@ -0,0 +1,28 @@ +#pragma once + +#define DATA_SIZE_INCREMENT 65536 + +#include + +class data_store +{ +public: + data_store(); + ~data_store(); + + void add(unsigned char value); + void add_range(unsigned char* buffer, uint32_t offset, uint32_t length); + void remove(uint32_t index); + void remove_range(uint32_t index, uint32_t count); + unsigned char get(uint32_t index); + unsigned char* get_all(); + uint32_t count(); + void clear(); + +private: + + unsigned char* mValueContainer; + uint32_t mSize; + uint32_t mMaxSize; +}; + diff --git a/BearSSL-OG/debug_utility.cpp b/BearSSL-OG/debug_utility.cpp new file mode 100644 index 0000000..6ba3c4b --- /dev/null +++ b/BearSSL-OG/debug_utility.cpp @@ -0,0 +1,28 @@ +#include "debug_utility.h" + +#include +#include +#include + +int debug_utility::debug_print(const char* format, ...) +{ + /* Use a fixed buffer since VS2003 doesn't support va_copy */ + char message[512]; + va_list args; + int length; + + va_start(args, format); + length = _vsnprintf(message, sizeof(message) - 1, format, args); + va_end(args); + + /* Ensure null termination */ + if (length < 0 || length >= (int)sizeof(message)) { + message[sizeof(message) - 1] = '\0'; + length = (int)sizeof(message) - 1; + } else { + message[length] = '\0'; + } + + OutputDebugStringA(message); + return length; +} \ No newline at end of file diff --git a/BearSSL-OG/debug_utility.h b/BearSSL-OG/debug_utility.h new file mode 100644 index 0000000..62c7817 --- /dev/null +++ b/BearSSL-OG/debug_utility.h @@ -0,0 +1,7 @@ +#pragma once + +class debug_utility +{ +public: + static int debug_print(const char* format, ...); +}; diff --git a/BearSSL-OG/key-ec.h b/BearSSL-OG/key-ec.h new file mode 100644 index 0000000..1ca82f5 --- /dev/null +++ b/BearSSL-OG/key-ec.h @@ -0,0 +1,45 @@ +#ifndef KEY_EC_H__ +#define KEY_EC_H__ + +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 "bearssl.h" + +/* + * The private key for the server certificate (EC). + */ + +static const unsigned char EC_X[] = { + 0x03, 0x91, 0x5B, 0x42, 0x06, 0x90, 0x73, 0x91, 0x1B, 0x48, 0xEF, 0x08, + 0xFB, 0xB5, 0xAD, 0x75, 0x65, 0xF9, 0xE6, 0xF7, 0x21, 0x47, 0x62, 0x48, + 0xFA, 0x3F, 0x97, 0x7B, 0x70, 0x9D, 0x86, 0xA5 +}; + +static const br_ec_private_key EC = { + 23, + (unsigned char *)EC_X, sizeof EC_X +}; + +#endif /* KEY_EC_H__ */ diff --git a/BearSSL-OG/key-ee-ec.pem b/BearSSL-OG/key-ee-ec.pem new file mode 100644 index 0000000..2e6a136 --- /dev/null +++ b/BearSSL-OG/key-ee-ec.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIAORW0IGkHORG0jvCPu1rXVl+eb3IUdiSPo/l3twnYaloAoGCCqGSM49AwEHoUQDQgAE +Xzidp/9Niq/2NDlGGvw63/Qjqqnq+8UI3gCOvnmlN1hMbd0ByqtH34m2xxcfOPwdIBTdRcDgj5NO +OAv86ZmhSQ== +-----END EC PRIVATE KEY----- diff --git a/BearSSL-OG/key-ee-rsa.pem b/BearSSL-OG/key-ee-rsa.pem new file mode 100644 index 0000000..e8b22b4 --- /dev/null +++ b/BearSSL-OG/key-ee-rsa.pem @@ -0,0 +1,23 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA1HodJ7orOmeykWr754NEyu0cda3dTYNi1qpolbIkIXsVriqZaBXtZvC4WOfT +9S7G2Spe5w4u5/xnWcDIYX1LpG/dn9nIhYdkx7oaDynUlqh4mmtiIKky0O6pjChhR6JQKmP2Id7a +2NXwf8UAgnDmo79ciSdPUZJ3A8OwzC477CPyL1NBr4mT/9KAsUOX3tYZoJISej1meeHBvOF3cKKL +PUaEUz/kTkJBN5IeH/04s/fvhzmA01bP9OAT3mSwcqQDhMRB7W/6PuLKBCDS19wsgit64m2hHEjb +z4lPNJc9KKhT2ufB4XMVozB2f48jQhQ9UTTSWq08m8vI/n9ujkDzvQIDAQABAoIBADzb40jzQpl+ +hT+wsIl96HDlXI76Z1Zh6SgKdF1YQpASdMHHstwE19Rx46OXd3cVWGBwifFNdzL8cU/cb6i43jcx +0X2NQCm6/6tTi05HkXw7shus4VTwkb0VdxvNnxuJCsQxkJjf/7g3AyVdtIkoNG+3ipZAW7BGLu+1 +mAjLv18h4LniI8JGWQK75z8xNQzEdOFVyqC1PujjC5emesxlRW8Ks+MzQ+20WTpHGkLAoLJZJ1XE +bDQqFbkRXu4imKLtA4iyBrEpXEKZR85tVO+NQOGdPyH/ugK23nSDcJlI2PTHSlGABTpZZUmigO4O +b8lppU7cFa2JemKG3kEj0BWDOWMCgYEA+fYynFHXcbJi7YEk2vapLMMtVZSVUeU2Ep4uH47YIiJk +XqP8YPAU3BBIb08afcw3Iyd2tjGq3nDJ7KsKUPHqeXl0vjurLmOXom8KRXvXbNJtG3AxA68miyjF ++ElnRUHx0zUFJyp5IdoGtj2i6DxA+m/E/PXEBeuaMapAfl7uIlsCgYEA2Zwa3JRR9sGW2g4RPzco +ejOwxL7faCvTHGVnejyvWVCrKTYXORVxl2LdzSXujf8mj3Ehvo+chU464STH4Urf0GCzxEQurHMW +XwfJOnNe2pvu4rSpPTMUe+6n1Kz3U+Y+8IVXTIuWG93XNvyJN1l1lnWLLvcELSmJ2befcTvi7ccC +gYEA5PwCLyvWRwTZFaRaI/EU17nRHPYpuEVXPMUFkclk/BgvhHeLay5knZiZEscPiLB8zkqHuK5V +TsNaZ+HkaHTFjRSTuvWkgrGfpqE8cpzZo4o9g4ZKkIpyr8bhXOu5nDumEgsfNlr1bupxfZ+HTmJs +UD/14JowQhAsSFUkEeBbHMMCgYEAjazgoDPAmVK4kAcQm4Ohys3UjINomD3QGHC8ygywbQnkJdSd +kgCwD8vCdEn54mD4DfOt8I83bGLeWq7Do55H0TbkUyfA622SZxR+optyagmToe3VMY8MCxP6GLDz +5Z/F4notuBw5ArOP5rDL9Uk9EVQ95bnU8kJVCXZPTD2dJQkCgYByDKfPBpVp9HUgNAPgz5pRk/VC +LvKFvs5POLWMoplC871lOOI0PyGd9b2zv3M8GN728H+hwlXyOOkOHjHn21HFcY1ncTqfVVJg7kX2 +CJiBt3sv8pZ9c9Cmq6qDSUE1qZBnztO5c1SqhACIiJAdhpvluM6JChtHYjHCP8OMhgk8hg== +-----END RSA PRIVATE KEY----- diff --git a/BearSSL-OG/key-ica-ec.pem b/BearSSL-OG/key-ica-ec.pem new file mode 100644 index 0000000..7443098 --- /dev/null +++ b/BearSSL-OG/key-ica-ec.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIEJOkvo4MZ9N+wlTodEzmWor1RauybudPe92K15viDbzoAoGCCqGSM49AwEHoUQDQgAE +cC6SggEXbG2r4dFjCUhJ0qY1UtM8c7uyiDeYh/GN4Oxlmg4T9e2RYci2bTOEbq6OVYDNSZ4Hv9Cu +nebQsycWoQ== +-----END EC PRIVATE KEY----- diff --git a/BearSSL-OG/key-ica-rsa.pem b/BearSSL-OG/key-ica-rsa.pem new file mode 100644 index 0000000..2e38e34 --- /dev/null +++ b/BearSSL-OG/key-ica-rsa.pem @@ -0,0 +1,23 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAs+hrr5wWUuOBDFCrJc7MDcfyH39Q3yxcNdZiLmMnQafkU6hLJ/oTkaP6CUov +O17Pd7OKwc1JlZx1DWR07+TXS7mhm2jSMHFI6vdLFN8/R6nYu+yPKMz637QflHyW/AgFKPno9C8v +7mKcijrghVhgtg8tMLTAQVSRTB9frfEZ8MAipn3YP3k0WUJ7W7VBxGR/Us88NyKhL3kllCRBwj/6 +x3X7SLUNGKf0VPMubthDWMSrUOgFrZG2HgF1s1Sc3qCZFfus8VyXSVHM71gSb3NrszQUAQ9anfqq +1pPT4urDq7xO7cxRobj4lLa0LKiGKx/2UUMpUl4TibNqeGBOTsAbpQIDAQABAoIBAAtBpQ85SGpK +QsZG+9ZjQIAyPPN8j05PY7uYnM8DNC8W9qHHW2B2dKf9pwTSx+7CiV+Xc7yZgBukzOwYF3r1CgV6 +aWKkZdZTGDlfXKrDJx3wQhfL/s8SODYr+nfbbcT6KXx9WnaAx1J2iA3cDjU5qN9rRqwP+yF7TZYC +NoXXGoTmHb7gj1H1IJNdiUgG0netXpM2HydRLzwHDweKav6sm4V4TTeHPYokVp8W7lL7xRhwQXVD +lcE1noY5NczXV88k9n0EbqGDwX3pJoDC/xWzBFh/+oupxotM4KY2dKJGmtKTmiIef3u43CPv5SYh +V2OcEXn+joV5qHGhg6yN+ri0/ucCgYEA4x2NBFNtbpx3lmc2r2hwfbawcTVKKlxqJWdoG2bd7HQz +bO+uqtxhLOxEou4S9uPUVylvpNlDs3xQ+DF9p8oTo5XlHvA6DT/cAjWSQ+MRHqCV30T0lDSd0McZ +4PaV1nq94bGuPVrGe/Dex5dL+VVhn2tpoqwudsyx5hHA8hFE1zcCgYEAysnhrQa1HZQ0hOaA2c/e +A8I47dEIyGi4N6uJVBUMM1ecKifs4FKybOtI+XM3mwuAXUyVQGi2SZBBpE4bN3oUDWGwYF7SAJV0 +JJHpBxlZBvYRC7Vfh8HFPYIQCynP0Q4BeQVDaCPW3puJsTWnn2lNhT/PsSm3v76JwTRrBoqaGgMC +gYAwyyiAxWu9V+BZb9NP3CBO4fEGYWyNrU0gvBahzHfhVRW3Ucc07iPygtA8MOniIRB9qWlTAVqK +NSswJ3HXmpKdkpanDvVp405hKyFBdIc5DUclsKrbLHK7aAsnSdLnQXeKBaJpjBcYiadTOi4YYz+W +AH2xdUyGOXP++dF6MDuaAQKBgQCtWyHygW5pR94R0t9J1FpuCiYSn4ULlgINjTXLzGZuqbGVlCX6 +qpdfZ1At92IMyCtHFwXsVtemUYzcAe1gYpsryVw3Njf+ScVM0fNMn02tFsQBp15wNqT/7OT8NhUz +GO8HXwl9yE2SZZKzDDQsoZ+kjqVlRU2QvDkVElN/9xK/swKBgDz6m4XHvhvITo2bd8/i4FxTN1gr +napgAc2DHOzCmeyYCjKvZAJDLeNleni1kj1UfrzVrH2BFM38asRJu8xPI4WjfH1fFktNjXVu6Ctk +YFu0/0TlWkzowZHmE/K0M0tuJLt42m/DLW8deMyl38x+PUPUZb4OdVAKAua/voOMZtQw +-----END RSA PRIVATE KEY----- diff --git a/BearSSL-OG/key-root-ec.pem b/BearSSL-OG/key-root-ec.pem new file mode 100644 index 0000000..e76db90 --- /dev/null +++ b/BearSSL-OG/key-root-ec.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINx41f6h/utlj52XNFbIGJdkF3qZy1/g9hH2/yV4t/tnoAoGCCqGSM49AwEHoUQDQgAE +cXS6q7kwLoHV5Vf58yBoDJz5ZNu0IA1t6kDQSm5C/baaaCVE9t97xPze3Xu7xdt8dj9BZkBu26eH +wuXYxfN/jQ== +-----END EC PRIVATE KEY----- diff --git a/BearSSL-OG/key-root-rsa.pem b/BearSSL-OG/key-root-rsa.pem new file mode 100644 index 0000000..82a2eb0 --- /dev/null +++ b/BearSSL-OG/key-root-rsa.pem @@ -0,0 +1,23 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAttk01FD9s696c/HOOL9db0Xh/U6xmMZggybSF9HFt5qjwd5jOZec8F5cyBwX +uYgZbfC2LjBQoVRuk8DbzzDLnx4nefHDmVI1qj2237CtfMtJzcDt52YQKunOKB8hUPp3TC3a7zxY +606/zun7Gtqjg6PNo8qTgNza8xfMeqszgJyy1H9GP8U83GGUtycpbiq8Wwk21MY7Deu+ztsdHLwQ +anFxs/LKKJp38orsQu+xSo7i8hoyKs3ApkYsmsKFN5F/RqGTgaF0Zt+6szkgkZP6HaGohefk+Qf2 +EPaoJwG2fxLDQMPJ4rCrSRg6ZLZZt5W1ljbfImmqcmpUTicpow6XFQIDAQABAoIBAENjavKDBPWn +yygXKqtEb/GWHlNmoNKO7jv33z9TGxzvW8IULZqos3jtNiG0JNRGgiTALcx5FwZWYUiIMBq8v5bd +nKv3O+DyaP/crdzkNxRCsekoXSXGuleugsHLs1IudTA4yDMamSTkCZH/LwH3KYNXJ+9hNhqsiu9D +yqM9HIad2k/hmVFv4NDdH3VWqsQJFfrGEXgKRJKNpuzKeST3oo4iLcwH9NGiKXfjW23ekOiLYFwZ +q8Yd6tOgNLpGuDWk9rlXPJALyXFZ/3UXZaKU5f0ZRfPfMQgM8toeWeWJS0FW7g6aLCJATsfOu/II +j3nTVCPryvGF4mwe/y+Rgbd67xMCgYEA3Wpiac27hvbLzwbSTWYsKql5uKV0HTim3haNDuzMHJVY +ZRJSuTY+rZBoaiuDRKMCMI3dQM8AZUJfHQclyTxjtn17Ig8cTKMN6Wr2MRTBplCq3wNLVjbOPAE2 +cv74gUfgpRLdlyueYO7j6PcTS+l41+wB1A/zAEm346Eoxoztt5cCgYEA02ipYQFX4T+8BSkcEyzP +qeMT9d3BLPm4tTeq2sXRgcfEbF/ENcAX9OfPSEx4kVtzsfJXma5/dg0fuVgl1hO5WLBT+L6MJ/A2 +sGX3Y7x+doXI0xcNd/Epr7oWqZuCO7477vzJcNtud/KQJj2EmRNaHKKtaohqO5dnNhsM540lnDMC +gYBU40KT2eJ5ngkJeE4Mio2IVa1rE1PvGBcxsmemPzcKBl/7cAjzJU7mcCT3/3K2T+C5CMq43CQE +rmuUz3a3LkX0YytgJXbuEt10jiORMaoEv4yjL7okdaKf8r8TW5mexxXjc9Ys7PYtp6kNWhy1z+8a +qUsSKIM7qwerZ9AgP0usRQKBgQDEHy4y/coG/tdweii/aSzlT/Huf2B8VtaR1yi7eBTaLvb8CwO9 +UY1n970GN1sKjiqQhF/cBFPesmIh0bKYHQgvTLU555uiWWiC0LVmYzF2xrn9ij9GbAXeLeZkRg3V +Wq/DD+PYvNiIkhBESYG/eIJ6WjhCwna6/cQUH5gjH4AqnQKBgQCsKyjLtx+FeFu7PZ8AgCGWRVvs +suxB74pxlMqMgBbBHyAGQOTTuaaTr/gwNXAAErAXS1X9VsAcAkM/yFv19mdZmJQG9vUMOe48AZDB +c7xt3t3Ul71eAlbAYkrQGtq64yO3w7ny4C7GUVqMX03XwKToCrXqeKfGwrZGNP+lgZYrbw== +-----END RSA PRIVATE KEY----- diff --git a/BearSSL-OG/key-rsa.h b/BearSSL-OG/key-rsa.h new file mode 100644 index 0000000..da0ff38 --- /dev/null +++ b/BearSSL-OG/key-rsa.h @@ -0,0 +1,113 @@ +#ifndef KEY_RSA_H__ +#define KEY_RSA_H__ + +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 "bearssl.h" + +/* + * The private key for the server certificate (RSA). + */ + +static const unsigned char RSA_P[] = { + 0xF9, 0xF6, 0x32, 0x9C, 0x51, 0xD7, 0x71, 0xB2, 0x62, 0xED, 0x81, 0x24, + 0xDA, 0xF6, 0xA9, 0x2C, 0xC3, 0x2D, 0x55, 0x94, 0x95, 0x51, 0xE5, 0x36, + 0x12, 0x9E, 0x2E, 0x1F, 0x8E, 0xD8, 0x22, 0x22, 0x64, 0x5E, 0xA3, 0xFC, + 0x60, 0xF0, 0x14, 0xDC, 0x10, 0x48, 0x6F, 0x4F, 0x1A, 0x7D, 0xCC, 0x37, + 0x23, 0x27, 0x76, 0xB6, 0x31, 0xAA, 0xDE, 0x70, 0xC9, 0xEC, 0xAB, 0x0A, + 0x50, 0xF1, 0xEA, 0x79, 0x79, 0x74, 0xBE, 0x3B, 0xAB, 0x2E, 0x63, 0x97, + 0xA2, 0x6F, 0x0A, 0x45, 0x7B, 0xD7, 0x6C, 0xD2, 0x6D, 0x1B, 0x70, 0x31, + 0x03, 0xAF, 0x26, 0x8B, 0x28, 0xC5, 0xF8, 0x49, 0x67, 0x45, 0x41, 0xF1, + 0xD3, 0x35, 0x05, 0x27, 0x2A, 0x79, 0x21, 0xDA, 0x06, 0xB6, 0x3D, 0xA2, + 0xE8, 0x3C, 0x40, 0xFA, 0x6F, 0xC4, 0xFC, 0xF5, 0xC4, 0x05, 0xEB, 0x9A, + 0x31, 0xAA, 0x40, 0x7E, 0x5E, 0xEE, 0x22, 0x5B +}; + +static const unsigned char RSA_Q[] = { + 0xD9, 0x9C, 0x1A, 0xDC, 0x94, 0x51, 0xF6, 0xC1, 0x96, 0xDA, 0x0E, 0x11, + 0x3F, 0x37, 0x28, 0x7A, 0x33, 0xB0, 0xC4, 0xBE, 0xDF, 0x68, 0x2B, 0xD3, + 0x1C, 0x65, 0x67, 0x7A, 0x3C, 0xAF, 0x59, 0x50, 0xAB, 0x29, 0x36, 0x17, + 0x39, 0x15, 0x71, 0x97, 0x62, 0xDD, 0xCD, 0x25, 0xEE, 0x8D, 0xFF, 0x26, + 0x8F, 0x71, 0x21, 0xBE, 0x8F, 0x9C, 0x85, 0x4E, 0x3A, 0xE1, 0x24, 0xC7, + 0xE1, 0x4A, 0xDF, 0xD0, 0x60, 0xB3, 0xC4, 0x44, 0x2E, 0xAC, 0x73, 0x16, + 0x5F, 0x07, 0xC9, 0x3A, 0x73, 0x5E, 0xDA, 0x9B, 0xEE, 0xE2, 0xB4, 0xA9, + 0x3D, 0x33, 0x14, 0x7B, 0xEE, 0xA7, 0xD4, 0xAC, 0xF7, 0x53, 0xE6, 0x3E, + 0xF0, 0x85, 0x57, 0x4C, 0x8B, 0x96, 0x1B, 0xDD, 0xD7, 0x36, 0xFC, 0x89, + 0x37, 0x59, 0x75, 0x96, 0x75, 0x8B, 0x2E, 0xF7, 0x04, 0x2D, 0x29, 0x89, + 0xD9, 0xB7, 0x9F, 0x71, 0x3B, 0xE2, 0xED, 0xC7 +}; + +static const unsigned char RSA_DP[] = { + 0xE4, 0xFC, 0x02, 0x2F, 0x2B, 0xD6, 0x47, 0x04, 0xD9, 0x15, 0xA4, 0x5A, + 0x23, 0xF1, 0x14, 0xD7, 0xB9, 0xD1, 0x1C, 0xF6, 0x29, 0xB8, 0x45, 0x57, + 0x3C, 0xC5, 0x05, 0x91, 0xC9, 0x64, 0xFC, 0x18, 0x2F, 0x84, 0x77, 0x8B, + 0x6B, 0x2E, 0x64, 0x9D, 0x98, 0x99, 0x12, 0xC7, 0x0F, 0x88, 0xB0, 0x7C, + 0xCE, 0x4A, 0x87, 0xB8, 0xAE, 0x55, 0x4E, 0xC3, 0x5A, 0x67, 0xE1, 0xE4, + 0x68, 0x74, 0xC5, 0x8D, 0x14, 0x93, 0xBA, 0xF5, 0xA4, 0x82, 0xB1, 0x9F, + 0xA6, 0xA1, 0x3C, 0x72, 0x9C, 0xD9, 0xA3, 0x8A, 0x3D, 0x83, 0x86, 0x4A, + 0x90, 0x8A, 0x72, 0xAF, 0xC6, 0xE1, 0x5C, 0xEB, 0xB9, 0x9C, 0x3B, 0xA6, + 0x12, 0x0B, 0x1F, 0x36, 0x5A, 0xF5, 0x6E, 0xEA, 0x71, 0x7D, 0x9F, 0x87, + 0x4E, 0x62, 0x6C, 0x50, 0x3F, 0xF5, 0xE0, 0x9A, 0x30, 0x42, 0x10, 0x2C, + 0x48, 0x55, 0x24, 0x11, 0xE0, 0x5B, 0x1C, 0xC3 +}; + +static const unsigned char RSA_DQ[] = { + 0x8D, 0xAC, 0xE0, 0xA0, 0x33, 0xC0, 0x99, 0x52, 0xB8, 0x90, 0x07, 0x10, + 0x9B, 0x83, 0xA1, 0xCA, 0xCD, 0xD4, 0x8C, 0x83, 0x68, 0x98, 0x3D, 0xD0, + 0x18, 0x70, 0xBC, 0xCA, 0x0C, 0xB0, 0x6D, 0x09, 0xE4, 0x25, 0xD4, 0x9D, + 0x92, 0x00, 0xB0, 0x0F, 0xCB, 0xC2, 0x74, 0x49, 0xF9, 0xE2, 0x60, 0xF8, + 0x0D, 0xF3, 0xAD, 0xF0, 0x8F, 0x37, 0x6C, 0x62, 0xDE, 0x5A, 0xAE, 0xC3, + 0xA3, 0x9E, 0x47, 0xD1, 0x36, 0xE4, 0x53, 0x27, 0xC0, 0xEB, 0x6D, 0x92, + 0x67, 0x14, 0x7E, 0xA2, 0x9B, 0x72, 0x6A, 0x09, 0x93, 0xA1, 0xED, 0xD5, + 0x31, 0x8F, 0x0C, 0x0B, 0x13, 0xFA, 0x18, 0xB0, 0xF3, 0xE5, 0x9F, 0xC5, + 0xE2, 0x7A, 0x2D, 0xB8, 0x1C, 0x39, 0x02, 0xB3, 0x8F, 0xE6, 0xB0, 0xCB, + 0xF5, 0x49, 0x3D, 0x11, 0x54, 0x3D, 0xE5, 0xB9, 0xD4, 0xF2, 0x42, 0x55, + 0x09, 0x76, 0x4F, 0x4C, 0x3D, 0x9D, 0x25, 0x09 +}; + +static const unsigned char RSA_IQ[] = { + 0x72, 0x0C, 0xA7, 0xCF, 0x06, 0x95, 0x69, 0xF4, 0x75, 0x20, 0x34, 0x03, + 0xE0, 0xCF, 0x9A, 0x51, 0x93, 0xF5, 0x42, 0x2E, 0xF2, 0x85, 0xBE, 0xCE, + 0x4F, 0x38, 0xB5, 0x8C, 0xA2, 0x99, 0x42, 0xF3, 0xBD, 0x65, 0x38, 0xE2, + 0x34, 0x3F, 0x21, 0x9D, 0xF5, 0xBD, 0xB3, 0xBF, 0x73, 0x3C, 0x18, 0xDE, + 0xF6, 0xF0, 0x7F, 0xA1, 0xC2, 0x55, 0xF2, 0x38, 0xE9, 0x0E, 0x1E, 0x31, + 0xE7, 0xDB, 0x51, 0xC5, 0x71, 0x8D, 0x67, 0x71, 0x3A, 0x9F, 0x55, 0x52, + 0x60, 0xEE, 0x45, 0xF6, 0x08, 0x98, 0x81, 0xB7, 0x7B, 0x2F, 0xF2, 0x96, + 0x7D, 0x73, 0xD0, 0xA6, 0xAB, 0xAA, 0x83, 0x49, 0x41, 0x35, 0xA9, 0x90, + 0x67, 0xCE, 0xD3, 0xB9, 0x73, 0x54, 0xAA, 0x84, 0x00, 0x88, 0x88, 0x90, + 0x1D, 0x86, 0x9B, 0xE5, 0xB8, 0xCE, 0x89, 0x0A, 0x1B, 0x47, 0x62, 0x31, + 0xC2, 0x3F, 0xC3, 0x8C, 0x86, 0x09, 0x3C, 0x86 +}; + +static const br_rsa_private_key RSA = { + 2048, + (unsigned char *)RSA_P, sizeof RSA_P, + (unsigned char *)RSA_Q, sizeof RSA_Q, + (unsigned char *)RSA_DP, sizeof RSA_DP, + (unsigned char *)RSA_DQ, sizeof RSA_DQ, + (unsigned char *)RSA_IQ, sizeof RSA_IQ +}; + +#endif /* KEY_RSA_H__ */ diff --git a/BearSSL-OG/libbearssl.vcproj b/BearSSL-OG/libbearssl.vcproj new file mode 100644 index 0000000..e791869 --- /dev/null +++ b/BearSSL-OG/libbearssl.vcproj @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BearSSL-OG/libbearssl/inc/bearssl.h b/BearSSL-OG/libbearssl/inc/bearssl.h new file mode 100644 index 0000000..310edb2 --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_H__ +#define BR_BEARSSL_H__ + +#include +#include + +/** \mainpage BearSSL API + * + * # API Layout + * + * The functions and structures defined by the BearSSL API are located + * in various header files: + * + * | Header file | Elements | + * | :-------------- | :------------------------------------------------ | + * | bearssl_hash.h | Hash functions | + * | bearssl_hmac.h | HMAC | + * | bearssl_kdf.h | Key Derivation Functions | + * | bearssl_rand.h | Pseudorandom byte generators | + * | bearssl_prf.h | PRF implementations (for SSL/TLS) | + * | bearssl_block.h | Symmetric encryption | + * | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) | + * | bearssl_rsa.h | RSA encryption and signatures | + * | bearssl_ec.h | Elliptic curves support (including ECDSA) | + * | bearssl_ssl.h | SSL/TLS engine interface | + * | bearssl_x509.h | X.509 certificate decoding and validation | + * | bearssl_pem.h | Base64/PEM decoding support functions | + * + * Applications using BearSSL are supposed to simply include `bearssl.h` + * as follows: + * + * #include + * + * The `bearssl.h` file itself includes all the other header files. It is + * possible to include specific header files, but it has no practical + * advantage for the application. The API is separated into separate + * header files only for documentation convenience. + * + * + * # Conventions + * + * ## MUST and SHALL + * + * In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology + * is used. Failure to meet requirements expressed with a "MUST" or + * "SHALL" implies undefined behaviour, which means that segmentation + * faults, buffer overflows, and other similar adverse events, may occur. + * + * In general, BearSSL is not very forgiving of programming errors, and + * does not include much failsafes or error reporting when the problem + * does not arise from external transient conditions, and can be fixed + * only in the application code. This is done so in order to make the + * total code footprint lighter. + * + * + * ## `NULL` values + * + * Function parameters with a pointer type shall not be `NULL` unless + * explicitly authorised by the documentation. As an exception, when + * the pointer aims at a sequence of bytes and is accompanied with + * a length parameter, and the length is zero (meaning that there is + * no byte at all to retrieve), then the pointer may be `NULL` even if + * not explicitly allowed. + * + * + * ## Memory Allocation + * + * BearSSL does not perform dynamic memory allocation. This implies that + * for any functionality that requires a non-transient state, the caller + * is responsible for allocating the relevant context structure. Such + * allocation can be done in any appropriate area, including static data + * segments, the heap, and the stack, provided that proper alignment is + * respected. The header files define these context structures + * (including size and contents), so the C compiler should handle + * alignment automatically. + * + * Since there is no dynamic resource allocation, there is also nothing to + * release. When the calling code is done with a BearSSL feature, it + * may simple release the context structures it allocated itself, with + * no "close function" to call. If the context structures were allocated + * on the stack (as local variables), then even that release operation is + * implicit. + * + * + * ## Structure Contents + * + * Except when explicitly indicated, structure contents are opaque: they + * are included in the header files so that calling code may know the + * structure sizes and alignment requirements, but callers SHALL NOT + * access individual fields directly. For fields that are supposed to + * be read from or written to, the API defines accessor functions (the + * simplest of these accessor functions are defined as `static inline` + * functions, and the C compiler will optimise them away). + * + * + * # API Usage + * + * BearSSL usage for running a SSL/TLS client or server is described + * on the [BearSSL Web site](https://www.bearssl.org/api1.html). The + * BearSSL source archive also comes with sample code. + */ + +#include "bearssl_hash.h" +#include "bearssl_hmac.h" +#include "bearssl_kdf.h" +#include "bearssl_rand.h" +#include "bearssl_prf.h" +#include "bearssl_block.h" +#include "bearssl_aead.h" +#include "bearssl_rsa.h" +#include "bearssl_ec.h" +#include "bearssl_ssl.h" +#include "bearssl_x509.h" +#include "bearssl_pem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Type for a configuration option. + * + * A "configuration option" is a value that is selected when the BearSSL + * library itself is compiled. Most options are boolean; their value is + * then either 1 (option is enabled) or 0 (option is disabled). Some + * values have other integer values. Option names correspond to macro + * names. Some of the options can be explicitly set in the internal + * `"config.h"` file. + */ +typedef struct { + /** \brief Configurable option name. */ + const char *name; + /** \brief Configurable option value. */ + long value; +} br_config_option; + +/** \brief Get configuration report. + * + * This function returns compiled configuration options, each as a + * 'long' value. Names match internal macro names, in particular those + * that can be set in the `"config.h"` inner file. For boolean options, + * the numerical value is 1 if enabled, 0 if disabled. For maximum + * key sizes, values are expressed in bits. + * + * The returned array is terminated by an entry whose `name` is `NULL`. + * + * \return the configuration report. + */ +const br_config_option *br_get_config(void); + +/* ======================================================================= */ + +/** \brief Version feature: support for time callback. */ +#define BR_FEATURE_X509_TIME_CALLBACK 1 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_aead.h b/BearSSL-OG/libbearssl/inc/bearssl_aead.h new file mode 100644 index 0000000..097e6e8 --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_aead.h @@ -0,0 +1,1059 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_AEAD_H__ +#define BR_BEARSSL_AEAD_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_aead.h + * + * # Authenticated Encryption with Additional Data + * + * This file documents the API for AEAD encryption. + * + * + * ## Procedural API + * + * An AEAD algorithm processes messages and provides confidentiality + * (encryption) and checked integrity (MAC). It uses the following + * parameters: + * + * - A symmetric key. Exact size depends on the AEAD algorithm. + * + * - A nonce (IV). Size depends on the AEAD algorithm; for most + * algorithms, it is crucial for security that any given nonce + * value is never used twice for the same key and distinct + * messages. + * + * - Data to encrypt and protect. + * + * - Additional authenticated data, which is covered by the MAC but + * otherwise left untouched (i.e. not encrypted). + * + * The AEAD algorithm encrypts the data, and produces an authentication + * tag. It is assumed that the encrypted data, the tag, the additional + * authenticated data and the nonce are sent to the receiver; the + * additional data and the nonce may be implicit (e.g. using elements of + * the underlying transport protocol, such as record sequence numbers). + * The receiver will recompute the tag value and compare it with the one + * received; if they match, then the data is correct, and can be + * decrypted and used; otherwise, at least one of the elements was + * altered in transit, normally leading to wholesale rejection of the + * complete message. + * + * For each AEAD algorithm, identified by a symbolic name (hereafter + * denoted as "`xxx`"), the following functions are defined: + * + * - `br_xxx_init()` + * + * Initialise the AEAD algorithm, on a provided context structure. + * Exact parameters depend on the algorithm, and may include + * pointers to extra implementations and context structures. The + * secret key is provided at this point, either directly or + * indirectly. + * + * - `br_xxx_reset()` + * + * Start a new AEAD computation. The nonce value is provided as + * parameter to this function. + * + * - `br_xxx_aad_inject()` + * + * Inject some additional authenticated data. Additional data may + * be provided in several chunks of arbitrary length. + * + * - `br_xxx_flip()` + * + * This function MUST be called after injecting all additional + * authenticated data, and before beginning to encrypt the plaintext + * (or decrypt the ciphertext). + * + * - `br_xxx_run()` + * + * Process some plaintext (to encrypt) or ciphertext (to decrypt). + * Encryption/decryption is done in place. Data may be provided in + * several chunks of arbitrary length. + * + * - `br_xxx_get_tag()` + * + * Compute the authentication tag. All message data (encrypted or + * decrypted) must have been injected at that point. Also, this + * call may modify internal context elements, so it may be called + * only once for a given AEAD computation. + * + * - `br_xxx_check_tag()` + * + * An alternative to `br_xxx_get_tag()`, meant to be used by the + * receiver: the authentication tag is internally recomputed, and + * compared with the one provided as parameter. + * + * This API makes the following assumptions on the AEAD algorithm: + * + * - Encryption does not expand the size of the ciphertext; there is + * no padding. This is true of most modern AEAD modes such as GCM. + * + * - The additional authenticated data must be processed first, + * before the encrypted/decrypted data. + * + * - Nonce, plaintext and additional authenticated data all consist + * in an integral number of bytes. There is no provision to use + * elements whose length in bits is not a multiple of 8. + * + * Each AEAD algorithm has its own requirements and limits on the sizes + * of additional data and plaintext. This API does not provide any + * way to report invalid usage; it is up to the caller to ensure that + * the provided key, nonce, and data elements all fit the algorithm's + * requirements. + * + * + * ## Object-Oriented API + * + * Each context structure begins with a field (called `vtable`) that + * points to an instance of a structure that references the relevant + * functions through pointers. Each such structure contains the + * following: + * + * - `reset` + * + * Pointer to the reset function, that allows starting a new + * computation. + * + * - `aad_inject` + * + * Pointer to the additional authenticated data injection function. + * + * - `flip` + * + * Pointer to the function that transitions from additional data + * to main message data processing. + * + * - `get_tag` + * + * Pointer to the function that computes and returns the tag. + * + * - `check_tag` + * + * Pointer to the function that computes and verifies the tag against + * a received value. + * + * Note that there is no OOP method for context initialisation: the + * various AEAD algorithms have different requirements that would not + * map well to a single initialisation API. + * + * The OOP API is not provided for CCM, due to its specific requirements + * (length of plaintext must be known in advance). + */ + +/** + * \brief Class type of an AEAD algorithm. + */ +typedef struct br_aead_class_ br_aead_class; +struct br_aead_class_ { + + /** + * \brief Size (in bytes) of authentication tags created by + * this AEAD algorithm. + */ + size_t tag_size; + + /** + * \brief Reset an AEAD context. + * + * This function resets an already initialised AEAD context for + * a new computation run. Implementations and keys are + * conserved. This function can be called at any time; it + * cancels any ongoing AEAD computation that uses the provided + * context structure. + + * The provided IV is a _nonce_. Each AEAD algorithm has its + * own requirements on IV size and contents; for most of them, + * it is crucial to security that each nonce value is used + * only once for a given secret key. + * + * \param cc AEAD context structure. + * \param iv AEAD nonce to use. + * \param len AEAD nonce length (in bytes). + */ + void (*reset)(const br_aead_class **cc, const void *iv, size_t len); + + /** + * \brief Inject additional authenticated data. + * + * The provided data is injected into a running AEAD + * computation. Additional data must be injected _before_ the + * call to `flip()`. Additional data can be injected in several + * chunks of arbitrary length. + * + * \param cc AEAD context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ + void (*aad_inject)(const br_aead_class **cc, + const void *data, size_t len); + + /** + * \brief Finish injection of additional authenticated data. + * + * This function MUST be called before beginning the actual + * encryption or decryption (with `run()`), even if no + * additional authenticated data was injected. No additional + * authenticated data may be injected after this function call. + * + * \param cc AEAD context structure. + */ + void (*flip)(const br_aead_class **cc); + + /** + * \brief Encrypt or decrypt some data. + * + * Data encryption or decryption can be done after `flip()` has + * been called on the context. If `encrypt` is non-zero, then + * the provided data shall be plaintext, and it is encrypted in + * place. Otherwise, the data shall be ciphertext, and it is + * decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. + * + * \param cc AEAD context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ + void (*run)(const br_aead_class **cc, int encrypt, + void *data, size_t len); + + /** + * \brief Compute authentication tag. + * + * Compute the AEAD authentication tag. The tag length depends + * on the AEAD algorithm; it is written in the provided `tag` + * buffer. This call terminates the AEAD run: no data may be + * processed with that AEAD context afterwards, until `reset()` + * is called to initiate a new AEAD run. + * + * The tag value must normally be sent along with the encrypted + * data. When decrypting, the tag value must be recomputed and + * compared with the received tag: if the two tag values differ, + * then either the tag or the encrypted data was altered in + * transit. As an alternative to this function, the + * `check_tag()` function may be used to compute and check the + * tag value. + * + * Tag length depends on the AEAD algorithm. + * + * \param cc AEAD context structure. + * \param tag destination buffer for the tag. + */ + void (*get_tag)(const br_aead_class **cc, void *tag); + + /** + * \brief Compute and check authentication tag. + * + * This function is an alternative to `get_tag()`, and is + * normally used on the receiving end (i.e. when decrypting + * messages). The tag value is recomputed and compared with the + * provided tag value. If they match, 1 is returned; on + * mismatch, 0 is returned. A returned value of 0 means that the + * data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length depends on the AEAD algorithm. + * + * \param cc AEAD context structure. + * \param tag tag value to compare with. + * \return 1 on success (exact match of tag value), 0 otherwise. + */ + uint32_t (*check_tag)(const br_aead_class **cc, const void *tag); + + /** + * \brief Compute authentication tag (with truncation). + * + * This function is similar to `get_tag()`, except that the tag + * length is provided. Some AEAD algorithms allow several tag + * lengths, usually by truncating the normal tag. Shorter tags + * mechanically increase success probability of forgeries. + * The range of allowed tag lengths depends on the algorithm. + * + * \param cc AEAD context structure. + * \param tag destination buffer for the tag. + * \param len tag length (in bytes). + */ + void (*get_tag_trunc)(const br_aead_class **cc, void *tag, size_t len); + + /** + * \brief Compute and check authentication tag (with truncation). + * + * This function is similar to `check_tag()` except that it + * works over an explicit tag length. See `get_tag()` for a + * discussion of explicit tag lengths; the range of allowed tag + * lengths depends on the algorithm. + * + * \param cc AEAD context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ + uint32_t (*check_tag_trunc)(const br_aead_class **cc, + const void *tag, size_t len); +}; + +/** + * \brief Context structure for GCM. + * + * GCM is an AEAD mode that combines a block cipher in CTR mode with a + * MAC based on GHASH, to provide authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with GCM. + * + * - The nonce can have any length, from 0 up to 2^64-1 bits; however, + * 96-bit nonces (12 bytes) are recommended (nonces with a length + * distinct from 12 bytes are internally hashed, which risks reusing + * nonce value with a small but not always negligible probability). + * + * - Additional authenticated data may have length up to 2^64-1 bits. + * + * - Message length may range up to 2^39-256 bits at most. + * + * - The authentication tag has length 16 bytes. + * + * The GCM initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * GCM context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_aead_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctr_class **bctx; + br_ghash gh; + unsigned char h[16]; + unsigned char j0_1[12]; + unsigned char buf[16]; + unsigned char y[16]; + uint32_t j0_2, jc; + uint64_t count_aad, count_ctr; +#endif +} br_gcm_context; + +/** + * \brief Initialize a GCM context. + * + * A block cipher implementation, with its initialised context structure, + * is provided. The block cipher MUST use 16-byte blocks in CTR mode, + * and its secret key MUST have been already set in the provided context. + * A GHASH implementation must also be provided. The parameters are linked + * in the GCM context. + * + * After this function has been called, the `br_gcm_reset()` function must + * be called, to provide the IV for GCM computation. + * + * \param ctx GCM context structure. + * \param bctx block cipher context (already initialised with secret key). + * \param gh GHASH implementation. + */ +void br_gcm_init(br_gcm_context *ctx, + const br_block_ctr_class **bctx, br_ghash gh); + +/** + * \brief Reset a GCM context. + * + * This function resets an already initialised GCM context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing GCM computation that + * uses the provided context structure. + * + * The provided IV is a _nonce_. It is critical to GCM security that IV + * values are not repeated for the same encryption key. IV can have + * arbitrary length (up to 2^64-1 bits), but the "normal" length is + * 96 bits (12 bytes). + * + * \param ctx GCM context structure. + * \param iv GCM nonce to use. + * \param len GCM nonce length (in bytes). + */ +void br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len); + +/** + * \brief Inject additional authenticated data into GCM. + * + * The provided data is injected into a running GCM computation. Additional + * data must be injected _before_ the call to `br_gcm_flip()`. + * Additional data can be injected in several chunks of arbitrary length; + * the maximum total size of additional authenticated data is 2^64-1 + * bits. + * + * \param ctx GCM context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into GCM. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_gcm_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx GCM context structure. + */ +void br_gcm_flip(br_gcm_context *ctx); + +/** + * \brief Encrypt or decrypt some data with GCM. + * + * Data encryption or decryption can be done after `br_gcm_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. The maximum + * total length for data is 2^39-256 bits, i.e. about 65 gigabytes. + * + * \param ctx GCM context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute GCM authentication tag. + * + * Compute the GCM authentication tag. The tag is a 16-byte value which + * is written in the provided `tag` buffer. This call terminates the + * GCM run: no data may be processed with that GCM context afterwards, + * until `br_gcm_reset()` is called to initiate a new GCM run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_gcm_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx GCM context structure. + * \param tag destination buffer for the tag (16 bytes). + */ +void br_gcm_get_tag(br_gcm_context *ctx, void *tag); + +/** + * \brief Compute and check GCM authentication tag. + * + * This function is an alternative to `br_gcm_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx GCM context structure. + * \param tag tag value to compare with (16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_gcm_check_tag(br_gcm_context *ctx, const void *tag); + +/** + * \brief Compute GCM authentication tag (with truncation). + * + * This function is similar to `br_gcm_get_tag()`, except that it allows + * the tag to be truncated to a smaller length. The intended tag length + * is provided as `len` (in bytes); it MUST be no more than 16, but + * it may be smaller. Note that decreasing tag length mechanically makes + * forgeries easier; NIST SP 800-38D specifies that the tag length shall + * lie between 12 and 16 bytes (inclusive), but may be truncated down to + * 4 or 8 bytes, for specific applications that can tolerate it. It must + * also be noted that successful forgeries leak information on the + * authentication key, making subsequent forgeries easier. Therefore, + * tag truncation, and in particular truncation to sizes lower than 12 + * bytes, shall be envisioned only with great care. + * + * The tag is written in the provided `tag` buffer. This call terminates + * the GCM run: no data may be processed with that GCM context + * afterwards, until `br_gcm_reset()` is called to initiate a new GCM + * run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_gcm_check_tag_trunc()` function can be used to + * compute and check the tag value. + * + * \param ctx GCM context structure. + * \param tag destination buffer for the tag. + * \param len tag length (16 bytes or less). + */ +void br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len); + +/** + * \brief Compute and check GCM authentication tag (with truncation). + * + * This function is an alternative to `br_gcm_get_tag_trunc()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length MUST be 16 bytes or less. The normal GCM tag length is 16 + * bytes. See `br_check_tag_trunc()` for some discussion on the potential + * perils of truncating authentication tags. + * + * \param ctx GCM context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_gcm_check_tag_trunc(br_gcm_context *ctx, + const void *tag, size_t len); + +/** + * \brief Class instance for GCM. + */ +extern const br_aead_class br_gcm_vtable; + +/** + * \brief Context structure for EAX. + * + * EAX is an AEAD mode that combines a block cipher in CTR mode with + * CBC-MAC using the same block cipher and the same key, to provide + * authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with EAX + * (technically, other block sizes are defined as well, but this + * is not implemented by these functions; shorter blocks also + * imply numerous security issues). + * + * - The nonce can have any length, as long as nonce values are + * not reused (thus, if nonces are randomly selected, the nonce + * size should be such that reuse probability is negligible). + * + * - Additional authenticated data length is unlimited. + * + * - Message length is unlimited. + * + * - The authentication tag has length 16 bytes. + * + * The EAX initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * EAX context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_aead_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctrcbc_class **bctx; + unsigned char L2[16]; + unsigned char L4[16]; + unsigned char nonce[16]; + unsigned char head[16]; + unsigned char ctr[16]; + unsigned char cbcmac[16]; + unsigned char buf[16]; + size_t ptr; +#endif +} br_eax_context; + +/** + * \brief EAX captured state. + * + * Some internal values computed by EAX may be captured at various + * points, and reused for another EAX run with the same secret key, + * for lower per-message overhead. Captured values do not depend on + * the nonce. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char st[3][16]; +#endif +} br_eax_state; + +/** + * \brief Initialize an EAX context. + * + * A block cipher implementation, with its initialised context + * structure, is provided. The block cipher MUST use 16-byte blocks in + * CTR + CBC-MAC mode, and its secret key MUST have been already set in + * the provided context. The parameters are linked in the EAX context. + * + * After this function has been called, the `br_eax_reset()` function must + * be called, to provide the nonce for EAX computation. + * + * \param ctx EAX context structure. + * \param bctx block cipher context (already initialised with secret key). + */ +void br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx); + +/** + * \brief Capture pre-AAD state. + * + * This function precomputes key-dependent data, and stores it in the + * provided `st` structure. This structure should then be used with + * `br_eax_reset_pre_aad()`, or updated with `br_eax_get_aad_mac()` + * and then used with `br_eax_reset_post_aad()`. + * + * The EAX context structure is unmodified by this call. + * + * \param ctx EAX context structure. + * \param st recipient for captured state. + */ +void br_eax_capture(const br_eax_context *ctx, br_eax_state *st); + +/** + * \brief Reset an EAX context. + * + * This function resets an already initialised EAX context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing EAX computation that + * uses the provided context structure. + * + * It is critical to EAX security that nonce values are not repeated for + * the same encryption key. Nonces can have arbitrary length. If nonces + * are randomly generated, then a nonce length of at least 128 bits (16 + * bytes) is recommended, to make nonce reuse probability sufficiently + * low. + * + * \param ctx EAX context structure. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len); + +/** + * \brief Reset an EAX context with a pre-AAD captured state. + * + * This function is an alternative to `br_eax_reset()`, that reuses a + * previously captured state structure for lower per-message overhead. + * The state should have been populated with `br_eax_capture_state()` + * but not updated with `br_eax_get_aad_mac()`. + * + * After this function is called, additional authenticated data MUST + * be injected. At least one byte of additional authenticated data + * MUST be provided with `br_eax_aad_inject()`; computation result will + * be incorrect if `br_eax_flip()` is called right away. + * + * After injection of the AAD and call to `br_eax_flip()`, at least + * one message byte must be provided. Empty messages are not supported + * with this reset mode. + * + * \param ctx EAX context structure. + * \param st pre-AAD captured state. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len); + +/** + * \brief Reset an EAX context with a post-AAD captured state. + * + * This function is an alternative to `br_eax_reset()`, that reuses a + * previously captured state structure for lower per-message overhead. + * The state should have been populated with `br_eax_capture_state()` + * and then updated with `br_eax_get_aad_mac()`. + * + * After this function is called, message data MUST be injected. The + * `br_eax_flip()` function MUST NOT be called. At least one byte of + * message data MUST be provided with `br_eax_run()`; empty messages + * are not supported with this reset mode. + * + * \param ctx EAX context structure. + * \param st post-AAD captured state. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len); + +/** + * \brief Inject additional authenticated data into EAX. + * + * The provided data is injected into a running EAX computation. Additional + * data must be injected _before_ the call to `br_eax_flip()`. + * Additional data can be injected in several chunks of arbitrary length; + * the total amount of additional authenticated data is unlimited. + * + * \param ctx EAX context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into EAX. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_eax_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx EAX context structure. + */ +void br_eax_flip(br_eax_context *ctx); + +/** + * \brief Obtain a copy of the MAC on additional authenticated data. + * + * This function may be called only after `br_eax_flip()`; it copies the + * AAD-specific MAC value into the provided state. The MAC value depends + * on the secret key and the additional data itself, but not on the + * nonce. The updated state `st` is meant to be used as parameter for a + * further `br_eax_reset_post_aad()` call. + * + * \param ctx EAX context structure. + * \param st captured state to update. + */ +static __inline void +br_eax_get_aad_mac(const br_eax_context *ctx, br_eax_state *st) +{ + memcpy(st->st[1], ctx->head, sizeof ctx->head); +} + +/** + * \brief Encrypt or decrypt some data with EAX. + * + * Data encryption or decryption can be done after `br_eax_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. + * + * \param ctx EAX context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute EAX authentication tag. + * + * Compute the EAX authentication tag. The tag is a 16-byte value which + * is written in the provided `tag` buffer. This call terminates the + * EAX run: no data may be processed with that EAX context afterwards, + * until `br_eax_reset()` is called to initiate a new EAX run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_eax_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx EAX context structure. + * \param tag destination buffer for the tag (16 bytes). + */ +void br_eax_get_tag(br_eax_context *ctx, void *tag); + +/** + * \brief Compute and check EAX authentication tag. + * + * This function is an alternative to `br_eax_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx EAX context structure. + * \param tag tag value to compare with (16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_eax_check_tag(br_eax_context *ctx, const void *tag); + +/** + * \brief Compute EAX authentication tag (with truncation). + * + * This function is similar to `br_eax_get_tag()`, except that it allows + * the tag to be truncated to a smaller length. The intended tag length + * is provided as `len` (in bytes); it MUST be no more than 16, but + * it may be smaller. Note that decreasing tag length mechanically makes + * forgeries easier; NIST SP 800-38D specifies that the tag length shall + * lie between 12 and 16 bytes (inclusive), but may be truncated down to + * 4 or 8 bytes, for specific applications that can tolerate it. It must + * also be noted that successful forgeries leak information on the + * authentication key, making subsequent forgeries easier. Therefore, + * tag truncation, and in particular truncation to sizes lower than 12 + * bytes, shall be envisioned only with great care. + * + * The tag is written in the provided `tag` buffer. This call terminates + * the EAX run: no data may be processed with that EAX context + * afterwards, until `br_eax_reset()` is called to initiate a new EAX + * run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_eax_check_tag_trunc()` function can be used to + * compute and check the tag value. + * + * \param ctx EAX context structure. + * \param tag destination buffer for the tag. + * \param len tag length (16 bytes or less). + */ +void br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len); + +/** + * \brief Compute and check EAX authentication tag (with truncation). + * + * This function is an alternative to `br_eax_get_tag_trunc()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length MUST be 16 bytes or less. The normal EAX tag length is 16 + * bytes. See `br_check_tag_trunc()` for some discussion on the potential + * perils of truncating authentication tags. + * + * \param ctx EAX context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_eax_check_tag_trunc(br_eax_context *ctx, + const void *tag, size_t len); + +/** + * \brief Class instance for EAX. + */ +extern const br_aead_class br_eax_vtable; + +/** + * \brief Context structure for CCM. + * + * CCM is an AEAD mode that combines a block cipher in CTR mode with + * CBC-MAC using the same block cipher and the same key, to provide + * authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with CCM + * (technically, other block sizes are defined as well, but this + * is not implemented by these functions; shorter blocks also + * imply numerous security issues). + * + * - The authentication tag length, and plaintext length, MUST be + * known when starting processing data. Plaintext and ciphertext + * can still be provided by chunks, but the total size must match + * the value provided upon initialisation. + * + * - The nonce length is constrained between 7 and 13 bytes (inclusive). + * Furthermore, the plaintext length, when encoded, must fit over + * 15-nonceLen bytes; thus, if the nonce has length 13 bytes, then + * the plaintext length cannot exceed 65535 bytes. + * + * - Additional authenticated data length is practically unlimited + * (formal limit is at 2^64 bytes). + * + * - The authentication tag has length 4 to 16 bytes (even values only). + * + * The CCM initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * CCM context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctrcbc_class **bctx; + unsigned char ctr[16]; + unsigned char cbcmac[16]; + unsigned char tagmask[16]; + unsigned char buf[16]; + size_t ptr; + size_t tag_len; +#endif +} br_ccm_context; + +/** + * \brief Initialize a CCM context. + * + * A block cipher implementation, with its initialised context + * structure, is provided. The block cipher MUST use 16-byte blocks in + * CTR + CBC-MAC mode, and its secret key MUST have been already set in + * the provided context. The parameters are linked in the CCM context. + * + * After this function has been called, the `br_ccm_reset()` function must + * be called, to provide the nonce for CCM computation. + * + * \param ctx CCM context structure. + * \param bctx block cipher context (already initialised with secret key). + */ +void br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx); + +/** + * \brief Reset a CCM context. + * + * This function resets an already initialised CCM context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing CCM computation that + * uses the provided context structure. + * + * The `aad_len` parameter contains the total length, in bytes, of the + * additional authenticated data. It may be zero. That length MUST be + * exact. + * + * The `data_len` parameter contains the total length, in bytes, of the + * data that will be injected (plaintext or ciphertext). That length MUST + * be exact. Moreover, that length MUST be less than 2^(8*(15-nonce_len)). + * + * The nonce length (`nonce_len`), in bytes, must be in the 7..13 range + * (inclusive). + * + * The tag length (`tag_len`), in bytes, must be in the 4..16 range, and + * be an even integer. Short tags mechanically allow for higher forgery + * probabilities; hence, tag sizes smaller than 12 bytes shall be used only + * with care. + * + * It is critical to CCM security that nonce values are not repeated for + * the same encryption key. Random generation of nonces is not generally + * recommended, due to the relatively small maximum nonce value. + * + * Returned value is 1 on success, 0 on error. An error is reported if + * the tag or nonce length is out of range, or if the + * plaintext/ciphertext length cannot be encoded with the specified + * nonce length. + * + * \param ctx CCM context structure. + * \param nonce CCM nonce to use. + * \param nonce_len CCM nonce length (in bytes, 7 to 13). + * \param aad_len additional authenticated data length (in bytes). + * \param data_len plaintext/ciphertext length (in bytes). + * \param tag_len tag length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, + uint64_t aad_len, uint64_t data_len, size_t tag_len); + +/** + * \brief Inject additional authenticated data into CCM. + * + * The provided data is injected into a running CCM computation. Additional + * data must be injected _before_ the call to `br_ccm_flip()`. + * Additional data can be injected in several chunks of arbitrary length, + * but the total amount MUST exactly match the value which was provided + * to `br_ccm_reset()`. + * + * \param ctx CCM context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into CCM. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_ccm_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx CCM context structure. + */ +void br_ccm_flip(br_ccm_context *ctx); + +/** + * \brief Encrypt or decrypt some data with CCM. + * + * Data encryption or decryption can be done after `br_ccm_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length, provided + * that the total length exactly matches the length provided to the + * `br_ccm_reset()` call. + * + * \param ctx CCM context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute CCM authentication tag. + * + * Compute the CCM authentication tag. This call terminates the CCM + * run: all data must have been injected with `br_ccm_run()` (in zero, + * one or more successive calls). After this function has been called, + * no more data can br processed; a `br_ccm_reset()` call is required + * to start a new message. + * + * The tag length was provided upon context initialisation (last call + * to `br_ccm_reset()`); it is returned by this function. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_ccm_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx CCM context structure. + * \param tag destination buffer for the tag (up to 16 bytes). + * \return the tag length (in bytes). + */ +size_t br_ccm_get_tag(br_ccm_context *ctx, void *tag); + +/** + * \brief Compute and check CCM authentication tag. + * + * This function is an alternative to `br_ccm_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx CCM context structure. + * \param tag tag value to compare with (up to 16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_ccm_check_tag(br_ccm_context *ctx, const void *tag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_block.h b/BearSSL-OG/libbearssl/inc/bearssl_block.h new file mode 100644 index 0000000..683a490 --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_block.h @@ -0,0 +1,2618 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_BLOCK_H__ +#define BR_BEARSSL_BLOCK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_block.h + * + * # Block Ciphers and Symmetric Ciphers + * + * This file documents the API for block ciphers and other symmetric + * ciphers. + * + * + * ## Procedural API + * + * For a block cipher implementation, up to three separate sets of + * functions are provided, for CBC encryption, CBC decryption, and CTR + * encryption/decryption. Each set has its own context structure, + * initialised with the encryption key. + * + * For CBC encryption and decryption, the data to encrypt or decrypt is + * referenced as a sequence of blocks. The implementations assume that + * there is no partial block; no padding is applied or removed. The + * caller is responsible for handling any kind of padding. + * + * Function for CTR encryption are defined only for block ciphers with + * blocks of 16 bytes or more (i.e. AES, but not DES/3DES). + * + * Each implemented block cipher is identified by an "internal name" + * from which are derived the names of structures and functions that + * implement the cipher. For the block cipher of internal name "`xxx`", + * the following are defined: + * + * - `br_xxx_BLOCK_SIZE` + * + * A macro that evaluates to the block size (in bytes) of the + * cipher. For all implemented block ciphers, this value is a + * power of two. + * + * - `br_xxx_cbcenc_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CBC encryption. The + * structure first field is called `vtable` and points to the + * appropriate OOP structure. + * + * - `br_xxx_cbcenc_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CBC encryption are computed and + * written in the provided context structure. The key length MUST be + * adequate for the implemented block cipher. This function also sets + * the `vtable` field. + * + * - `br_xxx_cbcenc_run(const br_xxx_cbcenc_keys *ctx, void *iv, void *data, size_t len)` + * + * Perform CBC encryption of `len` bytes, in place. The encrypted data + * replaces the cleartext. `len` MUST be a multiple of the block length + * (if it is not, the function may loop forever or overflow a buffer). + * The IV is provided with the `iv` pointer; it is also updated with + * a copy of the last encrypted block. + * + * - `br_xxx_cbcdec_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CBC decryption. The + * structure first field is called `vtable` and points to the + * appropriate OOP structure. + * + * - `br_xxx_cbcdec_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CBC decryption are computed and + * written in the provided context structure. The key length MUST be + * adequate for the implemented block cipher. This function also sets + * the `vtable` field. + * + * - `br_xxx_cbcdec_run(const br_xxx_cbcdec_keys *ctx, void *iv, void *data, size_t num_blocks)` + * + * Perform CBC decryption of `len` bytes, in place. The decrypted data + * replaces the ciphertext. `len` MUST be a multiple of the block length + * (if it is not, the function may loop forever or overflow a buffer). + * The IV is provided with the `iv` pointer; it is also updated with + * a copy of the last _encrypted_ block. + * + * - `br_xxx_ctr_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CTR encryption and + * decryption. The structure first field is called `vtable` and + * points to the appropriate OOP structure. + * + * - `br_xxx_ctr_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CTR encryption and decryption + * are computed and written in the provided context structure. The + * key length MUST be adequate for the implemented block cipher. This + * function also sets the `vtable` field. + * + * - `br_xxx_ctr_run(const br_xxx_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len)` (returns `uint32_t`) + * + * Perform CTR encryption/decryption of some data. Processing is done + * "in place" (the output data replaces the input data). This function + * implements the "standard incrementing function" from NIST SP800-38A, + * annex B: the IV length shall be 4 bytes less than the block size + * (i.e. 12 bytes for AES) and the counter is the 32-bit value starting + * with `cc`. The data length (`len`) is not necessarily a multiple of + * the block size. The new counter value is returned, which supports + * chunked processing, provided that each chunk length (except possibly + * the last one) is a multiple of the block size. + * + * - `br_xxx_ctrcbc_keys` + * + * Context structure that contains the subkeys resulting from the + * key expansion. These subkeys are appropriate for doing combined + * CTR encryption/decryption and CBC-MAC, as used in the CCM and EAX + * authenticated encryption modes. The structure first field is + * called `vtable` and points to the appropriate OOP structure. + * + * - `br_xxx_ctrcbc_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for combined CTR + * encryption/decryption and CBC-MAC are computed and written in the + * provided context structure. The key length MUST be adequate for + * the implemented block cipher. This function also sets the + * `vtable` field. + * + * - `br_xxx_ctrcbc_encrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` + * + * Perform CTR encryption of some data, and CBC-MAC. Processing is + * done "in place" (the output data replaces the input data). This + * function applies CTR encryption on the data, using a full + * block-size counter (i.e. for 128-bit blocks, the counter is + * incremented as a 128-bit value). The 'ctr' array contains the + * initial value for the counter (used in the first block) and it is + * updated with the new value after data processing. The 'cbcmac' + * value shall point to a block-sized value which is used as IV for + * CBC-MAC, computed over the encrypted data (output of CTR + * encryption); the resulting CBC-MAC is written over 'cbcmac' on + * output. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_decrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` + * + * Perform CTR decryption of some data, and CBC-MAC. Processing is + * done "in place" (the output data replaces the input data). This + * function applies CTR decryption on the data, using a full + * block-size counter (i.e. for 128-bit blocks, the counter is + * incremented as a 128-bit value). The 'ctr' array contains the + * initial value for the counter (used in the first block) and it is + * updated with the new value after data processing. The 'cbcmac' + * value shall point to a block-sized value which is used as IV for + * CBC-MAC, computed over the encrypted data (input of CTR + * encryption); the resulting CBC-MAC is written over 'cbcmac' on + * output. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_ctr(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *data, size_t len)` + * + * Perform CTR encryption or decryption of the provided data. The + * data is processed "in place" (the output data replaces the input + * data). A full block-sized counter is applied (i.e. for 128-bit + * blocks, the counter is incremented as a 128-bit value). The 'ctr' + * array contains the initial value for the counter (used in the + * first block), and it is updated with the new value after data + * processing. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_mac(const br_xxx_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len)` + * + * Compute CBC-MAC over the provided data. The IV for CBC-MAC is + * provided as 'cbcmac'; the output is written over the same array. + * The data itself is untouched. The data length MUST be a multiple + * of the block size. + * + * + * It shall be noted that the key expansion functions return `void`. If + * the provided key length is not allowed, then there will be no error + * reporting; implementations need not validate the key length, thus an + * invalid key length may result in undefined behaviour (e.g. buffer + * overflow). + * + * Subkey structures contain no interior pointer, and no external + * resources are allocated upon key expansion. They can thus be + * discarded without any explicit deallocation. + * + * + * ## Object-Oriented API + * + * Each context structure begins with a field (called `vtable`) that + * points to an instance of a structure that references the relevant + * functions through pointers. Each such structure contains the + * following: + * + * - `context_size` + * + * The size (in bytes) of the context structure for subkeys. + * + * - `block_size` + * + * The cipher block size (in bytes). + * + * - `log_block_size` + * + * The base-2 logarithm of cipher block size (e.g. 4 for blocks + * of 16 bytes). + * + * - `init` + * + * Pointer to the key expansion function. + * + * - `run` + * + * Pointer to the encryption/decryption function. + * + * For combined CTR/CBC-MAC encryption, the `vtable` has a slightly + * different structure: + * + * - `context_size` + * + * The size (in bytes) of the context structure for subkeys. + * + * - `block_size` + * + * The cipher block size (in bytes). + * + * - `log_block_size` + * + * The base-2 logarithm of cipher block size (e.g. 4 for blocks + * of 16 bytes). + * + * - `init` + * + * Pointer to the key expansion function. + * + * - `encrypt` + * + * Pointer to the CTR encryption + CBC-MAC function. + * + * - `decrypt` + * + * Pointer to the CTR decryption + CBC-MAC function. + * + * - `ctr` + * + * Pointer to the CTR encryption/decryption function. + * + * - `mac` + * + * Pointer to the CBC-MAC function. + * + * For block cipher "`xxx`", static, constant instances of these + * structures are defined, under the names: + * + * - `br_xxx_cbcenc_vtable` + * - `br_xxx_cbcdec_vtable` + * - `br_xxx_ctr_vtable` + * - `br_xxx_ctrcbc_vtable` + * + * + * ## Implemented Block Ciphers + * + * Provided implementations are: + * + * | Name | Function | Block Size (bytes) | Key lengths (bytes) | + * | :-------- | :------- | :----------------: | :-----------------: | + * | aes_big | AES | 16 | 16, 24 and 32 | + * | aes_small | AES | 16 | 16, 24 and 32 | + * | aes_ct | AES | 16 | 16, 24 and 32 | + * | aes_ct64 | AES | 16 | 16, 24 and 32 | + * | aes_x86ni | AES | 16 | 16, 24 and 32 | + * | aes_pwr8 | AES | 16 | 16, 24 and 32 | + * | des_ct | DES/3DES | 8 | 8, 16 and 24 | + * | des_tab | DES/3DES | 8 | 8, 16 and 24 | + * + * **Note:** DES/3DES nominally uses keys of 64, 128 and 192 bits (i.e. 8, + * 16 and 24 bytes), but some of the bits are ignored by the algorithm, so + * the _effective_ key lengths, from a security point of view, are 56, + * 112 and 168 bits, respectively. + * + * `aes_big` is a "classical" AES implementation, using tables. It + * is fast but not constant-time, since it makes data-dependent array + * accesses. + * + * `aes_small` is an AES implementation optimized for code size. It + * is substantially slower than `aes_big`; it is not constant-time + * either. + * + * `aes_ct` is a constant-time implementation of AES; its code is about + * as big as that of `aes_big`, while its performance is comparable to + * that of `aes_small`. However, it is constant-time. This + * implementation should thus be considered to be the "default" AES in + * BearSSL, to be used unless the operational context guarantees that a + * non-constant-time implementation is safe, or an architecture-specific + * constant-time implementation can be used (e.g. using dedicated + * hardware opcodes). + * + * `aes_ct64` is another constant-time implementation of AES. It is + * similar to `aes_ct` but uses 64-bit values. On 32-bit machines, + * `aes_ct64` is not faster than `aes_ct`, often a bit slower, and has + * a larger footprint; however, on 64-bit architectures, `aes_ct64` + * is typically twice faster than `aes_ct` for modes that allow parallel + * operations (i.e. CTR, and CBC decryption, but not CBC encryption). + * + * `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It + * uses the AES-NI opcodes when available. + * + * `aes_pwr8` exists only on PowerPC / POWER architectures (32-bit and + * 64-bit, both little-endian and big-endian). It uses the AES opcodes + * present in POWER8 and later. + * + * `des_tab` is a classic, table-based implementation of DES/3DES. It + * is not constant-time. + * + * `des_ct` is an constant-time implementation of DES/3DES. It is + * substantially slower than `des_tab`. + * + * ## ChaCha20 and Poly1305 + * + * ChaCha20 is a stream cipher. Poly1305 is a MAC algorithm. They + * are described in [RFC 7539](https://tools.ietf.org/html/rfc7539). + * + * Two function pointer types are defined: + * + * - `br_chacha20_run` describes a function that implements ChaCha20 + * only. + * + * - `br_poly1305_run` describes an implementation of Poly1305, + * in the AEAD combination with ChaCha20 specified in RFC 7539 + * (the ChaCha20 implementation is provided as a function pointer). + * + * `chacha20_ct` is a straightforward implementation of ChaCha20 in + * plain C; it is constant-time, small, and reasonably fast. + * + * `chacha20_sse2` leverages SSE2 opcodes (on x86 architectures that + * support these opcodes). It is faster than `chacha20_ct`. + * + * `poly1305_ctmul` is an implementation of the ChaCha20+Poly1305 AEAD + * construction, where the Poly1305 part is performed with mixed 32-bit + * multiplications (operands are 32-bit, result is 64-bit). + * + * `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit + * multiplications (32-bit operands, 32-bit result). It is slower than + * `poly1305_ctmul`, except on some specific architectures such as + * the ARM Cortex M0+. + * + * `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit + * multiplications (operands are 64-bit, result is 128-bit) on 64-bit + * platforms that support such operations. + * + * `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15" + * big integer implementation. It is meant mostly for testing purposes, + * although it can help with saving a few hundred bytes of code footprint + * on systems where code size is scarce. + */ + +/** + * \brief Class type for CBC encryption implementations. + * + * A `br_block_cbcenc_class` instance points to the functions implementing + * a specific block cipher, when used in CBC mode for encrypting data. + */ +typedef struct br_block_cbcenc_class_ br_block_cbcenc_class; +struct br_block_cbcenc_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_cbcenc_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CBC encryption. + * + * The `iv` parameter points to the IV for this run; it is + * updated with a copy of the last encrypted block. The data + * is encrypted "in place"; its length (`len`) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param iv IV for CBC encryption (updated). + * \param data data to encrypt. + * \param len data length (in bytes, multiple of block size). + */ + void (*run)(const br_block_cbcenc_class *const *ctx, + void *iv, void *data, size_t len); +}; + +/** + * \brief Class type for CBC decryption implementations. + * + * A `br_block_cbcdec_class` instance points to the functions implementing + * a specific block cipher, when used in CBC mode for decrypting data. + */ +typedef struct br_block_cbcdec_class_ br_block_cbcdec_class; +struct br_block_cbcdec_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_cbcdec_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CBC decryption. + * + * The `iv` parameter points to the IV for this run; it is + * updated with a copy of the last encrypted block. The data + * is decrypted "in place"; its length (`len`) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param iv IV for CBC decryption (updated). + * \param data data to decrypt. + * \param len data length (in bytes, multiple of block size). + */ + void (*run)(const br_block_cbcdec_class *const *ctx, + void *iv, void *data, size_t len); +}; + +/** + * \brief Class type for CTR encryption/decryption implementations. + * + * A `br_block_ctr_class` instance points to the functions implementing + * a specific block cipher, when used in CTR mode for encrypting or + * decrypting data. + */ +typedef struct br_block_ctr_class_ br_block_ctr_class; +struct br_block_ctr_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_ctr_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CTR encryption or decryption. + * + * The `iv` parameter points to the IV for this run; its + * length is exactly 4 bytes less than the block size (e.g. + * 12 bytes for AES/CTR). The IV is combined with a 32-bit + * block counter to produce the block value which is processed + * with the block cipher. + * + * The data to encrypt or decrypt is updated "in place". Its + * length (`len` bytes) is not required to be a multiple of + * the block size; if the final block is partial, then the + * corresponding key stream bits are dropped. + * + * The resulting counter value is returned. + * + * \param ctx context structure (already initialised). + * \param iv IV for CTR encryption/decryption. + * \param cc initial value for the block counter. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \return the new block counter value. + */ + uint32_t (*run)(const br_block_ctr_class *const *ctx, + const void *iv, uint32_t cc, void *data, size_t len); +}; + +/** + * \brief Class type for combined CTR and CBC-MAC implementations. + * + * A `br_block_ctrcbc_class` instance points to the functions implementing + * a specific block cipher, when used in CTR mode for encrypting or + * decrypting data, along with CBC-MAC. + */ +typedef struct br_block_ctrcbc_class_ br_block_ctrcbc_class; +struct br_block_ctrcbc_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_ctrcbc_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CTR encryption + CBC-MAC. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as encryption proceeds. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (output of CTR + * encryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data to encrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to encrypt. + * \param len data length (in bytes). + */ + void (*encrypt)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + + /** + * \brief Run the CTR decryption + CBC-MAC. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as decryption proceeds. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (i.e. before CTR + * decryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data to decrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*decrypt)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + + /** + * \brief Run the CTR encryption/decryption only. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as decryption proceeds. + * + * The data to decrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*ctr)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *data, size_t len); + + /** + * \brief Run the CBC-MAC only. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (i.e. before CTR + * decryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data is unmodified. Its length (`len` bytes) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*mac)(const br_block_ctrcbc_class *const *ctx, + void *cbcmac, const void *data, size_t len); +}; + +/* + * Traditional, table-based AES implementation. It is fast, but uses + * internal tables (in particular a 1 kB table for encryption, another + * 1 kB table for decryption, and a 256-byte table for key schedule), + * and it is not constant-time. In contexts where cache-timing attacks + * apply, this implementation may leak the secret key. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_big_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_big` implementation). + */ +extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_big` implementation). + */ +extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_big` implementation). + */ +extern const br_block_ctr_class br_aes_big_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_big` implementation). + */ +extern const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to encrypt or decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * AES implementation optimized for size. It is slower than the + * traditional table-based AES implementation, but requires much less + * code. It still uses data-dependent table accesses (albeit within a + * much smaller 256-byte table), which makes it conceptually vulnerable + * to cache-timing attacks. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_small_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_small` implementation). + */ +extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_small` implementation). + */ +extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_small` implementation). + */ +extern const br_block_ctr_class br_aes_small_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_small` implementation). + */ +extern const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * Constant-time AES implementation. Its size is similar to that of + * 'aes_big', and its performance is similar to that of 'aes_small' (faster + * decryption, slower encryption). However, it is constant-time, i.e. + * immune to cache-timing and similar attacks. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_ct_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_ct` implementation). + */ +extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_ct` implementation). + */ +extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_ct` implementation). + */ +extern const br_block_ctr_class br_aes_ct_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_ct` implementation). + */ +extern const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * 64-bit constant-time AES implementation. It is similar to 'aes_ct' + * but uses 64-bit registers, making it about twice faster than 'aes_ct' + * on 64-bit platforms, while remaining constant-time and with a similar + * code size. (The doubling in performance is only for CBC decryption + * and CTR mode; CBC encryption is non-parallel and cannot benefit from + * the larger registers.) + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_ct64_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_ct64` implementation). + */ +extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_ct64` implementation). + */ +extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_ct64` implementation). + */ +extern const br_block_ctr_class br_aes_ct64_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_ct64` implementation). + */ +extern const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * AES implementation using AES-NI opcodes (x86 platform). + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_x86ni_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_x86ni_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctrcbc_get_vtable()`. + */ +extern const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR + CBC-MAC implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_ctrcbc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctrcbc_class *br_aes_x86ni_ctrcbc_get_vtable(void); + +/* + * AES implementation using POWER8 opcodes. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_pwr8_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_pwr8_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_ctrcbc_get_vtable()`. + */ +extern const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/** + * \brief Obtain the `aes_pwr8` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 + * crypto opcodes are available on the currently running CPU. If either + * of these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_pwr8_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 + * crypto opcodes are available on the currently running CPU. If either + * of these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_pwr8_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_pwr8_ctr_vtable`, if that + * implementation was compiled in the library _and_ the POWER8 crypto + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_pwr8_ctr_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CTR + CBC-MAC implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_ctrcbc_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. + */ +const br_block_ctrcbc_class *br_aes_pwr8_ctrcbc_get_vtable(void); + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC encryption) for all AES implementations. + */ +typedef union { + const br_block_cbcenc_class *vtable; + br_aes_big_cbcenc_keys c_big; + br_aes_small_cbcenc_keys c_small; + br_aes_ct_cbcenc_keys c_ct; + br_aes_ct64_cbcenc_keys c_ct64; + br_aes_x86ni_cbcenc_keys c_x86ni; + br_aes_pwr8_cbcenc_keys c_pwr8; +} br_aes_gen_cbcenc_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC decryption) for all AES implementations. + */ +typedef union { + const br_block_cbcdec_class *vtable; + br_aes_big_cbcdec_keys c_big; + br_aes_small_cbcdec_keys c_small; + br_aes_ct_cbcdec_keys c_ct; + br_aes_ct64_cbcdec_keys c_ct64; + br_aes_x86ni_cbcdec_keys c_x86ni; + br_aes_pwr8_cbcdec_keys c_pwr8; +} br_aes_gen_cbcdec_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CTR encryption and decryption) for all AES implementations. + */ +typedef union { + const br_block_ctr_class *vtable; + br_aes_big_ctr_keys c_big; + br_aes_small_ctr_keys c_small; + br_aes_ct_ctr_keys c_ct; + br_aes_ct64_ctr_keys c_ct64; + br_aes_x86ni_ctr_keys c_x86ni; + br_aes_pwr8_ctr_keys c_pwr8; +} br_aes_gen_ctr_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CTR encryption/decryption + CBC-MAC) for all AES implementations. + */ +typedef union { + const br_block_ctrcbc_class *vtable; + br_aes_big_ctrcbc_keys c_big; + br_aes_small_ctrcbc_keys c_small; + br_aes_ct_ctrcbc_keys c_ct; + br_aes_ct64_ctrcbc_keys c_ct64; + br_aes_x86ni_ctrcbc_keys c_x86ni; + br_aes_pwr8_ctrcbc_keys c_pwr8; +} br_aes_gen_ctrcbc_keys; + +/* + * Traditional, table-based implementation for DES/3DES. Since tables are + * used, cache-timing attacks are conceptually possible. + */ + +/** \brief DES/3DES block size (8 bytes). */ +#define br_des_tab_BLOCK_SIZE 8 + +/** + * \brief Context for DES subkeys (`des_tab` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_tab_cbcenc_keys; + +/** + * \brief Context for DES subkeys (`des_tab` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_tab_cbcdec_keys; + +/** + * \brief Class instance for DES CBC encryption (`des_tab` implementation). + */ +extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable; + +/** + * \brief Class instance for DES CBC decryption (`des_tab` implementation). + */ +extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable; + +/** + * \brief Context initialisation (key schedule) for DES CBC encryption + * (`des_tab` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for DES CBC decryption + * (`des_tab` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with DES (`des_tab` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with DES (`des_tab` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/* + * Constant-time implementation for DES/3DES. It is substantially slower + * (by a factor of about 4x), but also immune to cache-timing attacks. + */ + +/** \brief DES/3DES block size (8 bytes). */ +#define br_des_ct_BLOCK_SIZE 8 + +/** + * \brief Context for DES subkeys (`des_ct` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_ct_cbcenc_keys; + +/** + * \brief Context for DES subkeys (`des_ct` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_ct_cbcdec_keys; + +/** + * \brief Class instance for DES CBC encryption (`des_ct` implementation). + */ +extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable; + +/** + * \brief Class instance for DES CBC decryption (`des_ct` implementation). + */ +extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable; + +/** + * \brief Context initialisation (key schedule) for DES CBC encryption + * (`des_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for DES CBC decryption + * (`des_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with DES (`des_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with DES (`des_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/* + * These structures are large enough to accommodate subkeys for all + * DES/3DES implementations. + */ + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC encryption) for all DES implementations. + */ +typedef union { + const br_block_cbcenc_class *vtable; + br_des_tab_cbcenc_keys tab; + br_des_ct_cbcenc_keys ct; +} br_des_gen_cbcenc_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC decryption) for all DES implementations. + */ +typedef union { + const br_block_cbcdec_class *vtable; + br_des_tab_cbcdec_keys c_tab; + br_des_ct_cbcdec_keys c_ct; +} br_des_gen_cbcdec_keys; + +/** + * \brief Type for a ChaCha20 implementation. + * + * An implementation follows the description in RFC 7539: + * + * - Key is 256 bits (`key` points to exactly 32 bytes). + * + * - IV is 96 bits (`iv` points to exactly 12 bytes). + * + * - Block counter is over 32 bits and starts at value `cc`; the + * resulting value is returned. + * + * Data (pointed to by `data`, of length `len`) is encrypted/decrypted + * in place. If `len` is not a multiple of 64, then the excess bytes from + * the last block processing are dropped (therefore, "chunked" processing + * works only as long as each non-final chunk has a length multiple of 64). + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +typedef uint32_t (*br_chacha20_run)(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief ChaCha20 implementation (straightforward C code, constant-time). + * + * \see br_chacha20_run + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +uint32_t br_chacha20_ct_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief ChaCha20 implementation (SSE2 code, constant-time). + * + * This implementation is available only on x86 platforms, depending on + * compiler support. Moreover, in 32-bit mode, it might not actually run, + * if the underlying hardware does not implement the SSE2 opcode (in + * 64-bit mode, SSE2 is part of the ABI, so if the code could be compiled + * at all, then it can run). Use `br_chacha20_sse2_get()` to safely obtain + * a pointer to that function. + * + * \see br_chacha20_run + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +uint32_t br_chacha20_sse2_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief Obtain the `sse2` ChaCha20 implementation, if available. + * + * This function returns a pointer to `br_chacha20_sse2_run`, if + * that implementation was compiled in the library _and_ the SSE2 + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `0`. + * + * \return the `sse2` ChaCha20 implementation, or `0`. + */ +br_chacha20_run br_chacha20_sse2_get(void); + +/** + * \brief Type for a ChaCha20+Poly1305 AEAD implementation. + * + * The provided data is encrypted or decrypted with ChaCha20. The + * authentication tag is computed on the concatenation of the + * additional data and the ciphertext, with the padding and lengths + * as described in RFC 7539 (section 2.8). + * + * After decryption, the caller is responsible for checking that the + * computed tag matches the expected value. + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +typedef void (*br_poly1305_run)(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (mixed 32-bit multiplications). + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmul_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications). + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmul32_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (i15). + * + * This implementation relies on the generic big integer code "i15" + * (which uses pure 32-bit multiplications). As such, it may save a + * little code footprint in a context where "i15" is already included + * (e.g. for elliptic curves or for RSA); however, it is also + * substantially slower than the ctmul and ctmul32 implementations. + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_i15_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (ctmulq). + * + * This implementation uses 64-bit multiplications (result over 128 bits). + * It is available only on platforms that offer such a primitive (in + * practice, 64-bit architectures). Use `br_poly1305_ctmulq_get()` to + * dynamically obtain a pointer to that function, or 0 if not supported. + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmulq_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief Get the ChaCha20+Poly1305 "ctmulq" implementation, if available. + * + * This function returns a pointer to the `br_poly1305_ctmulq_run()` + * function if supported on the current platform; otherwise, it returns 0. + * + * \return the ctmulq ChaCha20+Poly1305 implementation, or 0. + */ +br_poly1305_run br_poly1305_ctmulq_get(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_ec.h b/BearSSL-OG/libbearssl/inc/bearssl_ec.h new file mode 100644 index 0000000..acd3a2b --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_ec.h @@ -0,0 +1,967 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_EC_H__ +#define BR_BEARSSL_EC_H__ + +#include +#include + +#include "bearssl_rand.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ec.h + * + * # Elliptic Curves + * + * This file documents the EC implementations provided with BearSSL, and + * ECDSA. + * + * ## Elliptic Curve API + * + * Only "named curves" are supported. Each EC implementation supports + * one or several named curves, identified by symbolic identifiers. + * These identifiers are small integers, that correspond to the values + * registered by the + * [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8). + * + * Since all currently defined elliptic curve identifiers are in the 0..31 + * range, it is convenient to encode support of some curves in a 32-bit + * word, such that bit x corresponds to curve of identifier x. + * + * An EC implementation is incarnated by a `br_ec_impl` instance, that + * offers the following fields: + * + * - `supported_curves` + * + * A 32-bit word that documents the identifiers of the curves supported + * by this implementation. + * + * - `generator()` + * + * Callback method that returns a pointer to the conventional generator + * point for that curve. + * + * - `order()` + * + * Callback method that returns a pointer to the subgroup order for + * that curve. That value uses unsigned big-endian encoding. + * + * - `xoff()` + * + * Callback method that returns the offset and length of the X + * coordinate in an encoded point. + * + * - `mul()` + * + * Multiply a curve point with an integer. + * + * - `mulgen()` + * + * Multiply the curve generator with an integer. This may be faster + * than the generic `mul()`. + * + * - `muladd()` + * + * Multiply two curve points by two integers, and return the sum of + * the two products. + * + * All curve points are represented in uncompressed format. The `mul()` + * and `muladd()` methods take care to validate that the provided points + * are really part of the relevant curve subgroup. + * + * For all point multiplication functions, the following holds: + * + * - Functions validate that the provided points are valid members + * of the relevant curve subgroup. An error is reported if that is + * not the case. + * + * - Processing is constant-time, even if the point operands are not + * valid. This holds for both the source and resulting points, and + * the multipliers (integers). Only the byte length of the provided + * multiplier arrays (not their actual value length in bits) may + * leak through timing-based side channels. + * + * - The multipliers (integers) MUST be lower than the subgroup order. + * If this property is not met, then the result is indeterminate, + * but an error value is not necessarily returned. + * + * + * ## ECDSA + * + * ECDSA signatures have two standard formats, called "raw" and "asn1". + * Internally, such a signature is a pair of modular integers `(r,s)`. + * The "raw" format is the concatenation of the unsigned big-endian + * encodings of these two integers, possibly left-padded with zeros so + * that they have the same encoded length. The "asn1" format is the + * DER encoding of an ASN.1 structure that contains the two integer + * values: + * + * ECDSASignature ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * In general, in all of X.509 and SSL/TLS, the "asn1" format is used. + * BearSSL offers ECDSA implementations for both formats; conversion + * functions between the two formats are also provided. Conversion of a + * "raw" format signature into "asn1" may enlarge a signature by no more + * than 9 bytes for all supported curves; conversely, conversion of an + * "asn1" signature to "raw" may expand the signature but the "raw" + * length will never be more than twice the length of the "asn1" length + * (and usually it will be shorter). + * + * Note that for a given signature, the "raw" format is not fully + * deterministic, in that it does not enforce a minimal common length. + */ + +/* + * Standard curve ID. These ID are equal to the assigned numerical + * identifiers assigned to these curves for TLS: + * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + */ + +/** \brief Identifier for named curve sect163k1. */ +#define BR_EC_sect163k1 1 + +/** \brief Identifier for named curve sect163r1. */ +#define BR_EC_sect163r1 2 + +/** \brief Identifier for named curve sect163r2. */ +#define BR_EC_sect163r2 3 + +/** \brief Identifier for named curve sect193r1. */ +#define BR_EC_sect193r1 4 + +/** \brief Identifier for named curve sect193r2. */ +#define BR_EC_sect193r2 5 + +/** \brief Identifier for named curve sect233k1. */ +#define BR_EC_sect233k1 6 + +/** \brief Identifier for named curve sect233r1. */ +#define BR_EC_sect233r1 7 + +/** \brief Identifier for named curve sect239k1. */ +#define BR_EC_sect239k1 8 + +/** \brief Identifier for named curve sect283k1. */ +#define BR_EC_sect283k1 9 + +/** \brief Identifier for named curve sect283r1. */ +#define BR_EC_sect283r1 10 + +/** \brief Identifier for named curve sect409k1. */ +#define BR_EC_sect409k1 11 + +/** \brief Identifier for named curve sect409r1. */ +#define BR_EC_sect409r1 12 + +/** \brief Identifier for named curve sect571k1. */ +#define BR_EC_sect571k1 13 + +/** \brief Identifier for named curve sect571r1. */ +#define BR_EC_sect571r1 14 + +/** \brief Identifier for named curve secp160k1. */ +#define BR_EC_secp160k1 15 + +/** \brief Identifier for named curve secp160r1. */ +#define BR_EC_secp160r1 16 + +/** \brief Identifier for named curve secp160r2. */ +#define BR_EC_secp160r2 17 + +/** \brief Identifier for named curve secp192k1. */ +#define BR_EC_secp192k1 18 + +/** \brief Identifier for named curve secp192r1. */ +#define BR_EC_secp192r1 19 + +/** \brief Identifier for named curve secp224k1. */ +#define BR_EC_secp224k1 20 + +/** \brief Identifier for named curve secp224r1. */ +#define BR_EC_secp224r1 21 + +/** \brief Identifier for named curve secp256k1. */ +#define BR_EC_secp256k1 22 + +/** \brief Identifier for named curve secp256r1. */ +#define BR_EC_secp256r1 23 + +/** \brief Identifier for named curve secp384r1. */ +#define BR_EC_secp384r1 24 + +/** \brief Identifier for named curve secp521r1. */ +#define BR_EC_secp521r1 25 + +/** \brief Identifier for named curve brainpoolP256r1. */ +#define BR_EC_brainpoolP256r1 26 + +/** \brief Identifier for named curve brainpoolP384r1. */ +#define BR_EC_brainpoolP384r1 27 + +/** \brief Identifier for named curve brainpoolP512r1. */ +#define BR_EC_brainpoolP512r1 28 + +/** \brief Identifier for named curve Curve25519. */ +#define BR_EC_curve25519 29 + +/** \brief Identifier for named curve Curve448. */ +#define BR_EC_curve448 30 + +/** + * \brief Structure for an EC public key. + */ +typedef struct { + /** \brief Identifier for the curve used by this key. */ + int curve; + /** \brief Public curve point (uncompressed format). */ + unsigned char *q; + /** \brief Length of public curve point (in bytes). */ + size_t qlen; +} br_ec_public_key; + +/** + * \brief Structure for an EC private key. + * + * The private key is an integer modulo the curve subgroup order. The + * encoding below tolerates extra leading zeros. In general, it is + * recommended that the private key has the same length as the curve + * subgroup order. + */ +typedef struct { + /** \brief Identifier for the curve used by this key. */ + int curve; + /** \brief Private key (integer, unsigned big-endian encoding). */ + unsigned char *x; + /** \brief Private key length (in bytes). */ + size_t xlen; +} br_ec_private_key; + +/** + * \brief Type for an EC implementation. + */ +typedef struct { + /** + * \brief Supported curves. + * + * This word is a bitfield: bit `x` is set if the curve of ID `x` + * is supported. E.g. an implementation supporting both NIST P-256 + * (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have + * value `0x01800000` in this field. + */ + uint32_t supported_curves; + + /** + * \brief Get the conventional generator. + * + * This function returns the conventional generator (encoded + * curve point) for the specified curve. This function MUST NOT + * be called if the curve is not supported. + * + * \param curve curve identifier. + * \param len receiver for the encoded generator length (in bytes). + * \return the encoded generator. + */ + const unsigned char *(*generator)(int curve, size_t *len); + + /** + * \brief Get the subgroup order. + * + * This function returns the order of the subgroup generated by + * the conventional generator, for the specified curve. Unsigned + * big-endian encoding is used. This function MUST NOT be called + * if the curve is not supported. + * + * \param curve curve identifier. + * \param len receiver for the encoded order length (in bytes). + * \return the encoded order. + */ + const unsigned char *(*order)(int curve, size_t *len); + + /** + * \brief Get the offset and length for the X coordinate. + * + * This function returns the offset and length (in bytes) of + * the X coordinate in an encoded non-zero point. + * + * \param curve curve identifier. + * \param len receiver for the X coordinate length (in bytes). + * \return the offset for the X coordinate (in bytes). + */ + size_t (*xoff)(int curve, size_t *len); + + /** + * \brief Multiply a curve point by an integer. + * + * The source point is provided in array `G` (of size `Glen` bytes); + * the multiplication result is written over it. The multiplier + * `x` (of size `xlen` bytes) uses unsigned big-endian encoding. + * + * Rules: + * + * - The specified curve MUST be supported. + * + * - The source point must be a valid point on the relevant curve + * subgroup (and not the "point at infinity" either). If this is + * not the case, then this function returns an error (0). + * + * - The multiplier integer MUST be non-zero and less than the + * curve subgroup order. If this property does not hold, then + * the result is indeterminate and an error code is not + * guaranteed. + * + * Returned value is 1 on success, 0 on error. On error, the + * contents of `G` are indeterminate. + * + * \param G point to multiply. + * \param Glen length of the encoded point (in bytes). + * \param x multiplier (unsigned big-endian). + * \param xlen multiplier length (in bytes). + * \param curve curve identifier. + * \return 1 on success, 0 on error. + */ + uint32_t (*mul)(unsigned char *G, size_t Glen, + const unsigned char *x, size_t xlen, int curve); + + /** + * \brief Multiply the generator by an integer. + * + * The multiplier MUST be non-zero and less than the curve + * subgroup order. Results are indeterminate if this property + * does not hold. + * + * \param R output buffer for the point. + * \param x multiplier (unsigned big-endian). + * \param xlen multiplier length (in bytes). + * \param curve curve identifier. + * \return encoded result point length (in bytes). + */ + size_t (*mulgen)(unsigned char *R, + const unsigned char *x, size_t xlen, int curve); + + /** + * \brief Multiply two points by two integers and add the + * results. + * + * The point `x*A + y*B` is computed and written back in the `A` + * array. + * + * Rules: + * + * - The specified curve MUST be supported. + * + * - The source points (`A` and `B`) must be valid points on + * the relevant curve subgroup (and not the "point at + * infinity" either). If this is not the case, then this + * function returns an error (0). + * + * - If the `B` pointer is `NULL`, then the conventional + * subgroup generator is used. With some implementations, + * this may be faster than providing a pointer to the + * generator. + * + * - The multiplier integers (`x` and `y`) MUST be non-zero + * and less than the curve subgroup order. If either integer + * is zero, then an error is reported, but if one of them is + * not lower than the subgroup order, then the result is + * indeterminate and an error code is not guaranteed. + * + * - If the final result is the point at infinity, then an + * error is returned. + * + * Returned value is 1 on success, 0 on error. On error, the + * contents of `A` are indeterminate. + * + * \param A first point to multiply. + * \param B second point to multiply (`NULL` for the generator). + * \param len common length of the encoded points (in bytes). + * \param x multiplier for `A` (unsigned big-endian). + * \param xlen length of multiplier for `A` (in bytes). + * \param y multiplier for `A` (unsigned big-endian). + * \param ylen length of multiplier for `A` (in bytes). + * \param curve curve identifier. + * \return 1 on success, 0 on error. + */ + uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve); +} br_ec_impl; + +/** + * \brief EC implementation "i31". + * + * This implementation internally uses generic code for modular integers, + * with a representation as sequences of 31-bit words. It supports secp256r1, + * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). + */ +extern const br_ec_impl br_ec_prime_i31; + +/** + * \brief EC implementation "i15". + * + * This implementation internally uses generic code for modular integers, + * with a representation as sequences of 15-bit words. It supports secp256r1, + * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). + */ +extern const br_ec_impl br_ec_prime_i15; + +/** + * \brief EC implementation "m15" for P-256. + * + * This implementation uses specialised code for curve secp256r1 (also + * known as NIST P-256), with optional Karatsuba decomposition, and fast + * modular reduction thanks to the field modulus special format. Only + * 32-bit multiplications are used (with 32-bit results, not 64-bit). + */ +extern const br_ec_impl br_ec_p256_m15; + +/** + * \brief EC implementation "m31" for P-256. + * + * This implementation uses specialised code for curve secp256r1 (also + * known as NIST P-256), relying on multiplications of 31-bit values + * (MUL31). + */ +extern const br_ec_impl br_ec_p256_m31; + +/** + * \brief EC implementation "m62" (specialised code) for P-256. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer + * to that implementation. + */ +extern const br_ec_impl br_ec_p256_m62; + +/** + * \brief Get the "m62" implementation of P-256, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_p256_m62_get(void); + +/** + * \brief EC implementation "m64" (specialised code) for P-256. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer + * to that implementation. + */ +extern const br_ec_impl br_ec_p256_m64; + +/** + * \brief Get the "m64" implementation of P-256, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_p256_m64_get(void); + +/** + * \brief EC implementation "i15" (generic code) for Curve25519. + * + * This implementation uses the generic code for modular integers (with + * 15-bit words) to support Curve25519. Due to the specificities of the + * curve definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_i15; + +/** + * \brief EC implementation "i31" (generic code) for Curve25519. + * + * This implementation uses the generic code for modular integers (with + * 31-bit words) to support Curve25519. Due to the specificities of the + * curve definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_i31; + +/** + * \brief EC implementation "m15" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 15 bits. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m15; + +/** + * \brief EC implementation "m31" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 31 bits. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m31; + +/** + * \brief EC implementation "m62" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 62 bits, with a 124-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer + * to that implementation. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m62; + +/** + * \brief Get the "m62" implementation of Curve25519, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_c25519_m62_get(void); + +/** + * \brief EC implementation "m64" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer + * to that implementation. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m64; + +/** + * \brief Get the "m64" implementation of Curve25519, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_c25519_m64_get(void); + +/** + * \brief Aggregate EC implementation "m15". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m15` for Curve25519 + * - `br_ec_p256_m15` for NIST P-256 + * - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m15; + +/** + * \brief Aggregate EC implementation "m31". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m31` for Curve25519 + * - `br_ec_p256_m31` for NIST P-256 + * - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m31; + +/** + * \brief Get the "default" EC implementation for the current system. + * + * This returns a pointer to the preferred implementation on the + * current system. + * + * \return the default EC implementation. + */ +const br_ec_impl *br_ec_get_default(void); + +/** + * \brief Convert a signature from "raw" to "asn1". + * + * Conversion is done "in place" and the new length is returned. + * Conversion may enlarge the signature, but by no more than 9 bytes at + * most. On error, 0 is returned (error conditions include an odd raw + * signature length, or an oversized integer). + * + * \param sig signature to convert. + * \param sig_len signature length (in bytes). + * \return the new signature length, or 0 on error. + */ +size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len); + +/** + * \brief Convert a signature from "asn1" to "raw". + * + * Conversion is done "in place" and the new length is returned. + * Conversion may enlarge the signature, but the new signature length + * will be less than twice the source length at most. On error, 0 is + * returned (error conditions include an invalid ASN.1 structure or an + * oversized integer). + * + * \param sig signature to convert. + * \param sig_len signature length (in bytes). + * \return the new signature length, or 0 on error. + */ +size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len); + +/** + * \brief Type for an ECDSA signer function. + * + * A pointer to the EC implementation is provided. The hash value is + * assumed to have the length inferred from the designated hash function + * class. + * + * Signature is written in the buffer pointed to by `sig`, and the length + * (in bytes) is returned. On error, nothing is written in the buffer, + * and 0 is returned. This function returns 0 if the specified curve is + * not supported by the provided EC implementation. + * + * The signature format is either "raw" or "asn1", depending on the + * implementation; maximum length is predictable from the implemented + * curve: + * + * | curve | raw | asn1 | + * | :--------- | --: | ---: | + * | NIST P-256 | 64 | 72 | + * | NIST P-384 | 96 | 104 | + * | NIST P-521 | 132 | 139 | + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief Type for an ECDSA signature verification function. + * + * A pointer to the EC implementation is provided. The hashed value, + * computed over the purportedly signed data, is also provided with + * its length. + * + * The signature format is either "raw" or "asn1", depending on the + * implementation. + * + * Returned value is 1 on success (valid signature), 0 on error. This + * function returns 0 if the specified curve is not supported by the + * provided EC implementation. + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature generator, "i31" implementation, "asn1" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature generator, "i31" implementation, "raw" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature verifier, "i31" implementation, "asn1" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature verifier, "i31" implementation, "raw" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature generator, "i15" implementation, "asn1" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature generator, "i15" implementation, "raw" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature verifier, "i15" implementation, "asn1" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature verifier, "i15" implementation, "raw" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief Get "default" ECDSA implementation (signer, asn1 format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (signer, raw format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_raw_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, asn1 format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, raw format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void); + +/** + * \brief Maximum size for EC private key element buffer. + * + * This is the largest number of bytes that `br_ec_keygen()` may need or + * ever return. + */ +#define BR_EC_KBUF_PRIV_MAX_SIZE 72 + +/** + * \brief Maximum size for EC public key element buffer. + * + * This is the largest number of bytes that `br_ec_compute_public()` may + * need or ever return. + */ +#define BR_EC_KBUF_PUB_MAX_SIZE 145 + +/** + * \brief Generate a new EC private key. + * + * If the specified `curve` is not supported by the elliptic curve + * implementation (`impl`), then this function returns zero. + * + * The `sk` structure fields are set to the new private key data. In + * particular, `sk.x` is made to point to the provided key buffer (`kbuf`), + * in which the actual private key data is written. That buffer is assumed + * to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum + * size for all supported curves. + * + * The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then + * the private key is not actually generated, and `sk` may also be `NULL`; + * the minimum length for `kbuf` is still computed and returned. + * + * If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is + * still generated and stored in `kbuf`. + * + * \param rng_ctx source PRNG context (already initialized). + * \param impl the elliptic curve implementation. + * \param sk the private key structure to fill, or `NULL`. + * \param kbuf the key element buffer, or `NULL`. + * \param curve the curve identifier. + * \return the key data length (in bytes), or zero. + */ +size_t br_ec_keygen(const br_prng_class **rng_ctx, + const br_ec_impl *impl, br_ec_private_key *sk, + void *kbuf, int curve); + +/** + * \brief Compute EC public key from EC private key. + * + * This function uses the provided elliptic curve implementation (`impl`) + * to compute the public key corresponding to the private key held in `sk`. + * The public key point is written into `kbuf`, which is then linked from + * the `*pk` structure. The size of the public key point, i.e. the number + * of bytes used in `kbuf`, is returned. + * + * If `kbuf` is `NULL`, then the public key point is NOT computed, and + * the public key structure `*pk` is unmodified (`pk` may be `NULL` in + * that case). The size of the public key point is still returned. + * + * If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key + * point is computed and stored in `kbuf`, and its size is returned. + * + * If the curve used by the private key is not supported by the curve + * implementation, then this function returns zero. + * + * The private key MUST be valid. An off-range private key value is not + * necessarily detected, and leads to unpredictable results. + * + * \param impl the elliptic curve implementation. + * \param pk the public key structure to fill (or `NULL`). + * \param kbuf the public key point buffer (or `NULL`). + * \param sk the source private key. + * \return the public key point length (in bytes), or zero. + */ +size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk, + void *kbuf, const br_ec_private_key *sk); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_hash.h b/BearSSL-OG/libbearssl/inc/bearssl_hash.h new file mode 100644 index 0000000..7d7d233 --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_hash.h @@ -0,0 +1,1345 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_HASH_H__ +#define BR_BEARSSL_HASH_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_hash.h + * + * # Hash Functions + * + * This file documents the API for hash functions. + * + * + * ## Procedural API + * + * For each implemented hash function, of name "`xxx`", the following + * elements are defined: + * + * - `br_xxx_vtable` + * + * An externally defined instance of `br_hash_class`. + * + * - `br_xxx_SIZE` + * + * A macro that evaluates to the output size (in bytes) of the + * hash function. + * + * - `br_xxx_ID` + * + * A macro that evaluates to a symbolic identifier for the hash + * function. Such identifiers are used with HMAC and signature + * algorithm implementations. + * + * NOTE: for the "standard" hash functions defined in [the TLS + * standard](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1), + * the symbolic identifiers match the constants used in TLS, i.e. + * 1 to 6 for MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512, + * respectively. + * + * - `br_xxx_context` + * + * Context for an ongoing computation. It is allocated by the + * caller, and a pointer to it is passed to all functions. A + * context contains no interior pointer, so it can be moved around + * and cloned (with a simple `memcpy()` or equivalent) in order to + * capture the function state at some point. Computations that use + * distinct context structures are independent of each other. The + * first field of `br_xxx_context` is always a pointer to the + * `br_xxx_vtable` structure; `br_xxx_init()` sets that pointer. + * + * - `br_xxx_init(br_xxx_context *ctx)` + * + * Initialise the provided context. Previous contents of the structure + * are ignored. This calls resets the context to the start of a new + * hash computation; it also sets the first field of the context + * structure (called `vtable`) to a pointer to the statically + * allocated constant `br_xxx_vtable` structure. + * + * - `br_xxx_update(br_xxx_context *ctx, const void *data, size_t len)` + * + * Add some more bytes to the hash computation represented by the + * provided context. + * + * - `br_xxx_out(const br_xxx_context *ctx, void *out)` + * + * Complete the hash computation and write the result in the provided + * buffer. The output buffer MUST be large enough to accommodate the + * result. The context is NOT modified by this operation, so this + * function can be used to get a "partial hash" while still keeping + * the possibility of adding more bytes to the input. + * + * - `br_xxx_state(const br_xxx_context *ctx, void *out)` + * + * Get a copy of the "current state" for the computation so far. For + * MD functions (MD5, SHA-1, SHA-2 family), this is the running state + * resulting from the processing of the last complete input block. + * Returned value is the current input length (in bytes). + * + * - `br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count)` + * + * Set the internal state to the provided values. The 'stb' and + * 'count' values shall match that which was obtained from + * `br_xxx_state()`. This restores the hash state only if the state + * values were at an appropriate block boundary. This does NOT set + * the `vtable` pointer in the context. + * + * Context structures can be discarded without any explicit deallocation. + * Hash function implementations are purely software and don't reserve + * any resources outside of the context structure itself. + * + * + * ## Object-Oriented API + * + * For each hash function that follows the procedural API described + * above, an object-oriented API is also provided. In that API, function + * pointers from the vtable (`br_xxx_vtable`) are used. The vtable + * incarnates object-oriented programming. An introduction on the OOP + * concept used here can be read on the BearSSL Web site:
+ *    [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) + * + * The vtable offers functions called `init()`, `update()`, `out()`, + * `set()` and `set_state()`, which are in fact the functions from + * the procedural API. That vtable also contains two informative fields: + * + * - `context_size` + * + * The size of the context structure (`br_xxx_context`), in bytes. + * This can be used by generic implementations to perform dynamic + * context allocation. + * + * - `desc` + * + * A "descriptor" field that encodes some information on the hash + * function: symbolic identifier, output size, state size, + * internal block size, details on the padding. + * + * Users of this object-oriented API (in particular generic HMAC + * implementations) may make the following assumptions: + * + * - Hash output size is no more than 64 bytes. + * - Hash internal state size is no more than 64 bytes. + * - Internal block size is a power of two, no less than 16 and no more + * than 256. + * + * + * ## Implemented Hash Functions + * + * Implemented hash functions are: + * + * | Function | Name | Output length | State length | + * | :-------- | :------ | :-----------: | :----------: | + * | MD5 | md5 | 16 | 16 | + * | SHA-1 | sha1 | 20 | 20 | + * | SHA-224 | sha224 | 28 | 32 | + * | SHA-256 | sha256 | 32 | 32 | + * | SHA-384 | sha384 | 48 | 64 | + * | SHA-512 | sha512 | 64 | 64 | + * | MD5+SHA-1 | md5sha1 | 36 | 36 | + * + * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the + * same input; in the implementation, the internal data buffer is + * shared, thus making it more memory-efficient than separate MD5 and + * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS + * 1.1.) + * + * + * ## Multi-Hasher + * + * An aggregate hasher is provided, that can compute several standard + * hash functions in parallel. It uses `br_multihash_context` and a + * procedural API. It is configured with the implementations (the vtables) + * that it should use; it will then compute all these hash functions in + * parallel, on the same input. It is meant to be used in cases when the + * hash of an object will be used, but the exact hash function is not + * known yet (typically, streamed processing on X.509 certificates). + * + * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 + * and SHA-512) are supported by the multi-hasher. + * + * + * ## GHASH + * + * GHASH is not a generic hash function; it is a _universal_ hash function, + * which, as the name does not say, means that it CANNOT be used in most + * places where a hash function is needed. GHASH is used within the GCM + * encryption mode, to provide the checked integrity functionality. + * + * A GHASH implementation is basically a function that uses the type defined + * in this file under the name `br_ghash`: + * + * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); + * + * The `y` pointer refers to a 16-byte value which is used as input, and + * receives the output of the GHASH invocation. `h` is a 16-byte secret + * value (that serves as key). `data` and `len` define the input data. + * + * Three GHASH implementations are provided, all constant-time, based on + * the use of integer multiplications with appropriate masking to cancel + * carry propagation. + */ + +/** + * \brief Class type for hash function implementations. + * + * A `br_hash_class` instance references the methods implementing a hash + * function. Constant instances of this structure are defined for each + * implemented hash function. Such instances are also called "vtables". + * + * Vtables are used to support object-oriented programming, as + * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). + */ +typedef struct br_hash_class_ br_hash_class; +struct br_hash_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate for + * computing this hash function. + */ + size_t context_size; + + /** + * \brief Descriptor word that contains information about the hash + * function. + * + * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` + * and `BR_HASHDESC_xxx_MASK` to access the specific value, as + * follows: + * + * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK + * + * The defined elements are: + * + * - `ID`: the symbolic identifier for the function, as defined + * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) + * (MD5 = 1, SHA-1 = 2,...). + * + * - `OUT`: hash output size, in bytes. + * + * - `STATE`: internal running state size, in bytes. + * + * - `LBLEN`: base-2 logarithm for the internal block size, as + * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 + * and SHA-256, since these functions use 64-byte blocks; for + * SHA-384 and SHA-512, this is 7, corresponding to their + * 128-byte blocks). + * + * The descriptor may contain a few other flags. + */ + uint32_t desc; + + /** + * \brief Initialisation method. + * + * This method takes as parameter a pointer to a context area, + * that it initialises. The first field of the context is set + * to this vtable; other elements are initialised for a new hash + * computation. + * + * \param ctx pointer to (the first field of) the context. + */ + void (*init)(const br_hash_class **ctx); + + /** + * \brief Data injection method. + * + * The `len` bytes starting at address `data` are injected into + * the running hash computation incarnated by the specified + * context. The context is updated accordingly. It is allowed + * to have `len == 0`, in which case `data` is ignored (and could + * be `NULL`), and nothing happens. + * on the input data. + * + * \param ctx pointer to (the first field of) the context. + * \param data pointer to the first data byte to inject. + * \param len number of bytes to inject. + */ + void (*update)(const br_hash_class **ctx, const void *data, size_t len); + + /** + * \brief Produce hash output. + * + * The hash output corresponding to all data bytes injected in the + * context since the last `init()` call is computed, and written + * in the buffer pointed to by `dst`. The hash output size depends + * on the implemented hash function (e.g. 16 bytes for MD5). + * The context is _not_ modified by this call, so further bytes + * may be afterwards injected to continue the current computation. + * + * \param ctx pointer to (the first field of) the context. + * \param dst destination buffer for the hash output. + */ + void (*out)(const br_hash_class *const *ctx, void *dst); + + /** + * \brief Get running state. + * + * This method saves the current running state into the `dst` + * buffer. What constitutes the "running state" depends on the + * hash function; for Merkle-DamgÃ¥rd hash functions (like + * MD5 or SHA-1), this is the output obtained after processing + * each block. The number of bytes injected so far is returned. + * The context is not modified by this call. + * + * \param ctx pointer to (the first field of) the context. + * \param dst destination buffer for the state. + * \return the injected total byte length. + */ + uint64_t (*state)(const br_hash_class *const *ctx, void *dst); + + /** + * \brief Set running state. + * + * This methods replaces the running state for the function. + * + * \param ctx pointer to (the first field of) the context. + * \param stb source buffer for the state. + * \param count injected total byte length. + */ + void (*set_state)(const br_hash_class **ctx, + const void *stb, uint64_t count); +}; + +#ifndef BR_DOXYGEN_IGNORE +#define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) +#define BR_HASHDESC_ID_OFF 0 +#define BR_HASHDESC_ID_MASK 0xFF + +#define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) +#define BR_HASHDESC_OUT_OFF 8 +#define BR_HASHDESC_OUT_MASK 0x7F + +#define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) +#define BR_HASHDESC_STATE_OFF 15 +#define BR_HASHDESC_STATE_MASK 0xFF + +#define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) +#define BR_HASHDESC_LBLEN_OFF 23 +#define BR_HASHDESC_LBLEN_MASK 0x0F + +#define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) +#define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) +#define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) +#endif + +/* + * Specific hash functions. + * + * Rules for contexts: + * -- No interior pointer. + * -- No pointer to external dynamically allocated resources. + * -- First field is called 'vtable' and is a pointer to a + * const-qualified br_hash_class instance (pointer is set by init()). + * -- SHA-224 and SHA-256 contexts are identical. + * -- SHA-384 and SHA-512 contexts are identical. + * + * Thus, contexts can be moved and cloned to capture the hash function + * current state; and there is no need for any explicit "release" function. + */ + +/** + * \brief Symbolic identifier for MD5. + */ +#define br_md5_ID 1 + +/** + * \brief MD5 output size (in bytes). + */ +#define br_md5_SIZE 16 + +/** + * \brief Constant vtable for MD5. + */ +extern const br_hash_class br_md5_vtable; + +/** + * \brief MD5 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[4]; +#endif +} br_md5_context; + +/** + * \brief MD5 context initialisation. + * + * This function initialises or resets a context for a new MD5 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_md5_init(br_md5_context *ctx); + +/** + * \brief Inject some data bytes in a running MD5 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_md5_update(br_md5_context *ctx, const void *data, size_t len); + +/** + * \brief Compute MD5 output. + * + * The MD5 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_md5_out(const br_md5_context *ctx, void *out); + +/** + * \brief Save MD5 running state. + * + * The running state for MD5 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_md5_state(const br_md5_context *ctx, void *out); + +/** + * \brief Restore MD5 running state. + * + * The running state for MD5 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-1. + */ +#define br_sha1_ID 2 + +/** + * \brief SHA-1 output size (in bytes). + */ +#define br_sha1_SIZE 20 + +/** + * \brief Constant vtable for SHA-1. + */ +extern const br_hash_class br_sha1_vtable; + +/** + * \brief SHA-1 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[5]; +#endif +} br_sha1_context; + +/** + * \brief SHA-1 context initialisation. + * + * This function initialises or resets a context for a new SHA-1 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha1_init(br_sha1_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-1 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-1 output. + * + * The SHA-1 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha1_out(const br_sha1_context *ctx, void *out); + +/** + * \brief Save SHA-1 running state. + * + * The running state for SHA-1 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); + +/** + * \brief Restore SHA-1 running state. + * + * The running state for SHA-1 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-224. + */ +#define br_sha224_ID 3 + +/** + * \brief SHA-224 output size (in bytes). + */ +#define br_sha224_SIZE 28 + +/** + * \brief Constant vtable for SHA-224. + */ +extern const br_hash_class br_sha224_vtable; + +/** + * \brief SHA-224 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[8]; +#endif +} br_sha224_context; + +/** + * \brief SHA-224 context initialisation. + * + * This function initialises or resets a context for a new SHA-224 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha224_init(br_sha224_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-224 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-224 output. + * + * The SHA-224 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha224_out(const br_sha224_context *ctx, void *out); + +/** + * \brief Save SHA-224 running state. + * + * The running state for SHA-224 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); + +/** + * \brief Restore SHA-224 running state. + * + * The running state for SHA-224 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha224_set_state(br_sha224_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-256. + */ +#define br_sha256_ID 4 + +/** + * \brief SHA-256 output size (in bytes). + */ +#define br_sha256_SIZE 32 + +/** + * \brief Constant vtable for SHA-256. + */ +extern const br_hash_class br_sha256_vtable; + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief SHA-256 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +} br_sha256_context; +#else +typedef br_sha224_context br_sha256_context; +#endif + +/** + * \brief SHA-256 context initialisation. + * + * This function initialises or resets a context for a new SHA-256 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha256_init(br_sha256_context *ctx); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Inject some data bytes in a running SHA-256 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); +#else +#define br_sha256_update br_sha224_update +#endif + +/** + * \brief Compute SHA-256 output. + * + * The SHA-256 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha256_out(const br_sha256_context *ctx, void *out); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Save SHA-256 running state. + * + * The running state for SHA-256 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); +#else +#define br_sha256_state br_sha224_state +#endif + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Restore SHA-256 running state. + * + * The running state for SHA-256 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha256_set_state(br_sha256_context *ctx, + const void *stb, uint64_t count); +#else +#define br_sha256_set_state br_sha224_set_state +#endif + +/** + * \brief Symbolic identifier for SHA-384. + */ +#define br_sha384_ID 5 + +/** + * \brief SHA-384 output size (in bytes). + */ +#define br_sha384_SIZE 48 + +/** + * \brief Constant vtable for SHA-384. + */ +extern const br_hash_class br_sha384_vtable; + +/** + * \brief SHA-384 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[128]; + uint64_t count; + uint64_t val[8]; +#endif +} br_sha384_context; + +/** + * \brief SHA-384 context initialisation. + * + * This function initialises or resets a context for a new SHA-384 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha384_init(br_sha384_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-384 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-384 output. + * + * The SHA-384 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha384_out(const br_sha384_context *ctx, void *out); + +/** + * \brief Save SHA-384 running state. + * + * The running state for SHA-384 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); + +/** + * \brief Restore SHA-384 running state. + * + * The running state for SHA-384 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha384_set_state(br_sha384_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-512. + */ +#define br_sha512_ID 6 + +/** + * \brief SHA-512 output size (in bytes). + */ +#define br_sha512_SIZE 64 + +/** + * \brief Constant vtable for SHA-512. + */ +extern const br_hash_class br_sha512_vtable; + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief SHA-512 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +} br_sha512_context; +#else +typedef br_sha384_context br_sha512_context; +#endif + +/** + * \brief SHA-512 context initialisation. + * + * This function initialises or resets a context for a new SHA-512 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha512_init(br_sha512_context *ctx); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Inject some data bytes in a running SHA-512 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); +#else +#define br_sha512_update br_sha384_update +#endif + +/** + * \brief Compute SHA-512 output. + * + * The SHA-512 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha512_out(const br_sha512_context *ctx, void *out); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Save SHA-512 running state. + * + * The running state for SHA-512 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); +#else +#define br_sha512_state br_sha384_state +#endif + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Restore SHA-512 running state. + * + * The running state for SHA-512 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha512_set_state(br_sha512_context *ctx, + const void *stb, uint64_t count); +#else +#define br_sha512_set_state br_sha384_set_state +#endif + +/* + * "md5sha1" is a special hash function that computes both MD5 and SHA-1 + * on the same input, and produces a 36-byte output (MD5 and SHA-1 + * concatenation, in that order). State size is also 36 bytes. + */ + +/** + * \brief Symbolic identifier for MD5+SHA-1. + * + * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the + * same input. It is not one of the functions identified in TLS, so + * we give it a symbolic identifier of value 0. + */ +#define br_md5sha1_ID 0 + +/** + * \brief MD5+SHA-1 output size (in bytes). + */ +#define br_md5sha1_SIZE 36 + +/** + * \brief Constant vtable for MD5+SHA-1. + */ +extern const br_hash_class br_md5sha1_vtable; + +/** + * \brief MD5+SHA-1 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val_md5[4]; + uint32_t val_sha1[5]; +#endif +} br_md5sha1_context; + +/** + * \brief MD5+SHA-1 context initialisation. + * + * This function initialises or resets a context for a new SHA-512 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_md5sha1_init(br_md5sha1_context *ctx); + +/** + * \brief Inject some data bytes in a running MD5+SHA-1 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); + +/** + * \brief Compute MD5+SHA-1 output. + * + * The MD5+SHA-1 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); + +/** + * \brief Save MD5+SHA-1 running state. + * + * The running state for MD5+SHA-1 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); + +/** + * \brief Restore MD5+SHA-1 running state. + * + * The running state for MD5+SHA-1 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_md5sha1_set_state(br_md5sha1_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Aggregate context for configurable hash function support. + * + * The `br_hash_compat_context` type is a type which is large enough to + * serve as context for all standard hash functions defined above. + */ +typedef union { + const br_hash_class *vtable; + br_md5_context md5; + br_sha1_context sha1; + br_sha224_context sha224; + br_sha256_context sha256; + br_sha384_context sha384; + br_sha512_context sha512; + br_md5sha1_context md5sha1; +} br_hash_compat_context; + +/* + * The multi-hasher is a construct that handles hashing of the same input + * data with several hash functions, with a single shared input buffer. + * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 + * simultaneously, though which functions are activated depends on + * the set implementation pointers. + */ + +/** + * \brief Multi-hasher context structure. + * + * The multi-hasher runs up to six hash functions in the standard TLS list + * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over + * the same input. + * + * The multi-hasher does _not_ follow the OOP structure with a vtable. + * Instead, it is configured with the vtables of the hash functions it + * should run. Structure fields are not supposed to be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[128]; + uint64_t count; + uint32_t val_32[25]; + uint64_t val_64[16]; + const br_hash_class *impl[6]; +#endif +} br_multihash_context; + +/** + * \brief Clear a multi-hasher context. + * + * This should always be called once on a given context, _before_ setting + * the implementation pointers. + * + * \param ctx the multi-hasher context. + */ +void br_multihash_zero(br_multihash_context *ctx); + +/** + * \brief Set a hash function implementation. + * + * Implementations shall be set _after_ clearing the context (with + * `br_multihash_zero()`) but _before_ initialising the computation + * (with `br_multihash_init()`). The hash function implementation + * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, + * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove + * an implementation from the multi-hasher. + * + * \param ctx the multi-hasher context. + * \param id the hash function symbolic identifier. + * \param impl the hash function vtable, or `NULL`. + */ +static __inline void br_multihash_setimpl(br_multihash_context *ctx, + int id, const br_hash_class *impl) +{ + /* + * This code relies on hash functions ID being values 1 to 6, + * in the MD5 to SHA-512 order. + */ + ctx->impl[id - 1] = impl; +} + +/** + * \brief Get a hash function implementation. + * + * This function returns the currently configured vtable for a given + * hash function (by symbolic ID). If no such function was configured in + * the provided multi-hasher context, then this function returns `NULL`. + * + * \param ctx the multi-hasher context. + * \param id the hash function symbolic identifier. + * \return the hash function vtable, or `NULL`. + */ +static __inline const br_hash_class * +br_multihash_getimpl(const br_multihash_context *ctx, int id) +{ + return ctx->impl[id - 1]; +} + +/** + * \brief Reset a multi-hasher context. + * + * This function prepares the context for a new hashing computation, + * for all implementations configured at that point. + * + * \param ctx the multi-hasher context. + */ +void br_multihash_init(br_multihash_context *ctx); + +/** + * \brief Inject some data bytes in a running multi-hashing computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_multihash_update(br_multihash_context *ctx, + const void *data, size_t len); + +/** + * \brief Compute a hash output from a multi-hasher. + * + * The hash output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `dst`. The hash + * function to use is identified by `id` and must be one of the standard + * hash functions. If that hash function was indeed configured in the + * multi-hasher context, the corresponding hash value is written in + * `dst` and its length (in bytes) is returned. If the hash function + * was _not_ configured, then nothing is written in `dst` and 0 is + * returned. + * + * The context itself is not modified, so extra bytes may be injected + * afterwards to continue the hash computations. + * + * \param ctx pointer to the context structure. + * \param id the hash function symbolic identifier. + * \param dst destination buffer for the hash output. + * \return the hash output length (in bytes), or 0. + */ +size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); + +/** + * \brief Type for a GHASH implementation. + * + * GHASH is a sort of keyed hash meant to be used to implement GCM in + * combination with a block cipher (with 16-byte blocks). + * + * The `y` array has length 16 bytes and is used for input and output; in + * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte + * value that serves as key (it is derived from the encryption key in GCM, + * using the block cipher). The data length (`len`) is expressed in bytes. + * The `y` array is updated. + * + * If the data length is not a multiple of 16, then the data is implicitly + * padded with zeros up to the next multiple of 16. Thus, when using GHASH + * in GCM, this method may be called twice, for the associated data and + * for the ciphertext, respectively; the zero-padding implements exactly + * the GCM rules. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (mixed 32-bit). + * + * This implementation uses multiplications of 32-bit values, with a + * 64-bit result. It is constant-time (if multiplications are + * constant-time). + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (strict 32-bit). + * + * This implementation uses multiplications of 32-bit values, with a + * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, + * but it is expected to be faster on architectures for which the + * 32-bit multiplication opcode does not yield the upper 32 bits of the + * product. It is constant-time (if multiplications are constant-time). + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (64-bit). + * + * This implementation uses multiplications of 64-bit values, with a + * 64-bit result. It is constant-time (if multiplications are + * constant-time). It is substantially faster than `br_ghash_ctmul()` + * and `br_ghash_ctmul32()` on most 64-bit architectures. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using the `pclmulqdq` opcode (part of the + * AES-NI instructions). + * + * This implementation is available only on x86 platforms where the + * compiler supports the relevant intrinsic functions. Even if the + * compiler supports these functions, the local CPU might not support + * the `pclmulqdq` opcode, meaning that a call will fail with an + * illegal instruction exception. To safely obtain a pointer to this + * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pclmul` GHASH implementation, if available. + * + * If the `pclmul` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pclmul()` function. Otherwise, it will return `0`. + * + * \return the `pclmul` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pclmul_get(void); + +/** + * \brief GHASH implementation using the POWER8 opcodes. + * + * This implementation is available only on POWER8 platforms (and later). + * To safely obtain a pointer to this function when supported (or 0 + * otherwise), use `br_ghash_pwr8_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pwr8` GHASH implementation, if available. + * + * If the `pwr8` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pwr8()` function. Otherwise, it will return `0`. + * + * \return the `pwr8` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pwr8_get(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_hmac.h b/BearSSL-OG/libbearssl/inc/bearssl_hmac.h new file mode 100644 index 0000000..baa968b --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_hmac.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_HMAC_H__ +#define BR_BEARSSL_HMAC_H__ + +#include +#include + +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_hmac.h + * + * # HMAC + * + * HMAC is initialized with a key and an underlying hash function; it + * then fills a "key context". That context contains the processed + * key. + * + * With the key context, a HMAC context can be initialized to process + * the input bytes and obtain the MAC output. The key context is not + * modified during that process, and can be reused. + * + * IMPORTANT: HMAC shall be used only with functions that have the + * following properties: + * + * - hash output size does not exceed 64 bytes; + * - hash internal state size does not exceed 64 bytes; + * - internal block length is a power of 2 between 16 and 256 bytes. + */ + +/** + * \brief HMAC key context. + * + * The HMAC key context is initialised with a hash function implementation + * and a secret key. Contents are opaque (callers should not access them + * directly). The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + const br_hash_class *dig_vtable; + unsigned char ksi[64], kso[64]; +#endif +} br_hmac_key_context; + +/** + * \brief HMAC key context initialisation. + * + * Initialise the key context with the provided key, using the hash function + * identified by `digest_vtable`. This supports arbitrary key lengths. + * + * \param kc HMAC key context to initialise. + * \param digest_vtable pointer to the hash function implementation vtable. + * \param key pointer to the HMAC secret key. + * \param key_len HMAC secret key length (in bytes). + */ +void br_hmac_key_init(br_hmac_key_context *kc, + const br_hash_class *digest_vtable, const void *key, size_t key_len); + +/* + * \brief Get the underlying hash function. + * + * This function returns a pointer to the implementation vtable of the + * hash function used for this HMAC key context. + * + * \param kc HMAC key context. + * \return the hash function implementation. + */ +static __inline const br_hash_class *br_hmac_key_get_digest( + const br_hmac_key_context *kc) +{ + return kc->dig_vtable; +} + +/** + * \brief HMAC computation context. + * + * The HMAC computation context maintains the state for a single HMAC + * computation. It is modified as input bytes are injected. The context + * is caller-allocated and has no release function since it does not + * dynamically allocate external resources. Its contents are opaque. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + br_hash_compat_context dig; + unsigned char kso[64]; + size_t out_len; +#endif +} br_hmac_context; + +/** + * \brief HMAC computation initialisation. + * + * Initialise a HMAC context with a key context. The key context is + * unmodified. Relevant data from the key context is immediately copied; + * the key context can thus be independently reused, modified or released + * without impacting this HMAC computation. + * + * An explicit output length can be specified; the actual output length + * will be the minimum of that value and the natural HMAC output length. + * If `out_len` is 0, then the natural HMAC output length is selected. The + * "natural output length" is the output length of the underlying hash + * function. + * + * \param ctx HMAC context to initialise. + * \param kc HMAC key context (already initialised with the key). + * \param out_len HMAC output length (0 to select "natural length"). + */ +void br_hmac_init(br_hmac_context *ctx, + const br_hmac_key_context *kc, size_t out_len); + +/** + * \brief Get the HMAC output size. + * + * The HMAC output size is the number of bytes that will actually be + * produced with `br_hmac_out()` with the provided context. This function + * MUST NOT be called on a non-initialised HMAC computation context. + * The returned value is the minimum of the HMAC natural length (output + * size of the underlying hash function) and the `out_len` parameter which + * was used with the last `br_hmac_init()` call on that context (if the + * initialisation `out_len` parameter was 0, then this function will + * return the HMAC natural length). + * + * \param ctx the (already initialised) HMAC computation context. + * \return the HMAC actual output size. + */ +static __inline size_t +br_hmac_size(br_hmac_context *ctx) +{ + return ctx->out_len; +} + +/* + * \brief Get the underlying hash function. + * + * This function returns a pointer to the implementation vtable of the + * hash function used for this HMAC context. + * + * \param hc HMAC context. + * \return the hash function implementation. + */ +static __inline const br_hash_class *br_hmac_get_digest( + const br_hmac_context *hc) +{ + return hc->dig.vtable; +} + +/** + * \brief Inject some bytes in HMAC. + * + * The provided `len` bytes are injected as extra input in the HMAC + * computation incarnated by the `ctx` HMAC context. It is acceptable + * that `len` is zero, in which case `data` is ignored (and may be + * `NULL`) and this function does nothing. + */ +void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len); + +/** + * \brief Compute the HMAC output. + * + * The destination buffer MUST be large enough to accommodate the result; + * its length is at most the "natural length" of HMAC (i.e. the output + * length of the underlying hash function). The context is NOT modified; + * further bytes may be processed. Thus, "partial HMAC" values can be + * efficiently obtained. + * + * Returned value is the output length (in bytes). + * + * \param ctx HMAC computation context. + * \param out destination buffer for the HMAC output. + * \return the produced value length (in bytes). + */ +size_t br_hmac_out(const br_hmac_context *ctx, void *out); + +/** + * \brief Constant-time HMAC computation. + * + * This function compute the HMAC output in constant time. Some extra + * input bytes are processed, then the output is computed. The extra + * input consists in the `len` bytes pointed to by `data`. The `len` + * parameter must lie between `min_len` and `max_len` (inclusive); + * `max_len` bytes are actually read from `data`. Computing time (and + * memory access pattern) will not depend upon the data byte contents or + * the value of `len`. + * + * The output is written in the `out` buffer, that MUST be large enough + * to receive it. + * + * The difference `max_len - min_len` MUST be less than 230 + * (i.e. about one gigabyte). + * + * This function computes the output properly only if the underlying + * hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256, + * SHA-384 or SHA-512). + * + * The provided context is NOT modified. + * + * \param ctx the (already initialised) HMAC computation context. + * \param data the extra input bytes. + * \param len the extra input length (in bytes). + * \param min_len minimum extra input length (in bytes). + * \param max_len maximum extra input length (in bytes). + * \param out destination buffer for the HMAC output. + * \return the produced value length (in bytes). + */ +size_t br_hmac_outCT(const br_hmac_context *ctx, + const void *data, size_t len, size_t min_len, size_t max_len, + void *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_kdf.h b/BearSSL-OG/libbearssl/inc/bearssl_kdf.h new file mode 100644 index 0000000..955b843 --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_kdf.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_KDF_H__ +#define BR_BEARSSL_KDF_H__ + +#include +#include + +#include "bearssl_hash.h" +#include "bearssl_hmac.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_kdf.h + * + * # Key Derivation Functions + * + * KDF are functions that takes a variable length input, and provide a + * variable length output, meant to be used to derive subkeys from a + * master key. + * + * ## HKDF + * + * HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869). + * It is based on HMAC, itself using an underlying hash function. Any + * hash function can be used, as long as it is compatible with the rules + * for the HMAC implementation (i.e. output size is 64 bytes or less, hash + * internal state size is 64 bytes or less, and the internal block length is + * a power of 2 between 16 and 256 bytes). HKDF has two phases: + * + * - HKDF-Extract: the input data in ingested, along with a "salt" value. + * + * - HKDF-Expand: the output is produced, from the result of processing + * the input and salt, and using an extra non-secret parameter called + * "info". + * + * The "salt" and "info" strings are non-secret and can be empty. Their role + * is normally to bind the input and output, respectively, to conventional + * identifiers that qualifu them within the used protocol or application. + * + * The implementation defined in this file uses the following functions: + * + * - `br_hkdf_init()`: initialize an HKDF context, with a hash function, + * and the salt. This starts the HKDF-Extract process. + * + * - `br_hkdf_inject()`: inject more input bytes. This function may be + * called repeatedly if the input data is provided by chunks. + * + * - `br_hkdf_flip()`: end the HKDF-Extract process, and start the + * HKDF-Expand process. + * + * - `br_hkdf_produce()`: get the next bytes of output. This function + * may be called several times to obtain the full output by chunks. + * For correct HKDF processing, the same "info" string must be + * provided for each call. + * + * Note that the HKDF total output size (the number of bytes that + * HKDF-Expand is willing to produce) is limited: if the hash output size + * is _n_ bytes, then the maximum output size is _255*n_. + * + * ## SHAKE + * + * SHAKE is defined in + * [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final) + * under two versions: SHAKE128 and SHAKE256, offering an alleged + * "security level" of 128 and 256 bits, respectively (SHAKE128 is + * about 20 to 25% faster than SHAKE256). SHAKE internally relies on + * the Keccak family of sponge functions, not on any externally provided + * hash function. Contrary to HKDF, SHAKE does not have a concept of + * either a "salt" or an "info" string. The API consists in four + * functions: + * + * - `br_shake_init()`: initialize a SHAKE context for a given + * security level. + * + * - `br_shake_inject()`: inject more input bytes. This function may be + * called repeatedly if the input data is provided by chunks. + * + * - `br_shake_flip()`: end the data injection process, and start the + * data production process. + * + * - `br_shake_produce()`: get the next bytes of output. This function + * may be called several times to obtain the full output by chunks. + */ + +/** + * \brief HKDF context. + * + * The HKDF context is initialized with a hash function implementation + * and a salt value. Contents are opaque (callers should not access them + * directly). The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + union { + br_hmac_context hmac_ctx; + br_hmac_key_context prk_ctx; + } u; + unsigned char buf[64]; + size_t ptr; + size_t dig_len; + unsigned chunk_num; +#endif +} br_hkdf_context; + +/** + * \brief HKDF context initialization. + * + * The underlying hash function and salt value are provided. Arbitrary + * salt lengths can be used. + * + * HKDF makes a difference between a salt of length zero, and an + * absent salt (the latter being equivalent to a salt consisting of + * bytes of value zero, of the same length as the hash function output). + * If `salt_len` is zero, then this function assumes that the salt is + * present but of length zero. To specify an _absent_ salt, use + * `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored). + * + * \param hc HKDF context to initialise. + * \param digest_vtable pointer to the hash function implementation vtable. + * \param salt HKDF-Extract salt. + * \param salt_len HKDF-Extract salt length (in bytes). + */ +void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable, + const void *salt, size_t salt_len); + +/** + * \brief The special "absent salt" value for HKDF. + */ +#define BR_HKDF_NO_SALT (&br_hkdf_no_salt) + +#ifndef BR_DOXYGEN_IGNORE +extern const unsigned char br_hkdf_no_salt; +#endif + +/** + * \brief HKDF input injection (HKDF-Extract). + * + * This function injects some more input bytes ("key material") into + * HKDF. This function may be called several times, after `br_hkdf_init()` + * but before `br_hkdf_flip()`. + * + * \param hc HKDF context. + * \param ikm extra input bytes. + * \param ikm_len number of extra input bytes. + */ +void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len); + +/** + * \brief HKDF switch to the HKDF-Expand phase. + * + * This call terminates the HKDF-Extract process (input injection), and + * starts the HKDF-Expand process (output production). + * + * \param hc HKDF context. + */ +void br_hkdf_flip(br_hkdf_context *hc); + +/** + * \brief HKDF output production (HKDF-Expand). + * + * Produce more output bytes from the current state. This function may be + * called several times, but only after `br_hkdf_flip()`. + * + * Returned value is the number of actually produced bytes. The total + * output length is limited to 255 times the output length of the + * underlying hash function. + * + * \param hc HKDF context. + * \param info application specific information string. + * \param info_len application specific information string length (in bytes). + * \param out destination buffer for the HKDF output. + * \param out_len the length of the requested output (in bytes). + * \return the produced output length (in bytes). + */ +size_t br_hkdf_produce(br_hkdf_context *hc, + const void *info, size_t info_len, void *out, size_t out_len); + +/** + * \brief SHAKE context. + * + * The HKDF context is initialized with a "security level". The internal + * notion is called "capacity"; the capacity is twice the security level + * (for instance, SHAKE128 has capacity 256). + * + * The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char dbuf[200]; + size_t dptr; + size_t rate; + uint64_t A[25]; +#endif +} br_shake_context; + +/** + * \brief SHAKE context initialization. + * + * The context is initialized for the provided "security level". + * Internally, this sets the "capacity" to twice the security level; + * thus, for SHAKE128, the `security_level` parameter should be 128, + * which corresponds to a 256-bit capacity. + * + * Allowed security levels are all multiples of 32, from 32 to 768, + * inclusive. Larger security levels imply lower performance; levels + * beyond 256 bits don't make much sense. Standard levels are 128 + * and 256 bits (for SHAKE128 and SHAKE256, respectively). + * + * \param sc SHAKE context to initialise. + * \param security_level security level (in bits). + */ +void br_shake_init(br_shake_context *sc, int security_level); + +/** + * \brief SHAKE input injection. + * + * This function injects some more input bytes ("key material") into + * SHAKE. This function may be called several times, after `br_shake_init()` + * but before `br_shake_flip()`. + * + * \param sc SHAKE context. + * \param data extra input bytes. + * \param len number of extra input bytes. + */ +void br_shake_inject(br_shake_context *sc, const void *data, size_t len); + +/** + * \brief SHAKE switch to production phase. + * + * This call terminates the input injection process, and starts the + * output production process. + * + * \param sc SHAKE context. + */ +void br_shake_flip(br_shake_context *hc); + +/** + * \brief SHAKE output production. + * + * Produce more output bytes from the current state. This function may be + * called several times, but only after `br_shake_flip()`. + * + * There is no practical limit to the number of bytes that may be produced. + * + * \param sc SHAKE context. + * \param out destination buffer for the SHAKE output. + * \param len the length of the requested output (in bytes). + */ +void br_shake_produce(br_shake_context *sc, void *out, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_pem.h b/BearSSL-OG/libbearssl/inc/bearssl_pem.h new file mode 100644 index 0000000..d61cc36 --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_pem.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_PEM_H__ +#define BR_BEARSSL_PEM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_pem.h + * + * # PEM Support + * + * PEM is a traditional encoding layer use to store binary objects (in + * particular X.509 certificates, and private keys) in text files. While + * the acronym comes from an old, defunct standard ("Privacy Enhanced + * Mail"), the format has been reused, with some variations, by many + * systems, and is a _de facto_ standard, even though it is not, actually, + * specified in all clarity anywhere. + * + * ## Format Details + * + * BearSSL contains a generic, streamed PEM decoder, which handles the + * following format: + * + * - The input source (a sequence of bytes) is assumed to be the + * encoding of a text file in an ASCII-compatible charset. This + * includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each + * line ends on a newline character (U+000A LINE FEED). The + * U+000D CARRIAGE RETURN characters are ignored, so the code + * accepts both Windows-style and Unix-style line endings. + * + * - Each object begins with a banner that occurs at the start of + * a line; the first banner characters are "`-----BEGIN `" (five + * dashes, the word "BEGIN", and a space). The banner matching is + * not case-sensitive. + * + * - The _object name_ consists in the characters that follow the + * banner start sequence, up to the end of the line, but without + * trailing dashes (in "normal" PEM, there are five trailing + * dashes, but this implementation is not picky about these dashes). + * The BearSSL decoder normalises the name characters to uppercase + * (for ASCII letters only) and accepts names up to 127 characters. + * + * - The object ends with a banner that again occurs at the start of + * a line, and starts with "`-----END `" (again case-insensitive). + * + * - Between that start and end banner, only Base64 data shall occur. + * Base64 converts each sequence of three bytes into four + * characters; the four characters are ASCII letters, digits, "`+`" + * or "`-`" signs, and one or two "`=`" signs may occur in the last + * quartet. Whitespace is ignored (whitespace is any ASCII character + * of code 32 or less, so control characters are whitespace) and + * lines may have arbitrary length; the only restriction is that the + * four characters of a quartet must appear on the same line (no + * line break inside a quartet). + * + * - A single file may contain more than one PEM object. Bytes that + * occur between objects are ignored. + * + * + * ## PEM Decoder API + * + * The PEM decoder offers a state-machine API. The caller allocates a + * decoder context, then injects source bytes. Source bytes are pushed + * with `br_pem_decoder_push()`. The decoder stops accepting bytes when + * it reaches an "event", which is either the start of an object, the + * end of an object, or a decoding error within an object. + * + * The `br_pem_decoder_event()` function is used to obtain the current + * event; it also clears it, thus allowing the decoder to accept more + * bytes. When a object start event is raised, the decoder context + * offers the found object name (normalised to ASCII uppercase). + * + * When an object is reached, the caller must set an appropriate callback + * function, which will receive (by chunks) the decoded object data. + * + * Since the decoder context makes no dynamic allocation, it requires + * no explicit deallocation. + */ + +/** + * \brief PEM decoder context. + * + * Contents are opaque (they should not be accessed directly). + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + const unsigned char *hbuf; + size_t hlen; + + void (*dest)(void *dest_ctx, const void *src, size_t len); + void *dest_ctx; + + unsigned char event; + char name[128]; + unsigned char buf[255]; + size_t ptr; +#endif +} br_pem_decoder_context; + +/** + * \brief Initialise a PEM decoder structure. + * + * \param ctx decoder context to initialise. + */ +void br_pem_decoder_init(br_pem_decoder_context *ctx); + +/** + * \brief Push some bytes into the decoder. + * + * Returned value is the number of bytes actually consumed; this may be + * less than the number of provided bytes if an event is raised. When an + * event is raised, it must be read (with `br_pem_decoder_event()`); + * until the event is read, this function will return 0. + * + * \param ctx decoder context. + * \param data new data bytes. + * \param len number of new data bytes. + * \return the number of bytes actually received (may be less than `len`). + */ +size_t br_pem_decoder_push(br_pem_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Set the receiver for decoded data. + * + * When an object is entered, the provided function (with opaque context + * pointer) will be called repeatedly with successive chunks of decoded + * data for that object. If `dest` is set to 0, then decoded data is + * simply ignored. The receiver can be set at any time, but, in practice, + * it should be called immediately after receiving a "start of object" + * event. + * + * \param ctx decoder context. + * \param dest callback for receiving decoded data. + * \param dest_ctx opaque context pointer for the `dest` callback. + */ +static __inline void +br_pem_decoder_setdest(br_pem_decoder_context *ctx, + void (*dest)(void *dest_ctx, const void *src, size_t len), + void *dest_ctx) +{ + ctx->dest = dest; + ctx->dest_ctx = dest_ctx; +} + +/** + * \brief Get the last event. + * + * If an event was raised, then this function returns the event value, and + * also clears it, thereby allowing the decoder to proceed. If no event + * was raised since the last call to `br_pem_decoder_event()`, then this + * function returns 0. + * + * \param ctx decoder context. + * \return the raised event, or 0. + */ +int br_pem_decoder_event(br_pem_decoder_context *ctx); + +/** + * \brief Event: start of object. + * + * This event is raised when the start of a new object has been detected. + * The object name (normalised to uppercase) can be accessed with + * `br_pem_decoder_name()`. + */ +#define BR_PEM_BEGIN_OBJ 1 + +/** + * \brief Event: end of object. + * + * This event is raised when the end of the current object is reached + * (normally, i.e. with no decoding error). + */ +#define BR_PEM_END_OBJ 2 + +/** + * \brief Event: decoding error. + * + * This event is raised when decoding fails within an object. + * This formally closes the current object and brings the decoder back + * to the "out of any object" state. The offending line in the source + * is consumed. + */ +#define BR_PEM_ERROR 3 + +/** + * \brief Get the name of the encountered object. + * + * The encountered object name is defined only when the "start of object" + * event is raised. That name is normalised to uppercase (for ASCII letters + * only) and does not include trailing dashes. + * + * \param ctx decoder context. + * \return the current object name. + */ +static __inline const char * +br_pem_decoder_name(br_pem_decoder_context *ctx) +{ + return ctx->name; +} + +/** + * \brief Encode an object in PEM. + * + * This function encodes the provided binary object (`data`, of length `len` + * bytes) into PEM. The `banner` text will be included in the header and + * footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header). + * + * The length (in characters) of the PEM output is returned; that length + * does NOT include the terminating zero, that this function nevertheless + * adds. If using the returned value for allocation purposes, the allocated + * buffer size MUST be at least one byte larger than the returned size. + * + * If `dest` is `NULL`, then the encoding does not happen; however, the + * length of the encoded object is still computed and returned. + * + * The `data` pointer may be `NULL` only if `len` is zero (when encoding + * an object of length zero, which is not very useful), or when `dest` + * is `NULL` (in that case, source data bytes are ignored). + * + * Some `flags` can be specified to alter the encoding behaviour: + * + * - If `BR_PEM_LINE64` is set, then line-breaking will occur after + * every 64 characters of output, instead of the default of 76. + * + * - If `BR_PEM_CRLF` is set, then end-of-line sequence will use + * CR+LF instead of a single LF. + * + * The `data` and `dest` buffers may overlap, in which case the source + * binary data is destroyed in the process. Note that the PEM-encoded output + * is always larger than the source binary. + * + * \param dest the destination buffer (or `NULL`). + * \param data the source buffer (can be `NULL` in some cases). + * \param len the source length (in bytes). + * \param banner the PEM banner expression. + * \param flags the behavioural flags. + * \return the PEM object length (in characters), EXCLUDING the final zero. + */ +size_t br_pem_encode(void *dest, const void *data, size_t len, + const char *banner, unsigned flags); + +/** + * \brief PEM encoding flag: split lines at 64 characters. + */ +#define BR_PEM_LINE64 0x0001 + +/** + * \brief PEM encoding flag: use CR+LF line endings. + */ +#define BR_PEM_CRLF 0x0002 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_prf.h b/BearSSL-OG/libbearssl/inc/bearssl_prf.h new file mode 100644 index 0000000..fdf608c --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_prf.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_PRF_H__ +#define BR_BEARSSL_PRF_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_prf.h + * + * # The TLS PRF + * + * The "PRF" is the pseudorandom function used internally during the + * SSL/TLS handshake, notably to expand negotiated shared secrets into + * the symmetric encryption keys that will be used to process the + * application data. + * + * TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This + * is implemented by the `br_tls10_prf()` function. + * + * TLS 1.2 redefines the PRF, using an explicit hash function. The + * `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that + * PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites + * rely on the SHA-256 based PRF, but some use SHA-384. + * + * The PRF always uses as input three parameters: a "secret" (some + * bytes), a "label" (ASCII string), and a "seed" (again some bytes). An + * arbitrary output length can be produced. The "seed" is provided as an + * arbitrary number of binary chunks, that gets internally concatenated. + */ + +/** + * \brief Type for a seed chunk. + * + * Each chunk may have an arbitrary length, and may be empty (no byte at + * all). If the chunk length is zero, then the pointer to the chunk data + * may be `NULL`. + */ +typedef struct { + /** + * \brief Pointer to the chunk data. + */ + const void *data; + + /** + * \brief Chunk length (in bytes). + */ + size_t len; +} br_tls_prf_seed_chunk; + +/** + * \brief PRF implementation for TLS 1.0 and 1.1. + * + * This PRF is the one specified by TLS 1.0 and 1.1. It internally uses + * MD5 and SHA-1. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls10_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * \brief PRF implementation for TLS 1.2, with SHA-256. + * + * This PRF is the one specified by TLS 1.2, when the underlying hash + * function is SHA-256. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls12_sha256_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * \brief PRF implementation for TLS 1.2, with SHA-384. + * + * This PRF is the one specified by TLS 1.2, when the underlying hash + * function is SHA-384. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls12_sha384_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * brief A convenient type name for a PRF implementation. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +typedef void (*br_tls_prf_impl)(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_rand.h b/BearSSL-OG/libbearssl/inc/bearssl_rand.h new file mode 100644 index 0000000..e338d8f --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_rand.h @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_RAND_H__ +#define BR_BEARSSL_RAND_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_rand.h + * + * # Pseudo-Random Generators + * + * A PRNG is a state-based engine that outputs pseudo-random bytes on + * demand. It is initialized with an initial seed, and additional seed + * bytes can be added afterwards. Bytes produced depend on the seeds and + * also on the exact sequence of calls (including sizes requested for + * each call). + * + * + * ## Procedural and OOP API + * + * For the PRNG of name "`xxx`", two API are provided. The _procedural_ + * API defined a context structure `br_xxx_context` and three functions: + * + * - `br_xxx_init()` + * + * Initialise the context with an initial seed. + * + * - `br_xxx_generate()` + * + * Produce some pseudo-random bytes. + * + * - `br_xxx_update()` + * + * Inject some additional seed. + * + * The initialisation function sets the first context field (`vtable`) + * to a pointer to the vtable that supports the OOP API. The OOP API + * provides access to the same functions through function pointers, + * named `init()`, `generate()` and `update()`. + * + * Note that the context initialisation method may accept additional + * parameters, provided as a 'const void *' pointer at API level. These + * additional parameters depend on the implemented PRNG. + * + * + * ## HMAC_DRBG + * + * HMAC_DRBG is defined in [NIST SP 800-90A Revision + * 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf). + * It uses HMAC repeatedly, over some configurable underlying hash + * function. In BearSSL, it is implemented under the "`hmac_drbg`" name. + * The "extra parameters" pointer for context initialisation should be + * set to a pointer to the vtable for the underlying hash function (e.g. + * pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256). + * + * According to the NIST standard, each request shall produce up to + * 219 bits (i.e. 64 kB of data); moreover, the context shall + * be reseeded at least once every 248 requests. This + * implementation does not maintain the reseed counter (the threshold is + * too high to be reached in practice) and does not object to producing + * more than 64 kB in a single request; thus, the code cannot fail, + * which corresponds to the fact that the API has no room for error + * codes. However, this implies that requesting more than 64 kB in one + * `generate()` request, or making more than 248 requests + * without reseeding, is formally out of NIST specification. There is + * no currently known security penalty for exceeding the NIST limits, + * and, in any case, HMAC_DRBG usage in implementing SSL/TLS always + * stays much below these thresholds. + * + * + * ## AESCTR_DRBG + * + * AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is + * meant to be used only in situations where you are desperate for + * speed, and have an hardware-optimized AES/CTR implementation. Whether + * this will yield perceptible improvements depends on what you use the + * pseudorandom bytes for, and how many you want; for instance, RSA key + * pair generation uses a substantial amount of randomness, and using + * AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key + * generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz). + * + * Internally, it uses CTR mode with successive counter values, starting + * at zero (counter value expressed over 128 bits, big-endian convention). + * The counter is not allowed to reach 32768; thus, every 32768*16 bytes + * at most, the `update()` function is run (on an empty seed, if none is + * provided). The `update()` function computes the new AES-128 key by + * applying a custom hash function to the concatenation of a state-dependent + * word (encryption of an all-one block with the current key) and the new + * seed. The custom hash function uses Hirose's construction over AES-256; + * see the comments in `aesctr_drbg.c` for details. + * + * This DRBG does not follow an existing standard, and thus should be + * considered as inadequate for production use until it has been properly + * analysed. + */ + +/** + * \brief Class type for PRNG implementations. + * + * A `br_prng_class` instance references the methods implementing a PRNG. + * Constant instances of this structure are defined for each implemented + * PRNG. Such instances are also called "vtables". + */ +typedef struct br_prng_class_ br_prng_class; +struct br_prng_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate for + * running this PRNG. + */ + size_t context_size; + + /** + * \brief Initialisation method. + * + * The context to initialise is provided as a pointer to its + * first field (the vtable pointer); this function sets that + * first field to a pointer to the vtable. + * + * The extra parameters depend on the implementation; each + * implementation defines what kind of extra parameters it + * expects (if any). + * + * Requirements on the initial seed depend on the implemented + * PRNG. + * + * \param ctx PRNG context to initialise. + * \param params extra parameters for the PRNG. + * \param seed initial seed. + * \param seed_len initial seed length (in bytes). + */ + void (*init)(const br_prng_class **ctx, const void *params, + const void *seed, size_t seed_len); + + /** + * \brief Random bytes generation. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. + * + * \param ctx PRNG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ + void (*generate)(const br_prng_class **ctx, void *out, size_t len); + + /** + * \brief Inject additional seed bytes. + * + * The provided seed bytes are added into the PRNG internal + * entropy pool. + * + * \param ctx PRNG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ + void (*update)(const br_prng_class **ctx, + const void *seed, size_t seed_len); +}; + +/** + * \brief Context for HMAC_DRBG. + * + * The context contents are opaque, except the first field, which + * supports OOP. + */ +typedef struct { + /** + * \brief Pointer to the vtable. + * + * This field is set with the initialisation method/function. + */ + const br_prng_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char K[64]; + unsigned char V[64]; + const br_hash_class *digest_class; +#endif +} br_hmac_drbg_context; + +/** + * \brief Statically allocated, constant vtable for HMAC_DRBG. + */ +extern const br_prng_class br_hmac_drbg_vtable; + +/** + * \brief HMAC_DRBG initialisation. + * + * The context to initialise is provided as a pointer to its first field + * (the vtable pointer); this function sets that first field to a + * pointer to the vtable. + * + * The `seed` value is what is called, in NIST terminology, the + * concatenation of the "seed", "nonce" and "personalization string", in + * that order. + * + * The `digest_class` parameter defines the underlying hash function. + * Formally, the NIST standard specifies that the hash function shall + * be only SHA-1 or one of the SHA-2 functions. This implementation also + * works with any other implemented hash function (such as MD5), but + * this is non-standard and therefore not recommended. + * + * \param ctx HMAC_DRBG context to initialise. + * \param digest_class vtable for the underlying hash function. + * \param seed initial seed. + * \param seed_len initial seed length (in bytes). + */ +void br_hmac_drbg_init(br_hmac_drbg_context *ctx, + const br_hash_class *digest_class, const void *seed, size_t seed_len); + +/** + * \brief Random bytes generation with HMAC_DRBG. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. Formally, requesting + * more than 65536 bytes in one request falls out of specification + * limits (but it won't fail). + * + * \param ctx HMAC_DRBG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ +void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len); + +/** + * \brief Inject additional seed bytes in HMAC_DRBG. + * + * The provided seed bytes are added into the HMAC_DRBG internal + * entropy pool. The process does not _replace_ existing entropy, + * thus pushing non-random bytes (i.e. bytes which are known to the + * attackers) does not degrade the overall quality of generated bytes. + * + * \param ctx HMAC_DRBG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ +void br_hmac_drbg_update(br_hmac_drbg_context *ctx, + const void *seed, size_t seed_len); + +/** + * \brief Get the hash function implementation used by a given instance of + * HMAC_DRBG. + * + * This calls MUST NOT be performed on a context which was not + * previously initialised. + * + * \param ctx HMAC_DRBG context. + * \return the hash function vtable. + */ +static __inline const br_hash_class * +br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx) +{ + return ctx->digest_class; +} + +/** + * \brief Type for a provider of entropy seeds. + * + * A "seeder" is a function that is able to obtain random values from + * some source and inject them as entropy seed in a PRNG. A seeder + * shall guarantee that the total entropy of the injected seed is large + * enough to seed a PRNG for purposes of cryptographic key generation + * (i.e. at least 128 bits). + * + * A seeder may report a failure to obtain adequate entropy. Seeders + * shall endeavour to fix themselves transient errors by trying again; + * thus, callers may consider reported errors as permanent. + * + * \param ctx PRNG context to seed. + * \return 1 on success, 0 on error. + */ +typedef int (*br_prng_seeder)(const br_prng_class **ctx); + +/** + * \brief Get a seeder backed by the operating system or hardware. + * + * Get a seeder that feeds on RNG facilities provided by the current + * operating system or hardware. If no such facility is known, then 0 + * is returned. + * + * If `name` is not `NULL`, then `*name` is set to a symbolic string + * that identifies the seeder implementation. If no seeder is returned + * and `name` is not `NULL`, then `*name` is set to a pointer to the + * constant string `"none"`. + * + * \param name receiver for seeder name, or `NULL`. + * \return the system seeder, if available, or 0. + */ +br_prng_seeder br_prng_seeder_system(const char **name); + +/** + * \brief Context for AESCTR_DRBG. + * + * The context contents are opaque, except the first field, which + * supports OOP. + */ +typedef struct { + /** + * \brief Pointer to the vtable. + * + * This field is set with the initialisation method/function. + */ + const br_prng_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + br_aes_gen_ctr_keys sk; + uint32_t cc; +#endif +} br_aesctr_drbg_context; + +/** + * \brief Statically allocated, constant vtable for AESCTR_DRBG. + */ +extern const br_prng_class br_aesctr_drbg_vtable; + +/** + * \brief AESCTR_DRBG initialisation. + * + * The context to initialise is provided as a pointer to its first field + * (the vtable pointer); this function sets that first field to a + * pointer to the vtable. + * + * The internal AES key is first set to the all-zero key; then, the + * `br_aesctr_drbg_update()` function is called with the provided `seed`. + * The call is performed even if the seed length (`seed_len`) is zero. + * + * The `aesctr` parameter defines the underlying AES/CTR implementation. + * + * \param ctx AESCTR_DRBG context to initialise. + * \param aesctr vtable for the AES/CTR implementation. + * \param seed initial seed (can be `NULL` if `seed_len` is zero). + * \param seed_len initial seed length (in bytes). + */ +void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, + const br_block_ctr_class *aesctr, const void *seed, size_t seed_len); + +/** + * \brief Random bytes generation with AESCTR_DRBG. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. + * + * \param ctx AESCTR_DRBG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ +void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, + void *out, size_t len); + +/** + * \brief Inject additional seed bytes in AESCTR_DRBG. + * + * The provided seed bytes are added into the AESCTR_DRBG internal + * entropy pool. The process does not _replace_ existing entropy, + * thus pushing non-random bytes (i.e. bytes which are known to the + * attackers) does not degrade the overall quality of generated bytes. + * + * \param ctx AESCTR_DRBG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ +void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, + const void *seed, size_t seed_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_rsa.h b/BearSSL-OG/libbearssl/inc/bearssl_rsa.h new file mode 100644 index 0000000..0a069fd --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_rsa.h @@ -0,0 +1,1655 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_RSA_H__ +#define BR_BEARSSL_RSA_H__ + +#include +#include + +#include "bearssl_hash.h" +#include "bearssl_rand.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_rsa.h + * + * # RSA + * + * This file documents the RSA implementations provided with BearSSL. + * Note that the SSL engine accesses these implementations through a + * configurable API, so it is possible to, for instance, run a SSL + * server which uses a RSA engine which is not based on this code. + * + * ## Key Elements + * + * RSA public and private keys consist in lists of big integers. All + * such integers are represented with big-endian unsigned notation: + * first byte is the most significant, and the value is positive (so + * there is no dedicated "sign bit"). Public and private key structures + * thus contain, for each such integer, a pointer to the first value byte + * (`unsigned char *`), and a length (`size_t`) which is the number of + * relevant bytes. As a general rule, minimal-length encoding is not + * enforced: values may have extra leading bytes of value 0. + * + * RSA public keys consist in two integers: + * + * - the modulus (`n`); + * - the public exponent (`e`). + * + * RSA private keys, as defined in + * [PKCS#1](https://tools.ietf.org/html/rfc3447), contain eight integers: + * + * - the modulus (`n`); + * - the public exponent (`e`); + * - the private exponent (`d`); + * - the first prime factor (`p`); + * - the second prime factor (`q`); + * - the first reduced exponent (`dp`, which is `d` modulo `p-1`); + * - the second reduced exponent (`dq`, which is `d` modulo `q-1`); + * - the CRT coefficient (`iq`, the inverse of `q` modulo `p`). + * + * However, the implementations defined in BearSSL use only five of + * these integers: `p`, `q`, `dp`, `dq` and `iq`. + * + * ## Security Features and Limitations + * + * The implementations contained in BearSSL have the following limitations + * and features: + * + * - They are constant-time. This means that the execution time and + * memory access pattern may depend on the _lengths_ of the private + * key components, but not on their value, nor on the value of + * the operand. Note that this property is not achieved through + * random masking, but "true" constant-time code. + * + * - They support only private keys with two prime factors. RSA private + * keys with three or more prime factors are nominally supported, but + * rarely used; they may offer faster operations, at the expense of + * more code and potentially a reduction in security if there are + * "too many" prime factors. + * + * - The public exponent may have arbitrary length. Of course, it is + * a good idea to keep public exponents small, so that public key + * operations are fast; but, contrary to some widely deployed + * implementations, BearSSL has no problem with public exponents + * longer than 32 bits. + * + * - The two prime factors of the modulus need not have the same length + * (but severely imbalanced factor lengths might reduce security). + * Similarly, there is no requirement that the first factor (`p`) + * be greater than the second factor (`q`). + * + * - Prime factors and modulus must be smaller than a compile-time limit. + * This is made necessary by the use of fixed-size stack buffers, and + * the limit has been adjusted to keep stack usage under 2 kB for the + * RSA operations. Currently, the maximum modulus size is 4096 bits, + * and the maximum prime factor size is 2080 bits. + * + * - The RSA functions themselves do not enforce lower size limits, + * except that which is absolutely necessary for the operation to + * mathematically make sense (e.g. a PKCS#1 v1.5 signature with + * SHA-1 requires a modulus of at least 361 bits). It is up to users + * of this code to enforce size limitations when appropriate (e.g. + * the X.509 validation engine, by default, rejects RSA keys of + * less than 1017 bits). + * + * - Within the size constraints expressed above, arbitrary bit lengths + * are supported. There is no requirement that prime factors or + * modulus have a size multiple of 8 or 16. + * + * - When verifying PKCS#1 v1.5 signatures, both variants of the hash + * function identifying header (with and without the ASN.1 NULL) are + * supported. When producing such signatures, the variant with the + * ASN.1 NULL is used. + * + * ## Implementations + * + * Three RSA implementations are included: + * + * - The **i32** implementation internally represents big integers + * as arrays of 32-bit integers. It is perfunctory and portable, + * but not very efficient. + * + * - The **i31** implementation uses 32-bit integers, each containing + * 31 bits worth of integer data. The i31 implementation is somewhat + * faster than the i32 implementation (the reduced integer size makes + * carry propagation easier) for a similar code footprint, but uses + * very slightly larger stack buffers (about 4% bigger). + * + * - The **i62** implementation is similar to the i31 implementation, + * except that it internally leverages the 64x64->128 multiplication + * opcode. This implementation is available only on architectures + * where such an opcode exists. It is much faster than i31. + * + * - The **i15** implementation uses 16-bit integers, each containing + * 15 bits worth of integer data. Multiplication results fit on + * 32 bits, so this won't use the "widening" multiplication routine + * on ARM Cortex M0/M0+, for much better performance and constant-time + * execution. + */ + +/** + * \brief RSA public key. + * + * The structure references the modulus and the public exponent. Both + * integers use unsigned big-endian representation; extra leading bytes + * of value 0 are allowed. + */ +typedef struct { + /** \brief Modulus. */ + unsigned char *n; + /** \brief Modulus length (in bytes). */ + size_t nlen; + /** \brief Public exponent. */ + unsigned char *e; + /** \brief Public exponent length (in bytes). */ + size_t elen; +} br_rsa_public_key; + +/** + * \brief RSA private key. + * + * The structure references the private factors, reduced private + * exponents, and CRT coefficient. It also contains the bit length of + * the modulus. The big integers use unsigned big-endian representation; + * extra leading bytes of value 0 are allowed. However, the modulus bit + * length (`n_bitlen`) MUST be exact. + */ +typedef struct { + /** \brief Modulus bit length (in bits, exact value). */ + uint32_t n_bitlen; + /** \brief First prime factor. */ + unsigned char *p; + /** \brief First prime factor length (in bytes). */ + size_t plen; + /** \brief Second prime factor. */ + unsigned char *q; + /** \brief Second prime factor length (in bytes). */ + size_t qlen; + /** \brief First reduced private exponent. */ + unsigned char *dp; + /** \brief First reduced private exponent length (in bytes). */ + size_t dplen; + /** \brief Second reduced private exponent. */ + unsigned char *dq; + /** \brief Second reduced private exponent length (in bytes). */ + size_t dqlen; + /** \brief CRT coefficient. */ + unsigned char *iq; + /** \brief CRT coefficient length (in bytes). */ + size_t iqlen; +} br_rsa_private_key; + +/** + * \brief Type for a RSA public key engine. + * + * The public key engine performs the modular exponentiation of the + * provided value with the public exponent. The value is modified in + * place. + * + * The value length (`xlen`) is verified to have _exactly_ the same + * length as the modulus (actual modulus length, without extra leading + * zeros in the modulus representation in memory). If the length does + * not match, then this function returns 0 and `x[]` is unmodified. + * + * It `xlen` is correct, then `x[]` is modified. Returned value is 1 + * on success, 0 on error. Error conditions include an oversized `x[]` + * (the array has the same length as the modulus, but the numerical value + * is not lower than the modulus) and an invalid modulus (e.g. an even + * integer). If an error is reported, then the new contents of `x[]` are + * unspecified. + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief Type for a RSA signature verification engine (PKCS#1 v1.5). + * + * Parameters are: + * + * - The signature itself. The provided array is NOT modified. + * + * - The encoded OID for the hash function. The provided array must begin + * with a single byte that contains the length of the OID value (in + * bytes), followed by exactly that many bytes. This parameter may + * also be `NULL`, in which case the raw hash value should be used + * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up + * to TLS-1.1, with a 36-byte hash value). + * + * - The hash output length, in bytes. + * + * - The public key. + * + * - An output buffer for the hash value. The caller must still compare + * it with the hash of the data over which the signature is computed. + * + * **Constraints:** + * + * - Hash length MUST be no more than 64 bytes. + * + * - OID value length MUST be no more than 32 bytes (i.e. `hash_oid[0]` + * must have a value in the 0..32 range, inclusive). + * + * This function verifies that the signature length (`xlen`) matches the + * modulus length (this function returns 0 on mismatch). If the modulus + * size exceeds the maximum supported RSA size, then the function also + * returns 0. + * + * Returned value is 1 on success, 0 on error. + * + * Implementations of this type need not be constant-time. + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pkcs1_vrfy)(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief Type for a RSA signature verification engine (PSS). + * + * Parameters are: + * + * - The signature itself. The provided array is NOT modified. + * + * - The hash function which was used to hash the message. + * + * - The hash function to use with MGF1 within the PSS padding. This + * is not necessarily the same hash function as the one which was + * used to hash the signed message. + * + * - The hashed message (as an array of bytes). + * + * - The PSS salt length (in bytes). + * + * - The public key. + * + * **Constraints:** + * + * - Hash message length MUST be no more than 64 bytes. + * + * Note that, contrary to PKCS#1 v1.5 signature, the hash value of the + * signed data cannot be extracted from the signature; it must be + * provided to the verification function. + * + * This function verifies that the signature length (`xlen`) matches the + * modulus length (this function returns 0 on mismatch). If the modulus + * size exceeds the maximum supported RSA size, then the function also + * returns 0. + * + * Returned value is 1 on success, 0 on error. + * + * Implementations of this type need not be constant-time. + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pss_vrfy)(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief Type for a RSA encryption engine (OAEP). + * + * Parameters are: + * + * - A source of random bytes. The source must be already initialized. + * + * - A hash function, used internally with the mask generation function + * (MGF1). + * + * - A label. The `label` pointer may be `NULL` if `label_len` is zero + * (an empty label, which is the default in PKCS#1 v2.2). + * + * - The public key. + * + * - The destination buffer. Its maximum length (in bytes) is provided; + * if that length is lower than the public key length, then an error + * is reported. + * + * - The source message. + * + * The encrypted message output has exactly the same length as the modulus + * (mathematical length, in bytes, not counting extra leading zeros in the + * modulus representation in the public key). + * + * The source message (`src`, length `src_len`) may overlap with the + * destination buffer (`dst`, length `dst_max_len`). + * + * This function returns the actual encrypted message length, in bytes; + * on error, zero is returned. An error is reported if the output buffer + * is not large enough, or the public is invalid, or the public key + * modulus exceeds the maximum supported RSA size. + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +typedef size_t (*br_rsa_oaep_encrypt)( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief Type for a RSA private key engine. + * + * The `x[]` buffer is modified in place, and its length is inferred from + * the modulus length (`x[]` is assumed to have a length of + * `(sk->n_bitlen+7)/8` bytes). + * + * Returned value is 1 on success, 0 on error. + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_private)(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief Type for a RSA signature generation engine (PKCS#1 v1.5). + * + * Parameters are: + * + * - The encoded OID for the hash function. The provided array must begin + * with a single byte that contains the length of the OID value (in + * bytes), followed by exactly that many bytes. This parameter may + * also be `NULL`, in which case the raw hash value should be used + * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up + * to TLS-1.1, with a 36-byte hash value). + * + * - The hash value computes over the data to sign (its length is + * expressed in bytes). + * + * - The RSA private key. + * + * - The output buffer, that receives the signature. + * + * Returned value is 1 on success, 0 on error. Error conditions include + * a too small modulus for the provided hash OID and value, or some + * invalid key parameters. The signature length is exactly + * `(sk->n_bitlen+7)/8` bytes. + * + * This function is expected to be constant-time with regards to the + * private key bytes (lengths of the modulus and the individual factors + * may leak, though) and to the hashed data. + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pkcs1_sign)(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Type for a RSA signature generation engine (PSS). + * + * Parameters are: + * + * - An initialized PRNG for salt generation. If the salt length is + * zero (`salt_len` parameter), then the PRNG is optional (this is + * not the typical case, as the security proof of RSA/PSS is + * tighter when a non-empty salt is used). + * + * - The hash function which was used to hash the message. + * + * - The hash function to use with MGF1 within the PSS padding. This + * is not necessarily the same function as the one used to hash the + * message. + * + * - The hashed message. + * + * - The salt length, in bytes. + * + * - The RSA private key. + * + * - The output buffer, that receives the signature. + * + * Returned value is 1 on success, 0 on error. Error conditions include + * a too small modulus for the provided hash and salt lengths, or some + * invalid key parameters. The signature length is exactly + * `(sk->n_bitlen+7)/8` bytes. + * + * This function is expected to be constant-time with regards to the + * private key bytes (lengths of the modulus and the individual factors + * may leak, though) and to the hashed data. + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pss_sign)(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Encoded OID for SHA-1 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA1 \ + ((const unsigned char *)"\x05\x2B\x0E\x03\x02\x1A") + +/** + * \brief Encoded OID for SHA-224 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA224 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04") + +/** + * \brief Encoded OID for SHA-256 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA256 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01") + +/** + * \brief Encoded OID for SHA-384 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA384 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02") + +/** + * \brief Encoded OID for SHA-512 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA512 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03") + +/** + * \brief Type for a RSA decryption engine (OAEP). + * + * Parameters are: + * + * - A hash function, used internally with the mask generation function + * (MGF1). + * + * - A label. The `label` pointer may be `NULL` if `label_len` is zero + * (an empty label, which is the default in PKCS#1 v2.2). + * + * - The private key. + * + * - The source and destination buffer. The buffer initially contains + * the encrypted message; the buffer contents are altered, and the + * decrypted message is written at the start of that buffer + * (decrypted message is always shorter than the encrypted message). + * + * If decryption fails in any way, then `*len` is unmodified, and the + * function returns 0. Otherwise, `*len` is set to the decrypted message + * length, and 1 is returned. The implementation is responsible for + * checking that the input message length matches the key modulus length, + * and that the padding is correct. + * + * Implementations MUST use constant-time check of the validity of the + * OAEP padding, at least until the leading byte and hash value have + * been checked. Whether overall decryption worked, and the length of + * the decrypted message, may leak. + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_oaep_decrypt)( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/* + * RSA "i32" engine. Integers are internally represented as arrays of + * 32-bit integers, and the core multiplication primitive is the + * 32x32->64 multiplication. + */ + +/** + * \brief RSA public key engine "i32". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i32" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i32" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i32". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i32" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i32" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/* + * RSA "i31" engine. Similar to i32, but only 31 bits are used per 32-bit + * word. This uses slightly more stack space (about 4% more) and code + * space, but it quite faster. + */ + +/** + * \brief RSA public key engine "i31". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i31" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i31" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i31". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i31" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i31" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/* + * RSA "i62" engine. Similar to i31, but internal multiplication use + * 64x64->128 multiplications. This is available only on architecture + * that offer such an opcode. + */ + +/** + * \brief RSA public key engine "i62". + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_public_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i62" (PKCS#1 v1.5 signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pkcs1_vrfy_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i62" (PSS signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pss_vrfy_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i62". + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_private_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i62" (PKCS#1 v1.5 signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pkcs1_sign_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i62" (PSS signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pss_sign_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Get the RSA "i62" implementation (public key operations), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_public br_rsa_i62_public_get(void); + +/** + * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature verification), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pkcs1_vrfy br_rsa_i62_pkcs1_vrfy_get(void); + +/** + * \brief Get the RSA "i62" implementation (PSS signature verification), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pss_vrfy br_rsa_i62_pss_vrfy_get(void); + +/** + * \brief Get the RSA "i62" implementation (private key operations), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_private br_rsa_i62_private_get(void); + +/** + * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pkcs1_sign br_rsa_i62_pkcs1_sign_get(void); + +/** + * \brief Get the RSA "i62" implementation (PSS signature generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pss_sign br_rsa_i62_pss_sign_get(void); + +/** + * \brief Get the RSA "i62" implementation (OAEP encryption), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_oaep_encrypt br_rsa_i62_oaep_encrypt_get(void); + +/** + * \brief Get the RSA "i62" implementation (OAEP decryption), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_oaep_decrypt br_rsa_i62_oaep_decrypt_get(void); + +/* + * RSA "i15" engine. Integers are represented as 15-bit integers, so + * the code uses only 32-bit multiplication (no 64-bit result), which + * is vastly faster (and constant-time) on the ARM Cortex M0/M0+. + */ + +/** + * \brief RSA public key engine "i15". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i15" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i15" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i15". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i15" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i15" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Get "default" RSA implementation (public-key operations). + * + * This returns the preferred implementation of RSA (public-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_public br_rsa_public_get_default(void); + +/** + * \brief Get "default" RSA implementation (private-key operations). + * + * This returns the preferred implementation of RSA (private-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_private br_rsa_private_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PSS signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pss_vrfy br_rsa_pss_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void); + +/** + * \brief Get "default" RSA implementation (PSS signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pss_sign br_rsa_pss_sign_get_default(void); + +/** + * \brief Get "default" RSA implementation (OAEP encryption). + * + * This returns the preferred implementation of RSA (OAEP encryption) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_oaep_encrypt br_rsa_oaep_encrypt_get_default(void); + +/** + * \brief Get "default" RSA implementation (OAEP decryption). + * + * This returns the preferred implementation of RSA (OAEP decryption) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_oaep_decrypt br_rsa_oaep_decrypt_get_default(void); + +/** + * \brief RSA decryption helper, for SSL/TLS. + * + * This function performs the RSA decryption for a RSA-based key exchange + * in a SSL/TLS server. The provided RSA engine is used. The `data` + * parameter points to the value to decrypt, of length `len` bytes. On + * success, the 48-byte pre-master secret is copied into `data`, starting + * at the first byte of that buffer; on error, the contents of `data` + * become indeterminate. + * + * This function first checks that the provided value length (`len`) is + * not lower than 59 bytes, and matches the RSA modulus length; if neither + * of this property is met, then this function returns 0 and the buffer + * is unmodified. + * + * Otherwise, decryption and then padding verification are performed, both + * in constant-time. A decryption error, or a bad padding, or an + * incorrect decrypted value length are reported with a returned value of + * 0; on success, 1 is returned. The caller (SSL server engine) is supposed + * to proceed with a random pre-master secret in case of error. + * + * \param core RSA private key engine. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len length (in bytes) of the data to decrypt. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk, + unsigned char *data, size_t len); + +/** + * \brief RSA encryption (OAEP) with the "i15" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i15_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i15" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i31" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i31_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i31" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i32" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i32_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i32" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_oaep_encrypt_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i62_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_oaep_decrypt_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief Get buffer size to hold RSA private key elements. + * + * This macro returns the length (in bytes) of the buffer needed to + * receive the elements of a RSA private key, as generated by one of + * the `br_rsa_*_keygen()` functions. If the provided size is a constant + * expression, then the whole macro evaluates to a constant expression. + * + * \param size target key size (modulus size, in bits) + * \return the length of the private key buffer, in bytes. + */ +#define BR_RSA_KBUF_PRIV_SIZE(size) (5 * (((size) + 15) >> 4)) + +/** + * \brief Get buffer size to hold RSA public key elements. + * + * This macro returns the length (in bytes) of the buffer needed to + * receive the elements of a RSA public key, as generated by one of + * the `br_rsa_*_keygen()` functions. If the provided size is a constant + * expression, then the whole macro evaluates to a constant expression. + * + * \param size target key size (modulus size, in bits) + * \return the length of the public key buffer, in bytes. + */ +#define BR_RSA_KBUF_PUB_SIZE(size) (4 + (((size) + 7) >> 3)) + +/** + * \brief Type for RSA key pair generator implementation. + * + * This function generates a new RSA key pair whose modulus has bit + * length `size` bits. The private key elements are written in the + * `kbuf_priv` buffer, and pointer values and length fields to these + * elements are populated in the provided private key structure `sk`. + * Similarly, the public key elements are written in `kbuf_pub`, with + * pointers and lengths set in `pk`. + * + * If `pk` is `NULL`, then `kbuf_pub` may be `NULL`, and only the + * private key is set. + * + * If `pubexp` is not zero, then its value will be used as public + * exponent. Valid RSA public exponent values are odd integers + * greater than 1. If `pubexp` is zero, then the public exponent will + * have value 3. + * + * The provided PRNG (`rng_ctx`) must have already been initialized + * and seeded. + * + * Returned value is 1 on success, 0 on error. An error is reported + * if the requested range is outside of the supported key sizes, or + * if an invalid non-zero public exponent value is provided. Supported + * range starts at 512 bits, and up to an implementation-defined + * maximum (by default 4096 bits). Note that key sizes up to 768 bits + * have been broken in practice, and sizes lower than 2048 bits are + * usually considered to be weak and should not be used. + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +typedef uint32_t (*br_rsa_keygen)( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i15" engine. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i15_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i31" engine. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i31_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_keygen_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i62_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief Get the RSA "i62" implementation (key pair generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_keygen br_rsa_i62_keygen_get(void); + +/** + * \brief Get "default" RSA implementation (key pair generation). + * + * This returns the preferred implementation of RSA (key pair generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_keygen br_rsa_keygen_get_default(void); + +/** + * \brief Type for a modulus computing function. + * + * Such a function computes the public modulus from the private key. The + * encoded modulus (unsigned big-endian) is written on `n`, and the size + * (in bytes) is returned. If `n` is `NULL`, then the size is returned but + * the modulus itself is not computed. + * + * If the key size exceeds an internal limit, 0 is returned. + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +typedef size_t (*br_rsa_compute_modulus)(void *n, const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA modulus ("i15" engine). + * + * \see br_rsa_compute_modulus + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +size_t br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA modulus ("i31" engine). + * + * \see br_rsa_compute_modulus + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +size_t br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk); + +/** + * \brief Get "default" RSA implementation (recompute modulus). + * + * This returns the preferred implementation of RSA (recompute modulus) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_modulus br_rsa_compute_modulus_get_default(void); + +/** + * \brief Type for a public exponent computing function. + * + * Such a function recomputes the public exponent from the private key. + * 0 is returned if any of the following occurs: + * + * - Either `p` or `q` is not equal to 3 modulo 4. + * + * - The public exponent does not fit on 32 bits. + * + * - An internal limit is exceeded. + * + * - The private key is invalid in some way. + * + * For all private keys produced by the key generator functions + * (`br_rsa_keygen` type), this function succeeds and returns the true + * public exponent. The public exponent is always an odd integer greater + * than 1. + * + * \return the public exponent, or 0. + */ +typedef uint32_t (*br_rsa_compute_pubexp)(const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA public exponent ("i15" engine). + * + * \see br_rsa_compute_pubexp + * + * \return the public exponent, or 0. + */ +uint32_t br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA public exponent ("i31" engine). + * + * \see br_rsa_compute_pubexp + * + * \return the public exponent, or 0. + */ +uint32_t br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk); + +/** + * \brief Get "default" RSA implementation (recompute public exponent). + * + * This returns the preferred implementation of RSA (recompute public + * exponent) on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_pubexp br_rsa_compute_pubexp_get_default(void); + +/** + * \brief Type for a private exponent computing function. + * + * An RSA private key (`br_rsa_private_key`) contains two reduced + * private exponents, which are sufficient to perform private key + * operations. However, standard encoding formats for RSA private keys + * require also a copy of the complete private exponent (non-reduced), + * which this function recomputes. + * + * This function suceeds if all the following conditions hold: + * + * - Both private factors `p` and `q` are equal to 3 modulo 4. + * + * - The provided public exponent `pubexp` is correct, and, in particular, + * is odd, relatively prime to `p-1` and `q-1`, and greater than 1. + * + * - No internal storage limit is exceeded. + * + * For all private keys produced by the key generator functions + * (`br_rsa_keygen` type), this function succeeds. Note that the API + * restricts the public exponent to a maximum size of 32 bits. + * + * The encoded private exponent is written in `d` (unsigned big-endian + * convention), and the length (in bytes) is returned. If `d` is `NULL`, + * then the exponent is not written anywhere, but the length is still + * returned. On error, 0 is returned. + * + * Not all error conditions are detected when `d` is `NULL`; therefore, the + * returned value shall be checked also when actually producing the value. + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +typedef size_t (*br_rsa_compute_privexp)(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Recompute RSA private exponent ("i15" engine). + * + * \see br_rsa_compute_privexp + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +size_t br_rsa_i15_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Recompute RSA private exponent ("i31" engine). + * + * \see br_rsa_compute_privexp + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +size_t br_rsa_i31_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Get "default" RSA implementation (recompute private exponent). + * + * This returns the preferred implementation of RSA (recompute private + * exponent) on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_privexp br_rsa_compute_privexp_get_default(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_ssl.h b/BearSSL-OG/libbearssl/inc/bearssl_ssl.h new file mode 100644 index 0000000..3f84e6b --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_ssl.h @@ -0,0 +1,4307 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_SSL_H__ +#define BR_BEARSSL_SSL_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" +#include "bearssl_hmac.h" +#include "bearssl_prf.h" +#include "bearssl_rand.h" +#include "bearssl_x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ssl.h + * + * # SSL + * + * For an overview of the SSL/TLS API, see [the BearSSL Web + * site](https://www.bearssl.org/api1.html). + * + * The `BR_TLS_*` constants correspond to the standard cipher suites and + * their values in the [IANA + * registry](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4). + * + * The `BR_ALERT_*` constants are for standard TLS alert messages. When + * a fatal alert message is sent of received, then the SSL engine context + * status is set to the sum of that alert value (an integer in the 0..255 + * range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert, + * `BR_ERR_RECV_FATAL_ALERT` for a received alert). + */ + +/** \brief Optimal input buffer size. */ +#define BR_SSL_BUFSIZE_INPUT (16384 + 325) + +/** \brief Optimal output buffer size. */ +#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85) + +/** \brief Optimal buffer size for monodirectional engine + (shared input/output buffer). */ +#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT + +/** \brief Optimal buffer size for bidirectional engine + (single buffer split into two separate input/output buffers). */ +#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT) + +/* + * Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1 + * and TLS 1.2). Note that though there is a constant for SSL 3.0, that + * protocol version is not actually supported. + */ + +/** \brief Protocol version: SSL 3.0 (unsupported). */ +#define BR_SSL30 0x0300 +/** \brief Protocol version: TLS 1.0. */ +#define BR_TLS10 0x0301 +/** \brief Protocol version: TLS 1.1. */ +#define BR_TLS11 0x0302 +/** \brief Protocol version: TLS 1.2. */ +#define BR_TLS12 0x0303 + +/* + * Error constants. They are used to report the reason why a context has + * been marked as failed. + * + * Implementation note: SSL-level error codes should be in the 1..31 + * range. The 32..63 range is for certificate decoding and validation + * errors. Received fatal alerts imply an error code in the 256..511 range. + */ + +/** \brief SSL status: no error so far (0). */ +#define BR_ERR_OK 0 + +/** \brief SSL status: caller-provided parameter is incorrect. */ +#define BR_ERR_BAD_PARAM 1 + +/** \brief SSL status: operation requested by the caller cannot be applied + with the current context state (e.g. reading data while outgoing data + is waiting to be sent). */ +#define BR_ERR_BAD_STATE 2 + +/** \brief SSL status: incoming protocol or record version is unsupported. */ +#define BR_ERR_UNSUPPORTED_VERSION 3 + +/** \brief SSL status: incoming record version does not match the expected + version. */ +#define BR_ERR_BAD_VERSION 4 + +/** \brief SSL status: incoming record length is invalid. */ +#define BR_ERR_BAD_LENGTH 5 + +/** \brief SSL status: incoming record is too large to be processed, or + buffer is too small for the handshake message to send. */ +#define BR_ERR_TOO_LARGE 6 + +/** \brief SSL status: decryption found an invalid padding, or the record + MAC is not correct. */ +#define BR_ERR_BAD_MAC 7 + +/** \brief SSL status: no initial entropy was provided, and none can be + obtained from the OS. */ +#define BR_ERR_NO_RANDOM 8 + +/** \brief SSL status: incoming record type is unknown. */ +#define BR_ERR_UNKNOWN_TYPE 9 + +/** \brief SSL status: incoming record or message has wrong type with + regards to the current engine state. */ +#define BR_ERR_UNEXPECTED 10 + +/** \brief SSL status: ChangeCipherSpec message from the peer has invalid + contents. */ +#define BR_ERR_BAD_CCS 12 + +/** \brief SSL status: alert message from the peer has invalid contents + (odd length). */ +#define BR_ERR_BAD_ALERT 13 + +/** \brief SSL status: incoming handshake message decoding failed. */ +#define BR_ERR_BAD_HANDSHAKE 14 + +/** \brief SSL status: ServerHello contains a session ID which is larger + than 32 bytes. */ +#define BR_ERR_OVERSIZED_ID 15 + +/** \brief SSL status: server wants to use a cipher suite that we did + not claim to support. This is also reported if we tried to advertise + a cipher suite that we do not support. */ +#define BR_ERR_BAD_CIPHER_SUITE 16 + +/** \brief SSL status: server wants to use a compression that we did not + claim to support. */ +#define BR_ERR_BAD_COMPRESSION 17 + +/** \brief SSL status: server's max fragment length does not match + client's. */ +#define BR_ERR_BAD_FRAGLEN 18 + +/** \brief SSL status: secure renegotiation failed. */ +#define BR_ERR_BAD_SECRENEG 19 + +/** \brief SSL status: server sent an extension type that we did not + announce, or used the same extension type several times in a single + ServerHello. */ +#define BR_ERR_EXTRA_EXTENSION 20 + +/** \brief SSL status: invalid Server Name Indication contents (when + used by the server, this extension shall be empty). */ +#define BR_ERR_BAD_SNI 21 + +/** \brief SSL status: invalid ServerHelloDone from the server (length + is not 0). */ +#define BR_ERR_BAD_HELLO_DONE 22 + +/** \brief SSL status: internal limit exceeded (e.g. server's public key + is too large). */ +#define BR_ERR_LIMIT_EXCEEDED 23 + +/** \brief SSL status: Finished message from peer does not match the + expected value. */ +#define BR_ERR_BAD_FINISHED 24 + +/** \brief SSL status: session resumption attempt with distinct version + or cipher suite. */ +#define BR_ERR_RESUME_MISMATCH 25 + +/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve, + signature algorithm, hash function). */ +#define BR_ERR_INVALID_ALGORITHM 26 + +/** \brief SSL status: invalid signature (on ServerKeyExchange from + server, or in CertificateVerify from client). */ +#define BR_ERR_BAD_SIGNATURE 27 + +/** \brief SSL status: peer's public key does not have the proper type + or is not allowed for requested operation. */ +#define BR_ERR_WRONG_KEY_USAGE 28 + +/** \brief SSL status: client did not send a certificate upon request, + or the client certificate could not be validated. */ +#define BR_ERR_NO_CLIENT_AUTH 29 + +/** \brief SSL status: I/O error or premature close on underlying + transport stream. This error code is set only by the simplified + I/O API ("br_sslio_*"). */ +#define BR_ERR_IO 31 + +/** \brief SSL status: base value for a received fatal alert. + + When a fatal alert is received from the peer, the alert value + is added to this constant. */ +#define BR_ERR_RECV_FATAL_ALERT 256 + +/** \brief SSL status: base value for a sent fatal alert. + + When a fatal alert is sent to the peer, the alert value is added + to this constant. */ +#define BR_ERR_SEND_FATAL_ALERT 512 + +/* ===================================================================== */ + +/** + * \brief Decryption engine for SSL. + * + * When processing incoming records, the SSL engine will use a decryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The decryption engine is responsible for applying decryption, verifying + * MAC, and keeping track of the record sequence number. + */ +typedef struct br_sslrec_in_class_ br_sslrec_in_class; +struct br_sslrec_in_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Test validity of the incoming record length. + * + * This function returns 1 if the announced length for an + * incoming record is valid, 0 otherwise, + * + * \param ctx decryption engine context. + * \param record_len incoming record length. + * \return 1 of a valid length, 0 otherwise. + */ + int (*check_length)(const br_sslrec_in_class *const *ctx, + size_t record_len); + + /** + * \brief Decrypt the incoming record. + * + * This function may assume that the record length is valid + * (it has been previously tested with `check_length()`). + * Decryption is done in place; `*len` is updated with the + * cleartext length, and the address of the first plaintext + * byte is returned. If the record is correct but empty, then + * `*len` is set to 0 and a non-`NULL` pointer is returned. + * + * On decryption/MAC error, `NULL` is returned. + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param payload address of encrypted payload. + * \param len pointer to payload length (updated). + * \return pointer to plaintext, or `NULL` on error. + */ + unsigned char *(*decrypt)(const br_sslrec_in_class **ctx, + int record_type, unsigned version, + void *payload, size_t *len); +}; + +/** + * \brief Encryption engine for SSL. + * + * When building outgoing records, the SSL engine will use an encryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The encryption engine is responsible for applying encryption and MAC, + * and keeping track of the record sequence number. + */ +typedef struct br_sslrec_out_class_ br_sslrec_out_class; +struct br_sslrec_out_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Compute maximum plaintext sizes and offsets. + * + * When this function is called, the `*start` and `*end` + * values contain offsets designating the free area in the + * outgoing buffer for plaintext data; that free area is + * preceded by a 5-byte space which will receive the record + * header. + * + * The `max_plaintext()` function is responsible for adjusting + * both `*start` and `*end` to make room for any record-specific + * header, MAC, padding, and possible split. + * + * \param ctx encryption engine context. + * \param start pointer to start of plaintext offset (updated). + * \param end pointer to start of plaintext offset (updated). + */ + void (*max_plaintext)(const br_sslrec_out_class *const *ctx, + size_t *start, size_t *end); + + /** + * \brief Perform record encryption. + * + * This function encrypts the record. The plaintext address and + * length are provided. Returned value is the start of the + * encrypted record (or sequence of records, if a split was + * performed), _including_ the 5-byte header, and `*len` is + * adjusted to the total size of the record(s), there again + * including the header(s). + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param plaintext address of plaintext. + * \param len pointer to plaintext length (updated). + * \return pointer to start of built record. + */ + unsigned char *(*encrypt)(const br_sslrec_out_class **ctx, + int record_type, unsigned version, + void *plaintext, size_t *len); +}; + +/** + * \brief Context for a no-encryption engine. + * + * The no-encryption engine processes outgoing records during the initial + * handshake, before encryption is applied. + */ +typedef struct { + /** \brief No-encryption engine vtable. */ + const br_sslrec_out_class *vtable; +} br_sslrec_out_clear_context; + +/** \brief Static, constant vtable for the no-encryption engine. */ +extern const br_sslrec_out_class br_sslrec_out_clear_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CBC mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class; +struct br_sslrec_in_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC decryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_in_cbc_class **ctx, + const br_block_cbcdec_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for CBC mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class; +struct br_sslrec_out_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC encryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_out_cbc_class **ctx, + const br_block_cbcenc_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Context structure for decrypting incoming records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_in_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcdec_class *vtable; + br_aes_gen_cbcdec_keys aes; + br_des_gen_cbcdec_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_in_cbc_context; + +/** + * \brief Static, constant vtable for record decryption with CBC. + */ +extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable; + +/** + * \brief Context structure for encrypting outgoing records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_out_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcenc_class *vtable; + br_aes_gen_cbcenc_keys aes; + br_des_gen_cbcenc_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_out_cbc_context; + +/** + * \brief Static, constant vtable for record encryption with CBC. + */ +extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for GCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class; +struct br_sslrec_in_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_in_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for GCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class; +struct br_sslrec_out_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_out_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Context structure for processing records with GCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_gcm_class *in; + const br_sslrec_out_gcm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctr_class *vtable; + br_aes_gen_ctr_keys aes; + } bc; + br_ghash gh; + unsigned char iv[4]; + unsigned char h[16]; +#endif +} br_sslrec_gcm_context; + +/** + * \brief Static, constant vtable for record decryption with GCM. + */ +extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable; + +/** + * \brief Static, constant vtable for record encryption with GCM. + */ +extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class; +struct br_sslrec_in_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_in_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Record encryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class; +struct br_sslrec_out_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_out_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Context structure for processing records with ChaCha20+Poly1305. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_chapol_class *in; + const br_sslrec_out_chapol_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + unsigned char key[32]; + unsigned char iv[12]; + br_chacha20_run ichacha; + br_poly1305_run ipoly; +#endif +} br_sslrec_chapol_context; + +/** + * \brief Static, constant vtable for record decryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable; + +/** + * \brief Static, constant vtable for record encryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class; +struct br_sslrec_in_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_in_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Record encryption engine class, for CCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class; +struct br_sslrec_out_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_out_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Context structure for processing records with CCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_ccm_class *in; + const br_sslrec_out_ccm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctrcbc_class *vtable; + br_aes_gen_ctrcbc_keys aes; + } bc; + unsigned char iv[4]; + size_t tag_len; +#endif +} br_sslrec_ccm_context; + +/** + * \brief Static, constant vtable for record decryption with CCM. + */ +extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable; + +/** + * \brief Static, constant vtable for record encryption with CCM. + */ +extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable; + +/* ===================================================================== */ + +/** + * \brief Type for session parameters, to be saved for session resumption. + */ +typedef struct { + /** \brief Session ID buffer. */ + unsigned char session_id[32]; + /** \brief Session ID length (in bytes, at most 32). */ + unsigned char session_id_len; + /** \brief Protocol version. */ + uint16_t version; + /** \brief Cipher suite. */ + uint16_t cipher_suite; + /** \brief Master secret. */ + unsigned char master_secret[48]; + /** \brief Session ticket (RFC 5077), opaque blob from server. */ + unsigned char session_ticket[1024]; + /** \brief Session ticket length (0 if no ticket). */ + uint16_t session_ticket_len; +} br_ssl_session_parameters; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Maximum number of cipher suites supported by a client or server. + */ +#define BR_MAX_CIPHER_SUITES 48 +#endif + +/** + * \brief Context structure for SSL engine. + * + * This strucuture is common to the client and server; both the client + * context (`br_ssl_client_context`) and the server context + * (`br_ssl_server_context`) include a `br_ssl_engine_context` as their + * first field. + * + * The engine context manages records, including alerts, closures, and + * transitions to new encryption/MAC algorithms. Processing of handshake + * records is delegated to externally provided code. This structure + * should not be used directly. + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* + * The error code. When non-zero, then the state is "failed" and + * no I/O may occur until reset. + */ + int err; + + /* + * Configured I/O buffers. They are either disjoint, or identical. + */ + unsigned char *ibuf, *obuf; + size_t ibuf_len, obuf_len; + + /* + * Maximum fragment length applies to outgoing records; incoming + * records can be processed as long as they fit in the input + * buffer. It is guaranteed that incoming records at least as big + * as max_frag_len can be processed. + */ + uint16_t max_frag_len; + unsigned char log_max_frag_len; + unsigned char peer_log_max_frag_len; + + /* + * Buffering management registers. + */ + size_t ixa, ixb, ixc; + size_t oxa, oxb, oxc; + unsigned char iomode; + unsigned char incrypt; + + /* + * Shutdown flag: when set to non-zero, incoming record bytes + * will not be accepted anymore. This is used after a close_notify + * has been received: afterwards, the engine no longer claims that + * it could receive bytes from the transport medium. + */ + unsigned char shutdown_recv; + + /* + * 'record_type_in' is set to the incoming record type when the + * record header has been received. + * 'record_type_out' is used to make the next outgoing record + * header when it is ready to go. + */ + unsigned char record_type_in, record_type_out; + + /* + * When a record is received, its version is extracted: + * -- if 'version_in' is 0, then it is set to the received version; + * -- otherwise, if the received version is not identical to + * the 'version_in' contents, then a failure is reported. + * + * This implements the SSL requirement that all records shall + * use the negotiated protocol version, once decided (in the + * ServerHello). It is up to the handshake handler to adjust this + * field when necessary. + */ + uint16_t version_in; + + /* + * 'version_out' is used when the next outgoing record is ready + * to go. + */ + uint16_t version_out; + + /* + * Record handler contexts. + */ + union { + const br_sslrec_in_class *vtable; + br_sslrec_in_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } in; + union { + const br_sslrec_out_class *vtable; + br_sslrec_out_clear_context clear; + br_sslrec_out_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } out; + + /* + * The "application data" flag. Value: + * 0 handshake is in process, no application data acceptable + * 1 application data can be sent and received + * 2 closing, no application data can be sent, but some + * can still be received (and discarded) + */ + unsigned char application_data; + + /* + * Context RNG. + * + * rng_init_done is initially 0. It is set to 1 when the + * basic structure of the RNG is set, and 2 when some + * entropy has been pushed in. The value 2 marks the RNG + * as "properly seeded". + * + * rng_os_rand_done is initially 0. It is set to 1 when + * some seeding from the OS or hardware has been attempted. + */ + br_hmac_drbg_context rng; + int rng_init_done; + int rng_os_rand_done; + + /* + * Supported minimum and maximum versions, and cipher suites. + */ + uint16_t version_min; + uint16_t version_max; + uint16_t suites_buf[BR_MAX_CIPHER_SUITES]; + unsigned char suites_num; + + /* + * For clients, the server name to send as a SNI extension. For + * servers, the name received in the SNI extension (if any). + */ + char server_name[256]; + + /* + * "Security parameters". These are filled by the handshake + * handler, and used when switching encryption state. + */ + unsigned char client_random[32]; + unsigned char server_random[32]; + br_ssl_session_parameters session; + + /* + * ECDHE elements: curve and point from the peer. The server also + * uses that buffer for the point to send to the client. + */ + unsigned char ecdhe_curve; + unsigned char ecdhe_point[133]; + unsigned char ecdhe_point_len; + + /* + * Secure renegotiation (RFC 5746): 'reneg' can be: + * 0 first handshake (server support is not known) + * 1 peer does not support secure renegotiation + * 2 peer supports secure renegotiation + * + * The saved_finished buffer contains the client and the + * server "Finished" values from the last handshake, in + * that order (12 bytes each). + */ + unsigned char reneg; + unsigned char saved_finished[24]; + + /* + * Session ticket (RFC 5077) support flag. Set to 1 when the + * server confirms ticket support in its ServerHello extensions. + */ + unsigned char session_ticket_ok; + + /* + * Behavioural flags. + */ + uint32_t flags; + + /* + * Context variables for the handshake processor. The 'pad' must + * be large enough to accommodate an RSA-encrypted pre-master + * secret, or an RSA signature; since we want to support up to + * RSA-4096, this means at least 512 bytes. (Other pad usages + * require its length to be at least 256.) + */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + unsigned char pad[512]; + unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out; + size_t hlen_in, hlen_out; + void (*hsrun)(void *ctx); + + /* + * The 'action' value communicates OOB information between the + * engine and the handshake processor. + * + * From the engine: + * 0 invocation triggered by I/O + * 1 invocation triggered by explicit close + * 2 invocation triggered by explicit renegotiation + */ + unsigned char action; + + /* + * State for alert messages. Value is either 0, or the value of + * the alert level byte (level is either 1 for warning, or 2 for + * fatal; we convert all other values to 'fatal'). + */ + unsigned char alert; + + /* + * Closure flags. This flag is set when a close_notify has been + * received from the peer. + */ + unsigned char close_received; + + /* + * Multi-hasher for the handshake messages. The handshake handler + * is responsible for resetting it when appropriate. + */ + br_multihash_context mhash; + + /* + * Pointer to the X.509 engine. The engine is supposed to be + * already initialized. It is used to validate the peer's + * certificate. + */ + const br_x509_class **x509ctx; + + /* + * Certificate chain to send. This is used by both client and + * server, when they send their respective Certificate messages. + * If chain_len is 0, then chain may be NULL. + */ + const br_x509_certificate *chain; + size_t chain_len; + const unsigned char *cert_cur; + size_t cert_len; + + /* + * List of supported protocol names (ALPN extension). If unset, + * (number of names is 0), then: + * - the client sends no ALPN extension; + * - the server ignores any incoming ALPN extension. + * + * Otherwise: + * - the client sends an ALPN extension with all the names; + * - the server selects the first protocol in its list that + * the client also supports, or fails (fatal alert 120) + * if the client sends an ALPN extension and there is no + * match. + * + * The 'selected_protocol' field contains 1+n if the matching + * name has index n in the list (the value is 0 if no match was + * performed, e.g. the peer did not send an ALPN extension). + */ + const char **protocol_names; + uint16_t protocol_names_num; + uint16_t selected_protocol; + + /* + * Pointers to implementations; left to NULL for unsupported + * functions. For the raw hash functions, implementations are + * referenced from the multihasher (mhash field). + */ + br_tls_prf_impl prf10; + br_tls_prf_impl prf_sha256; + br_tls_prf_impl prf_sha384; + const br_block_cbcenc_class *iaes_cbcenc; + const br_block_cbcdec_class *iaes_cbcdec; + const br_block_ctr_class *iaes_ctr; + const br_block_ctrcbc_class *iaes_ctrcbc; + const br_block_cbcenc_class *ides_cbcenc; + const br_block_cbcdec_class *ides_cbcdec; + br_ghash ighash; + br_chacha20_run ichacha; + br_poly1305_run ipoly; + const br_sslrec_in_cbc_class *icbc_in; + const br_sslrec_out_cbc_class *icbc_out; + const br_sslrec_in_gcm_class *igcm_in; + const br_sslrec_out_gcm_class *igcm_out; + const br_sslrec_in_chapol_class *ichapol_in; + const br_sslrec_out_chapol_class *ichapol_out; + const br_sslrec_in_ccm_class *iccm_in; + const br_sslrec_out_ccm_class *iccm_out; + const br_ec_impl *iec; + br_rsa_pkcs1_vrfy irsavrfy; + br_ecdsa_vrfy iecdsa; +#endif +} br_ssl_engine_context; + +/** + * \brief Get currently defined engine behavioural flags. + * + * \param cc SSL engine context. + * \return the flags. + */ +static __inline uint32_t +br_ssl_engine_get_flags(br_ssl_engine_context *cc) +{ + return cc->flags; +} + +/** + * \brief Set all engine behavioural flags. + * + * \param cc SSL engine context. + * \param flags new value for all flags. + */ +static __inline void +br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags = flags; +} + +/** + * \brief Set some engine behavioural flags. + * + * The flags set in the `flags` parameter are set in the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags additional set flags. + */ +static __inline void +br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags |= flags; +} + +/** + * \brief Clear some engine behavioural flags. + * + * The flags set in the `flags` parameter are cleared from the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags flags to remove. + */ +static __inline void +br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags &= ~flags; +} + +/** + * \brief Behavioural flag: enforce server preferences. + * + * If this flag is set, then the server will enforce its own cipher suite + * preference order; otherwise, it follows the client preferences. + */ +#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0) + +/** + * \brief Behavioural flag: disable renegotiation. + * + * If this flag is set, then renegotiations are rejected unconditionally: + * they won't be honoured if asked for programmatically, and requests from + * the peer are rejected. + */ +#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1) + +/** + * \brief Behavioural flag: tolerate lack of client authentication. + * + * If this flag is set in a server and the server requests a client + * certificate, but the authentication fails (the client does not send + * a certificate, or the client's certificate chain cannot be validated), + * then the connection keeps on. Without this flag, a failed client + * authentication terminates the connection. + * + * Notes: + * + * - If the client's certificate can be validated and its public key is + * supported, then a wrong signature value terminates the connection + * regardless of that flag. + * + * - If using full-static ECDH, then a failure to validate the client's + * certificate prevents the handshake from succeeding. + */ +#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2) + +/** + * \brief Behavioural flag: fail on application protocol mismatch. + * + * The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301)) + * allows the client to send a list of application protocol names, and + * the server to select one. A mismatch is one of the following occurrences: + * + * - On the client: the client sends a list of names, the server + * responds with a protocol name which is _not_ part of the list of + * names sent by the client. + * + * - On the server: the client sends a list of names, and the server + * is also configured with a list of names, but there is no common + * protocol name between the two lists. + * + * Normal behaviour in case of mismatch is to report no matching name + * (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on. + * If the flag is set, then a mismatch implies a protocol failure (if + * the mismatch is detected by the server, it will send a fatal alert). + * + * Note: even with this flag, `br_ssl_engine_get_selected_protocol()` + * may still return `NULL` if the client or the server does not send an + * ALPN extension at all. + */ +#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3) + +/** + * \brief Set the minimum and maximum supported protocol versions. + * + * The two provided versions MUST be supported by the implementation + * (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower + * than `version_min`. + * + * \param cc SSL engine context. + * \param version_min minimum supported TLS version. + * \param version_max maximum supported TLS version. + */ +static __inline void +br_ssl_engine_set_versions(br_ssl_engine_context *cc, + unsigned version_min, unsigned version_max) +{ + cc->version_min = (uint16_t)version_min; + cc->version_max = (uint16_t)version_max; +} + +/** + * \brief Set the list of cipher suites advertised by this context. + * + * The provided array is copied into the context. It is the caller + * responsibility to ensure that all provided suites will be supported + * by the context. The engine context has enough room to receive _all_ + * suites supported by the implementation. The provided array MUST NOT + * contain duplicates. + * + * If the engine is for a client, the "signaling" pseudo-cipher suite + * `TLS_FALLBACK_SCSV` can be added at the end of the list, if the + * calling application is performing a voluntary downgrade (voluntary + * downgrades are not recommended, but if such a downgrade is done, then + * adding the fallback pseudo-suite is a good idea). + * + * \param cc SSL engine context. + * \param suites cipher suites. + * \param suites_num number of cipher suites. + */ +void br_ssl_engine_set_suites(br_ssl_engine_context *cc, + const uint16_t *suites, size_t suites_num); + +/** + * \brief Set the X.509 engine. + * + * The caller shall ensure that the X.509 engine is properly initialised. + * + * \param cc SSL engine context. + * \param x509ctx X.509 certificate validation context. + */ +static __inline void +br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx) +{ + cc->x509ctx = x509ctx; +} + +/** + * \brief Set the supported protocol names. + * + * Protocol names are part of the ALPN extension ([RFC + * 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a + * character string, containing no more than 255 characters (256 with the + * terminating zero). When names are set, then: + * + * - The client will send an ALPN extension, containing the names. If + * the server responds with an ALPN extension, the client will verify + * that the response contains one of its name, and report that name + * through `br_ssl_engine_get_selected_protocol()`. + * + * - The server will parse incoming ALPN extension (from clients), and + * try to find a common protocol; if none is found, the connection + * is aborted with a fatal alert. On match, a response ALPN extension + * is sent, and name is reported through + * `br_ssl_engine_get_selected_protocol()`. + * + * The provided array is linked in, and must remain valid while the + * connection is live. + * + * Names MUST NOT be empty. Names MUST NOT be longer than 255 characters + * (excluding the terminating 0). + * + * \param ctx SSL engine context. + * \param names list of protocol names (zero-terminated). + * \param num number of protocol names (MUST be 1 or more). + */ +static __inline void +br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx, + const char **names, size_t num) +{ + ctx->protocol_names = names; + ctx->protocol_names_num = (uint16_t)num; +} + +/** + * \brief Get the selected protocol. + * + * If this context was initialised with a non-empty list of protocol + * names, and both client and server sent ALPN extensions during the + * handshake, and a common name was found, then that name is returned. + * Otherwise, `NULL` is returned. + * + * The returned pointer is one of the pointers provided to the context + * with `br_ssl_engine_set_protocol_names()`. + * + * \return the selected protocol, or `NULL`. + */ +static __inline const char * +br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx) +{ + unsigned k; + + k = ctx->selected_protocol; + return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1]; +} + +/** + * \brief Set a hash function implementation (by ID). + * + * Hash functions set with this call will be used for SSL/TLS specific + * usages, not X.509 certificate validation. Only "standard" hash functions + * may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl` + * is `NULL`, then the hash function support is removed, not added. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \param impl hash function implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_hash(br_ssl_engine_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Get a hash function implementation (by ID). + * + * This function retrieves a hash function implementation which was + * set with `br_ssl_engine_set_hash()`. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \return the hash function implementation (or `NULL`). + */ +static __inline const br_hash_class * +br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id) +{ + return br_multihash_getimpl(&ctx->mhash, id); +} + +/** + * \brief Set the PRF implementation (for TLS 1.0 and 1.1). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the PRF used in TLS 1.0 and 1.1. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf10 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-256 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-256 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha256 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-384 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-384 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha384 = impl; +} + +/** + * \brief Set the AES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc AES/CBC encryption implementation (or `NULL`). + * \param impl_dec AES/CBC decryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->iaes_cbcenc = impl_enc; + cc->iaes_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" AES/CBC implementations. + * + * This function configures in the engine the AES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR encryption/decryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc, + const br_block_ctr_class *impl) +{ + cc->iaes_ctr = impl; +} + +/** + * \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH). + * + * This function configures in the engine the AES/CTR and GHASH + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for GCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc); + +/** + * \brief Set the DES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc DES/CBC encryption implementation (or `NULL`). + * \param impl_dec DES/CBC decryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->ides_cbcenc = impl_enc; + cc->ides_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" DES/CBC implementations. + * + * This function configures in the engine the DES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the GHASH implementation (used in GCM mode). + * + * \param cc SSL engine context. + * \param impl GHASH implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl) +{ + cc->ighash = impl; +} + +/** + * \brief Set the ChaCha20 implementation. + * + * \param cc SSL engine context. + * \param ichacha ChaCha20 implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_chacha20(br_ssl_engine_context *cc, + br_chacha20_run ichacha) +{ + cc->ichacha = ichacha; +} + +/** + * \brief Set the Poly1305 implementation. + * + * \param cc SSL engine context. + * \param ipoly Poly1305 implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_poly1305(br_ssl_engine_context *cc, + br_poly1305_run ipoly) +{ + cc->ipoly = ipoly; +} + +/** + * \brief Set the "default" ChaCha20 and Poly1305 implementations. + * + * This function configures in the engine the ChaCha20 and Poly1305 + * implementations that should provide best runtime performance on the + * local system, while still being safe (in particular, constant-time). + * It also sets the handlers for ChaCha20+Poly1305 records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR+CBC implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc, + const br_block_ctrcbc_class *impl) +{ + cc->iaes_ctrcbc = impl; +} + +/** + * \brief Set the "default" implementations for AES/CCM. + * + * This function configures in the engine the AES/CTR+CBC + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for CCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc); + +/** + * \brief Set the record encryption and decryption engines for CBC + HMAC. + * + * \param cc SSL engine context. + * \param impl_in record CBC decryption implementation (or `NULL`). + * \param impl_out record CBC encryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_cbc(br_ssl_engine_context *cc, + const br_sslrec_in_cbc_class *impl_in, + const br_sslrec_out_cbc_class *impl_out) +{ + cc->icbc_in = impl_in; + cc->icbc_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for GCM. + * + * \param cc SSL engine context. + * \param impl_in record GCM decryption implementation (or `NULL`). + * \param impl_out record GCM encryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_gcm(br_ssl_engine_context *cc, + const br_sslrec_in_gcm_class *impl_in, + const br_sslrec_out_gcm_class *impl_out) +{ + cc->igcm_in = impl_in; + cc->igcm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for CCM. + * + * \param cc SSL engine context. + * \param impl_in record CCM decryption implementation (or `NULL`). + * \param impl_out record CCM encryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_ccm(br_ssl_engine_context *cc, + const br_sslrec_in_ccm_class *impl_in, + const br_sslrec_out_ccm_class *impl_out) +{ + cc->iccm_in = impl_in; + cc->iccm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for + * ChaCha20+Poly1305. + * + * \param cc SSL engine context. + * \param impl_in record ChaCha20 decryption implementation (or `NULL`). + * \param impl_out record ChaCha20 encryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_chapol(br_ssl_engine_context *cc, + const br_sslrec_in_chapol_class *impl_in, + const br_sslrec_out_chapol_class *impl_out) +{ + cc->ichapol_in = impl_in; + cc->ichapol_out = impl_out; +} + +/** + * \brief Set the EC implementation. + * + * The elliptic curve implementation will be used for ECDH and ECDHE + * cipher suites, and for ECDSA support. + * + * \param cc SSL engine context. + * \param iec EC implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec) +{ + cc->iec = iec; +} + +/** + * \brief Set the "default" EC implementation. + * + * This function sets the elliptic curve implementation for ECDH and + * ECDHE cipher suites, and for ECDSA support. It selects the fastest + * implementation on the current system. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc); + +/** + * \brief Get the EC implementation configured in the provided engine. + * + * \param cc SSL engine context. + * \return the EC implementation. + */ +static __inline const br_ec_impl * +br_ssl_engine_get_ec(br_ssl_engine_context *cc) +{ + return cc->iec; +} + +/** + * \brief Set the RSA signature verification implementation. + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, and that certificate contains a RSA key). + * + * \param cc SSL engine context. + * \param irsavrfy RSA signature verification implementation. + */ +static __inline void +br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy) +{ + cc->irsavrfy = irsavrfy; +} + +/** + * \brief Set the "default" RSA implementation (signature verification). + * + * This function sets the RSA implementation (signature verification) + * to the fastest implementation available on the current platform. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc); + +/** + * \brief Get the RSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the RSA signature verification implementation. + */ +static __inline br_rsa_pkcs1_vrfy +br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc) +{ + return cc->irsavrfy; +} + +/* + * \brief Set the ECDSA implementation (signature verification). + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, that certificate contains an EC key, + * and full-static ECDH is not used). + * + * The ECDSA implementation will use the EC core implementation configured + * in the engine context. + * + * \param cc client context. + * \param iecdsa ECDSA verification implementation. + */ +static __inline void +br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa) +{ + cc->iecdsa = iecdsa; +} + +/** + * \brief Set the "default" ECDSA implementation (signature verification). + * + * This function sets the ECDSA implementation (signature verification) + * to the fastest implementation available on the current platform. This + * call also sets the elliptic curve implementation itself, there again + * to the fastest EC implementation available. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc); + +/** + * \brief Get the ECDSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the ECDSA signature verification implementation. + */ +static __inline br_ecdsa_vrfy +br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc) +{ + return cc->iecdsa; +} + +/** + * \brief Set the I/O buffer for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * The provided buffer will be used as long as the engine context is + * used. The caller is responsible for keeping it available. + * + * If `bidi` is 0, then the engine will operate in half-duplex mode + * (it won't be able to send data while there is unprocessed incoming + * data in the buffer, and it won't be able to receive data while there + * is unsent data in the buffer). The optimal buffer size in half-duplex + * mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra + * bytes are ignored. If the buffer is smaller, then this limits the + * capacity of the engine to support all allowed record sizes. + * + * If `bidi` is 1, then the engine will split the buffer into two + * parts, for separate handling of outgoing and incoming data. This + * enables full-duplex processing, but requires more RAM. The optimal + * buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the + * buffer is larger, then extra bytes are ignored. If the buffer is + * smaller, then the split will favour the incoming part, so that + * interoperability is maximised. + * + * \param cc SSL engine context + * \param iobuf I/O buffer. + * \param iobuf_len I/O buffer length (in bytes). + * \param bidi non-zero for full-duplex mode. + */ +void br_ssl_engine_set_buffer(br_ssl_engine_context *cc, + void *iobuf, size_t iobuf_len, int bidi); + +/** + * \brief Set the I/O buffers for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * This function is similar to `br_ssl_engine_set_buffer()`, except + * that it enforces full-duplex mode, and the two I/O buffers are + * provided as separate chunks. + * + * The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT` + * evaluate to the optimal (maximum) sizes for the input and output + * buffer, respectively. + * + * \param cc SSL engine context + * \param ibuf input buffer. + * \param ibuf_len input buffer length (in bytes). + * \param obuf output buffer. + * \param obuf_len output buffer length (in bytes). + */ +void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc, + void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len); + +/** + * \brief Inject some "initial entropy" in the context. + * + * This entropy will be added to what can be obtained from the + * underlying operating system, if that OS is supported. + * + * This function may be called several times; all injected entropy chunks + * are cumulatively mixed. + * + * If entropy gathering from the OS is supported and compiled in, then this + * step is optional. Otherwise, it is mandatory to inject randomness, and + * the caller MUST take care to push (as one or several successive calls) + * enough entropy to achieve cryptographic resistance (at least 80 bits, + * preferably 128 or more). The engine will report an error if no entropy + * was provided and none can be obtained from the OS. + * + * Take care that this function cannot assess the cryptographic quality of + * the provided bytes. + * + * In all generality, "entropy" must here be considered to mean "that + * which the attacker cannot predict". If your OS/architecture does not + * have a suitable source of randomness, then you can make do with the + * combination of a large enough secret value (possibly a copy of an + * asymmetric private key that you also store on the system) AND a + * non-repeating value (e.g. current time, provided that the local clock + * cannot be reset or altered by the attacker). + * + * \param cc SSL engine context. + * \param data extra entropy to inject. + * \param len length of the extra data (in bytes). + */ +void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc, + const void *data, size_t len); + +/** + * \brief Get the "server name" in this engine. + * + * For clients, this is the name provided with `br_ssl_client_reset()`; + * for servers, this is the name received from the client as part of the + * ClientHello message. If there is no such name (e.g. the client did + * not send an SNI extension) then the returned string is empty + * (returned pointer points to a byte of value 0). + * + * The returned pointer refers to a buffer inside the context, which may + * be overwritten as part of normal SSL activity (even within the same + * connection, if a renegotiation occurs). + * + * \param cc SSL engine context. + * \return the server name (possibly empty). + */ +static __inline const char * +br_ssl_engine_get_server_name(const br_ssl_engine_context *cc) +{ + return cc->server_name; +} + +/** + * \brief Get the protocol version. + * + * This function returns the protocol version that is used by the + * engine. That value is set after sending (for a server) or receiving + * (for a client) the ServerHello message. + * + * \param cc SSL engine context. + * \return the protocol version. + */ +static __inline unsigned +br_ssl_engine_get_version(const br_ssl_engine_context *cc) +{ + return cc->session.version; +} + +/** + * \brief Get a copy of the session parameters. + * + * The session parameters are filled during the handshake, so this + * function shall not be called before completion of the handshake. + * The initial handshake is completed when the context first allows + * application data to be injected. + * + * This function copies the current session parameters into the provided + * structure. Beware that the session parameters include the master + * secret, which is sensitive data, to handle with great care. + * + * \param cc SSL engine context. + * \param pp destination structure for the session parameters. + */ +static __inline void +br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc, + br_ssl_session_parameters *pp) +{ + memcpy(pp, &cc->session, sizeof *pp); +} + +/** + * \brief Set the session parameters to the provided values. + * + * This function is meant to be used in the client, before doing a new + * handshake; a session resumption will be attempted with these + * parameters. In the server, this function has no effect. + * + * \param cc SSL engine context. + * \param pp source structure for the session parameters. + */ +static __inline void +br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc, + const br_ssl_session_parameters *pp) +{ + memcpy(&cc->session, pp, sizeof *pp); +} + +/** + * \brief Get identifier for the curve used for key exchange. + * + * If the cipher suite uses ECDHE, then this function returns the + * identifier for the curve used for transient parameters. This is + * defined during the course of the handshake, when the ServerKeyExchange + * is sent (on the server) or received (on the client). If the + * cipher suite does not use ECDHE (e.g. static ECDH, or RSA key + * exchange), then this value is indeterminate. + * + * @param cc SSL engine context. + * @return the ECDHE curve identifier. + */ +static __inline int +br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc) +{ + return cc->ecdhe_curve; +} + +/** + * \brief Get the current engine state. + * + * An SSL engine (client or server) has, at any time, a state which is + * the combination of zero, one or more of these flags: + * + * - `BR_SSL_CLOSED` + * + * Engine is finished, no more I/O (until next reset). + * + * - `BR_SSL_SENDREC` + * + * Engine has some bytes to send to the peer. + * + * - `BR_SSL_RECVREC` + * + * Engine expects some bytes from the peer. + * + * - `BR_SSL_SENDAPP` + * + * Engine may receive application data to send (or flush). + * + * - `BR_SSL_RECVAPP` + * + * Engine has obtained some application data from the peer, + * that should be read by the caller. + * + * If no flag at all is set (state value is 0), then the engine is not + * fully initialised yet. + * + * The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag + * is set. To distinguish between a normal closure and an error, use + * `br_ssl_engine_last_error()`. + * + * Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually + * exclusive: the input buffer, at any point, either accumulates + * plaintext data, or contains an assembled record that is being sent. + * Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive. + * This may change in a future library version. + * + * \param cc SSL engine context. + * \return the current engine state. + */ +unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc); + +/** \brief SSL engine state: closed or failed. */ +#define BR_SSL_CLOSED 0x0001 +/** \brief SSL engine state: record data is ready to be sent to the peer. */ +#define BR_SSL_SENDREC 0x0002 +/** \brief SSL engine state: engine may receive records from the peer. */ +#define BR_SSL_RECVREC 0x0004 +/** \brief SSL engine state: engine may accept application data to send. */ +#define BR_SSL_SENDAPP 0x0008 +/** \brief SSL engine state: engine has received application data. */ +#define BR_SSL_RECVAPP 0x0010 + +/** + * \brief Get the engine error indicator. + * + * The error indicator is `BR_ERR_OK` (0) if no error was encountered + * since the last call to `br_ssl_client_reset()` or + * `br_ssl_server_reset()`. Other status values are "sticky": they + * remain set, and prevent all I/O activity, until cleared. Only the + * reset calls clear the error indicator. + * + * \param cc SSL engine context. + * \return 0, or a non-zero error code. + */ +static __inline int +br_ssl_engine_last_error(const br_ssl_engine_context *cc) +{ + return cc->err; +} + +/* + * There are four I/O operations, each identified by a symbolic name: + * + * sendapp inject application data in the engine + * recvapp retrieving application data from the engine + * sendrec sending records on the transport medium + * recvrec receiving records from the transport medium + * + * Terminology works thus: in a layered model where the SSL engine sits + * between the application and the network, "send" designates operations + * where bytes flow from application to network, and "recv" for the + * reverse operation. Application data (the plaintext that is to be + * conveyed through SSL) is "app", while encrypted records are "rec". + * Note that from the SSL engine point of view, "sendapp" and "recvrec" + * designate bytes that enter the engine ("inject" operation), while + * "recvapp" and "sendrec" designate bytes that exit the engine + * ("extract" operation). + * + * For the operation 'xxx', two functions are defined: + * + * br_ssl_engine_xxx_buf + * Returns a pointer and length to the buffer to use for that + * operation. '*len' is set to the number of bytes that may be read + * from the buffer (extract operation) or written to the buffer + * (inject operation). If no byte may be exchanged for that operation + * at that point, then '*len' is set to zero, and NULL is returned. + * The engine state is unmodified by this call. + * + * br_ssl_engine_xxx_ack + * Informs the engine that 'len' bytes have been read from the buffer + * (extract operation) or written to the buffer (inject operation). + * The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed + * that which was obtained from a preceding br_ssl_engine_xxx_buf() + * call. + */ + +/** + * \brief Get buffer for application data to send. + * + * If the engine is ready to accept application data to send to the + * peer, then this call returns a pointer to the buffer where such + * data shall be written, and its length is written in `*len`. + * Otherwise, `*len` is set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data output buffer length, or 0. + * \return the application data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new application data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_sendapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for received application data. + * + * If the engine has received application data from the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data input buffer length, or 0. + * \return the application data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some received application data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_recvapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for record data to send. + * + * If the engine has prepared some records to send to the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data output buffer length, or 0. + * \return the record data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some sent record data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_sendrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for incoming records. + * + * If the engine is ready to accept records from the peer, then this + * call returns a pointer to the buffer where such data shall be + * written, and its length is written in `*len`. Otherwise, `*len` is + * set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data input buffer length, or 0. + * \return the record data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new record data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_recvrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Flush buffered application data. + * + * If some application data has been buffered in the engine, then wrap + * it into a record and mark it for sending. If no application data has + * been buffered but the engine would be ready to accept some, AND the + * `force` parameter is non-zero, then an empty record is assembled and + * marked for sending. In all other cases, this function does nothing. + * + * Empty records are technically legal, but not all existing SSL/TLS + * implementations support them. Empty records can be useful as a + * transparent "keep-alive" mechanism to maintain some low-level + * network activity. + * + * \param cc SSL engine context. + * \param force non-zero to force sending an empty record. + */ +void br_ssl_engine_flush(br_ssl_engine_context *cc, int force); + +/** + * \brief Initiate a closure. + * + * If, at that point, the context is open and in ready state, then a + * `close_notify` alert is assembled and marked for sending; this + * triggers the closure protocol. Otherwise, no such alert is assembled. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_close(br_ssl_engine_context *cc); + +/** + * \brief Initiate a renegotiation. + * + * If the engine is failed or closed, or if the peer is known not to + * support secure renegotiation (RFC 5746), or if renegotiations have + * been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there + * is buffered incoming application data, then this function returns 0 + * and nothing else happens. + * + * Otherwise, this function returns 1, and a renegotiation attempt is + * triggered (if a handshake is already ongoing at that point, then + * no new handshake is triggered). + * + * \param cc SSL engine context. + * \return 1 on success, 0 on error. + */ +int br_ssl_engine_renegotiate(br_ssl_engine_context *cc); + +/** + * \brief Export key material from a connected SSL engine (RFC 5705). + * + * This calls compute a secret key of arbitrary length from the master + * secret of a connected SSL engine. If the provided context is not + * currently in "application data" state (initial handshake is not + * finished, another handshake is ongoing, or the connection failed or + * was closed), then this function returns 0. Otherwise, a secret key of + * length `len` bytes is computed and written in the buffer pointed to + * by `dst`, and 1 is returned. + * + * The computed key follows the specification described in RFC 5705. + * That RFC includes two key computations, with and without a "context + * value". If `context` is `NULL`, then the variant without context is + * used; otherwise, the `context_len` bytes located at the address + * pointed to by `context` are used in the computation. Note that it + * is possible to have a "with context" key with a context length of + * zero bytes, by setting `context` to a non-`NULL` value but + * `context_len` to 0. + * + * When context bytes are used, the context length MUST NOT exceed + * 65535 bytes. + * + * \param cc SSL engine context. + * \param dst destination buffer for exported key. + * \param len exported key length (in bytes). + * \param label disambiguation label. + * \param context context value (or `NULL`). + * \param context_len context length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ssl_key_export(br_ssl_engine_context *cc, + void *dst, size_t len, const char *label, + const void *context, size_t context_len); + +/* + * Pre-declaration for the SSL client context. + */ +typedef struct br_ssl_client_context_ br_ssl_client_context; + +/** + * \brief Type for the client certificate, if requested by the server. + */ +typedef struct { + /** + * \brief Authentication type. + * + * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA` + * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange). + */ + int auth_type; + + /** + * \brief Hash function for computing the CertificateVerify. + * + * This is the symbolic identifier for the hash function that + * will be used to produce the hash of handshake messages, to + * be signed into the CertificateVerify. For full static ECDH + * (client and server certificates are both EC in the same + * curve, and static ECDH is used), this value is set to -1. + * + * Take care that with TLS 1.0 and 1.1, that value MUST match + * the protocol requirements: value must be 0 (MD5+SHA-1) for + * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only + * TLS 1.2 allows for other hash functions. + */ + int hash_id; + + /** + * \brief Certificate chain to send to the server. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The client + * code does not try to decode these elements. If there is no + * chain to send to the server, then this pointer shall be + * set to `NULL`. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + * + * If there is no chain to send to the server, then this value + * shall be set to 0. + */ + size_t chain_len; + +} br_ssl_client_certificate; + +/* + * Note: the constants below for signatures match the TLS constants. + */ + +/** \brief Client authentication type: static ECDH. */ +#define BR_AUTH_ECDH 0 +/** \brief Client authentication type: RSA signature. */ +#define BR_AUTH_RSA 1 +/** \brief Client authentication type: ECDSA signature. */ +#define BR_AUTH_ECDSA 3 + +/** + * \brief Class type for a certificate handler (client side). + * + * A certificate handler selects a client certificate chain to send to + * the server, upon explicit request from that server. It receives + * the list of trust anchor DN from the server, and supported types + * of certificates and signatures, and returns the chain to use. It + * is also invoked to perform the corresponding private key operation + * (a signature, or an ECDH computation). + * + * The SSL client engine will first push the trust anchor DN with + * `start_name_list()`, `start_name()`, `append_name()`, `end_name()` + * and `end_name_list()`. Then it will call `choose()`, to select the + * actual chain (and signature/hash algorithms). Finally, it will call + * either `do_sign()` or `do_keyx()`, depending on the algorithm choices. + */ +typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class; +struct br_ssl_client_certificate_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Begin reception of a list of trust anchor names. This + * is called while parsing the incoming CertificateRequest. + * + * \param pctx certificate handler context. + */ + void (*start_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Begin reception of a new trust anchor name. + * + * The total encoded name length is provided; it is less than + * 65535 bytes. + * + * \param pctx certificate handler context. + * \param len encoded name length (in bytes). + */ + void (*start_name)(const br_ssl_client_certificate_class **pctx, + size_t len); + + /** + * \brief Receive some more bytes for the current trust anchor name. + * + * The provided reference (`data`) points to a transient buffer + * they may be reused as soon as this function returns. The chunk + * length (`len`) is never zero. + * + * \param pctx certificate handler context. + * \param data anchor name chunk. + * \param len anchor name chunk length (in bytes). + */ + void (*append_name)(const br_ssl_client_certificate_class **pctx, + const unsigned char *data, size_t len); + + /** + * \brief End current trust anchor name. + * + * This function is called when all the encoded anchor name data + * has been provided. + * + * \param pctx certificate handler context. + */ + void (*end_name)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief End list of trust anchor names. + * + * This function is called when all the anchor names in the + * CertificateRequest message have been obtained. + * + * \param pctx certificate handler context. + */ + void (*end_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Select client certificate and algorithms. + * + * This callback function shall fill the provided `choices` + * structure with the selected algorithms and certificate chain. + * The `hash_id`, `chain` and `chain_len` fields must be set. If + * the client cannot or does not wish to send a certificate, + * then it shall set `chain` to `NULL` and `chain_len` to 0. + * + * The `auth_types` parameter describes the authentication types, + * signature algorithms and hash functions that are supported by + * both the client context and the server, and compatible with + * the current protocol version. This is a bit field with the + * following contents: + * + * - If RSA signatures with hash function x are supported, then + * bit x is set. + * + * - If ECDSA signatures with hash function x are supported, + * then bit 8+x is set. + * + * - If static ECDH is supported, with a RSA-signed certificate, + * then bit 16 is set. + * + * - If static ECDH is supported, with an ECDSA-signed certificate, + * then bit 17 is set. + * + * Notes: + * + * - When using TLS 1.0 or 1.1, the hash function for RSA + * signatures is always the special MD5+SHA-1 (id 0), and the + * hash function for ECDSA signatures is always SHA-1 (id 2). + * + * - When using TLS 1.2, the list of hash functions is trimmed + * down to include only hash functions that the client context + * can support. The actual server list can be obtained with + * `br_ssl_client_get_server_hashes()`; that list may be used + * to select the certificate chain to send to the server. + * + * \param pctx certificate handler context. + * \param cc SSL client context. + * \param auth_types supported authentication types and algorithms. + * \param choices destination structure for the policy choices. + */ + void (*choose)(const br_ssl_client_certificate_class **pctx, + const br_ssl_client_context *cc, uint32_t auth_types, + br_ssl_client_certificate *choices); + + /** + * \brief Perform key exchange (client part). + * + * This callback is invoked in case of a full static ECDH key + * exchange: + * + * - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`; + * + * - the server requests a client certificate; + * + * - the client has, and sends, a client certificate that + * uses an EC key in the same curve as the server's key, + * and chooses static ECDH (the `hash_id` field in the choice + * structure was set to -1). + * + * In that situation, this callback is invoked to compute the + * client-side ECDH: the provided `data` (of length `*len` bytes) + * is the server's public key point (as decoded from its + * certificate), and the client shall multiply that point with + * its own private key, and write back the X coordinate of the + * resulting point in the same buffer, starting at offset 0. + * The `*len` value shall be modified to designate the actual + * length of the X coordinate. + * + * The callback must uphold the following: + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx certificate handler context. + * \param data server public key point. + * \param len public key point length / X coordinate length. + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (client authentication). + * + * This callback is invoked when a client certificate was sent, + * and static ECDH is not used. It shall compute a signature, + * using the client's private key, over the provided hash value + * (which is the hash of all previous handshake messages). + * + * On input, the hash value to sign is in `data`, of size + * `hv_len`; the involved hash function is identified by + * `hash_id`. The signature shall be computed and written + * back into `data`; the total size of that buffer is `len` + * bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * For RSA signatures, the `hash_id` may be 0, in which case + * this is the special header-less signature specified in TLS 1.0 + * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1 + * v1.5 signatures shall be computed. + * + * For ECDSA signatures, the signature value shall use the ASN.1 + * based encoding. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx certificate handler context. + * \param hash_id hash function identifier. + * \param hv_len hash value length (in bytes). + * \param data input/output buffer (hash value, then signature). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_client_certificate_class **pctx, + int hash_id, size_t hv_len, unsigned char *data, size_t len); +}; + +/** + * \brief A single-chain RSA client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_client_certificate_rsa_context; + +/** + * \brief A single-chain EC client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * This handler may support both static ECDH, and ECDSA signatures + * (either usage may be selectively disabled). + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_client_certificate_ec_context; + +/** + * \brief Context structure for a SSL client. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_client_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Minimum ClientHello length; padding with an extension (RFC + * 7685) is added if necessary to match at least that length. + * Such padding is nominally unnecessary, but it has been used + * to work around some server implementation bugs. + */ + uint16_t min_clienthello_len; + + /* + * Bit field for algoithms (hash + signature) supported by the + * server when requesting a client certificate. + */ + uint32_t hashes; + + /* + * Server's public key curve. + */ + int server_curve; + + /* + * Context for certificate handler. + */ + const br_ssl_client_certificate_class **client_auth_vtable; + + /* + * Client authentication type. + */ + unsigned char auth_type; + + /* + * Hash function to use for the client signature. This is 0xFF + * if static ECDH is used. + */ + unsigned char hash_id; + + /* + * For the core certificate handlers, thus avoiding (in most + * cases) the need for an externally provided policy context. + */ + union { + const br_ssl_client_certificate_class *vtable; + br_ssl_client_certificate_rsa_context single_rsa; + br_ssl_client_certificate_ec_context single_ec; + } client_auth; + + /* + * Implementations. + */ + br_rsa_public irsapub; +#endif +}; + +/** + * \brief Get the hash functions and signature algorithms supported by + * the server. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc client context. + * \return the server-supported hash functions and signature algorithms. + */ +static __inline uint32_t +br_ssl_client_get_server_hashes(const br_ssl_client_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the server key curve. + * + * This function returns the ID for the curve used by the server's public + * key. This is set when the server's certificate chain is processed; + * this value is 0 if the server's key is not an EC key. + * + * \return the server's public key curve ID, or 0. + */ +static __inline int +br_ssl_client_get_server_curve(const br_ssl_client_context *cc) +{ + return cc->server_curve; +} + +/* + * Each br_ssl_client_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full all supported versions and suites; constant-time implementations + * TODO: add other profiles + */ + +/** + * \brief SSL client profile: full. + * + * This function initialises the provided SSL client context with + * all supported algorithms and cipher suites. It also initialises + * a companion X.509 validation engine with all supported algorithms, + * and the provided trust anchors; the X.509 engine will be used by + * the client context to validate the server's certificate. + * + * \param cc client context to initialise. + * \param xc X.509 validation context to initialise. + * \param trust_anchors trust anchors to use. + * \param trust_anchors_num number of trust anchors. + */ +void br_ssl_client_init_full(br_ssl_client_context *cc, + br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Clear the complete contents of a SSL client context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc client context to clear. + */ +void br_ssl_client_zero(br_ssl_client_context *cc); + +/** + * \brief Set an externally provided client certificate handler context. + * + * The handler's methods are invoked when the server requests a client + * certificate. + * + * \param cc client context. + * \param pctx certificate handler context (pointer to its vtable field). + */ +static __inline void +br_ssl_client_set_client_certificate(br_ssl_client_context *cc, + const br_ssl_client_certificate_class **pctx) +{ + cc->client_auth_vtable = pctx; +} + +/** + * \brief Set the RSA public-key operations implementation. + * + * This will be used to encrypt the pre-master secret with the server's + * RSA public key (RSA-encryption cipher suites only). + * + * \param cc client context. + * \param irsapub RSA public-key encryption implementation. + */ +static __inline void +br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub) +{ + cc->irsapub = irsapub; +} + +/** + * \brief Set the "default" RSA implementation for public-key operations. + * + * This sets the RSA implementation in the client context (for encrypting + * the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest + * available on the current platform. + * + * \param cc client context. + */ +void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc); + +/** + * \brief Set the minimum ClientHello length (RFC 7685 padding). + * + * If this value is set and the ClientHello would be shorter, then + * the Pad ClientHello extension will be added with enough padding bytes + * to reach the target size. Because of the extension header, the resulting + * size will sometimes be slightly more than `len` bytes if the target + * size cannot be exactly met. + * + * The target length relates to the _contents_ of the ClientHello, not + * counting its 4-byte header. For instance, if `len` is set to 512, + * then the padding will bring the ClientHello size to 516 bytes with its + * header, and 521 bytes when counting the 5-byte record header. + * + * \param cc client context. + * \param len minimum ClientHello length (in bytes). + */ +static __inline void +br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len) +{ + cc->min_clienthello_len = len; +} + +/** + * \brief Prepare or reset a client context for a new connection. + * + * The `server_name` parameter is used to fill the SNI extension; the + * X.509 "minimal" engine will also match that name against the server + * names included in the server's certificate. If the parameter is + * `NULL` then no SNI extension will be sent, and the X.509 "minimal" + * engine (if used for server certificate validation) will not check + * presence of any specific name in the received certificate. + * + * Therefore, setting the `server_name` to `NULL` shall be reserved + * to cases where alternate or additional methods are used to ascertain + * that the right server public key is used (e.g. a "known key" model). + * + * If `resume_session` is non-zero and the context was previously used + * then the session parameters may be reused (depending on whether the + * server previously sent a non-empty session ID, and accepts the session + * resumption). The session parameters for session resumption can also + * be set explicitly with `br_ssl_engine_set_session_parameters()`. + * + * On failure, the context is marked as failed, and this function + * returns 0. A possible failure condition is when no initial entropy + * was injected, and none could be obtained from the OS (either OS + * randomness gathering is not supported, or it failed). + * + * \param cc client context. + * \param server_name target server name, or `NULL`. + * \param resume_session non-zero to try session resumption. + * \return 0 on failure, 1 on success. + */ +int br_ssl_client_reset(br_ssl_client_context *cc, + const char *server_name, int resume_session); + +/** + * \brief Forget any session in the context. + * + * This means that the next handshake that uses this context will + * necessarily be a full handshake (this applies both to new connections + * and to renegotiations). + * + * \param cc client context. + */ +static __inline void +br_ssl_client_forget_session(br_ssl_client_context *cc) +{ + cc->eng.session.session_id_len = 0; + cc->eng.session.session_ticket_len = 0; +} + +/** + * \brief Set client certificate chain and key (single RSA case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an RSA public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * \param cc SSL client context. + * \param chain client certificate chain (SSL order: EE comes first). + * \param chain_len client chain length (number of certificates). + * \param sk client private key. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_client_set_single_rsa(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign); + +/* + * \brief Set the client certificate chain and key (single EC case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an EC public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX` + * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value + * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA + * signature implementation must be provided; otherwise, the `iecdsa` + * parameter may be 0. + * + * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or + * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA + * that issued (signed) the client certificate. That value is used with + * full static ECDH: support of the certificate by the server depends + * on how the certificate was signed. (Note: when using TLS 1.2, this + * parameter is ignored; but its value matters for TLS 1.0 and 1.1.) + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_client_set_single_ec(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Type for a "translated cipher suite", as an array of two + * 16-bit integers. + * + * The first element is the cipher suite identifier (as used on the wire). + * The second element is the concatenation of four 4-bit elements which + * characterise the cipher suite contents. In most to least significant + * order, these 4-bit elements are: + * + * - Bits 12 to 15: key exchange + server key type + * + * | val | symbolic constant | suite type | details | + * | :-- | :----------------------- | :---------- | :----------------------------------------------- | + * | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) | + * | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) | + * | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) | + * | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA | + * | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA | + * + * - Bits 8 to 11: symmetric encryption algorithm + * + * | val | symbolic constant | symmetric encryption | key strength (bits) | + * | :-- | :--------------------- | :------------------- | :------------------ | + * | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 | + * | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 | + * | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 | + * | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 | + * | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 | + * | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 | + * + * - Bits 4 to 7: MAC algorithm + * + * | val | symbolic constant | MAC type | details | + * | :-- | :----------------- | :----------- | :------------------------------------ | + * | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) | + * | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` | + * | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` | + * + * - Bits 0 to 3: hash function for PRF when used with TLS-1.2 + * + * | val | symbolic constant | hash function | details | + * | :-- | :----------------- | :------------ | :----------------------------------- | + * | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` | + * + * For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has + * standard identifier 0x009C, and is translated to 0x0304, for, in + * that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0), + * SHA-256 in the TLS PRF (4). + */ +typedef uint16_t br_suite_translated[2]; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Constants are already documented in the br_suite_translated type. + */ + +#define BR_SSLKEYX_RSA 0 +#define BR_SSLKEYX_ECDHE_RSA 1 +#define BR_SSLKEYX_ECDHE_ECDSA 2 +#define BR_SSLKEYX_ECDH_RSA 3 +#define BR_SSLKEYX_ECDH_ECDSA 4 + +#define BR_SSLENC_3DES_CBC 0 +#define BR_SSLENC_AES128_CBC 1 +#define BR_SSLENC_AES256_CBC 2 +#define BR_SSLENC_AES128_GCM 3 +#define BR_SSLENC_AES256_GCM 4 +#define BR_SSLENC_CHACHA20 5 + +#define BR_SSLMAC_AEAD 0 +#define BR_SSLMAC_SHA1 br_sha1_ID +#define BR_SSLMAC_SHA256 br_sha256_ID +#define BR_SSLMAC_SHA384 br_sha384_ID + +#define BR_SSLPRF_SHA256 br_sha256_ID +#define BR_SSLPRF_SHA384 br_sha384_ID + +#endif + +/* + * Pre-declaration for the SSL server context. + */ +typedef struct br_ssl_server_context_ br_ssl_server_context; + +/** + * \brief Type for the server policy choices, taken after analysis of + * the client message (ClientHello). + */ +typedef struct { + /** + * \brief Cipher suite to use with that client. + */ + uint16_t cipher_suite; + + /** + * \brief Hash function or algorithm for signing the ServerKeyExchange. + * + * This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*` + * cipher suites; it is used only for `TLS_ECDHE_*` suites, in + * which the server _signs_ the ephemeral EC Diffie-Hellman + * parameters sent to the client. + * + * This identifier must be one of the following values: + * + * - `0xFF00 + id`, where `id` is a hash function identifier + * (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions); + * + * - a full 16-bit identifier, lower than `0xFF00`. + * + * If the first option is used, then the SSL engine will + * compute the hash of the data that is to be signed, with the + * designated hash function. The `do_sign()` method will be + * invoked with that hash value provided in the the `data` + * buffer. + * + * If the second option is used, then the SSL engine will NOT + * compute a hash on the data; instead, it will provide the + * to-be-signed data itself in `data`, i.e. the concatenation of + * the client random, server random, and encoded ECDH + * parameters. Furthermore, with TLS-1.2 and later, the 16-bit + * identifier will be used "as is" in the protocol, in the + * SignatureAndHashAlgorithm; for instance, `0x0401` stands for + * RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash + * function (the `04`). + * + * Take care that with TLS 1.0 and 1.1, the hash function is + * constrainted by the protocol: RSA signature must use + * MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1 + * (`0xFF02`). Since TLS 1.0 and 1.1 don't include a + * SignatureAndHashAlgorithm field in their ServerKeyExchange + * messages, any value below `0xFF00` will be usable to send the + * raw ServerKeyExchange data to the `do_sign()` callback, but + * that callback must still follow the protocol requirements + * when generating the signature. + */ + unsigned algo_id; + + /** + * \brief Certificate chain to send to the client. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The server + * code does not try to decode these elements. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + */ + size_t chain_len; + +} br_ssl_server_choices; + +/** + * \brief Class type for a policy handler (server side). + * + * A policy handler selects the policy parameters for a connection + * (cipher suite and other algorithms, and certificate chain to send to + * the client); it also performs the server-side computations involving + * its permanent private key. + * + * The SSL server engine will invoke first `choose()`, once the + * ClientHello message has been received, then either `do_keyx()` + * `do_sign()`, depending on the cipher suite. + */ +typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class; +struct br_ssl_server_policy_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Select algorithms and certificates for this connection. + * + * This callback function shall fill the provided `choices` + * structure with the policy choices for this connection. This + * entails selecting the cipher suite, hash function for signing + * the ServerKeyExchange (applicable only to ECDHE cipher suites), + * and certificate chain to send. + * + * The callback receives a pointer to the server context that + * contains the relevant data. In particular, the functions + * `br_ssl_server_get_client_suites()`, + * `br_ssl_server_get_client_hashes()` and + * `br_ssl_server_get_client_curves()` can be used to obtain + * the cipher suites, hash functions and elliptic curves + * supported by both the client and server, respectively. The + * `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()` + * functions yield the protocol version and requested server name + * (SNI), respectively. + * + * This function may modify its context structure (`pctx`) in + * arbitrary ways to keep track of its own choices. + * + * This function shall return 1 if appropriate policy choices + * could be made, or 0 if this connection cannot be pursued. + * + * \param pctx policy context. + * \param cc SSL server context. + * \param choices destination structure for the policy choices. + * \return 1 on success, 0 on error. + */ + int (*choose)(const br_ssl_server_policy_class **pctx, + const br_ssl_server_context *cc, + br_ssl_server_choices *choices); + + /** + * \brief Perform key exchange (server part). + * + * This callback is invoked to perform the server-side cryptographic + * operation for a key exchange that is not ECDHE. This callback + * uses the private key. + * + * **For RSA key exchange**, the provided `data` (of length `*len` + * bytes) shall be decrypted with the server's private key, and + * the 48-byte premaster secret copied back to the first 48 bytes + * of `data`. + * + * - The caller makes sure that `*len` is at least 59 bytes. + * + * - This callback MUST check that the provided length matches + * that of the key modulus; it shall report an error otherwise. + * + * - If the length matches that of the RSA key modulus, then + * processing MUST be constant-time, even if decryption fails, + * or the padding is incorrect, or the plaintext message length + * is not exactly 48 bytes. + * + * - This callback needs not check the two first bytes of the + * obtained pre-master secret (the caller will do that). + * + * - If an error is reported (0), then what the callback put + * in the first 48 bytes of `data` is unimportant (the caller + * will use random bytes instead). + * + * **For ECDH key exchange**, the provided `data` (of length `*len` + * bytes) is the elliptic curve point from the client. The + * callback shall multiply it with its private key, and store + * the resulting X coordinate in `data`, starting at offset 0, + * and set `*len` to the length of the X coordinate. + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx policy context. + * \param data key exchange data from the client. + * \param len key exchange data length (in bytes). + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (for a ServerKeyExchange message). + * + * This callback function is invoked for ECDHE cipher suites. On + * input, the hash value or message to sign is in `data`, of + * size `hv_len`; the involved hash function or algorithm is + * identified by `algo_id`. The signature shall be computed and + * written back into `data`; the total size of that buffer is + * `len` bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * The `algo_id` value matches that which was written in the + * `choices` structures by the `choose()` callback. This will be + * one of the following: + * + * - `0xFF00 + id` for a hash function identifier `id`. In + * that case, the `data` buffer contains a hash value + * already computed over the data that is to be signed, + * of length `hv_len`. The `id` may be 0 to designate the + * special MD5+SHA-1 concatenation (old-style RSA signing). + * + * - Another value, lower than `0xFF00`. The `data` buffer + * then contains the raw, non-hashed data to be signed + * (concatenation of the client and server randoms and + * ECDH parameters). The callback is responsible to apply + * any relevant hashing as part of the signing process. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx policy context. + * \param algo_id hash function / algorithm identifier. + * \param data input/output buffer (message/hash, then signature). + * \param hv_len hash value or message length (in bytes). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_server_policy_class **pctx, + unsigned algo_id, + unsigned char *data, size_t hv_len, size_t len); +}; + +/** + * \brief A single-chain RSA policy handler. + * + * This policy context uses a single certificate chain, and a RSA + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + unsigned allowed_usages; + br_rsa_private irsacore; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_server_policy_rsa_context; + +/** + * \brief A single-chain EC policy handler. + * + * This policy context uses a single certificate chain, and an EC + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Due to how TLS is defined, this context must be made aware whether + * the server certificate was itself signed with RSA or ECDSA. The code + * does not try to decode the certificate to obtain that information. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned cert_issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_server_policy_ec_context; + +/** + * \brief Class type for a session parameter cache. + * + * Session parameters are saved in the cache with `save()`, and + * retrieved with `load()`. The cache implementation can apply any + * storage and eviction strategy that it sees fit. The SSL server + * context that performs the request is provided, so that its + * functionalities may be used by the implementation (e.g. hash + * functions or random number generation). + */ +typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class; +struct br_ssl_session_cache_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Record a session. + * + * This callback should record the provided session parameters. + * The `params` structure is transient, so its contents shall + * be copied into the cache. The session ID has been randomly + * generated and always has length exactly 32 bytes. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params session parameters to save. + */ + void (*save)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + const br_ssl_session_parameters *params); + + /** + * \brief Lookup a session in the cache. + * + * The session ID to lookup is in `params` and always has length + * exactly 32 bytes. If the session parameters are found in the + * cache, then the parameters shall be copied into the `params` + * structure. Returned value is 1 on successful lookup, 0 + * otherwise. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params destination for session parameters. + * \return 1 if found, 0 otherwise. + */ + int (*load)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + br_ssl_session_parameters *params); +}; + +/** + * \brief Context for a basic cache system. + * + * The system stores session parameters in a buffer provided at + * initialisation time. Each entry uses exactly 100 bytes, and + * buffer sizes up to 4294967295 bytes are supported. + * + * Entries are evicted with a LRU (Least Recently Used) policy. A + * search tree is maintained to keep lookups fast even with large + * caches. + * + * Apart from the first field (vtable pointer), the structure + * contents are opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_session_cache_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char *store; + size_t store_len, store_ptr; + unsigned char index_key[32]; + const br_hash_class *hash; + int init_done; + uint32_t head, tail, root; +#endif +} br_ssl_session_cache_lru; + +/** + * \brief Initialise a LRU session cache with the provided storage space. + * + * The provided storage space must remain valid as long as the cache + * is used. Arbitrary lengths are supported, up to 4294967295 bytes; + * each entry uses up exactly 100 bytes. + * + * \param cc session cache context. + * \param store storage space for cached entries. + * \param store_len storage space length (in bytes). + */ +void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc, + unsigned char *store, size_t store_len); + +/** + * \brief Forget an entry in an LRU session cache. + * + * The session cache context must have been initialised. The entry + * with the provided session ID (of exactly 32 bytes) is looked for + * in the cache; if located, it is disabled. + * + * \param cc session cache context. + * \param id session ID to forget. + */ +void br_ssl_session_cache_lru_forget( + br_ssl_session_cache_lru *cc, const unsigned char *id); + +/** + * \brief Context structure for a SSL server. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_server_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Maximum version from the client. + */ + uint16_t client_max_version; + + /* + * Session cache. + */ + const br_ssl_session_cache_class **cache_vtable; + + /* + * Translated cipher suites supported by the client. The list + * is trimmed to include only the cipher suites that the + * server also supports; they are in the same order as in the + * client message. + */ + br_suite_translated client_suites[BR_MAX_CIPHER_SUITES]; + unsigned char client_suites_num; + + /* + * Hash functions supported by the client, with ECDSA and RSA + * (bit mask). For hash function with id 'x', set bit index is + * x for RSA, x+8 for ECDSA. For newer algorithms, with ID + * 0x08**, bit 16+k is set for algorithm 0x0800+k. + */ + uint32_t hashes; + + /* + * Curves supported by the client (bit mask, for named curves). + */ + uint32_t curves; + + /* + * Context for chain handler. + */ + const br_ssl_server_policy_class **policy_vtable; + uint16_t sign_hash_id; + + /* + * For the core handlers, thus avoiding (in most cases) the + * need for an externally provided policy context. + */ + union { + const br_ssl_server_policy_class *vtable; + br_ssl_server_policy_rsa_context single_rsa; + br_ssl_server_policy_ec_context single_ec; + } chain_handler; + + /* + * Buffer for the ECDHE private key. + */ + unsigned char ecdhe_key[70]; + size_t ecdhe_key_len; + + /* + * Trust anchor names for client authentication. "ta_names" and + * "tas" cannot be both non-NULL. + */ + const br_x500_name *ta_names; + const br_x509_trust_anchor *tas; + size_t num_tas; + size_t cur_dn_index; + const unsigned char *cur_dn; + size_t cur_dn_len; + + /* + * Buffer for the hash value computed over all handshake messages + * prior to CertificateVerify, and identifier for the hash function. + */ + unsigned char hash_CV[64]; + size_t hash_CV_len; + int hash_CV_id; + + /* + * Server-specific implementations. + * (none for now) + */ +#endif +}; + +/* + * Each br_ssl_server_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full_rsa all supported algorithm, server key type is RSA + * full_ec all supported algorithm, server key type is EC + * TODO: add other profiles + * + * Naming scheme for "minimal" profiles: min123 + * + * -- character 1: key exchange + * r = RSA + * e = ECDHE_RSA + * f = ECDHE_ECDSA + * u = ECDH_RSA + * v = ECDH_ECDSA + * -- character 2: version / PRF + * 0 = TLS 1.0 / 1.1 with MD5+SHA-1 + * 2 = TLS 1.2 with SHA-256 + * 3 = TLS 1.2 with SHA-384 + * -- character 3: encryption + * a = AES/CBC + * d = 3DES/CBC + * g = AES/GCM + * c = ChaCha20+Poly1305 + */ + +/** + * \brief SSL server profile: full_rsa. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on a RSA + * key pair. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_full_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: full_ec. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on an EC + * key pair. + * + * The key type of the CA that issued the server's certificate must + * be provided, since it matters for ECDH cipher suites (ECDH_RSA + * suites require a RSA-powered CA). The key type is either + * `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len chain length (number of certificates). + * \param cert_issuer_key_type certificate issuer's key type. + * \param sk EC private key. + */ +void br_ssl_server_init_full_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + unsigned cert_issuer_key_type, const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minr2g. + * + * This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is + * RSA, and RSA key exchange is used (not forward secure, but uses little + * CPU in the client). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_minr2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: mine2g. + * + * This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key + * is RSA, and ECDHE key exchange is used. This suite provides forward + * security, with a higher CPU expense on the client, and a somewhat + * larger code footprint (compared to "minr2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2g. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security, with a higher CPU expense on the client and server + * (by a factor of about 3 to 4), and a somewhat larger code footprint + * (compared to "minu2g" and "minv2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minu2g. + * + * This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * a RSA key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minu2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minv2g. + * + * This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * an EC key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minv2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: mine2c. + * + * This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is RSA, and ECDHE key exchange is used. This suite + * provides forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2c. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief Get the supported client suites. + * + * This function shall be called only after the ClientHello has been + * processed, typically from the policy engine. The returned array + * contains the cipher suites that are supported by both the client + * and the server; these suites are in client preference order, unless + * the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case + * they are in server preference order. + * + * The suites are _translated_, which means that each suite is given + * as two 16-bit integers: the standard suite identifier, and its + * translated version, broken down into its individual components, + * as explained with the `br_suite_translated` type. + * + * The returned array is allocated in the context and will be rewritten + * by each handshake. + * + * \param cc server context. + * \param num receives the array size (number of suites). + * \return the translated common cipher suites, in preference order. + */ +static __inline const br_suite_translated * +br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num) +{ + *num = cc->client_suites_num; + return cc->client_suites; +} + +/** + * \brief Get the hash functions and signature algorithms supported by + * the client. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc server context. + * \return the client-supported hash functions and signature algorithms. + */ +static __inline uint32_t +br_ssl_server_get_client_hashes(const br_ssl_server_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the elliptic curves supported by the client. + * + * This is a bit field (bit x is set if curve of ID x is supported). + * + * \param cc server context. + * \return the client-supported elliptic curves. + */ +static __inline uint32_t +br_ssl_server_get_client_curves(const br_ssl_server_context *cc) +{ + return cc->curves; +} + +/** + * \brief Clear the complete contents of a SSL server context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc server context to clear. + */ +void br_ssl_server_zero(br_ssl_server_context *cc); + +/** + * \brief Set an externally provided policy context. + * + * The policy context's methods are invoked to decide the cipher suite + * and certificate chain, and to perform operations involving the server's + * private key. + * + * \param cc server context. + * \param pctx policy context (pointer to its vtable field). + */ +static __inline void +br_ssl_server_set_policy(br_ssl_server_context *cc, + const br_ssl_server_policy_class **pctx) +{ + cc->policy_vtable = pctx; +} + +/** + * \brief Set the server certificate chain and key (single RSA case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with a RSA + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for + * key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures). + * + * \param cc server context. + * \param chain server certificate chain to send to the client. + * \param chain_len chain length (number of certificates). + * \param sk server private key (RSA). + * \param allowed_usages allowed private key usages. + * \param irsacore RSA core implementation. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_server_set_single_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, unsigned allowed_usages, + br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign); + +/** + * \brief Set the server certificate chain and key (single EC case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with an EC + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for + * key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures). + * + * In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH), + * the algorithm type of the key used by the issuing CA to sign the + * server's certificate must be provided, as `cert_issuer_key_type` + * parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`). + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_server_set_single_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Activate client certificate authentication. + * + * The trust anchor encoded X.500 names (DN) to send to the client are + * provided. A client certificate will be requested and validated through + * the X.509 validator configured in the SSL engine. If `num` is 0, then + * client certificate authentication is disabled. + * + * If the client does not send a certificate, or on validation failure, + * the handshake aborts. Unauthenticated clients can be tolerated by + * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param ta_names encoded trust anchor names. + * \param num number of encoded trust anchor names. + */ +static __inline void +br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc, + const br_x500_name *ta_names, size_t num) +{ + cc->ta_names = ta_names; + cc->tas = NULL; + cc->num_tas = num; +} + +/** + * \brief Activate client certificate authentication. + * + * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the + * trust anchor names are provided not as an array of stand-alone names + * (`br_x500_name` structures), but as an array of trust anchors + * (`br_x509_trust_anchor` structures). The server engine itself will + * only use the `dn` field of each trust anchor. This is meant to allow + * defining a single array of trust anchors, to be used here and in the + * X.509 validation engine itself. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param tas trust anchors (only names are used). + * \param num number of trust anchors. + */ +static __inline void +br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc, + const br_x509_trust_anchor *tas, size_t num) +{ + cc->ta_names = NULL; + cc->tas = tas; + cc->num_tas = num; +} + +/** + * \brief Configure the cache for session parameters. + * + * The cache context is provided as a pointer to its first field (vtable + * pointer). + * + * \param cc server context. + * \param vtable session cache context. + */ +static __inline void +br_ssl_server_set_cache(br_ssl_server_context *cc, + const br_ssl_session_cache_class **vtable) +{ + cc->cache_vtable = vtable; +} + +/** + * \brief Prepare or reset a server context for handling an incoming client. + * + * \param cc server context. + * \return 1 on success, 0 on error. + */ +int br_ssl_server_reset(br_ssl_server_context *cc); + +/* ===================================================================== */ + +/* + * Context for the simplified I/O context. The transport medium is accessed + * through the low_read() and low_write() callback functions, each with + * its own opaque context pointer. + * + * low_read() read some bytes, at most 'len' bytes, into data[]. The + * returned value is the number of read bytes, or -1 on error. + * The 'len' parameter is guaranteed never to exceed 20000, + * so the length always fits in an 'int' on all platforms. + * + * low_write() write up to 'len' bytes, to be read from data[]. The + * returned value is the number of written bytes, or -1 on + * error. The 'len' parameter is guaranteed never to exceed + * 20000, so the length always fits in an 'int' on all + * parameters. + * + * A socket closure (if the transport medium is a socket) should be reported + * as an error (-1). The callbacks shall endeavour to block until at least + * one byte can be read or written; a callback returning 0 at times is + * acceptable, but this normally leads to the callback being immediately + * called again, so the callback should at least always try to block for + * some time if no I/O can take place. + * + * The SSL engine naturally applies some buffering, so the callbacks need + * not apply buffers of their own. + */ +/** + * \brief Context structure for the simplified SSL I/O wrapper. + * + * This structure is initialised with `br_sslio_init()`. Its contents + * are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + br_ssl_engine_context *engine; + int (*low_read)(void *read_context, + unsigned char *data, size_t len); + void *read_context; + int (*low_write)(void *write_context, + const unsigned char *data, size_t len); + void *write_context; +#endif +} br_sslio_context; + +/** + * \brief Initialise a simplified I/O wrapper context. + * + * The simplified I/O wrapper offers a simpler read/write API for a SSL + * engine (client or server), using the provided callback functions for + * reading data from, or writing data to, the transport medium. + * + * The callback functions have the following semantics: + * + * - Each callback receives an opaque context value (of type `void *`) + * that the callback may use arbitrarily (or possibly ignore). + * + * - `low_read()` reads at least one byte, at most `len` bytes, from + * the transport medium. Read bytes shall be written in `data`. + * + * - `low_write()` writes at least one byte, at most `len` bytes, unto + * the transport medium. The bytes to write are read from `data`. + * + * - The `len` parameter is never zero, and is always lower than 20000. + * + * - The number of processed bytes (read or written) is returned. Since + * that number is less than 20000, it always fits on an `int`. + * + * - On error, the callbacks return -1. Reaching end-of-stream is an + * error. Errors are permanent: the SSL connection is terminated. + * + * - Callbacks SHOULD NOT return 0. This is tolerated, as long as + * callbacks endeavour to block for some non-negligible amount of + * time until at least one byte can be sent or received (if a + * callback returns 0, then the wrapper invokes it again + * immediately). + * + * - Callbacks MAY return as soon as at least one byte is processed; + * they MAY also insist on reading or writing _all_ requested bytes. + * Since SSL is a self-terminated protocol (each record has a length + * header), this does not change semantics. + * + * - Callbacks need not apply any buffering (for performance) since SSL + * itself uses buffers. + * + * \param ctx wrapper context to initialise. + * \param engine SSL engine to wrap. + * \param low_read callback for reading data from the transport. + * \param read_context context pointer for `low_read()`. + * \param low_write callback for writing data on the transport. + * \param write_context context pointer for `low_write()`. + */ +void br_sslio_init(br_sslio_context *ctx, + br_ssl_engine_context *engine, + int (*low_read)(void *read_context, + unsigned char *data, size_t len), + void *read_context, + int (*low_write)(void *write_context, + const unsigned char *data, size_t len), + void *write_context); + +/** + * \brief Read some application data from a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been obtained. + * Returned value is the number of bytes read, or -1 on error. The + * number of bytes always fits on an 'int' (data from a single SSL/TLS + * record is returned). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len maximum number of bytes to obtain. + * \return number of bytes obtained, or -1 on error. + */ +int br_sslio_read(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Read application data from a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes are read, + * or an error is reached. Returned value is 0 on success, -1 on error. + * A normal (verified) SSL closure before that many bytes are obtained + * is reported as an error by this function. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len number of bytes to obtain. + * \return 0 on success, or -1 on error. + */ +int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Write some application data unto a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been written. + * Returned value is the number of bytes written, or -1 on error. The + * number of bytes always fits on an 'int' (less than 20000). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len maximum number of bytes to write. + * \return number of bytes written, or -1 on error. + */ +int br_sslio_write(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Write application data unto a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes have been + * written, or an error is reached. Returned value is 0 on success, -1 + * on error. A normal (verified) SSL closure before that many bytes are + * written is reported as an error by this function. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len number of bytes to write. + * \return 0 on success, or -1 on error. + */ +int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Flush pending data. + * + * This call makes sure that any buffered application data in the + * provided context (including the wrapped SSL engine) has been sent + * to the transport medium (i.e. accepted by the `low_write()` callback + * method). If there is no such pending data, then this function does + * nothing (and returns a success, i.e. 0). + * + * If the underlying transport medium has its own buffers, then it is + * up to the caller to ensure the corresponding flushing. + * + * Returned value is 0 on success, -1 on error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_flush(br_sslio_context *cc); + +/** + * \brief Close the SSL connection. + * + * This call runs the SSL closure protocol (sending a `close_notify`, + * receiving the response `close_notify`). When it returns, the SSL + * connection is finished. It is still up to the caller to manage the + * possible transport-level termination, if applicable (alternatively, + * the underlying transport stream may be reused for non-SSL messages). + * + * Returned value is 0 on success, -1 on error. A failure by the peer + * to process the complete closure protocol (i.e. sending back the + * `close_notify`) is an error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_close(br_sslio_context *cc); + +/* ===================================================================== */ + +/* + * Symbolic constants for cipher suites. + */ + +/* From RFC 5246 */ +#define BR_TLS_NULL_WITH_NULL_NULL 0x0000 +#define BR_TLS_RSA_WITH_NULL_MD5 0x0001 +#define BR_TLS_RSA_WITH_NULL_SHA 0x0002 +#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B +#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004 +#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005 +#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D +#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D +#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 +#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 +#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B +#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018 +#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D + +/* From RFC 4492 */ +#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 +#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 +#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 +#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 +#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 +#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A +#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B +#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C +#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F +#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 +#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 +#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 +#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015 +#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016 +#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017 +#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 +#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 + +/* From RFC 5288 */ +#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C +#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D +#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E +#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F +#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0 +#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1 +#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2 +#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3 +#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4 +#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5 +#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6 +#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7 + +/* From RFC 5289 */ +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E +#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F +#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 +#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 +#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 + +/* From RFC 6655 and 7251 */ +#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C +#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D +#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 +#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF + +/* From RFC 7905 */ +#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 +#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 +#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA +#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB +#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC +#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD +#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE + +/* From RFC 7507 */ +#define BR_TLS_FALLBACK_SCSV 0x5600 + +/* + * Symbolic constants for alerts. + */ +#define BR_ALERT_CLOSE_NOTIFY 0 +#define BR_ALERT_UNEXPECTED_MESSAGE 10 +#define BR_ALERT_BAD_RECORD_MAC 20 +#define BR_ALERT_RECORD_OVERFLOW 22 +#define BR_ALERT_DECOMPRESSION_FAILURE 30 +#define BR_ALERT_HANDSHAKE_FAILURE 40 +#define BR_ALERT_BAD_CERTIFICATE 42 +#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43 +#define BR_ALERT_CERTIFICATE_REVOKED 44 +#define BR_ALERT_CERTIFICATE_EXPIRED 45 +#define BR_ALERT_CERTIFICATE_UNKNOWN 46 +#define BR_ALERT_ILLEGAL_PARAMETER 47 +#define BR_ALERT_UNKNOWN_CA 48 +#define BR_ALERT_ACCESS_DENIED 49 +#define BR_ALERT_DECODE_ERROR 50 +#define BR_ALERT_DECRYPT_ERROR 51 +#define BR_ALERT_PROTOCOL_VERSION 70 +#define BR_ALERT_INSUFFICIENT_SECURITY 71 +#define BR_ALERT_INTERNAL_ERROR 80 +#define BR_ALERT_USER_CANCELED 90 +#define BR_ALERT_NO_RENEGOTIATION 100 +#define BR_ALERT_UNSUPPORTED_EXTENSION 110 +#define BR_ALERT_NO_APPLICATION_PROTOCOL 120 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/inc/bearssl_x509.h b/BearSSL-OG/libbearssl/inc/bearssl_x509.h new file mode 100644 index 0000000..f19624a --- /dev/null +++ b/BearSSL-OG/libbearssl/inc/bearssl_x509.h @@ -0,0 +1,1474 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_X509_H__ +#define BR_BEARSSL_X509_H__ + +#include +#include + +#include "bearssl_ec.h" +#include "bearssl_hash.h" +#include "bearssl_rsa.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_x509.h + * + * # X.509 Certificate Chain Processing + * + * An X.509 processing engine receives an X.509 chain, chunk by chunk, + * as received from a SSL/TLS client or server (the client receives the + * server's certificate chain, and the server receives the client's + * certificate chain if it requested a client certificate). The chain + * is thus injected in the engine in SSL order (end-entity first). + * + * The engine's job is to return the public key to use for SSL/TLS. + * How exactly that key is obtained and verified is entirely up to the + * engine. + * + * **The "known key" engine** returns a public key which is already known + * from out-of-band information (e.g. the client _remembers_ the key from + * a previous connection, as in the usual SSH model). This is the simplest + * engine since it simply ignores the chain, thereby avoiding the need + * for any decoding logic. + * + * **The "minimal" engine** implements minimal X.509 decoding and chain + * validation: + * + * - The provided chain should validate "as is". There is no attempt + * at reordering, skipping or downloading extra certificates. + * + * - X.509 v1, v2 and v3 certificates are supported. + * + * - Trust anchors are a DN and a public key. Each anchor is either a + * "CA" anchor, or a non-CA. + * + * - If the end-entity certificate matches a non-CA anchor (subject DN + * is equal to the non-CA name, and public key is also identical to + * the anchor key), then this is a _direct trust_ case and the + * remaining certificates are ignored. + * + * - Unless direct trust is applied, the chain must be verifiable up to + * a certificate whose issuer DN matches the DN from a "CA" trust anchor, + * and whose signature is verifiable against that anchor's public key. + * Subsequent certificates in the chain are ignored. + * + * - The engine verifies subject/issuer DN matching, and enforces + * processing of Basic Constraints and Key Usage extensions. The + * Authority Key Identifier, Subject Key Identifier, Issuer Alt Name, + * Subject Directory Attribute, CRL Distribution Points, Freshest CRL, + * Authority Info Access and Subject Info Access extensions are + * ignored. The Subject Alt Name is decoded for the end-entity + * certificate under some conditions (see below). Other extensions + * are ignored if non-critical, or imply chain rejection if critical. + * + * - The Subject Alt Name extension is parsed for names of type `dNSName` + * when decoding the end-entity certificate, and only if there is a + * server name to match. If there is no SAN extension, then the + * Common Name from the subjectDN is used. That name matching is + * case-insensitive and honours a single starting wildcard (i.e. if + * the name in the certificate starts with "`*.`" then this matches + * any word as first element). Note: this name matching is performed + * also in the "direct trust" model. + * + * - DN matching is byte-to-byte equality (a future version might + * include some limited processing for case-insensitive matching and + * whitespace normalisation). + * + * - Successful validation produces a public key type but also a set + * of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * The caller is responsible for checking that the key type and + * usages are compatible with the expected values (e.g. with the + * selected cipher suite, when the client validates the server's + * certificate). + * + * **Important caveats:** + * + * - The "minimal" engine does not check revocation status. The relevant + * extensions are ignored, and CRL or OCSP responses are not gathered + * or checked. + * + * - The "minimal" engine does not currently support Name Constraints + * (some basic functionality to handle sub-domains may be added in a + * later version). + * + * - The decoder is not "validating" in the sense that it won't reject + * some certificates with invalid field values when these fields are + * not actually processed. + */ + +/* + * X.509 error codes are in the 32..63 range. + */ + +/** \brief X.509 status: validation was successful; this is not actually + an error. */ +#define BR_ERR_X509_OK 32 + +/** \brief X.509 status: invalid value in an ASN.1 structure. */ +#define BR_ERR_X509_INVALID_VALUE 33 + +/** \brief X.509 status: truncated certificate. */ +#define BR_ERR_X509_TRUNCATED 34 + +/** \brief X.509 status: empty certificate chain (no certificate at all). */ +#define BR_ERR_X509_EMPTY_CHAIN 35 + +/** \brief X.509 status: decoding error: inner element extends beyond + outer element size. */ +#define BR_ERR_X509_INNER_TRUNC 36 + +/** \brief X.509 status: decoding error: unsupported tag class (application + or private). */ +#define BR_ERR_X509_BAD_TAG_CLASS 37 + +/** \brief X.509 status: decoding error: unsupported tag value. */ +#define BR_ERR_X509_BAD_TAG_VALUE 38 + +/** \brief X.509 status: decoding error: indefinite length. */ +#define BR_ERR_X509_INDEFINITE_LENGTH 39 + +/** \brief X.509 status: decoding error: extraneous element. */ +#define BR_ERR_X509_EXTRA_ELEMENT 40 + +/** \brief X.509 status: decoding error: unexpected element. */ +#define BR_ERR_X509_UNEXPECTED 41 + +/** \brief X.509 status: decoding error: expected constructed element, but + is primitive. */ +#define BR_ERR_X509_NOT_CONSTRUCTED 42 + +/** \brief X.509 status: decoding error: expected primitive element, but + is constructed. */ +#define BR_ERR_X509_NOT_PRIMITIVE 43 + +/** \brief X.509 status: decoding error: BIT STRING length is not multiple + of 8. */ +#define BR_ERR_X509_PARTIAL_BYTE 44 + +/** \brief X.509 status: decoding error: BOOLEAN value has invalid length. */ +#define BR_ERR_X509_BAD_BOOLEAN 45 + +/** \brief X.509 status: decoding error: value is off-limits. */ +#define BR_ERR_X509_OVERFLOW 46 + +/** \brief X.509 status: invalid distinguished name. */ +#define BR_ERR_X509_BAD_DN 47 + +/** \brief X.509 status: invalid date/time representation. */ +#define BR_ERR_X509_BAD_TIME 48 + +/** \brief X.509 status: certificate contains unsupported features that + cannot be ignored. */ +#define BR_ERR_X509_UNSUPPORTED 49 + +/** \brief X.509 status: key or signature size exceeds internal limits. */ +#define BR_ERR_X509_LIMIT_EXCEEDED 50 + +/** \brief X.509 status: key type does not match that which was expected. */ +#define BR_ERR_X509_WRONG_KEY_TYPE 51 + +/** \brief X.509 status: signature is invalid. */ +#define BR_ERR_X509_BAD_SIGNATURE 52 + +/** \brief X.509 status: validation time is unknown. */ +#define BR_ERR_X509_TIME_UNKNOWN 53 + +/** \brief X.509 status: certificate is expired or not yet valid. */ +#define BR_ERR_X509_EXPIRED 54 + +/** \brief X.509 status: issuer/subject DN mismatch in the chain. */ +#define BR_ERR_X509_DN_MISMATCH 55 + +/** \brief X.509 status: expected server name was not found in the chain. */ +#define BR_ERR_X509_BAD_SERVER_NAME 56 + +/** \brief X.509 status: unknown critical extension in certificate. */ +#define BR_ERR_X509_CRITICAL_EXTENSION 57 + +/** \brief X.509 status: not a CA, or path length constraint violation */ +#define BR_ERR_X509_NOT_CA 58 + +/** \brief X.509 status: Key Usage extension prohibits intended usage. */ +#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59 + +/** \brief X.509 status: public key found in certificate is too small. */ +#define BR_ERR_X509_WEAK_PUBLIC_KEY 60 + +/** \brief X.509 status: chain could not be linked to a trust anchor. */ +#define BR_ERR_X509_NOT_TRUSTED 62 + +/** + * \brief Aggregate structure for public keys. + */ +typedef struct { + /** \brief Key type: `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC` */ + unsigned char key_type; + /** \brief Actual public key. */ + union { + /** \brief RSA public key. */ + br_rsa_public_key rsa; + /** \brief EC public key. */ + br_ec_public_key ec; + } key; +} br_x509_pkey; + +/** + * \brief Distinguished Name (X.500) structure. + * + * The DN is DER-encoded. + */ +typedef struct { + /** \brief Encoded DN data. */ + unsigned char *data; + /** \brief Encoded DN length (in bytes). */ + size_t len; +} br_x500_name; + +/** + * \brief Trust anchor structure. + */ +typedef struct { + /** \brief Encoded DN (X.500 name). */ + br_x500_name dn; + /** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */ + unsigned flags; + /** \brief Anchor public key. */ + br_x509_pkey pkey; +} br_x509_trust_anchor; + +/** + * \brief Trust anchor flag: CA. + * + * A "CA" anchor is deemed fit to verify signatures on certificates. + * A "non-CA" anchor is accepted only for direct trust (server's + * certificate name and key match the anchor). + */ +#define BR_X509_TA_CA 0x0001 + +/* + * Key type: combination of a basic key type (low 4 bits) and some + * optional flags. + * + * For a public key, the basic key type only is set. + * + * For an expected key type, the flags indicate the intended purpose(s) + * for the key; the basic key type may be set to 0 to indicate that any + * key type compatible with the indicated purpose is acceptable. + */ +/** \brief Key type: algorithm is RSA. */ +#define BR_KEYTYPE_RSA 1 +/** \brief Key type: algorithm is EC. */ +#define BR_KEYTYPE_EC 2 + +/** + * \brief Key type: usage is "key exchange". + * + * This value is combined (with bitwise OR) with the algorithm + * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 + * validation engine that it should find a public key of that type, + * fit for key exchanges (e.g. `TLS_RSA_*` and `TLS_ECDH_*` cipher + * suites). + */ +#define BR_KEYTYPE_KEYX 0x10 + +/** + * \brief Key type: usage is "signature". + * + * This value is combined (with bitwise OR) with the algorithm + * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 + * validation engine that it should find a public key of that type, + * fit for signatures (e.g. `TLS_ECDHE_*` cipher suites). + */ +#define BR_KEYTYPE_SIGN 0x20 + +/* + * start_chain Called when a new chain is started. If 'server_name' + * is not NULL and non-empty, then it is a name that + * should be looked for in the EE certificate (in the + * SAN extension as dNSName, or in the subjectDN's CN + * if there is no SAN extension). + * The caller ensures that the provided 'server_name' + * pointer remains valid throughout validation. + * + * start_cert Begins a new certificate in the chain. The provided + * length is in bytes; this is the total certificate length. + * + * append Get some additional bytes for the current certificate. + * + * end_cert Ends the current certificate. + * + * end_chain Called at the end of the chain. Returned value is + * 0 on success, or a non-zero error code. + * + * get_pkey Returns the EE certificate public key. + * + * For a complete chain, start_chain() and end_chain() are always + * called. For each certificate, start_cert(), some append() calls, then + * end_cert() are called, in that order. There may be no append() call + * at all if the certificate is empty (which is not valid but may happen + * if the peer sends exactly that). + * + * get_pkey() shall return a pointer to a structure that is valid as + * long as a new chain is not started. This may be a sub-structure + * within the context for the engine. This function MAY return a valid + * pointer to a public key even in some cases of validation failure, + * depending on the validation engine. + */ + +/** + * \brief Class type for an X.509 engine. + * + * A certificate chain validation uses a caller-allocated context, which + * contains the running state for that validation. Methods are called + * in due order: + * + * - `start_chain()` is called at the start of the validation. + * - Certificates are processed one by one, in SSL order (end-entity + * comes first). For each certificate, the following methods are + * called: + * + * - `start_cert()` at the beginning of the certificate. + * - `append()` is called zero, one or more times, to provide + * the certificate (possibly in chunks). + * - `end_cert()` at the end of the certificate. + * + * - `end_chain()` is called when the last certificate in the chain + * was processed. + * - `get_pkey()` is called after chain processing, if the chain + * validation was successful. + * + * A context structure may be reused; the `start_chain()` method shall + * ensure (re)initialisation. + */ +typedef struct br_x509_class_ br_x509_class; +struct br_x509_class_ { + /** + * \brief X.509 context size, in bytes. + */ + size_t context_size; + + /** + * \brief Start a new chain. + * + * This method shall set the vtable (first field) of the context + * structure. + * + * The `server_name`, if not `NULL`, will be considered as a + * fully qualified domain name, to be matched against the `dNSName` + * elements of the end-entity certificate's SAN extension (if there + * is no SAN, then the Common Name from the subjectDN will be used). + * If `server_name` is `NULL` then no such matching is performed. + * + * \param ctx validation context. + * \param server_name server name to match (or `NULL`). + */ + void (*start_chain)(const br_x509_class **ctx, + const char *server_name); + + /** + * \brief Start a new certificate. + * + * \param ctx validation context. + * \param length new certificate length (in bytes). + */ + void (*start_cert)(const br_x509_class **ctx, uint32_t length); + + /** + * \brief Receive some bytes for the current certificate. + * + * This function may be called several times in succession for + * a given certificate. The caller guarantees that for each + * call, `len` is not zero, and the sum of all chunk lengths + * for a certificate matches the total certificate length which + * was provided in the previous `start_cert()` call. + * + * If the new certificate is empty (no byte at all) then this + * function won't be called at all. + * + * \param ctx validation context. + * \param buf certificate data chunk. + * \param len certificate data chunk length (in bytes). + */ + void (*append)(const br_x509_class **ctx, + const unsigned char *buf, size_t len); + + /** + * \brief Finish the current certificate. + * + * This function is called when the end of the current certificate + * is reached. + * + * \param ctx validation context. + */ + void (*end_cert)(const br_x509_class **ctx); + + /** + * \brief Finish the chain. + * + * This function is called at the end of the chain. It shall + * return either 0 if the validation was successful, or a + * non-zero error code. The `BR_ERR_X509_*` constants are + * error codes, though other values may be possible. + * + * \param ctx validation context. + * \return 0 on success, or a non-zero error code. + */ + unsigned (*end_chain)(const br_x509_class **ctx); + + /** + * \brief Get the resulting end-entity public key. + * + * The decoded public key is returned. The returned pointer + * may be valid only as long as the context structure is + * unmodified, i.e. it may cease to be valid if the context + * is released or reused. + * + * This function _may_ return `NULL` if the validation failed. + * However, returning a public key does not mean that the + * validation was wholly successful; some engines may return + * a decoded public key even if the chain did not end on a + * trusted anchor. + * + * If validation succeeded and `usage` is not `NULL`, then + * `*usage` is filled with a combination of `BR_KEYTYPE_SIGN` + * and/or `BR_KEYTYPE_KEYX` that specifies the validated key + * usage types. It is the caller's responsibility to check + * that value against the intended use of the public key. + * + * \param ctx validation context. + * \return the end-entity public key, or `NULL`. + */ + const br_x509_pkey *(*get_pkey)( + const br_x509_class *const *ctx, unsigned *usages); +}; + +/** + * \brief The "known key" X.509 engine structure. + * + * The structure contents are opaque (they shall not be accessed directly), + * except for the first field (the vtable). + * + * The "known key" engine returns an externally configured public key, + * and totally ignores the certificate contents. + */ +typedef struct { + /** \brief Reference to the context vtable. */ + const br_x509_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + br_x509_pkey pkey; + unsigned usages; +#endif +} br_x509_knownkey_context; + +/** + * \brief Class instance for the "known key" X.509 engine. + */ +extern const br_x509_class br_x509_knownkey_vtable; + +/** + * \brief Initialize a "known key" X.509 engine with a known RSA public key. + * + * The `usages` parameter indicates the allowed key usages for that key + * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * + * The provided pointers are linked in, not copied, so they must remain + * valid while the public key may be in usage. + * + * \param ctx context to initialise. + * \param pk known public key. + * \param usages allowed key usages. + */ +void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx, + const br_rsa_public_key *pk, unsigned usages); + +/** + * \brief Initialize a "known key" X.509 engine with a known EC public key. + * + * The `usages` parameter indicates the allowed key usages for that key + * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * + * The provided pointers are linked in, not copied, so they must remain + * valid while the public key may be in usage. + * + * \param ctx context to initialise. + * \param pk known public key. + * \param usages allowed key usages. + */ +void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx, + const br_ec_public_key *pk, unsigned usages); + +#ifndef BR_DOXYGEN_IGNORE +/* + * The minimal X.509 engine has some state buffers which must be large + * enough to simultaneously accommodate: + * -- the public key extracted from the current certificate; + * -- the signature on the current certificate or on the previous + * certificate; + * -- the public key extracted from the EE certificate. + * + * We store public key elements in their raw unsigned big-endian + * encoding. We want to support up to RSA-4096 with a short (up to 64 + * bits) public exponent, thus a buffer for a public key must have + * length at least 520 bytes. Similarly, a RSA-4096 signature has length + * 512 bytes. + * + * Though RSA public exponents can formally be as large as the modulus + * (mathematically, even larger exponents would work, but PKCS#1 forbids + * them), exponents that do not fit on 32 bits are extremely rare, + * notably because some widespread implementations (e.g. Microsoft's + * CryptoAPI) don't support them. Moreover, large public exponent do not + * seem to imply any tangible security benefit, and they increase the + * cost of public key operations. The X.509 "minimal" engine will tolerate + * public exponents of arbitrary size as long as the modulus and the + * exponent can fit together in the dedicated buffer. + * + * EC public keys are shorter than RSA public keys; even with curve + * NIST P-521 (the largest curve we care to support), a public key is + * encoded over 133 bytes only. + */ +#define BR_X509_BUFSIZE_KEY 520 +#define BR_X509_BUFSIZE_SIG 512 +#endif + +/** + * \brief Type for receiving a name element. + * + * An array of such structures can be provided to the X.509 decoding + * engines. If the specified elements are found in the certificate + * subject DN or the SAN extension, then the name contents are copied + * as zero-terminated strings into the buffer. + * + * The decoder converts TeletexString and BMPString to UTF8String, and + * ensures that the resulting string is zero-terminated. If the string + * does not fit in the provided buffer, then the copy is aborted and an + * error is reported. + */ +typedef struct { + /** + * \brief Element OID. + * + * For X.500 name elements (to be extracted from the subject DN), + * this is the encoded OID for the requested name element; the + * first byte shall contain the length of the DER-encoded OID + * value, followed by the OID value (for instance, OID 2.5.4.3, + * for id-at-commonName, will be `03 55 04 03`). This is + * equivalent to full DER encoding with the length but without + * the tag. + * + * For SAN name elements, the first byte (`oid[0]`) has value 0, + * followed by another byte that matches the expected GeneralName + * tag. Allowed second byte values are then: + * + * - 1: `rfc822Name` + * + * - 2: `dNSName` + * + * - 6: `uniformResourceIdentifier` + * + * - 0: `otherName` + * + * If first and second byte are 0, then this is a SAN element of + * type `otherName`; the `oid[]` array should then contain, right + * after the two bytes of value 0, an encoded OID (with the same + * conventions as for X.500 name elements). If a match is found + * for that OID, then the corresponding name element will be + * extracted, as long as it is a supported string type. + */ + const unsigned char *oid; + + /** + * \brief Destination buffer. + */ + char *buf; + + /** + * \brief Length (in bytes) of the destination buffer. + * + * The buffer MUST NOT be smaller than 1 byte. + */ + size_t len; + + /** + * \brief Decoding status. + * + * Status is 0 if the name element was not found, 1 if it was + * found and decoded, or -1 on error. Error conditions include + * an unrecognised encoding, an invalid encoding, or a string + * too large for the destination buffer. + */ + int status; + +} br_name_element; + +/** + * \brief Callback for validity date checks. + * + * The function receives as parameter an arbitrary user-provided context, + * and the notBefore and notAfter dates specified in an X.509 certificate, + * both expressed as a number of days and a number of seconds: + * + * - Days are counted in a proleptic Gregorian calendar since + * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; + * it is also traditionally known as "1 BC". + * + * - Seconds are counted since midnight, from 0 to 86400 (a count of + * 86400 is possible only if a leap second happened). + * + * Each date and time is understood in the UTC time zone. The "Unix + * Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 and + * seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is + * days=584754, seconds=0. + * + * This function must return -1 if the current date is strictly before + * the "notBefore" time, or +1 if the current date is strictly after the + * "notAfter" time. If neither condition holds, then the function returns + * 0, which means that the current date falls within the validity range of + * the certificate. If the function returns a value distinct from -1, 0 + * and +1, then this is interpreted as an unavailability of the current + * time, which normally ends the validation process with a + * `BR_ERR_X509_TIME_UNKNOWN` error. + * + * During path validation, this callback will be invoked for each + * considered X.509 certificate. Validation fails if any of the calls + * returns a non-zero value. + * + * The context value is an abritrary pointer set by the caller when + * configuring this callback. + * + * \param tctx context pointer. + * \param not_before_days notBefore date (days since Jan 1st, 0 AD). + * \param not_before_seconds notBefore time (seconds, at most 86400). + * \param not_after_days notAfter date (days since Jan 1st, 0 AD). + * \param not_after_seconds notAfter time (seconds, at most 86400). + * \return -1, 0 or +1. + */ +typedef int (*br_x509_time_check)(void *tctx, + uint32_t not_before_days, uint32_t not_before_seconds, + uint32_t not_after_days, uint32_t not_after_seconds); + +/** + * \brief The "minimal" X.509 engine structure. + * + * The structure contents are opaque (they shall not be accessed directly), + * except for the first field (the vtable). + * + * The "minimal" engine performs a rudimentary but serviceable X.509 path + * validation. + */ +typedef struct { + const br_x509_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the EE public key. */ + br_x509_pkey pkey; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[31]; + uint32_t rp_stack[31]; + int err; + + /* Server name to match with the SAN / CN of the EE certificate. */ + const char *server_name; + + /* Validated key usages. */ + unsigned char key_usages; + + /* Explicitly set date and time. */ + uint32_t days, seconds; + + /* Current certificate length (in bytes). Set to 0 when the + certificate has been fully processed. */ + uint32_t cert_length; + + /* Number of certificates processed so far in the current chain. + It is incremented at the end of the processing of a certificate, + so it is 0 for the EE. */ + uint32_t num_certs; + + /* Certificate data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Buffer for EE public key data. */ + unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Buffer for currently decoded public key. */ + unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Signature type: signer key type, offset to the hash + function OID (in the T0 data block) and hash function + output length (TBS hash length). */ + unsigned char cert_signer_key_type; + uint16_t cert_sig_hash_oid; + unsigned char cert_sig_hash_len; + + /* Current/last certificate signature. */ + unsigned char cert_sig[BR_X509_BUFSIZE_SIG]; + uint16_t cert_sig_len; + + /* Minimum RSA key length (difference in bytes from 128). */ + int16_t min_rsa_size; + + /* Configured trust anchors. */ + const br_x509_trust_anchor *trust_anchors; + size_t trust_anchors_num; + + /* + * Multi-hasher for the TBS. + */ + unsigned char do_mhash; + br_multihash_context mhash; + unsigned char tbs_hash[64]; + + /* + * Simple hasher for the subject/issuer DN. + */ + unsigned char do_dn_hash; + const br_hash_class *dn_hash_impl; + br_hash_compat_context dn_hash; + unsigned char current_dn_hash[64]; + unsigned char next_dn_hash[64]; + unsigned char saved_dn_hash[64]; + + /* + * Name elements to gather. + */ + br_name_element *name_elts; + size_t num_name_elts; + + /* + * Callback function (and context) to get the current date. + */ + void *itime_ctx; + br_x509_time_check itime; + + /* + * Public key cryptography implementations (signature verification). + */ + br_rsa_pkcs1_vrfy irsa; + br_ecdsa_vrfy iecdsa; + const br_ec_impl *iec; +#endif + +} br_x509_minimal_context; + +/** + * \brief Class instance for the "minimal" X.509 engine. + */ +extern const br_x509_class br_x509_minimal_vtable; + +/** + * \brief Initialise a "minimal" X.509 engine. + * + * The `dn_hash_impl` parameter shall be a hash function internally used + * to match X.500 names (subject/issuer DN, and anchor names). Any standard + * hash function may be used, but a collision-resistant hash function is + * advised. + * + * After initialization, some implementations for signature verification + * (hash functions and signature algorithms) MUST be added. + * + * \param ctx context to initialise. + * \param dn_hash_impl hash function for DN comparisons. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init(br_x509_minimal_context *ctx, + const br_hash_class *dn_hash_impl, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Set a supported hash function in an X.509 "minimal" engine. + * + * Hash functions are used with signature verification algorithms. + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the hash functions it shall support for that + * purpose. The hash function identifier MUST be one of the standard + * hash function identifiers (1 to 6, for MD5, SHA-1, SHA-224, SHA-256, + * SHA-384 and SHA-512). + * + * If `impl` is `NULL`, this _removes_ support for the designated + * hash function. + * + * \param ctx validation context. + * \param id hash function identifier (from 1 to 6). + * \param impl hash function implementation (or `NULL`). + */ +static __inline void +br_x509_minimal_set_hash(br_x509_minimal_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Set a RSA signature verification implementation in the X.509 + * "minimal" engine. + * + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the signature verification implementations that + * it is supposed to support. If `irsa` is `0`, then the RSA support + * is disabled. + * + * \param ctx validation context. + * \param irsa RSA signature verification implementation (or `0`). + */ +static __inline void +br_x509_minimal_set_rsa(br_x509_minimal_context *ctx, + br_rsa_pkcs1_vrfy irsa) +{ + ctx->irsa = irsa; +} + +/** + * \brief Set a ECDSA signature verification implementation in the X.509 + * "minimal" engine. + * + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the signature verification implementations that + * it is supposed to support. + * + * If `iecdsa` is `0`, then this call disables ECDSA support; in that + * case, `iec` may be `NULL`. Otherwise, `iecdsa` MUST point to a function + * that verifies ECDSA signatures with format "asn1", and it will use + * `iec` as underlying elliptic curve support. + * + * \param ctx validation context. + * \param iec elliptic curve implementation (or `NULL`). + * \param iecdsa ECDSA implementation (or `0`). + */ +static __inline void +br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx, + const br_ec_impl *iec, br_ecdsa_vrfy iecdsa) +{ + ctx->iecdsa = iecdsa; + ctx->iec = iec; +} + +/** + * \brief Initialise a "minimal" X.509 engine with default algorithms. + * + * This function performs the same job as `br_x509_minimal_init()`, but + * also sets implementations for RSA, ECDSA, and the standard hash + * functions. + * + * \param ctx context to initialise. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init_full(br_x509_minimal_context *ctx, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Set the validation time for the X.509 "minimal" engine. + * + * The validation time is set as two 32-bit integers, for days and + * seconds since a fixed epoch: + * + * - Days are counted in a proleptic Gregorian calendar since + * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; + * it is also traditionally known as "1 BC". + * + * - Seconds are counted since midnight, from 0 to 86400 (a count of + * 86400 is possible only if a leap second happened). + * + * The validation date and time is understood in the UTC time zone. The + * "Unix Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 + * and seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is + * days=584754, seconds=0. + * + * If the validation date and time are not explicitly set, but BearSSL + * was compiled with support for the system clock on the underlying + * platform, then the current time will automatically be used. Otherwise, + * not setting the validation date and time implies a validation + * failure (except in case of direct trust of the EE key). + * + * \param ctx validation context. + * \param days days since January 1st, 0 AD (Gregorian calendar). + * \param seconds seconds since midnight (0 to 86400). + */ +static __inline void +br_x509_minimal_set_time(br_x509_minimal_context *ctx, + uint32_t days, uint32_t seconds) +{ + ctx->days = days; + ctx->seconds = seconds; + ctx->itime = 0; +} + +/** + * \brief Set the validity range callback function for the X.509 + * "minimal" engine. + * + * The provided function will be invoked to check whether the validation + * date is within the validity range for a given X.509 certificate; a + * call will be issued for each considered certificate. The provided + * context pointer (itime_ctx) will be passed as first parameter to the + * callback. + * + * \param tctx context for callback invocation. + * \param cb callback function. + */ +static __inline void +br_x509_minimal_set_time_callback(br_x509_minimal_context *ctx, + void *itime_ctx, br_x509_time_check itime) +{ + ctx->itime_ctx = itime_ctx; + ctx->itime = itime; +} + +/** + * \brief Set the minimal acceptable length for RSA keys (X.509 "minimal" + * engine). + * + * The RSA key length is expressed in bytes. The default minimum key + * length is 128 bytes, corresponding to 1017 bits. RSA keys shorter + * than the configured length will be rejected, implying validation + * failure. This setting applies to keys extracted from certificates + * (both end-entity, and intermediate CA) but not to "CA" trust anchors. + * + * \param ctx validation context. + * \param byte_length minimum RSA key length, **in bytes** (not bits). + */ +static __inline void +br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length) +{ + ctx->min_rsa_size = (int16_t)(byte_length - 128); +} + +/** + * \brief Set the name elements to gather. + * + * The provided array is linked in the context. The elements are + * gathered from the EE certificate. If the same element type is + * requested several times, then the relevant structures will be filled + * in the order the matching values are encountered in the certificate. + * + * \param ctx validation context. + * \param elts array of name element structures to fill. + * \param num_elts number of name element structures to fill. + */ +static __inline void +br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx, + br_name_element *elts, size_t num_elts) +{ + ctx->name_elts = elts; + ctx->num_name_elts = num_elts; +} + +/** + * \brief X.509 decoder context. + * + * This structure is _not_ for X.509 validation, but for extracting + * names and public keys from encoded certificates. Intended usage is + * to use (self-signed) certificates as trust anchors. + * + * Contents are opaque and shall not be accessed directly. + */ +typedef struct { + +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the public key. */ + br_x509_pkey pkey; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Flag set when decoding succeeds. */ + unsigned char decoded; + + /* Validity dates. */ + uint32_t notbefore_days, notbefore_seconds; + uint32_t notafter_days, notafter_seconds; + + /* The "CA" flag. This is set to true if the certificate contains + a Basic Constraints extension that asserts CA status. */ + unsigned char isCA; + + /* DN processing: the subject DN is extracted and pushed to the + provided callback. */ + unsigned char copy_dn; + void *append_dn_ctx; + void (*append_dn)(void *ctx, const void *buf, size_t len); + + /* Certificate data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* Buffer for decoded public key. */ + unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Type of key and hash function used in the certificate signature. */ + unsigned char signer_key_type; + unsigned char signer_hash_id; +#endif + +} br_x509_decoder_context; + +/** + * \brief Initialise an X.509 decoder context for processing a new + * certificate. + * + * The `append_dn()` callback (with opaque context `append_dn_ctx`) + * will be invoked to receive, chunk by chunk, the certificate's + * subject DN. If `append_dn` is `0` then the subject DN will be + * ignored. + * + * \param ctx X.509 decoder context to initialise. + * \param append_dn DN receiver callback (or `0`). + * \param append_dn_ctx context for the DN receiver callback. + */ +void br_x509_decoder_init(br_x509_decoder_context *ctx, + void (*append_dn)(void *ctx, const void *buf, size_t len), + void *append_dn_ctx); + +/** + * \brief Push some certificate bytes into a decoder context. + * + * If `len` is non-zero, then that many bytes are pushed, from address + * `data`, into the provided decoder context. + * + * \param ctx X.509 decoder context. + * \param data certificate data chunk. + * \param len certificate data chunk length (in bytes). + */ +void br_x509_decoder_push(br_x509_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Obtain the decoded public key. + * + * Returned value is a pointer to a structure internal to the decoder + * context; releasing or reusing the decoder context invalidates that + * structure. + * + * If decoding was not finished, or failed, then `NULL` is returned. + * + * \param ctx X.509 decoder context. + * \return the public key, or `NULL` on unfinished/error. + */ +static __inline br_x509_pkey * +br_x509_decoder_get_pkey(br_x509_decoder_context *ctx) +{ + if (ctx->decoded && ctx->err == 0) { + return &ctx->pkey; + } else { + return NULL; + } +} + +/** + * \brief Get decoder error status. + * + * If no error was reported yet but the certificate decoding is not + * finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding + * was successful, then 0 is returned. + * + * \param ctx X.509 decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static __inline int +br_x509_decoder_last_error(br_x509_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (!ctx->decoded) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the "isCA" flag from an X.509 decoder context. + * + * This flag is set if the decoded certificate claims to be a CA through + * a Basic Constraints extension. This flag should not be read before + * decoding completed successfully. + * + * \param ctx X.509 decoder context. + * \return the "isCA" flag. + */ +static __inline int +br_x509_decoder_isCA(br_x509_decoder_context *ctx) +{ + return ctx->isCA; +} + +/** + * \brief Get the issuing CA key type (type of algorithm used to sign the + * decoded certificate). + * + * This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned + * if the signature type was not recognised. + * + * \param ctx X.509 decoder context. + * \return the issuing CA key type. + */ +static __inline int +br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx) +{ + return ctx->signer_key_type; +} + +/** + * \brief Get the identifier for the hash function used to sign the decoded + * certificate. + * + * This is 0 if the hash function was not recognised. + * + * \param ctx X.509 decoder context. + * \return the signature hash function identifier. + */ +static __inline int +br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx) +{ + return ctx->signer_hash_id; +} + +/** + * \brief Type for an X.509 certificate (DER-encoded). + */ +typedef struct { + /** \brief The DER-encoded certificate data. */ + unsigned char *data; + /** \brief The DER-encoded certificate length (in bytes). */ + size_t data_len; +} br_x509_certificate; + +/** + * \brief Private key decoder context. + * + * The private key decoder recognises RSA and EC private keys, either in + * their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8 + * archive (again DER-encoded). + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the private key. */ + union { + br_rsa_private_key rsa; + br_ec_private_key ec; + } key; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* Private key data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Decoded key type; 0 until decoding is complete. */ + unsigned char key_type; + + /* Buffer for the private key elements. It shall be large enough + to accommodate all elements for a RSA-4096 private key (roughly + five 2048-bit integers, possibly a bit more). */ + unsigned char key_data[3 * BR_X509_BUFSIZE_SIG]; +#endif +} br_skey_decoder_context; + +/** + * \brief Initialise a private key decoder context. + * + * \param ctx key decoder context to initialise. + */ +void br_skey_decoder_init(br_skey_decoder_context *ctx); + +/** + * \brief Push some data bytes into a private key decoder context. + * + * If `len` is non-zero, then that many data bytes, starting at address + * `data`, are pushed into the decoder. + * + * \param ctx key decoder context. + * \param data private key data chunk. + * \param len private key data chunk length (in bytes). + */ +void br_skey_decoder_push(br_skey_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Get the decoding status for a private key. + * + * Decoding status is 0 on success, or a non-zero error code. If the + * decoding is unfinished when this function is called, then the + * status code `BR_ERR_X509_TRUNCATED` is returned. + * + * \param ctx key decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static __inline int +br_skey_decoder_last_error(const br_skey_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (ctx->key_type == 0) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the decoded private key type. + * + * Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is + * not finished or failed, then 0 is returned. + * + * \param ctx key decoder context. + * \return decoded private key type, or 0. + */ +static __inline int +br_skey_decoder_key_type(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0) { + return ctx->key_type; + } else { + return 0; + } +} + +/** + * \brief Get the decoded RSA private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not RSA. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded RSA private key, or `NULL`. + */ +static __inline const br_rsa_private_key * +br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) { + return &ctx->key.rsa; + } else { + return NULL; + } +} + +/** + * \brief Get the decoded EC private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not EC. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded EC private key, or `NULL`. + */ +static __inline const br_ec_private_key * +br_skey_decoder_get_ec(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) { + return &ctx->key.ec; + } else { + return NULL; + } +} + +/** + * \brief Encode an RSA private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER + * encoding rules. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an RSA private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER" + * format for the RSA key, as implemented by `br_encode_rsa_raw_der()`. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an EC private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in RFC 5915 (type `ECPrivateKey`), with DER encoding rules. + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is `NULL`, then the encoded key will not include the public key + * in its `publicKey` field (which is nominally optional). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_raw_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief Encode an EC private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). The curve is identified + * by an OID provided as parameters to the `privateKeyAlgorithm` + * field. The private key value (contents of the `privateKey` field) + * contains the DER encoding of the `ECPrivateKey` type defined in + * RFC 5915, without the `parameters` field (since they would be + * redundant with the information in `privateKeyAlgorithm`). + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is not `NULL`, then the encoded public key is included in the + * `publicKey` field of the private key value (but not in the `publicKey` + * field of the PKCS#8 `OneAsymmetricKey` wrapper). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_pkcs8_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief PEM banner for RSA private key (raw). + */ +#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY" + +/** + * \brief PEM banner for EC private key (raw). + */ +#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY" + +/** + * \brief PEM banner for an RSA or EC private key in PKCS#8 format. + */ +#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BearSSL-OG/libbearssl/src/aead/ccm.c b/BearSSL-OG/libbearssl/src/aead/ccm.c new file mode 100644 index 0000000..68cc913 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/aead/ccm.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Implementation Notes + * ==================== + * + * The combined CTR + CBC-MAC functions can only handle full blocks, + * so some buffering is necessary. + * + * - 'ptr' contains a value from 0 to 15, which is the number of bytes + * accumulated in buf[] that still needs to be processed with the + * current CBC-MAC computation. + * + * - When processing the message itself, CTR encryption/decryption is + * also done at the same time. The first 'ptr' bytes of buf[] then + * contains the plaintext bytes, while the last '16 - ptr' bytes of + * buf[] are the remnants of the stream block, to be used against + * the next input bytes, when available. When 'ptr' is 0, the + * contents of buf[] are to be ignored. + * + * - The current counter and running CBC-MAC values are kept in 'ctr' + * and 'cbcmac', respectively. + */ + +/* see bearssl_block.h */ +void +br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx) +{ + ctx->bctx = bctx; +} + +/* see bearssl_block.h */ +int +br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, + uint64_t aad_len, uint64_t data_len, size_t tag_len) +{ + unsigned char tmp[16]; + unsigned u, q; + + if (nonce_len < 7 || nonce_len > 13) { + return 0; + } + if (tag_len < 4 || tag_len > 16 || (tag_len & 1) != 0) { + return 0; + } + q = 15 - (unsigned)nonce_len; + ctx->tag_len = tag_len; + + /* + * Block B0, to start CBC-MAC. + */ + tmp[0] = (aad_len > 0 ? 0x40 : 0x00) + | (((unsigned)tag_len - 2) << 2) + | (q - 1); + memcpy(tmp + 1, nonce, nonce_len); + for (u = 0; u < q; u ++) { + tmp[15 - u] = (unsigned char)data_len; + data_len >>= 8; + } + if (data_len != 0) { + /* + * If the data length was not entirely consumed in the + * loop above, then it exceeds the maximum limit of + * q bytes (when encoded). + */ + return 0; + } + + /* + * Start CBC-MAC. + */ + memset(ctx->cbcmac, 0, sizeof ctx->cbcmac); + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, tmp, sizeof tmp); + + /* + * Assemble AAD length header. + */ + if ((aad_len >> 32) != 0) { + ctx->buf[0] = 0xFF; + ctx->buf[1] = 0xFF; + br_enc64be(ctx->buf + 2, aad_len); + ctx->ptr = 10; + } else if (aad_len >= 0xFF00) { + ctx->buf[0] = 0xFF; + ctx->buf[1] = 0xFE; + br_enc32be(ctx->buf + 2, (uint32_t)aad_len); + ctx->ptr = 6; + } else if (aad_len > 0) { + br_enc16be(ctx->buf, (unsigned)aad_len); + ctx->ptr = 2; + } else { + ctx->ptr = 0; + } + + /* + * Make initial counter value and compute tag mask. + */ + ctx->ctr[0] = q - 1; + memcpy(ctx->ctr + 1, nonce, nonce_len); + memset(ctx->ctr + 1 + nonce_len, 0, q); + memset(ctx->tagmask, 0, sizeof ctx->tagmask); + (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, + ctx->tagmask, sizeof ctx->tagmask); + + return 1; +} + +/* see bearssl_block.h */ +void +br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len) +{ + const unsigned char *dbuf; + size_t ptr; + + dbuf = data; + + /* + * Complete partial block, if needed. + */ + ptr = ctx->ptr; + if (ptr != 0) { + size_t clen; + + clen = (sizeof ctx->buf) - ptr; + if (clen > len) { + memcpy(ctx->buf + ptr, dbuf, len); + ctx->ptr = ptr + len; + return; + } + memcpy(ctx->buf + ptr, dbuf, clen); + dbuf += clen; + len -= clen; + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, + ctx->buf, sizeof ctx->buf); + } + + /* + * Process complete blocks. + */ + ptr = len & 15; + len -= ptr; + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, dbuf, len); + dbuf += len; + + /* + * Copy last partial block in the context buffer. + */ + memcpy(ctx->buf, dbuf, ptr); + ctx->ptr = ptr; +} + +/* see bearssl_block.h */ +void +br_ccm_flip(br_ccm_context *ctx) +{ + size_t ptr; + + /* + * Complete AAD partial block with zeros, if necessary. + */ + ptr = ctx->ptr; + if (ptr != 0) { + memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, + ctx->buf, sizeof ctx->buf); + ctx->ptr = 0; + } + + /* + * Counter was already set by br_ccm_reset(). + */ +} + +/* see bearssl_block.h */ +void +br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len) +{ + unsigned char *dbuf; + size_t ptr; + + dbuf = data; + + /* + * Complete a partial block, if any: ctx->buf[] contains + * ctx->ptr plaintext bytes (already reported), and the other + * bytes are CTR stream output. + */ + ptr = ctx->ptr; + if (ptr != 0) { + size_t clen; + size_t u; + + clen = (sizeof ctx->buf) - ptr; + if (clen > len) { + clen = len; + } + if (encrypt) { + for (u = 0; u < clen; u ++) { + unsigned w, x; + + w = ctx->buf[ptr + u]; + x = dbuf[u]; + ctx->buf[ptr + u] = x; + dbuf[u] = w ^ x; + } + } else { + for (u = 0; u < clen; u ++) { + unsigned w; + + w = ctx->buf[ptr + u] ^ dbuf[u]; + dbuf[u] = w; + ctx->buf[ptr + u] = w; + } + } + dbuf += clen; + len -= clen; + ptr += clen; + if (ptr < sizeof ctx->buf) { + ctx->ptr = ptr; + return; + } + (*ctx->bctx)->mac(ctx->bctx, + ctx->cbcmac, ctx->buf, sizeof ctx->buf); + } + + /* + * Process all complete blocks. Note that the ctrcbc API is for + * encrypt-then-MAC (CBC-MAC is computed over the encrypted + * blocks) while CCM uses MAC-and-encrypt (CBC-MAC is computed + * over the plaintext blocks). Therefore, we need to use the + * _decryption_ function for encryption, and the encryption + * function for decryption (this works because CTR encryption + * and decryption are identical, so the choice really is about + * computing the CBC-MAC before or after XORing with the CTR + * stream). + */ + ptr = len & 15; + len -= ptr; + if (encrypt) { + (*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac, + dbuf, len); + } else { + (*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac, + dbuf, len); + } + dbuf += len; + + /* + * If there is some remaining data, then we need to compute an + * extra block of CTR stream. + */ + if (ptr != 0) { + size_t u; + + memset(ctx->buf, 0, sizeof ctx->buf); + (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, + ctx->buf, sizeof ctx->buf); + if (encrypt) { + for (u = 0; u < ptr; u ++) { + unsigned w, x; + + w = ctx->buf[u]; + x = dbuf[u]; + ctx->buf[u] = x; + dbuf[u] = w ^ x; + } + } else { + for (u = 0; u < ptr; u ++) { + unsigned w; + + w = ctx->buf[u] ^ dbuf[u]; + dbuf[u] = w; + ctx->buf[u] = w; + } + } + } + ctx->ptr = ptr; +} + +/* see bearssl_block.h */ +size_t +br_ccm_get_tag(br_ccm_context *ctx, void *tag) +{ + size_t ptr; + size_t u; + + /* + * If there is some buffered data, then we need to pad it with + * zeros and finish up CBC-MAC. + */ + ptr = ctx->ptr; + if (ptr != 0) { + memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, + ctx->buf, sizeof ctx->buf); + } + + /* + * XOR the tag mask into the CBC-MAC output. + */ + for (u = 0; u < ctx->tag_len; u ++) { + ctx->cbcmac[u] ^= ctx->tagmask[u]; + } + memcpy(tag, ctx->cbcmac, ctx->tag_len); + return ctx->tag_len; +} + +/* see bearssl_block.h */ +uint32_t +br_ccm_check_tag(br_ccm_context *ctx, const void *tag) +{ + unsigned char tmp[16]; + size_t u, tag_len; + uint32_t z; + + tag_len = br_ccm_get_tag(ctx, tmp); + z = 0; + for (u = 0; u < tag_len; u ++) { + z |= tmp[u] ^ ((const unsigned char *)tag)[u]; + } + return EQ0(z); +} diff --git a/BearSSL-OG/libbearssl/src/aead/eax.c b/BearSSL-OG/libbearssl/src/aead/eax.c new file mode 100644 index 0000000..bcc704a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/aead/eax.c @@ -0,0 +1,525 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Implementation Notes + * ==================== + * + * The combined CTR + CBC-MAC functions can only handle full blocks, + * so some buffering is necessary. Moreover, EAX has a special padding + * rule for CBC-MAC, which implies that we cannot compute the MAC over + * the last received full block until we know whether we are at the + * end of the data or not. + * + * - 'ptr' contains a value from 1 to 16, which is the number of bytes + * accumulated in buf[] that still needs to be processed with the + * current OMAC computation. Beware that this can go to 16: a + * complete block cannot be processed until it is known whether it + * is the last block or not. However, it can never be 0, because + * OMAC^t works on an input that is at least one-block long. + * + * - When processing the message itself, CTR encryption/decryption is + * also done at the same time. The first 'ptr' bytes of buf[] then + * contains the encrypted bytes, while the last '16 - ptr' bytes of + * buf[] are the remnants of the stream block, to be used against + * the next input bytes, when available. + * + * - The current counter and running CBC-MAC values are kept in 'ctr' + * and 'cbcmac', respectively. + * + * - The derived keys for padding are kept in L2 and L4 (double and + * quadruple of Enc_K(0^n), in GF(2^128), respectively). + */ + +/* + * Start an OMAC computation; the first block is the big-endian + * representation of the provided value ('val' must fit on one byte). + * We make it a delayed block because it may also be the last one, + */ +static void +omac_start(br_eax_context *ctx, unsigned val) +{ + memset(ctx->cbcmac, 0, sizeof ctx->cbcmac); + memset(ctx->buf, 0, sizeof ctx->buf); + ctx->buf[15] = val; + ctx->ptr = 16; +} + +/* + * Double a value in finite field GF(2^128), defined with modulus + * X^128+X^7+X^2+X+1. + */ +static void +double_gf128(unsigned char *dst, const unsigned char *src) +{ + unsigned cc; + int i; + + cc = 0x87 & -((unsigned)src[0] >> 7); + for (i = 15; i >= 0; i --) { + unsigned z; + + z = (src[i] << 1) ^ cc; + cc = z >> 8; + dst[i] = (unsigned char)z; + } +} + +/* + * Apply padding to the last block, currently in ctx->buf (with + * ctx->ptr bytes), and finalize OMAC computation. + */ +static void +do_pad(br_eax_context *ctx) +{ + unsigned char *pad; + size_t ptr, u; + + ptr = ctx->ptr; + if (ptr == 16) { + pad = ctx->L2; + } else { + ctx->buf[ptr ++] = 0x80; + memset(ctx->buf + ptr, 0x00, 16 - ptr); + pad = ctx->L4; + } + for (u = 0; u < sizeof ctx->buf; u ++) { + ctx->buf[u] ^= pad[u]; + } + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf); +} + +/* + * Apply CBC-MAC on the provided data, with buffering management. + * + * Upon entry, two situations are acceptable: + * + * ctx->ptr == 0: there is no data to process in ctx->buf + * ctx->ptr == 16: there is a full block of unprocessed data in ctx->buf + * + * Upon exit, ctx->ptr may be zero only if it was already zero on entry, + * and len == 0. In all other situations, ctx->ptr will be non-zero on + * exit (and may have value 16). + */ +static void +do_cbcmac_chunk(br_eax_context *ctx, const void *data, size_t len) +{ + size_t ptr; + + if (len == 0) { + return; + } + ptr = len & (size_t)15; + if (ptr == 0) { + len -= 16; + ptr = 16; + } else { + len -= ptr; + } + if (ctx->ptr == 16) { + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, + ctx->buf, sizeof ctx->buf); + } + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, data, len); + memcpy(ctx->buf, (const unsigned char *)data + len, ptr); + ctx->ptr = ptr; +} + +/* see bearssl_aead.h */ +void +br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx) +{ + unsigned char tmp[16], iv[16]; + + ctx->vtable = &br_eax_vtable; + ctx->bctx = bctx; + + /* + * Encrypt a whole-zero block to compute L2 and L4. + */ + memset(tmp, 0, sizeof tmp); + memset(iv, 0, sizeof iv); + (*bctx)->ctr(bctx, iv, tmp, sizeof tmp); + double_gf128(ctx->L2, tmp); + double_gf128(ctx->L4, ctx->L2); +} + +/* see bearssl_aead.h */ +void +br_eax_capture(const br_eax_context *ctx, br_eax_state *st) +{ + /* + * We capture the three OMAC* states _after_ processing the + * initial block (assuming that nonce, message and AAD are + * all non-empty). + */ + int i; + + memset(st->st, 0, sizeof st->st); + for (i = 0; i < 3; i ++) { + unsigned char tmp[16]; + + memset(tmp, 0, sizeof tmp); + tmp[15] = (unsigned char)i; + (*ctx->bctx)->mac(ctx->bctx, st->st[i], tmp, sizeof tmp); + } +} + +/* see bearssl_aead.h */ +void +br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len) +{ + /* + * Process nonce with OMAC^0. + */ + omac_start(ctx, 0); + do_cbcmac_chunk(ctx, nonce, len); + do_pad(ctx); + memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac); + + /* + * Start OMAC^1 for the AAD ("header" in the EAX specification). + */ + omac_start(ctx, 1); + + /* + * We use ctx->head[0] as temporary flag to mark that we are + * using a "normal" reset(). + */ + ctx->head[0] = 0; +} + +/* see bearssl_aead.h */ +void +br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len) +{ + if (len == 0) { + omac_start(ctx, 0); + } else { + memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac); + ctx->ptr = 0; + do_cbcmac_chunk(ctx, nonce, len); + } + do_pad(ctx); + memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac); + + memcpy(ctx->cbcmac, st->st[1], sizeof ctx->cbcmac); + ctx->ptr = 0; + + memcpy(ctx->ctr, st->st[2], sizeof ctx->ctr); + + /* + * We use ctx->head[0] as a flag to indicate that we use a + * a recorded state, with ctx->ctr containing the preprocessed + * first block for OMAC^2. + */ + ctx->head[0] = 1; +} + +/* see bearssl_aead.h */ +void +br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len) +{ + if (len == 0) { + omac_start(ctx, 0); + } else { + memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac); + ctx->ptr = 0; + do_cbcmac_chunk(ctx, nonce, len); + } + do_pad(ctx); + memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac); + memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce); + + memcpy(ctx->head, st->st[1], sizeof ctx->head); + + memcpy(ctx->cbcmac, st->st[2], sizeof ctx->cbcmac); + ctx->ptr = 0; +} + +/* see bearssl_aead.h */ +void +br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len) +{ + size_t ptr; + + ptr = ctx->ptr; + + /* + * If there is a partial block, first complete it. + */ + if (ptr < 16) { + size_t clen; + + clen = 16 - ptr; + if (len <= clen) { + memcpy(ctx->buf + ptr, data, len); + ctx->ptr = ptr + len; + return; + } + memcpy(ctx->buf + ptr, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + } + + /* + * We now have a full block in buf[], and this is not the last + * block. + */ + do_cbcmac_chunk(ctx, data, len); +} + +/* see bearssl_aead.h */ +void +br_eax_flip(br_eax_context *ctx) +{ + int from_capture; + + /* + * ctx->head[0] may be non-zero if the context was reset with + * a pre-AAD captured state. In that case, ctx->ctr[] contains + * the state for OMAC^2 _after_ processing the first block. + */ + from_capture = ctx->head[0]; + + /* + * Complete the OMAC computation on the AAD. + */ + do_pad(ctx); + memcpy(ctx->head, ctx->cbcmac, sizeof ctx->cbcmac); + + /* + * Start OMAC^2 for the encrypted data. + * If the context was initialized from a captured state, then + * the OMAC^2 value is in the ctr[] array. + */ + if (from_capture) { + memcpy(ctx->cbcmac, ctx->ctr, sizeof ctx->cbcmac); + ctx->ptr = 0; + } else { + omac_start(ctx, 2); + } + + /* + * Initial counter value for CTR is the processed nonce. + */ + memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce); +} + +/* see bearssl_aead.h */ +void +br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len) +{ + unsigned char *dbuf; + size_t ptr; + + /* + * Ensure that there is actual data to process. + */ + if (len == 0) { + return; + } + + dbuf = data; + ptr = ctx->ptr; + + /* + * We may have ptr == 0 here if we initialized from a captured + * state. In that case, there is no partially consumed block + * or unprocessed data. + */ + if (ptr != 0 && ptr != 16) { + /* + * We have a partially consumed block. + */ + size_t u, clen; + + clen = 16 - ptr; + if (len <= clen) { + clen = len; + } + if (encrypt) { + for (u = 0; u < clen; u ++) { + ctx->buf[ptr + u] ^= dbuf[u]; + } + memcpy(dbuf, ctx->buf + ptr, clen); + } else { + for (u = 0; u < clen; u ++) { + unsigned dx, sx; + + sx = ctx->buf[ptr + u]; + dx = dbuf[u]; + ctx->buf[ptr + u] = dx; + dbuf[u] = sx ^ dx; + } + } + + if (len <= clen) { + ctx->ptr = ptr + clen; + return; + } + dbuf += clen; + len -= clen; + } + + /* + * We now have a complete encrypted block in buf[] that must still + * be processed with OMAC, and this is not the final buf. + * Exception: when ptr == 0, no block has been produced yet. + */ + if (ptr != 0) { + (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, + ctx->buf, sizeof ctx->buf); + } + + /* + * Do CTR encryption or decryption and CBC-MAC for all full blocks + * except the last. + */ + ptr = len & (size_t)15; + if (ptr == 0) { + len -= 16; + ptr = 16; + } else { + len -= ptr; + } + if (encrypt) { + (*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac, + dbuf, len); + } else { + (*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac, + dbuf, len); + } + dbuf += len; + + /* + * Compute next block of CTR stream, and use it to finish + * encrypting or decrypting the data. + */ + memset(ctx->buf, 0, sizeof ctx->buf); + (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf); + if (encrypt) { + size_t u; + + for (u = 0; u < ptr; u ++) { + ctx->buf[u] ^= dbuf[u]; + } + memcpy(dbuf, ctx->buf, ptr); + } else { + size_t u; + + for (u = 0; u < ptr; u ++) { + unsigned dx, sx; + + sx = ctx->buf[u]; + dx = dbuf[u]; + ctx->buf[u] = dx; + dbuf[u] = sx ^ dx; + } + } + ctx->ptr = ptr; +} + +/* + * Complete tag computation. The final tag is written in ctx->cbcmac. + */ +static void +do_final(br_eax_context *ctx) +{ + size_t u; + + do_pad(ctx); + + /* + * Authentication tag is the XOR of the three OMAC outputs for + * the nonce, AAD and encrypted data. + */ + for (u = 0; u < 16; u ++) { + ctx->cbcmac[u] ^= ctx->nonce[u] ^ ctx->head[u]; + } +} + +/* see bearssl_aead.h */ +void +br_eax_get_tag(br_eax_context *ctx, void *tag) +{ + do_final(ctx); + memcpy(tag, ctx->cbcmac, sizeof ctx->cbcmac); +} + +/* see bearssl_aead.h */ +void +br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len) +{ + do_final(ctx); + memcpy(tag, ctx->cbcmac, len); +} + +/* see bearssl_aead.h */ +uint32_t +br_eax_check_tag_trunc(br_eax_context *ctx, const void *tag, size_t len) +{ + unsigned char tmp[16]; + size_t u; + int x; + + br_eax_get_tag(ctx, tmp); + x = 0; + for (u = 0; u < len; u ++) { + x |= tmp[u] ^ ((const unsigned char *)tag)[u]; + } + return EQ0(x); +} + +/* see bearssl_aead.h */ +uint32_t +br_eax_check_tag(br_eax_context *ctx, const void *tag) +{ + return br_eax_check_tag_trunc(ctx, tag, 16); +} + +/* see bearssl_aead.h */ +const br_aead_class br_eax_vtable = { + 16, + (void (*)(const br_aead_class **, const void *, size_t)) + &br_eax_reset, + (void (*)(const br_aead_class **, const void *, size_t)) + &br_eax_aad_inject, + (void (*)(const br_aead_class **)) + &br_eax_flip, + (void (*)(const br_aead_class **, int, void *, size_t)) + &br_eax_run, + (void (*)(const br_aead_class **, void *)) + &br_eax_get_tag, + (uint32_t (*)(const br_aead_class **, const void *)) + &br_eax_check_tag, + (void (*)(const br_aead_class **, void *, size_t)) + &br_eax_get_tag_trunc, + (uint32_t (*)(const br_aead_class **, const void *, size_t)) + &br_eax_check_tag_trunc +}; diff --git a/BearSSL-OG/libbearssl/src/aead/gcm.c b/BearSSL-OG/libbearssl/src/aead/gcm.c new file mode 100644 index 0000000..ede5f08 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/aead/gcm.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Implementation Notes + * ==================== + * + * Since CTR and GHASH implementations can handle only full blocks, a + * 16-byte buffer (buf[]) is maintained in the context: + * + * - When processing AAD, buf[] contains the 0-15 unprocessed bytes. + * + * - When doing CTR encryption / decryption, buf[] contains the AES output + * for the last partial block, to be used with the next few bytes of + * data, as well as the already encrypted bytes. For instance, if the + * processed data length so far is 21 bytes, then buf[0..4] contains + * the five last encrypted bytes, and buf[5..15] contains the next 11 + * AES output bytes to be XORed with the next 11 bytes of input. + * + * The recorded AES output bytes are used to complete the block when + * the corresponding bytes are obtained. Note that buf[] always + * contains the _encrypted_ bytes, whether we apply encryption or + * decryption: these bytes are used as input to GHASH when the block + * is complete. + * + * In both cases, the low bits of the data length counters (count_aad, + * count_ctr) are used to work out the current situation. + */ + +/* see bearssl_aead.h */ +void +br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh) +{ + unsigned char iv[12]; + + ctx->vtable = &br_gcm_vtable; + ctx->bctx = bctx; + ctx->gh = gh; + + /* + * The GHASH key h[] is the raw encryption of the all-zero + * block. Since we only have a CTR implementation, we use it + * with an all-zero IV and a zero counter, to CTR-encrypt an + * all-zero block. + */ + memset(ctx->h, 0, sizeof ctx->h); + memset(iv, 0, sizeof iv); + (*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h); +} + +/* see bearssl_aead.h */ +void +br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len) +{ + /* + * If the provided nonce is 12 bytes, then this is the initial + * IV for CTR mode; it will be used with a counter that starts + * at 2 (value 1 is for encrypting the GHASH output into the tag). + * + * If the provided nonce has any other length, then it is hashed + * (with GHASH) into a 16-byte value that will be the IV for CTR + * (both 12-byte IV and 32-bit counter). + */ + if (len == 12) { + memcpy(ctx->j0_1, iv, 12); + ctx->j0_2 = 1; + } else { + unsigned char ty[16], tmp[16]; + + memset(ty, 0, sizeof ty); + ctx->gh(ty, ctx->h, iv, len); + memset(tmp, 0, 8); + br_enc64be(tmp + 8, (uint64_t)len << 3); + ctx->gh(ty, ctx->h, tmp, 16); + memcpy(ctx->j0_1, ty, 12); + ctx->j0_2 = br_dec32be(ty + 12); + } + ctx->jc = ctx->j0_2 + 1; + memset(ctx->y, 0, sizeof ctx->y); + ctx->count_aad = 0; + ctx->count_ctr = 0; +} + +/* see bearssl_aead.h */ +void +br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len) +{ + size_t ptr, dlen; + + ptr = (size_t)ctx->count_aad & (size_t)15; + if (ptr != 0) { + /* + * If there is a partial block, then we first try to + * complete it. + */ + size_t clen; + + clen = 16 - ptr; + if (len < clen) { + memcpy(ctx->buf + ptr, data, len); + ctx->count_aad += (uint64_t)len; + return; + } + memcpy(ctx->buf + ptr, data, clen); + ctx->gh(ctx->y, ctx->h, ctx->buf, 16); + data = (const unsigned char *)data + clen; + len -= clen; + ctx->count_aad += (uint64_t)clen; + } + + /* + * Now AAD is aligned on a 16-byte block (with regards to GHASH). + * We process all complete blocks, and save the last partial + * block. + */ + dlen = len & ~(size_t)15; + ctx->gh(ctx->y, ctx->h, data, dlen); + memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen); + ctx->count_aad += (uint64_t)len; +} + +/* see bearssl_aead.h */ +void +br_gcm_flip(br_gcm_context *ctx) +{ + /* + * We complete the GHASH computation if there is a partial block. + * The GHASH implementation automatically applies padding with + * zeros. + */ + size_t ptr; + + ptr = (size_t)ctx->count_aad & (size_t)15; + if (ptr != 0) { + ctx->gh(ctx->y, ctx->h, ctx->buf, ptr); + } +} + +/* see bearssl_aead.h */ +void +br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len) +{ + unsigned char *buf; + size_t ptr, dlen; + + buf = data; + ptr = (size_t)ctx->count_ctr & (size_t)15; + if (ptr != 0) { + /* + * If we have a partial block, then we try to complete it. + */ + size_t u, clen; + + clen = 16 - ptr; + if (len < clen) { + clen = len; + } + for (u = 0; u < clen; u ++) { + unsigned x, y; + + x = buf[u]; + y = x ^ ctx->buf[ptr + u]; + ctx->buf[ptr + u] = encrypt ? y : x; + buf[u] = y; + } + ctx->count_ctr += (uint64_t)clen; + buf += clen; + len -= clen; + if (ptr + clen < 16) { + return; + } + ctx->gh(ctx->y, ctx->h, ctx->buf, 16); + } + + /* + * Process full blocks. + */ + dlen = len & ~(size_t)15; + if (!encrypt) { + ctx->gh(ctx->y, ctx->h, buf, dlen); + } + ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, buf, dlen); + if (encrypt) { + ctx->gh(ctx->y, ctx->h, buf, dlen); + } + buf += dlen; + len -= dlen; + ctx->count_ctr += (uint64_t)dlen; + + if (len > 0) { + /* + * There is a partial block. + */ + size_t u; + + memset(ctx->buf, 0, sizeof ctx->buf); + ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, + ctx->jc, ctx->buf, 16); + for (u = 0; u < len; u ++) { + unsigned x, y; + + x = buf[u]; + y = x ^ ctx->buf[u]; + ctx->buf[u] = encrypt ? y : x; + buf[u] = y; + } + ctx->count_ctr += (uint64_t)len; + } +} + +/* see bearssl_aead.h */ +void +br_gcm_get_tag(br_gcm_context *ctx, void *tag) +{ + size_t ptr; + unsigned char tmp[16]; + + ptr = (size_t)ctx->count_ctr & (size_t)15; + if (ptr > 0) { + /* + * There is a partial block: encrypted/decrypted data has + * been produced, but the encrypted bytes must still be + * processed by GHASH. + */ + ctx->gh(ctx->y, ctx->h, ctx->buf, ptr); + } + + /* + * Final block for GHASH: the AAD and plaintext lengths (in bits). + */ + br_enc64be(tmp, ctx->count_aad << 3); + br_enc64be(tmp + 8, ctx->count_ctr << 3); + ctx->gh(ctx->y, ctx->h, tmp, 16); + + /* + * Tag is the GHASH output XORed with the encryption of the + * nonce with the initial counter value. + */ + memcpy(tag, ctx->y, 16); + (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16); +} + +/* see bearssl_aead.h */ +void +br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len) +{ + unsigned char tmp[16]; + + br_gcm_get_tag(ctx, tmp); + memcpy(tag, tmp, len); +} + +/* see bearssl_aead.h */ +uint32_t +br_gcm_check_tag_trunc(br_gcm_context *ctx, const void *tag, size_t len) +{ + unsigned char tmp[16]; + size_t u; + int x; + + br_gcm_get_tag(ctx, tmp); + x = 0; + for (u = 0; u < len; u ++) { + x |= tmp[u] ^ ((const unsigned char *)tag)[u]; + } + return EQ0(x); +} + +/* see bearssl_aead.h */ +uint32_t +br_gcm_check_tag(br_gcm_context *ctx, const void *tag) +{ + return br_gcm_check_tag_trunc(ctx, tag, 16); +} + +/* see bearssl_aead.h */ +const br_aead_class br_gcm_vtable = { + 16, + (void (*)(const br_aead_class **, const void *, size_t)) + &br_gcm_reset, + (void (*)(const br_aead_class **, const void *, size_t)) + &br_gcm_aad_inject, + (void (*)(const br_aead_class **)) + &br_gcm_flip, + (void (*)(const br_aead_class **, int, void *, size_t)) + &br_gcm_run, + (void (*)(const br_aead_class **, void *)) + &br_gcm_get_tag, + (uint32_t (*)(const br_aead_class **, const void *)) + &br_gcm_check_tag, + (void (*)(const br_aead_class **, void *, size_t)) + &br_gcm_get_tag_trunc, + (uint32_t (*)(const br_aead_class **, const void *, size_t)) + &br_gcm_check_tag_trunc +}; diff --git a/BearSSL-OG/libbearssl/src/codec/ccopy.c b/BearSSL-OG/libbearssl/src/codec/ccopy.c new file mode 100644 index 0000000..2beace7 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/ccopy.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + uint32_t x, y; + + x = *s ++; + y = *d; + *d = MUX(ctl, x, y); + d ++; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/dec16be.c b/BearSSL-OG/libbearssl/src/codec/dec16be.c new file mode 100644 index 0000000..4f3f7f4 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/dec16be.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_dec16be(uint16_t *v, size_t num, const void *src) +{ + const unsigned char *buf; + + buf = src; + while (num -- > 0) { + *v ++ = br_dec16be(buf); + buf += 2; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/dec16le.c b/BearSSL-OG/libbearssl/src/codec/dec16le.c new file mode 100644 index 0000000..84d8536 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/dec16le.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_dec16le(uint16_t *v, size_t num, const void *src) +{ + const unsigned char *buf; + + buf = src; + while (num -- > 0) { + *v ++ = br_dec16le(buf); + buf += 2; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/dec32be.c b/BearSSL-OG/libbearssl/src/codec/dec32be.c new file mode 100644 index 0000000..5a8fc59 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/dec32be.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_dec32be(uint32_t *v, size_t num, const void *src) +{ + const unsigned char *buf; + + buf = src; + while (num -- > 0) { + *v ++ = br_dec32be(buf); + buf += 4; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/dec32le.c b/BearSSL-OG/libbearssl/src/codec/dec32le.c new file mode 100644 index 0000000..ed36e71 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/dec32le.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_dec32le(uint32_t *v, size_t num, const void *src) +{ + const unsigned char *buf; + + buf = src; + while (num -- > 0) { + *v ++ = br_dec32le(buf); + buf += 4; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/dec64be.c b/BearSSL-OG/libbearssl/src/codec/dec64be.c new file mode 100644 index 0000000..0c40a76 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/dec64be.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_dec64be(uint64_t *v, size_t num, const void *src) +{ + const unsigned char *buf; + + buf = src; + while (num -- > 0) { + *v ++ = br_dec64be(buf); + buf += 8; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/dec64le.c b/BearSSL-OG/libbearssl/src/codec/dec64le.c new file mode 100644 index 0000000..cbd02c2 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/dec64le.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_dec64le(uint64_t *v, size_t num, const void *src) +{ + const unsigned char *buf; + + buf = src; + while (num -- > 0) { + *v ++ = br_dec64le(buf); + buf += 8; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/enc16be.c b/BearSSL-OG/libbearssl/src/codec/enc16be.c new file mode 100644 index 0000000..6e06652 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/enc16be.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_enc16be(void *dst, const uint16_t *v, size_t num) +{ + unsigned char *buf; + + buf = dst; + while (num -- > 0) { + br_enc16be(buf, *v ++); + buf += 2; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/enc16le.c b/BearSSL-OG/libbearssl/src/codec/enc16le.c new file mode 100644 index 0000000..3e5049a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/enc16le.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_enc16le(void *dst, const uint16_t *v, size_t num) +{ + unsigned char *buf; + + buf = dst; + while (num -- > 0) { + br_enc16le(buf, *v ++); + buf += 2; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/enc32be.c b/BearSSL-OG/libbearssl/src/codec/enc32be.c new file mode 100644 index 0000000..97298b5 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/enc32be.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_enc32be(void *dst, const uint32_t *v, size_t num) +{ + unsigned char *buf; + + buf = dst; + while (num -- > 0) { + br_enc32be(buf, *v ++); + buf += 4; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/enc32le.c b/BearSSL-OG/libbearssl/src/codec/enc32le.c new file mode 100644 index 0000000..9e9c856 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/enc32le.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_enc32le(void *dst, const uint32_t *v, size_t num) +{ + unsigned char *buf; + + buf = dst; + while (num -- > 0) { + br_enc32le(buf, *v ++); + buf += 4; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/enc64be.c b/BearSSL-OG/libbearssl/src/codec/enc64be.c new file mode 100644 index 0000000..d548944 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/enc64be.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_enc64be(void *dst, const uint64_t *v, size_t num) +{ + unsigned char *buf; + + buf = dst; + while (num -- > 0) { + br_enc64be(buf, *v ++); + buf += 8; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/enc64le.c b/BearSSL-OG/libbearssl/src/codec/enc64le.c new file mode 100644 index 0000000..1f1d68e --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/enc64le.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_range_enc64le(void *dst, const uint64_t *v, size_t num) +{ + unsigned char *buf; + + buf = dst; + while (num -- > 0) { + br_enc64le(buf, *v ++); + buf += 8; + } +} diff --git a/BearSSL-OG/libbearssl/src/codec/pemdec.c b/BearSSL-OG/libbearssl/src/codec/pemdec.c new file mode 100644 index 0000000..8e54e6d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/pemdec.c @@ -0,0 +1,526 @@ +/* Automatically generated code; do not modify directly. */ + +#include +#include + +typedef struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; +} t0_context; + +static uint32_t +t0_parse7E_unsigned(const unsigned char **p) +{ + uint32_t x; + + x = 0; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + return x; + } + } +} + +static int32_t +t0_parse7E_signed(const unsigned char **p) +{ + int neg; + uint32_t x; + + neg = ((**p) >> 6) & 1; + x = (uint32_t)-neg; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + if (neg) { + return -(int32_t)~x - 1; + } else { + return (int32_t)x; + } + } + } +} + +#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) +#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) +#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) +#define T0_INT1(x) T0_FBYTE(x, 0) +#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) + +/* static const unsigned char t0_datablock[]; */ + + +void br_pem_decoder_init_main(void *t0ctx); + +void br_pem_decoder_run(void *t0ctx); + + + +#include "inner.h" + +#define CTX ((br_pem_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu))) + +/* see bearssl_pem.h */ +void +br_pem_decoder_init(br_pem_decoder_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->cpu.dp = &ctx->dp_stack[0]; + ctx->cpu.rp = &ctx->rp_stack[0]; + br_pem_decoder_init_main(&ctx->cpu); + br_pem_decoder_run(&ctx->cpu); +} + +/* see bearssl_pem.h */ +size_t +br_pem_decoder_push(br_pem_decoder_context *ctx, + const void *data, size_t len) +{ + if (ctx->event) { + return 0; + } + ctx->hbuf = data; + ctx->hlen = len; + br_pem_decoder_run(&ctx->cpu); + return len - ctx->hlen; +} + +/* see bearssl_pem.h */ +int +br_pem_decoder_event(br_pem_decoder_context *ctx) +{ + int event; + + event = ctx->event; + ctx->event = 0; + return event; +} + + + +static const unsigned char t0_datablock[] = { + 0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, + 0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x00 +}; + +static const unsigned char t0_codeblock[] = { + 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01, + 0x01, 0x08, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_pem_decoder_context, event)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_pem_decoder_context, name)), 0x00, 0x00, 0x05, + 0x14, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x03, 0x13, 0x04, 0x76, 0x01, + 0x2D, 0x0C, 0x06, 0x05, 0x2E, 0x01, 0x03, 0x2D, 0x00, 0x01, 0x0D, 0x27, + 0x05, 0x04, 0x01, 0x03, 0x2D, 0x00, 0x15, 0x2E, 0x01, 0x02, 0x2D, 0x00, + 0x01, 0x01, 0x7F, 0x03, 0x00, 0x25, 0x01, 0x00, 0x18, 0x0D, 0x06, 0x03, + 0x13, 0x04, 0x3C, 0x01, 0x7F, 0x18, 0x0D, 0x06, 0x13, 0x13, 0x02, 0x00, + 0x05, 0x06, 0x2E, 0x01, 0x03, 0x2D, 0x04, 0x03, 0x01, 0x7F, 0x23, 0x01, + 0x00, 0x00, 0x04, 0x23, 0x01, 0x01, 0x18, 0x0D, 0x06, 0x09, 0x13, 0x01, + 0x00, 0x23, 0x01, 0x00, 0x00, 0x04, 0x14, 0x01, 0x02, 0x18, 0x0D, 0x06, + 0x06, 0x13, 0x01, 0x7F, 0x00, 0x04, 0x08, 0x13, 0x01, 0x03, 0x2D, 0x01, + 0x00, 0x00, 0x13, 0x01, 0x00, 0x03, 0x00, 0x04, 0xFF, 0x33, 0x01, 0x2C, + 0x14, 0x01, 0x2D, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x7F, 0x00, 0x14, 0x31, + 0x06, 0x02, 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, + 0x02, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, + 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, + 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, + 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, + 0x06, 0x04, 0x13, 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x2E, + 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, 0x00, + 0x2F, 0x05, 0x04, 0x13, 0x01, 0x03, 0x00, 0x01, 0x3D, 0x0C, 0x06, 0x03, + 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x0F, 0x10, 0x06, 0x03, 0x01, 0x03, + 0x00, 0x02, 0x00, 0x01, 0x04, 0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14, + 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, + 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, + 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x20, 0x13, 0x2F, 0x05, + 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x03, 0x10, 0x06, 0x03, 0x01, + 0x03, 0x00, 0x02, 0x00, 0x01, 0x0A, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x02, + 0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, + 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x02, + 0x00, 0x01, 0x10, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x08, 0x0F, 0x1C, 0x02, + 0x00, 0x1C, 0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x01, 0x2D, 0x24, 0x06, + 0x02, 0x04, 0x7B, 0x04, 0x75, 0x00, 0x14, 0x12, 0x2A, 0x14, 0x05, 0x04, + 0x20, 0x01, 0x7F, 0x00, 0x2C, 0x2A, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x05, + 0x13, 0x20, 0x01, 0x00, 0x00, 0x0D, 0x05, 0x05, 0x13, 0x2E, 0x01, 0x00, + 0x00, 0x1E, 0x04, 0x5E, 0x00, 0x01, 0x01, 0x27, 0x06, 0x0B, 0x22, 0x01, + 0x80, 0x7F, 0x2B, 0x14, 0x06, 0x02, 0x30, 0x00, 0x13, 0x04, 0x6E, 0x00, + 0x2C, 0x14, 0x31, 0x05, 0x01, 0x00, 0x13, 0x04, 0x77, 0x00, 0x14, 0x14, + 0x01, 0x80, 0x61, 0x0E, 0x1B, 0x01, 0x80, 0x7A, 0x0B, 0x10, 0x06, 0x03, + 0x01, 0x20, 0x08, 0x00, 0x01, 0x14, 0x03, 0x00, 0x1B, 0x18, 0x05, 0x05, + 0x20, 0x2E, 0x01, 0x00, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x06, + 0x20, 0x02, 0x00, 0x1B, 0x08, 0x00, 0x14, 0x01, 0x0D, 0x0D, 0x06, 0x03, + 0x13, 0x04, 0x03, 0x2A, 0x18, 0x1A, 0x1E, 0x1B, 0x1F, 0x1B, 0x04, 0x59, + 0x00, 0x19, 0x14, 0x1D, 0x05, 0x01, 0x00, 0x13, 0x11, 0x04, 0x76, 0x00, + 0x21, 0x1A, 0x11, 0x00, 0x00, 0x2C, 0x01, 0x0A, 0x0C, 0x06, 0x02, 0x04, + 0x78, 0x00, 0x01, 0x01, 0x7F, 0x03, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0C, + 0x06, 0x09, 0x31, 0x05, 0x04, 0x01, 0x00, 0x03, 0x00, 0x04, 0x70, 0x13, + 0x02, 0x00, 0x00, 0x00, 0x14, 0x06, 0x14, 0x1F, 0x14, 0x22, 0x07, 0x17, + 0x01, 0x2D, 0x0C, 0x06, 0x08, 0x22, 0x07, 0x1E, 0x01, 0x00, 0x1B, 0x1A, + 0x00, 0x04, 0x69, 0x22, 0x1A, 0x00, 0x00, 0x14, 0x01, 0x0A, 0x0C, 0x1B, + 0x01, 0x20, 0x0B, 0x10, 0x00 +}; + +static const uint16_t t0_caddr[] = { + 0, + 5, + 10, + 15, + 19, + 24, + 29, + 67, + 149, + 384, + 396, + 431, + 450, + 460, + 479, + 523, + 534, + 539, + 549, + 574, + 601 +}; + +#define T0_INTERPRETED 29 + +#define T0_ENTER(ip, rp, slot) do { \ + const unsigned char *t0_newip; \ + uint32_t t0_lnum; \ + t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ + t0_lnum = t0_parse7E_unsigned(&t0_newip); \ + (rp) += t0_lnum; \ + *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ + (ip) = t0_newip; \ + } while (0) + +#define T0_DEFENTRY(name, slot) \ +void \ +name(void *ctx) \ +{ \ + t0_context *t0ctx = ctx; \ + t0ctx->ip = &t0_codeblock[0]; \ + T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ +} + +T0_DEFENTRY(br_pem_decoder_init_main, 38) + +#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) + +void +br_pem_decoder_run(void *t0ctx) +{ + uint32_t *dp, *rp; + const unsigned char *ip; + +#define T0_LOCAL(x) (*(rp - 2 - (x))) +#define T0_POP() (*-- dp) +#define T0_POPi() (*(int32_t *)(-- dp)) +#define T0_PEEK(x) (*(dp - 1 - (x))) +#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) +#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) +#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) +#define T0_RPOP() (*-- rp) +#define T0_RPOPi() (*(int32_t *)(-- rp)) +#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) +#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) +#define T0_ROLL(x) do { \ + size_t t0len = (size_t)(x); \ + uint32_t t0tmp = *(dp - 1 - t0len); \ + memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_SWAP() do { \ + uint32_t t0tmp = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_ROT() do { \ + uint32_t t0tmp = *(dp - 3); \ + *(dp - 3) = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_NROT() do { \ + uint32_t t0tmp = *(dp - 1); \ + *(dp - 1) = *(dp - 2); \ + *(dp - 2) = *(dp - 3); \ + *(dp - 3) = t0tmp; \ +} while (0) +#define T0_PICK(x) do { \ + uint32_t t0depth = (x); \ + T0_PUSH(T0_PEEK(t0depth)); \ +} while (0) +#define T0_CO() do { \ + goto t0_exit; \ +} while (0) +#define T0_RET() goto t0_next + + dp = ((t0_context *)t0ctx)->dp; + rp = ((t0_context *)t0ctx)->rp; + ip = ((t0_context *)t0ctx)->ip; + goto t0_next; + for (;;) { + uint32_t t0x; + + t0_next: + t0x = T0_NEXT(&ip); + if (t0x < T0_INTERPRETED) { + switch (t0x) { + int32_t t0off; + + case 0: /* ret */ + t0x = T0_RPOP(); + rp -= (t0x >> 16); + t0x &= 0xFFFF; + if (t0x == 0) { + ip = NULL; + goto t0_exit; + } + ip = &t0_codeblock[t0x]; + break; + case 1: /* literal constant */ + T0_PUSHi(t0_parse7E_signed(&ip)); + break; + case 2: /* read local */ + T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); + break; + case 3: /* write local */ + T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); + break; + case 4: /* jump */ + t0off = t0_parse7E_signed(&ip); + ip += t0off; + break; + case 5: /* jump if */ + t0off = t0_parse7E_signed(&ip); + if (T0_POP()) { + ip += t0off; + } + break; + case 6: /* jump if not */ + t0off = t0_parse7E_signed(&ip); + if (!T0_POP()) { + ip += t0off; + } + break; + case 7: { + /* + */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a + b); + + } + break; + case 8: { + /* - */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a - b); + + } + break; + case 9: { + /* < */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a < b)); + + } + break; + case 10: { + /* << */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x << c); + + } + break; + case 11: { + /* <= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a <= b)); + + } + break; + case 12: { + /* <> */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a != b)); + + } + break; + case 13: { + /* = */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a == b)); + + } + break; + case 14: { + /* >= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a >= b)); + + } + break; + case 15: { + /* >> */ + + int c = (int)T0_POPi(); + int32_t x = T0_POPi(); + T0_PUSHi(x >> c); + + } + break; + case 16: { + /* and */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a & b); + + } + break; + case 17: { + /* co */ + T0_CO(); + } + break; + case 18: { + /* data-get8 */ + + size_t addr = T0_POP(); + T0_PUSH(t0_datablock[addr]); + + } + break; + case 19: { + /* drop */ + (void)T0_POP(); + } + break; + case 20: { + /* dup */ + T0_PUSH(T0_PEEK(0)); + } + break; + case 21: { + /* flush-buf */ + + if (CTX->ptr > 0) { + if (CTX->dest) { + CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr); + } + CTX->ptr = 0; + } + + } + break; + case 22: { + /* from-base64 */ + + uint32_t c = T0_POP(); + uint32_t p, q, r, z; + p = c - 0x41; + q = c - 0x61; + r = c - 0x30; + + z = ((p + 2) & -LT(p, 26)) + | ((q + 28) & -LT(q, 26)) + | ((r + 54) & -LT(r, 10)) + | (64 & -EQ(c, 0x2B)) + | (65 & -EQ(c, 0x2F)) + | EQ(c, 0x3D); + T0_PUSHi((int32_t)z - 2); + + } + break; + case 23: { + /* get8 */ + + size_t addr = T0_POP(); + T0_PUSH(*((unsigned char *)CTX + addr)); + + } + break; + case 24: { + /* over */ + T0_PUSH(T0_PEEK(1)); + } + break; + case 25: { + /* read8-native */ + + if (CTX->hlen > 0) { + T0_PUSH(*CTX->hbuf ++); + CTX->hlen --; + } else { + T0_PUSHi(-1); + } + + } + break; + case 26: { + /* set8 */ + + size_t addr = T0_POP(); + unsigned x = T0_POP(); + *((unsigned char *)CTX + addr) = x; + + } + break; + case 27: { + /* swap */ + T0_SWAP(); + } + break; + case 28: { + /* write8 */ + + unsigned char x = (unsigned char)T0_POP(); + CTX->buf[CTX->ptr ++] = x; + if (CTX->ptr == sizeof CTX->buf) { + if (CTX->dest) { + CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf); + } + CTX->ptr = 0; + } + + } + break; + } + + } else { + T0_ENTER(ip, rp, t0x); + } + } +t0_exit: + ((t0_context *)t0ctx)->dp = dp; + ((t0_context *)t0ctx)->rp = rp; + ((t0_context *)t0ctx)->ip = ip; +} diff --git a/BearSSL-OG/libbearssl/src/codec/pemdec.t0 b/BearSSL-OG/libbearssl/src/codec/pemdec.t0 new file mode 100644 index 0000000..2237abb --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/pemdec.t0 @@ -0,0 +1,314 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +preamble { + +#include "inner.h" + +#define CTX ((br_pem_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu))) + +/* see bearssl_pem.h */ +void +br_pem_decoder_init(br_pem_decoder_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->cpu.dp = &ctx->dp_stack[0]; + ctx->cpu.rp = &ctx->rp_stack[0]; + br_pem_decoder_init_main(&ctx->cpu); + br_pem_decoder_run(&ctx->cpu); +} + +/* see bearssl_pem.h */ +size_t +br_pem_decoder_push(br_pem_decoder_context *ctx, + const void *data, size_t len) +{ + if (ctx->event) { + return 0; + } + ctx->hbuf = data; + ctx->hlen = len; + br_pem_decoder_run(&ctx->cpu); + return len - ctx->hlen; +} + +/* see bearssl_pem.h */ +int +br_pem_decoder_event(br_pem_decoder_context *ctx) +{ + int event; + + event = ctx->event; + ctx->event = 0; + return event; +} + +} + +\ Define a word that evaluates to the address of a field within the +\ decoder context. +: addr: + next-word { field } + "addr-" field + 0 1 define-word + 0 8191 "offsetof(br_pem_decoder_context, " field + ")" + make-CX + postpone literal postpone ; ; + +addr: event +addr: name +addr: buf +addr: ptr + +\ Set a byte at a specific address (offset within the context). +cc: set8 ( value addr -- ) { + size_t addr = T0_POP(); + unsigned x = T0_POP(); + *((unsigned char *)CTX + addr) = x; +} + +\ Get a byte at a specific address (offset within the context). +cc: get8 ( addr -- value ) { + size_t addr = T0_POP(); + T0_PUSH(*((unsigned char *)CTX + addr)); +} + +\ Send an event. +: send-event ( event -- ) + addr-event set8 co ; + +\ Low-level function to read a single byte. Returned value is the byte +\ (0 to 255), or -1 if there is no available data. +cc: read8-native ( -- x ) { + if (CTX->hlen > 0) { + T0_PUSH(*CTX->hbuf ++); + CTX->hlen --; + } else { + T0_PUSHi(-1); + } +} + +\ Read next byte. Block until the next byte is available. +: read8 ( -- x ) + begin read8-native dup 0< ifnot ret then drop co again ; + +\ Read bytes until next end-of-line. +: skip-newline ( -- ) + begin read8 `\n <> while repeat ; + +\ Read bytes until next end-of-line; verify that they are all whitespace. +\ This returns -1 if they were all whitespace, 0 otherwise. +: skip-newline-ws ( -- bool ) + -1 { r } + begin read8 dup `\n <> while ws? ifnot 0 >r then repeat + drop r ; + +\ Normalise a byte to uppercase (ASCII only). +: norm-upper ( x -- x ) + dup dup `a >= swap `z <= and if 32 - then ; + +\ Read bytes and compare with the provided string. On mismatch, the +\ rest of the line is consumed. Matching is not case sensitive. +: match-string ( str -- bool ) + begin + dup data-get8 norm-upper dup ifnot 2drop -1 ret then + read8 norm-upper dup `\n = if drop 2drop 0 ret then + = ifnot drop skip-newline 0 ret then + 1+ + again ; + +\ Read bytes into the provided buffer, but no more than the provided +\ count. Reading stops when end-of-line is reached. Returned value +\ is the count of bytes written to the buffer, or 0 if the buffer size +\ was exceeded. All bytes are normalised to uppercase (ASCII only). +: read-bytes ( addr len -- len ) + dup { orig-len } + swap + begin + over ifnot 2drop skip-newline 0 ret then + read8 dup `\n = if 2drop orig-len swap - ret then + dup `\r = if drop else norm-upper over set8 then + 1+ swap 1- swap + again ; + +\ Remove trailing dashes from the name buffer. +: trim-dashes ( len -- ) + begin dup while + 1- + dup addr-name + get8 `- <> if + addr-name + 1+ 0 swap set8 ret + then + repeat + addr-name set8 ; + +\ Scan input for next "begin" banner. +: next-banner-begin ( -- ) + begin + "-----BEGIN " match-string if + addr-name 127 read-bytes + dup if trim-dashes ret then + drop + then + again ; + +\ Convert a Base64 character to its numerical value. Returned value is +\ 0 to 63 for Base64 characters, -1 for '=', and -2 for all other characters. +cc: from-base64 ( char -- x ) { + uint32_t c = T0_POP(); + uint32_t p, q, r, z; + p = c - 0x41; + q = c - 0x61; + r = c - 0x30; + + z = ((p + 2) & -LT(p, 26)) + | ((q + 28) & -LT(q, 26)) + | ((r + 54) & -LT(r, 10)) + | (64 & -EQ(c, 0x2B)) + | (65 & -EQ(c, 0x2F)) + | EQ(c, 0x3D); + T0_PUSHi((int32_t)z - 2); +} + +\ Test whether a character is whitespace (but not a newline). +: ws? ( x -- bool ) + dup `\n <> swap 32 <= and ; + +\ Read next character, skipping whitespace (except newline). +: next-nonws ( -- x ) + begin + read8 dup ws? ifnot ret then + drop + again ; + +\ Write one byte in the output buffer. +cc: write8 ( x -- ) { + unsigned char x = (unsigned char)T0_POP(); + CTX->buf[CTX->ptr ++] = x; + if (CTX->ptr == sizeof CTX->buf) { + if (CTX->dest) { + CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf); + } + CTX->ptr = 0; + } +} + +\ Flush the output buffer. +cc: flush-buf ( -- ) { + if (CTX->ptr > 0) { + if (CTX->dest) { + CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr); + } + CTX->ptr = 0; + } +} + +\ Decode the four next Base64 characters. Returned value is: +\ 0 quartet processed, three bytes produced. +\ -1 dash encountered as first character (no leading whitespace). +\ 1 quartet processed, one or two bytes produced, terminator reached. +\ 2 end-of-line reached. +\ 3 error. +\ For all positive return values, the remaining of the current line has been +\ consumed. +: decode-next-quartet ( -- r ) + \ Process first character. It may be a dash. + read8 dup `- = if drop -1 ret then + dup ws? if drop next-nonws then + dup `\n = if drop 2 ret then + from-base64 dup 0< if drop skip-newline 3 ret then + { acc } + + \ Second character. + next-nonws dup `\n = if drop 3 ret then + from-base64 dup 0< if drop skip-newline 3 ret then + acc 6 << + >acc + + \ Third character: may be an equal sign. + next-nonws dup `\n = if drop 3 ret then + dup `= = if + \ Fourth character must be an equal sign. + drop + next-nonws dup `\n = if drop 3 ret then + skip-newline-ws ifnot drop 3 ret then + `= <> if 3 ret then + acc 0x0F and if 3 ret then + acc 4 >> write8 + 1 ret + then + from-base64 dup 0< if drop skip-newline 3 ret then + acc 6 << + >acc + + \ Fourth character: may be an equal sign. + next-nonws dup `\n = if drop 3 ret then + dup `= = if + drop skip-newline-ws ifnot 3 ret then + acc 0x03 and if 3 ret then + acc 10 >> write8 + acc 2 >> write8 + 1 ret + then + from-base64 dup 0< if drop skip-newline 3 ret then + acc 6 << + >acc + acc 16 >> write8 + acc 8 >> write8 + acc write8 + 0 ; + +\ Check trailer line (possibly, the leading dash has been read). This +\ sends the appropriate event. +: check-trailer ( bool -- ) + ifnot + begin read8 dup `\n = while drop repeat + `- <> if skip-newline 3 send-event ret then + then + "----END " match-string ifnot 3 send-event ret then + flush-buf + skip-newline 2 send-event ; + +\ Decode one line worth of characters. Returned value is 0 if the end of the +\ object is reached, -1 otherwise. The end of object or error event is sent. +: decode-line ( -- bool ) + -1 { first } + begin + decode-next-quartet + case + 0 of endof + -1 of + first ifnot + skip-newline 3 send-event + else + -1 check-trailer + then + 0 ret + endof + 1 of 0 check-trailer 0 ret endof + 2 of -1 ret endof + + \ On decoding error + drop 3 send-event 0 ret + endcase + 0 >first + again ; + +: main ( -- ! ) + begin + next-banner-begin 1 send-event + begin decode-line while repeat + again ; diff --git a/BearSSL-OG/libbearssl/src/codec/pemenc.c b/BearSSL-OG/libbearssl/src/codec/pemenc.c new file mode 100644 index 0000000..236601e --- /dev/null +++ b/BearSSL-OG/libbearssl/src/codec/pemenc.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * Get the appropriate Base64 character for a numeric value in the + * 0..63 range. This is constant-time. + */ +static char +b64char(uint32_t x) +{ + /* + * Values 0 to 25 map to 0x41..0x5A ('A' to 'Z') + * Values 26 to 51 map to 0x61..0x7A ('a' to 'z') + * Values 52 to 61 map to 0x30..0x39 ('0' to '9') + * Value 62 maps to 0x2B ('+') + * Value 63 maps to 0x2F ('/') + */ + uint32_t a, b, c; + + a = x - 26; + b = x - 52; + c = x - 62; + + /* + * Looking at bits 8..15 of values a, b and c: + * + * x a b c + * --------------------- + * 0..25 FF FF FF + * 26..51 00 FF FF + * 52..61 00 00 FF + * 62..63 00 00 00 + */ + return (char)(((x + 0x41) & ((a & b & c) >> 8)) + | ((x + (0x61 - 26)) & ((~a & b & c) >> 8)) + | ((x - (52 - 0x30)) & ((~a & ~b & c) >> 8)) + | ((0x2B + ((x & 1) << 2)) & (~(a | b | c) >> 8))); +} + +/* see bearssl_pem.h */ +size_t +br_pem_encode(void *dest, const void *data, size_t len, + const char *banner, unsigned flags) +{ + size_t dlen, banner_len, lines; + char *d; + unsigned char *buf; + size_t u; + int off, lim; + + banner_len = strlen(banner); + /* FIXME: try to avoid divisions here, as they may pull + an extra libc function. */ + if ((flags & BR_PEM_LINE64) != 0) { + lines = (len + 47) / 48; + } else { + lines = (len + 56) / 57; + } + dlen = (banner_len << 1) + 30 + (((len + 2) / 3) << 2) + + lines + 2; + if ((flags & BR_PEM_CRLF) != 0) { + dlen += lines + 2; + } + + if (dest == NULL) { + return dlen; + } + + d = dest; + + /* + * We always move the source data to the end of output buffer; + * the encoding process never "catches up" except at the very + * end. This also handles all conditions of partial or total + * overlap. + */ + buf = (unsigned char *)d + dlen - len; + memmove(buf, data, len); + + memcpy(d, "-----BEGIN ", 11); + d += 11; + memcpy(d, banner, banner_len); + d += banner_len; + memcpy(d, "-----", 5); + d += 5; + if ((flags & BR_PEM_CRLF) != 0) { + *d ++ = 0x0D; + } + *d ++ = 0x0A; + + off = 0; + lim = (flags & BR_PEM_LINE64) != 0 ? 16 : 19; + for (u = 0; (u + 2) < len; u += 3) { + uint32_t w; + + w = ((uint32_t)buf[u] << 16) + | ((uint32_t)buf[u + 1] << 8) + | (uint32_t)buf[u + 2]; + *d ++ = b64char(w >> 18); + *d ++ = b64char((w >> 12) & 0x3F); + *d ++ = b64char((w >> 6) & 0x3F); + *d ++ = b64char(w & 0x3F); + if (++ off == lim) { + off = 0; + if ((flags & BR_PEM_CRLF) != 0) { + *d ++ = 0x0D; + } + *d ++ = 0x0A; + } + } + if (u < len) { + uint32_t w; + + w = (uint32_t)buf[u] << 16; + if (u + 1 < len) { + w |= (uint32_t)buf[u + 1] << 8; + } + *d ++ = b64char(w >> 18); + *d ++ = b64char((w >> 12) & 0x3F); + if (u + 1 < len) { + *d ++ = b64char((w >> 6) & 0x3F); + } else { + *d ++ = 0x3D; + } + *d ++ = 0x3D; + off ++; + } + if (off != 0) { + if ((flags & BR_PEM_CRLF) != 0) { + *d ++ = 0x0D; + } + *d ++ = 0x0A; + } + + memcpy(d, "-----END ", 9); + d += 9; + memcpy(d, banner, banner_len); + d += banner_len; + memcpy(d, "-----", 5); + d += 5; + if ((flags & BR_PEM_CRLF) != 0) { + *d ++ = 0x0D; + } + *d ++ = 0x0A; + + /* Final zero, not counted in returned length. */ + *d ++ = 0x00; + + return dlen; +} diff --git a/BearSSL-OG/libbearssl/src/config.h b/BearSSL-OG/libbearssl/src/config.h new file mode 100644 index 0000000..dcc3a2b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/config.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef CONFIG_H__ +#define CONFIG_H__ + +/* + * This file contains compile-time flags that can override the + * autodetection performed in relevant files. Each flag is a macro; it + * deactivates the feature if defined to 0, activates it if defined to a + * non-zero integer (normally 1). If the macro is not defined, then + * autodetection applies. + */ + +/* + * When BR_64 is enabled, 64-bit integer types are assumed to be + * efficient (i.e. the architecture has 64-bit registers and can + * do 64-bit operations as fast as 32-bit operations). + * +#define BR_64 1 + */ + +/* + * When BR_LOMUL is enabled, then multiplications of 32-bit values whose + * result are truncated to the low 32 bits are assumed to be + * substantially more efficient than 32-bit multiplications that yield + * 64-bit results. This is typically the case on low-end ARM Cortex M + * systems (M0, M0+, M1, and arguably M3 and M4 as well). + * +#define BR_LOMUL 1 + */ + +/* + * When BR_SLOW_MUL is enabled, multiplications are assumed to be + * substantially slow with regards to other integer operations, thus + * making it worth to make more operations for a given task if it allows + * using less multiplications. + * +#define BR_SLOW_MUL 1 + */ + +/* + * When BR_SLOW_MUL15 is enabled, short multplications (on 15-bit words) + * are assumed to be substantially slow with regards to other integer + * operations, thus making it worth to make more integer operations if + * it allows using less multiplications. + * +#define BR_SLOW_MUL15 1 + */ + +/* + * When BR_CT_MUL31 is enabled, multiplications of 31-bit values (used + * in the "i31" big integer implementation) use an alternate implementation + * which is slower and larger than the normal multiplication, but should + * ensure constant-time multiplications even on architectures where the + * multiplication opcode takes a variable number of cycles to complete. + * +#define BR_CT_MUL31 1 + */ + +/* + * When BR_CT_MUL15 is enabled, multiplications of 15-bit values (held + * in 32-bit words) use an alternate implementation which is slower and + * larger than the normal multiplication, but should ensure + * constant-time multiplications on most/all architectures where the + * basic multiplication is not constant-time. +#define BR_CT_MUL15 1 + */ + +/* + * When BR_NO_ARITH_SHIFT is enabled, arithmetic right shifts (with sign + * extension) are performed with a sequence of operations which is bigger + * and slower than a simple right shift on a signed value. This avoids + * relying on an implementation-defined behaviour. However, most if not + * all C compilers use sign extension for right shifts on signed values, + * so this alternate macro is disabled by default. +#define BR_NO_ARITH_SHIFT 1 + */ + +/* + * When BR_RDRAND is enabled, the SSL engine will use the RDRAND opcode + * to automatically obtain quality randomness for seeding its internal + * PRNG. Since that opcode is present only in recent x86 CPU, its + * support is dynamically tested; if the current CPU does not support + * it, then another random source will be used, such as /dev/urandom or + * CryptGenRandom(). + * +#define BR_RDRAND 1 + */ + +/* + * When BR_USE_GETENTROPY is enabled, the SSL engine will use the + * getentropy() function to obtain quality randomness for seeding its + * internal PRNG. On Linux and FreeBSD, getentropy() is implemented by + * the standard library with the system call getrandom(); on OpenBSD, + * getentropy() is the system call, and there is no getrandom() wrapper, + * hence the use of the getentropy() function for maximum portability. + * + * If the getentropy() call fails, and BR_USE_URANDOM is not explicitly + * disabled, then /dev/urandom will be used as a fallback mechanism. On + * FreeBSD and OpenBSD, this does not change much, since /dev/urandom + * will block if not enough entropy has been obtained since last boot. + * On Linux, /dev/urandom might not block, which can be troublesome in + * early boot stages, which is why getentropy() is preferred. + * +#define BR_USE_GETENTROPY 1 + */ + +/* + * When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom + * to automatically obtain quality randomness for seeding its internal + * PRNG. + * +#define BR_USE_URANDOM 1 + */ + +/* + * When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32 + * (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to + * automatically obtain quality randomness for seeding its internal PRNG. + * + * Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the + * former takes precedence. + * +#define BR_USE_WIN32_RAND 1 + */ + +/* + * When BR_USE_XBOX_RAND is enabled, the SSL engine will use custom code for xbox + * + * Note: if both BR_USE_URANDOM and BR_USE_XBOX_RAND are defined, the + * former takes precedence. + * +#define BR_USE_XBOX_RAND 1 + */ + +/* + * When BR_USE_UNIX_TIME is enabled, the X.509 validation engine obtains + * the current time from the OS by calling time(), and assuming that the + * returned value (a 'time_t') is an integer that counts time in seconds + * since the Unix Epoch (Jan 1st, 1970, 00:00 UTC). + * +#define BR_USE_UNIX_TIME 1 + */ + +/* + * When BR_USE_WIN32_TIME is enabled, the X.509 validation engine obtains + * the current time from the OS by calling the Win32 function + * GetSystemTimeAsFileTime(). + * + * Note: if both BR_USE_UNIX_TIME and BR_USE_WIN32_TIME are defined, the + * former takes precedence. + * +#define BR_USE_WIN32_TIME 1 + */ + +/* + * When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with + * inline assembly which is shorter and/or faster. This should be used + * only when all of the following are true: + * - target architecture is ARM in Thumb mode + * - target endianness is little-endian + * - compiler is GCC (or GCC-compatible for inline assembly syntax) + * + * This is meant for the low-end cores (Cortex M0, M0+, M1, M3). + * Note: if BR_LOMUL is not explicitly enabled or disabled, then + * enabling BR_ARMEL_CORTEXM_GCC also enables BR_LOMUL. + * +#define BR_ARMEL_CORTEXM_GCC 1 + */ + +/* + * When BR_AES_X86NI is enabled, the AES implementation using the x86 "NI" + * instructions (dedicated AES opcodes) will be compiled. If this is not + * enabled explicitly, then that AES implementation will be compiled only + * if a compatible compiler is detected. If set explicitly to 0, the + * implementation will not be compiled at all. + * +#define BR_AES_X86NI 1 + */ + +/* + * When BR_SSE2 is enabled, SSE2 intrinsics will be used for some + * algorithm implementations that use them (e.g. chacha20_sse2). If this + * is not enabled explicitly, then support for SSE2 intrinsics will be + * automatically detected. If set explicitly to 0, then SSE2 code will + * not be compiled at all. + * +#define BR_SSE2 0 + */ + +/* + * When BR_POWER8 is enabled, the AES implementation using the POWER ISA + * 2.07 opcodes (available on POWER8 processors and later) is compiled. + * If this is not enabled explicitly, then that implementation will be + * compiled only if a compatible compiler is detected, _and_ the target + * architecture is POWER8 or later. + * +#define BR_POWER8 1 + */ + +/* + * When BR_INT128 is enabled, then code using the 'unsigned __int64' + * and 'unsigned __int128' types will be used to leverage 64x64->128 + * unsigned multiplications. This should work with GCC and compatible + * compilers on 64-bit architectures. + * +#define BR_INT128 0 + */ + +/* + * When BR_UMUL128 is enabled, then code using the '_umul128()' and + * '_addcarry_u64()' intrinsics will be used to implement 64x64->128 + * unsigned multiplications. This should work on Visual C on x64 systems. + * +#define BR_UMUL128 0 + */ + +/* + * When BR_LE_UNALIGNED is enabled, then the current architecture is + * assumed to use little-endian encoding for integers, and to tolerate + * unaligned accesses with no or minimal time penalty. + * +#define BR_LE_UNALIGNED 1 + */ + +/* + * When BR_BE_UNALIGNED is enabled, then the current architecture is + * assumed to use big-endian encoding for integers, and to tolerate + * unaligned accesses with no or minimal time penalty. + * +#define BR_BE_UNALIGNED 1 + */ + +#endif diff --git a/BearSSL-OG/libbearssl/src/ec/ec_all_m15.c b/BearSSL-OG/libbearssl/src/ec/ec_all_m15.c new file mode 100644 index 0000000..bb550e1 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_all_m15.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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 const unsigned char * +api_generator(int curve, size_t *len) +{ + switch (curve) { + case BR_EC_secp256r1: + return br_ec_p256_m15.generator(curve, len); + case BR_EC_curve25519: + return br_ec_c25519_m15.generator(curve, len); + default: + return br_ec_prime_i15.generator(curve, len); + } +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + switch (curve) { + case BR_EC_secp256r1: + return br_ec_p256_m15.order(curve, len); + case BR_EC_curve25519: + return br_ec_c25519_m15.order(curve, len); + default: + return br_ec_prime_i15.order(curve, len); + } +} + +static size_t +api_xoff(int curve, size_t *len) +{ + switch (curve) { + case BR_EC_secp256r1: + return br_ec_p256_m15.xoff(curve, len); + case BR_EC_curve25519: + return br_ec_c25519_m15.xoff(curve, len); + default: + return br_ec_prime_i15.xoff(curve, len); + } +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *kb, size_t kblen, int curve) +{ + switch (curve) { + case BR_EC_secp256r1: + return br_ec_p256_m15.mul(G, Glen, kb, kblen, curve); + case BR_EC_curve25519: + return br_ec_c25519_m15.mul(G, Glen, kb, kblen, curve); + default: + return br_ec_prime_i15.mul(G, Glen, kb, kblen, curve); + } +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + switch (curve) { + case BR_EC_secp256r1: + return br_ec_p256_m15.mulgen(R, x, xlen, curve); + case BR_EC_curve25519: + return br_ec_c25519_m15.mulgen(R, x, xlen, curve); + default: + return br_ec_prime_i15.mulgen(R, x, xlen, curve); + } +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + switch (curve) { + case BR_EC_secp256r1: + return br_ec_p256_m15.muladd(A, B, len, + x, xlen, y, ylen, curve); + case BR_EC_curve25519: + return br_ec_c25519_m15.muladd(A, B, len, + x, xlen, y, ylen, curve); + default: + return br_ec_prime_i15.muladd(A, B, len, + x, xlen, y, ylen, curve); + } +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_all_m15 = { + (uint32_t)0x23800000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_all_m31.c b/BearSSL-OG/libbearssl/src/ec/ec_all_m31.c new file mode 100644 index 0000000..8fd8c3c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_all_m31.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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 const unsigned char * +api_generator(int curve, size_t *len) +{ + switch (curve) { + case BR_EC_secp256r1: +#if BR_INT128 || BR_UMUL128 + return br_ec_p256_m64.generator(curve, len); +#else + return br_ec_p256_m31.generator(curve, len); +#endif + case BR_EC_curve25519: +#if BR_INT128 || BR_UMUL128 + return br_ec_c25519_m64.generator(curve, len); +#else + return br_ec_c25519_m31.generator(curve, len); +#endif + default: + return br_ec_prime_i31.generator(curve, len); + } +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + switch (curve) { + case BR_EC_secp256r1: +#if BR_INT128 || BR_UMUL128 + return br_ec_p256_m64.order(curve, len); +#else + return br_ec_p256_m31.order(curve, len); +#endif + case BR_EC_curve25519: +#if BR_INT128 || BR_UMUL128 + return br_ec_c25519_m64.order(curve, len); +#else + return br_ec_c25519_m31.order(curve, len); +#endif + default: + return br_ec_prime_i31.order(curve, len); + } +} + +static size_t +api_xoff(int curve, size_t *len) +{ + switch (curve) { + case BR_EC_secp256r1: +#if BR_INT128 || BR_UMUL128 + return br_ec_p256_m64.xoff(curve, len); +#else + return br_ec_p256_m31.xoff(curve, len); +#endif + case BR_EC_curve25519: +#if BR_INT128 || BR_UMUL128 + return br_ec_c25519_m64.xoff(curve, len); +#else + return br_ec_c25519_m31.xoff(curve, len); +#endif + default: + return br_ec_prime_i31.xoff(curve, len); + } +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *kb, size_t kblen, int curve) +{ + switch (curve) { + case BR_EC_secp256r1: +#if BR_INT128 || BR_UMUL128 + return br_ec_p256_m64.mul(G, Glen, kb, kblen, curve); +#else + return br_ec_p256_m31.mul(G, Glen, kb, kblen, curve); +#endif + case BR_EC_curve25519: +#if BR_INT128 || BR_UMUL128 + return br_ec_c25519_m64.mul(G, Glen, kb, kblen, curve); +#else + return br_ec_c25519_m31.mul(G, Glen, kb, kblen, curve); +#endif + default: + return br_ec_prime_i31.mul(G, Glen, kb, kblen, curve); + } +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + switch (curve) { + case BR_EC_secp256r1: +#if BR_INT128 || BR_UMUL128 + return br_ec_p256_m64.mulgen(R, x, xlen, curve); +#else + return br_ec_p256_m31.mulgen(R, x, xlen, curve); +#endif + case BR_EC_curve25519: +#if BR_INT128 || BR_UMUL128 + return br_ec_c25519_m64.mulgen(R, x, xlen, curve); +#else + return br_ec_c25519_m31.mulgen(R, x, xlen, curve); +#endif + default: + return br_ec_prime_i31.mulgen(R, x, xlen, curve); + } +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + switch (curve) { + case BR_EC_secp256r1: +#if BR_INT128 || BR_UMUL128 + return br_ec_p256_m64.muladd(A, B, len, + x, xlen, y, ylen, curve); +#else + return br_ec_p256_m31.muladd(A, B, len, + x, xlen, y, ylen, curve); +#endif + case BR_EC_curve25519: +#if BR_INT128 || BR_UMUL128 + return br_ec_c25519_m64.muladd(A, B, len, + x, xlen, y, ylen, curve); +#else + return br_ec_c25519_m31.muladd(A, B, len, + x, xlen, y, ylen, curve); +#endif + default: + return br_ec_prime_i31.muladd(A, B, len, + x, xlen, y, ylen, curve); + } +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_all_m31 = { + (uint32_t)0x23800000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_c25519_i15.c b/BearSSL-OG/libbearssl/src/ec/ec_c25519_i15.c new file mode 100644 index 0000000..8fadcf4 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_c25519_i15.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Parameters for the field: + * - field modulus p = 2^255-19 + * - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p) + */ + +static const uint16_t C255_P[] = { + 0x0110, + 0x7FED, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, + 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, + 0x7FFF +}; + +#define P0I 0x4A1B + +static const uint16_t C255_R2[] = { + 0x0110, + 0x0169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000 +}; + +/* obsolete +#include +#include +static void +print_int_mont(const char *name, const uint16_t *x) +{ + uint16_t y[18]; + unsigned char tmp[32]; + size_t u; + + printf("%s = ", name); + memcpy(y, x, sizeof y); + br_i15_from_monty(y, C255_P, P0I); + br_i15_encode(tmp, sizeof tmp, y); + for (u = 0; u < sizeof tmp; u ++) { + printf("%02X", tmp[u]); + } + printf("\n"); +} +*/ + +static const uint16_t C255_A24[] = { + 0x0110, + 0x45D3, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000 +}; + +static const unsigned char GEN[] = { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char ORDER[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return GEN; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return ORDER; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 0; +} + +static void +cswap(uint16_t *a, uint16_t *b, uint32_t ctl) +{ + int i; + + ctl = -ctl; + for (i = 0; i < 18; i ++) { + uint32_t aw, bw, tw; + + aw = a[i]; + bw = b[i]; + tw = ctl & (aw ^ bw); + a[i] = aw ^ tw; + b[i] = bw ^ tw; + } +} + +static void +c255_add(uint16_t *d, const uint16_t *a, const uint16_t *b) +{ + uint32_t ctl; + uint16_t t[18]; + + memcpy(t, a, sizeof t); + ctl = br_i15_add(t, b, 1); + ctl |= NOT(br_i15_sub(t, C255_P, 0)); + br_i15_sub(t, C255_P, ctl); + memcpy(d, t, sizeof t); +} + +static void +c255_sub(uint16_t *d, const uint16_t *a, const uint16_t *b) +{ + uint16_t t[18]; + + memcpy(t, a, sizeof t); + br_i15_add(t, C255_P, br_i15_sub(t, b, 1)); + memcpy(d, t, sizeof t); +} + +static void +c255_mul(uint16_t *d, const uint16_t *a, const uint16_t *b) +{ + uint16_t t[18]; + + br_i15_montymul(t, a, b, C255_P, P0I); + memcpy(d, t, sizeof t); +} + +static void +byteswap(unsigned char *G) +{ + int i; + + for (i = 0; i < 16; i ++) { + unsigned char t; + + t = G[i]; + G[i] = G[31 - i]; + G[31 - i] = t; + } +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *kb, size_t kblen, int curve) +{ +#define ILEN (18 * sizeof(uint16_t)) + + /* + * The a[] and b[] arrays have an extra word to allow for + * decoding without using br_i15_decode_reduce(). + */ + uint16_t x1[18], x2[18], x3[18], z2[18], z3[18]; + uint16_t a[19], aa[18], b[19], bb[18]; + uint16_t c[18], d[18], e[18], da[18], cb[18]; + unsigned char k[32]; + uint32_t swap; + int i; + + (void)curve; + + /* + * Points are encoded over exactly 32 bytes. Multipliers must fit + * in 32 bytes as well. + * RFC 7748 mandates that the high bit of the last point byte must + * be ignored/cleared. + */ + if (Glen != 32 || kblen > 32) { + return 0; + } + G[31] &= 0x7F; + + /* + * Byteswap the point encoding, because it uses little-endian, and + * the generic decoding routine uses big-endian. + */ + byteswap(G); + + /* + * Decode the point ('u' coordinate). This should be reduced + * modulo p, but we prefer to avoid the dependency on + * br_i15_decode_reduce(). Instead, we use br_i15_decode_mod() + * with a synthetic modulus of value 2^255 (this must work + * since G was truncated to 255 bits), then use a conditional + * subtraction. We use br_i15_decode_mod() and not + * br_i15_decode(), because the ec_prime_i15 implementation uses + * the former but not the latter. + * br_i15_decode_reduce(a, G, 32, C255_P); + */ + br_i15_zero(b, 0x111); + b[18] = 1; + br_i15_decode_mod(a, G, 32, b); + a[0] = 0x110; + br_i15_sub(a, C255_P, NOT(br_i15_sub(a, C255_P, 0))); + + /* + * Initialise variables x1, x2, z2, x3 and z3. We set all of them + * into Montgomery representation. + */ + br_i15_montymul(x1, a, C255_R2, C255_P, P0I); + memcpy(x3, x1, ILEN); + br_i15_zero(z2, C255_P[0]); + memcpy(x2, z2, ILEN); + x2[1] = 19; + memcpy(z3, x2, ILEN); + + memset(k, 0, (sizeof k) - kblen); + memcpy(k + (sizeof k) - kblen, kb, kblen); + k[31] &= 0xF8; + k[0] &= 0x7F; + k[0] |= 0x40; + + /* obsolete + print_int_mont("x1", x1); + */ + + swap = 0; + for (i = 254; i >= 0; i --) { + uint32_t kt; + + kt = (k[31 - (i >> 3)] >> (i & 7)) & 1; + swap ^= kt; + cswap(x2, x3, swap); + cswap(z2, z3, swap); + swap = kt; + + /* obsolete + print_int_mont("x2", x2); + print_int_mont("z2", z2); + print_int_mont("x3", x3); + print_int_mont("z3", z3); + */ + + c255_add(a, x2, z2); + c255_mul(aa, a, a); + c255_sub(b, x2, z2); + c255_mul(bb, b, b); + c255_sub(e, aa, bb); + c255_add(c, x3, z3); + c255_sub(d, x3, z3); + c255_mul(da, d, a); + c255_mul(cb, c, b); + + /* obsolete + print_int_mont("a ", a); + print_int_mont("aa", aa); + print_int_mont("b ", b); + print_int_mont("bb", bb); + print_int_mont("e ", e); + print_int_mont("c ", c); + print_int_mont("d ", d); + print_int_mont("da", da); + print_int_mont("cb", cb); + */ + + c255_add(x3, da, cb); + c255_mul(x3, x3, x3); + c255_sub(z3, da, cb); + c255_mul(z3, z3, z3); + c255_mul(z3, z3, x1); + c255_mul(x2, aa, bb); + c255_mul(z2, C255_A24, e); + c255_add(z2, z2, aa); + c255_mul(z2, e, z2); + + /* obsolete + print_int_mont("x2", x2); + print_int_mont("z2", z2); + print_int_mont("x3", x3); + print_int_mont("z3", z3); + */ + } + cswap(x2, x3, swap); + cswap(z2, z3, swap); + + /* + * Inverse z2 with a modular exponentiation. This is a simple + * square-and-multiply algorithm; we mutualise most non-squarings + * since the exponent contains almost only ones. + */ + memcpy(a, z2, ILEN); + for (i = 0; i < 15; i ++) { + c255_mul(a, a, a); + c255_mul(a, a, z2); + } + memcpy(b, a, ILEN); + for (i = 0; i < 14; i ++) { + int j; + + for (j = 0; j < 16; j ++) { + c255_mul(b, b, b); + } + c255_mul(b, b, a); + } + for (i = 14; i >= 0; i --) { + c255_mul(b, b, b); + if ((0xFFEB >> i) & 1) { + c255_mul(b, z2, b); + } + } + c255_mul(b, x2, b); + + /* + * To avoid a dependency on br_i15_from_monty(), we use a + * Montgomery multiplication with 1. + * memcpy(x2, b, ILEN); + * br_i15_from_monty(x2, C255_P, P0I); + */ + br_i15_zero(a, C255_P[0]); + a[1] = 1; + br_i15_montymul(x2, a, b, C255_P, P0I); + + br_i15_encode(G, 32, x2); + byteswap(G); + return 1; + +#undef ILEN +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + const unsigned char *G; + size_t Glen; + + G = api_generator(curve, &Glen); + memcpy(R, G, Glen); + api_mul(R, Glen, x, xlen, curve); + return Glen; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + /* + * We don't implement this method, since it is used for ECDSA + * only, and there is no ECDSA over Curve25519 (which instead + * uses EdDSA). + */ + (void)A; + (void)B; + (void)len; + (void)x; + (void)xlen; + (void)y; + (void)ylen; + (void)curve; + return 0; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_c25519_i15 = { + (uint32_t)0x20000000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_c25519_i31.c b/BearSSL-OG/libbearssl/src/ec/ec_c25519_i31.c new file mode 100644 index 0000000..f8ffc2c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_c25519_i31.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Parameters for the field: + * - field modulus p = 2^255-19 + * - R^2 mod p (R = 2^(31k) for the smallest k such that R >= p) + */ + +static const uint32_t C255_P[] = { + 0x00000107, + 0x7FFFFFED, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0000007F +}; + +#define P0I 0x286BCA1B + +static const uint32_t C255_R2[] = { + 0x00000107, + 0x00000000, 0x02D20000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +static const uint32_t C255_A24[] = { + 0x00000107, + 0x53000000, 0x0000468B, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +/* obsolete +#include +#include +static void +print_int_mont(const char *name, const uint32_t *x) +{ + uint32_t y[10]; + unsigned char tmp[32]; + size_t u; + + printf("%s = ", name); + memcpy(y, x, sizeof y); + br_i31_from_monty(y, C255_P, P0I); + br_i31_encode(tmp, sizeof tmp, y); + for (u = 0; u < sizeof tmp; u ++) { + printf("%02X", tmp[u]); + } + printf("\n"); +} +*/ + +static const unsigned char GEN[] = { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char ORDER[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return GEN; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return ORDER; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 0; +} + +static void +cswap(uint32_t *a, uint32_t *b, uint32_t ctl) +{ + int i; + + ctl = -ctl; + for (i = 0; i < 10; i ++) { + uint32_t aw, bw, tw; + + aw = a[i]; + bw = b[i]; + tw = ctl & (aw ^ bw); + a[i] = aw ^ tw; + b[i] = bw ^ tw; + } +} + +static void +c255_add(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t ctl; + uint32_t t[10]; + + memcpy(t, a, sizeof t); + ctl = br_i31_add(t, b, 1); + ctl |= NOT(br_i31_sub(t, C255_P, 0)); + br_i31_sub(t, C255_P, ctl); + memcpy(d, t, sizeof t); +} + +static void +c255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t t[10]; + + memcpy(t, a, sizeof t); + br_i31_add(t, C255_P, br_i31_sub(t, b, 1)); + memcpy(d, t, sizeof t); +} + +static void +c255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t t[10]; + + br_i31_montymul(t, a, b, C255_P, P0I); + memcpy(d, t, sizeof t); +} + +static void +byteswap(unsigned char *G) +{ + int i; + + for (i = 0; i < 16; i ++) { + unsigned char t; + + t = G[i]; + G[i] = G[31 - i]; + G[31 - i] = t; + } +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *kb, size_t kblen, int curve) +{ + uint32_t x1[10], x2[10], x3[10], z2[10], z3[10]; + uint32_t a[10], aa[10], b[10], bb[10]; + uint32_t c[10], d[10], e[10], da[10], cb[10]; + unsigned char k[32]; + uint32_t swap; + int i; + + (void)curve; + + /* + * Points are encoded over exactly 32 bytes. Multipliers must fit + * in 32 bytes as well. + * RFC 7748 mandates that the high bit of the last point byte must + * be ignored/cleared. + */ + if (Glen != 32 || kblen > 32) { + return 0; + } + G[31] &= 0x7F; + + /* + * Byteswap the point encoding, because it uses little-endian, and + * the generic decoding routine uses big-endian. + */ + byteswap(G); + + /* + * Decode the point ('u' coordinate). This should be reduced + * modulo p, but we prefer to avoid the dependency on + * br_i31_decode_reduce(). Instead, we use br_i31_decode_mod() + * with a synthetic modulus of value 2^255 (this must work + * since G was truncated to 255 bits), then use a conditional + * subtraction. We use br_i31_decode_mod() and not + * br_i31_decode(), because the ec_prime_i31 implementation uses + * the former but not the latter. + * br_i31_decode_reduce(a, G, 32, C255_P); + */ + br_i31_zero(b, 0x108); + b[9] = 0x0080; + br_i31_decode_mod(a, G, 32, b); + a[0] = 0x107; + br_i31_sub(a, C255_P, NOT(br_i31_sub(a, C255_P, 0))); + + /* + * Initialise variables x1, x2, z2, x3 and z3. We set all of them + * into Montgomery representation. + */ + br_i31_montymul(x1, a, C255_R2, C255_P, P0I); + memcpy(x3, x1, sizeof x1); + br_i31_zero(z2, C255_P[0]); + memcpy(x2, z2, sizeof z2); + x2[1] = 0x13000000; + memcpy(z3, x2, sizeof x2); + + /* + * kb[] is in big-endian notation, but possibly shorter than k[]. + */ + memset(k, 0, (sizeof k) - kblen); + memcpy(k + (sizeof k) - kblen, kb, kblen); + k[31] &= 0xF8; + k[0] &= 0x7F; + k[0] |= 0x40; + + /* obsolete + print_int_mont("x1", x1); + */ + + swap = 0; + for (i = 254; i >= 0; i --) { + uint32_t kt; + + kt = (k[31 - (i >> 3)] >> (i & 7)) & 1; + swap ^= kt; + cswap(x2, x3, swap); + cswap(z2, z3, swap); + swap = kt; + + /* obsolete + print_int_mont("x2", x2); + print_int_mont("z2", z2); + print_int_mont("x3", x3); + print_int_mont("z3", z3); + */ + + c255_add(a, x2, z2); + c255_mul(aa, a, a); + c255_sub(b, x2, z2); + c255_mul(bb, b, b); + c255_sub(e, aa, bb); + c255_add(c, x3, z3); + c255_sub(d, x3, z3); + c255_mul(da, d, a); + c255_mul(cb, c, b); + + /* obsolete + print_int_mont("a ", a); + print_int_mont("aa", aa); + print_int_mont("b ", b); + print_int_mont("bb", bb); + print_int_mont("e ", e); + print_int_mont("c ", c); + print_int_mont("d ", d); + print_int_mont("da", da); + print_int_mont("cb", cb); + */ + + c255_add(x3, da, cb); + c255_mul(x3, x3, x3); + c255_sub(z3, da, cb); + c255_mul(z3, z3, z3); + c255_mul(z3, z3, x1); + c255_mul(x2, aa, bb); + c255_mul(z2, C255_A24, e); + c255_add(z2, z2, aa); + c255_mul(z2, e, z2); + + /* obsolete + print_int_mont("x2", x2); + print_int_mont("z2", z2); + print_int_mont("x3", x3); + print_int_mont("z3", z3); + */ + } + cswap(x2, x3, swap); + cswap(z2, z3, swap); + + /* + * Inverse z2 with a modular exponentiation. This is a simple + * square-and-multiply algorithm; we mutualise most non-squarings + * since the exponent contains almost only ones. + */ + memcpy(a, z2, sizeof z2); + for (i = 0; i < 15; i ++) { + c255_mul(a, a, a); + c255_mul(a, a, z2); + } + memcpy(b, a, sizeof a); + for (i = 0; i < 14; i ++) { + int j; + + for (j = 0; j < 16; j ++) { + c255_mul(b, b, b); + } + c255_mul(b, b, a); + } + for (i = 14; i >= 0; i --) { + c255_mul(b, b, b); + if ((0xFFEB >> i) & 1) { + c255_mul(b, z2, b); + } + } + c255_mul(b, x2, b); + + /* + * To avoid a dependency on br_i31_from_monty(), we use + * a Montgomery multiplication with 1. + * memcpy(x2, b, sizeof b); + * br_i31_from_monty(x2, C255_P, P0I); + */ + br_i31_zero(a, C255_P[0]); + a[1] = 1; + br_i31_montymul(x2, a, b, C255_P, P0I); + + br_i31_encode(G, 32, x2); + byteswap(G); + return 1; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + const unsigned char *G; + size_t Glen; + + G = api_generator(curve, &Glen); + memcpy(R, G, Glen); + api_mul(R, Glen, x, xlen, curve); + return Glen; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + /* + * We don't implement this method, since it is used for ECDSA + * only, and there is no ECDSA over Curve25519 (which instead + * uses EdDSA). + */ + (void)A; + (void)B; + (void)len; + (void)x; + (void)xlen; + (void)y; + (void)ylen; + (void)curve; + return 0; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_c25519_i31 = { + (uint32_t)0x20000000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_c25519_m15.c b/BearSSL-OG/libbearssl/src/ec/ec_c25519_m15.c new file mode 100644 index 0000000..289d37c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_c25519_m15.c @@ -0,0 +1,1478 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* obsolete +#include +#include +static void +print_int(const char *name, const uint32_t *x) +{ + size_t u; + unsigned char tmp[36]; + + printf("%s = ", name); + for (u = 0; u < 20; u ++) { + if (x[u] > 0x1FFF) { + printf("INVALID:"); + for (u = 0; u < 20; u ++) { + printf(" %04X", x[u]); + } + printf("\n"); + return; + } + } + memset(tmp, 0, sizeof tmp); + for (u = 0; u < 20; u ++) { + uint32_t w; + int j, k; + + w = x[u]; + j = 13 * (int)u; + k = j & 7; + if (k != 0) { + w <<= k; + j -= k; + } + k = j >> 3; + tmp[35 - k] |= (unsigned char)w; + tmp[34 - k] |= (unsigned char)(w >> 8); + tmp[33 - k] |= (unsigned char)(w >> 16); + tmp[32 - k] |= (unsigned char)(w >> 24); + } + for (u = 4; u < 36; u ++) { + printf("%02X", tmp[u]); + } + printf("\n"); +} +*/ + +/* + * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_ + * that right-shifting a signed negative integer copies the sign bit + * (arithmetic right-shift). This is "implementation-defined behaviour", + * i.e. it is not undefined, but it may differ between compilers. Each + * compiler is supposed to document its behaviour in that respect. GCC + * explicitly defines that an arithmetic right shift is used. We expect + * all other compilers to do the same, because underlying CPU offer an + * arithmetic right shift opcode that could not be used otherwise. + */ +#if BR_NO_ARITH_SHIFT +#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ + | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) +#else +#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) +#endif + +/* + * Convert an integer from unsigned little-endian encoding to a sequence of + * 13-bit words in little-endian order. The final "partial" word is + * returned. + */ +static uint32_t +le8_to_le13(uint32_t *dst, const unsigned char *src, size_t len) +{ + uint32_t acc; + int acc_len; + + acc = 0; + acc_len = 0; + while (len -- > 0) { + acc |= (uint32_t)(*src ++) << acc_len; + acc_len += 8; + if (acc_len >= 13) { + *dst ++ = acc & 0x1FFF; + acc >>= 13; + acc_len -= 13; + } + } + return acc; +} + +/* + * Convert an integer (13-bit words, little-endian) to unsigned + * little-endian encoding. The total encoding length is provided; all + * the destination bytes will be filled. + */ +static void +le13_to_le8(unsigned char *dst, size_t len, const uint32_t *src) +{ + uint32_t acc; + int acc_len; + + acc = 0; + acc_len = 0; + while (len -- > 0) { + if (acc_len < 8) { + acc |= (*src ++) << acc_len; + acc_len += 13; + } + *dst ++ = (unsigned char)acc; + acc >>= 8; + acc_len -= 8; + } +} + +/* + * Normalise an array of words to a strict 13 bits per word. Returned + * value is the resulting carry. The source (w) and destination (d) + * arrays may be identical, but shall not overlap partially. + */ +static __inline uint32_t +norm13(uint32_t *d, const uint32_t *w, size_t len) +{ + size_t u; + uint32_t cc; + + cc = 0; + for (u = 0; u < len; u ++) { + int32_t z; + + z = w[u] + cc; + d[u] = z & 0x1FFF; + cc = ARSH(z, 13); + } + return cc; +} + +/* + * mul20() multiplies two 260-bit integers together. Each word must fit + * on 13 bits; source operands use 20 words, destination operand + * receives 40 words. All overlaps allowed. + * + * square20() computes the square of a 260-bit integer. Each word must + * fit on 13 bits; source operand uses 20 words, destination operand + * receives 40 words. All overlaps allowed. + */ + +#if BR_SLOW_MUL15 + +static void +mul20(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + /* + * Two-level Karatsuba: turns a 20x20 multiplication into + * nine 5x5 multiplications. We use 13-bit words but do not + * propagate carries immediately, so words may expand: + * + * - First Karatsuba decomposition turns the 20x20 mul on + * 13-bit words into three 10x10 muls, two on 13-bit words + * and one on 14-bit words. + * + * - Second Karatsuba decomposition further splits these into: + * + * * four 5x5 muls on 13-bit words + * * four 5x5 muls on 14-bit words + * * one 5x5 mul on 15-bit words + * + * Highest word value is 8191, 16382 or 32764, for 13-bit, 14-bit + * or 15-bit words, respectively. + */ + uint32_t u[45], v[45], w[90]; + uint32_t cc; + int i; + +#define ZADD(dw, d_off, s1w, s1_off, s2w, s2_off) do { \ + (dw)[5 * (d_off) + 0] = (s1w)[5 * (s1_off) + 0] \ + + (s2w)[5 * (s2_off) + 0]; \ + (dw)[5 * (d_off) + 1] = (s1w)[5 * (s1_off) + 1] \ + + (s2w)[5 * (s2_off) + 1]; \ + (dw)[5 * (d_off) + 2] = (s1w)[5 * (s1_off) + 2] \ + + (s2w)[5 * (s2_off) + 2]; \ + (dw)[5 * (d_off) + 3] = (s1w)[5 * (s1_off) + 3] \ + + (s2w)[5 * (s2_off) + 3]; \ + (dw)[5 * (d_off) + 4] = (s1w)[5 * (s1_off) + 4] \ + + (s2w)[5 * (s2_off) + 4]; \ + } while (0) + +#define ZADDT(dw, d_off, sw, s_off) do { \ + (dw)[5 * (d_off) + 0] += (sw)[5 * (s_off) + 0]; \ + (dw)[5 * (d_off) + 1] += (sw)[5 * (s_off) + 1]; \ + (dw)[5 * (d_off) + 2] += (sw)[5 * (s_off) + 2]; \ + (dw)[5 * (d_off) + 3] += (sw)[5 * (s_off) + 3]; \ + (dw)[5 * (d_off) + 4] += (sw)[5 * (s_off) + 4]; \ + } while (0) + +#define ZSUB2F(dw, d_off, s1w, s1_off, s2w, s2_off) do { \ + (dw)[5 * (d_off) + 0] -= (s1w)[5 * (s1_off) + 0] \ + + (s2w)[5 * (s2_off) + 0]; \ + (dw)[5 * (d_off) + 1] -= (s1w)[5 * (s1_off) + 1] \ + + (s2w)[5 * (s2_off) + 1]; \ + (dw)[5 * (d_off) + 2] -= (s1w)[5 * (s1_off) + 2] \ + + (s2w)[5 * (s2_off) + 2]; \ + (dw)[5 * (d_off) + 3] -= (s1w)[5 * (s1_off) + 3] \ + + (s2w)[5 * (s2_off) + 3]; \ + (dw)[5 * (d_off) + 4] -= (s1w)[5 * (s1_off) + 4] \ + + (s2w)[5 * (s2_off) + 4]; \ + } while (0) + +#define CPR1(w, cprcc) do { \ + uint32_t cprz = (w) + cprcc; \ + (w) = cprz & 0x1FFF; \ + cprcc = cprz >> 13; \ + } while (0) + +#define CPR(dw, d_off) do { \ + uint32_t cprcc; \ + cprcc = 0; \ + CPR1((dw)[(d_off) + 0], cprcc); \ + CPR1((dw)[(d_off) + 1], cprcc); \ + CPR1((dw)[(d_off) + 2], cprcc); \ + CPR1((dw)[(d_off) + 3], cprcc); \ + CPR1((dw)[(d_off) + 4], cprcc); \ + CPR1((dw)[(d_off) + 5], cprcc); \ + CPR1((dw)[(d_off) + 6], cprcc); \ + CPR1((dw)[(d_off) + 7], cprcc); \ + CPR1((dw)[(d_off) + 8], cprcc); \ + (dw)[(d_off) + 9] = cprcc; \ + } while (0) + + memcpy(u, a, 20 * sizeof *a); + ZADD(u, 4, a, 0, a, 1); + ZADD(u, 5, a, 2, a, 3); + ZADD(u, 6, a, 0, a, 2); + ZADD(u, 7, a, 1, a, 3); + ZADD(u, 8, u, 6, u, 7); + + memcpy(v, b, 20 * sizeof *b); + ZADD(v, 4, b, 0, b, 1); + ZADD(v, 5, b, 2, b, 3); + ZADD(v, 6, b, 0, b, 2); + ZADD(v, 7, b, 1, b, 3); + ZADD(v, 8, v, 6, v, 7); + + /* + * Do the eight first 8x8 muls. Source words are at most 16382 + * each, so we can add product results together "as is" in 32-bit + * words. + */ + for (i = 0; i < 40; i += 5) { + w[(i << 1) + 0] = MUL15(u[i + 0], v[i + 0]); + w[(i << 1) + 1] = MUL15(u[i + 0], v[i + 1]) + + MUL15(u[i + 1], v[i + 0]); + w[(i << 1) + 2] = MUL15(u[i + 0], v[i + 2]) + + MUL15(u[i + 1], v[i + 1]) + + MUL15(u[i + 2], v[i + 0]); + w[(i << 1) + 3] = MUL15(u[i + 0], v[i + 3]) + + MUL15(u[i + 1], v[i + 2]) + + MUL15(u[i + 2], v[i + 1]) + + MUL15(u[i + 3], v[i + 0]); + w[(i << 1) + 4] = MUL15(u[i + 0], v[i + 4]) + + MUL15(u[i + 1], v[i + 3]) + + MUL15(u[i + 2], v[i + 2]) + + MUL15(u[i + 3], v[i + 1]) + + MUL15(u[i + 4], v[i + 0]); + w[(i << 1) + 5] = MUL15(u[i + 1], v[i + 4]) + + MUL15(u[i + 2], v[i + 3]) + + MUL15(u[i + 3], v[i + 2]) + + MUL15(u[i + 4], v[i + 1]); + w[(i << 1) + 6] = MUL15(u[i + 2], v[i + 4]) + + MUL15(u[i + 3], v[i + 3]) + + MUL15(u[i + 4], v[i + 2]); + w[(i << 1) + 7] = MUL15(u[i + 3], v[i + 4]) + + MUL15(u[i + 4], v[i + 3]); + w[(i << 1) + 8] = MUL15(u[i + 4], v[i + 4]); + w[(i << 1) + 9] = 0; + } + + /* + * For the 9th multiplication, source words are up to 32764, + * so we must do some carry propagation. If we add up to + * 4 products and the carry is no more than 524224, then the + * result fits in 32 bits, and the next carry will be no more + * than 524224 (because 4*(32764^2)+524224 < 8192*524225). + * + * We thus just skip one of the products in the middle word, + * then do a carry propagation (this reduces words to 13 bits + * each, except possibly the last, which may use up to 17 bits + * or so), then add the missing product. + */ + w[80 + 0] = MUL15(u[40 + 0], v[40 + 0]); + w[80 + 1] = MUL15(u[40 + 0], v[40 + 1]) + + MUL15(u[40 + 1], v[40 + 0]); + w[80 + 2] = MUL15(u[40 + 0], v[40 + 2]) + + MUL15(u[40 + 1], v[40 + 1]) + + MUL15(u[40 + 2], v[40 + 0]); + w[80 + 3] = MUL15(u[40 + 0], v[40 + 3]) + + MUL15(u[40 + 1], v[40 + 2]) + + MUL15(u[40 + 2], v[40 + 1]) + + MUL15(u[40 + 3], v[40 + 0]); + w[80 + 4] = MUL15(u[40 + 0], v[40 + 4]) + + MUL15(u[40 + 1], v[40 + 3]) + + MUL15(u[40 + 2], v[40 + 2]) + + MUL15(u[40 + 3], v[40 + 1]); + /* + MUL15(u[40 + 4], v[40 + 0]) */ + w[80 + 5] = MUL15(u[40 + 1], v[40 + 4]) + + MUL15(u[40 + 2], v[40 + 3]) + + MUL15(u[40 + 3], v[40 + 2]) + + MUL15(u[40 + 4], v[40 + 1]); + w[80 + 6] = MUL15(u[40 + 2], v[40 + 4]) + + MUL15(u[40 + 3], v[40 + 3]) + + MUL15(u[40 + 4], v[40 + 2]); + w[80 + 7] = MUL15(u[40 + 3], v[40 + 4]) + + MUL15(u[40 + 4], v[40 + 3]); + w[80 + 8] = MUL15(u[40 + 4], v[40 + 4]); + + CPR(w, 80); + + w[80 + 4] += MUL15(u[40 + 4], v[40 + 0]); + + /* + * The products on 14-bit words in slots 6 and 7 yield values + * up to 5*(16382^2) each, and we need to subtract two such + * values from the higher word. We need the subtraction to fit + * in a _signed_ 32-bit integer, i.e. 31 bits + a sign bit. + * However, 10*(16382^2) does not fit. So we must perform a + * bit of reduction here. + */ + CPR(w, 60); + CPR(w, 70); + + /* + * Recompose results. + */ + + /* 0..1*0..1 into 0..3 */ + ZSUB2F(w, 8, w, 0, w, 2); + ZSUB2F(w, 9, w, 1, w, 3); + ZADDT(w, 1, w, 8); + ZADDT(w, 2, w, 9); + + /* 2..3*2..3 into 4..7 */ + ZSUB2F(w, 10, w, 4, w, 6); + ZSUB2F(w, 11, w, 5, w, 7); + ZADDT(w, 5, w, 10); + ZADDT(w, 6, w, 11); + + /* (0..1+2..3)*(0..1+2..3) into 12..15 */ + ZSUB2F(w, 16, w, 12, w, 14); + ZSUB2F(w, 17, w, 13, w, 15); + ZADDT(w, 13, w, 16); + ZADDT(w, 14, w, 17); + + /* first-level recomposition */ + ZSUB2F(w, 12, w, 0, w, 4); + ZSUB2F(w, 13, w, 1, w, 5); + ZSUB2F(w, 14, w, 2, w, 6); + ZSUB2F(w, 15, w, 3, w, 7); + ZADDT(w, 2, w, 12); + ZADDT(w, 3, w, 13); + ZADDT(w, 4, w, 14); + ZADDT(w, 5, w, 15); + + /* + * Perform carry propagation to bring all words down to 13 bits. + */ + cc = norm13(d, w, 40); + d[39] += (cc << 13); + +#undef ZADD +#undef ZADDT +#undef ZSUB2F +#undef CPR1 +#undef CPR +} + +static inline void +square20(uint32_t *d, const uint32_t *a) +{ + mul20(d, a, a); +} + +#else + +static void +mul20(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t t[39]; + + t[ 0] = MUL15(a[ 0], b[ 0]); + t[ 1] = MUL15(a[ 0], b[ 1]) + + MUL15(a[ 1], b[ 0]); + t[ 2] = MUL15(a[ 0], b[ 2]) + + MUL15(a[ 1], b[ 1]) + + MUL15(a[ 2], b[ 0]); + t[ 3] = MUL15(a[ 0], b[ 3]) + + MUL15(a[ 1], b[ 2]) + + MUL15(a[ 2], b[ 1]) + + MUL15(a[ 3], b[ 0]); + t[ 4] = MUL15(a[ 0], b[ 4]) + + MUL15(a[ 1], b[ 3]) + + MUL15(a[ 2], b[ 2]) + + MUL15(a[ 3], b[ 1]) + + MUL15(a[ 4], b[ 0]); + t[ 5] = MUL15(a[ 0], b[ 5]) + + MUL15(a[ 1], b[ 4]) + + MUL15(a[ 2], b[ 3]) + + MUL15(a[ 3], b[ 2]) + + MUL15(a[ 4], b[ 1]) + + MUL15(a[ 5], b[ 0]); + t[ 6] = MUL15(a[ 0], b[ 6]) + + MUL15(a[ 1], b[ 5]) + + MUL15(a[ 2], b[ 4]) + + MUL15(a[ 3], b[ 3]) + + MUL15(a[ 4], b[ 2]) + + MUL15(a[ 5], b[ 1]) + + MUL15(a[ 6], b[ 0]); + t[ 7] = MUL15(a[ 0], b[ 7]) + + MUL15(a[ 1], b[ 6]) + + MUL15(a[ 2], b[ 5]) + + MUL15(a[ 3], b[ 4]) + + MUL15(a[ 4], b[ 3]) + + MUL15(a[ 5], b[ 2]) + + MUL15(a[ 6], b[ 1]) + + MUL15(a[ 7], b[ 0]); + t[ 8] = MUL15(a[ 0], b[ 8]) + + MUL15(a[ 1], b[ 7]) + + MUL15(a[ 2], b[ 6]) + + MUL15(a[ 3], b[ 5]) + + MUL15(a[ 4], b[ 4]) + + MUL15(a[ 5], b[ 3]) + + MUL15(a[ 6], b[ 2]) + + MUL15(a[ 7], b[ 1]) + + MUL15(a[ 8], b[ 0]); + t[ 9] = MUL15(a[ 0], b[ 9]) + + MUL15(a[ 1], b[ 8]) + + MUL15(a[ 2], b[ 7]) + + MUL15(a[ 3], b[ 6]) + + MUL15(a[ 4], b[ 5]) + + MUL15(a[ 5], b[ 4]) + + MUL15(a[ 6], b[ 3]) + + MUL15(a[ 7], b[ 2]) + + MUL15(a[ 8], b[ 1]) + + MUL15(a[ 9], b[ 0]); + t[10] = MUL15(a[ 0], b[10]) + + MUL15(a[ 1], b[ 9]) + + MUL15(a[ 2], b[ 8]) + + MUL15(a[ 3], b[ 7]) + + MUL15(a[ 4], b[ 6]) + + MUL15(a[ 5], b[ 5]) + + MUL15(a[ 6], b[ 4]) + + MUL15(a[ 7], b[ 3]) + + MUL15(a[ 8], b[ 2]) + + MUL15(a[ 9], b[ 1]) + + MUL15(a[10], b[ 0]); + t[11] = MUL15(a[ 0], b[11]) + + MUL15(a[ 1], b[10]) + + MUL15(a[ 2], b[ 9]) + + MUL15(a[ 3], b[ 8]) + + MUL15(a[ 4], b[ 7]) + + MUL15(a[ 5], b[ 6]) + + MUL15(a[ 6], b[ 5]) + + MUL15(a[ 7], b[ 4]) + + MUL15(a[ 8], b[ 3]) + + MUL15(a[ 9], b[ 2]) + + MUL15(a[10], b[ 1]) + + MUL15(a[11], b[ 0]); + t[12] = MUL15(a[ 0], b[12]) + + MUL15(a[ 1], b[11]) + + MUL15(a[ 2], b[10]) + + MUL15(a[ 3], b[ 9]) + + MUL15(a[ 4], b[ 8]) + + MUL15(a[ 5], b[ 7]) + + MUL15(a[ 6], b[ 6]) + + MUL15(a[ 7], b[ 5]) + + MUL15(a[ 8], b[ 4]) + + MUL15(a[ 9], b[ 3]) + + MUL15(a[10], b[ 2]) + + MUL15(a[11], b[ 1]) + + MUL15(a[12], b[ 0]); + t[13] = MUL15(a[ 0], b[13]) + + MUL15(a[ 1], b[12]) + + MUL15(a[ 2], b[11]) + + MUL15(a[ 3], b[10]) + + MUL15(a[ 4], b[ 9]) + + MUL15(a[ 5], b[ 8]) + + MUL15(a[ 6], b[ 7]) + + MUL15(a[ 7], b[ 6]) + + MUL15(a[ 8], b[ 5]) + + MUL15(a[ 9], b[ 4]) + + MUL15(a[10], b[ 3]) + + MUL15(a[11], b[ 2]) + + MUL15(a[12], b[ 1]) + + MUL15(a[13], b[ 0]); + t[14] = MUL15(a[ 0], b[14]) + + MUL15(a[ 1], b[13]) + + MUL15(a[ 2], b[12]) + + MUL15(a[ 3], b[11]) + + MUL15(a[ 4], b[10]) + + MUL15(a[ 5], b[ 9]) + + MUL15(a[ 6], b[ 8]) + + MUL15(a[ 7], b[ 7]) + + MUL15(a[ 8], b[ 6]) + + MUL15(a[ 9], b[ 5]) + + MUL15(a[10], b[ 4]) + + MUL15(a[11], b[ 3]) + + MUL15(a[12], b[ 2]) + + MUL15(a[13], b[ 1]) + + MUL15(a[14], b[ 0]); + t[15] = MUL15(a[ 0], b[15]) + + MUL15(a[ 1], b[14]) + + MUL15(a[ 2], b[13]) + + MUL15(a[ 3], b[12]) + + MUL15(a[ 4], b[11]) + + MUL15(a[ 5], b[10]) + + MUL15(a[ 6], b[ 9]) + + MUL15(a[ 7], b[ 8]) + + MUL15(a[ 8], b[ 7]) + + MUL15(a[ 9], b[ 6]) + + MUL15(a[10], b[ 5]) + + MUL15(a[11], b[ 4]) + + MUL15(a[12], b[ 3]) + + MUL15(a[13], b[ 2]) + + MUL15(a[14], b[ 1]) + + MUL15(a[15], b[ 0]); + t[16] = MUL15(a[ 0], b[16]) + + MUL15(a[ 1], b[15]) + + MUL15(a[ 2], b[14]) + + MUL15(a[ 3], b[13]) + + MUL15(a[ 4], b[12]) + + MUL15(a[ 5], b[11]) + + MUL15(a[ 6], b[10]) + + MUL15(a[ 7], b[ 9]) + + MUL15(a[ 8], b[ 8]) + + MUL15(a[ 9], b[ 7]) + + MUL15(a[10], b[ 6]) + + MUL15(a[11], b[ 5]) + + MUL15(a[12], b[ 4]) + + MUL15(a[13], b[ 3]) + + MUL15(a[14], b[ 2]) + + MUL15(a[15], b[ 1]) + + MUL15(a[16], b[ 0]); + t[17] = MUL15(a[ 0], b[17]) + + MUL15(a[ 1], b[16]) + + MUL15(a[ 2], b[15]) + + MUL15(a[ 3], b[14]) + + MUL15(a[ 4], b[13]) + + MUL15(a[ 5], b[12]) + + MUL15(a[ 6], b[11]) + + MUL15(a[ 7], b[10]) + + MUL15(a[ 8], b[ 9]) + + MUL15(a[ 9], b[ 8]) + + MUL15(a[10], b[ 7]) + + MUL15(a[11], b[ 6]) + + MUL15(a[12], b[ 5]) + + MUL15(a[13], b[ 4]) + + MUL15(a[14], b[ 3]) + + MUL15(a[15], b[ 2]) + + MUL15(a[16], b[ 1]) + + MUL15(a[17], b[ 0]); + t[18] = MUL15(a[ 0], b[18]) + + MUL15(a[ 1], b[17]) + + MUL15(a[ 2], b[16]) + + MUL15(a[ 3], b[15]) + + MUL15(a[ 4], b[14]) + + MUL15(a[ 5], b[13]) + + MUL15(a[ 6], b[12]) + + MUL15(a[ 7], b[11]) + + MUL15(a[ 8], b[10]) + + MUL15(a[ 9], b[ 9]) + + MUL15(a[10], b[ 8]) + + MUL15(a[11], b[ 7]) + + MUL15(a[12], b[ 6]) + + MUL15(a[13], b[ 5]) + + MUL15(a[14], b[ 4]) + + MUL15(a[15], b[ 3]) + + MUL15(a[16], b[ 2]) + + MUL15(a[17], b[ 1]) + + MUL15(a[18], b[ 0]); + t[19] = MUL15(a[ 0], b[19]) + + MUL15(a[ 1], b[18]) + + MUL15(a[ 2], b[17]) + + MUL15(a[ 3], b[16]) + + MUL15(a[ 4], b[15]) + + MUL15(a[ 5], b[14]) + + MUL15(a[ 6], b[13]) + + MUL15(a[ 7], b[12]) + + MUL15(a[ 8], b[11]) + + MUL15(a[ 9], b[10]) + + MUL15(a[10], b[ 9]) + + MUL15(a[11], b[ 8]) + + MUL15(a[12], b[ 7]) + + MUL15(a[13], b[ 6]) + + MUL15(a[14], b[ 5]) + + MUL15(a[15], b[ 4]) + + MUL15(a[16], b[ 3]) + + MUL15(a[17], b[ 2]) + + MUL15(a[18], b[ 1]) + + MUL15(a[19], b[ 0]); + t[20] = MUL15(a[ 1], b[19]) + + MUL15(a[ 2], b[18]) + + MUL15(a[ 3], b[17]) + + MUL15(a[ 4], b[16]) + + MUL15(a[ 5], b[15]) + + MUL15(a[ 6], b[14]) + + MUL15(a[ 7], b[13]) + + MUL15(a[ 8], b[12]) + + MUL15(a[ 9], b[11]) + + MUL15(a[10], b[10]) + + MUL15(a[11], b[ 9]) + + MUL15(a[12], b[ 8]) + + MUL15(a[13], b[ 7]) + + MUL15(a[14], b[ 6]) + + MUL15(a[15], b[ 5]) + + MUL15(a[16], b[ 4]) + + MUL15(a[17], b[ 3]) + + MUL15(a[18], b[ 2]) + + MUL15(a[19], b[ 1]); + t[21] = MUL15(a[ 2], b[19]) + + MUL15(a[ 3], b[18]) + + MUL15(a[ 4], b[17]) + + MUL15(a[ 5], b[16]) + + MUL15(a[ 6], b[15]) + + MUL15(a[ 7], b[14]) + + MUL15(a[ 8], b[13]) + + MUL15(a[ 9], b[12]) + + MUL15(a[10], b[11]) + + MUL15(a[11], b[10]) + + MUL15(a[12], b[ 9]) + + MUL15(a[13], b[ 8]) + + MUL15(a[14], b[ 7]) + + MUL15(a[15], b[ 6]) + + MUL15(a[16], b[ 5]) + + MUL15(a[17], b[ 4]) + + MUL15(a[18], b[ 3]) + + MUL15(a[19], b[ 2]); + t[22] = MUL15(a[ 3], b[19]) + + MUL15(a[ 4], b[18]) + + MUL15(a[ 5], b[17]) + + MUL15(a[ 6], b[16]) + + MUL15(a[ 7], b[15]) + + MUL15(a[ 8], b[14]) + + MUL15(a[ 9], b[13]) + + MUL15(a[10], b[12]) + + MUL15(a[11], b[11]) + + MUL15(a[12], b[10]) + + MUL15(a[13], b[ 9]) + + MUL15(a[14], b[ 8]) + + MUL15(a[15], b[ 7]) + + MUL15(a[16], b[ 6]) + + MUL15(a[17], b[ 5]) + + MUL15(a[18], b[ 4]) + + MUL15(a[19], b[ 3]); + t[23] = MUL15(a[ 4], b[19]) + + MUL15(a[ 5], b[18]) + + MUL15(a[ 6], b[17]) + + MUL15(a[ 7], b[16]) + + MUL15(a[ 8], b[15]) + + MUL15(a[ 9], b[14]) + + MUL15(a[10], b[13]) + + MUL15(a[11], b[12]) + + MUL15(a[12], b[11]) + + MUL15(a[13], b[10]) + + MUL15(a[14], b[ 9]) + + MUL15(a[15], b[ 8]) + + MUL15(a[16], b[ 7]) + + MUL15(a[17], b[ 6]) + + MUL15(a[18], b[ 5]) + + MUL15(a[19], b[ 4]); + t[24] = MUL15(a[ 5], b[19]) + + MUL15(a[ 6], b[18]) + + MUL15(a[ 7], b[17]) + + MUL15(a[ 8], b[16]) + + MUL15(a[ 9], b[15]) + + MUL15(a[10], b[14]) + + MUL15(a[11], b[13]) + + MUL15(a[12], b[12]) + + MUL15(a[13], b[11]) + + MUL15(a[14], b[10]) + + MUL15(a[15], b[ 9]) + + MUL15(a[16], b[ 8]) + + MUL15(a[17], b[ 7]) + + MUL15(a[18], b[ 6]) + + MUL15(a[19], b[ 5]); + t[25] = MUL15(a[ 6], b[19]) + + MUL15(a[ 7], b[18]) + + MUL15(a[ 8], b[17]) + + MUL15(a[ 9], b[16]) + + MUL15(a[10], b[15]) + + MUL15(a[11], b[14]) + + MUL15(a[12], b[13]) + + MUL15(a[13], b[12]) + + MUL15(a[14], b[11]) + + MUL15(a[15], b[10]) + + MUL15(a[16], b[ 9]) + + MUL15(a[17], b[ 8]) + + MUL15(a[18], b[ 7]) + + MUL15(a[19], b[ 6]); + t[26] = MUL15(a[ 7], b[19]) + + MUL15(a[ 8], b[18]) + + MUL15(a[ 9], b[17]) + + MUL15(a[10], b[16]) + + MUL15(a[11], b[15]) + + MUL15(a[12], b[14]) + + MUL15(a[13], b[13]) + + MUL15(a[14], b[12]) + + MUL15(a[15], b[11]) + + MUL15(a[16], b[10]) + + MUL15(a[17], b[ 9]) + + MUL15(a[18], b[ 8]) + + MUL15(a[19], b[ 7]); + t[27] = MUL15(a[ 8], b[19]) + + MUL15(a[ 9], b[18]) + + MUL15(a[10], b[17]) + + MUL15(a[11], b[16]) + + MUL15(a[12], b[15]) + + MUL15(a[13], b[14]) + + MUL15(a[14], b[13]) + + MUL15(a[15], b[12]) + + MUL15(a[16], b[11]) + + MUL15(a[17], b[10]) + + MUL15(a[18], b[ 9]) + + MUL15(a[19], b[ 8]); + t[28] = MUL15(a[ 9], b[19]) + + MUL15(a[10], b[18]) + + MUL15(a[11], b[17]) + + MUL15(a[12], b[16]) + + MUL15(a[13], b[15]) + + MUL15(a[14], b[14]) + + MUL15(a[15], b[13]) + + MUL15(a[16], b[12]) + + MUL15(a[17], b[11]) + + MUL15(a[18], b[10]) + + MUL15(a[19], b[ 9]); + t[29] = MUL15(a[10], b[19]) + + MUL15(a[11], b[18]) + + MUL15(a[12], b[17]) + + MUL15(a[13], b[16]) + + MUL15(a[14], b[15]) + + MUL15(a[15], b[14]) + + MUL15(a[16], b[13]) + + MUL15(a[17], b[12]) + + MUL15(a[18], b[11]) + + MUL15(a[19], b[10]); + t[30] = MUL15(a[11], b[19]) + + MUL15(a[12], b[18]) + + MUL15(a[13], b[17]) + + MUL15(a[14], b[16]) + + MUL15(a[15], b[15]) + + MUL15(a[16], b[14]) + + MUL15(a[17], b[13]) + + MUL15(a[18], b[12]) + + MUL15(a[19], b[11]); + t[31] = MUL15(a[12], b[19]) + + MUL15(a[13], b[18]) + + MUL15(a[14], b[17]) + + MUL15(a[15], b[16]) + + MUL15(a[16], b[15]) + + MUL15(a[17], b[14]) + + MUL15(a[18], b[13]) + + MUL15(a[19], b[12]); + t[32] = MUL15(a[13], b[19]) + + MUL15(a[14], b[18]) + + MUL15(a[15], b[17]) + + MUL15(a[16], b[16]) + + MUL15(a[17], b[15]) + + MUL15(a[18], b[14]) + + MUL15(a[19], b[13]); + t[33] = MUL15(a[14], b[19]) + + MUL15(a[15], b[18]) + + MUL15(a[16], b[17]) + + MUL15(a[17], b[16]) + + MUL15(a[18], b[15]) + + MUL15(a[19], b[14]); + t[34] = MUL15(a[15], b[19]) + + MUL15(a[16], b[18]) + + MUL15(a[17], b[17]) + + MUL15(a[18], b[16]) + + MUL15(a[19], b[15]); + t[35] = MUL15(a[16], b[19]) + + MUL15(a[17], b[18]) + + MUL15(a[18], b[17]) + + MUL15(a[19], b[16]); + t[36] = MUL15(a[17], b[19]) + + MUL15(a[18], b[18]) + + MUL15(a[19], b[17]); + t[37] = MUL15(a[18], b[19]) + + MUL15(a[19], b[18]); + t[38] = MUL15(a[19], b[19]); + + d[39] = norm13(d, t, 39); +} + +static void +square20(uint32_t *d, const uint32_t *a) +{ + uint32_t t[39]; + + t[ 0] = MUL15(a[ 0], a[ 0]); + t[ 1] = ((MUL15(a[ 0], a[ 1])) << 1); + t[ 2] = MUL15(a[ 1], a[ 1]) + + ((MUL15(a[ 0], a[ 2])) << 1); + t[ 3] = ((MUL15(a[ 0], a[ 3]) + + MUL15(a[ 1], a[ 2])) << 1); + t[ 4] = MUL15(a[ 2], a[ 2]) + + ((MUL15(a[ 0], a[ 4]) + + MUL15(a[ 1], a[ 3])) << 1); + t[ 5] = ((MUL15(a[ 0], a[ 5]) + + MUL15(a[ 1], a[ 4]) + + MUL15(a[ 2], a[ 3])) << 1); + t[ 6] = MUL15(a[ 3], a[ 3]) + + ((MUL15(a[ 0], a[ 6]) + + MUL15(a[ 1], a[ 5]) + + MUL15(a[ 2], a[ 4])) << 1); + t[ 7] = ((MUL15(a[ 0], a[ 7]) + + MUL15(a[ 1], a[ 6]) + + MUL15(a[ 2], a[ 5]) + + MUL15(a[ 3], a[ 4])) << 1); + t[ 8] = MUL15(a[ 4], a[ 4]) + + ((MUL15(a[ 0], a[ 8]) + + MUL15(a[ 1], a[ 7]) + + MUL15(a[ 2], a[ 6]) + + MUL15(a[ 3], a[ 5])) << 1); + t[ 9] = ((MUL15(a[ 0], a[ 9]) + + MUL15(a[ 1], a[ 8]) + + MUL15(a[ 2], a[ 7]) + + MUL15(a[ 3], a[ 6]) + + MUL15(a[ 4], a[ 5])) << 1); + t[10] = MUL15(a[ 5], a[ 5]) + + ((MUL15(a[ 0], a[10]) + + MUL15(a[ 1], a[ 9]) + + MUL15(a[ 2], a[ 8]) + + MUL15(a[ 3], a[ 7]) + + MUL15(a[ 4], a[ 6])) << 1); + t[11] = ((MUL15(a[ 0], a[11]) + + MUL15(a[ 1], a[10]) + + MUL15(a[ 2], a[ 9]) + + MUL15(a[ 3], a[ 8]) + + MUL15(a[ 4], a[ 7]) + + MUL15(a[ 5], a[ 6])) << 1); + t[12] = MUL15(a[ 6], a[ 6]) + + ((MUL15(a[ 0], a[12]) + + MUL15(a[ 1], a[11]) + + MUL15(a[ 2], a[10]) + + MUL15(a[ 3], a[ 9]) + + MUL15(a[ 4], a[ 8]) + + MUL15(a[ 5], a[ 7])) << 1); + t[13] = ((MUL15(a[ 0], a[13]) + + MUL15(a[ 1], a[12]) + + MUL15(a[ 2], a[11]) + + MUL15(a[ 3], a[10]) + + MUL15(a[ 4], a[ 9]) + + MUL15(a[ 5], a[ 8]) + + MUL15(a[ 6], a[ 7])) << 1); + t[14] = MUL15(a[ 7], a[ 7]) + + ((MUL15(a[ 0], a[14]) + + MUL15(a[ 1], a[13]) + + MUL15(a[ 2], a[12]) + + MUL15(a[ 3], a[11]) + + MUL15(a[ 4], a[10]) + + MUL15(a[ 5], a[ 9]) + + MUL15(a[ 6], a[ 8])) << 1); + t[15] = ((MUL15(a[ 0], a[15]) + + MUL15(a[ 1], a[14]) + + MUL15(a[ 2], a[13]) + + MUL15(a[ 3], a[12]) + + MUL15(a[ 4], a[11]) + + MUL15(a[ 5], a[10]) + + MUL15(a[ 6], a[ 9]) + + MUL15(a[ 7], a[ 8])) << 1); + t[16] = MUL15(a[ 8], a[ 8]) + + ((MUL15(a[ 0], a[16]) + + MUL15(a[ 1], a[15]) + + MUL15(a[ 2], a[14]) + + MUL15(a[ 3], a[13]) + + MUL15(a[ 4], a[12]) + + MUL15(a[ 5], a[11]) + + MUL15(a[ 6], a[10]) + + MUL15(a[ 7], a[ 9])) << 1); + t[17] = ((MUL15(a[ 0], a[17]) + + MUL15(a[ 1], a[16]) + + MUL15(a[ 2], a[15]) + + MUL15(a[ 3], a[14]) + + MUL15(a[ 4], a[13]) + + MUL15(a[ 5], a[12]) + + MUL15(a[ 6], a[11]) + + MUL15(a[ 7], a[10]) + + MUL15(a[ 8], a[ 9])) << 1); + t[18] = MUL15(a[ 9], a[ 9]) + + ((MUL15(a[ 0], a[18]) + + MUL15(a[ 1], a[17]) + + MUL15(a[ 2], a[16]) + + MUL15(a[ 3], a[15]) + + MUL15(a[ 4], a[14]) + + MUL15(a[ 5], a[13]) + + MUL15(a[ 6], a[12]) + + MUL15(a[ 7], a[11]) + + MUL15(a[ 8], a[10])) << 1); + t[19] = ((MUL15(a[ 0], a[19]) + + MUL15(a[ 1], a[18]) + + MUL15(a[ 2], a[17]) + + MUL15(a[ 3], a[16]) + + MUL15(a[ 4], a[15]) + + MUL15(a[ 5], a[14]) + + MUL15(a[ 6], a[13]) + + MUL15(a[ 7], a[12]) + + MUL15(a[ 8], a[11]) + + MUL15(a[ 9], a[10])) << 1); + t[20] = MUL15(a[10], a[10]) + + ((MUL15(a[ 1], a[19]) + + MUL15(a[ 2], a[18]) + + MUL15(a[ 3], a[17]) + + MUL15(a[ 4], a[16]) + + MUL15(a[ 5], a[15]) + + MUL15(a[ 6], a[14]) + + MUL15(a[ 7], a[13]) + + MUL15(a[ 8], a[12]) + + MUL15(a[ 9], a[11])) << 1); + t[21] = ((MUL15(a[ 2], a[19]) + + MUL15(a[ 3], a[18]) + + MUL15(a[ 4], a[17]) + + MUL15(a[ 5], a[16]) + + MUL15(a[ 6], a[15]) + + MUL15(a[ 7], a[14]) + + MUL15(a[ 8], a[13]) + + MUL15(a[ 9], a[12]) + + MUL15(a[10], a[11])) << 1); + t[22] = MUL15(a[11], a[11]) + + ((MUL15(a[ 3], a[19]) + + MUL15(a[ 4], a[18]) + + MUL15(a[ 5], a[17]) + + MUL15(a[ 6], a[16]) + + MUL15(a[ 7], a[15]) + + MUL15(a[ 8], a[14]) + + MUL15(a[ 9], a[13]) + + MUL15(a[10], a[12])) << 1); + t[23] = ((MUL15(a[ 4], a[19]) + + MUL15(a[ 5], a[18]) + + MUL15(a[ 6], a[17]) + + MUL15(a[ 7], a[16]) + + MUL15(a[ 8], a[15]) + + MUL15(a[ 9], a[14]) + + MUL15(a[10], a[13]) + + MUL15(a[11], a[12])) << 1); + t[24] = MUL15(a[12], a[12]) + + ((MUL15(a[ 5], a[19]) + + MUL15(a[ 6], a[18]) + + MUL15(a[ 7], a[17]) + + MUL15(a[ 8], a[16]) + + MUL15(a[ 9], a[15]) + + MUL15(a[10], a[14]) + + MUL15(a[11], a[13])) << 1); + t[25] = ((MUL15(a[ 6], a[19]) + + MUL15(a[ 7], a[18]) + + MUL15(a[ 8], a[17]) + + MUL15(a[ 9], a[16]) + + MUL15(a[10], a[15]) + + MUL15(a[11], a[14]) + + MUL15(a[12], a[13])) << 1); + t[26] = MUL15(a[13], a[13]) + + ((MUL15(a[ 7], a[19]) + + MUL15(a[ 8], a[18]) + + MUL15(a[ 9], a[17]) + + MUL15(a[10], a[16]) + + MUL15(a[11], a[15]) + + MUL15(a[12], a[14])) << 1); + t[27] = ((MUL15(a[ 8], a[19]) + + MUL15(a[ 9], a[18]) + + MUL15(a[10], a[17]) + + MUL15(a[11], a[16]) + + MUL15(a[12], a[15]) + + MUL15(a[13], a[14])) << 1); + t[28] = MUL15(a[14], a[14]) + + ((MUL15(a[ 9], a[19]) + + MUL15(a[10], a[18]) + + MUL15(a[11], a[17]) + + MUL15(a[12], a[16]) + + MUL15(a[13], a[15])) << 1); + t[29] = ((MUL15(a[10], a[19]) + + MUL15(a[11], a[18]) + + MUL15(a[12], a[17]) + + MUL15(a[13], a[16]) + + MUL15(a[14], a[15])) << 1); + t[30] = MUL15(a[15], a[15]) + + ((MUL15(a[11], a[19]) + + MUL15(a[12], a[18]) + + MUL15(a[13], a[17]) + + MUL15(a[14], a[16])) << 1); + t[31] = ((MUL15(a[12], a[19]) + + MUL15(a[13], a[18]) + + MUL15(a[14], a[17]) + + MUL15(a[15], a[16])) << 1); + t[32] = MUL15(a[16], a[16]) + + ((MUL15(a[13], a[19]) + + MUL15(a[14], a[18]) + + MUL15(a[15], a[17])) << 1); + t[33] = ((MUL15(a[14], a[19]) + + MUL15(a[15], a[18]) + + MUL15(a[16], a[17])) << 1); + t[34] = MUL15(a[17], a[17]) + + ((MUL15(a[15], a[19]) + + MUL15(a[16], a[18])) << 1); + t[35] = ((MUL15(a[16], a[19]) + + MUL15(a[17], a[18])) << 1); + t[36] = MUL15(a[18], a[18]) + + ((MUL15(a[17], a[19])) << 1); + t[37] = ((MUL15(a[18], a[19])) << 1); + t[38] = MUL15(a[19], a[19]); + + d[39] = norm13(d, t, 39); +} + +#endif + +/* + * Perform a "final reduction" in field F255 (field for Curve25519) + * The source value must be less than twice the modulus. If the value + * is not lower than the modulus, then the modulus is subtracted and + * this function returns 1; otherwise, it leaves it untouched and it + * returns 0. + */ +static uint32_t +reduce_final_f255(uint32_t *d) +{ + uint32_t t[20]; + uint32_t cc; + int i; + + memcpy(t, d, sizeof t); + cc = 19; + for (i = 0; i < 20; i ++) { + uint32_t w; + + w = t[i] + cc; + cc = w >> 13; + t[i] = w & 0x1FFF; + } + cc = t[19] >> 8; + t[19] &= 0xFF; + CCOPY(cc, d, t, sizeof t); + return cc; +} + +static void +f255_mulgen(uint32_t *d, const uint32_t *a, const uint32_t *b, int square) +{ + uint32_t t[40], cc, w; + + /* + * Compute raw multiplication. All result words fit in 13 bits + * each; upper word (t[39]) must fit on 5 bits, since the product + * of two 256-bit integers must fit on 512 bits. + */ + if (square) { + square20(t, a); + } else { + mul20(t, a, b); + } + + /* + * Modular reduction: each high word is added where necessary. + * Since the modulus is 2^255-19 and word 20 corresponds to + * offset 20*13 = 260, word 20+k must be added to word k with + * a factor of 19*2^5 = 608. The extra bits in word 19 are also + * added that way. + */ + cc = MUL15(t[19] >> 8, 19); + t[19] &= 0xFF; + +#define MM1(x) do { \ + w = t[x] + cc + MUL15(t[(x) + 20], 608); \ + t[x] = w & 0x1FFF; \ + cc = w >> 13; \ + } while (0) + + MM1( 0); + MM1( 1); + MM1( 2); + MM1( 3); + MM1( 4); + MM1( 5); + MM1( 6); + MM1( 7); + MM1( 8); + MM1( 9); + MM1(10); + MM1(11); + MM1(12); + MM1(13); + MM1(14); + MM1(15); + MM1(16); + MM1(17); + MM1(18); + MM1(19); + +#undef MM1 + + cc = MUL15(w >> 8, 19); + t[19] &= 0xFF; + +#define MM2(x) do { \ + w = t[x] + cc; \ + d[x] = w & 0x1FFF; \ + cc = w >> 13; \ + } while (0) + + MM2( 0); + MM2( 1); + MM2( 2); + MM2( 3); + MM2( 4); + MM2( 5); + MM2( 6); + MM2( 7); + MM2( 8); + MM2( 9); + MM2(10); + MM2(11); + MM2(12); + MM2(13); + MM2(14); + MM2(15); + MM2(16); + MM2(17); + MM2(18); + MM2(19); + +#undef MM2 +} + +/* + * Perform a multiplication of two integers modulo 2^255-19. + * Operands are arrays of 20 words, each containing 13 bits of data, in + * little-endian order. Input value may be up to 2^256-1; on output, value + * fits on 256 bits and is lower than twice the modulus. + * + * f255_mul() is the general multiplication, f255_square() is specialised + * for squarings. + */ +#define f255_mul(d, a, b) f255_mulgen(d, a, b, 0) +#define f255_square(d, a) f255_mulgen(d, a, a, 1) + +/* + * Add two values in F255. Partial reduction is performed (down to less + * than twice the modulus). + */ +static void +f255_add(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + int i; + uint32_t cc, w; + + cc = 0; + for (i = 0; i < 20; i ++) { + w = a[i] + b[i] + cc; + d[i] = w & 0x1FFF; + cc = w >> 13; + } + cc = MUL15(w >> 8, 19); + d[19] &= 0xFF; + for (i = 0; i < 20; i ++) { + w = d[i] + cc; + d[i] = w & 0x1FFF; + cc = w >> 13; + } +} + +/* + * Subtract one value from another in F255. Partial reduction is + * performed (down to less than twice the modulus). + */ +static void +f255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + /* + * We actually compute a - b + 2*p, so that the final value is + * necessarily positive. + */ + int i; + uint32_t cc, w; + + cc = (uint32_t)-38; + for (i = 0; i < 20; i ++) { + w = a[i] - b[i] + cc; + d[i] = w & 0x1FFF; + cc = ARSH(w, 13); + } + cc = MUL15((w + 0x200) >> 8, 19); + d[19] &= 0xFF; + for (i = 0; i < 20; i ++) { + w = d[i] + cc; + d[i] = w & 0x1FFF; + cc = w >> 13; + } +} + +/* + * Multiply an integer by the 'A24' constant (121665). Partial reduction + * is performed (down to less than twice the modulus). + */ +static void +f255_mul_a24(uint32_t *d, const uint32_t *a) +{ + int i; + uint32_t cc, w; + + cc = 0; + for (i = 0; i < 20; i ++) { + w = MUL15(a[i], 121665) + cc; + d[i] = w & 0x1FFF; + cc = w >> 13; + } + cc = MUL15(w >> 8, 19); + d[19] &= 0xFF; + for (i = 0; i < 20; i ++) { + w = d[i] + cc; + d[i] = w & 0x1FFF; + cc = w >> 13; + } +} + +static const unsigned char GEN[] = { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char ORDER[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return GEN; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return ORDER; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 0; +} + +static void +cswap(uint32_t *a, uint32_t *b, uint32_t ctl) +{ + int i; + + ctl = -ctl; + for (i = 0; i < 20; i ++) { + uint32_t aw, bw, tw; + + aw = a[i]; + bw = b[i]; + tw = ctl & (aw ^ bw); + a[i] = aw ^ tw; + b[i] = bw ^ tw; + } +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *kb, size_t kblen, int curve) +{ + uint32_t x1[20], x2[20], x3[20], z2[20], z3[20]; + uint32_t a[20], aa[20], b[20], bb[20]; + uint32_t c[20], d[20], e[20], da[20], cb[20]; + unsigned char k[32]; + uint32_t swap; + int i; + + (void)curve; + + /* + * Points are encoded over exactly 32 bytes. Multipliers must fit + * in 32 bytes as well. + * RFC 7748 mandates that the high bit of the last point byte must + * be ignored/cleared. + */ + if (Glen != 32 || kblen > 32) { + return 0; + } + G[31] &= 0x7F; + + /* + * Initialise variables x1, x2, z2, x3 and z3. We set all of them + * into Montgomery representation. + */ + x1[19] = le8_to_le13(x1, G, 32); + memcpy(x3, x1, sizeof x1); + memset(z2, 0, sizeof z2); + memset(x2, 0, sizeof x2); + x2[0] = 1; + memset(z3, 0, sizeof z3); + z3[0] = 1; + + memset(k, 0, (sizeof k) - kblen); + memcpy(k + (sizeof k) - kblen, kb, kblen); + k[31] &= 0xF8; + k[0] &= 0x7F; + k[0] |= 0x40; + + /* obsolete + print_int("x1", x1); + */ + + swap = 0; + for (i = 254; i >= 0; i --) { + uint32_t kt; + + kt = (k[31 - (i >> 3)] >> (i & 7)) & 1; + swap ^= kt; + cswap(x2, x3, swap); + cswap(z2, z3, swap); + swap = kt; + + /* obsolete + print_int("x2", x2); + print_int("z2", z2); + print_int("x3", x3); + print_int("z3", z3); + */ + + f255_add(a, x2, z2); + f255_square(aa, a); + f255_sub(b, x2, z2); + f255_square(bb, b); + f255_sub(e, aa, bb); + f255_add(c, x3, z3); + f255_sub(d, x3, z3); + f255_mul(da, d, a); + f255_mul(cb, c, b); + + /* obsolete + print_int("a ", a); + print_int("aa", aa); + print_int("b ", b); + print_int("bb", bb); + print_int("e ", e); + print_int("c ", c); + print_int("d ", d); + print_int("da", da); + print_int("cb", cb); + */ + + f255_add(x3, da, cb); + f255_square(x3, x3); + f255_sub(z3, da, cb); + f255_square(z3, z3); + f255_mul(z3, z3, x1); + f255_mul(x2, aa, bb); + f255_mul_a24(z2, e); + f255_add(z2, z2, aa); + f255_mul(z2, e, z2); + + /* obsolete + print_int("x2", x2); + print_int("z2", z2); + print_int("x3", x3); + print_int("z3", z3); + */ + } + cswap(x2, x3, swap); + cswap(z2, z3, swap); + + /* + * Inverse z2 with a modular exponentiation. This is a simple + * square-and-multiply algorithm; we mutualise most non-squarings + * since the exponent contains almost only ones. + */ + memcpy(a, z2, sizeof z2); + for (i = 0; i < 15; i ++) { + f255_square(a, a); + f255_mul(a, a, z2); + } + memcpy(b, a, sizeof a); + for (i = 0; i < 14; i ++) { + int j; + + for (j = 0; j < 16; j ++) { + f255_square(b, b); + } + f255_mul(b, b, a); + } + for (i = 14; i >= 0; i --) { + f255_square(b, b); + if ((0xFFEB >> i) & 1) { + f255_mul(b, z2, b); + } + } + f255_mul(x2, x2, b); + reduce_final_f255(x2); + le13_to_le8(G, 32, x2); + return 1; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + const unsigned char *G; + size_t Glen; + + G = api_generator(curve, &Glen); + memcpy(R, G, Glen); + api_mul(R, Glen, x, xlen, curve); + return Glen; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + /* + * We don't implement this method, since it is used for ECDSA + * only, and there is no ECDSA over Curve25519 (which instead + * uses EdDSA). + */ + (void)A; + (void)B; + (void)len; + (void)x; + (void)xlen; + (void)y; + (void)ylen; + (void)curve; + return 0; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_c25519_m15 = { + (uint32_t)0x20000000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_c25519_m31.c b/BearSSL-OG/libbearssl/src/ec/ec_c25519_m31.c new file mode 100644 index 0000000..1dd6d51 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_c25519_m31.c @@ -0,0 +1,800 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* obsolete +#include +#include +static void +print_int(const char *name, const uint32_t *x) +{ + size_t u; + unsigned char tmp[40]; + + printf("%s = ", name); + for (u = 0; u < 9; u ++) { + if (x[u] > 0x3FFFFFFF) { + printf("INVALID:"); + for (u = 0; u < 9; u ++) { + printf(" %08X", x[u]); + } + printf("\n"); + return; + } + } + memset(tmp, 0, sizeof tmp); + for (u = 0; u < 9; u ++) { + uint64_t w; + int j, k; + + w = x[u]; + j = 30 * (int)u; + k = j & 7; + if (k != 0) { + w <<= k; + j -= k; + } + k = j >> 3; + for (j = 0; j < 8; j ++) { + tmp[39 - k - j] |= (unsigned char)w; + w >>= 8; + } + } + for (u = 8; u < 40; u ++) { + printf("%02X", tmp[u]); + } + printf("\n"); +} +*/ + +/* + * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_ + * that right-shifting a signed negative integer copies the sign bit + * (arithmetic right-shift). This is "implementation-defined behaviour", + * i.e. it is not undefined, but it may differ between compilers. Each + * compiler is supposed to document its behaviour in that respect. GCC + * explicitly defines that an arithmetic right shift is used. We expect + * all other compilers to do the same, because underlying CPU offer an + * arithmetic right shift opcode that could not be used otherwise. + */ +#if BR_NO_ARITH_SHIFT +#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ + | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) +#else +#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) +#endif + +/* + * Convert an integer from unsigned little-endian encoding to a sequence of + * 30-bit words in little-endian order. The final "partial" word is + * returned. + */ +static uint32_t +le8_to_le30(uint32_t *dst, const unsigned char *src, size_t len) +{ + uint32_t acc; + int acc_len; + + acc = 0; + acc_len = 0; + while (len -- > 0) { + uint32_t b; + + b = *src ++; + if (acc_len < 22) { + acc |= b << acc_len; + acc_len += 8; + } else { + *dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF; + acc = b >> (30 - acc_len); + acc_len -= 22; + } + } + return acc; +} + +/* + * Convert an integer (30-bit words, little-endian) to unsigned + * little-endian encoding. The total encoding length is provided; all + * the destination bytes will be filled. + */ +static void +le30_to_le8(unsigned char *dst, size_t len, const uint32_t *src) +{ + uint32_t acc; + int acc_len; + + acc = 0; + acc_len = 0; + while (len -- > 0) { + if (acc_len < 8) { + uint32_t w; + + w = *src ++; + *dst ++ = (unsigned char)(acc | (w << acc_len)); + acc = w >> (8 - acc_len); + acc_len += 22; + } else { + *dst ++ = (unsigned char)acc; + acc >>= 8; + acc_len -= 8; + } + } +} + +/* + * Multiply two integers. Source integers are represented as arrays of + * nine 30-bit words, for values up to 2^270-1. Result is encoded over + * 18 words of 30 bits each. + */ +static void +mul9(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + /* + * Maximum intermediate result is no more than + * 10376293531797946367, which fits in 64 bits. Reason: + * + * 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406 + * 10376293531797946367 < 9663676407 * 2^30 + * + * Thus, adding together 9 products of 30-bit integers, with + * a carry of at most 9663676406, yields an integer that fits + * on 64 bits and generates a carry of at most 9663676406. + */ + uint64_t t[17]; + uint64_t cc; + int i; + + t[ 0] = MUL31(a[0], b[0]); + t[ 1] = MUL31(a[0], b[1]) + + MUL31(a[1], b[0]); + t[ 2] = MUL31(a[0], b[2]) + + MUL31(a[1], b[1]) + + MUL31(a[2], b[0]); + t[ 3] = MUL31(a[0], b[3]) + + MUL31(a[1], b[2]) + + MUL31(a[2], b[1]) + + MUL31(a[3], b[0]); + t[ 4] = MUL31(a[0], b[4]) + + MUL31(a[1], b[3]) + + MUL31(a[2], b[2]) + + MUL31(a[3], b[1]) + + MUL31(a[4], b[0]); + t[ 5] = MUL31(a[0], b[5]) + + MUL31(a[1], b[4]) + + MUL31(a[2], b[3]) + + MUL31(a[3], b[2]) + + MUL31(a[4], b[1]) + + MUL31(a[5], b[0]); + t[ 6] = MUL31(a[0], b[6]) + + MUL31(a[1], b[5]) + + MUL31(a[2], b[4]) + + MUL31(a[3], b[3]) + + MUL31(a[4], b[2]) + + MUL31(a[5], b[1]) + + MUL31(a[6], b[0]); + t[ 7] = MUL31(a[0], b[7]) + + MUL31(a[1], b[6]) + + MUL31(a[2], b[5]) + + MUL31(a[3], b[4]) + + MUL31(a[4], b[3]) + + MUL31(a[5], b[2]) + + MUL31(a[6], b[1]) + + MUL31(a[7], b[0]); + t[ 8] = MUL31(a[0], b[8]) + + MUL31(a[1], b[7]) + + MUL31(a[2], b[6]) + + MUL31(a[3], b[5]) + + MUL31(a[4], b[4]) + + MUL31(a[5], b[3]) + + MUL31(a[6], b[2]) + + MUL31(a[7], b[1]) + + MUL31(a[8], b[0]); + t[ 9] = MUL31(a[1], b[8]) + + MUL31(a[2], b[7]) + + MUL31(a[3], b[6]) + + MUL31(a[4], b[5]) + + MUL31(a[5], b[4]) + + MUL31(a[6], b[3]) + + MUL31(a[7], b[2]) + + MUL31(a[8], b[1]); + t[10] = MUL31(a[2], b[8]) + + MUL31(a[3], b[7]) + + MUL31(a[4], b[6]) + + MUL31(a[5], b[5]) + + MUL31(a[6], b[4]) + + MUL31(a[7], b[3]) + + MUL31(a[8], b[2]); + t[11] = MUL31(a[3], b[8]) + + MUL31(a[4], b[7]) + + MUL31(a[5], b[6]) + + MUL31(a[6], b[5]) + + MUL31(a[7], b[4]) + + MUL31(a[8], b[3]); + t[12] = MUL31(a[4], b[8]) + + MUL31(a[5], b[7]) + + MUL31(a[6], b[6]) + + MUL31(a[7], b[5]) + + MUL31(a[8], b[4]); + t[13] = MUL31(a[5], b[8]) + + MUL31(a[6], b[7]) + + MUL31(a[7], b[6]) + + MUL31(a[8], b[5]); + t[14] = MUL31(a[6], b[8]) + + MUL31(a[7], b[7]) + + MUL31(a[8], b[6]); + t[15] = MUL31(a[7], b[8]) + + MUL31(a[8], b[7]); + t[16] = MUL31(a[8], b[8]); + + /* + * Propagate carries. + */ + cc = 0; + for (i = 0; i < 17; i ++) { + uint64_t w; + + w = t[i] + cc; + d[i] = (uint32_t)w & 0x3FFFFFFF; + cc = w >> 30; + } + d[17] = (uint32_t)cc; +} + +/* + * Square a 270-bit integer, represented as an array of nine 30-bit words. + * Result uses 18 words of 30 bits each. + */ +static void +square9(uint32_t *d, const uint32_t *a) +{ + uint64_t t[17]; + uint64_t cc; + int i; + + t[ 0] = MUL31(a[0], a[0]); + t[ 1] = ((MUL31(a[0], a[1])) << 1); + t[ 2] = MUL31(a[1], a[1]) + + ((MUL31(a[0], a[2])) << 1); + t[ 3] = ((MUL31(a[0], a[3]) + + MUL31(a[1], a[2])) << 1); + t[ 4] = MUL31(a[2], a[2]) + + ((MUL31(a[0], a[4]) + + MUL31(a[1], a[3])) << 1); + t[ 5] = ((MUL31(a[0], a[5]) + + MUL31(a[1], a[4]) + + MUL31(a[2], a[3])) << 1); + t[ 6] = MUL31(a[3], a[3]) + + ((MUL31(a[0], a[6]) + + MUL31(a[1], a[5]) + + MUL31(a[2], a[4])) << 1); + t[ 7] = ((MUL31(a[0], a[7]) + + MUL31(a[1], a[6]) + + MUL31(a[2], a[5]) + + MUL31(a[3], a[4])) << 1); + t[ 8] = MUL31(a[4], a[4]) + + ((MUL31(a[0], a[8]) + + MUL31(a[1], a[7]) + + MUL31(a[2], a[6]) + + MUL31(a[3], a[5])) << 1); + t[ 9] = ((MUL31(a[1], a[8]) + + MUL31(a[2], a[7]) + + MUL31(a[3], a[6]) + + MUL31(a[4], a[5])) << 1); + t[10] = MUL31(a[5], a[5]) + + ((MUL31(a[2], a[8]) + + MUL31(a[3], a[7]) + + MUL31(a[4], a[6])) << 1); + t[11] = ((MUL31(a[3], a[8]) + + MUL31(a[4], a[7]) + + MUL31(a[5], a[6])) << 1); + t[12] = MUL31(a[6], a[6]) + + ((MUL31(a[4], a[8]) + + MUL31(a[5], a[7])) << 1); + t[13] = ((MUL31(a[5], a[8]) + + MUL31(a[6], a[7])) << 1); + t[14] = MUL31(a[7], a[7]) + + ((MUL31(a[6], a[8])) << 1); + t[15] = ((MUL31(a[7], a[8])) << 1); + t[16] = MUL31(a[8], a[8]); + + /* + * Propagate carries. + */ + cc = 0; + for (i = 0; i < 17; i ++) { + uint64_t w; + + w = t[i] + cc; + d[i] = (uint32_t)w & 0x3FFFFFFF; + cc = w >> 30; + } + d[17] = (uint32_t)cc; +} + +/* + * Perform a "final reduction" in field F255 (field for Curve25519) + * The source value must be less than twice the modulus. If the value + * is not lower than the modulus, then the modulus is subtracted and + * this function returns 1; otherwise, it leaves it untouched and it + * returns 0. + */ +static uint32_t +reduce_final_f255(uint32_t *d) +{ + uint32_t t[9]; + uint32_t cc; + int i; + + memcpy(t, d, sizeof t); + cc = 19; + for (i = 0; i < 9; i ++) { + uint32_t w; + + w = t[i] + cc; + cc = w >> 30; + t[i] = w & 0x3FFFFFFF; + } + cc = t[8] >> 15; + t[8] &= 0x7FFF; + CCOPY(cc, d, t, sizeof t); + return cc; +} + +/* + * Perform a multiplication of two integers modulo 2^255-19. + * Operands are arrays of 9 words, each containing 30 bits of data, in + * little-endian order. Input value may be up to 2^256-1; on output, value + * fits on 256 bits and is lower than twice the modulus. + */ +static void +f255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t t[18], cc; + int i; + + /* + * Compute raw multiplication. All result words fit in 30 bits + * each; upper word (t[17]) must fit on 2 bits, since the product + * of two 256-bit integers must fit on 512 bits. + */ + mul9(t, a, b); + + /* + * Modular reduction: each high word is added where necessary. + * Since the modulus is 2^255-19 and word 9 corresponds to + * offset 9*30 = 270, word 9+k must be added to word k with + * a factor of 19*2^15 = 622592. The extra bits in word 8 are also + * added that way. + * + * Keeping the carry on 32 bits helps with 32-bit architectures, + * and does not noticeably impact performance on 64-bit systems. + */ + cc = MUL15(t[8] >> 15, 19); /* at most 19*(2^15-1) = 622573 */ + t[8] &= 0x7FFF; + for (i = 0; i < 9; i ++) { + uint64_t w; + + w = (uint64_t)t[i] + (uint64_t)cc + MUL31(t[i + 9], 622592); + t[i] = (uint32_t)w & 0x3FFFFFFF; + cc = (uint32_t)(w >> 30); /* at most 622592 */ + } + + /* + * Original product was up to (2^256-1)^2, i.e. a 512-bit integer. + * This was split into two parts (upper of 257 bits, lower of 255 + * bits), and the upper was added to the lower with a factor 19, + * which means that the intermediate value is less than 77*2^255 + * (19*2^257 + 2^255). Therefore, the extra bits "t[8] >> 15" are + * less than 77, and the initial carry cc is at most 76*19 = 1444. + */ + cc = MUL15(t[8] >> 15, 19); + t[8] &= 0x7FFF; + for (i = 0; i < 9; i ++) { + uint32_t z; + + z = t[i] + cc; + d[i] = z & 0x3FFFFFFF; + cc = z >> 30; + } + + /* + * Final result is at most 2^255 + 1443. In particular, the last + * carry is necessarily 0, since t[8] was truncated to 15 bits. + */ +} + +/* + * Perform a squaring of an integer modulo 2^255-19. + * Operands are arrays of 9 words, each containing 30 bits of data, in + * little-endian order. Input value may be up to 2^256-1; on output, value + * fits on 256 bits and is lower than twice the modulus. + */ +static void +f255_square(uint32_t *d, const uint32_t *a) +{ + uint32_t t[18], cc; + int i; + + /* + * Compute raw squaring. All result words fit in 30 bits + * each; upper word (t[17]) must fit on 2 bits, since the square + * of a 256-bit integers must fit on 512 bits. + */ + square9(t, a); + + /* + * Modular reduction: each high word is added where necessary. + * See f255_mul() for details on the reduction and carry limits. + */ + cc = MUL15(t[8] >> 15, 19); + t[8] &= 0x7FFF; + for (i = 0; i < 9; i ++) { + uint64_t w; + + w = (uint64_t)t[i] + (uint64_t)cc + MUL31(t[i + 9], 622592); + t[i] = (uint32_t)w & 0x3FFFFFFF; + cc = (uint32_t)(w >> 30); + } + cc = MUL15(t[8] >> 15, 19); + t[8] &= 0x7FFF; + for (i = 0; i < 9; i ++) { + uint32_t z; + + z = t[i] + cc; + d[i] = z & 0x3FFFFFFF; + cc = z >> 30; + } +} + +/* + * Add two values in F255. Partial reduction is performed (down to less + * than twice the modulus). + */ +static void +f255_add(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + /* + * Since operand words fit on 30 bits, we can use 32-bit + * variables throughout. + */ + int i; + uint32_t cc, w; + + cc = 0; + for (i = 0; i < 9; i ++) { + w = a[i] + b[i] + cc; + d[i] = w & 0x3FFFFFFF; + cc = w >> 30; + } + cc = MUL15(w >> 15, 19); + d[8] &= 0x7FFF; + for (i = 0; i < 9; i ++) { + w = d[i] + cc; + d[i] = w & 0x3FFFFFFF; + cc = w >> 30; + } +} + +/* + * Subtract one value from another in F255. Partial reduction is + * performed (down to less than twice the modulus). + */ +static void +f255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + /* + * We actually compute a - b + 2*p, so that the final value is + * necessarily positive. + */ + int i; + uint32_t cc, w; + + cc = (uint32_t)-38; + for (i = 0; i < 9; i ++) { + w = a[i] - b[i] + cc; + d[i] = w & 0x3FFFFFFF; + cc = ARSH(w, 30); + } + cc = MUL15((w + 0x10000) >> 15, 19); + d[8] &= 0x7FFF; + for (i = 0; i < 9; i ++) { + w = d[i] + cc; + d[i] = w & 0x3FFFFFFF; + cc = w >> 30; + } +} + +/* + * Multiply an integer by the 'A24' constant (121665). Partial reduction + * is performed (down to less than twice the modulus). + */ +static void +f255_mul_a24(uint32_t *d, const uint32_t *a) +{ + int i; + uint64_t w; + uint32_t cc; + + /* + * a[] is over 256 bits, thus a[8] has length at most 16 bits. + * We single out the processing of the last word: intermediate + * value w is up to 121665*2^16, yielding a carry for the next + * loop of at most 19*(121665*2^16/2^15) = 4623289. + */ + cc = 0; + for (i = 0; i < 8; i ++) { + w = MUL31(a[i], 121665) + (uint64_t)cc; + d[i] = (uint32_t)w & 0x3FFFFFFF; + cc = (uint32_t)(w >> 30); + } + w = MUL31(a[8], 121665) + (uint64_t)cc; + d[8] = (uint32_t)w & 0x7FFF; + cc = MUL15((uint32_t)(w >> 15), 19); + + for (i = 0; i < 9; i ++) { + uint32_t z; + + z = d[i] + cc; + d[i] = z & 0x3FFFFFFF; + cc = z >> 30; + } +} + +static const unsigned char GEN[] = { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char ORDER[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return GEN; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return ORDER; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 0; +} + +static void +cswap(uint32_t *a, uint32_t *b, uint32_t ctl) +{ + int i; + + ctl = -ctl; + for (i = 0; i < 9; i ++) { + uint32_t aw, bw, tw; + + aw = a[i]; + bw = b[i]; + tw = ctl & (aw ^ bw); + a[i] = aw ^ tw; + b[i] = bw ^ tw; + } +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *kb, size_t kblen, int curve) +{ + uint32_t x1[9], x2[9], x3[9], z2[9], z3[9]; + uint32_t a[9], aa[9], b[9], bb[9]; + uint32_t c[9], d[9], e[9], da[9], cb[9]; + unsigned char k[32]; + uint32_t swap; + int i; + + (void)curve; + + /* + * Points are encoded over exactly 32 bytes. Multipliers must fit + * in 32 bytes as well. + * RFC 7748 mandates that the high bit of the last point byte must + * be ignored/cleared. + */ + if (Glen != 32 || kblen > 32) { + return 0; + } + G[31] &= 0x7F; + + /* + * Initialise variables x1, x2, z2, x3 and z3. We set all of them + * into Montgomery representation. + */ + x1[8] = le8_to_le30(x1, G, 32); + memcpy(x3, x1, sizeof x1); + memset(z2, 0, sizeof z2); + memset(x2, 0, sizeof x2); + x2[0] = 1; + memset(z3, 0, sizeof z3); + z3[0] = 1; + + memset(k, 0, (sizeof k) - kblen); + memcpy(k + (sizeof k) - kblen, kb, kblen); + k[31] &= 0xF8; + k[0] &= 0x7F; + k[0] |= 0x40; + + /* obsolete + print_int("x1", x1); + */ + + swap = 0; + for (i = 254; i >= 0; i --) { + uint32_t kt; + + kt = (k[31 - (i >> 3)] >> (i & 7)) & 1; + swap ^= kt; + cswap(x2, x3, swap); + cswap(z2, z3, swap); + swap = kt; + + /* obsolete + print_int("x2", x2); + print_int("z2", z2); + print_int("x3", x3); + print_int("z3", z3); + */ + + f255_add(a, x2, z2); + f255_square(aa, a); + f255_sub(b, x2, z2); + f255_square(bb, b); + f255_sub(e, aa, bb); + f255_add(c, x3, z3); + f255_sub(d, x3, z3); + f255_mul(da, d, a); + f255_mul(cb, c, b); + + /* obsolete + print_int("a ", a); + print_int("aa", aa); + print_int("b ", b); + print_int("bb", bb); + print_int("e ", e); + print_int("c ", c); + print_int("d ", d); + print_int("da", da); + print_int("cb", cb); + */ + + f255_add(x3, da, cb); + f255_square(x3, x3); + f255_sub(z3, da, cb); + f255_square(z3, z3); + f255_mul(z3, z3, x1); + f255_mul(x2, aa, bb); + f255_mul_a24(z2, e); + f255_add(z2, z2, aa); + f255_mul(z2, e, z2); + + /* obsolete + print_int("x2", x2); + print_int("z2", z2); + print_int("x3", x3); + print_int("z3", z3); + */ + } + cswap(x2, x3, swap); + cswap(z2, z3, swap); + + /* + * Inverse z2 with a modular exponentiation. This is a simple + * square-and-multiply algorithm; we mutualise most non-squarings + * since the exponent contains almost only ones. + */ + memcpy(a, z2, sizeof z2); + for (i = 0; i < 15; i ++) { + f255_square(a, a); + f255_mul(a, a, z2); + } + memcpy(b, a, sizeof a); + for (i = 0; i < 14; i ++) { + int j; + + for (j = 0; j < 16; j ++) { + f255_square(b, b); + } + f255_mul(b, b, a); + } + for (i = 14; i >= 0; i --) { + f255_square(b, b); + if ((0xFFEB >> i) & 1) { + f255_mul(b, z2, b); + } + } + f255_mul(x2, x2, b); + reduce_final_f255(x2); + le30_to_le8(G, 32, x2); + return 1; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + const unsigned char *G; + size_t Glen; + + G = api_generator(curve, &Glen); + memcpy(R, G, Glen); + api_mul(R, Glen, x, xlen, curve); + return Glen; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + /* + * We don't implement this method, since it is used for ECDSA + * only, and there is no ECDSA over Curve25519 (which instead + * uses EdDSA). + */ + (void)A; + (void)B; + (void)len; + (void)x; + (void)xlen; + (void)y; + (void)ylen; + (void)curve; + return 0; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_c25519_m31 = { + (uint32_t)0x20000000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_c25519_m62.c b/BearSSL-OG/libbearssl/src/ec/ec_c25519_m62.c new file mode 100644 index 0000000..6b058eb --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_c25519_m62.c @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +#if BR_UMUL128 +#include +#endif + +static const unsigned char GEN[] = { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char ORDER[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return GEN; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return ORDER; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 0; +} + +/* + * A field element is encoded as five 64-bit integers, in basis 2^51. + * Limbs may be occasionally larger than 2^51, to save on carry + * propagation costs. + */ + +#define MASK51 (((uint64_t)1 << 51) - (uint64_t)1) + +/* + * Swap two field elements, conditionally on a flag. + */ +static inline void +f255_cswap(uint64_t *a, uint64_t *b, uint32_t ctl) +{ + uint64_t m, w; + + m = -(uint64_t)ctl; + w = m & (a[0] ^ b[0]); a[0] ^= w; b[0] ^= w; + w = m & (a[1] ^ b[1]); a[1] ^= w; b[1] ^= w; + w = m & (a[2] ^ b[2]); a[2] ^= w; b[2] ^= w; + w = m & (a[3] ^ b[3]); a[3] ^= w; b[3] ^= w; + w = m & (a[4] ^ b[4]); a[4] ^= w; b[4] ^= w; +} + +/* + * Addition with no carry propagation. Limbs double in size. + */ +static inline void +f255_add(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ + d[0] = a[0] + b[0]; + d[1] = a[1] + b[1]; + d[2] = a[2] + b[2]; + d[3] = a[3] + b[3]; + d[4] = a[4] + b[4]; +} + +/* + * Subtraction. + * On input, limbs must fit on 60 bits each. On output, result is + * partially reduced, with max value 2^255+19456; moreover, all + * limbs will fit on 51 bits, except the low limb, which may have + * value up to 2^51+19455. + */ +static inline void +f255_sub(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ + uint64_t cc, w; + + /* + * We compute d = (2^255-19)*1024 + a - b. Since the limbs + * fit on 60 bits, the maximum value of operands are slightly + * more than 2^264, but much less than 2^265-19456. This + * ensures that the result is positive. + */ + + /* + * Initial carry is 19456, since we add 2^265-19456. Each + * individual subtraction may yield a carry up to 513. + */ + w = a[0] - b[0] - 19456; + d[0] = w & MASK51; + cc = -(w >> 51) & 0x3FF; + w = a[1] - b[1] - cc; + d[1] = w & MASK51; + cc = -(w >> 51) & 0x3FF; + w = a[2] - b[2] - cc; + d[2] = w & MASK51; + cc = -(w >> 51) & 0x3FF; + w = a[3] - b[3] - cc; + d[3] = w & MASK51; + cc = -(w >> 51) & 0x3FF; + d[4] = ((uint64_t)1 << 61) + a[4] - b[4] - cc; + + /* + * Partial reduction. The intermediate result may be up to + * slightly above 2^265, but less than 2^265+2^255. When we + * truncate to 255 bits, the upper bits will be at most 1024. + */ + d[0] += 19 * (d[4] >> 51); + d[4] &= MASK51; +} + +/* + * UMUL51(hi, lo, x, y) computes: + * + * hi = floor((x * y) / (2^51)) + * lo = x * y mod 2^51 + * + * Note that lo < 2^51, but "hi" may be larger, if the input operands are + * larger. + */ +#if BR_INT128 + +#define UMUL51(hi, lo, x, y) do { \ + unsigned __int128 umul_tmp; \ + umul_tmp = (unsigned __int128)(x) * (unsigned __int128)(y); \ + (hi) = (uint64_t)(umul_tmp >> 51); \ + (lo) = (uint64_t)umul_tmp & MASK51; \ + } while (0) + +#elif BR_UMUL128 + +#define UMUL51(hi, lo, x, y) do { \ + uint64_t umul_hi, umul_lo; \ + umul_lo = _umul128((x), (y), &umul_hi); \ + (hi) = (umul_hi << 13) | (umul_lo >> 51); \ + (lo) = umul_lo & MASK51; \ + } while (0) + +#endif + +/* + * Multiplication. + * On input, limbs must fit on 54 bits each. + * On output, limb 0 is at most 2^51 + 155647, and other limbs fit + * on 51 bits each. + */ +static inline void +f255_mul(uint64_t *d, uint64_t *a, uint64_t *b) +{ + uint64_t t[10], hi, lo, w, cc; + + /* + * Perform cross products, accumulating values without carry + * propagation. + * + * Since input limbs fit on 54 bits each, each individual + * UMUL51 will produce a "hi" of less than 2^57. The maximum + * sum will be at most 5*(2^57-1) + 4*(2^51-1) (for t[5]), + * i.e. less than 324*2^51. + */ + + UMUL51(t[1], t[0], a[0], b[0]); + + UMUL51(t[2], lo, a[1], b[0]); t[1] += lo; + UMUL51(hi, lo, a[0], b[1]); t[1] += lo; t[2] += hi; + + UMUL51(t[3], lo, a[2], b[0]); t[2] += lo; + UMUL51(hi, lo, a[1], b[1]); t[2] += lo; t[3] += hi; + UMUL51(hi, lo, a[0], b[2]); t[2] += lo; t[3] += hi; + + UMUL51(t[4], lo, a[3], b[0]); t[3] += lo; + UMUL51(hi, lo, a[2], b[1]); t[3] += lo; t[4] += hi; + UMUL51(hi, lo, a[1], b[2]); t[3] += lo; t[4] += hi; + UMUL51(hi, lo, a[0], b[3]); t[3] += lo; t[4] += hi; + + UMUL51(t[5], lo, a[4], b[0]); t[4] += lo; + UMUL51(hi, lo, a[3], b[1]); t[4] += lo; t[5] += hi; + UMUL51(hi, lo, a[2], b[2]); t[4] += lo; t[5] += hi; + UMUL51(hi, lo, a[1], b[3]); t[4] += lo; t[5] += hi; + UMUL51(hi, lo, a[0], b[4]); t[4] += lo; t[5] += hi; + + UMUL51(t[6], lo, a[4], b[1]); t[5] += lo; + UMUL51(hi, lo, a[3], b[2]); t[5] += lo; t[6] += hi; + UMUL51(hi, lo, a[2], b[3]); t[5] += lo; t[6] += hi; + UMUL51(hi, lo, a[1], b[4]); t[5] += lo; t[6] += hi; + + UMUL51(t[7], lo, a[4], b[2]); t[6] += lo; + UMUL51(hi, lo, a[3], b[3]); t[6] += lo; t[7] += hi; + UMUL51(hi, lo, a[2], b[4]); t[6] += lo; t[7] += hi; + + UMUL51(t[8], lo, a[4], b[3]); t[7] += lo; + UMUL51(hi, lo, a[3], b[4]); t[7] += lo; t[8] += hi; + + UMUL51(t[9], lo, a[4], b[4]); t[8] += lo; + + /* + * The upper words t[5]..t[9] are folded back into the lower + * words, using the rule that 2^255 = 19 in the field. + * + * Since each t[i] is less than 324*2^51, the additions below + * will yield less than 6480*2^51 in each limb; this fits in + * 64 bits (6480*2^51 < 8192*2^51 = 2^64), hence there is + * no overflow. + */ + t[0] += 19 * t[5]; + t[1] += 19 * t[6]; + t[2] += 19 * t[7]; + t[3] += 19 * t[8]; + t[4] += 19 * t[9]; + + /* + * Propagate carries. + */ + w = t[0]; + d[0] = w & MASK51; + cc = w >> 51; + w = t[1] + cc; + d[1] = w & MASK51; + cc = w >> 51; + w = t[2] + cc; + d[2] = w & MASK51; + cc = w >> 51; + w = t[3] + cc; + d[3] = w & MASK51; + cc = w >> 51; + w = t[4] + cc; + d[4] = w & MASK51; + cc = w >> 51; + + /* + * Since the limbs were 64-bit values, the top carry is at + * most 8192 (in practice, that cannot be reached). We simply + * performed a partial reduction. + */ + d[0] += 19 * cc; +} + +/* + * Multiplication by A24 = 121665. + * Input must have limbs of 60 bits at most. + */ +static inline void +f255_mul_a24(uint64_t *d, const uint64_t *a) +{ + uint64_t t[5], cc, w; + + /* + * 121665 = 15 * 8111. We first multiply by 15, with carry + * propagation and partial reduction. + */ + w = a[0] * 15; + t[0] = w & MASK51; + cc = w >> 51; + w = a[1] * 15 + cc; + t[1] = w & MASK51; + cc = w >> 51; + w = a[2] * 15 + cc; + t[2] = w & MASK51; + cc = w >> 51; + w = a[3] * 15 + cc; + t[3] = w & MASK51; + cc = w >> 51; + w = a[4] * 15 + cc; + t[4] = w & MASK51; + t[0] += 19 * (w >> 51); + + /* + * Then multiplication by 8111. At that point, we known that + * t[0] is less than 2^51 + 19*8192, and other limbs are less + * than 2^51; thus, there will be no overflow. + */ + w = t[0] * 8111; + d[0] = w & MASK51; + cc = w >> 51; + w = t[1] * 8111 + cc; + d[1] = w & MASK51; + cc = w >> 51; + w = t[2] * 8111 + cc; + d[2] = w & MASK51; + cc = w >> 51; + w = t[3] * 8111 + cc; + d[3] = w & MASK51; + cc = w >> 51; + w = t[4] * 8111 + cc; + d[4] = w & MASK51; + d[0] += 19 * (w >> 51); +} + +/* + * Finalize reduction. + * On input, limbs must fit on 51 bits, except possibly the low limb, + * which may be slightly above 2^51. + */ +static inline void +f255_final_reduce(uint64_t *a) +{ + uint64_t t[5], cc, w; + + /* + * We add 19. If the result (in t[]) is below 2^255, then a[] + * is already less than 2^255-19, thus already reduced. + * Otherwise, we subtract 2^255 from t[], in which case we + * have t = a - (2^255-19), and that's our result. + */ + w = a[0] + 19; + t[0] = w & MASK51; + cc = w >> 51; + w = a[1] + cc; + t[1] = w & MASK51; + cc = w >> 51; + w = a[2] + cc; + t[2] = w & MASK51; + cc = w >> 51; + w = a[3] + cc; + t[3] = w & MASK51; + cc = w >> 51; + w = a[4] + cc; + t[4] = w & MASK51; + cc = w >> 51; + + /* + * The bit 255 of t is in cc. If that bit is 0, when a[] must + * be unchanged; otherwise, it must be replaced with t[]. + */ + cc = -cc; + a[0] ^= cc & (a[0] ^ t[0]); + a[1] ^= cc & (a[1] ^ t[1]); + a[2] ^= cc & (a[2] ^ t[2]); + a[3] ^= cc & (a[3] ^ t[3]); + a[4] ^= cc & (a[4] ^ t[4]); +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *kb, size_t kblen, int curve) +{ + unsigned char k[32]; + uint64_t x1[5], x2[5], z2[5], x3[5], z3[5]; + uint32_t swap; + int i; + + (void)curve; + + /* + * Points are encoded over exactly 32 bytes. Multipliers must fit + * in 32 bytes as well. + */ + if (Glen != 32 || kblen > 32) { + return 0; + } + + /* + * RFC 7748 mandates that the high bit of the last point byte must + * be ignored/cleared; the "& MASK51" in the initialization for + * x1[4] clears that bit. + */ + x1[0] = br_dec64le(&G[0]) & MASK51; + x1[1] = (br_dec64le(&G[6]) >> 3) & MASK51; + x1[2] = (br_dec64le(&G[12]) >> 6) & MASK51; + x1[3] = (br_dec64le(&G[19]) >> 1) & MASK51; + x1[4] = (br_dec64le(&G[24]) >> 12) & MASK51; + + /* + * We can use memset() to clear values, because exact-width types + * like uint64_t are guaranteed to have no padding bits or + * trap representations. + */ + memset(x2, 0, sizeof x2); + x2[0] = 1; + memset(z2, 0, sizeof z2); + memcpy(x3, x1, sizeof x1); + memcpy(z3, x2, sizeof x2); + + /* + * The multiplier is provided in big-endian notation, and + * possibly shorter than 32 bytes. + */ + memset(k, 0, (sizeof k) - kblen); + memcpy(k + (sizeof k) - kblen, kb, kblen); + k[31] &= 0xF8; + k[0] &= 0x7F; + k[0] |= 0x40; + + swap = 0; + + for (i = 254; i >= 0; i --) { + uint64_t a[5], aa[5], b[5], bb[5], e[5]; + uint64_t c[5], d[5], da[5], cb[5]; + uint32_t kt; + + kt = (k[31 - (i >> 3)] >> (i & 7)) & 1; + swap ^= kt; + f255_cswap(x2, x3, swap); + f255_cswap(z2, z3, swap); + swap = kt; + + /* + * At that point, limbs of x_2 and z_2 are assumed to fit + * on at most 52 bits each. + * + * Each f255_add() adds one bit to the maximum range of + * the values, but f255_sub() and f255_mul() bring back + * the limbs into 52 bits. All f255_add() outputs are + * used only as inputs for f255_mul(), which ensures + * that limbs remain in the proper range. + */ + + /* A = x_2 + z_2 -- limbs fit on 53 bits each */ + f255_add(a, x2, z2); + + /* AA = A^2 */ + f255_mul(aa, a, a); + + /* B = x_2 - z_2 */ + f255_sub(b, x2, z2); + + /* BB = B^2 */ + f255_mul(bb, b, b); + + /* E = AA - BB */ + f255_sub(e, aa, bb); + + /* C = x_3 + z_3 -- limbs fit on 53 bits each */ + f255_add(c, x3, z3); + + /* D = x_3 - z_3 */ + f255_sub(d, x3, z3); + + /* DA = D * A */ + f255_mul(da, d, a); + + /* CB = C * B */ + f255_mul(cb, c, b); + + /* x_3 = (DA + CB)^2 */ + f255_add(x3, da, cb); + f255_mul(x3, x3, x3); + + /* z_3 = x_1 * (DA - CB)^2 */ + f255_sub(z3, da, cb); + f255_mul(z3, z3, z3); + f255_mul(z3, x1, z3); + + /* x_2 = AA * BB */ + f255_mul(x2, aa, bb); + + /* z_2 = E * (AA + a24 * E) */ + f255_mul_a24(z2, e); + f255_add(z2, aa, z2); + f255_mul(z2, e, z2); + } + + f255_cswap(x2, x3, swap); + f255_cswap(z2, z3, swap); + + /* + * Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize + * most non-squarings. We use x1 and x3, now useless, as temporaries. + */ + memcpy(x1, z2, sizeof z2); + for (i = 0; i < 15; i ++) { + f255_mul(x1, x1, x1); + f255_mul(x1, x1, z2); + } + memcpy(x3, x1, sizeof x1); + for (i = 0; i < 14; i ++) { + int j; + + for (j = 0; j < 16; j ++) { + f255_mul(x3, x3, x3); + } + f255_mul(x3, x3, x1); + } + for (i = 14; i >= 0; i --) { + f255_mul(x3, x3, x3); + if ((0xFFEB >> i) & 1) { + f255_mul(x3, z2, x3); + } + } + + /* + * Compute x2/z2. We have 1/z2 in x3. + */ + f255_mul(x2, x2, x3); + f255_final_reduce(x2); + + /* + * Encode the final x2 value in little-endian. We first assemble + * the limbs into 64-bit values. + */ + x2[0] |= x2[1] << 51; + x2[1] = (x2[1] >> 13) | (x2[2] << 38); + x2[2] = (x2[2] >> 26) | (x2[3] << 25); + x2[3] = (x2[3] >> 39) | (x2[4] << 12); + br_enc64le(G, x2[0]); + br_enc64le(G + 8, x2[1]); + br_enc64le(G + 16, x2[2]); + br_enc64le(G + 24, x2[3]); + return 1; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + const unsigned char *G; + size_t Glen; + + G = api_generator(curve, &Glen); + memcpy(R, G, Glen); + api_mul(R, Glen, x, xlen, curve); + return Glen; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + /* + * We don't implement this method, since it is used for ECDSA + * only, and there is no ECDSA over Curve25519 (which instead + * uses EdDSA). + */ + (void)A; + (void)B; + (void)len; + (void)x; + (void)xlen; + (void)y; + (void)ylen; + (void)curve; + return 0; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_c25519_m62 = { + (uint32_t)0x20000000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_c25519_m62_get(void) +{ + return &br_ec_c25519_m62; +} + +#else + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_c25519_m62_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/ec/ec_c25519_m64.c b/BearSSL-OG/libbearssl/src/ec/ec_c25519_m64.c new file mode 100644 index 0000000..df48834 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_c25519_m64.c @@ -0,0 +1,831 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +#if BR_UMUL128 +#include +#endif + +static const unsigned char GEN[] = { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char ORDER[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return GEN; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return ORDER; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 0; +} + +/* + * A field element is encoded as four 64-bit integers, in basis 2^63. + * Operations return partially reduced values, which may range up to + * 2^255+37. + */ + +#define MASK63 (((uint64_t)1 << 63) - (uint64_t)1) + +/* + * Swap two field elements, conditionally on a flag. + */ +static inline void +f255_cswap(uint64_t *a, uint64_t *b, uint32_t ctl) +{ + uint64_t m, w; + + m = -(uint64_t)ctl; + w = m & (a[0] ^ b[0]); a[0] ^= w; b[0] ^= w; + w = m & (a[1] ^ b[1]); a[1] ^= w; b[1] ^= w; + w = m & (a[2] ^ b[2]); a[2] ^= w; b[2] ^= w; + w = m & (a[3] ^ b[3]); a[3] ^= w; b[3] ^= w; +} + +/* + * Addition in the field. + */ +static inline void +f255_add(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ +#if BR_INT128 + + uint64_t t0, t1, t2, t3, cc; + unsigned __int128 z; + + z = (unsigned __int128)a[0] + (unsigned __int128)b[0]; + t0 = (uint64_t)z; + z = (unsigned __int128)a[1] + (unsigned __int128)b[1] + (z >> 64); + t1 = (uint64_t)z; + z = (unsigned __int128)a[2] + (unsigned __int128)b[2] + (z >> 64); + t2 = (uint64_t)z; + z = (unsigned __int128)a[3] + (unsigned __int128)b[3] + (z >> 64); + t3 = (uint64_t)z & MASK63; + cc = (uint64_t)(z >> 63); + + /* + * Since operands are at most 2^255+37, the sum is at most + * 2^256+74; thus, the carry cc is equal to 0, 1 or 2. + * + * We use: 2^255 = 19 mod p. + * Since we add 0, 19 or 38 to a value that fits on 255 bits, + * the result is at most 2^255+37. + */ + z = (unsigned __int128)t0 + (unsigned __int128)(19 * cc); + d[0] = (uint64_t)z; + z = (unsigned __int128)t1 + (z >> 64); + d[1] = (uint64_t)z; + z = (unsigned __int128)t2 + (z >> 64); + d[2] = (uint64_t)z; + d[3] = t3 + (uint64_t)(z >> 64); + +#elif BR_UMUL128 + + uint64_t t0, t1, t2, t3, cc; + unsigned char k; + + k = _addcarry_u64(0, a[0], b[0], &t0); + k = _addcarry_u64(k, a[1], b[1], &t1); + k = _addcarry_u64(k, a[2], b[2], &t2); + k = _addcarry_u64(k, a[3], b[3], &t3); + cc = (k << 1) + (t3 >> 63); + t3 &= MASK63; + + /* + * Since operands are at most 2^255+37, the sum is at most + * 2^256+74; thus, the carry cc is equal to 0, 1 or 2. + * + * We use: 2^255 = 19 mod p. + * Since we add 0, 19 or 38 to a value that fits on 255 bits, + * the result is at most 2^255+37. + */ + k = _addcarry_u64(0, t0, 19 * cc, &d[0]); + k = _addcarry_u64(k, t1, 0, &d[1]); + k = _addcarry_u64(k, t2, 0, &d[2]); + (void)_addcarry_u64(k, t3, 0, &d[3]); + +#endif +} + +/* + * Subtraction. + */ +static inline void +f255_sub(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ +#if BR_INT128 + + /* + * We compute t = 2^256 - 38 + a - b, which is necessarily + * positive but lower than 2^256 + 2^255, since a <= 2^255 + 37 + * and b <= 2^255 + 37. We then subtract 0, p or 2*p, depending + * on the two upper bits of t (bits 255 and 256). + */ + + uint64_t t0, t1, t2, t3, t4, cc; + unsigned __int128 z; + + z = (unsigned __int128)a[0] - (unsigned __int128)b[0] - 38; + t0 = (uint64_t)z; + cc = -(uint64_t)(z >> 64); + z = (unsigned __int128)a[1] - (unsigned __int128)b[1] + - (unsigned __int128)cc; + t1 = (uint64_t)z; + cc = -(uint64_t)(z >> 64); + z = (unsigned __int128)a[2] - (unsigned __int128)b[2] + - (unsigned __int128)cc; + t2 = (uint64_t)z; + cc = -(uint64_t)(z >> 64); + z = (unsigned __int128)a[3] - (unsigned __int128)b[3] + - (unsigned __int128)cc; + t3 = (uint64_t)z; + t4 = 1 + (uint64_t)(z >> 64); + + /* + * We have a 257-bit result. The two top bits can be 00, 01 or 10, + * but not 11 (value t <= 2^256 - 38 + 2^255 + 37 = 2^256 + 2^255 - 1). + * Therefore, we can truncate to 255 bits, and add 0, 19 or 38. + * This guarantees that the result is at most 2^255+37. + */ + cc = (38 & -t4) + (19 & -(t3 >> 63)); + t3 &= MASK63; + z = (unsigned __int128)t0 + (unsigned __int128)cc; + d[0] = (uint64_t)z; + z = (unsigned __int128)t1 + (z >> 64); + d[1] = (uint64_t)z; + z = (unsigned __int128)t2 + (z >> 64); + d[2] = (uint64_t)z; + d[3] = t3 + (uint64_t)(z >> 64); + +#elif BR_UMUL128 + + /* + * We compute t = 2^256 - 38 + a - b, which is necessarily + * positive but lower than 2^256 + 2^255, since a <= 2^255 + 37 + * and b <= 2^255 + 37. We then subtract 0, p or 2*p, depending + * on the two upper bits of t (bits 255 and 256). + */ + + uint64_t t0, t1, t2, t3, t4; + unsigned char k; + + k = _subborrow_u64(0, a[0], b[0], &t0); + k = _subborrow_u64(k, a[1], b[1], &t1); + k = _subborrow_u64(k, a[2], b[2], &t2); + k = _subborrow_u64(k, a[3], b[3], &t3); + (void)_subborrow_u64(k, 1, 0, &t4); + + k = _subborrow_u64(0, t0, 38, &t0); + k = _subborrow_u64(k, t1, 0, &t1); + k = _subborrow_u64(k, t2, 0, &t2); + k = _subborrow_u64(k, t3, 0, &t3); + (void)_subborrow_u64(k, t4, 0, &t4); + + /* + * We have a 257-bit result. The two top bits can be 00, 01 or 10, + * but not 11 (value t <= 2^256 - 38 + 2^255 + 37 = 2^256 + 2^255 - 1). + * Therefore, we can truncate to 255 bits, and add 0, 19 or 38. + * This guarantees that the result is at most 2^255+37. + */ + t4 = (38 & -t4) + (19 & -(t3 >> 63)); + t3 &= MASK63; + k = _addcarry_u64(0, t0, t4, &d[0]); + k = _addcarry_u64(k, t1, 0, &d[1]); + k = _addcarry_u64(k, t2, 0, &d[2]); + (void)_addcarry_u64(k, t3, 0, &d[3]); + +#endif +} + +/* + * Multiplication. + */ +static inline void +f255_mul(uint64_t *d, uint64_t *a, uint64_t *b) +{ +#if BR_INT128 + + unsigned __int128 z; + uint64_t t0, t1, t2, t3, t4, t5, t6, t7, th; + + /* + * Compute the product a*b over plain integers. + */ + z = (unsigned __int128)a[0] * (unsigned __int128)b[0]; + t0 = (uint64_t)z; + z = (unsigned __int128)a[0] * (unsigned __int128)b[1] + (z >> 64); + t1 = (uint64_t)z; + z = (unsigned __int128)a[0] * (unsigned __int128)b[2] + (z >> 64); + t2 = (uint64_t)z; + z = (unsigned __int128)a[0] * (unsigned __int128)b[3] + (z >> 64); + t3 = (uint64_t)z; + t4 = (uint64_t)(z >> 64); + + z = (unsigned __int128)a[1] * (unsigned __int128)b[0] + + (unsigned __int128)t1; + t1 = (uint64_t)z; + z = (unsigned __int128)a[1] * (unsigned __int128)b[1] + + (unsigned __int128)t2 + (z >> 64); + t2 = (uint64_t)z; + z = (unsigned __int128)a[1] * (unsigned __int128)b[2] + + (unsigned __int128)t3 + (z >> 64); + t3 = (uint64_t)z; + z = (unsigned __int128)a[1] * (unsigned __int128)b[3] + + (unsigned __int128)t4 + (z >> 64); + t4 = (uint64_t)z; + t5 = (uint64_t)(z >> 64); + + z = (unsigned __int128)a[2] * (unsigned __int128)b[0] + + (unsigned __int128)t2; + t2 = (uint64_t)z; + z = (unsigned __int128)a[2] * (unsigned __int128)b[1] + + (unsigned __int128)t3 + (z >> 64); + t3 = (uint64_t)z; + z = (unsigned __int128)a[2] * (unsigned __int128)b[2] + + (unsigned __int128)t4 + (z >> 64); + t4 = (uint64_t)z; + z = (unsigned __int128)a[2] * (unsigned __int128)b[3] + + (unsigned __int128)t5 + (z >> 64); + t5 = (uint64_t)z; + t6 = (uint64_t)(z >> 64); + + z = (unsigned __int128)a[3] * (unsigned __int128)b[0] + + (unsigned __int128)t3; + t3 = (uint64_t)z; + z = (unsigned __int128)a[3] * (unsigned __int128)b[1] + + (unsigned __int128)t4 + (z >> 64); + t4 = (uint64_t)z; + z = (unsigned __int128)a[3] * (unsigned __int128)b[2] + + (unsigned __int128)t5 + (z >> 64); + t5 = (uint64_t)z; + z = (unsigned __int128)a[3] * (unsigned __int128)b[3] + + (unsigned __int128)t6 + (z >> 64); + t6 = (uint64_t)z; + t7 = (uint64_t)(z >> 64); + + /* + * Modulo p, we have: + * + * 2^255 = 19 + * 2^510 = 19*19 = 361 + * + * We split the intermediate t into three parts, in basis + * 2^255. The low one will be in t0..t3; the middle one in t4..t7. + * The upper one can only be a single bit (th), since the + * multiplication operands are at most 2^255+37 each. + */ + th = t7 >> 62; + t7 = ((t7 << 1) | (t6 >> 63)) & MASK63; + t6 = (t6 << 1) | (t5 >> 63); + t5 = (t5 << 1) | (t4 >> 63); + t4 = (t4 << 1) | (t3 >> 63); + t3 &= MASK63; + + /* + * Multiply the middle part (t4..t7) by 19. We truncate it to + * 255 bits; the extra bits will go along with th. + */ + z = (unsigned __int128)t4 * 19; + t4 = (uint64_t)z; + z = (unsigned __int128)t5 * 19 + (z >> 64); + t5 = (uint64_t)z; + z = (unsigned __int128)t6 * 19 + (z >> 64); + t6 = (uint64_t)z; + z = (unsigned __int128)t7 * 19 + (z >> 64); + t7 = (uint64_t)z & MASK63; + + th = (361 & -th) + (19 * (uint64_t)(z >> 63)); + + /* + * Add elements together. + * At this point: + * t0..t3 fits on 255 bits. + * t4..t7 fits on 255 bits. + * th <= 361 + 342 = 703. + */ + z = (unsigned __int128)t0 + (unsigned __int128)t4 + + (unsigned __int128)th; + t0 = (uint64_t)z; + z = (unsigned __int128)t1 + (unsigned __int128)t5 + (z >> 64); + t1 = (uint64_t)z; + z = (unsigned __int128)t2 + (unsigned __int128)t6 + (z >> 64); + t2 = (uint64_t)z; + z = (unsigned __int128)t3 + (unsigned __int128)t7 + (z >> 64); + t3 = (uint64_t)z & MASK63; + th = (uint64_t)(z >> 63); + + /* + * Since the sum is at most 2^256 + 703, the two upper bits, in th, + * can only have value 0, 1 or 2. We just add th*19, which + * guarantees a result of at most 2^255+37. + */ + z = (unsigned __int128)t0 + (19 * th); + d[0] = (uint64_t)z; + z = (unsigned __int128)t1 + (z >> 64); + d[1] = (uint64_t)z; + z = (unsigned __int128)t2 + (z >> 64); + d[2] = (uint64_t)z; + d[3] = t3 + (uint64_t)(z >> 64); + +#elif BR_UMUL128 + + uint64_t t0, t1, t2, t3, t4, t5, t6, t7, th; + uint64_t h0, h1, h2, h3; + unsigned char k; + + /* + * Compute the product a*b over plain integers. + */ + t0 = _umul128(a[0], b[0], &h0); + t1 = _umul128(a[0], b[1], &h1); + k = _addcarry_u64(0, t1, h0, &t1); + t2 = _umul128(a[0], b[2], &h2); + k = _addcarry_u64(k, t2, h1, &t2); + t3 = _umul128(a[0], b[3], &h3); + k = _addcarry_u64(k, t3, h2, &t3); + (void)_addcarry_u64(k, h3, 0, &t4); + + k = _addcarry_u64(0, _umul128(a[1], b[0], &h0), t1, &t1); + k = _addcarry_u64(k, _umul128(a[1], b[1], &h1), t2, &t2); + k = _addcarry_u64(k, _umul128(a[1], b[2], &h2), t3, &t3); + k = _addcarry_u64(k, _umul128(a[1], b[3], &h3), t4, &t4); + t5 = k; + k = _addcarry_u64(0, t2, h0, &t2); + k = _addcarry_u64(k, t3, h1, &t3); + k = _addcarry_u64(k, t4, h2, &t4); + (void)_addcarry_u64(k, t5, h3, &t5); + + k = _addcarry_u64(0, _umul128(a[2], b[0], &h0), t2, &t2); + k = _addcarry_u64(k, _umul128(a[2], b[1], &h1), t3, &t3); + k = _addcarry_u64(k, _umul128(a[2], b[2], &h2), t4, &t4); + k = _addcarry_u64(k, _umul128(a[2], b[3], &h3), t5, &t5); + t6 = k; + k = _addcarry_u64(0, t3, h0, &t3); + k = _addcarry_u64(k, t4, h1, &t4); + k = _addcarry_u64(k, t5, h2, &t5); + (void)_addcarry_u64(k, t6, h3, &t6); + + k = _addcarry_u64(0, _umul128(a[3], b[0], &h0), t3, &t3); + k = _addcarry_u64(k, _umul128(a[3], b[1], &h1), t4, &t4); + k = _addcarry_u64(k, _umul128(a[3], b[2], &h2), t5, &t5); + k = _addcarry_u64(k, _umul128(a[3], b[3], &h3), t6, &t6); + t7 = k; + k = _addcarry_u64(0, t4, h0, &t4); + k = _addcarry_u64(k, t5, h1, &t5); + k = _addcarry_u64(k, t6, h2, &t6); + (void)_addcarry_u64(k, t7, h3, &t7); + + /* + * Modulo p, we have: + * + * 2^255 = 19 + * 2^510 = 19*19 = 361 + * + * We split the intermediate t into three parts, in basis + * 2^255. The low one will be in t0..t3; the middle one in t4..t7. + * The upper one can only be a single bit (th), since the + * multiplication operands are at most 2^255+37 each. + */ + th = t7 >> 62; + t7 = ((t7 << 1) | (t6 >> 63)) & MASK63; + t6 = (t6 << 1) | (t5 >> 63); + t5 = (t5 << 1) | (t4 >> 63); + t4 = (t4 << 1) | (t3 >> 63); + t3 &= MASK63; + + /* + * Multiply the middle part (t4..t7) by 19. We truncate it to + * 255 bits; the extra bits will go along with th. + */ + t4 = _umul128(t4, 19, &h0); + t5 = _umul128(t5, 19, &h1); + t6 = _umul128(t6, 19, &h2); + t7 = _umul128(t7, 19, &h3); + k = _addcarry_u64(0, t5, h0, &t5); + k = _addcarry_u64(k, t6, h1, &t6); + k = _addcarry_u64(k, t7, h2, &t7); + (void)_addcarry_u64(k, h3, 0, &h3); + th = (361 & -th) + (19 * ((h3 << 1) + (t7 >> 63))); + t7 &= MASK63; + + /* + * Add elements together. + * At this point: + * t0..t3 fits on 255 bits. + * t4..t7 fits on 255 bits. + * th <= 361 + 342 = 703. + */ + k = _addcarry_u64(0, t0, t4, &t0); + k = _addcarry_u64(k, t1, t5, &t1); + k = _addcarry_u64(k, t2, t6, &t2); + k = _addcarry_u64(k, t3, t7, &t3); + t4 = k; + k = _addcarry_u64(0, t0, th, &t0); + k = _addcarry_u64(k, t1, 0, &t1); + k = _addcarry_u64(k, t2, 0, &t2); + k = _addcarry_u64(k, t3, 0, &t3); + (void)_addcarry_u64(k, t4, 0, &t4); + + th = (t4 << 1) + (t3 >> 63); + t3 &= MASK63; + + /* + * Since the sum is at most 2^256 + 703, the two upper bits, in th, + * can only have value 0, 1 or 2. We just add th*19, which + * guarantees a result of at most 2^255+37. + */ + k = _addcarry_u64(0, t0, 19 * th, &d[0]); + k = _addcarry_u64(k, t1, 0, &d[1]); + k = _addcarry_u64(k, t2, 0, &d[2]); + (void)_addcarry_u64(k, t3, 0, &d[3]); + +#endif +} + +/* + * Multiplication by A24 = 121665. + */ +static inline void +f255_mul_a24(uint64_t *d, const uint64_t *a) +{ +#if BR_INT128 + + uint64_t t0, t1, t2, t3; + unsigned __int128 z; + + z = (unsigned __int128)a[0] * 121665; + t0 = (uint64_t)z; + z = (unsigned __int128)a[1] * 121665 + (z >> 64); + t1 = (uint64_t)z; + z = (unsigned __int128)a[2] * 121665 + (z >> 64); + t2 = (uint64_t)z; + z = (unsigned __int128)a[3] * 121665 + (z >> 64); + t3 = (uint64_t)z & MASK63; + + z = (unsigned __int128)t0 + (19 * (uint64_t)(z >> 63)); + t0 = (uint64_t)z; + z = (unsigned __int128)t1 + (z >> 64); + t1 = (uint64_t)z; + z = (unsigned __int128)t2 + (z >> 64); + t2 = (uint64_t)z; + t3 = t3 + (uint64_t)(z >> 64); + + z = (unsigned __int128)t0 + (19 & -(t3 >> 63)); + d[0] = (uint64_t)z; + z = (unsigned __int128)t1 + (z >> 64); + d[1] = (uint64_t)z; + z = (unsigned __int128)t2 + (z >> 64); + d[2] = (uint64_t)z; + d[3] = (t3 & MASK63) + (uint64_t)(z >> 64); + +#elif BR_UMUL128 + + uint64_t t0, t1, t2, t3, t4, h0, h1, h2, h3; + unsigned char k; + + t0 = _umul128(a[0], 121665, &h0); + t1 = _umul128(a[1], 121665, &h1); + k = _addcarry_u64(0, t1, h0, &t1); + t2 = _umul128(a[2], 121665, &h2); + k = _addcarry_u64(k, t2, h1, &t2); + t3 = _umul128(a[3], 121665, &h3); + k = _addcarry_u64(k, t3, h2, &t3); + (void)_addcarry_u64(k, h3, 0, &t4); + + t4 = (t4 << 1) + (t3 >> 63); + t3 &= MASK63; + k = _addcarry_u64(0, t0, 19 * t4, &t0); + k = _addcarry_u64(k, t1, 0, &t1); + k = _addcarry_u64(k, t2, 0, &t2); + (void)_addcarry_u64(k, t3, 0, &t3); + + t4 = 19 & -(t3 >> 63); + t3 &= MASK63; + k = _addcarry_u64(0, t0, t4, &d[0]); + k = _addcarry_u64(k, t1, 0, &d[1]); + k = _addcarry_u64(k, t2, 0, &d[2]); + (void)_addcarry_u64(k, t3, 0, &d[3]); + +#endif +} + +/* + * Finalize reduction. + */ +static inline void +f255_final_reduce(uint64_t *a) +{ +#if BR_INT128 + + uint64_t t0, t1, t2, t3, m; + unsigned __int128 z; + + /* + * We add 19. If the result (in t) is below 2^255, then a[] + * is already less than 2^255-19, thus already reduced. + * Otherwise, we subtract 2^255 from t[], in which case we + * have t = a - (2^255-19), and that's our result. + */ + z = (unsigned __int128)a[0] + 19; + t0 = (uint64_t)z; + z = (unsigned __int128)a[1] + (z >> 64); + t1 = (uint64_t)z; + z = (unsigned __int128)a[2] + (z >> 64); + t2 = (uint64_t)z; + t3 = a[3] + (uint64_t)(z >> 64); + + m = -(t3 >> 63); + t3 &= MASK63; + a[0] ^= m & (a[0] ^ t0); + a[1] ^= m & (a[1] ^ t1); + a[2] ^= m & (a[2] ^ t2); + a[3] ^= m & (a[3] ^ t3); + +#elif BR_UMUL128 + + uint64_t t0, t1, t2, t3, m; + unsigned char k; + + /* + * We add 19. If the result (in t) is below 2^255, then a[] + * is already less than 2^255-19, thus already reduced. + * Otherwise, we subtract 2^255 from t[], in which case we + * have t = a - (2^255-19), and that's our result. + */ + k = _addcarry_u64(0, a[0], 19, &t0); + k = _addcarry_u64(k, a[1], 0, &t1); + k = _addcarry_u64(k, a[2], 0, &t2); + (void)_addcarry_u64(k, a[3], 0, &t3); + + m = -(t3 >> 63); + t3 &= MASK63; + a[0] ^= m & (a[0] ^ t0); + a[1] ^= m & (a[1] ^ t1); + a[2] ^= m & (a[2] ^ t2); + a[3] ^= m & (a[3] ^ t3); + +#endif +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *kb, size_t kblen, int curve) +{ + unsigned char k[32]; + uint64_t x1[4], x2[4], z2[4], x3[4], z3[4]; + uint32_t swap; + int i; + + (void)curve; + + /* + * Points are encoded over exactly 32 bytes. Multipliers must fit + * in 32 bytes as well. + */ + if (Glen != 32 || kblen > 32) { + return 0; + } + + /* + * RFC 7748 mandates that the high bit of the last point byte must + * be ignored/cleared. + */ + x1[0] = br_dec64le(&G[ 0]); + x1[1] = br_dec64le(&G[ 8]); + x1[2] = br_dec64le(&G[16]); + x1[3] = br_dec64le(&G[24]) & MASK63; + + /* + * We can use memset() to clear values, because exact-width types + * like uint64_t are guaranteed to have no padding bits or + * trap representations. + */ + memset(x2, 0, sizeof x2); + x2[0] = 1; + memset(z2, 0, sizeof z2); + memcpy(x3, x1, sizeof x1); + memcpy(z3, x2, sizeof x2); + + /* + * The multiplier is provided in big-endian notation, and + * possibly shorter than 32 bytes. + */ + memset(k, 0, (sizeof k) - kblen); + memcpy(k + (sizeof k) - kblen, kb, kblen); + k[31] &= 0xF8; + k[0] &= 0x7F; + k[0] |= 0x40; + + swap = 0; + + for (i = 254; i >= 0; i --) { + uint64_t a[4], aa[4], b[4], bb[4], e[4]; + uint64_t c[4], d[4], da[4], cb[4]; + uint32_t kt; + + kt = (k[31 - (i >> 3)] >> (i & 7)) & 1; + swap ^= kt; + f255_cswap(x2, x3, swap); + f255_cswap(z2, z3, swap); + swap = kt; + + /* A = x_2 + z_2 */ + f255_add(a, x2, z2); + + /* AA = A^2 */ + f255_mul(aa, a, a); + + /* B = x_2 - z_2 */ + f255_sub(b, x2, z2); + + /* BB = B^2 */ + f255_mul(bb, b, b); + + /* E = AA - BB */ + f255_sub(e, aa, bb); + + /* C = x_3 + z_3 */ + f255_add(c, x3, z3); + + /* D = x_3 - z_3 */ + f255_sub(d, x3, z3); + + /* DA = D * A */ + f255_mul(da, d, a); + + /* CB = C * B */ + f255_mul(cb, c, b); + + /* x_3 = (DA + CB)^2 */ + f255_add(x3, da, cb); + f255_mul(x3, x3, x3); + + /* z_3 = x_1 * (DA - CB)^2 */ + f255_sub(z3, da, cb); + f255_mul(z3, z3, z3); + f255_mul(z3, x1, z3); + + /* x_2 = AA * BB */ + f255_mul(x2, aa, bb); + + /* z_2 = E * (AA + a24 * E) */ + f255_mul_a24(z2, e); + f255_add(z2, aa, z2); + f255_mul(z2, e, z2); + } + + f255_cswap(x2, x3, swap); + f255_cswap(z2, z3, swap); + + /* + * Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize + * most non-squarings. We use x1 and x3, now useless, as temporaries. + */ + memcpy(x1, z2, sizeof z2); + for (i = 0; i < 15; i ++) { + f255_mul(x1, x1, x1); + f255_mul(x1, x1, z2); + } + memcpy(x3, x1, sizeof x1); + for (i = 0; i < 14; i ++) { + int j; + + for (j = 0; j < 16; j ++) { + f255_mul(x3, x3, x3); + } + f255_mul(x3, x3, x1); + } + for (i = 14; i >= 0; i --) { + f255_mul(x3, x3, x3); + if ((0xFFEB >> i) & 1) { + f255_mul(x3, z2, x3); + } + } + + /* + * Compute x2/z2. We have 1/z2 in x3. + */ + f255_mul(x2, x2, x3); + f255_final_reduce(x2); + + /* + * Encode the final x2 value in little-endian. + */ + br_enc64le(G, x2[0]); + br_enc64le(G + 8, x2[1]); + br_enc64le(G + 16, x2[2]); + br_enc64le(G + 24, x2[3]); + return 1; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + const unsigned char *G; + size_t Glen; + + G = api_generator(curve, &Glen); + memcpy(R, G, Glen); + api_mul(R, Glen, x, xlen, curve); + return Glen; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + /* + * We don't implement this method, since it is used for ECDSA + * only, and there is no ECDSA over Curve25519 (which instead + * uses EdDSA). + */ + (void)A; + (void)B; + (void)len; + (void)x; + (void)xlen; + (void)y; + (void)ylen; + (void)curve; + return 0; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_c25519_m64 = { + (uint32_t)0x20000000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_c25519_m64_get(void) +{ + return &br_ec_c25519_m64; +} + +#else + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_c25519_m64_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/ec/ec_curve25519.c b/BearSSL-OG/libbearssl/src/ec/ec_curve25519.c new file mode 100644 index 0000000..a47d215 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_curve25519.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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 const unsigned char GEN[] = { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char ORDER[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* see inner.h */ +const br_ec_curve_def br_curve25519 = { + BR_EC_curve25519, + ORDER, sizeof ORDER, + GEN, sizeof GEN +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_default.c b/BearSSL-OG/libbearssl/src/ec/ec_default.c new file mode 100644 index 0000000..7bb6e0c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_default.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_get_default(void) +{ +#if BR_LOMUL + return &br_ec_all_m15; +#else + return &br_ec_all_m31; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ec/ec_keygen.c b/BearSSL-OG/libbearssl/src/ec/ec_keygen.c new file mode 100644 index 0000000..02a3096 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_keygen.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_ec.h */ +size_t +br_ec_keygen(const br_prng_class **rng_ctx, + const br_ec_impl *impl, br_ec_private_key *sk, + void *kbuf, int curve) +{ + const unsigned char *order; + unsigned char *buf; + size_t len; + unsigned mask; + + if (curve < 0 || curve >= 32 + || ((impl->supported_curves >> curve) & 1) == 0) + { + return 0; + } + order = impl->order(curve, &len); + while (len > 0 && *order == 0) { + order ++; + len --; + } + if (kbuf == NULL || len == 0) { + return len; + } + mask = order[0]; + mask |= (mask >> 1); + mask |= (mask >> 2); + mask |= (mask >> 4); + + /* + * We generate sequences of random bits of the right size, until + * the value is strictly lower than the curve order (we also + * check for all-zero values, which are invalid). + */ + buf = kbuf; + for (;;) { + size_t u; + unsigned cc, zz; + + (*rng_ctx)->generate(rng_ctx, buf, len); + buf[0] &= mask; + cc = 0; + u = len; + zz = 0; + while (u -- > 0) { + cc = ((unsigned)(buf[u] - order[u] - cc) >> 8) & 1; + zz |= buf[u]; + } + if (cc != 0 && zz != 0) { + break; + } + } + + if (sk != NULL) { + sk->curve = curve; + sk->x = buf; + sk->xlen = len; + } + return len; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ec_p256_m15.c b/BearSSL-OG/libbearssl/src/ec/ec_p256_m15.c new file mode 100644 index 0000000..1242438 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_p256_m15.c @@ -0,0 +1,2124 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_ + * that right-shifting a signed negative integer copies the sign bit + * (arithmetic right-shift). This is "implementation-defined behaviour", + * i.e. it is not undefined, but it may differ between compilers. Each + * compiler is supposed to document its behaviour in that respect. GCC + * explicitly defines that an arithmetic right shift is used. We expect + * all other compilers to do the same, because underlying CPU offer an + * arithmetic right shift opcode that could not be used otherwise. + */ +#if BR_NO_ARITH_SHIFT +#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ + | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) +#else +#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) +#endif + +/* + * Convert an integer from unsigned big-endian encoding to a sequence of + * 13-bit words in little-endian order. The final "partial" word is + * returned. + */ +static uint32_t +be8_to_le13(uint32_t *dst, const unsigned char *src, size_t len) +{ + uint32_t acc; + int acc_len; + + acc = 0; + acc_len = 0; + while (len -- > 0) { + acc |= (uint32_t)src[len] << acc_len; + acc_len += 8; + if (acc_len >= 13) { + *dst ++ = acc & 0x1FFF; + acc >>= 13; + acc_len -= 13; + } + } + return acc; +} + +/* + * Convert an integer (13-bit words, little-endian) to unsigned + * big-endian encoding. The total encoding length is provided; all + * the destination bytes will be filled. + */ +static void +le13_to_be8(unsigned char *dst, size_t len, const uint32_t *src) +{ + uint32_t acc; + int acc_len; + + acc = 0; + acc_len = 0; + while (len -- > 0) { + if (acc_len < 8) { + acc |= (*src ++) << acc_len; + acc_len += 13; + } + dst[len] = (unsigned char)acc; + acc >>= 8; + acc_len -= 8; + } +} + +/* + * Normalise an array of words to a strict 13 bits per word. Returned + * value is the resulting carry. The source (w) and destination (d) + * arrays may be identical, but shall not overlap partially. + */ +static __inline uint32_t +norm13(uint32_t *d, const uint32_t *w, size_t len) +{ + size_t u; + uint32_t cc; + + cc = 0; + for (u = 0; u < len; u ++) { + int32_t z; + + z = w[u] + cc; + d[u] = z & 0x1FFF; + cc = ARSH(z, 13); + } + return cc; +} + +/* + * mul20() multiplies two 260-bit integers together. Each word must fit + * on 13 bits; source operands use 20 words, destination operand + * receives 40 words. All overlaps allowed. + * + * square20() computes the square of a 260-bit integer. Each word must + * fit on 13 bits; source operand uses 20 words, destination operand + * receives 40 words. All overlaps allowed. + */ + +#if BR_SLOW_MUL15 + +static void +mul20(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + /* + * Two-level Karatsuba: turns a 20x20 multiplication into + * nine 5x5 multiplications. We use 13-bit words but do not + * propagate carries immediately, so words may expand: + * + * - First Karatsuba decomposition turns the 20x20 mul on + * 13-bit words into three 10x10 muls, two on 13-bit words + * and one on 14-bit words. + * + * - Second Karatsuba decomposition further splits these into: + * + * * four 5x5 muls on 13-bit words + * * four 5x5 muls on 14-bit words + * * one 5x5 mul on 15-bit words + * + * Highest word value is 8191, 16382 or 32764, for 13-bit, 14-bit + * or 15-bit words, respectively. + */ + uint32_t u[45], v[45], w[90]; + uint32_t cc; + int i; + +#define ZADD(dw, d_off, s1w, s1_off, s2w, s2_off) do { \ + (dw)[5 * (d_off) + 0] = (s1w)[5 * (s1_off) + 0] \ + + (s2w)[5 * (s2_off) + 0]; \ + (dw)[5 * (d_off) + 1] = (s1w)[5 * (s1_off) + 1] \ + + (s2w)[5 * (s2_off) + 1]; \ + (dw)[5 * (d_off) + 2] = (s1w)[5 * (s1_off) + 2] \ + + (s2w)[5 * (s2_off) + 2]; \ + (dw)[5 * (d_off) + 3] = (s1w)[5 * (s1_off) + 3] \ + + (s2w)[5 * (s2_off) + 3]; \ + (dw)[5 * (d_off) + 4] = (s1w)[5 * (s1_off) + 4] \ + + (s2w)[5 * (s2_off) + 4]; \ + } while (0) + +#define ZADDT(dw, d_off, sw, s_off) do { \ + (dw)[5 * (d_off) + 0] += (sw)[5 * (s_off) + 0]; \ + (dw)[5 * (d_off) + 1] += (sw)[5 * (s_off) + 1]; \ + (dw)[5 * (d_off) + 2] += (sw)[5 * (s_off) + 2]; \ + (dw)[5 * (d_off) + 3] += (sw)[5 * (s_off) + 3]; \ + (dw)[5 * (d_off) + 4] += (sw)[5 * (s_off) + 4]; \ + } while (0) + +#define ZSUB2F(dw, d_off, s1w, s1_off, s2w, s2_off) do { \ + (dw)[5 * (d_off) + 0] -= (s1w)[5 * (s1_off) + 0] \ + + (s2w)[5 * (s2_off) + 0]; \ + (dw)[5 * (d_off) + 1] -= (s1w)[5 * (s1_off) + 1] \ + + (s2w)[5 * (s2_off) + 1]; \ + (dw)[5 * (d_off) + 2] -= (s1w)[5 * (s1_off) + 2] \ + + (s2w)[5 * (s2_off) + 2]; \ + (dw)[5 * (d_off) + 3] -= (s1w)[5 * (s1_off) + 3] \ + + (s2w)[5 * (s2_off) + 3]; \ + (dw)[5 * (d_off) + 4] -= (s1w)[5 * (s1_off) + 4] \ + + (s2w)[5 * (s2_off) + 4]; \ + } while (0) + +#define CPR1(w, cprcc) do { \ + uint32_t cprz = (w) + cprcc; \ + (w) = cprz & 0x1FFF; \ + cprcc = cprz >> 13; \ + } while (0) + +#define CPR(dw, d_off) do { \ + uint32_t cprcc; \ + cprcc = 0; \ + CPR1((dw)[(d_off) + 0], cprcc); \ + CPR1((dw)[(d_off) + 1], cprcc); \ + CPR1((dw)[(d_off) + 2], cprcc); \ + CPR1((dw)[(d_off) + 3], cprcc); \ + CPR1((dw)[(d_off) + 4], cprcc); \ + CPR1((dw)[(d_off) + 5], cprcc); \ + CPR1((dw)[(d_off) + 6], cprcc); \ + CPR1((dw)[(d_off) + 7], cprcc); \ + CPR1((dw)[(d_off) + 8], cprcc); \ + (dw)[(d_off) + 9] = cprcc; \ + } while (0) + + memcpy(u, a, 20 * sizeof *a); + ZADD(u, 4, a, 0, a, 1); + ZADD(u, 5, a, 2, a, 3); + ZADD(u, 6, a, 0, a, 2); + ZADD(u, 7, a, 1, a, 3); + ZADD(u, 8, u, 6, u, 7); + + memcpy(v, b, 20 * sizeof *b); + ZADD(v, 4, b, 0, b, 1); + ZADD(v, 5, b, 2, b, 3); + ZADD(v, 6, b, 0, b, 2); + ZADD(v, 7, b, 1, b, 3); + ZADD(v, 8, v, 6, v, 7); + + /* + * Do the eight first 8x8 muls. Source words are at most 16382 + * each, so we can add product results together "as is" in 32-bit + * words. + */ + for (i = 0; i < 40; i += 5) { + w[(i << 1) + 0] = MUL15(u[i + 0], v[i + 0]); + w[(i << 1) + 1] = MUL15(u[i + 0], v[i + 1]) + + MUL15(u[i + 1], v[i + 0]); + w[(i << 1) + 2] = MUL15(u[i + 0], v[i + 2]) + + MUL15(u[i + 1], v[i + 1]) + + MUL15(u[i + 2], v[i + 0]); + w[(i << 1) + 3] = MUL15(u[i + 0], v[i + 3]) + + MUL15(u[i + 1], v[i + 2]) + + MUL15(u[i + 2], v[i + 1]) + + MUL15(u[i + 3], v[i + 0]); + w[(i << 1) + 4] = MUL15(u[i + 0], v[i + 4]) + + MUL15(u[i + 1], v[i + 3]) + + MUL15(u[i + 2], v[i + 2]) + + MUL15(u[i + 3], v[i + 1]) + + MUL15(u[i + 4], v[i + 0]); + w[(i << 1) + 5] = MUL15(u[i + 1], v[i + 4]) + + MUL15(u[i + 2], v[i + 3]) + + MUL15(u[i + 3], v[i + 2]) + + MUL15(u[i + 4], v[i + 1]); + w[(i << 1) + 6] = MUL15(u[i + 2], v[i + 4]) + + MUL15(u[i + 3], v[i + 3]) + + MUL15(u[i + 4], v[i + 2]); + w[(i << 1) + 7] = MUL15(u[i + 3], v[i + 4]) + + MUL15(u[i + 4], v[i + 3]); + w[(i << 1) + 8] = MUL15(u[i + 4], v[i + 4]); + w[(i << 1) + 9] = 0; + } + + /* + * For the 9th multiplication, source words are up to 32764, + * so we must do some carry propagation. If we add up to + * 4 products and the carry is no more than 524224, then the + * result fits in 32 bits, and the next carry will be no more + * than 524224 (because 4*(32764^2)+524224 < 8192*524225). + * + * We thus just skip one of the products in the middle word, + * then do a carry propagation (this reduces words to 13 bits + * each, except possibly the last, which may use up to 17 bits + * or so), then add the missing product. + */ + w[80 + 0] = MUL15(u[40 + 0], v[40 + 0]); + w[80 + 1] = MUL15(u[40 + 0], v[40 + 1]) + + MUL15(u[40 + 1], v[40 + 0]); + w[80 + 2] = MUL15(u[40 + 0], v[40 + 2]) + + MUL15(u[40 + 1], v[40 + 1]) + + MUL15(u[40 + 2], v[40 + 0]); + w[80 + 3] = MUL15(u[40 + 0], v[40 + 3]) + + MUL15(u[40 + 1], v[40 + 2]) + + MUL15(u[40 + 2], v[40 + 1]) + + MUL15(u[40 + 3], v[40 + 0]); + w[80 + 4] = MUL15(u[40 + 0], v[40 + 4]) + + MUL15(u[40 + 1], v[40 + 3]) + + MUL15(u[40 + 2], v[40 + 2]) + + MUL15(u[40 + 3], v[40 + 1]); + /* + MUL15(u[40 + 4], v[40 + 0]) */ + w[80 + 5] = MUL15(u[40 + 1], v[40 + 4]) + + MUL15(u[40 + 2], v[40 + 3]) + + MUL15(u[40 + 3], v[40 + 2]) + + MUL15(u[40 + 4], v[40 + 1]); + w[80 + 6] = MUL15(u[40 + 2], v[40 + 4]) + + MUL15(u[40 + 3], v[40 + 3]) + + MUL15(u[40 + 4], v[40 + 2]); + w[80 + 7] = MUL15(u[40 + 3], v[40 + 4]) + + MUL15(u[40 + 4], v[40 + 3]); + w[80 + 8] = MUL15(u[40 + 4], v[40 + 4]); + + CPR(w, 80); + + w[80 + 4] += MUL15(u[40 + 4], v[40 + 0]); + + /* + * The products on 14-bit words in slots 6 and 7 yield values + * up to 5*(16382^2) each, and we need to subtract two such + * values from the higher word. We need the subtraction to fit + * in a _signed_ 32-bit integer, i.e. 31 bits + a sign bit. + * However, 10*(16382^2) does not fit. So we must perform a + * bit of reduction here. + */ + CPR(w, 60); + CPR(w, 70); + + /* + * Recompose results. + */ + + /* 0..1*0..1 into 0..3 */ + ZSUB2F(w, 8, w, 0, w, 2); + ZSUB2F(w, 9, w, 1, w, 3); + ZADDT(w, 1, w, 8); + ZADDT(w, 2, w, 9); + + /* 2..3*2..3 into 4..7 */ + ZSUB2F(w, 10, w, 4, w, 6); + ZSUB2F(w, 11, w, 5, w, 7); + ZADDT(w, 5, w, 10); + ZADDT(w, 6, w, 11); + + /* (0..1+2..3)*(0..1+2..3) into 12..15 */ + ZSUB2F(w, 16, w, 12, w, 14); + ZSUB2F(w, 17, w, 13, w, 15); + ZADDT(w, 13, w, 16); + ZADDT(w, 14, w, 17); + + /* first-level recomposition */ + ZSUB2F(w, 12, w, 0, w, 4); + ZSUB2F(w, 13, w, 1, w, 5); + ZSUB2F(w, 14, w, 2, w, 6); + ZSUB2F(w, 15, w, 3, w, 7); + ZADDT(w, 2, w, 12); + ZADDT(w, 3, w, 13); + ZADDT(w, 4, w, 14); + ZADDT(w, 5, w, 15); + + /* + * Perform carry propagation to bring all words down to 13 bits. + */ + cc = norm13(d, w, 40); + d[39] += (cc << 13); + +#undef ZADD +#undef ZADDT +#undef ZSUB2F +#undef CPR1 +#undef CPR +} + +static inline void +square20(uint32_t *d, const uint32_t *a) +{ + mul20(d, a, a); +} + +#else + +static void +mul20(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t t[39]; + + t[ 0] = MUL15(a[ 0], b[ 0]); + t[ 1] = MUL15(a[ 0], b[ 1]) + + MUL15(a[ 1], b[ 0]); + t[ 2] = MUL15(a[ 0], b[ 2]) + + MUL15(a[ 1], b[ 1]) + + MUL15(a[ 2], b[ 0]); + t[ 3] = MUL15(a[ 0], b[ 3]) + + MUL15(a[ 1], b[ 2]) + + MUL15(a[ 2], b[ 1]) + + MUL15(a[ 3], b[ 0]); + t[ 4] = MUL15(a[ 0], b[ 4]) + + MUL15(a[ 1], b[ 3]) + + MUL15(a[ 2], b[ 2]) + + MUL15(a[ 3], b[ 1]) + + MUL15(a[ 4], b[ 0]); + t[ 5] = MUL15(a[ 0], b[ 5]) + + MUL15(a[ 1], b[ 4]) + + MUL15(a[ 2], b[ 3]) + + MUL15(a[ 3], b[ 2]) + + MUL15(a[ 4], b[ 1]) + + MUL15(a[ 5], b[ 0]); + t[ 6] = MUL15(a[ 0], b[ 6]) + + MUL15(a[ 1], b[ 5]) + + MUL15(a[ 2], b[ 4]) + + MUL15(a[ 3], b[ 3]) + + MUL15(a[ 4], b[ 2]) + + MUL15(a[ 5], b[ 1]) + + MUL15(a[ 6], b[ 0]); + t[ 7] = MUL15(a[ 0], b[ 7]) + + MUL15(a[ 1], b[ 6]) + + MUL15(a[ 2], b[ 5]) + + MUL15(a[ 3], b[ 4]) + + MUL15(a[ 4], b[ 3]) + + MUL15(a[ 5], b[ 2]) + + MUL15(a[ 6], b[ 1]) + + MUL15(a[ 7], b[ 0]); + t[ 8] = MUL15(a[ 0], b[ 8]) + + MUL15(a[ 1], b[ 7]) + + MUL15(a[ 2], b[ 6]) + + MUL15(a[ 3], b[ 5]) + + MUL15(a[ 4], b[ 4]) + + MUL15(a[ 5], b[ 3]) + + MUL15(a[ 6], b[ 2]) + + MUL15(a[ 7], b[ 1]) + + MUL15(a[ 8], b[ 0]); + t[ 9] = MUL15(a[ 0], b[ 9]) + + MUL15(a[ 1], b[ 8]) + + MUL15(a[ 2], b[ 7]) + + MUL15(a[ 3], b[ 6]) + + MUL15(a[ 4], b[ 5]) + + MUL15(a[ 5], b[ 4]) + + MUL15(a[ 6], b[ 3]) + + MUL15(a[ 7], b[ 2]) + + MUL15(a[ 8], b[ 1]) + + MUL15(a[ 9], b[ 0]); + t[10] = MUL15(a[ 0], b[10]) + + MUL15(a[ 1], b[ 9]) + + MUL15(a[ 2], b[ 8]) + + MUL15(a[ 3], b[ 7]) + + MUL15(a[ 4], b[ 6]) + + MUL15(a[ 5], b[ 5]) + + MUL15(a[ 6], b[ 4]) + + MUL15(a[ 7], b[ 3]) + + MUL15(a[ 8], b[ 2]) + + MUL15(a[ 9], b[ 1]) + + MUL15(a[10], b[ 0]); + t[11] = MUL15(a[ 0], b[11]) + + MUL15(a[ 1], b[10]) + + MUL15(a[ 2], b[ 9]) + + MUL15(a[ 3], b[ 8]) + + MUL15(a[ 4], b[ 7]) + + MUL15(a[ 5], b[ 6]) + + MUL15(a[ 6], b[ 5]) + + MUL15(a[ 7], b[ 4]) + + MUL15(a[ 8], b[ 3]) + + MUL15(a[ 9], b[ 2]) + + MUL15(a[10], b[ 1]) + + MUL15(a[11], b[ 0]); + t[12] = MUL15(a[ 0], b[12]) + + MUL15(a[ 1], b[11]) + + MUL15(a[ 2], b[10]) + + MUL15(a[ 3], b[ 9]) + + MUL15(a[ 4], b[ 8]) + + MUL15(a[ 5], b[ 7]) + + MUL15(a[ 6], b[ 6]) + + MUL15(a[ 7], b[ 5]) + + MUL15(a[ 8], b[ 4]) + + MUL15(a[ 9], b[ 3]) + + MUL15(a[10], b[ 2]) + + MUL15(a[11], b[ 1]) + + MUL15(a[12], b[ 0]); + t[13] = MUL15(a[ 0], b[13]) + + MUL15(a[ 1], b[12]) + + MUL15(a[ 2], b[11]) + + MUL15(a[ 3], b[10]) + + MUL15(a[ 4], b[ 9]) + + MUL15(a[ 5], b[ 8]) + + MUL15(a[ 6], b[ 7]) + + MUL15(a[ 7], b[ 6]) + + MUL15(a[ 8], b[ 5]) + + MUL15(a[ 9], b[ 4]) + + MUL15(a[10], b[ 3]) + + MUL15(a[11], b[ 2]) + + MUL15(a[12], b[ 1]) + + MUL15(a[13], b[ 0]); + t[14] = MUL15(a[ 0], b[14]) + + MUL15(a[ 1], b[13]) + + MUL15(a[ 2], b[12]) + + MUL15(a[ 3], b[11]) + + MUL15(a[ 4], b[10]) + + MUL15(a[ 5], b[ 9]) + + MUL15(a[ 6], b[ 8]) + + MUL15(a[ 7], b[ 7]) + + MUL15(a[ 8], b[ 6]) + + MUL15(a[ 9], b[ 5]) + + MUL15(a[10], b[ 4]) + + MUL15(a[11], b[ 3]) + + MUL15(a[12], b[ 2]) + + MUL15(a[13], b[ 1]) + + MUL15(a[14], b[ 0]); + t[15] = MUL15(a[ 0], b[15]) + + MUL15(a[ 1], b[14]) + + MUL15(a[ 2], b[13]) + + MUL15(a[ 3], b[12]) + + MUL15(a[ 4], b[11]) + + MUL15(a[ 5], b[10]) + + MUL15(a[ 6], b[ 9]) + + MUL15(a[ 7], b[ 8]) + + MUL15(a[ 8], b[ 7]) + + MUL15(a[ 9], b[ 6]) + + MUL15(a[10], b[ 5]) + + MUL15(a[11], b[ 4]) + + MUL15(a[12], b[ 3]) + + MUL15(a[13], b[ 2]) + + MUL15(a[14], b[ 1]) + + MUL15(a[15], b[ 0]); + t[16] = MUL15(a[ 0], b[16]) + + MUL15(a[ 1], b[15]) + + MUL15(a[ 2], b[14]) + + MUL15(a[ 3], b[13]) + + MUL15(a[ 4], b[12]) + + MUL15(a[ 5], b[11]) + + MUL15(a[ 6], b[10]) + + MUL15(a[ 7], b[ 9]) + + MUL15(a[ 8], b[ 8]) + + MUL15(a[ 9], b[ 7]) + + MUL15(a[10], b[ 6]) + + MUL15(a[11], b[ 5]) + + MUL15(a[12], b[ 4]) + + MUL15(a[13], b[ 3]) + + MUL15(a[14], b[ 2]) + + MUL15(a[15], b[ 1]) + + MUL15(a[16], b[ 0]); + t[17] = MUL15(a[ 0], b[17]) + + MUL15(a[ 1], b[16]) + + MUL15(a[ 2], b[15]) + + MUL15(a[ 3], b[14]) + + MUL15(a[ 4], b[13]) + + MUL15(a[ 5], b[12]) + + MUL15(a[ 6], b[11]) + + MUL15(a[ 7], b[10]) + + MUL15(a[ 8], b[ 9]) + + MUL15(a[ 9], b[ 8]) + + MUL15(a[10], b[ 7]) + + MUL15(a[11], b[ 6]) + + MUL15(a[12], b[ 5]) + + MUL15(a[13], b[ 4]) + + MUL15(a[14], b[ 3]) + + MUL15(a[15], b[ 2]) + + MUL15(a[16], b[ 1]) + + MUL15(a[17], b[ 0]); + t[18] = MUL15(a[ 0], b[18]) + + MUL15(a[ 1], b[17]) + + MUL15(a[ 2], b[16]) + + MUL15(a[ 3], b[15]) + + MUL15(a[ 4], b[14]) + + MUL15(a[ 5], b[13]) + + MUL15(a[ 6], b[12]) + + MUL15(a[ 7], b[11]) + + MUL15(a[ 8], b[10]) + + MUL15(a[ 9], b[ 9]) + + MUL15(a[10], b[ 8]) + + MUL15(a[11], b[ 7]) + + MUL15(a[12], b[ 6]) + + MUL15(a[13], b[ 5]) + + MUL15(a[14], b[ 4]) + + MUL15(a[15], b[ 3]) + + MUL15(a[16], b[ 2]) + + MUL15(a[17], b[ 1]) + + MUL15(a[18], b[ 0]); + t[19] = MUL15(a[ 0], b[19]) + + MUL15(a[ 1], b[18]) + + MUL15(a[ 2], b[17]) + + MUL15(a[ 3], b[16]) + + MUL15(a[ 4], b[15]) + + MUL15(a[ 5], b[14]) + + MUL15(a[ 6], b[13]) + + MUL15(a[ 7], b[12]) + + MUL15(a[ 8], b[11]) + + MUL15(a[ 9], b[10]) + + MUL15(a[10], b[ 9]) + + MUL15(a[11], b[ 8]) + + MUL15(a[12], b[ 7]) + + MUL15(a[13], b[ 6]) + + MUL15(a[14], b[ 5]) + + MUL15(a[15], b[ 4]) + + MUL15(a[16], b[ 3]) + + MUL15(a[17], b[ 2]) + + MUL15(a[18], b[ 1]) + + MUL15(a[19], b[ 0]); + t[20] = MUL15(a[ 1], b[19]) + + MUL15(a[ 2], b[18]) + + MUL15(a[ 3], b[17]) + + MUL15(a[ 4], b[16]) + + MUL15(a[ 5], b[15]) + + MUL15(a[ 6], b[14]) + + MUL15(a[ 7], b[13]) + + MUL15(a[ 8], b[12]) + + MUL15(a[ 9], b[11]) + + MUL15(a[10], b[10]) + + MUL15(a[11], b[ 9]) + + MUL15(a[12], b[ 8]) + + MUL15(a[13], b[ 7]) + + MUL15(a[14], b[ 6]) + + MUL15(a[15], b[ 5]) + + MUL15(a[16], b[ 4]) + + MUL15(a[17], b[ 3]) + + MUL15(a[18], b[ 2]) + + MUL15(a[19], b[ 1]); + t[21] = MUL15(a[ 2], b[19]) + + MUL15(a[ 3], b[18]) + + MUL15(a[ 4], b[17]) + + MUL15(a[ 5], b[16]) + + MUL15(a[ 6], b[15]) + + MUL15(a[ 7], b[14]) + + MUL15(a[ 8], b[13]) + + MUL15(a[ 9], b[12]) + + MUL15(a[10], b[11]) + + MUL15(a[11], b[10]) + + MUL15(a[12], b[ 9]) + + MUL15(a[13], b[ 8]) + + MUL15(a[14], b[ 7]) + + MUL15(a[15], b[ 6]) + + MUL15(a[16], b[ 5]) + + MUL15(a[17], b[ 4]) + + MUL15(a[18], b[ 3]) + + MUL15(a[19], b[ 2]); + t[22] = MUL15(a[ 3], b[19]) + + MUL15(a[ 4], b[18]) + + MUL15(a[ 5], b[17]) + + MUL15(a[ 6], b[16]) + + MUL15(a[ 7], b[15]) + + MUL15(a[ 8], b[14]) + + MUL15(a[ 9], b[13]) + + MUL15(a[10], b[12]) + + MUL15(a[11], b[11]) + + MUL15(a[12], b[10]) + + MUL15(a[13], b[ 9]) + + MUL15(a[14], b[ 8]) + + MUL15(a[15], b[ 7]) + + MUL15(a[16], b[ 6]) + + MUL15(a[17], b[ 5]) + + MUL15(a[18], b[ 4]) + + MUL15(a[19], b[ 3]); + t[23] = MUL15(a[ 4], b[19]) + + MUL15(a[ 5], b[18]) + + MUL15(a[ 6], b[17]) + + MUL15(a[ 7], b[16]) + + MUL15(a[ 8], b[15]) + + MUL15(a[ 9], b[14]) + + MUL15(a[10], b[13]) + + MUL15(a[11], b[12]) + + MUL15(a[12], b[11]) + + MUL15(a[13], b[10]) + + MUL15(a[14], b[ 9]) + + MUL15(a[15], b[ 8]) + + MUL15(a[16], b[ 7]) + + MUL15(a[17], b[ 6]) + + MUL15(a[18], b[ 5]) + + MUL15(a[19], b[ 4]); + t[24] = MUL15(a[ 5], b[19]) + + MUL15(a[ 6], b[18]) + + MUL15(a[ 7], b[17]) + + MUL15(a[ 8], b[16]) + + MUL15(a[ 9], b[15]) + + MUL15(a[10], b[14]) + + MUL15(a[11], b[13]) + + MUL15(a[12], b[12]) + + MUL15(a[13], b[11]) + + MUL15(a[14], b[10]) + + MUL15(a[15], b[ 9]) + + MUL15(a[16], b[ 8]) + + MUL15(a[17], b[ 7]) + + MUL15(a[18], b[ 6]) + + MUL15(a[19], b[ 5]); + t[25] = MUL15(a[ 6], b[19]) + + MUL15(a[ 7], b[18]) + + MUL15(a[ 8], b[17]) + + MUL15(a[ 9], b[16]) + + MUL15(a[10], b[15]) + + MUL15(a[11], b[14]) + + MUL15(a[12], b[13]) + + MUL15(a[13], b[12]) + + MUL15(a[14], b[11]) + + MUL15(a[15], b[10]) + + MUL15(a[16], b[ 9]) + + MUL15(a[17], b[ 8]) + + MUL15(a[18], b[ 7]) + + MUL15(a[19], b[ 6]); + t[26] = MUL15(a[ 7], b[19]) + + MUL15(a[ 8], b[18]) + + MUL15(a[ 9], b[17]) + + MUL15(a[10], b[16]) + + MUL15(a[11], b[15]) + + MUL15(a[12], b[14]) + + MUL15(a[13], b[13]) + + MUL15(a[14], b[12]) + + MUL15(a[15], b[11]) + + MUL15(a[16], b[10]) + + MUL15(a[17], b[ 9]) + + MUL15(a[18], b[ 8]) + + MUL15(a[19], b[ 7]); + t[27] = MUL15(a[ 8], b[19]) + + MUL15(a[ 9], b[18]) + + MUL15(a[10], b[17]) + + MUL15(a[11], b[16]) + + MUL15(a[12], b[15]) + + MUL15(a[13], b[14]) + + MUL15(a[14], b[13]) + + MUL15(a[15], b[12]) + + MUL15(a[16], b[11]) + + MUL15(a[17], b[10]) + + MUL15(a[18], b[ 9]) + + MUL15(a[19], b[ 8]); + t[28] = MUL15(a[ 9], b[19]) + + MUL15(a[10], b[18]) + + MUL15(a[11], b[17]) + + MUL15(a[12], b[16]) + + MUL15(a[13], b[15]) + + MUL15(a[14], b[14]) + + MUL15(a[15], b[13]) + + MUL15(a[16], b[12]) + + MUL15(a[17], b[11]) + + MUL15(a[18], b[10]) + + MUL15(a[19], b[ 9]); + t[29] = MUL15(a[10], b[19]) + + MUL15(a[11], b[18]) + + MUL15(a[12], b[17]) + + MUL15(a[13], b[16]) + + MUL15(a[14], b[15]) + + MUL15(a[15], b[14]) + + MUL15(a[16], b[13]) + + MUL15(a[17], b[12]) + + MUL15(a[18], b[11]) + + MUL15(a[19], b[10]); + t[30] = MUL15(a[11], b[19]) + + MUL15(a[12], b[18]) + + MUL15(a[13], b[17]) + + MUL15(a[14], b[16]) + + MUL15(a[15], b[15]) + + MUL15(a[16], b[14]) + + MUL15(a[17], b[13]) + + MUL15(a[18], b[12]) + + MUL15(a[19], b[11]); + t[31] = MUL15(a[12], b[19]) + + MUL15(a[13], b[18]) + + MUL15(a[14], b[17]) + + MUL15(a[15], b[16]) + + MUL15(a[16], b[15]) + + MUL15(a[17], b[14]) + + MUL15(a[18], b[13]) + + MUL15(a[19], b[12]); + t[32] = MUL15(a[13], b[19]) + + MUL15(a[14], b[18]) + + MUL15(a[15], b[17]) + + MUL15(a[16], b[16]) + + MUL15(a[17], b[15]) + + MUL15(a[18], b[14]) + + MUL15(a[19], b[13]); + t[33] = MUL15(a[14], b[19]) + + MUL15(a[15], b[18]) + + MUL15(a[16], b[17]) + + MUL15(a[17], b[16]) + + MUL15(a[18], b[15]) + + MUL15(a[19], b[14]); + t[34] = MUL15(a[15], b[19]) + + MUL15(a[16], b[18]) + + MUL15(a[17], b[17]) + + MUL15(a[18], b[16]) + + MUL15(a[19], b[15]); + t[35] = MUL15(a[16], b[19]) + + MUL15(a[17], b[18]) + + MUL15(a[18], b[17]) + + MUL15(a[19], b[16]); + t[36] = MUL15(a[17], b[19]) + + MUL15(a[18], b[18]) + + MUL15(a[19], b[17]); + t[37] = MUL15(a[18], b[19]) + + MUL15(a[19], b[18]); + t[38] = MUL15(a[19], b[19]); + d[39] = norm13(d, t, 39); +} + +static void +square20(uint32_t *d, const uint32_t *a) +{ + uint32_t t[39]; + + t[ 0] = MUL15(a[ 0], a[ 0]); + t[ 1] = ((MUL15(a[ 0], a[ 1])) << 1); + t[ 2] = MUL15(a[ 1], a[ 1]) + + ((MUL15(a[ 0], a[ 2])) << 1); + t[ 3] = ((MUL15(a[ 0], a[ 3]) + + MUL15(a[ 1], a[ 2])) << 1); + t[ 4] = MUL15(a[ 2], a[ 2]) + + ((MUL15(a[ 0], a[ 4]) + + MUL15(a[ 1], a[ 3])) << 1); + t[ 5] = ((MUL15(a[ 0], a[ 5]) + + MUL15(a[ 1], a[ 4]) + + MUL15(a[ 2], a[ 3])) << 1); + t[ 6] = MUL15(a[ 3], a[ 3]) + + ((MUL15(a[ 0], a[ 6]) + + MUL15(a[ 1], a[ 5]) + + MUL15(a[ 2], a[ 4])) << 1); + t[ 7] = ((MUL15(a[ 0], a[ 7]) + + MUL15(a[ 1], a[ 6]) + + MUL15(a[ 2], a[ 5]) + + MUL15(a[ 3], a[ 4])) << 1); + t[ 8] = MUL15(a[ 4], a[ 4]) + + ((MUL15(a[ 0], a[ 8]) + + MUL15(a[ 1], a[ 7]) + + MUL15(a[ 2], a[ 6]) + + MUL15(a[ 3], a[ 5])) << 1); + t[ 9] = ((MUL15(a[ 0], a[ 9]) + + MUL15(a[ 1], a[ 8]) + + MUL15(a[ 2], a[ 7]) + + MUL15(a[ 3], a[ 6]) + + MUL15(a[ 4], a[ 5])) << 1); + t[10] = MUL15(a[ 5], a[ 5]) + + ((MUL15(a[ 0], a[10]) + + MUL15(a[ 1], a[ 9]) + + MUL15(a[ 2], a[ 8]) + + MUL15(a[ 3], a[ 7]) + + MUL15(a[ 4], a[ 6])) << 1); + t[11] = ((MUL15(a[ 0], a[11]) + + MUL15(a[ 1], a[10]) + + MUL15(a[ 2], a[ 9]) + + MUL15(a[ 3], a[ 8]) + + MUL15(a[ 4], a[ 7]) + + MUL15(a[ 5], a[ 6])) << 1); + t[12] = MUL15(a[ 6], a[ 6]) + + ((MUL15(a[ 0], a[12]) + + MUL15(a[ 1], a[11]) + + MUL15(a[ 2], a[10]) + + MUL15(a[ 3], a[ 9]) + + MUL15(a[ 4], a[ 8]) + + MUL15(a[ 5], a[ 7])) << 1); + t[13] = ((MUL15(a[ 0], a[13]) + + MUL15(a[ 1], a[12]) + + MUL15(a[ 2], a[11]) + + MUL15(a[ 3], a[10]) + + MUL15(a[ 4], a[ 9]) + + MUL15(a[ 5], a[ 8]) + + MUL15(a[ 6], a[ 7])) << 1); + t[14] = MUL15(a[ 7], a[ 7]) + + ((MUL15(a[ 0], a[14]) + + MUL15(a[ 1], a[13]) + + MUL15(a[ 2], a[12]) + + MUL15(a[ 3], a[11]) + + MUL15(a[ 4], a[10]) + + MUL15(a[ 5], a[ 9]) + + MUL15(a[ 6], a[ 8])) << 1); + t[15] = ((MUL15(a[ 0], a[15]) + + MUL15(a[ 1], a[14]) + + MUL15(a[ 2], a[13]) + + MUL15(a[ 3], a[12]) + + MUL15(a[ 4], a[11]) + + MUL15(a[ 5], a[10]) + + MUL15(a[ 6], a[ 9]) + + MUL15(a[ 7], a[ 8])) << 1); + t[16] = MUL15(a[ 8], a[ 8]) + + ((MUL15(a[ 0], a[16]) + + MUL15(a[ 1], a[15]) + + MUL15(a[ 2], a[14]) + + MUL15(a[ 3], a[13]) + + MUL15(a[ 4], a[12]) + + MUL15(a[ 5], a[11]) + + MUL15(a[ 6], a[10]) + + MUL15(a[ 7], a[ 9])) << 1); + t[17] = ((MUL15(a[ 0], a[17]) + + MUL15(a[ 1], a[16]) + + MUL15(a[ 2], a[15]) + + MUL15(a[ 3], a[14]) + + MUL15(a[ 4], a[13]) + + MUL15(a[ 5], a[12]) + + MUL15(a[ 6], a[11]) + + MUL15(a[ 7], a[10]) + + MUL15(a[ 8], a[ 9])) << 1); + t[18] = MUL15(a[ 9], a[ 9]) + + ((MUL15(a[ 0], a[18]) + + MUL15(a[ 1], a[17]) + + MUL15(a[ 2], a[16]) + + MUL15(a[ 3], a[15]) + + MUL15(a[ 4], a[14]) + + MUL15(a[ 5], a[13]) + + MUL15(a[ 6], a[12]) + + MUL15(a[ 7], a[11]) + + MUL15(a[ 8], a[10])) << 1); + t[19] = ((MUL15(a[ 0], a[19]) + + MUL15(a[ 1], a[18]) + + MUL15(a[ 2], a[17]) + + MUL15(a[ 3], a[16]) + + MUL15(a[ 4], a[15]) + + MUL15(a[ 5], a[14]) + + MUL15(a[ 6], a[13]) + + MUL15(a[ 7], a[12]) + + MUL15(a[ 8], a[11]) + + MUL15(a[ 9], a[10])) << 1); + t[20] = MUL15(a[10], a[10]) + + ((MUL15(a[ 1], a[19]) + + MUL15(a[ 2], a[18]) + + MUL15(a[ 3], a[17]) + + MUL15(a[ 4], a[16]) + + MUL15(a[ 5], a[15]) + + MUL15(a[ 6], a[14]) + + MUL15(a[ 7], a[13]) + + MUL15(a[ 8], a[12]) + + MUL15(a[ 9], a[11])) << 1); + t[21] = ((MUL15(a[ 2], a[19]) + + MUL15(a[ 3], a[18]) + + MUL15(a[ 4], a[17]) + + MUL15(a[ 5], a[16]) + + MUL15(a[ 6], a[15]) + + MUL15(a[ 7], a[14]) + + MUL15(a[ 8], a[13]) + + MUL15(a[ 9], a[12]) + + MUL15(a[10], a[11])) << 1); + t[22] = MUL15(a[11], a[11]) + + ((MUL15(a[ 3], a[19]) + + MUL15(a[ 4], a[18]) + + MUL15(a[ 5], a[17]) + + MUL15(a[ 6], a[16]) + + MUL15(a[ 7], a[15]) + + MUL15(a[ 8], a[14]) + + MUL15(a[ 9], a[13]) + + MUL15(a[10], a[12])) << 1); + t[23] = ((MUL15(a[ 4], a[19]) + + MUL15(a[ 5], a[18]) + + MUL15(a[ 6], a[17]) + + MUL15(a[ 7], a[16]) + + MUL15(a[ 8], a[15]) + + MUL15(a[ 9], a[14]) + + MUL15(a[10], a[13]) + + MUL15(a[11], a[12])) << 1); + t[24] = MUL15(a[12], a[12]) + + ((MUL15(a[ 5], a[19]) + + MUL15(a[ 6], a[18]) + + MUL15(a[ 7], a[17]) + + MUL15(a[ 8], a[16]) + + MUL15(a[ 9], a[15]) + + MUL15(a[10], a[14]) + + MUL15(a[11], a[13])) << 1); + t[25] = ((MUL15(a[ 6], a[19]) + + MUL15(a[ 7], a[18]) + + MUL15(a[ 8], a[17]) + + MUL15(a[ 9], a[16]) + + MUL15(a[10], a[15]) + + MUL15(a[11], a[14]) + + MUL15(a[12], a[13])) << 1); + t[26] = MUL15(a[13], a[13]) + + ((MUL15(a[ 7], a[19]) + + MUL15(a[ 8], a[18]) + + MUL15(a[ 9], a[17]) + + MUL15(a[10], a[16]) + + MUL15(a[11], a[15]) + + MUL15(a[12], a[14])) << 1); + t[27] = ((MUL15(a[ 8], a[19]) + + MUL15(a[ 9], a[18]) + + MUL15(a[10], a[17]) + + MUL15(a[11], a[16]) + + MUL15(a[12], a[15]) + + MUL15(a[13], a[14])) << 1); + t[28] = MUL15(a[14], a[14]) + + ((MUL15(a[ 9], a[19]) + + MUL15(a[10], a[18]) + + MUL15(a[11], a[17]) + + MUL15(a[12], a[16]) + + MUL15(a[13], a[15])) << 1); + t[29] = ((MUL15(a[10], a[19]) + + MUL15(a[11], a[18]) + + MUL15(a[12], a[17]) + + MUL15(a[13], a[16]) + + MUL15(a[14], a[15])) << 1); + t[30] = MUL15(a[15], a[15]) + + ((MUL15(a[11], a[19]) + + MUL15(a[12], a[18]) + + MUL15(a[13], a[17]) + + MUL15(a[14], a[16])) << 1); + t[31] = ((MUL15(a[12], a[19]) + + MUL15(a[13], a[18]) + + MUL15(a[14], a[17]) + + MUL15(a[15], a[16])) << 1); + t[32] = MUL15(a[16], a[16]) + + ((MUL15(a[13], a[19]) + + MUL15(a[14], a[18]) + + MUL15(a[15], a[17])) << 1); + t[33] = ((MUL15(a[14], a[19]) + + MUL15(a[15], a[18]) + + MUL15(a[16], a[17])) << 1); + t[34] = MUL15(a[17], a[17]) + + ((MUL15(a[15], a[19]) + + MUL15(a[16], a[18])) << 1); + t[35] = ((MUL15(a[16], a[19]) + + MUL15(a[17], a[18])) << 1); + t[36] = MUL15(a[18], a[18]) + + ((MUL15(a[17], a[19])) << 1); + t[37] = ((MUL15(a[18], a[19])) << 1); + t[38] = MUL15(a[19], a[19]); + d[39] = norm13(d, t, 39); +} + +#endif + +/* + * Modulus for field F256 (field for point coordinates in curve P-256). + */ +static const uint32_t F256[] = { + 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x001F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0400, 0x0000, + 0x0000, 0x1FF8, 0x1FFF, 0x01FF +}; + +/* + * The 'b' curve equation coefficient for P-256. + */ +static const uint32_t P256_B[] = { + 0x004B, 0x1E93, 0x0F89, 0x1C78, 0x03BC, 0x187B, 0x114E, 0x1619, + 0x1D06, 0x0328, 0x01AF, 0x0D31, 0x1557, 0x15DE, 0x1ECF, 0x127C, + 0x0A3A, 0x0EC5, 0x118D, 0x00B5 +}; + +/* + * Perform a "short reduction" in field F256 (field for curve P-256). + * The source value should be less than 262 bits; on output, it will + * be at most 257 bits, and less than twice the modulus. + */ +static void +reduce_f256(uint32_t *d) +{ + uint32_t x; + + x = d[19] >> 9; + d[19] &= 0x01FF; + d[17] += x << 3; + d[14] -= x << 10; + d[7] -= x << 5; + d[0] += x; + norm13(d, d, 20); +} + +/* + * Perform a "final reduction" in field F256 (field for curve P-256). + * The source value must be less than twice the modulus. If the value + * is not lower than the modulus, then the modulus is subtracted and + * this function returns 1; otherwise, it leaves it untouched and it + * returns 0. + */ +static uint32_t +reduce_final_f256(uint32_t *d) +{ + uint32_t t[20]; + uint32_t cc; + int i; + + memcpy(t, d, sizeof t); + cc = 0; + for (i = 0; i < 20; i ++) { + uint32_t w; + + w = t[i] - F256[i] - cc; + cc = w >> 31; + t[i] = w & 0x1FFF; + } + cc ^= 1; + CCOPY(cc, d, t, sizeof t); + return cc; +} + +/* + * Perform a multiplication of two integers modulo + * 2^256-2^224+2^192+2^96-1 (for NIST curve P-256). Operands are arrays + * of 20 words, each containing 13 bits of data, in little-endian order. + * On input, upper word may be up to 13 bits (hence value up to 2^260-1); + * on output, value fits on 257 bits and is lower than twice the modulus. + */ +static void +mul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t t[40], cc; + int i; + + /* + * Compute raw multiplication. All result words fit in 13 bits + * each. + */ + mul20(t, a, b); + + /* + * Modular reduction: each high word in added/subtracted where + * necessary. + * + * The modulus is: + * p = 2^256 - 2^224 + 2^192 + 2^96 - 1 + * Therefore: + * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p + * + * For a word x at bit offset n (n >= 256), we have: + * x*2^n = x*2^(n-32) - x*2^(n-64) + * - x*2^(n - 160) + x*2^(n-256) mod p + * + * Thus, we can nullify the high word if we reinject it at some + * proper emplacements. + */ + for (i = 39; i >= 20; i --) { + uint32_t x; + + x = t[i]; + t[i - 2] += ARSH(x, 6); + t[i - 3] += (x << 7) & 0x1FFF; + t[i - 4] -= ARSH(x, 12); + t[i - 5] -= (x << 1) & 0x1FFF; + t[i - 12] -= ARSH(x, 4); + t[i - 13] -= (x << 9) & 0x1FFF; + t[i - 19] += ARSH(x, 9); + t[i - 20] += (x << 4) & 0x1FFF; + } + + /* + * Propagate carries. This is a signed propagation, and the + * result may be negative. The loop above may enlarge values, + * but not two much: worst case is the chain involving t[i - 3], + * in which a value may be added to itself up to 7 times. Since + * starting values are 13-bit each, all words fit on 20 bits + * (21 to account for the sign bit). + */ + cc = norm13(t, t, 20); + + /* + * Perform modular reduction again for the bits beyond 256 (the carry + * and the bits 256..259). Since the largest shift below is by 10 + * bits, and the values fit on 21 bits, values fit in 32-bit words, + * thereby allowing injecting full word values. + */ + cc = (cc << 4) | (t[19] >> 9); + t[19] &= 0x01FF; + t[17] += cc << 3; + t[14] -= cc << 10; + t[7] -= cc << 5; + t[0] += cc; + + /* + * If the carry is negative, then after carry propagation, we may + * end up with a value which is negative, and we don't want that. + * Thus, in that case, we add the modulus. Note that the subtraction + * result, when the carry is negative, is always smaller than the + * modulus, so the extra addition will not make the value exceed + * twice the modulus. + */ + cc >>= 31; + t[0] -= cc; + t[7] += cc << 5; + t[14] += cc << 10; + t[17] -= cc << 3; + t[19] += cc << 9; + + norm13(d, t, 20); +} + +/* + * Square an integer modulo 2^256-2^224+2^192+2^96-1 (for NIST curve + * P-256). Operand is an array of 20 words, each containing 13 bits of + * data, in little-endian order. On input, upper word may be up to 13 + * bits (hence value up to 2^260-1); on output, value fits on 257 bits + * and is lower than twice the modulus. + */ +static void +square_f256(uint32_t *d, const uint32_t *a) +{ + uint32_t t[40], cc; + int i; + + /* + * Compute raw square. All result words fit in 13 bits each. + */ + square20(t, a); + + /* + * Modular reduction: each high word in added/subtracted where + * necessary. + * + * The modulus is: + * p = 2^256 - 2^224 + 2^192 + 2^96 - 1 + * Therefore: + * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p + * + * For a word x at bit offset n (n >= 256), we have: + * x*2^n = x*2^(n-32) - x*2^(n-64) + * - x*2^(n - 160) + x*2^(n-256) mod p + * + * Thus, we can nullify the high word if we reinject it at some + * proper emplacements. + */ + for (i = 39; i >= 20; i --) { + uint32_t x; + + x = t[i]; + t[i - 2] += ARSH(x, 6); + t[i - 3] += (x << 7) & 0x1FFF; + t[i - 4] -= ARSH(x, 12); + t[i - 5] -= (x << 1) & 0x1FFF; + t[i - 12] -= ARSH(x, 4); + t[i - 13] -= (x << 9) & 0x1FFF; + t[i - 19] += ARSH(x, 9); + t[i - 20] += (x << 4) & 0x1FFF; + } + + /* + * Propagate carries. This is a signed propagation, and the + * result may be negative. The loop above may enlarge values, + * but not two much: worst case is the chain involving t[i - 3], + * in which a value may be added to itself up to 7 times. Since + * starting values are 13-bit each, all words fit on 20 bits + * (21 to account for the sign bit). + */ + cc = norm13(t, t, 20); + + /* + * Perform modular reduction again for the bits beyond 256 (the carry + * and the bits 256..259). Since the largest shift below is by 10 + * bits, and the values fit on 21 bits, values fit in 32-bit words, + * thereby allowing injecting full word values. + */ + cc = (cc << 4) | (t[19] >> 9); + t[19] &= 0x01FF; + t[17] += cc << 3; + t[14] -= cc << 10; + t[7] -= cc << 5; + t[0] += cc; + + /* + * If the carry is negative, then after carry propagation, we may + * end up with a value which is negative, and we don't want that. + * Thus, in that case, we add the modulus. Note that the subtraction + * result, when the carry is negative, is always smaller than the + * modulus, so the extra addition will not make the value exceed + * twice the modulus. + */ + cc >>= 31; + t[0] -= cc; + t[7] += cc << 5; + t[14] += cc << 10; + t[17] -= cc << 3; + t[19] += cc << 9; + + norm13(d, t, 20); +} + +/* + * Jacobian coordinates for a point in P-256: affine coordinates (X,Y) + * are such that: + * X = x / z^2 + * Y = y / z^3 + * For the point at infinity, z = 0. + * Each point thus admits many possible representations. + * + * Coordinates are represented in arrays of 32-bit integers, each holding + * 13 bits of data. Values may also be slightly greater than the modulus, + * but they will always be lower than twice the modulus. + */ +typedef struct { + uint32_t x[20]; + uint32_t y[20]; + uint32_t z[20]; +} p256_jacobian; + +/* + * Convert a point to affine coordinates: + * - If the point is the point at infinity, then all three coordinates + * are set to 0. + * - Otherwise, the 'z' coordinate is set to 1, and the 'x' and 'y' + * coordinates are the 'X' and 'Y' affine coordinates. + * The coordinates are guaranteed to be lower than the modulus. + */ +static void +p256_to_affine(p256_jacobian *P) +{ + uint32_t t1[20], t2[20]; + int i; + + /* + * Invert z with a modular exponentiation: the modulus is + * p = 2^256 - 2^224 + 2^192 + 2^96 - 1, and the exponent is + * p-2. Exponent bit pattern (from high to low) is: + * - 32 bits of value 1 + * - 31 bits of value 0 + * - 1 bit of value 1 + * - 96 bits of value 0 + * - 94 bits of value 1 + * - 1 bit of value 0 + * - 1 bit of value 1 + * Thus, we precompute z^(2^31-1) to speed things up. + * + * If z = 0 (point at infinity) then the modular exponentiation + * will yield 0, which leads to the expected result (all three + * coordinates set to 0). + */ + + /* + * A simple square-and-multiply for z^(2^31-1). We could save about + * two dozen multiplications here with an addition chain, but + * this would require a bit more code, and extra stack buffers. + */ + memcpy(t1, P->z, sizeof P->z); + for (i = 0; i < 30; i ++) { + square_f256(t1, t1); + mul_f256(t1, t1, P->z); + } + + /* + * Square-and-multiply. Apart from the squarings, we have a few + * multiplications to set bits to 1; we multiply by the original z + * for setting 1 bit, and by t1 for setting 31 bits. + */ + memcpy(t2, P->z, sizeof P->z); + for (i = 1; i < 256; i ++) { + square_f256(t2, t2); + switch (i) { + case 31: + case 190: + case 221: + case 252: + mul_f256(t2, t2, t1); + break; + case 63: + case 253: + case 255: + mul_f256(t2, t2, P->z); + break; + } + } + + /* + * Now that we have 1/z, multiply x by 1/z^2 and y by 1/z^3. + */ + mul_f256(t1, t2, t2); + mul_f256(P->x, t1, P->x); + mul_f256(t1, t1, t2); + mul_f256(P->y, t1, P->y); + reduce_final_f256(P->x); + reduce_final_f256(P->y); + + /* + * Multiply z by 1/z. If z = 0, then this will yield 0, otherwise + * this will set z to 1. + */ + mul_f256(P->z, P->z, t2); + reduce_final_f256(P->z); +} + +/* + * Double a point in P-256. This function works for all valid points, + * including the point at infinity. + */ +static void +p256_double(p256_jacobian *Q) +{ + /* + * Doubling formulas are: + * + * s = 4*x*y^2 + * m = 3*(x + z^2)*(x - z^2) + * x' = m^2 - 2*s + * y' = m*(s - x') - 8*y^4 + * z' = 2*y*z + * + * These formulas work for all points, including points of order 2 + * and points at infinity: + * - If y = 0 then z' = 0. But there is no such point in P-256 + * anyway. + * - If z = 0 then z' = 0. + */ + uint32_t t1[20], t2[20], t3[20], t4[20]; + int i; + + /* + * Compute z^2 in t1. + */ + square_f256(t1, Q->z); + + /* + * Compute x-z^2 in t2 and x+z^2 in t1. + */ + for (i = 0; i < 20; i ++) { + t2[i] = (F256[i] << 1) + Q->x[i] - t1[i]; + t1[i] += Q->x[i]; + } + norm13(t1, t1, 20); + norm13(t2, t2, 20); + + /* + * Compute 3*(x+z^2)*(x-z^2) in t1. + */ + mul_f256(t3, t1, t2); + for (i = 0; i < 20; i ++) { + t1[i] = MUL15(3, t3[i]); + } + norm13(t1, t1, 20); + + /* + * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3). + */ + square_f256(t3, Q->y); + for (i = 0; i < 20; i ++) { + t3[i] <<= 1; + } + norm13(t3, t3, 20); + mul_f256(t2, Q->x, t3); + for (i = 0; i < 20; i ++) { + t2[i] <<= 1; + } + norm13(t2, t2, 20); + reduce_f256(t2); + + /* + * Compute x' = m^2 - 2*s. + */ + square_f256(Q->x, t1); + for (i = 0; i < 20; i ++) { + Q->x[i] += (F256[i] << 2) - (t2[i] << 1); + } + norm13(Q->x, Q->x, 20); + reduce_f256(Q->x); + + /* + * Compute z' = 2*y*z. + */ + mul_f256(t4, Q->y, Q->z); + for (i = 0; i < 20; i ++) { + Q->z[i] = t4[i] << 1; + } + norm13(Q->z, Q->z, 20); + reduce_f256(Q->z); + + /* + * Compute y' = m*(s - x') - 8*y^4. Note that we already have + * 2*y^2 in t3. + */ + for (i = 0; i < 20; i ++) { + t2[i] += (F256[i] << 1) - Q->x[i]; + } + norm13(t2, t2, 20); + mul_f256(Q->y, t1, t2); + square_f256(t4, t3); + for (i = 0; i < 20; i ++) { + Q->y[i] += (F256[i] << 2) - (t4[i] << 1); + } + norm13(Q->y, Q->y, 20); + reduce_f256(Q->y); +} + +/* + * Add point P2 to point P1. + * + * This function computes the wrong result in the following cases: + * + * - If P1 == 0 but P2 != 0 + * - If P1 != 0 but P2 == 0 + * - If P1 == P2 + * + * In all three cases, P1 is set to the point at infinity. + * + * Returned value is 0 if one of the following occurs: + * + * - P1 and P2 have the same Y coordinate + * - P1 == 0 and P2 == 0 + * - The Y coordinate of one of the points is 0 and the other point is + * the point at infinity. + * + * The third case cannot actually happen with valid points, since a point + * with Y == 0 is a point of order 2, and there is no point of order 2 on + * curve P-256. + * + * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller + * can apply the following: + * + * - If the result is not the point at infinity, then it is correct. + * - Otherwise, if the returned value is 1, then this is a case of + * P1+P2 == 0, so the result is indeed the point at infinity. + * - Otherwise, P1 == P2, so a "double" operation should have been + * performed. + */ +static uint32_t +p256_add(p256_jacobian *P1, const p256_jacobian *P2) +{ + /* + * Addtions formulas are: + * + * u1 = x1 * z2^2 + * u2 = x2 * z1^2 + * s1 = y1 * z2^3 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 * z2 + */ + uint32_t t1[20], t2[20], t3[20], t4[20], t5[20], t6[20], t7[20]; + uint32_t ret; + int i; + + /* + * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). + */ + square_f256(t3, P2->z); + mul_f256(t1, P1->x, t3); + mul_f256(t4, P2->z, t3); + mul_f256(t3, P1->y, t4); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + square_f256(t4, P1->z); + mul_f256(t2, P2->x, t4); + mul_f256(t5, P1->z, t4); + mul_f256(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * We need to test whether r is zero, so we will do some extra + * reduce. + */ + for (i = 0; i < 20; i ++) { + t2[i] += (F256[i] << 1) - t1[i]; + t4[i] += (F256[i] << 1) - t3[i]; + } + norm13(t2, t2, 20); + norm13(t4, t4, 20); + reduce_f256(t4); + reduce_final_f256(t4); + ret = 0; + for (i = 0; i < 20; i ++) { + ret |= t4[i]; + } + ret = (ret | -ret) >> 31; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + square_f256(t7, t2); + mul_f256(t6, t1, t7); + mul_f256(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + square_f256(P1->x, t4); + for (i = 0; i < 20; i ++) { + P1->x[i] += (F256[i] << 3) - t5[i] - (t6[i] << 1); + } + norm13(P1->x, P1->x, 20); + reduce_f256(P1->x); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + for (i = 0; i < 20; i ++) { + t6[i] += (F256[i] << 1) - P1->x[i]; + } + norm13(t6, t6, 20); + mul_f256(P1->y, t4, t6); + mul_f256(t1, t5, t3); + for (i = 0; i < 20; i ++) { + P1->y[i] += (F256[i] << 1) - t1[i]; + } + norm13(P1->y, P1->y, 20); + reduce_f256(P1->y); + + /* + * Compute z3 = h*z1*z2. + */ + mul_f256(t1, P1->z, P2->z); + mul_f256(P1->z, t1, t2); + + return ret; +} + +/* + * Add point P2 to point P1. This is a specialised function for the + * case when P2 is a non-zero point in affine coordinate. + * + * This function computes the wrong result in the following cases: + * + * - If P1 == 0 + * - If P1 == P2 + * + * In both cases, P1 is set to the point at infinity. + * + * Returned value is 0 if one of the following occurs: + * + * - P1 and P2 have the same Y coordinate + * - The Y coordinate of P2 is 0 and P1 is the point at infinity. + * + * The second case cannot actually happen with valid points, since a point + * with Y == 0 is a point of order 2, and there is no point of order 2 on + * curve P-256. + * + * Therefore, assuming that P1 != 0 on input, then the caller + * can apply the following: + * + * - If the result is not the point at infinity, then it is correct. + * - Otherwise, if the returned value is 1, then this is a case of + * P1+P2 == 0, so the result is indeed the point at infinity. + * - Otherwise, P1 == P2, so a "double" operation should have been + * performed. + */ +static uint32_t +p256_add_mixed(p256_jacobian *P1, const p256_jacobian *P2) +{ + /* + * Addtions formulas are: + * + * u1 = x1 + * u2 = x2 * z1^2 + * s1 = y1 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 + */ + uint32_t t1[20], t2[20], t3[20], t4[20], t5[20], t6[20], t7[20]; + uint32_t ret; + int i; + + /* + * Compute u1 = x1 (in t1) and s1 = y1 (in t3). + */ + memcpy(t1, P1->x, sizeof t1); + memcpy(t3, P1->y, sizeof t3); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + square_f256(t4, P1->z); + mul_f256(t2, P2->x, t4); + mul_f256(t5, P1->z, t4); + mul_f256(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * We need to test whether r is zero, so we will do some extra + * reduce. + */ + for (i = 0; i < 20; i ++) { + t2[i] += (F256[i] << 1) - t1[i]; + t4[i] += (F256[i] << 1) - t3[i]; + } + norm13(t2, t2, 20); + norm13(t4, t4, 20); + reduce_f256(t4); + reduce_final_f256(t4); + ret = 0; + for (i = 0; i < 20; i ++) { + ret |= t4[i]; + } + ret = (ret | -ret) >> 31; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + square_f256(t7, t2); + mul_f256(t6, t1, t7); + mul_f256(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + square_f256(P1->x, t4); + for (i = 0; i < 20; i ++) { + P1->x[i] += (F256[i] << 3) - t5[i] - (t6[i] << 1); + } + norm13(P1->x, P1->x, 20); + reduce_f256(P1->x); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + for (i = 0; i < 20; i ++) { + t6[i] += (F256[i] << 1) - P1->x[i]; + } + norm13(t6, t6, 20); + mul_f256(P1->y, t4, t6); + mul_f256(t1, t5, t3); + for (i = 0; i < 20; i ++) { + P1->y[i] += (F256[i] << 1) - t1[i]; + } + norm13(P1->y, P1->y, 20); + reduce_f256(P1->y); + + /* + * Compute z3 = h*z1*z2. + */ + mul_f256(P1->z, P1->z, t2); + + return ret; +} + +/* + * Decode a P-256 point. This function does not support the point at + * infinity. Returned value is 0 if the point is invalid, 1 otherwise. + */ +static uint32_t +p256_decode(p256_jacobian *P, const void *src, size_t len) +{ + const unsigned char *buf; + uint32_t tx[20], ty[20], t1[20], t2[20]; + uint32_t bad; + int i; + + if (len != 65) { + return 0; + } + buf = src; + + /* + * First byte must be 0x04 (uncompressed format). We could support + * "hybrid format" (first byte is 0x06 or 0x07, and encodes the + * least significant bit of the Y coordinate), but it is explicitly + * forbidden by RFC 5480 (section 2.2). + */ + bad = NEQ(buf[0], 0x04); + + /* + * Decode the coordinates, and check that they are both lower + * than the modulus. + */ + tx[19] = be8_to_le13(tx, buf + 1, 32); + ty[19] = be8_to_le13(ty, buf + 33, 32); + bad |= reduce_final_f256(tx); + bad |= reduce_final_f256(ty); + + /* + * Check curve equation. + */ + square_f256(t1, tx); + mul_f256(t1, tx, t1); + square_f256(t2, ty); + for (i = 0; i < 20; i ++) { + t1[i] += (F256[i] << 3) - MUL15(3, tx[i]) + P256_B[i] - t2[i]; + } + norm13(t1, t1, 20); + reduce_f256(t1); + reduce_final_f256(t1); + for (i = 0; i < 20; i ++) { + bad |= t1[i]; + } + + /* + * Copy coordinates to the point structure. + */ + memcpy(P->x, tx, sizeof tx); + memcpy(P->y, ty, sizeof ty); + memset(P->z, 0, sizeof P->z); + P->z[0] = 1; + return EQ(bad, 0); +} + +/* + * Encode a point into a buffer. This function assumes that the point is + * valid, in affine coordinates, and not the point at infinity. + */ +static void +p256_encode(void *dst, const p256_jacobian *P) +{ + unsigned char *buf; + + buf = dst; + buf[0] = 0x04; + le13_to_be8(buf + 1, 32, P->x); + le13_to_be8(buf + 33, 32, P->y); +} + +/* + * Multiply a curve point by an integer. The integer is assumed to be + * lower than the curve order, and the base point must not be the point + * at infinity. + */ +static void +p256_mul(p256_jacobian *P, const unsigned char *x, size_t xlen) +{ + /* + * qz is a flag that is initially 1, and remains equal to 1 + * as long as the point is the point at infinity. + * + * We use a 2-bit window to handle multiplier bits by pairs. + * The precomputed window really is the points P2 and P3. + */ + uint32_t qz; + p256_jacobian P2, P3, Q, T, U; + + /* + * Compute window values. + */ + P2 = *P; + p256_double(&P2); + P3 = *P; + p256_add(&P3, &P2); + + /* + * We start with Q = 0. We process multiplier bits 2 by 2. + */ + memset(&Q, 0, sizeof Q); + qz = 1; + while (xlen -- > 0) { + int k; + + for (k = 6; k >= 0; k -= 2) { + uint32_t bits; + uint32_t bnz; + + p256_double(&Q); + p256_double(&Q); + T = *P; + U = Q; + bits = (*x >> k) & (uint32_t)3; + bnz = NEQ(bits, 0); + CCOPY(EQ(bits, 2), &T, &P2, sizeof T); + CCOPY(EQ(bits, 3), &T, &P3, sizeof T); + p256_add(&U, &T); + CCOPY(bnz & qz, &Q, &T, sizeof Q); + CCOPY(bnz & ~qz, &Q, &U, sizeof Q); + qz &= ~bnz; + } + x ++; + } + *P = Q; +} + +/* + * Precomputed window: k*G points, where G is the curve generator, and k + * is an integer from 1 to 15 (inclusive). The X and Y coordinates of + * the point are encoded as 20 words of 13 bits each (little-endian + * order); 13-bit words are then grouped 2-by-2 into 32-bit words + * (little-endian order within each word). + */ +static const uint32_t Gwin[15][20] = { + + { 0x04C60296, 0x02721176, 0x19D00F4A, 0x102517AC, + 0x13B8037D, 0x0748103C, 0x1E730E56, 0x08481FE2, + 0x0F97012C, 0x00D605F4, 0x1DFA11F5, 0x0C801A0D, + 0x0F670CBB, 0x0AED0CC5, 0x115E0E33, 0x181F0785, + 0x13F514A7, 0x0FF30E3B, 0x17171E1A, 0x009F18D0 }, + + { 0x1B341978, 0x16911F11, 0x0D9A1A60, 0x1C4E1FC8, + 0x1E040969, 0x096A06B0, 0x091C0030, 0x09EF1A29, + 0x18C40D03, 0x00F91C9E, 0x13C313D1, 0x096F0748, + 0x011419E0, 0x1CC713A6, 0x1DD31DAD, 0x1EE80C36, + 0x1ECD0C69, 0x1A0800A4, 0x08861B8E, 0x000E1DD5 }, + + { 0x173F1D6C, 0x02CC06F1, 0x14C21FB4, 0x043D1EB6, + 0x0F3606B7, 0x1A971C59, 0x1BF71951, 0x01481323, + 0x068D0633, 0x00BD12F9, 0x13EA1032, 0x136209E8, + 0x1C1E19A7, 0x06C7013E, 0x06C10AB0, 0x14C908BB, + 0x05830CE1, 0x1FEF18DD, 0x00620998, 0x010E0D19 }, + + { 0x18180852, 0x0604111A, 0x0B771509, 0x1B6F0156, + 0x00181FE2, 0x1DCC0AF4, 0x16EF0659, 0x11F70E80, + 0x11A912D0, 0x01C414D2, 0x027618C6, 0x05840FC6, + 0x100215C4, 0x187E0C3B, 0x12771C96, 0x150C0B5D, + 0x0FF705FD, 0x07981C67, 0x1AD20C63, 0x01C11C55 }, + + { 0x1E8113ED, 0x0A940370, 0x12920215, 0x1FA31D6F, + 0x1F7C0C82, 0x10CD03F7, 0x02640560, 0x081A0B5E, + 0x1BD21151, 0x00A21642, 0x0D0B0DA4, 0x0176113F, + 0x04440D1D, 0x001A1360, 0x1068012F, 0x1F141E49, + 0x10DF136B, 0x0E4F162B, 0x0D44104A, 0x01C1105F }, + + { 0x011411A9, 0x01551A4F, 0x0ADA0C6B, 0x01BD0EC8, + 0x18120C74, 0x112F1778, 0x099202CB, 0x0C05124B, + 0x195316A4, 0x01600685, 0x1E3B1FE2, 0x189014E3, + 0x0B5E1FD7, 0x0E0311F8, 0x08E000F7, 0x174E00DE, + 0x160702DF, 0x1B5A15BF, 0x03A11237, 0x01D01704 }, + + { 0x0C3D12A3, 0x0C501C0C, 0x17AD1300, 0x1715003F, + 0x03F719F8, 0x18031ED8, 0x1D980667, 0x0F681896, + 0x1B7D00BF, 0x011C14CE, 0x0FA000B4, 0x1C3501B0, + 0x0D901C55, 0x06790C10, 0x029E0736, 0x0DEB0400, + 0x034F183A, 0x030619B4, 0x0DEF0033, 0x00E71AC7 }, + + { 0x1B7D1393, 0x1B3B1076, 0x0BED1B4D, 0x13011F3A, + 0x0E0E1238, 0x156A132B, 0x013A02D3, 0x160A0D01, + 0x1CED1EE9, 0x00C5165D, 0x184C157E, 0x08141A83, + 0x153C0DA5, 0x1ED70F9D, 0x05170D51, 0x02CF13B8, + 0x18AE1771, 0x1B04113F, 0x05EC11E9, 0x015A16B3 }, + + { 0x04A41EE0, 0x1D1412E4, 0x1C591D79, 0x118511B7, + 0x14F00ACB, 0x1AE31E1C, 0x049C0D51, 0x016E061E, + 0x1DB71EDF, 0x01D41A35, 0x0E8208FA, 0x14441293, + 0x011F1E85, 0x1D54137A, 0x026B114F, 0x151D0832, + 0x00A50964, 0x1F9C1E1C, 0x064B12C9, 0x005409D1 }, + + { 0x062B123F, 0x0C0D0501, 0x183704C3, 0x08E31120, + 0x0A2E0A6C, 0x14440FED, 0x090A0D1E, 0x13271964, + 0x0B590A3A, 0x019D1D9B, 0x05780773, 0x09770A91, + 0x0F770CA3, 0x053F19D4, 0x02C80DED, 0x1A761304, + 0x091E0DD9, 0x15D201B8, 0x151109AA, 0x010F0198 }, + + { 0x05E101D1, 0x072314DD, 0x045F1433, 0x1A041541, + 0x10B3142E, 0x01840736, 0x1C1B19DB, 0x098B0418, + 0x1DBC083B, 0x007D1444, 0x01511740, 0x11DD1F3A, + 0x04ED0E2F, 0x1B4B1A62, 0x10480D04, 0x09E911A2, + 0x04211AFA, 0x19140893, 0x04D60CC4, 0x01210648 }, + + { 0x112703C4, 0x018B1BA1, 0x164C1D50, 0x05160BE0, + 0x0BCC1830, 0x01CB1554, 0x13291732, 0x1B2B1918, + 0x0DED0817, 0x00E80775, 0x0A2401D3, 0x0BFE08B3, + 0x0E531199, 0x058616E9, 0x04770B91, 0x110F0C55, + 0x19C11554, 0x0BFB1159, 0x03541C38, 0x000E1C2D }, + + { 0x10390C01, 0x02BB0751, 0x0AC5098E, 0x096C17AB, + 0x03C90E28, 0x10BD18BF, 0x002E1F2D, 0x092B0986, + 0x1BD700AC, 0x002E1F20, 0x1E3D1FD8, 0x077718BB, + 0x06F919C4, 0x187407ED, 0x11370E14, 0x081E139C, + 0x00481ADB, 0x14AB0289, 0x066A0EBE, 0x00C70ED6 }, + + { 0x0694120B, 0x124E1CC9, 0x0E2F0570, 0x17CF081A, + 0x078906AC, 0x066D17CF, 0x1B3207F4, 0x0C5705E9, + 0x10001C38, 0x00A919DE, 0x06851375, 0x0F900BD8, + 0x080401BA, 0x0EEE0D42, 0x1B8B11EA, 0x0B4519F0, + 0x090F18C0, 0x062E1508, 0x0DD909F4, 0x01EB067C }, + + { 0x0CDC1D5F, 0x0D1818F9, 0x07781636, 0x125B18E8, + 0x0D7003AF, 0x13110099, 0x1D9B1899, 0x175C1EB7, + 0x0E34171A, 0x01E01153, 0x081A0F36, 0x0B391783, + 0x1D1F147E, 0x19CE16D7, 0x11511B21, 0x1F2C10F9, + 0x12CA0E51, 0x05A31D39, 0x171A192E, 0x016B0E4F } +}; + +/* + * Lookup one of the Gwin[] values, by index. This is constant-time. + */ +static void +lookup_Gwin(p256_jacobian *T, uint32_t idx) +{ + uint32_t xy[20]; + uint32_t k; + size_t u; + + memset(xy, 0, sizeof xy); + for (k = 0; k < 15; k ++) { + uint32_t m; + + m = -EQ(idx, k + 1); + for (u = 0; u < 20; u ++) { + xy[u] |= m & Gwin[k][u]; + } + } + for (u = 0; u < 10; u ++) { + T->x[(u << 1) + 0] = xy[u] & 0xFFFF; + T->x[(u << 1) + 1] = xy[u] >> 16; + T->y[(u << 1) + 0] = xy[u + 10] & 0xFFFF; + T->y[(u << 1) + 1] = xy[u + 10] >> 16; + } + memset(T->z, 0, sizeof T->z); + T->z[0] = 1; +} + +/* + * Multiply the generator by an integer. The integer is assumed non-zero + * and lower than the curve order. + */ +static void +p256_mulgen(p256_jacobian *P, const unsigned char *x, size_t xlen) +{ + /* + * qz is a flag that is initially 1, and remains equal to 1 + * as long as the point is the point at infinity. + * + * We use a 4-bit window to handle multiplier bits by groups + * of 4. The precomputed window is constant static data, with + * points in affine coordinates; we use a constant-time lookup. + */ + p256_jacobian Q; + uint32_t qz; + + memset(&Q, 0, sizeof Q); + qz = 1; + while (xlen -- > 0) { + int k; + unsigned bx; + + bx = *x ++; + for (k = 0; k < 2; k ++) { + uint32_t bits; + uint32_t bnz; + p256_jacobian T, U; + + p256_double(&Q); + p256_double(&Q); + p256_double(&Q); + p256_double(&Q); + bits = (bx >> 4) & 0x0F; + bnz = NEQ(bits, 0); + lookup_Gwin(&T, bits); + U = Q; + p256_add_mixed(&U, &T); + CCOPY(bnz & qz, &Q, &T, sizeof Q); + CCOPY(bnz & ~qz, &Q, &U, sizeof Q); + qz &= ~bnz; + bx <<= 4; + } + } + *P = Q; +} + +static const unsigned char P256_G[] = { + 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, + 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, + 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, + 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, + 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, + 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, + 0x68, 0x37, 0xBF, 0x51, 0xF5 +}; + +static const unsigned char P256_N[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, + 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, + 0x25, 0x51 +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = sizeof P256_G; + return P256_G; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = sizeof P256_N; + return P256_N; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 1; +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *x, size_t xlen, int curve) +{ + uint32_t r; + p256_jacobian P; + + (void)curve; + if (Glen != 65) { + return 0; + } + r = p256_decode(&P, G, Glen); + p256_mul(&P, x, xlen); + p256_to_affine(&P); + p256_encode(G, &P); + return r; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + p256_jacobian P; + + (void)curve; + p256_mulgen(&P, x, xlen); + p256_to_affine(&P); + p256_encode(R, &P); + return 65; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + p256_jacobian P, Q; + uint32_t r, t, z; + int i; + + (void)curve; + if (len != 65) { + return 0; + } + r = p256_decode(&P, A, len); + p256_mul(&P, x, xlen); + if (B == NULL) { + p256_mulgen(&Q, y, ylen); + } else { + r &= p256_decode(&Q, B, len); + p256_mul(&Q, y, ylen); + } + + /* + * The final addition may fail in case both points are equal. + */ + t = p256_add(&P, &Q); + reduce_final_f256(P.z); + z = 0; + for (i = 0; i < 20; i ++) { + z |= P.z[i]; + } + z = EQ(z, 0); + p256_double(&Q); + + /* + * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we + * have the following: + * + * z = 0, t = 0 return P (normal addition) + * z = 0, t = 1 return P (normal addition) + * z = 1, t = 0 return Q (a 'double' case) + * z = 1, t = 1 report an error (P+Q = 0) + */ + CCOPY(z & ~t, &P, &Q, sizeof Q); + p256_to_affine(&P); + p256_encode(A, &P); + r &= ~(z & t); + return r; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_p256_m15 = { + (uint32_t)0x00800000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_p256_m31.c b/BearSSL-OG/libbearssl/src/ec/ec_p256_m31.c new file mode 100644 index 0000000..b185937 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_p256_m31.c @@ -0,0 +1,1469 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_ + * that right-shifting a signed negative integer copies the sign bit + * (arithmetic right-shift). This is "implementation-defined behaviour", + * i.e. it is not undefined, but it may differ between compilers. Each + * compiler is supposed to document its behaviour in that respect. GCC + * explicitly defines that an arithmetic right shift is used. We expect + * all other compilers to do the same, because underlying CPU offer an + * arithmetic right shift opcode that could not be used otherwise. + */ +#if BR_NO_ARITH_SHIFT +#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ + | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) +#define ARSHW(x, n) (((uint64_t)(x) >> (n)) \ + | ((-((uint64_t)(x) >> 63)) << (64 - (n)))) +#else +#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) +#define ARSHW(x, n) ((*(int64_t *)&(x)) >> (n)) +#endif + +/* + * Convert an integer from unsigned big-endian encoding to a sequence of + * 30-bit words in little-endian order. The final "partial" word is + * returned. + */ +static uint32_t +be8_to_le30(uint32_t *dst, const unsigned char *src, size_t len) +{ + uint32_t acc; + int acc_len; + + acc = 0; + acc_len = 0; + while (len -- > 0) { + uint32_t b; + + b = src[len]; + if (acc_len < 22) { + acc |= b << acc_len; + acc_len += 8; + } else { + *dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF; + acc = b >> (30 - acc_len); + acc_len -= 22; + } + } + return acc; +} + +/* + * Convert an integer (30-bit words, little-endian) to unsigned + * big-endian encoding. The total encoding length is provided; all + * the destination bytes will be filled. + */ +static void +le30_to_be8(unsigned char *dst, size_t len, const uint32_t *src) +{ + uint32_t acc; + int acc_len; + + acc = 0; + acc_len = 0; + while (len -- > 0) { + if (acc_len < 8) { + uint32_t w; + + w = *src ++; + dst[len] = (unsigned char)(acc | (w << acc_len)); + acc = w >> (8 - acc_len); + acc_len += 22; + } else { + dst[len] = (unsigned char)acc; + acc >>= 8; + acc_len -= 8; + } + } +} + +/* + * Multiply two integers. Source integers are represented as arrays of + * nine 30-bit words, for values up to 2^270-1. Result is encoded over + * 18 words of 30 bits each. + */ +static void +mul9(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + /* + * Maximum intermediate result is no more than + * 10376293531797946367, which fits in 64 bits. Reason: + * + * 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406 + * 10376293531797946367 < 9663676407 * 2^30 + * + * Thus, adding together 9 products of 30-bit integers, with + * a carry of at most 9663676406, yields an integer that fits + * on 64 bits and generates a carry of at most 9663676406. + */ + uint64_t t[17]; + uint64_t cc; + int i; + + t[ 0] = MUL31(a[0], b[0]); + t[ 1] = MUL31(a[0], b[1]) + + MUL31(a[1], b[0]); + t[ 2] = MUL31(a[0], b[2]) + + MUL31(a[1], b[1]) + + MUL31(a[2], b[0]); + t[ 3] = MUL31(a[0], b[3]) + + MUL31(a[1], b[2]) + + MUL31(a[2], b[1]) + + MUL31(a[3], b[0]); + t[ 4] = MUL31(a[0], b[4]) + + MUL31(a[1], b[3]) + + MUL31(a[2], b[2]) + + MUL31(a[3], b[1]) + + MUL31(a[4], b[0]); + t[ 5] = MUL31(a[0], b[5]) + + MUL31(a[1], b[4]) + + MUL31(a[2], b[3]) + + MUL31(a[3], b[2]) + + MUL31(a[4], b[1]) + + MUL31(a[5], b[0]); + t[ 6] = MUL31(a[0], b[6]) + + MUL31(a[1], b[5]) + + MUL31(a[2], b[4]) + + MUL31(a[3], b[3]) + + MUL31(a[4], b[2]) + + MUL31(a[5], b[1]) + + MUL31(a[6], b[0]); + t[ 7] = MUL31(a[0], b[7]) + + MUL31(a[1], b[6]) + + MUL31(a[2], b[5]) + + MUL31(a[3], b[4]) + + MUL31(a[4], b[3]) + + MUL31(a[5], b[2]) + + MUL31(a[6], b[1]) + + MUL31(a[7], b[0]); + t[ 8] = MUL31(a[0], b[8]) + + MUL31(a[1], b[7]) + + MUL31(a[2], b[6]) + + MUL31(a[3], b[5]) + + MUL31(a[4], b[4]) + + MUL31(a[5], b[3]) + + MUL31(a[6], b[2]) + + MUL31(a[7], b[1]) + + MUL31(a[8], b[0]); + t[ 9] = MUL31(a[1], b[8]) + + MUL31(a[2], b[7]) + + MUL31(a[3], b[6]) + + MUL31(a[4], b[5]) + + MUL31(a[5], b[4]) + + MUL31(a[6], b[3]) + + MUL31(a[7], b[2]) + + MUL31(a[8], b[1]); + t[10] = MUL31(a[2], b[8]) + + MUL31(a[3], b[7]) + + MUL31(a[4], b[6]) + + MUL31(a[5], b[5]) + + MUL31(a[6], b[4]) + + MUL31(a[7], b[3]) + + MUL31(a[8], b[2]); + t[11] = MUL31(a[3], b[8]) + + MUL31(a[4], b[7]) + + MUL31(a[5], b[6]) + + MUL31(a[6], b[5]) + + MUL31(a[7], b[4]) + + MUL31(a[8], b[3]); + t[12] = MUL31(a[4], b[8]) + + MUL31(a[5], b[7]) + + MUL31(a[6], b[6]) + + MUL31(a[7], b[5]) + + MUL31(a[8], b[4]); + t[13] = MUL31(a[5], b[8]) + + MUL31(a[6], b[7]) + + MUL31(a[7], b[6]) + + MUL31(a[8], b[5]); + t[14] = MUL31(a[6], b[8]) + + MUL31(a[7], b[7]) + + MUL31(a[8], b[6]); + t[15] = MUL31(a[7], b[8]) + + MUL31(a[8], b[7]); + t[16] = MUL31(a[8], b[8]); + + /* + * Propagate carries. + */ + cc = 0; + for (i = 0; i < 17; i ++) { + uint64_t w; + + w = t[i] + cc; + d[i] = (uint32_t)w & 0x3FFFFFFF; + cc = w >> 30; + } + d[17] = (uint32_t)cc; +} + +/* + * Square a 270-bit integer, represented as an array of nine 30-bit words. + * Result uses 18 words of 30 bits each. + */ +static void +square9(uint32_t *d, const uint32_t *a) +{ + uint64_t t[17]; + uint64_t cc; + int i; + + t[ 0] = MUL31(a[0], a[0]); + t[ 1] = ((MUL31(a[0], a[1])) << 1); + t[ 2] = MUL31(a[1], a[1]) + + ((MUL31(a[0], a[2])) << 1); + t[ 3] = ((MUL31(a[0], a[3]) + + MUL31(a[1], a[2])) << 1); + t[ 4] = MUL31(a[2], a[2]) + + ((MUL31(a[0], a[4]) + + MUL31(a[1], a[3])) << 1); + t[ 5] = ((MUL31(a[0], a[5]) + + MUL31(a[1], a[4]) + + MUL31(a[2], a[3])) << 1); + t[ 6] = MUL31(a[3], a[3]) + + ((MUL31(a[0], a[6]) + + MUL31(a[1], a[5]) + + MUL31(a[2], a[4])) << 1); + t[ 7] = ((MUL31(a[0], a[7]) + + MUL31(a[1], a[6]) + + MUL31(a[2], a[5]) + + MUL31(a[3], a[4])) << 1); + t[ 8] = MUL31(a[4], a[4]) + + ((MUL31(a[0], a[8]) + + MUL31(a[1], a[7]) + + MUL31(a[2], a[6]) + + MUL31(a[3], a[5])) << 1); + t[ 9] = ((MUL31(a[1], a[8]) + + MUL31(a[2], a[7]) + + MUL31(a[3], a[6]) + + MUL31(a[4], a[5])) << 1); + t[10] = MUL31(a[5], a[5]) + + ((MUL31(a[2], a[8]) + + MUL31(a[3], a[7]) + + MUL31(a[4], a[6])) << 1); + t[11] = ((MUL31(a[3], a[8]) + + MUL31(a[4], a[7]) + + MUL31(a[5], a[6])) << 1); + t[12] = MUL31(a[6], a[6]) + + ((MUL31(a[4], a[8]) + + MUL31(a[5], a[7])) << 1); + t[13] = ((MUL31(a[5], a[8]) + + MUL31(a[6], a[7])) << 1); + t[14] = MUL31(a[7], a[7]) + + ((MUL31(a[6], a[8])) << 1); + t[15] = ((MUL31(a[7], a[8])) << 1); + t[16] = MUL31(a[8], a[8]); + + /* + * Propagate carries. + */ + cc = 0; + for (i = 0; i < 17; i ++) { + uint64_t w; + + w = t[i] + cc; + d[i] = (uint32_t)w & 0x3FFFFFFF; + cc = w >> 30; + } + d[17] = (uint32_t)cc; +} + +/* + * Base field modulus for P-256. + */ +static const uint32_t F256[] = { + + 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x0000003F, 0x00000000, + 0x00000000, 0x00001000, 0x3FFFC000, 0x0000FFFF +}; + +/* + * The 'b' curve equation coefficient for P-256. + */ +static const uint32_t P256_B[] = { + + 0x27D2604B, 0x2F38F0F8, 0x053B0F63, 0x0741AC33, 0x1886BC65, + 0x2EF555DA, 0x293E7B3E, 0x0D762A8E, 0x00005AC6 +}; + +/* + * Addition in the field. Source operands shall fit on 257 bits; output + * will be lower than twice the modulus. + */ +static void +add_f256(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t w, cc; + int i; + + cc = 0; + for (i = 0; i < 9; i ++) { + w = a[i] + b[i] + cc; + d[i] = w & 0x3FFFFFFF; + cc = w >> 30; + } + w >>= 16; + d[8] &= 0xFFFF; + d[3] -= w << 6; + d[6] -= w << 12; + d[7] += w << 14; + cc = w; + for (i = 0; i < 9; i ++) { + w = d[i] + cc; + d[i] = w & 0x3FFFFFFF; + cc = ARSH(w, 30); + } +} + +/* + * Subtraction in the field. Source operands shall be smaller than twice + * the modulus; the result will fulfil the same property. + */ +static void +sub_f256(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t w, cc; + int i; + + /* + * We really compute a - b + 2*p to make sure that the result is + * positive. + */ + w = a[0] - b[0] - 0x00002; + d[0] = w & 0x3FFFFFFF; + w = a[1] - b[1] + ARSH(w, 30); + d[1] = w & 0x3FFFFFFF; + w = a[2] - b[2] + ARSH(w, 30); + d[2] = w & 0x3FFFFFFF; + w = a[3] - b[3] + ARSH(w, 30) + 0x00080; + d[3] = w & 0x3FFFFFFF; + w = a[4] - b[4] + ARSH(w, 30); + d[4] = w & 0x3FFFFFFF; + w = a[5] - b[5] + ARSH(w, 30); + d[5] = w & 0x3FFFFFFF; + w = a[6] - b[6] + ARSH(w, 30) + 0x02000; + d[6] = w & 0x3FFFFFFF; + w = a[7] - b[7] + ARSH(w, 30) - 0x08000; + d[7] = w & 0x3FFFFFFF; + w = a[8] - b[8] + ARSH(w, 30) + 0x20000; + d[8] = w & 0xFFFF; + w >>= 16; + d[8] &= 0xFFFF; + d[3] -= w << 6; + d[6] -= w << 12; + d[7] += w << 14; + cc = w; + for (i = 0; i < 9; i ++) { + w = d[i] + cc; + d[i] = w & 0x3FFFFFFF; + cc = ARSH(w, 30); + } +} + +/* + * Compute a multiplication in F256. Source operands shall be less than + * twice the modulus. + */ +static void +mul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + uint32_t t[18]; + uint64_t s[18]; + uint64_t cc, x; + uint32_t z, c; + int i; + + mul9(t, a, b); + + /* + * Modular reduction: each high word in added/subtracted where + * necessary. + * + * The modulus is: + * p = 2^256 - 2^224 + 2^192 + 2^96 - 1 + * Therefore: + * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p + * + * For a word x at bit offset n (n >= 256), we have: + * x*2^n = x*2^(n-32) - x*2^(n-64) + * - x*2^(n - 160) + x*2^(n-256) mod p + * + * Thus, we can nullify the high word if we reinject it at some + * proper emplacements. + * + * We use 64-bit intermediate words to allow for carries to + * accumulate easily, before performing the final propagation. + */ + for (i = 0; i < 18; i ++) { + s[i] = t[i]; + } + + for (i = 17; i >= 9; i --) { + uint64_t y; + + y = s[i]; + s[i - 1] += ARSHW(y, 2); + s[i - 2] += (y << 28) & 0x3FFFFFFF; + s[i - 2] -= ARSHW(y, 4); + s[i - 3] -= (y << 26) & 0x3FFFFFFF; + s[i - 5] -= ARSHW(y, 10); + s[i - 6] -= (y << 20) & 0x3FFFFFFF; + s[i - 8] += ARSHW(y, 16); + s[i - 9] += (y << 14) & 0x3FFFFFFF; + } + + /* + * Carry propagation must be signed. Moreover, we may have overdone + * it a bit, and obtain a negative result. + * + * The loop above ran 9 times; each time, each word was augmented + * by at most one extra word (in absolute value). Thus, the top + * word must in fine fit in 39 bits, so the carry below will fit + * on 9 bits. + */ + cc = 0; + for (i = 0; i < 9; i ++) { + x = s[i] + cc; + d[i] = (uint32_t)x & 0x3FFFFFFF; + cc = ARSHW(x, 30); + } + + /* + * All nine words fit on 30 bits, but there may be an extra + * carry for a few bits (at most 9), and that carry may be + * negative. Moreover, we want the result to fit on 257 bits. + * The two lines below ensure that the word in d[] has length + * 256 bits, and the (signed) carry (beyond 2^256) is in cc. The + * significant length of cc is less than 24 bits, so we will be + * able to switch to 32-bit operations. + */ + cc = ARSHW(x, 16); + d[8] &= 0xFFFF; + + /* + * One extra round of reduction, for cc*2^256, which means + * adding cc*(2^224-2^192-2^96+1) to a 256-bit (nonnegative) + * value. If cc is negative, then it may happen (rarely, but + * not neglectibly so) that the result would be negative. In + * order to avoid that, if cc is negative, then we add the + * modulus once. Note that if cc is negative, then propagating + * that carry must yield a value lower than the modulus, so + * adding the modulus once will keep the final result under + * twice the modulus. + */ + z = (uint32_t)cc; + d[3] -= z << 6; + d[6] -= (z << 12) & 0x3FFFFFFF; + d[7] -= ARSH(z, 18); + d[7] += (z << 14) & 0x3FFFFFFF; + d[8] += ARSH(z, 16); + c = z >> 31; + d[0] -= c; + d[3] += c << 6; + d[6] += c << 12; + d[7] -= c << 14; + d[8] += c << 16; + for (i = 0; i < 9; i ++) { + uint32_t w; + + w = d[i] + z; + d[i] = w & 0x3FFFFFFF; + z = ARSH(w, 30); + } +} + +/* + * Compute a square in F256. Source operand shall be less than + * twice the modulus. + */ +static void +square_f256(uint32_t *d, const uint32_t *a) +{ + uint32_t t[18]; + uint64_t s[18]; + uint64_t cc, x; + uint32_t z, c; + int i; + + square9(t, a); + + /* + * Modular reduction: each high word in added/subtracted where + * necessary. + * + * The modulus is: + * p = 2^256 - 2^224 + 2^192 + 2^96 - 1 + * Therefore: + * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p + * + * For a word x at bit offset n (n >= 256), we have: + * x*2^n = x*2^(n-32) - x*2^(n-64) + * - x*2^(n - 160) + x*2^(n-256) mod p + * + * Thus, we can nullify the high word if we reinject it at some + * proper emplacements. + * + * We use 64-bit intermediate words to allow for carries to + * accumulate easily, before performing the final propagation. + */ + for (i = 0; i < 18; i ++) { + s[i] = t[i]; + } + + for (i = 17; i >= 9; i --) { + uint64_t y; + + y = s[i]; + s[i - 1] += ARSHW(y, 2); + s[i - 2] += (y << 28) & 0x3FFFFFFF; + s[i - 2] -= ARSHW(y, 4); + s[i - 3] -= (y << 26) & 0x3FFFFFFF; + s[i - 5] -= ARSHW(y, 10); + s[i - 6] -= (y << 20) & 0x3FFFFFFF; + s[i - 8] += ARSHW(y, 16); + s[i - 9] += (y << 14) & 0x3FFFFFFF; + } + + /* + * Carry propagation must be signed. Moreover, we may have overdone + * it a bit, and obtain a negative result. + * + * The loop above ran 9 times; each time, each word was augmented + * by at most one extra word (in absolute value). Thus, the top + * word must in fine fit in 39 bits, so the carry below will fit + * on 9 bits. + */ + cc = 0; + for (i = 0; i < 9; i ++) { + x = s[i] + cc; + d[i] = (uint32_t)x & 0x3FFFFFFF; + cc = ARSHW(x, 30); + } + + /* + * All nine words fit on 30 bits, but there may be an extra + * carry for a few bits (at most 9), and that carry may be + * negative. Moreover, we want the result to fit on 257 bits. + * The two lines below ensure that the word in d[] has length + * 256 bits, and the (signed) carry (beyond 2^256) is in cc. The + * significant length of cc is less than 24 bits, so we will be + * able to switch to 32-bit operations. + */ + cc = ARSHW(x, 16); + d[8] &= 0xFFFF; + + /* + * One extra round of reduction, for cc*2^256, which means + * adding cc*(2^224-2^192-2^96+1) to a 256-bit (nonnegative) + * value. If cc is negative, then it may happen (rarely, but + * not neglectibly so) that the result would be negative. In + * order to avoid that, if cc is negative, then we add the + * modulus once. Note that if cc is negative, then propagating + * that carry must yield a value lower than the modulus, so + * adding the modulus once will keep the final result under + * twice the modulus. + */ + z = (uint32_t)cc; + d[3] -= z << 6; + d[6] -= (z << 12) & 0x3FFFFFFF; + d[7] -= ARSH(z, 18); + d[7] += (z << 14) & 0x3FFFFFFF; + d[8] += ARSH(z, 16); + c = z >> 31; + d[0] -= c; + d[3] += c << 6; + d[6] += c << 12; + d[7] -= c << 14; + d[8] += c << 16; + for (i = 0; i < 9; i ++) { + uint32_t w; + + w = d[i] + z; + d[i] = w & 0x3FFFFFFF; + z = ARSH(w, 30); + } +} + +/* + * Perform a "final reduction" in field F256 (field for curve P-256). + * The source value must be less than twice the modulus. If the value + * is not lower than the modulus, then the modulus is subtracted and + * this function returns 1; otherwise, it leaves it untouched and it + * returns 0. + */ +static uint32_t +reduce_final_f256(uint32_t *d) +{ + uint32_t t[9]; + uint32_t cc; + int i; + + cc = 0; + for (i = 0; i < 9; i ++) { + uint32_t w; + + w = d[i] - F256[i] - cc; + cc = w >> 31; + t[i] = w & 0x3FFFFFFF; + } + cc ^= 1; + CCOPY(cc, d, t, sizeof t); + return cc; +} + +/* + * Jacobian coordinates for a point in P-256: affine coordinates (X,Y) + * are such that: + * X = x / z^2 + * Y = y / z^3 + * For the point at infinity, z = 0. + * Each point thus admits many possible representations. + * + * Coordinates are represented in arrays of 32-bit integers, each holding + * 30 bits of data. Values may also be slightly greater than the modulus, + * but they will always be lower than twice the modulus. + */ +typedef struct { + uint32_t x[9]; + uint32_t y[9]; + uint32_t z[9]; +} p256_jacobian; + +/* + * Convert a point to affine coordinates: + * - If the point is the point at infinity, then all three coordinates + * are set to 0. + * - Otherwise, the 'z' coordinate is set to 1, and the 'x' and 'y' + * coordinates are the 'X' and 'Y' affine coordinates. + * The coordinates are guaranteed to be lower than the modulus. + */ +static void +p256_to_affine(p256_jacobian *P) +{ + uint32_t t1[9], t2[9]; + int i; + + /* + * Invert z with a modular exponentiation: the modulus is + * p = 2^256 - 2^224 + 2^192 + 2^96 - 1, and the exponent is + * p-2. Exponent bit pattern (from high to low) is: + * - 32 bits of value 1 + * - 31 bits of value 0 + * - 1 bit of value 1 + * - 96 bits of value 0 + * - 94 bits of value 1 + * - 1 bit of value 0 + * - 1 bit of value 1 + * Thus, we precompute z^(2^31-1) to speed things up. + * + * If z = 0 (point at infinity) then the modular exponentiation + * will yield 0, which leads to the expected result (all three + * coordinates set to 0). + */ + + /* + * A simple square-and-multiply for z^(2^31-1). We could save about + * two dozen multiplications here with an addition chain, but + * this would require a bit more code, and extra stack buffers. + */ + memcpy(t1, P->z, sizeof P->z); + for (i = 0; i < 30; i ++) { + square_f256(t1, t1); + mul_f256(t1, t1, P->z); + } + + /* + * Square-and-multiply. Apart from the squarings, we have a few + * multiplications to set bits to 1; we multiply by the original z + * for setting 1 bit, and by t1 for setting 31 bits. + */ + memcpy(t2, P->z, sizeof P->z); + for (i = 1; i < 256; i ++) { + square_f256(t2, t2); + switch (i) { + case 31: + case 190: + case 221: + case 252: + mul_f256(t2, t2, t1); + break; + case 63: + case 253: + case 255: + mul_f256(t2, t2, P->z); + break; + } + } + + /* + * Now that we have 1/z, multiply x by 1/z^2 and y by 1/z^3. + */ + mul_f256(t1, t2, t2); + mul_f256(P->x, t1, P->x); + mul_f256(t1, t1, t2); + mul_f256(P->y, t1, P->y); + reduce_final_f256(P->x); + reduce_final_f256(P->y); + + /* + * Multiply z by 1/z. If z = 0, then this will yield 0, otherwise + * this will set z to 1. + */ + mul_f256(P->z, P->z, t2); + reduce_final_f256(P->z); +} + +/* + * Double a point in P-256. This function works for all valid points, + * including the point at infinity. + */ +static void +p256_double(p256_jacobian *Q) +{ + /* + * Doubling formulas are: + * + * s = 4*x*y^2 + * m = 3*(x + z^2)*(x - z^2) + * x' = m^2 - 2*s + * y' = m*(s - x') - 8*y^4 + * z' = 2*y*z + * + * These formulas work for all points, including points of order 2 + * and points at infinity: + * - If y = 0 then z' = 0. But there is no such point in P-256 + * anyway. + * - If z = 0 then z' = 0. + */ + uint32_t t1[9], t2[9], t3[9], t4[9]; + + /* + * Compute z^2 in t1. + */ + square_f256(t1, Q->z); + + /* + * Compute x-z^2 in t2 and x+z^2 in t1. + */ + add_f256(t2, Q->x, t1); + sub_f256(t1, Q->x, t1); + + /* + * Compute 3*(x+z^2)*(x-z^2) in t1. + */ + mul_f256(t3, t1, t2); + add_f256(t1, t3, t3); + add_f256(t1, t3, t1); + + /* + * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3). + */ + square_f256(t3, Q->y); + add_f256(t3, t3, t3); + mul_f256(t2, Q->x, t3); + add_f256(t2, t2, t2); + + /* + * Compute x' = m^2 - 2*s. + */ + square_f256(Q->x, t1); + sub_f256(Q->x, Q->x, t2); + sub_f256(Q->x, Q->x, t2); + + /* + * Compute z' = 2*y*z. + */ + mul_f256(t4, Q->y, Q->z); + add_f256(Q->z, t4, t4); + + /* + * Compute y' = m*(s - x') - 8*y^4. Note that we already have + * 2*y^2 in t3. + */ + sub_f256(t2, t2, Q->x); + mul_f256(Q->y, t1, t2); + square_f256(t4, t3); + add_f256(t4, t4, t4); + sub_f256(Q->y, Q->y, t4); +} + +/* + * Add point P2 to point P1. + * + * This function computes the wrong result in the following cases: + * + * - If P1 == 0 but P2 != 0 + * - If P1 != 0 but P2 == 0 + * - If P1 == P2 + * + * In all three cases, P1 is set to the point at infinity. + * + * Returned value is 0 if one of the following occurs: + * + * - P1 and P2 have the same Y coordinate + * - P1 == 0 and P2 == 0 + * - The Y coordinate of one of the points is 0 and the other point is + * the point at infinity. + * + * The third case cannot actually happen with valid points, since a point + * with Y == 0 is a point of order 2, and there is no point of order 2 on + * curve P-256. + * + * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller + * can apply the following: + * + * - If the result is not the point at infinity, then it is correct. + * - Otherwise, if the returned value is 1, then this is a case of + * P1+P2 == 0, so the result is indeed the point at infinity. + * - Otherwise, P1 == P2, so a "double" operation should have been + * performed. + */ +static uint32_t +p256_add(p256_jacobian *P1, const p256_jacobian *P2) +{ + /* + * Addtions formulas are: + * + * u1 = x1 * z2^2 + * u2 = x2 * z1^2 + * s1 = y1 * z2^3 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 * z2 + */ + uint32_t t1[9], t2[9], t3[9], t4[9], t5[9], t6[9], t7[9]; + uint32_t ret; + int i; + + /* + * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). + */ + square_f256(t3, P2->z); + mul_f256(t1, P1->x, t3); + mul_f256(t4, P2->z, t3); + mul_f256(t3, P1->y, t4); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + square_f256(t4, P1->z); + mul_f256(t2, P2->x, t4); + mul_f256(t5, P1->z, t4); + mul_f256(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * We need to test whether r is zero, so we will do some extra + * reduce. + */ + sub_f256(t2, t2, t1); + sub_f256(t4, t4, t3); + reduce_final_f256(t4); + ret = 0; + for (i = 0; i < 9; i ++) { + ret |= t4[i]; + } + ret = (ret | -ret) >> 31; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + square_f256(t7, t2); + mul_f256(t6, t1, t7); + mul_f256(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + square_f256(P1->x, t4); + sub_f256(P1->x, P1->x, t5); + sub_f256(P1->x, P1->x, t6); + sub_f256(P1->x, P1->x, t6); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + sub_f256(t6, t6, P1->x); + mul_f256(P1->y, t4, t6); + mul_f256(t1, t5, t3); + sub_f256(P1->y, P1->y, t1); + + /* + * Compute z3 = h*z1*z2. + */ + mul_f256(t1, P1->z, P2->z); + mul_f256(P1->z, t1, t2); + + return ret; +} + +/* + * Add point P2 to point P1. This is a specialised function for the + * case when P2 is a non-zero point in affine coordinate. + * + * This function computes the wrong result in the following cases: + * + * - If P1 == 0 + * - If P1 == P2 + * + * In both cases, P1 is set to the point at infinity. + * + * Returned value is 0 if one of the following occurs: + * + * - P1 and P2 have the same Y coordinate + * - The Y coordinate of P2 is 0 and P1 is the point at infinity. + * + * The second case cannot actually happen with valid points, since a point + * with Y == 0 is a point of order 2, and there is no point of order 2 on + * curve P-256. + * + * Therefore, assuming that P1 != 0 on input, then the caller + * can apply the following: + * + * - If the result is not the point at infinity, then it is correct. + * - Otherwise, if the returned value is 1, then this is a case of + * P1+P2 == 0, so the result is indeed the point at infinity. + * - Otherwise, P1 == P2, so a "double" operation should have been + * performed. + */ +static uint32_t +p256_add_mixed(p256_jacobian *P1, const p256_jacobian *P2) +{ + /* + * Addtions formulas are: + * + * u1 = x1 + * u2 = x2 * z1^2 + * s1 = y1 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 + */ + uint32_t t1[9], t2[9], t3[9], t4[9], t5[9], t6[9], t7[9]; + uint32_t ret; + int i; + + /* + * Compute u1 = x1 (in t1) and s1 = y1 (in t3). + */ + memcpy(t1, P1->x, sizeof t1); + memcpy(t3, P1->y, sizeof t3); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + square_f256(t4, P1->z); + mul_f256(t2, P2->x, t4); + mul_f256(t5, P1->z, t4); + mul_f256(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * We need to test whether r is zero, so we will do some extra + * reduce. + */ + sub_f256(t2, t2, t1); + sub_f256(t4, t4, t3); + reduce_final_f256(t4); + ret = 0; + for (i = 0; i < 9; i ++) { + ret |= t4[i]; + } + ret = (ret | -ret) >> 31; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + square_f256(t7, t2); + mul_f256(t6, t1, t7); + mul_f256(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + square_f256(P1->x, t4); + sub_f256(P1->x, P1->x, t5); + sub_f256(P1->x, P1->x, t6); + sub_f256(P1->x, P1->x, t6); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + sub_f256(t6, t6, P1->x); + mul_f256(P1->y, t4, t6); + mul_f256(t1, t5, t3); + sub_f256(P1->y, P1->y, t1); + + /* + * Compute z3 = h*z1*z2. + */ + mul_f256(P1->z, P1->z, t2); + + return ret; +} + +/* + * Decode a P-256 point. This function does not support the point at + * infinity. Returned value is 0 if the point is invalid, 1 otherwise. + */ +static uint32_t +p256_decode(p256_jacobian *P, const void *src, size_t len) +{ + const unsigned char *buf; + uint32_t tx[9], ty[9], t1[9], t2[9]; + uint32_t bad; + int i; + + if (len != 65) { + return 0; + } + buf = src; + + /* + * First byte must be 0x04 (uncompressed format). We could support + * "hybrid format" (first byte is 0x06 or 0x07, and encodes the + * least significant bit of the Y coordinate), but it is explicitly + * forbidden by RFC 5480 (section 2.2). + */ + bad = NEQ(buf[0], 0x04); + + /* + * Decode the coordinates, and check that they are both lower + * than the modulus. + */ + tx[8] = be8_to_le30(tx, buf + 1, 32); + ty[8] = be8_to_le30(ty, buf + 33, 32); + bad |= reduce_final_f256(tx); + bad |= reduce_final_f256(ty); + + /* + * Check curve equation. + */ + square_f256(t1, tx); + mul_f256(t1, tx, t1); + square_f256(t2, ty); + sub_f256(t1, t1, tx); + sub_f256(t1, t1, tx); + sub_f256(t1, t1, tx); + add_f256(t1, t1, P256_B); + sub_f256(t1, t1, t2); + reduce_final_f256(t1); + for (i = 0; i < 9; i ++) { + bad |= t1[i]; + } + + /* + * Copy coordinates to the point structure. + */ + memcpy(P->x, tx, sizeof tx); + memcpy(P->y, ty, sizeof ty); + memset(P->z, 0, sizeof P->z); + P->z[0] = 1; + return EQ(bad, 0); +} + +/* + * Encode a point into a buffer. This function assumes that the point is + * valid, in affine coordinates, and not the point at infinity. + */ +static void +p256_encode(void *dst, const p256_jacobian *P) +{ + unsigned char *buf; + + buf = dst; + buf[0] = 0x04; + le30_to_be8(buf + 1, 32, P->x); + le30_to_be8(buf + 33, 32, P->y); +} + +/* + * Multiply a curve point by an integer. The integer is assumed to be + * lower than the curve order, and the base point must not be the point + * at infinity. + */ +static void +p256_mul(p256_jacobian *P, const unsigned char *x, size_t xlen) +{ + /* + * qz is a flag that is initially 1, and remains equal to 1 + * as long as the point is the point at infinity. + * + * We use a 2-bit window to handle multiplier bits by pairs. + * The precomputed window really is the points P2 and P3. + */ + uint32_t qz; + p256_jacobian P2, P3, Q, T, U; + + /* + * Compute window values. + */ + P2 = *P; + p256_double(&P2); + P3 = *P; + p256_add(&P3, &P2); + + /* + * We start with Q = 0. We process multiplier bits 2 by 2. + */ + memset(&Q, 0, sizeof Q); + qz = 1; + while (xlen -- > 0) { + int k; + + for (k = 6; k >= 0; k -= 2) { + uint32_t bits; + uint32_t bnz; + + p256_double(&Q); + p256_double(&Q); + T = *P; + U = Q; + bits = (*x >> k) & (uint32_t)3; + bnz = NEQ(bits, 0); + CCOPY(EQ(bits, 2), &T, &P2, sizeof T); + CCOPY(EQ(bits, 3), &T, &P3, sizeof T); + p256_add(&U, &T); + CCOPY(bnz & qz, &Q, &T, sizeof Q); + CCOPY(bnz & ~qz, &Q, &U, sizeof Q); + qz &= ~bnz; + } + x ++; + } + *P = Q; +} + +/* + * Precomputed window: k*G points, where G is the curve generator, and k + * is an integer from 1 to 15 (inclusive). The X and Y coordinates of + * the point are encoded as 9 words of 30 bits each (little-endian + * order). + */ +static const uint32_t Gwin[15][18] = { + + { 0x1898C296, 0x1284E517, 0x1EB33A0F, 0x00DF604B, + 0x2440F277, 0x339B958E, 0x04247F8B, 0x347CB84B, + 0x00006B17, 0x37BF51F5, 0x2ED901A0, 0x3315ECEC, + 0x338CD5DA, 0x0F9E162B, 0x1FAD29F0, 0x27F9B8EE, + 0x10B8BF86, 0x00004FE3 }, + + { 0x07669978, 0x182D23F1, 0x3F21B35A, 0x225A789D, + 0x351AC3C0, 0x08E00C12, 0x34F7E8A5, 0x1EC62340, + 0x00007CF2, 0x227873D1, 0x3812DE74, 0x0E982299, + 0x1F6B798F, 0x3430DBBA, 0x366B1A7D, 0x2D040293, + 0x154436E3, 0x00000777 }, + + { 0x06E7FD6C, 0x2D05986F, 0x3ADA985F, 0x31ADC87B, + 0x0BF165E6, 0x1FBE5475, 0x30A44C8F, 0x3934698C, + 0x00005ECB, 0x227D5032, 0x29E6C49E, 0x04FB83D9, + 0x0AAC0D8E, 0x24A2ECD8, 0x2C1B3869, 0x0FF7E374, + 0x19031266, 0x00008734 }, + + { 0x2B030852, 0x024C0911, 0x05596EF5, 0x07F8B6DE, + 0x262BD003, 0x3779967B, 0x08FBBA02, 0x128D4CB4, + 0x0000E253, 0x184ED8C6, 0x310B08FC, 0x30EE0055, + 0x3F25B0FC, 0x062D764E, 0x3FB97F6A, 0x33CC719D, + 0x15D69318, 0x0000E0F1 }, + + { 0x03D033ED, 0x05552837, 0x35BE5242, 0x2320BF47, + 0x268FDFEF, 0x13215821, 0x140D2D78, 0x02DE9454, + 0x00005159, 0x3DA16DA4, 0x0742ED13, 0x0D80888D, + 0x004BC035, 0x0A79260D, 0x06FCDAFE, 0x2727D8AE, + 0x1F6A2412, 0x0000E0C1 }, + + { 0x3C2291A9, 0x1AC2ABA4, 0x3B215B4C, 0x131D037A, + 0x17DDE302, 0x0C90B2E2, 0x0602C92D, 0x05CA9DA9, + 0x0000B01A, 0x0FC77FE2, 0x35F1214E, 0x07E16BDF, + 0x003DDC07, 0x2703791C, 0x3038B7EE, 0x3DAD56FE, + 0x041D0C8D, 0x0000E85C }, + + { 0x3187B2A3, 0x0018A1C0, 0x00FEF5B3, 0x3E7E2E2A, + 0x01FB607E, 0x2CC199F0, 0x37B4625B, 0x0EDBE82F, + 0x00008E53, 0x01F400B4, 0x15786A1B, 0x3041B21C, + 0x31CD8CF2, 0x35900053, 0x1A7E0E9B, 0x318366D0, + 0x076F780C, 0x000073EB }, + + { 0x1B6FB393, 0x13767707, 0x3CE97DBB, 0x348E2603, + 0x354CADC1, 0x09D0B4EA, 0x1B053404, 0x1DE76FBA, + 0x000062D9, 0x0F09957E, 0x295029A8, 0x3E76A78D, + 0x3B547DAE, 0x27CEE0A2, 0x0575DC45, 0x1D8244FF, + 0x332F647A, 0x0000AD5A }, + + { 0x10949EE0, 0x1E7A292E, 0x06DF8B3D, 0x02B2E30B, + 0x31F8729E, 0x24E35475, 0x30B71878, 0x35EDBFB7, + 0x0000EA68, 0x0DD048FA, 0x21688929, 0x0DE823FE, + 0x1C53FAA9, 0x0EA0C84D, 0x052A592A, 0x1FCE7870, + 0x11325CB2, 0x00002A27 }, + + { 0x04C5723F, 0x30D81A50, 0x048306E4, 0x329B11C7, + 0x223FB545, 0x085347A8, 0x2993E591, 0x1B5ACA8E, + 0x0000CEF6, 0x04AF0773, 0x28D2EEA9, 0x2751EEEC, + 0x037B4A7F, 0x3B4C1059, 0x08F37674, 0x2AE906E1, + 0x18A88A6A, 0x00008786 }, + + { 0x34BC21D1, 0x0CCE474D, 0x15048BF4, 0x1D0BB409, + 0x021CDA16, 0x20DE76C3, 0x34C59063, 0x04EDE20E, + 0x00003ED1, 0x282A3740, 0x0BE3BBF3, 0x29889DAE, + 0x03413697, 0x34C68A09, 0x210EBE93, 0x0C8A224C, + 0x0826B331, 0x00009099 }, + + { 0x0624E3C4, 0x140317BA, 0x2F82C99D, 0x260C0A2C, + 0x25D55179, 0x194DCC83, 0x3D95E462, 0x356F6A05, + 0x0000741D, 0x0D4481D3, 0x2657FC8B, 0x1BA5CA71, + 0x3AE44B0D, 0x07B1548E, 0x0E0D5522, 0x05FDC567, + 0x2D1AA70E, 0x00000770 }, + + { 0x06072C01, 0x23857675, 0x1EAD58A9, 0x0B8A12D9, + 0x1EE2FC79, 0x0177CB61, 0x0495A618, 0x20DEB82B, + 0x0000177C, 0x2FC7BFD8, 0x310EEF8B, 0x1FB4DF39, + 0x3B8530E8, 0x0F4E7226, 0x0246B6D0, 0x2A558A24, + 0x163353AF, 0x000063BB }, + + { 0x24D2920B, 0x1C249DCC, 0x2069C5E5, 0x09AB2F9E, + 0x36DF3CF1, 0x1991FD0C, 0x062B97A7, 0x1E80070E, + 0x000054E7, 0x20D0B375, 0x2E9F20BD, 0x35090081, + 0x1C7A9DDC, 0x22E7C371, 0x087E3016, 0x03175421, + 0x3C6ECA7D, 0x0000F599 }, + + { 0x259B9D5F, 0x0D9A318F, 0x23A0EF16, 0x00EBE4B7, + 0x088265AE, 0x2CDE2666, 0x2BAE7ADF, 0x1371A5C6, + 0x0000F045, 0x0D034F36, 0x1F967378, 0x1B5FA3F4, + 0x0EC8739D, 0x1643E62A, 0x1653947E, 0x22D1F4E6, + 0x0FB8D64B, 0x0000B5B9 } +}; + +/* + * Lookup one of the Gwin[] values, by index. This is constant-time. + */ +static void +lookup_Gwin(p256_jacobian *T, uint32_t idx) +{ + uint32_t xy[18]; + uint32_t k; + size_t u; + + memset(xy, 0, sizeof xy); + for (k = 0; k < 15; k ++) { + uint32_t m; + + m = -EQ(idx, k + 1); + for (u = 0; u < 18; u ++) { + xy[u] |= m & Gwin[k][u]; + } + } + memcpy(T->x, &xy[0], sizeof T->x); + memcpy(T->y, &xy[9], sizeof T->y); + memset(T->z, 0, sizeof T->z); + T->z[0] = 1; +} + +/* + * Multiply the generator by an integer. The integer is assumed non-zero + * and lower than the curve order. + */ +static void +p256_mulgen(p256_jacobian *P, const unsigned char *x, size_t xlen) +{ + /* + * qz is a flag that is initially 1, and remains equal to 1 + * as long as the point is the point at infinity. + * + * We use a 4-bit window to handle multiplier bits by groups + * of 4. The precomputed window is constant static data, with + * points in affine coordinates; we use a constant-time lookup. + */ + p256_jacobian Q; + uint32_t qz; + + memset(&Q, 0, sizeof Q); + qz = 1; + while (xlen -- > 0) { + int k; + unsigned bx; + + bx = *x ++; + for (k = 0; k < 2; k ++) { + uint32_t bits; + uint32_t bnz; + p256_jacobian T, U; + + p256_double(&Q); + p256_double(&Q); + p256_double(&Q); + p256_double(&Q); + bits = (bx >> 4) & 0x0F; + bnz = NEQ(bits, 0); + lookup_Gwin(&T, bits); + U = Q; + p256_add_mixed(&U, &T); + CCOPY(bnz & qz, &Q, &T, sizeof Q); + CCOPY(bnz & ~qz, &Q, &U, sizeof Q); + qz &= ~bnz; + bx <<= 4; + } + } + *P = Q; +} + +static const unsigned char P256_G[] = { + 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, + 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, + 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, + 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, + 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, + 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, + 0x68, 0x37, 0xBF, 0x51, 0xF5 +}; + +static const unsigned char P256_N[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, + 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, + 0x25, 0x51 +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = sizeof P256_G; + return P256_G; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = sizeof P256_N; + return P256_N; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 1; +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *x, size_t xlen, int curve) +{ + uint32_t r; + p256_jacobian P; + + (void)curve; + if (Glen != 65) { + return 0; + } + r = p256_decode(&P, G, Glen); + p256_mul(&P, x, xlen); + p256_to_affine(&P); + p256_encode(G, &P); + return r; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + p256_jacobian P; + + (void)curve; + p256_mulgen(&P, x, xlen); + p256_to_affine(&P); + p256_encode(R, &P); + return 65; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + p256_jacobian P, Q; + uint32_t r, t, z; + int i; + + (void)curve; + if (len != 65) { + return 0; + } + r = p256_decode(&P, A, len); + p256_mul(&P, x, xlen); + if (B == NULL) { + p256_mulgen(&Q, y, ylen); + } else { + r &= p256_decode(&Q, B, len); + p256_mul(&Q, y, ylen); + } + + /* + * The final addition may fail in case both points are equal. + */ + t = p256_add(&P, &Q); + reduce_final_f256(P.z); + z = 0; + for (i = 0; i < 9; i ++) { + z |= P.z[i]; + } + z = EQ(z, 0); + p256_double(&Q); + + /* + * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we + * have the following: + * + * z = 0, t = 0 return P (normal addition) + * z = 0, t = 1 return P (normal addition) + * z = 1, t = 0 return Q (a 'double' case) + * z = 1, t = 1 report an error (P+Q = 0) + */ + CCOPY(z & ~t, &P, &Q, sizeof Q); + p256_to_affine(&P); + p256_encode(A, &P); + r &= ~(z & t); + return r; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_p256_m31 = { + (uint32_t)0x00800000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_p256_m62.c b/BearSSL-OG/libbearssl/src/ec/ec_p256_m62.c new file mode 100644 index 0000000..a431790 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_p256_m62.c @@ -0,0 +1,1765 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +#if BR_UMUL128 +#include +#endif + +static const unsigned char P256_G[] = { + 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, + 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, + 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, + 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, + 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, + 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, + 0x68, 0x37, 0xBF, 0x51, 0xF5 +}; + +static const unsigned char P256_N[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, + 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, + 0x25, 0x51 +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = sizeof P256_G; + return P256_G; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = sizeof P256_N; + return P256_N; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 1; +} + +/* + * A field element is encoded as five 64-bit integers, in basis 2^52. + * Limbs may occasionally exceed 2^52. + * + * A _partially reduced_ value is such that the following hold: + * - top limb is less than 2^48 + 2^30 + * - the other limbs fit on 53 bits each + * In particular, such a value is less than twice the modulus p. + */ + +#define BIT(n) ((uint64_t)1 << (n)) +#define MASK48 (BIT(48) - BIT(0)) +#define MASK52 (BIT(52) - BIT(0)) + +/* R = 2^260 mod p */ +static const uint64_t F256_R[] = { + 0x0000000000010, 0xF000000000000, 0xFFFFFFFFFFFFF, + 0xFFEFFFFFFFFFF, 0x00000000FFFFF +}; + +/* Curve equation is y^2 = x^3 - 3*x + B. This constant is B*R mod p + (Montgomery representation of B). */ +static const uint64_t P256_B_MONTY[] = { + 0xDF6229C4BDDFD, 0xCA8843090D89C, 0x212ED6ACF005C, + 0x83415A220ABF7, 0x0C30061DD4874 +}; + +/* + * Addition in the field. Carry propagation is not performed. + * On input, limbs may be up to 63 bits each; on output, they will + * be up to one bit more than on input. + */ +static inline void +f256_add(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ + d[0] = a[0] + b[0]; + d[1] = a[1] + b[1]; + d[2] = a[2] + b[2]; + d[3] = a[3] + b[3]; + d[4] = a[4] + b[4]; +} + +/* + * Partially reduce the provided value. + * Input: limbs can go up to 61 bits each. + * Output: partially reduced. + */ +static inline void +f256_partial_reduce(uint64_t *a) +{ + uint64_t w, cc, s; + + /* + * Propagate carries. + */ + w = a[0]; + a[0] = w & MASK52; + cc = w >> 52; + w = a[1] + cc; + a[1] = w & MASK52; + cc = w >> 52; + w = a[2] + cc; + a[2] = w & MASK52; + cc = w >> 52; + w = a[3] + cc; + a[3] = w & MASK52; + cc = w >> 52; + a[4] += cc; + + s = a[4] >> 48; /* s < 2^14 */ + a[0] += s; /* a[0] < 2^52 + 2^14 */ + w = a[1] - (s << 44); + a[1] = w & MASK52; /* a[1] < 2^52 */ + cc = -(w >> 52) & 0xFFF; /* cc < 16 */ + w = a[2] - cc; + a[2] = w & MASK52; /* a[2] < 2^52 */ + cc = w >> 63; /* cc = 0 or 1 */ + w = a[3] - cc - (s << 36); + a[3] = w & MASK52; /* a[3] < 2^52 */ + cc = w >> 63; /* cc = 0 or 1 */ + w = a[4] & MASK48; + a[4] = w + (s << 16) - cc; /* a[4] < 2^48 + 2^30 */ +} + +/* + * Subtraction in the field. + * Input: limbs must fit on 60 bits each; in particular, the complete + * integer will be less than 2^268 + 2^217. + * Output: partially reduced. + */ +static inline void +f256_sub(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ + uint64_t t[5], w, s, cc; + + /* + * We compute d = 2^13*p + a - b; this ensures a positive + * intermediate value. + * + * Each individual addition/subtraction may yield a positive or + * negative result; thus, we need to handle a signed carry, thus + * with sign extension. We prefer not to use signed types (int64_t) + * because conversion from unsigned to signed is cumbersome (a + * direct cast with the top bit set is undefined behavior; instead, + * we have to use pointer aliasing, using the guaranteed properties + * of exact-width types, but this requires the compiler to optimize + * away the writes and reads from RAM), and right-shifting a + * signed negative value is implementation-defined. Therefore, + * we use a custom sign extension. + */ + + w = a[0] - b[0] - BIT(13); + t[0] = w & MASK52; + cc = w >> 52; + cc |= -(cc & BIT(11)); + w = a[1] - b[1] + cc; + t[1] = w & MASK52; + cc = w >> 52; + cc |= -(cc & BIT(11)); + w = a[2] - b[2] + cc; + t[2] = (w & MASK52) + BIT(5); + cc = w >> 52; + cc |= -(cc & BIT(11)); + w = a[3] - b[3] + cc; + t[3] = (w & MASK52) + BIT(49); + cc = w >> 52; + cc |= -(cc & BIT(11)); + t[4] = (BIT(61) - BIT(29)) + a[4] - b[4] + cc; + + /* + * Perform partial reduction. Rule is: + * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p + * + * At that point: + * 0 <= t[0] <= 2^52 - 1 + * 0 <= t[1] <= 2^52 - 1 + * 2^5 <= t[2] <= 2^52 + 2^5 - 1 + * 2^49 <= t[3] <= 2^52 + 2^49 - 1 + * 2^59 < t[4] <= 2^61 + 2^60 - 2^29 + * + * Thus, the value 's' (t[4] / 2^48) will be necessarily + * greater than 2048, and less than 12288. + */ + s = t[4] >> 48; + + d[0] = t[0] + s; /* d[0] <= 2^52 + 12287 */ + w = t[1] - (s << 44); + d[1] = w & MASK52; /* d[1] <= 2^52 - 1 */ + cc = -(w >> 52) & 0xFFF; /* cc <= 48 */ + w = t[2] - cc; + cc = w >> 63; /* cc = 0 or 1 */ + d[2] = w + (cc << 52); /* d[2] <= 2^52 + 31 */ + w = t[3] - cc - (s << 36); + cc = w >> 63; /* cc = 0 or 1 */ + d[3] = w + (cc << 52); /* t[3] <= 2^52 + 2^49 - 1 */ + d[4] = (t[4] & MASK48) + (s << 16) - cc; /* d[4] < 2^48 + 2^30 */ + + /* + * If s = 0, then none of the limbs is modified, and there cannot + * be an overflow; if s != 0, then (s << 16) > cc, and there is + * no overflow either. + */ +} + +/* + * Montgomery multiplication in the field. + * Input: limbs must fit on 56 bits each. + * Output: partially reduced. + */ +static void +f256_montymul(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ +#if BR_INT128 + + int i; + uint64_t t[5]; + + t[0] = 0; + t[1] = 0; + t[2] = 0; + t[3] = 0; + t[4] = 0; + for (i = 0; i < 5; i ++) { + uint64_t x, f, cc, w, s; + unsigned __int128 z; + + /* + * Since limbs of a[] and b[] fit on 56 bits each, + * each individual product fits on 112 bits. Also, + * the factor f fits on 52 bits, so f<<48 fits on + * 112 bits too. This guarantees that carries (cc) + * will fit on 62 bits, thus no overflow. + * + * The operations below compute: + * t <- (t + x*b + f*p) / 2^64 + */ + x = a[i]; + z = (unsigned __int128)b[0] * (unsigned __int128)x + + (unsigned __int128)t[0]; + f = (uint64_t)z & MASK52; + cc = (uint64_t)(z >> 52); + z = (unsigned __int128)b[1] * (unsigned __int128)x + + (unsigned __int128)t[1] + cc + + ((unsigned __int128)f << 44); + t[0] = (uint64_t)z & MASK52; + cc = (uint64_t)(z >> 52); + z = (unsigned __int128)b[2] * (unsigned __int128)x + + (unsigned __int128)t[2] + cc; + t[1] = (uint64_t)z & MASK52; + cc = (uint64_t)(z >> 52); + z = (unsigned __int128)b[3] * (unsigned __int128)x + + (unsigned __int128)t[3] + cc + + ((unsigned __int128)f << 36); + t[2] = (uint64_t)z & MASK52; + cc = (uint64_t)(z >> 52); + z = (unsigned __int128)b[4] * (unsigned __int128)x + + (unsigned __int128)t[4] + cc + + ((unsigned __int128)f << 48) + - ((unsigned __int128)f << 16); + t[3] = (uint64_t)z & MASK52; + t[4] = (uint64_t)(z >> 52); + + /* + * t[4] may be up to 62 bits here; we need to do a + * partial reduction. Note that limbs t[0] to t[3] + * fit on 52 bits each. + */ + s = t[4] >> 48; /* s < 2^14 */ + t[0] += s; /* t[0] < 2^52 + 2^14 */ + w = t[1] - (s << 44); + t[1] = w & MASK52; /* t[1] < 2^52 */ + cc = -(w >> 52) & 0xFFF; /* cc < 16 */ + w = t[2] - cc; + t[2] = w & MASK52; /* t[2] < 2^52 */ + cc = w >> 63; /* cc = 0 or 1 */ + w = t[3] - cc - (s << 36); + t[3] = w & MASK52; /* t[3] < 2^52 */ + cc = w >> 63; /* cc = 0 or 1 */ + w = t[4] & MASK48; + t[4] = w + (s << 16) - cc; /* t[4] < 2^48 + 2^30 */ + + /* + * The final t[4] cannot overflow because cc is 0 or 1, + * and cc can be 1 only if s != 0. + */ + } + + d[0] = t[0]; + d[1] = t[1]; + d[2] = t[2]; + d[3] = t[3]; + d[4] = t[4]; + +#elif BR_UMUL128 + + int i; + uint64_t t[5]; + + t[0] = 0; + t[1] = 0; + t[2] = 0; + t[3] = 0; + t[4] = 0; + for (i = 0; i < 5; i ++) { + uint64_t x, f, cc, w, s, zh, zl; + unsigned char k; + + /* + * Since limbs of a[] and b[] fit on 56 bits each, + * each individual product fits on 112 bits. Also, + * the factor f fits on 52 bits, so f<<48 fits on + * 112 bits too. This guarantees that carries (cc) + * will fit on 62 bits, thus no overflow. + * + * The operations below compute: + * t <- (t + x*b + f*p) / 2^64 + */ + x = a[i]; + zl = _umul128(b[0], x, &zh); + k = _addcarry_u64(0, t[0], zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + f = zl & MASK52; + cc = (zl >> 52) | (zh << 12); + + zl = _umul128(b[1], x, &zh); + k = _addcarry_u64(0, t[1], zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + k = _addcarry_u64(0, cc, zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + k = _addcarry_u64(0, f << 44, zl, &zl); + (void)_addcarry_u64(k, f >> 20, zh, &zh); + t[0] = zl & MASK52; + cc = (zl >> 52) | (zh << 12); + + zl = _umul128(b[2], x, &zh); + k = _addcarry_u64(0, t[2], zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + k = _addcarry_u64(0, cc, zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + t[1] = zl & MASK52; + cc = (zl >> 52) | (zh << 12); + + zl = _umul128(b[3], x, &zh); + k = _addcarry_u64(0, t[3], zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + k = _addcarry_u64(0, cc, zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + k = _addcarry_u64(0, f << 36, zl, &zl); + (void)_addcarry_u64(k, f >> 28, zh, &zh); + t[2] = zl & MASK52; + cc = (zl >> 52) | (zh << 12); + + zl = _umul128(b[4], x, &zh); + k = _addcarry_u64(0, t[4], zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + k = _addcarry_u64(0, cc, zl, &zl); + (void)_addcarry_u64(k, 0, zh, &zh); + k = _addcarry_u64(0, f << 48, zl, &zl); + (void)_addcarry_u64(k, f >> 16, zh, &zh); + k = _subborrow_u64(0, zl, f << 16, &zl); + (void)_subborrow_u64(k, zh, f >> 48, &zh); + t[3] = zl & MASK52; + t[4] = (zl >> 52) | (zh << 12); + + /* + * t[4] may be up to 62 bits here; we need to do a + * partial reduction. Note that limbs t[0] to t[3] + * fit on 52 bits each. + */ + s = t[4] >> 48; /* s < 2^14 */ + t[0] += s; /* t[0] < 2^52 + 2^14 */ + w = t[1] - (s << 44); + t[1] = w & MASK52; /* t[1] < 2^52 */ + cc = -(w >> 52) & 0xFFF; /* cc < 16 */ + w = t[2] - cc; + t[2] = w & MASK52; /* t[2] < 2^52 */ + cc = w >> 63; /* cc = 0 or 1 */ + w = t[3] - cc - (s << 36); + t[3] = w & MASK52; /* t[3] < 2^52 */ + cc = w >> 63; /* cc = 0 or 1 */ + w = t[4] & MASK48; + t[4] = w + (s << 16) - cc; /* t[4] < 2^48 + 2^30 */ + + /* + * The final t[4] cannot overflow because cc is 0 or 1, + * and cc can be 1 only if s != 0. + */ + } + + d[0] = t[0]; + d[1] = t[1]; + d[2] = t[2]; + d[3] = t[3]; + d[4] = t[4]; + +#endif +} + +/* + * Montgomery squaring in the field; currently a basic wrapper around + * multiplication (inline, should be optimized away). + * TODO: see if some extra speed can be gained here. + */ +static inline void +f256_montysquare(uint64_t *d, const uint64_t *a) +{ + f256_montymul(d, a, a); +} + +/* + * Convert to Montgomery representation. + */ +static void +f256_tomonty(uint64_t *d, const uint64_t *a) +{ + /* + * R2 = 2^520 mod p. + * If R = 2^260 mod p, then R2 = R^2 mod p; and the Montgomery + * multiplication of a by R2 is: a*R2/R = a*R mod p, i.e. the + * conversion to Montgomery representation. + */ + static const uint64_t R2[] = { + 0x0000000000300, 0xFFFFFFFF00000, 0xFFFFEFFFFFFFB, + 0xFDFFFFFFFFFFF, 0x0000004FFFFFF + }; + + f256_montymul(d, a, R2); +} + +/* + * Convert from Montgomery representation. + */ +static void +f256_frommonty(uint64_t *d, const uint64_t *a) +{ + /* + * Montgomery multiplication by 1 is division by 2^260 modulo p. + */ + static const uint64_t one[] = { 1, 0, 0, 0, 0 }; + + f256_montymul(d, a, one); +} + +/* + * Inversion in the field. If the source value is 0 modulo p, then this + * returns 0 or p. This function uses Montgomery representation. + */ +static void +f256_invert(uint64_t *d, const uint64_t *a) +{ + /* + * We compute a^(p-2) mod p. The exponent pattern (from high to + * low) is: + * - 32 bits of value 1 + * - 31 bits of value 0 + * - 1 bit of value 1 + * - 96 bits of value 0 + * - 94 bits of value 1 + * - 1 bit of value 0 + * - 1 bit of value 1 + * To speed up the square-and-multiply algorithm, we precompute + * a^(2^31-1). + */ + + uint64_t r[5], t[5]; + int i; + + memcpy(t, a, sizeof t); + for (i = 0; i < 30; i ++) { + f256_montysquare(t, t); + f256_montymul(t, t, a); + } + + memcpy(r, t, sizeof t); + for (i = 224; i >= 0; i --) { + f256_montysquare(r, r); + switch (i) { + case 0: + case 2: + case 192: + case 224: + f256_montymul(r, r, a); + break; + case 3: + case 34: + case 65: + f256_montymul(r, r, t); + break; + } + } + memcpy(d, r, sizeof r); +} + +/* + * Finalize reduction. + * Input value should be partially reduced. + * On output, limbs a[0] to a[3] fit on 52 bits each, limb a[4] fits + * on 48 bits, and the integer is less than p. + */ +static inline void +f256_final_reduce(uint64_t *a) +{ + uint64_t r[5], t[5], w, cc; + int i; + + /* + * Propagate carries to ensure that limbs 0 to 3 fit on 52 bits. + */ + cc = 0; + for (i = 0; i < 5; i ++) { + w = a[i] + cc; + r[i] = w & MASK52; + cc = w >> 52; + } + + /* + * We compute t = r + (2^256 - p) = r + 2^224 - 2^192 - 2^96 + 1. + * If t < 2^256, then r < p, and we return r. Otherwise, we + * want to return r - p = t - 2^256. + */ + + /* + * Add 2^224 + 1, and propagate carries to ensure that limbs + * t[0] to t[3] fit in 52 bits each. + */ + w = r[0] + 1; + t[0] = w & MASK52; + cc = w >> 52; + w = r[1] + cc; + t[1] = w & MASK52; + cc = w >> 52; + w = r[2] + cc; + t[2] = w & MASK52; + cc = w >> 52; + w = r[3] + cc; + t[3] = w & MASK52; + cc = w >> 52; + t[4] = r[4] + cc + BIT(16); + + /* + * Subtract 2^192 + 2^96. Since we just added 2^224 + 1, the + * result cannot be negative. + */ + w = t[1] - BIT(44); + t[1] = w & MASK52; + cc = w >> 63; + w = t[2] - cc; + t[2] = w & MASK52; + cc = w >> 63; + w = t[3] - BIT(36) - cc; + t[3] = w & MASK52; + cc = w >> 63; + t[4] -= cc; + + /* + * If the top limb t[4] fits on 48 bits, then r[] is already + * in the proper range. Otherwise, t[] is the value to return + * (truncated to 256 bits). + */ + cc = -(t[4] >> 48); + t[4] &= MASK48; + for (i = 0; i < 5; i ++) { + a[i] = r[i] ^ (cc & (r[i] ^ t[i])); + } +} + +/* + * Points in affine and Jacobian coordinates. + * + * - In affine coordinates, the point-at-infinity cannot be encoded. + * - Jacobian coordinates (X,Y,Z) correspond to affine (X/Z^2,Y/Z^3); + * if Z = 0 then this is the point-at-infinity. + */ +typedef struct { + uint64_t x[5]; + uint64_t y[5]; +} p256_affine; + +typedef struct { + uint64_t x[5]; + uint64_t y[5]; + uint64_t z[5]; +} p256_jacobian; + +/* + * Decode a field element (unsigned big endian notation). + */ +static void +f256_decode(uint64_t *a, const unsigned char *buf) +{ + uint64_t w0, w1, w2, w3; + + w3 = br_dec64be(buf + 0); + w2 = br_dec64be(buf + 8); + w1 = br_dec64be(buf + 16); + w0 = br_dec64be(buf + 24); + a[0] = w0 & MASK52; + a[1] = ((w0 >> 52) | (w1 << 12)) & MASK52; + a[2] = ((w1 >> 40) | (w2 << 24)) & MASK52; + a[3] = ((w2 >> 28) | (w3 << 36)) & MASK52; + a[4] = w3 >> 16; +} + +/* + * Encode a field element (unsigned big endian notation). The field + * element MUST be fully reduced. + */ +static void +f256_encode(unsigned char *buf, const uint64_t *a) +{ + uint64_t w0, w1, w2, w3; + + w0 = a[0] | (a[1] << 52); + w1 = (a[1] >> 12) | (a[2] << 40); + w2 = (a[2] >> 24) | (a[3] << 28); + w3 = (a[3] >> 36) | (a[4] << 16); + br_enc64be(buf + 0, w3); + br_enc64be(buf + 8, w2); + br_enc64be(buf + 16, w1); + br_enc64be(buf + 24, w0); +} + +/* + * Decode a point. The returned point is in Jacobian coordinates, but + * with z = 1. If the encoding is invalid, or encodes a point which is + * not on the curve, or encodes the point at infinity, then this function + * returns 0. Otherwise, 1 is returned. + * + * The buffer is assumed to have length exactly 65 bytes. + */ +static uint32_t +point_decode(p256_jacobian *P, const unsigned char *buf) +{ + uint64_t x[5], y[5], t[5], x3[5], tt; + uint32_t r; + + /* + * Header byte shall be 0x04. + */ + r = EQ(buf[0], 0x04); + + /* + * Decode X and Y coordinates, and convert them into + * Montgomery representation. + */ + f256_decode(x, buf + 1); + f256_decode(y, buf + 33); + f256_tomonty(x, x); + f256_tomonty(y, y); + + /* + * Verify y^2 = x^3 + A*x + B. In curve P-256, A = -3. + * Note that the Montgomery representation of 0 is 0. We must + * take care to apply the final reduction to make sure we have + * 0 and not p. + */ + f256_montysquare(t, y); + f256_montysquare(x3, x); + f256_montymul(x3, x3, x); + f256_sub(t, t, x3); + f256_add(t, t, x); + f256_add(t, t, x); + f256_add(t, t, x); + f256_sub(t, t, P256_B_MONTY); + f256_final_reduce(t); + tt = t[0] | t[1] | t[2] | t[3] | t[4]; + r &= EQ((uint32_t)(tt | (tt >> 32)), 0); + + /* + * Return the point in Jacobian coordinates (and Montgomery + * representation). + */ + memcpy(P->x, x, sizeof x); + memcpy(P->y, y, sizeof y); + memcpy(P->z, F256_R, sizeof F256_R); + return r; +} + +/* + * Final conversion for a point: + * - The point is converted back to affine coordinates. + * - Final reduction is performed. + * - The point is encoded into the provided buffer. + * + * If the point is the point-at-infinity, all operations are performed, + * but the buffer contents are indeterminate, and 0 is returned. Otherwise, + * the encoded point is written in the buffer, and 1 is returned. + */ +static uint32_t +point_encode(unsigned char *buf, const p256_jacobian *P) +{ + uint64_t t1[5], t2[5], z; + + /* Set t1 = 1/z^2 and t2 = 1/z^3. */ + f256_invert(t2, P->z); + f256_montysquare(t1, t2); + f256_montymul(t2, t2, t1); + + /* Compute affine coordinates x (in t1) and y (in t2). */ + f256_montymul(t1, P->x, t1); + f256_montymul(t2, P->y, t2); + + /* Convert back from Montgomery representation, and finalize + reductions. */ + f256_frommonty(t1, t1); + f256_frommonty(t2, t2); + f256_final_reduce(t1); + f256_final_reduce(t2); + + /* Encode. */ + buf[0] = 0x04; + f256_encode(buf + 1, t1); + f256_encode(buf + 33, t2); + + /* Return success if and only if P->z != 0. */ + z = P->z[0] | P->z[1] | P->z[2] | P->z[3] | P->z[4]; + return NEQ((uint32_t)(z | z >> 32), 0); +} + +/* + * Point doubling in Jacobian coordinates: point P is doubled. + * Note: if the source point is the point-at-infinity, then the result is + * still the point-at-infinity, which is correct. Moreover, if the three + * coordinates were zero, then they still are zero in the returned value. + */ +static void +p256_double(p256_jacobian *P) +{ + /* + * Doubling formulas are: + * + * s = 4*x*y^2 + * m = 3*(x + z^2)*(x - z^2) + * x' = m^2 - 2*s + * y' = m*(s - x') - 8*y^4 + * z' = 2*y*z + * + * These formulas work for all points, including points of order 2 + * and points at infinity: + * - If y = 0 then z' = 0. But there is no such point in P-256 + * anyway. + * - If z = 0 then z' = 0. + */ + uint64_t t1[5], t2[5], t3[5], t4[5]; + + /* + * Compute z^2 in t1. + */ + f256_montysquare(t1, P->z); + + /* + * Compute x-z^2 in t2 and x+z^2 in t1. + */ + f256_add(t2, P->x, t1); + f256_sub(t1, P->x, t1); + + /* + * Compute 3*(x+z^2)*(x-z^2) in t1. + */ + f256_montymul(t3, t1, t2); + f256_add(t1, t3, t3); + f256_add(t1, t3, t1); + + /* + * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3). + */ + f256_montysquare(t3, P->y); + f256_add(t3, t3, t3); + f256_montymul(t2, P->x, t3); + f256_add(t2, t2, t2); + + /* + * Compute x' = m^2 - 2*s. + */ + f256_montysquare(P->x, t1); + f256_sub(P->x, P->x, t2); + f256_sub(P->x, P->x, t2); + + /* + * Compute z' = 2*y*z. + */ + f256_montymul(t4, P->y, P->z); + f256_add(P->z, t4, t4); + f256_partial_reduce(P->z); + + /* + * Compute y' = m*(s - x') - 8*y^4. Note that we already have + * 2*y^2 in t3. + */ + f256_sub(t2, t2, P->x); + f256_montymul(P->y, t1, t2); + f256_montysquare(t4, t3); + f256_add(t4, t4, t4); + f256_sub(P->y, P->y, t4); +} + +/* + * Point addition (Jacobian coordinates): P1 is replaced with P1+P2. + * This function computes the wrong result in the following cases: + * + * - If P1 == 0 but P2 != 0 + * - If P1 != 0 but P2 == 0 + * - If P1 == P2 + * + * In all three cases, P1 is set to the point at infinity. + * + * Returned value is 0 if one of the following occurs: + * + * - P1 and P2 have the same Y coordinate. + * - P1 == 0 and P2 == 0. + * - The Y coordinate of one of the points is 0 and the other point is + * the point at infinity. + * + * The third case cannot actually happen with valid points, since a point + * with Y == 0 is a point of order 2, and there is no point of order 2 on + * curve P-256. + * + * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller + * can apply the following: + * + * - If the result is not the point at infinity, then it is correct. + * - Otherwise, if the returned value is 1, then this is a case of + * P1+P2 == 0, so the result is indeed the point at infinity. + * - Otherwise, P1 == P2, so a "double" operation should have been + * performed. + * + * Note that you can get a returned value of 0 with a correct result, + * e.g. if P1 and P2 have the same Y coordinate, but distinct X coordinates. + */ +static uint32_t +p256_add(p256_jacobian *P1, const p256_jacobian *P2) +{ + /* + * Addtions formulas are: + * + * u1 = x1 * z2^2 + * u2 = x2 * z1^2 + * s1 = y1 * z2^3 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 * z2 + */ + uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt; + uint32_t ret; + + /* + * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). + */ + f256_montysquare(t3, P2->z); + f256_montymul(t1, P1->x, t3); + f256_montymul(t4, P2->z, t3); + f256_montymul(t3, P1->y, t4); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + f256_montysquare(t4, P1->z); + f256_montymul(t2, P2->x, t4); + f256_montymul(t5, P1->z, t4); + f256_montymul(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * We need to test whether r is zero, so we will do some extra + * reduce. + */ + f256_sub(t2, t2, t1); + f256_sub(t4, t4, t3); + f256_final_reduce(t4); + tt = t4[0] | t4[1] | t4[2] | t4[3] | t4[4]; + ret = (uint32_t)(tt | (tt >> 32)); + ret = (ret | -ret) >> 31; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + f256_montysquare(t7, t2); + f256_montymul(t6, t1, t7); + f256_montymul(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + f256_montysquare(P1->x, t4); + f256_sub(P1->x, P1->x, t5); + f256_sub(P1->x, P1->x, t6); + f256_sub(P1->x, P1->x, t6); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + f256_sub(t6, t6, P1->x); + f256_montymul(P1->y, t4, t6); + f256_montymul(t1, t5, t3); + f256_sub(P1->y, P1->y, t1); + + /* + * Compute z3 = h*z1*z2. + */ + f256_montymul(t1, P1->z, P2->z); + f256_montymul(P1->z, t1, t2); + + return ret; +} + +/* + * Point addition (mixed coordinates): P1 is replaced with P1+P2. + * This is a specialised function for the case when P2 is a non-zero point + * in affine coordinates. + * + * This function computes the wrong result in the following cases: + * + * - If P1 == 0 + * - If P1 == P2 + * + * In both cases, P1 is set to the point at infinity. + * + * Returned value is 0 if one of the following occurs: + * + * - P1 and P2 have the same Y (affine) coordinate. + * - The Y coordinate of P2 is 0 and P1 is the point at infinity. + * + * The second case cannot actually happen with valid points, since a point + * with Y == 0 is a point of order 2, and there is no point of order 2 on + * curve P-256. + * + * Therefore, assuming that P1 != 0 on input, then the caller + * can apply the following: + * + * - If the result is not the point at infinity, then it is correct. + * - Otherwise, if the returned value is 1, then this is a case of + * P1+P2 == 0, so the result is indeed the point at infinity. + * - Otherwise, P1 == P2, so a "double" operation should have been + * performed. + * + * Again, a value of 0 may be returned in some cases where the addition + * result is correct. + */ +static uint32_t +p256_add_mixed(p256_jacobian *P1, const p256_affine *P2) +{ + /* + * Addtions formulas are: + * + * u1 = x1 + * u2 = x2 * z1^2 + * s1 = y1 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 + */ + uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt; + uint32_t ret; + + /* + * Compute u1 = x1 (in t1) and s1 = y1 (in t3). + */ + memcpy(t1, P1->x, sizeof t1); + memcpy(t3, P1->y, sizeof t3); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + f256_montysquare(t4, P1->z); + f256_montymul(t2, P2->x, t4); + f256_montymul(t5, P1->z, t4); + f256_montymul(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * We need to test whether r is zero, so we will do some extra + * reduce. + */ + f256_sub(t2, t2, t1); + f256_sub(t4, t4, t3); + f256_final_reduce(t4); + tt = t4[0] | t4[1] | t4[2] | t4[3] | t4[4]; + ret = (uint32_t)(tt | (tt >> 32)); + ret = (ret | -ret) >> 31; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + f256_montysquare(t7, t2); + f256_montymul(t6, t1, t7); + f256_montymul(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + f256_montysquare(P1->x, t4); + f256_sub(P1->x, P1->x, t5); + f256_sub(P1->x, P1->x, t6); + f256_sub(P1->x, P1->x, t6); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + f256_sub(t6, t6, P1->x); + f256_montymul(P1->y, t4, t6); + f256_montymul(t1, t5, t3); + f256_sub(P1->y, P1->y, t1); + + /* + * Compute z3 = h*z1*z2. + */ + f256_montymul(P1->z, P1->z, t2); + + return ret; +} + +#if 0 +/* unused */ +/* + * Point addition (mixed coordinates, complete): P1 is replaced with P1+P2. + * This is a specialised function for the case when P2 is a non-zero point + * in affine coordinates. + * + * This function returns the correct result in all cases. + */ +static uint32_t +p256_add_complete_mixed(p256_jacobian *P1, const p256_affine *P2) +{ + /* + * Addtions formulas, in the general case, are: + * + * u1 = x1 + * u2 = x2 * z1^2 + * s1 = y1 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 + * + * These formulas mishandle the two following cases: + * + * - If P1 is the point-at-infinity (z1 = 0), then z3 is + * incorrectly set to 0. + * + * - If P1 = P2, then u1 = u2 and s1 = s2, and x3, y3 and z3 + * are all set to 0. + * + * However, if P1 + P2 = 0, then u1 = u2 but s1 != s2, and then + * we correctly get z3 = 0 (the point-at-infinity). + * + * To fix the case P1 = 0, we perform at the end a copy of P2 + * over P1, conditional to z1 = 0. + * + * For P1 = P2: in that case, both h and r are set to 0, and + * we get x3, y3 and z3 equal to 0. We can test for that + * occurrence to make a mask which will be all-one if P1 = P2, + * or all-zero otherwise; then we can compute the double of P2 + * and add it, combined with the mask, to (x3,y3,z3). + * + * Using the doubling formulas in p256_double() on (x2,y2), + * simplifying since P2 is affine (i.e. z2 = 1, implicitly), + * we get: + * s = 4*x2*y2^2 + * m = 3*(x2 + 1)*(x2 - 1) + * x' = m^2 - 2*s + * y' = m*(s - x') - 8*y2^4 + * z' = 2*y2 + * which requires only 6 multiplications. Added to the 11 + * multiplications of the normal mixed addition in Jacobian + * coordinates, we get a cost of 17 multiplications in total. + */ + uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt, zz; + int i; + + /* + * Set zz to -1 if P1 is the point at infinity, 0 otherwise. + */ + zz = P1->z[0] | P1->z[1] | P1->z[2] | P1->z[3] | P1->z[4]; + zz = ((zz | -zz) >> 63) - (uint64_t)1; + + /* + * Compute u1 = x1 (in t1) and s1 = y1 (in t3). + */ + memcpy(t1, P1->x, sizeof t1); + memcpy(t3, P1->y, sizeof t3); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + f256_montysquare(t4, P1->z); + f256_montymul(t2, P2->x, t4); + f256_montymul(t5, P1->z, t4); + f256_montymul(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * reduce. + */ + f256_sub(t2, t2, t1); + f256_sub(t4, t4, t3); + + /* + * If both h = 0 and r = 0, then P1 = P2, and we want to set + * the mask tt to -1; otherwise, the mask will be 0. + */ + f256_final_reduce(t2); + f256_final_reduce(t4); + tt = t2[0] | t2[1] | t2[2] | t2[3] | t2[4] + | t4[0] | t4[1] | t4[2] | t4[3] | t4[4]; + tt = ((tt | -tt) >> 63) - (uint64_t)1; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + f256_montysquare(t7, t2); + f256_montymul(t6, t1, t7); + f256_montymul(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + f256_montysquare(P1->x, t4); + f256_sub(P1->x, P1->x, t5); + f256_sub(P1->x, P1->x, t6); + f256_sub(P1->x, P1->x, t6); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + f256_sub(t6, t6, P1->x); + f256_montymul(P1->y, t4, t6); + f256_montymul(t1, t5, t3); + f256_sub(P1->y, P1->y, t1); + + /* + * Compute z3 = h*z1. + */ + f256_montymul(P1->z, P1->z, t2); + + /* + * The "double" result, in case P1 = P2. + */ + + /* + * Compute z' = 2*y2 (in t1). + */ + f256_add(t1, P2->y, P2->y); + f256_partial_reduce(t1); + + /* + * Compute 2*(y2^2) (in t2) and s = 4*x2*(y2^2) (in t3). + */ + f256_montysquare(t2, P2->y); + f256_add(t2, t2, t2); + f256_add(t3, t2, t2); + f256_montymul(t3, P2->x, t3); + + /* + * Compute m = 3*(x2^2 - 1) (in t4). + */ + f256_montysquare(t4, P2->x); + f256_sub(t4, t4, F256_R); + f256_add(t5, t4, t4); + f256_add(t4, t4, t5); + + /* + * Compute x' = m^2 - 2*s (in t5). + */ + f256_montysquare(t5, t4); + f256_sub(t5, t3); + f256_sub(t5, t3); + + /* + * Compute y' = m*(s - x') - 8*y2^4 (in t6). + */ + f256_sub(t6, t3, t5); + f256_montymul(t6, t6, t4); + f256_montysquare(t7, t2); + f256_sub(t6, t6, t7); + f256_sub(t6, t6, t7); + + /* + * We now have the alternate (doubling) coordinates in (t5,t6,t1). + * We combine them with (x3,y3,z3). + */ + for (i = 0; i < 5; i ++) { + P1->x[i] |= tt & t5[i]; + P1->y[i] |= tt & t6[i]; + P1->z[i] |= tt & t1[i]; + } + + /* + * If P1 = 0, then we get z3 = 0 (which is invalid); if z1 is 0, + * then we want to replace the result with a copy of P2. The + * test on z1 was done at the start, in the zz mask. + */ + for (i = 0; i < 5; i ++) { + P1->x[i] ^= zz & (P1->x[i] ^ P2->x[i]); + P1->y[i] ^= zz & (P1->y[i] ^ P2->y[i]); + P1->z[i] ^= zz & (P1->z[i] ^ F256_R[i]); + } +} +#endif + +/* + * Inner function for computing a point multiplication. A window is + * provided, with points 1*P to 15*P in affine coordinates. + * + * Assumptions: + * - All provided points are valid points on the curve. + * - Multiplier is non-zero, and smaller than the curve order. + * - Everything is in Montgomery representation. + */ +static void +point_mul_inner(p256_jacobian *R, const p256_affine *W, + const unsigned char *k, size_t klen) +{ + p256_jacobian Q; + uint32_t qz; + + memset(&Q, 0, sizeof Q); + qz = 1; + while (klen -- > 0) { + int i; + unsigned bk; + + bk = *k ++; + for (i = 0; i < 2; i ++) { + uint32_t bits; + uint32_t bnz; + p256_affine T; + p256_jacobian U; + uint32_t n; + int j; + uint64_t m; + + p256_double(&Q); + p256_double(&Q); + p256_double(&Q); + p256_double(&Q); + bits = (bk >> 4) & 0x0F; + bnz = NEQ(bits, 0); + + /* + * Lookup point in window. If the bits are 0, + * we get something invalid, which is not a + * problem because we will use it only if the + * bits are non-zero. + */ + memset(&T, 0, sizeof T); + for (n = 0; n < 15; n ++) { + m = -(uint64_t)EQ(bits, n + 1); + T.x[0] |= m & W[n].x[0]; + T.x[1] |= m & W[n].x[1]; + T.x[2] |= m & W[n].x[2]; + T.x[3] |= m & W[n].x[3]; + T.x[4] |= m & W[n].x[4]; + T.y[0] |= m & W[n].y[0]; + T.y[1] |= m & W[n].y[1]; + T.y[2] |= m & W[n].y[2]; + T.y[3] |= m & W[n].y[3]; + T.y[4] |= m & W[n].y[4]; + } + + U = Q; + p256_add_mixed(&U, &T); + + /* + * If qz is still 1, then Q was all-zeros, and this + * is conserved through p256_double(). + */ + m = -(uint64_t)(bnz & qz); + for (j = 0; j < 5; j ++) { + Q.x[j] ^= m & (Q.x[j] ^ T.x[j]); + Q.y[j] ^= m & (Q.y[j] ^ T.y[j]); + Q.z[j] ^= m & (Q.z[j] ^ F256_R[j]); + } + CCOPY(bnz & ~qz, &Q, &U, sizeof Q); + qz &= ~bnz; + bk <<= 4; + } + } + *R = Q; +} + +/* + * Convert a window from Jacobian to affine coordinates. A single + * field inversion is used. This function works for windows up to + * 32 elements. + * + * The destination array (aff[]) and the source array (jac[]) may + * overlap, provided that the start of aff[] is not after the start of + * jac[]. Even if the arrays do _not_ overlap, the source array is + * modified. + */ +static void +window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) +{ + /* + * Convert the window points to affine coordinates. We use the + * following trick to mutualize the inversion computation: if + * we have z1, z2, z3, and z4, and want to invert all of them, + * we compute u = 1/(z1*z2*z3*z4), and then we have: + * 1/z1 = u*z2*z3*z4 + * 1/z2 = u*z1*z3*z4 + * 1/z3 = u*z1*z2*z4 + * 1/z4 = u*z1*z2*z3 + * + * The partial products are computed recursively: + * + * - on input (z_1,z_2), return (z_2,z_1) and z_1*z_2 + * - on input (z_1,z_2,... z_n): + * recurse on (z_1,z_2,... z_(n/2)) -> r1 and m1 + * recurse on (z_(n/2+1),z_(n/2+2)... z_n) -> r2 and m2 + * multiply elements of r1 by m2 -> s1 + * multiply elements of r2 by m1 -> s2 + * return r1||r2 and m1*m2 + * + * In the example below, we suppose that we have 14 elements. + * Let z1, z2,... zE be the 14 values to invert (index noted in + * hexadecimal, starting at 1). + * + * - Depth 1: + * swap(z1, z2); z12 = z1*z2 + * swap(z3, z4); z34 = z3*z4 + * swap(z5, z6); z56 = z5*z6 + * swap(z7, z8); z78 = z7*z8 + * swap(z9, zA); z9A = z9*zA + * swap(zB, zC); zBC = zB*zC + * swap(zD, zE); zDE = zD*zE + * + * - Depth 2: + * z1 <- z1*z34, z2 <- z2*z34, z3 <- z3*z12, z4 <- z4*z12 + * z1234 = z12*z34 + * z5 <- z5*z78, z6 <- z6*z78, z7 <- z7*z56, z8 <- z8*z56 + * z5678 = z56*z78 + * z9 <- z9*zBC, zA <- zA*zBC, zB <- zB*z9A, zC <- zC*z9A + * z9ABC = z9A*zBC + * + * - Depth 3: + * z1 <- z1*z5678, z2 <- z2*z5678, z3 <- z3*z5678, z4 <- z4*z5678 + * z5 <- z5*z1234, z6 <- z6*z1234, z7 <- z7*z1234, z8 <- z8*z1234 + * z12345678 = z1234*z5678 + * z9 <- z9*zDE, zA <- zA*zDE, zB <- zB*zDE, zC <- zC*zDE + * zD <- zD*z9ABC, zE*z9ABC + * z9ABCDE = z9ABC*zDE + * + * - Depth 4: + * multiply z1..z8 by z9ABCDE + * multiply z9..zE by z12345678 + * final z = z12345678*z9ABCDE + */ + + uint64_t z[16][5]; + int i, k, s; +#define zt (z[15]) +#define zu (z[14]) +#define zv (z[13]) + + /* + * First recursion step (pairwise swapping and multiplication). + * If there is an odd number of elements, then we "invent" an + * extra one with coordinate Z = 1 (in Montgomery representation). + */ + for (i = 0; (i + 1) < num; i += 2) { + memcpy(zt, jac[i].z, sizeof zt); + memcpy(jac[i].z, jac[i + 1].z, sizeof zt); + memcpy(jac[i + 1].z, zt, sizeof zt); + f256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z); + } + if ((num & 1) != 0) { + memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); + memcpy(jac[num - 1].z, F256_R, sizeof F256_R); + } + + /* + * Perform further recursion steps. At the entry of each step, + * the process has been done for groups of 's' points. The + * integer k is the log2 of s. + */ + for (k = 1, s = 2; s < num; k ++, s <<= 1) { + int n; + + for (i = 0; i < num; i ++) { + f256_montymul(jac[i].z, jac[i].z, z[(i >> k) ^ 1]); + } + n = (num + s - 1) >> k; + for (i = 0; i < (n >> 1); i ++) { + f256_montymul(z[i], z[i << 1], z[(i << 1) + 1]); + } + if ((n & 1) != 0) { + memmove(z[n >> 1], z[n], sizeof zt); + } + } + + /* + * Invert the final result, and convert all points. + */ + f256_invert(zt, z[0]); + for (i = 0; i < num; i ++) { + f256_montymul(zv, jac[i].z, zt); + f256_montysquare(zu, zv); + f256_montymul(zv, zv, zu); + f256_montymul(aff[i].x, jac[i].x, zu); + f256_montymul(aff[i].y, jac[i].y, zv); + } +} + +/* + * Multiply the provided point by an integer. + * Assumptions: + * - Source point is a valid curve point. + * - Source point is not the point-at-infinity. + * - Integer is not 0, and is lower than the curve order. + * If these conditions are not met, then the result is indeterminate + * (but the process is still constant-time). + */ +static void +p256_mul(p256_jacobian *P, const unsigned char *k, size_t klen) +{ + union { + p256_affine aff[15]; + p256_jacobian jac[15]; + } window; + int i; + + /* + * Compute window, in Jacobian coordinates. + */ + window.jac[0] = *P; + for (i = 2; i < 16; i ++) { + window.jac[i - 1] = window.jac[(i >> 1) - 1]; + if ((i & 1) == 0) { + p256_double(&window.jac[i - 1]); + } else { + p256_add(&window.jac[i - 1], &window.jac[i >> 1]); + } + } + + /* + * Convert the window points to affine coordinates. Point + * window[0] is the source point, already in affine coordinates. + */ + window_to_affine(window.aff, window.jac, 15); + + /* + * Perform point multiplication. + */ + point_mul_inner(P, window.aff, k, klen); +} + +/* + * Precomputed window for the conventional generator: P256_Gwin[n] + * contains (n+1)*G (affine coordinates, in Montgomery representation). + */ +static const p256_affine P256_Gwin[] = { + { + { 0x30D418A9143C1, 0xC4FEDB60179E7, 0x62251075BA95F, + 0x5C669FB732B77, 0x08905F76B5375 }, + { 0x5357CE95560A8, 0x43A19E45CDDF2, 0x21F3258B4AB8E, + 0xD8552E88688DD, 0x0571FF18A5885 } + }, + { + { 0x46D410DDD64DF, 0x0B433827D8500, 0x1490D9AA6AE3C, + 0xA3A832205038D, 0x06BB32E52DCF3 }, + { 0x48D361BEE1A57, 0xB7B236FF82F36, 0x042DBE152CD7C, + 0xA3AA9A8FB0E92, 0x08C577517A5B8 } + }, + { + { 0x3F904EEBC1272, 0x9E87D81FBFFAC, 0xCBBC98B027F84, + 0x47E46AD77DD87, 0x06936A3FD6FF7 }, + { 0x5C1FC983A7EBD, 0xC3861FE1AB04C, 0x2EE98E583E47A, + 0xC06A88208311A, 0x05F06A2AB587C } + }, + { + { 0xB50D46918DCC5, 0xD7623C17374B0, 0x100AF24650A6E, + 0x76ABCDAACACE8, 0x077362F591B01 }, + { 0xF24CE4CBABA68, 0x17AD6F4472D96, 0xDDD22E1762847, + 0x862EB6C36DEE5, 0x04B14C39CC5AB } + }, + { + { 0x8AAEC45C61F5C, 0x9D4B9537DBE1B, 0x76C20C90EC649, + 0x3C7D41CB5AAD0, 0x0907960649052 }, + { 0x9B4AE7BA4F107, 0xF75EB882BEB30, 0x7A1F6873C568E, + 0x915C540A9877E, 0x03A076BB9DD1E } + }, + { + { 0x47373E77664A1, 0xF246CEE3E4039, 0x17A3AD55AE744, + 0x673C50A961A5B, 0x03074B5964213 }, + { 0x6220D377E44BA, 0x30DFF14B593D3, 0x639F11299C2B5, + 0x75F5424D44CEF, 0x04C9916DEA07F } + }, + { + { 0x354EA0173B4F1, 0x3C23C00F70746, 0x23BB082BD2021, + 0xE03E43EAAB50C, 0x03BA5119D3123 }, + { 0xD0303F5B9D4DE, 0x17DA67BDD2847, 0xC941956742F2F, + 0x8670F933BDC77, 0x0AEDD9164E240 } + }, + { + { 0x4CD19499A78FB, 0x4BF9B345527F1, 0x2CFC6B462AB5C, + 0x30CDF90F02AF0, 0x0763891F62652 }, + { 0xA3A9532D49775, 0xD7F9EBA15F59D, 0x60BBF021E3327, + 0xF75C23C7B84BE, 0x06EC12F2C706D } + }, + { + { 0x6E8F264E20E8E, 0xC79A7A84175C9, 0xC8EB00ABE6BFE, + 0x16A4CC09C0444, 0x005B3081D0C4E }, + { 0x777AA45F33140, 0xDCE5D45E31EB7, 0xB12F1A56AF7BE, + 0xF9B2B6E019A88, 0x086659CDFD835 } + }, + { + { 0xDBD19DC21EC8C, 0x94FCF81392C18, 0x250B4998F9868, + 0x28EB37D2CD648, 0x0C61C947E4B34 }, + { 0x407880DD9E767, 0x0C83FBE080C2B, 0x9BE5D2C43A899, + 0xAB4EF7D2D6577, 0x08719A555B3B4 } + }, + { + { 0x260A6245E4043, 0x53E7FDFE0EA7D, 0xAC1AB59DE4079, + 0x072EFF3A4158D, 0x0E7090F1949C9 }, + { 0x85612B944E886, 0xE857F61C81A76, 0xAD643D250F939, + 0x88DAC0DAA891E, 0x089300244125B } + }, + { + { 0x1AA7D26977684, 0x58A345A3304B7, 0x37385EABDEDEF, + 0x155E409D29DEE, 0x0EE1DF780B83E }, + { 0x12D91CBB5B437, 0x65A8956370CAC, 0xDE6D66170ED2F, + 0xAC9B8228CFA8A, 0x0FF57C95C3238 } + }, + { + { 0x25634B2ED7097, 0x9156FD30DCCC4, 0x9E98110E35676, + 0x7594CBCD43F55, 0x038477ACC395B }, + { 0x2B90C00EE17FF, 0xF842ED2E33575, 0x1F5BC16874838, + 0x7968CD06422BD, 0x0BC0876AB9E7B } + }, + { + { 0xA35BB0CF664AF, 0x68F9707E3A242, 0x832660126E48F, + 0x72D2717BF54C6, 0x0AAE7333ED12C }, + { 0x2DB7995D586B1, 0xE732237C227B5, 0x65E7DBBE29569, + 0xBBBD8E4193E2A, 0x052706DC3EAA1 } + }, + { + { 0xD8B7BC60055BE, 0xD76E27E4B72BC, 0x81937003CC23E, + 0xA090E337424E4, 0x02AA0E43EAD3D }, + { 0x524F6383C45D2, 0x422A41B2540B8, 0x8A4797D766355, + 0xDF444EFA6DE77, 0x0042170A9079A } + }, +}; + +/* + * Multiply the conventional generator of the curve by the provided + * integer. Return is written in *P. + * + * Assumptions: + * - Integer is not 0, and is lower than the curve order. + * If this conditions is not met, then the result is indeterminate + * (but the process is still constant-time). + */ +static void +p256_mulgen(p256_jacobian *P, const unsigned char *k, size_t klen) +{ + point_mul_inner(P, P256_Gwin, k, klen); +} + +/* + * Return 1 if all of the following hold: + * - klen <= 32 + * - k != 0 + * - k is lower than the curve order + * Otherwise, return 0. + * + * Constant-time behaviour: only klen may be observable. + */ +static uint32_t +check_scalar(const unsigned char *k, size_t klen) +{ + uint32_t z; + int32_t c; + size_t u; + + if (klen > 32) { + return 0; + } + z = 0; + for (u = 0; u < klen; u ++) { + z |= k[u]; + } + if (klen == 32) { + c = 0; + for (u = 0; u < klen; u ++) { + c |= -(int32_t)EQ0(c) & CMP(k[u], P256_N[u]); + } + } else { + c = -1; + } + return NEQ(z, 0) & LT0(c); +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *k, size_t klen, int curve) +{ + uint32_t r; + p256_jacobian P; + + (void)curve; + if (Glen != 65) { + return 0; + } + r = check_scalar(k, klen); + r &= point_decode(&P, G); + p256_mul(&P, k, klen); + r &= point_encode(G, &P); + return r; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *k, size_t klen, int curve) +{ + p256_jacobian P; + + (void)curve; + p256_mulgen(&P, k, klen); + point_encode(R, &P); + return 65; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + /* + * We might want to use Shamir's trick here: make a composite + * window of u*P+v*Q points, to merge the two doubling-ladders + * into one. This, however, has some complications: + * + * - During the computation, we may hit the point-at-infinity. + * Thus, we would need p256_add_complete_mixed() (complete + * formulas for point addition), with a higher cost (17 muls + * instead of 11). + * + * - A 4-bit window would be too large, since it would involve + * 16*16-1 = 255 points. For the same window size as in the + * p256_mul() case, we would need to reduce the window size + * to 2 bits, and thus perform twice as many non-doubling + * point additions. + * + * - The window may itself contain the point-at-infinity, and + * thus cannot be in all generality be made of affine points. + * Instead, we would need to make it a window of points in + * Jacobian coordinates. Even p256_add_complete_mixed() would + * be inappropriate. + * + * For these reasons, the code below performs two separate + * point multiplications, then computes the final point addition + * (which is both a "normal" addition, and a doubling, to handle + * all cases). + */ + + p256_jacobian P, Q; + uint32_t r, t, s; + uint64_t z; + + (void)curve; + if (len != 65) { + return 0; + } + r = point_decode(&P, A); + p256_mul(&P, x, xlen); + if (B == NULL) { + p256_mulgen(&Q, y, ylen); + } else { + r &= point_decode(&Q, B); + p256_mul(&Q, y, ylen); + } + + /* + * The final addition may fail in case both points are equal. + */ + t = p256_add(&P, &Q); + f256_final_reduce(P.z); + z = P.z[0] | P.z[1] | P.z[2] | P.z[3] | P.z[4]; + s = EQ((uint32_t)(z | (z >> 32)), 0); + p256_double(&Q); + + /* + * If s is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we + * have the following: + * + * s = 0, t = 0 return P (normal addition) + * s = 0, t = 1 return P (normal addition) + * s = 1, t = 0 return Q (a 'double' case) + * s = 1, t = 1 report an error (P+Q = 0) + */ + CCOPY(s & ~t, &P, &Q, sizeof Q); + point_encode(A, &P); + r &= ~(s & t); + return r; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_p256_m62 = { + (uint32_t)0x00800000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_p256_m62_get(void) +{ + return &br_ec_p256_m62; +} + +#else + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_p256_m62_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/ec/ec_p256_m64.c b/BearSSL-OG/libbearssl/src/ec/ec_p256_m64.c new file mode 100644 index 0000000..71a527c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_p256_m64.c @@ -0,0 +1,1781 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +#if BR_UMUL128 +#include +#endif + +static const unsigned char P256_G[] = { + 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, + 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, + 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, + 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, + 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, + 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, + 0x68, 0x37, 0xBF, 0x51, 0xF5 +}; + +static const unsigned char P256_N[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, + 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, + 0x25, 0x51 +}; + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + (void)curve; + *len = sizeof P256_G; + return P256_G; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + (void)curve; + *len = sizeof P256_N; + return P256_N; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + (void)curve; + *len = 32; + return 1; +} + +/* + * A field element is encoded as four 64-bit integers, in basis 2^64. + * Values may reach up to 2^256-1. Montgomery multiplication is used. + */ + +/* R = 2^256 mod p */ +static const uint64_t F256_R[] = { + 0x0000000000000001, 0xFFFFFFFF00000000, + 0xFFFFFFFFFFFFFFFF, 0x00000000FFFFFFFE +}; + +/* Curve equation is y^2 = x^3 - 3*x + B. This constant is B*R mod p + (Montgomery representation of B). */ +static const uint64_t P256_B_MONTY[] = { + 0xD89CDF6229C4BDDF, 0xACF005CD78843090, + 0xE5A220ABF7212ED6, 0xDC30061D04874834 +}; + +/* + * Addition in the field. + */ +static inline void +f256_add(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ +#if BR_INT128 + unsigned __int128 w; + uint64_t t; + + /* + * Do the addition, with an extra carry in t. + */ + w = (unsigned __int128)a[0] + b[0]; + d[0] = (uint64_t)w; + w = (unsigned __int128)a[1] + b[1] + (w >> 64); + d[1] = (uint64_t)w; + w = (unsigned __int128)a[2] + b[2] + (w >> 64); + d[2] = (uint64_t)w; + w = (unsigned __int128)a[3] + b[3] + (w >> 64); + d[3] = (uint64_t)w; + t = (uint64_t)(w >> 64); + + /* + * Fold carry t, using: 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p. + */ + w = (unsigned __int128)d[0] + t; + d[0] = (uint64_t)w; + w = (unsigned __int128)d[1] + (w >> 64) - (t << 32); + d[1] = (uint64_t)w; + /* Here, carry "w >> 64" can only be 0 or -1 */ + w = (unsigned __int128)d[2] - ((w >> 64) & 1); + d[2] = (uint64_t)w; + /* Again, carry is 0 or -1. But there can be carry only if t = 1, + in which case the addition of (t << 32) - t is positive. */ + w = (unsigned __int128)d[3] - ((w >> 64) & 1) + (t << 32) - t; + d[3] = (uint64_t)w; + t = (uint64_t)(w >> 64); + + /* + * There can be an extra carry here, which we must fold again. + */ + w = (unsigned __int128)d[0] + t; + d[0] = (uint64_t)w; + w = (unsigned __int128)d[1] + (w >> 64) - (t << 32); + d[1] = (uint64_t)w; + w = (unsigned __int128)d[2] - ((w >> 64) & 1); + d[2] = (uint64_t)w; + d[3] += (t << 32) - t - (uint64_t)((w >> 64) & 1); + +#elif BR_UMUL128 + + unsigned char cc; + uint64_t t; + + cc = _addcarry_u64(0, a[0], b[0], &d[0]); + cc = _addcarry_u64(cc, a[1], b[1], &d[1]); + cc = _addcarry_u64(cc, a[2], b[2], &d[2]); + cc = _addcarry_u64(cc, a[3], b[3], &d[3]); + + /* + * If there is a carry, then we want to subtract p, which we + * do by adding 2^256 - p. + */ + t = cc; + cc = _addcarry_u64(cc, d[0], 0, &d[0]); + cc = _addcarry_u64(cc, d[1], -(t << 32), &d[1]); + cc = _addcarry_u64(cc, d[2], -t, &d[2]); + cc = _addcarry_u64(cc, d[3], (t << 32) - (t << 1), &d[3]); + + /* + * We have to do it again if there still is a carry. + */ + t = cc; + cc = _addcarry_u64(cc, d[0], 0, &d[0]); + cc = _addcarry_u64(cc, d[1], -(t << 32), &d[1]); + cc = _addcarry_u64(cc, d[2], -t, &d[2]); + (void)_addcarry_u64(cc, d[3], (t << 32) - (t << 1), &d[3]); + +#endif +} + +/* + * Subtraction in the field. + */ +static inline void +f256_sub(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ +#if BR_INT128 + + unsigned __int128 w; + uint64_t t; + + w = (unsigned __int128)a[0] - b[0]; + d[0] = (uint64_t)w; + w = (unsigned __int128)a[1] - b[1] - ((w >> 64) & 1); + d[1] = (uint64_t)w; + w = (unsigned __int128)a[2] - b[2] - ((w >> 64) & 1); + d[2] = (uint64_t)w; + w = (unsigned __int128)a[3] - b[3] - ((w >> 64) & 1); + d[3] = (uint64_t)w; + t = (uint64_t)(w >> 64) & 1; + + /* + * If there is a borrow (t = 1), then we must add the modulus + * p = 2^256 - 2^224 + 2^192 + 2^96 - 1. + */ + w = (unsigned __int128)d[0] - t; + d[0] = (uint64_t)w; + w = (unsigned __int128)d[1] + (t << 32) - ((w >> 64) & 1); + d[1] = (uint64_t)w; + /* Here, carry "w >> 64" can only be 0 or +1 */ + w = (unsigned __int128)d[2] + (w >> 64); + d[2] = (uint64_t)w; + /* Again, carry is 0 or +1 */ + w = (unsigned __int128)d[3] + (w >> 64) - (t << 32) + t; + d[3] = (uint64_t)w; + t = (uint64_t)(w >> 64) & 1; + + /* + * There may be again a borrow, in which case we must add the + * modulus again. + */ + w = (unsigned __int128)d[0] - t; + d[0] = (uint64_t)w; + w = (unsigned __int128)d[1] + (t << 32) - ((w >> 64) & 1); + d[1] = (uint64_t)w; + w = (unsigned __int128)d[2] + (w >> 64); + d[2] = (uint64_t)w; + d[3] += (uint64_t)(w >> 64) - (t << 32) + t; + +#elif BR_UMUL128 + + unsigned char cc; + uint64_t t; + + cc = _subborrow_u64(0, a[0], b[0], &d[0]); + cc = _subborrow_u64(cc, a[1], b[1], &d[1]); + cc = _subborrow_u64(cc, a[2], b[2], &d[2]); + cc = _subborrow_u64(cc, a[3], b[3], &d[3]); + + /* + * If there is a borrow, then we need to add p. We (virtually) + * add 2^256, then subtract 2^256 - p. + */ + t = cc; + cc = _subborrow_u64(0, d[0], t, &d[0]); + cc = _subborrow_u64(cc, d[1], -(t << 32), &d[1]); + cc = _subborrow_u64(cc, d[2], -t, &d[2]); + cc = _subborrow_u64(cc, d[3], (t << 32) - (t << 1), &d[3]); + + /* + * If there still is a borrow, then we need to add p again. + */ + t = cc; + cc = _subborrow_u64(0, d[0], t, &d[0]); + cc = _subborrow_u64(cc, d[1], -(t << 32), &d[1]); + cc = _subborrow_u64(cc, d[2], -t, &d[2]); + (void)_subborrow_u64(cc, d[3], (t << 32) - (t << 1), &d[3]); + +#endif +} + +/* + * Montgomery multiplication in the field. + */ +static void +f256_montymul(uint64_t *d, const uint64_t *a, const uint64_t *b) +{ +#if BR_INT128 + + uint64_t x, f, t0, t1, t2, t3, t4; + unsigned __int128 z, ff; + int i; + + /* + * When computing d <- d + a[u]*b, we also add f*p such + * that d + a[u]*b + f*p is a multiple of 2^64. Since + * p = -1 mod 2^64, we can compute f = d[0] + a[u]*b[0] mod 2^64. + */ + + /* + * Step 1: t <- (a[0]*b + f*p) / 2^64 + * We have f = a[0]*b[0] mod 2^64. Since p = -1 mod 2^64, this + * ensures that (a[0]*b + f*p) is a multiple of 2^64. + * + * We also have: f*p = f*2^256 - f*2^224 + f*2^192 + f*2^96 - f. + */ + x = a[0]; + z = (unsigned __int128)b[0] * x; + f = (uint64_t)z; + z = (unsigned __int128)b[1] * x + (z >> 64) + (uint64_t)(f << 32); + t0 = (uint64_t)z; + z = (unsigned __int128)b[2] * x + (z >> 64) + (uint64_t)(f >> 32); + t1 = (uint64_t)z; + z = (unsigned __int128)b[3] * x + (z >> 64) + f; + t2 = (uint64_t)z; + t3 = (uint64_t)(z >> 64); + ff = ((unsigned __int128)f << 64) - ((unsigned __int128)f << 32); + z = (unsigned __int128)t2 + (uint64_t)ff; + t2 = (uint64_t)z; + z = (unsigned __int128)t3 + (z >> 64) + (ff >> 64); + t3 = (uint64_t)z; + t4 = (uint64_t)(z >> 64); + + /* + * Steps 2 to 4: t <- (t + a[i]*b + f*p) / 2^64 + */ + for (i = 1; i < 4; i ++) { + x = a[i]; + + /* t <- (t + x*b - f) / 2^64 */ + z = (unsigned __int128)b[0] * x + t0; + f = (uint64_t)z; + z = (unsigned __int128)b[1] * x + t1 + (z >> 64); + t0 = (uint64_t)z; + z = (unsigned __int128)b[2] * x + t2 + (z >> 64); + t1 = (uint64_t)z; + z = (unsigned __int128)b[3] * x + t3 + (z >> 64); + t2 = (uint64_t)z; + z = t4 + (z >> 64); + t3 = (uint64_t)z; + t4 = (uint64_t)(z >> 64); + + /* t <- t + f*2^32, carry in the upper half of z */ + z = (unsigned __int128)t0 + (uint64_t)(f << 32); + t0 = (uint64_t)z; + z = (z >> 64) + (unsigned __int128)t1 + (uint64_t)(f >> 32); + t1 = (uint64_t)z; + + /* t <- t + f*2^192 - f*2^160 + f*2^128 */ + ff = ((unsigned __int128)f << 64) + - ((unsigned __int128)f << 32) + f; + z = (z >> 64) + (unsigned __int128)t2 + (uint64_t)ff; + t2 = (uint64_t)z; + z = (unsigned __int128)t3 + (z >> 64) + (ff >> 64); + t3 = (uint64_t)z; + t4 += (uint64_t)(z >> 64); + } + + /* + * At that point, we have computed t = (a*b + F*p) / 2^256, where + * F is a 256-bit integer whose limbs are the "f" coefficients + * in the steps above. We have: + * a <= 2^256-1 + * b <= 2^256-1 + * F <= 2^256-1 + * Hence: + * a*b + F*p <= (2^256-1)*(2^256-1) + p*(2^256-1) + * a*b + F*p <= 2^256*(2^256 - 2 + p) + 1 - p + * Therefore: + * t < 2^256 + p - 2 + * Since p < 2^256, it follows that: + * t4 can be only 0 or 1 + * t - p < 2^256 + * We can therefore subtract p from t, conditionally on t4, to + * get a nonnegative result that fits on 256 bits. + */ + z = (unsigned __int128)t0 + t4; + t0 = (uint64_t)z; + z = (unsigned __int128)t1 - (t4 << 32) + (z >> 64); + t1 = (uint64_t)z; + z = (unsigned __int128)t2 - (z >> 127); + t2 = (uint64_t)z; + t3 = t3 - (uint64_t)(z >> 127) - t4 + (t4 << 32); + + d[0] = t0; + d[1] = t1; + d[2] = t2; + d[3] = t3; + +#elif BR_UMUL128 + + uint64_t x, f, t0, t1, t2, t3, t4; + uint64_t zl, zh, ffl, ffh; + unsigned char k, m; + int i; + + /* + * When computing d <- d + a[u]*b, we also add f*p such + * that d + a[u]*b + f*p is a multiple of 2^64. Since + * p = -1 mod 2^64, we can compute f = d[0] + a[u]*b[0] mod 2^64. + */ + + /* + * Step 1: t <- (a[0]*b + f*p) / 2^64 + * We have f = a[0]*b[0] mod 2^64. Since p = -1 mod 2^64, this + * ensures that (a[0]*b + f*p) is a multiple of 2^64. + * + * We also have: f*p = f*2^256 - f*2^224 + f*2^192 + f*2^96 - f. + */ + x = a[0]; + + zl = _umul128(b[0], x, &zh); + f = zl; + t0 = zh; + + zl = _umul128(b[1], x, &zh); + k = _addcarry_u64(0, zl, t0, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + k = _addcarry_u64(0, zl, f << 32, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + t0 = zl; + t1 = zh; + + zl = _umul128(b[2], x, &zh); + k = _addcarry_u64(0, zl, t1, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + k = _addcarry_u64(0, zl, f >> 32, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + t1 = zl; + t2 = zh; + + zl = _umul128(b[3], x, &zh); + k = _addcarry_u64(0, zl, t2, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + k = _addcarry_u64(0, zl, f, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + t2 = zl; + t3 = zh; + + t4 = _addcarry_u64(0, t3, f, &t3); + k = _subborrow_u64(0, t2, f << 32, &t2); + k = _subborrow_u64(k, t3, f >> 32, &t3); + (void)_subborrow_u64(k, t4, 0, &t4); + + /* + * Steps 2 to 4: t <- (t + a[i]*b + f*p) / 2^64 + */ + for (i = 1; i < 4; i ++) { + x = a[i]; + /* f = t0 + x * b[0]; -- computed below */ + + /* t <- (t + x*b - f) / 2^64 */ + zl = _umul128(b[0], x, &zh); + k = _addcarry_u64(0, zl, t0, &f); + (void)_addcarry_u64(k, zh, 0, &t0); + + zl = _umul128(b[1], x, &zh); + k = _addcarry_u64(0, zl, t0, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + k = _addcarry_u64(0, zl, t1, &t0); + (void)_addcarry_u64(k, zh, 0, &t1); + + zl = _umul128(b[2], x, &zh); + k = _addcarry_u64(0, zl, t1, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + k = _addcarry_u64(0, zl, t2, &t1); + (void)_addcarry_u64(k, zh, 0, &t2); + + zl = _umul128(b[3], x, &zh); + k = _addcarry_u64(0, zl, t2, &zl); + (void)_addcarry_u64(k, zh, 0, &zh); + k = _addcarry_u64(0, zl, t3, &t2); + (void)_addcarry_u64(k, zh, 0, &t3); + + t4 = _addcarry_u64(0, t3, t4, &t3); + + /* t <- t + f*2^32, carry in k */ + k = _addcarry_u64(0, t0, f << 32, &t0); + k = _addcarry_u64(k, t1, f >> 32, &t1); + + /* t <- t + f*2^192 - f*2^160 + f*2^128 */ + m = _subborrow_u64(0, f, f << 32, &ffl); + (void)_subborrow_u64(m, f, f >> 32, &ffh); + k = _addcarry_u64(k, t2, ffl, &t2); + k = _addcarry_u64(k, t3, ffh, &t3); + (void)_addcarry_u64(k, t4, 0, &t4); + } + + /* + * At that point, we have computed t = (a*b + F*p) / 2^256, where + * F is a 256-bit integer whose limbs are the "f" coefficients + * in the steps above. We have: + * a <= 2^256-1 + * b <= 2^256-1 + * F <= 2^256-1 + * Hence: + * a*b + F*p <= (2^256-1)*(2^256-1) + p*(2^256-1) + * a*b + F*p <= 2^256*(2^256 - 2 + p) + 1 - p + * Therefore: + * t < 2^256 + p - 2 + * Since p < 2^256, it follows that: + * t4 can be only 0 or 1 + * t - p < 2^256 + * We can therefore subtract p from t, conditionally on t4, to + * get a nonnegative result that fits on 256 bits. + */ + k = _addcarry_u64(0, t0, t4, &t0); + k = _addcarry_u64(k, t1, -(t4 << 32), &t1); + k = _addcarry_u64(k, t2, -t4, &t2); + (void)_addcarry_u64(k, t3, (t4 << 32) - (t4 << 1), &t3); + + d[0] = t0; + d[1] = t1; + d[2] = t2; + d[3] = t3; + +#endif +} + +/* + * Montgomery squaring in the field; currently a basic wrapper around + * multiplication (inline, should be optimized away). + * TODO: see if some extra speed can be gained here. + */ +static inline void +f256_montysquare(uint64_t *d, const uint64_t *a) +{ + f256_montymul(d, a, a); +} + +/* + * Convert to Montgomery representation. + */ +static void +f256_tomonty(uint64_t *d, const uint64_t *a) +{ + /* + * R2 = 2^512 mod p. + * If R = 2^256 mod p, then R2 = R^2 mod p; and the Montgomery + * multiplication of a by R2 is: a*R2/R = a*R mod p, i.e. the + * conversion to Montgomery representation. + */ + static const uint64_t R2[] = { + 0x0000000000000003, + 0xFFFFFFFBFFFFFFFF, + 0xFFFFFFFFFFFFFFFE, + 0x00000004FFFFFFFD + }; + + f256_montymul(d, a, R2); +} + +/* + * Convert from Montgomery representation. + */ +static void +f256_frommonty(uint64_t *d, const uint64_t *a) +{ + /* + * Montgomery multiplication by 1 is division by 2^256 modulo p. + */ + static const uint64_t one[] = { 1, 0, 0, 0 }; + + f256_montymul(d, a, one); +} + +/* + * Inversion in the field. If the source value is 0 modulo p, then this + * returns 0 or p. This function uses Montgomery representation. + */ +static void +f256_invert(uint64_t *d, const uint64_t *a) +{ + /* + * We compute a^(p-2) mod p. The exponent pattern (from high to + * low) is: + * - 32 bits of value 1 + * - 31 bits of value 0 + * - 1 bit of value 1 + * - 96 bits of value 0 + * - 94 bits of value 1 + * - 1 bit of value 0 + * - 1 bit of value 1 + * To speed up the square-and-multiply algorithm, we precompute + * a^(2^31-1). + */ + + uint64_t r[4], t[4]; + int i; + + memcpy(t, a, sizeof t); + for (i = 0; i < 30; i ++) { + f256_montysquare(t, t); + f256_montymul(t, t, a); + } + + memcpy(r, t, sizeof t); + for (i = 224; i >= 0; i --) { + f256_montysquare(r, r); + switch (i) { + case 0: + case 2: + case 192: + case 224: + f256_montymul(r, r, a); + break; + case 3: + case 34: + case 65: + f256_montymul(r, r, t); + break; + } + } + memcpy(d, r, sizeof r); +} + +/* + * Finalize reduction. + * Input value fits on 256 bits. This function subtracts p if and only + * if the input is greater than or equal to p. + */ +static inline void +f256_final_reduce(uint64_t *a) +{ +#if BR_INT128 + + uint64_t t0, t1, t2, t3, cc; + unsigned __int128 z; + + /* + * We add 2^224 - 2^192 - 2^96 + 1 to a. If there is no carry, + * then a < p; otherwise, the addition result we computed is + * the value we must return. + */ + z = (unsigned __int128)a[0] + 1; + t0 = (uint64_t)z; + z = (unsigned __int128)a[1] + (z >> 64) - ((uint64_t)1 << 32); + t1 = (uint64_t)z; + z = (unsigned __int128)a[2] - (z >> 127); + t2 = (uint64_t)z; + z = (unsigned __int128)a[3] - (z >> 127) + 0xFFFFFFFF; + t3 = (uint64_t)z; + cc = -(uint64_t)(z >> 64); + + a[0] ^= cc & (a[0] ^ t0); + a[1] ^= cc & (a[1] ^ t1); + a[2] ^= cc & (a[2] ^ t2); + a[3] ^= cc & (a[3] ^ t3); + +#elif BR_UMUL128 + + uint64_t t0, t1, t2, t3, m; + unsigned char k; + + k = _addcarry_u64(0, a[0], (uint64_t)1, &t0); + k = _addcarry_u64(k, a[1], -((uint64_t)1 << 32), &t1); + k = _addcarry_u64(k, a[2], -(uint64_t)1, &t2); + k = _addcarry_u64(k, a[3], ((uint64_t)1 << 32) - 2, &t3); + m = -(uint64_t)k; + + a[0] ^= m & (a[0] ^ t0); + a[1] ^= m & (a[1] ^ t1); + a[2] ^= m & (a[2] ^ t2); + a[3] ^= m & (a[3] ^ t3); + +#endif +} + +/* + * Points in affine and Jacobian coordinates. + * + * - In affine coordinates, the point-at-infinity cannot be encoded. + * - Jacobian coordinates (X,Y,Z) correspond to affine (X/Z^2,Y/Z^3); + * if Z = 0 then this is the point-at-infinity. + */ +typedef struct { + uint64_t x[4]; + uint64_t y[4]; +} p256_affine; + +typedef struct { + uint64_t x[4]; + uint64_t y[4]; + uint64_t z[4]; +} p256_jacobian; + +/* + * Decode a point. The returned point is in Jacobian coordinates, but + * with z = 1. If the encoding is invalid, or encodes a point which is + * not on the curve, or encodes the point at infinity, then this function + * returns 0. Otherwise, 1 is returned. + * + * The buffer is assumed to have length exactly 65 bytes. + */ +static uint32_t +point_decode(p256_jacobian *P, const unsigned char *buf) +{ + uint64_t x[4], y[4], t[4], x3[4], tt; + uint32_t r; + + /* + * Header byte shall be 0x04. + */ + r = EQ(buf[0], 0x04); + + /* + * Decode X and Y coordinates, and convert them into + * Montgomery representation. + */ + x[3] = br_dec64be(buf + 1); + x[2] = br_dec64be(buf + 9); + x[1] = br_dec64be(buf + 17); + x[0] = br_dec64be(buf + 25); + y[3] = br_dec64be(buf + 33); + y[2] = br_dec64be(buf + 41); + y[1] = br_dec64be(buf + 49); + y[0] = br_dec64be(buf + 57); + f256_tomonty(x, x); + f256_tomonty(y, y); + + /* + * Verify y^2 = x^3 + A*x + B. In curve P-256, A = -3. + * Note that the Montgomery representation of 0 is 0. We must + * take care to apply the final reduction to make sure we have + * 0 and not p. + */ + f256_montysquare(t, y); + f256_montysquare(x3, x); + f256_montymul(x3, x3, x); + f256_sub(t, t, x3); + f256_add(t, t, x); + f256_add(t, t, x); + f256_add(t, t, x); + f256_sub(t, t, P256_B_MONTY); + f256_final_reduce(t); + tt = t[0] | t[1] | t[2] | t[3]; + r &= EQ((uint32_t)(tt | (tt >> 32)), 0); + + /* + * Return the point in Jacobian coordinates (and Montgomery + * representation). + */ + memcpy(P->x, x, sizeof x); + memcpy(P->y, y, sizeof y); + memcpy(P->z, F256_R, sizeof F256_R); + return r; +} + +/* + * Final conversion for a point: + * - The point is converted back to affine coordinates. + * - Final reduction is performed. + * - The point is encoded into the provided buffer. + * + * If the point is the point-at-infinity, all operations are performed, + * but the buffer contents are indeterminate, and 0 is returned. Otherwise, + * the encoded point is written in the buffer, and 1 is returned. + */ +static uint32_t +point_encode(unsigned char *buf, const p256_jacobian *P) +{ + uint64_t t1[4], t2[4], z; + + /* Set t1 = 1/z^2 and t2 = 1/z^3. */ + f256_invert(t2, P->z); + f256_montysquare(t1, t2); + f256_montymul(t2, t2, t1); + + /* Compute affine coordinates x (in t1) and y (in t2). */ + f256_montymul(t1, P->x, t1); + f256_montymul(t2, P->y, t2); + + /* Convert back from Montgomery representation, and finalize + reductions. */ + f256_frommonty(t1, t1); + f256_frommonty(t2, t2); + f256_final_reduce(t1); + f256_final_reduce(t2); + + /* Encode. */ + buf[0] = 0x04; + br_enc64be(buf + 1, t1[3]); + br_enc64be(buf + 9, t1[2]); + br_enc64be(buf + 17, t1[1]); + br_enc64be(buf + 25, t1[0]); + br_enc64be(buf + 33, t2[3]); + br_enc64be(buf + 41, t2[2]); + br_enc64be(buf + 49, t2[1]); + br_enc64be(buf + 57, t2[0]); + + /* Return success if and only if P->z != 0. */ + z = P->z[0] | P->z[1] | P->z[2] | P->z[3]; + return NEQ((uint32_t)(z | z >> 32), 0); +} + +/* + * Point doubling in Jacobian coordinates: point P is doubled. + * Note: if the source point is the point-at-infinity, then the result is + * still the point-at-infinity, which is correct. Moreover, if the three + * coordinates were zero, then they still are zero in the returned value. + * + * (Note: this is true even without the final reduction: if the three + * coordinates are encoded as four words of value zero each, then the + * result will also have all-zero coordinate encodings, not the alternate + * encoding as the integer p.) + */ +static void +p256_double(p256_jacobian *P) +{ + /* + * Doubling formulas are: + * + * s = 4*x*y^2 + * m = 3*(x + z^2)*(x - z^2) + * x' = m^2 - 2*s + * y' = m*(s - x') - 8*y^4 + * z' = 2*y*z + * + * These formulas work for all points, including points of order 2 + * and points at infinity: + * - If y = 0 then z' = 0. But there is no such point in P-256 + * anyway. + * - If z = 0 then z' = 0. + */ + uint64_t t1[4], t2[4], t3[4], t4[4]; + + /* + * Compute z^2 in t1. + */ + f256_montysquare(t1, P->z); + + /* + * Compute x-z^2 in t2 and x+z^2 in t1. + */ + f256_add(t2, P->x, t1); + f256_sub(t1, P->x, t1); + + /* + * Compute 3*(x+z^2)*(x-z^2) in t1. + */ + f256_montymul(t3, t1, t2); + f256_add(t1, t3, t3); + f256_add(t1, t3, t1); + + /* + * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3). + */ + f256_montysquare(t3, P->y); + f256_add(t3, t3, t3); + f256_montymul(t2, P->x, t3); + f256_add(t2, t2, t2); + + /* + * Compute x' = m^2 - 2*s. + */ + f256_montysquare(P->x, t1); + f256_sub(P->x, P->x, t2); + f256_sub(P->x, P->x, t2); + + /* + * Compute z' = 2*y*z. + */ + f256_montymul(t4, P->y, P->z); + f256_add(P->z, t4, t4); + + /* + * Compute y' = m*(s - x') - 8*y^4. Note that we already have + * 2*y^2 in t3. + */ + f256_sub(t2, t2, P->x); + f256_montymul(P->y, t1, t2); + f256_montysquare(t4, t3); + f256_add(t4, t4, t4); + f256_sub(P->y, P->y, t4); +} + +/* + * Point addition (Jacobian coordinates): P1 is replaced with P1+P2. + * This function computes the wrong result in the following cases: + * + * - If P1 == 0 but P2 != 0 + * - If P1 != 0 but P2 == 0 + * - If P1 == P2 + * + * In all three cases, P1 is set to the point at infinity. + * + * Returned value is 0 if one of the following occurs: + * + * - P1 and P2 have the same Y coordinate. + * - P1 == 0 and P2 == 0. + * - The Y coordinate of one of the points is 0 and the other point is + * the point at infinity. + * + * The third case cannot actually happen with valid points, since a point + * with Y == 0 is a point of order 2, and there is no point of order 2 on + * curve P-256. + * + * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller + * can apply the following: + * + * - If the result is not the point at infinity, then it is correct. + * - Otherwise, if the returned value is 1, then this is a case of + * P1+P2 == 0, so the result is indeed the point at infinity. + * - Otherwise, P1 == P2, so a "double" operation should have been + * performed. + * + * Note that you can get a returned value of 0 with a correct result, + * e.g. if P1 and P2 have the same Y coordinate, but distinct X coordinates. + */ +static uint32_t +p256_add(p256_jacobian *P1, const p256_jacobian *P2) +{ + /* + * Addtions formulas are: + * + * u1 = x1 * z2^2 + * u2 = x2 * z1^2 + * s1 = y1 * z2^3 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 * z2 + */ + uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt; + uint32_t ret; + + /* + * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). + */ + f256_montysquare(t3, P2->z); + f256_montymul(t1, P1->x, t3); + f256_montymul(t4, P2->z, t3); + f256_montymul(t3, P1->y, t4); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + f256_montysquare(t4, P1->z); + f256_montymul(t2, P2->x, t4); + f256_montymul(t5, P1->z, t4); + f256_montymul(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * We need to test whether r is zero, so we will do some extra + * reduce. + */ + f256_sub(t2, t2, t1); + f256_sub(t4, t4, t3); + f256_final_reduce(t4); + tt = t4[0] | t4[1] | t4[2] | t4[3]; + ret = (uint32_t)(tt | (tt >> 32)); + ret = (ret | -ret) >> 31; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + f256_montysquare(t7, t2); + f256_montymul(t6, t1, t7); + f256_montymul(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + f256_montysquare(P1->x, t4); + f256_sub(P1->x, P1->x, t5); + f256_sub(P1->x, P1->x, t6); + f256_sub(P1->x, P1->x, t6); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + f256_sub(t6, t6, P1->x); + f256_montymul(P1->y, t4, t6); + f256_montymul(t1, t5, t3); + f256_sub(P1->y, P1->y, t1); + + /* + * Compute z3 = h*z1*z2. + */ + f256_montymul(t1, P1->z, P2->z); + f256_montymul(P1->z, t1, t2); + + return ret; +} + +/* + * Point addition (mixed coordinates): P1 is replaced with P1+P2. + * This is a specialised function for the case when P2 is a non-zero point + * in affine coordinates. + * + * This function computes the wrong result in the following cases: + * + * - If P1 == 0 + * - If P1 == P2 + * + * In both cases, P1 is set to the point at infinity. + * + * Returned value is 0 if one of the following occurs: + * + * - P1 and P2 have the same Y (affine) coordinate. + * - The Y coordinate of P2 is 0 and P1 is the point at infinity. + * + * The second case cannot actually happen with valid points, since a point + * with Y == 0 is a point of order 2, and there is no point of order 2 on + * curve P-256. + * + * Therefore, assuming that P1 != 0 on input, then the caller + * can apply the following: + * + * - If the result is not the point at infinity, then it is correct. + * - Otherwise, if the returned value is 1, then this is a case of + * P1+P2 == 0, so the result is indeed the point at infinity. + * - Otherwise, P1 == P2, so a "double" operation should have been + * performed. + * + * Again, a value of 0 may be returned in some cases where the addition + * result is correct. + */ +static uint32_t +p256_add_mixed(p256_jacobian *P1, const p256_affine *P2) +{ + /* + * Addtions formulas are: + * + * u1 = x1 + * u2 = x2 * z1^2 + * s1 = y1 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 + */ + uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt; + uint32_t ret; + + /* + * Compute u1 = x1 (in t1) and s1 = y1 (in t3). + */ + memcpy(t1, P1->x, sizeof t1); + memcpy(t3, P1->y, sizeof t3); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + f256_montysquare(t4, P1->z); + f256_montymul(t2, P2->x, t4); + f256_montymul(t5, P1->z, t4); + f256_montymul(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * We need to test whether r is zero, so we will do some extra + * reduce. + */ + f256_sub(t2, t2, t1); + f256_sub(t4, t4, t3); + f256_final_reduce(t4); + tt = t4[0] | t4[1] | t4[2] | t4[3]; + ret = (uint32_t)(tt | (tt >> 32)); + ret = (ret | -ret) >> 31; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + f256_montysquare(t7, t2); + f256_montymul(t6, t1, t7); + f256_montymul(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + f256_montysquare(P1->x, t4); + f256_sub(P1->x, P1->x, t5); + f256_sub(P1->x, P1->x, t6); + f256_sub(P1->x, P1->x, t6); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + f256_sub(t6, t6, P1->x); + f256_montymul(P1->y, t4, t6); + f256_montymul(t1, t5, t3); + f256_sub(P1->y, P1->y, t1); + + /* + * Compute z3 = h*z1*z2. + */ + f256_montymul(P1->z, P1->z, t2); + + return ret; +} + +#if 0 +/* unused */ +/* + * Point addition (mixed coordinates, complete): P1 is replaced with P1+P2. + * This is a specialised function for the case when P2 is a non-zero point + * in affine coordinates. + * + * This function returns the correct result in all cases. + */ +static uint32_t +p256_add_complete_mixed(p256_jacobian *P1, const p256_affine *P2) +{ + /* + * Addtions formulas, in the general case, are: + * + * u1 = x1 + * u2 = x2 * z1^2 + * s1 = y1 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 + * + * These formulas mishandle the two following cases: + * + * - If P1 is the point-at-infinity (z1 = 0), then z3 is + * incorrectly set to 0. + * + * - If P1 = P2, then u1 = u2 and s1 = s2, and x3, y3 and z3 + * are all set to 0. + * + * However, if P1 + P2 = 0, then u1 = u2 but s1 != s2, and then + * we correctly get z3 = 0 (the point-at-infinity). + * + * To fix the case P1 = 0, we perform at the end a copy of P2 + * over P1, conditional to z1 = 0. + * + * For P1 = P2: in that case, both h and r are set to 0, and + * we get x3, y3 and z3 equal to 0. We can test for that + * occurrence to make a mask which will be all-one if P1 = P2, + * or all-zero otherwise; then we can compute the double of P2 + * and add it, combined with the mask, to (x3,y3,z3). + * + * Using the doubling formulas in p256_double() on (x2,y2), + * simplifying since P2 is affine (i.e. z2 = 1, implicitly), + * we get: + * s = 4*x2*y2^2 + * m = 3*(x2 + 1)*(x2 - 1) + * x' = m^2 - 2*s + * y' = m*(s - x') - 8*y2^4 + * z' = 2*y2 + * which requires only 6 multiplications. Added to the 11 + * multiplications of the normal mixed addition in Jacobian + * coordinates, we get a cost of 17 multiplications in total. + */ + uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt, zz; + int i; + + /* + * Set zz to -1 if P1 is the point at infinity, 0 otherwise. + */ + zz = P1->z[0] | P1->z[1] | P1->z[2] | P1->z[3]; + zz = ((zz | -zz) >> 63) - (uint64_t)1; + + /* + * Compute u1 = x1 (in t1) and s1 = y1 (in t3). + */ + memcpy(t1, P1->x, sizeof t1); + memcpy(t3, P1->y, sizeof t3); + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + f256_montysquare(t4, P1->z); + f256_montymul(t2, P2->x, t4); + f256_montymul(t5, P1->z, t4); + f256_montymul(t4, P2->y, t5); + + /* + * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). + * reduce. + */ + f256_sub(t2, t2, t1); + f256_sub(t4, t4, t3); + + /* + * If both h = 0 and r = 0, then P1 = P2, and we want to set + * the mask tt to -1; otherwise, the mask will be 0. + */ + f256_final_reduce(t2); + f256_final_reduce(t4); + tt = t2[0] | t2[1] | t2[2] | t2[3] | t4[0] | t4[1] | t4[2] | t4[3]; + tt = ((tt | -tt) >> 63) - (uint64_t)1; + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5); + */ + f256_montysquare(t7, t2); + f256_montymul(t6, t1, t7); + f256_montymul(t5, t7, t2); + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + */ + f256_montysquare(P1->x, t4); + f256_sub(P1->x, P1->x, t5); + f256_sub(P1->x, P1->x, t6); + f256_sub(P1->x, P1->x, t6); + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + f256_sub(t6, t6, P1->x); + f256_montymul(P1->y, t4, t6); + f256_montymul(t1, t5, t3); + f256_sub(P1->y, P1->y, t1); + + /* + * Compute z3 = h*z1. + */ + f256_montymul(P1->z, P1->z, t2); + + /* + * The "double" result, in case P1 = P2. + */ + + /* + * Compute z' = 2*y2 (in t1). + */ + f256_add(t1, P2->y, P2->y); + + /* + * Compute 2*(y2^2) (in t2) and s = 4*x2*(y2^2) (in t3). + */ + f256_montysquare(t2, P2->y); + f256_add(t2, t2, t2); + f256_add(t3, t2, t2); + f256_montymul(t3, P2->x, t3); + + /* + * Compute m = 3*(x2^2 - 1) (in t4). + */ + f256_montysquare(t4, P2->x); + f256_sub(t4, t4, F256_R); + f256_add(t5, t4, t4); + f256_add(t4, t4, t5); + + /* + * Compute x' = m^2 - 2*s (in t5). + */ + f256_montysquare(t5, t4); + f256_sub(t5, t3); + f256_sub(t5, t3); + + /* + * Compute y' = m*(s - x') - 8*y2^4 (in t6). + */ + f256_sub(t6, t3, t5); + f256_montymul(t6, t6, t4); + f256_montysquare(t7, t2); + f256_sub(t6, t6, t7); + f256_sub(t6, t6, t7); + + /* + * We now have the alternate (doubling) coordinates in (t5,t6,t1). + * We combine them with (x3,y3,z3). + */ + for (i = 0; i < 4; i ++) { + P1->x[i] |= tt & t5[i]; + P1->y[i] |= tt & t6[i]; + P1->z[i] |= tt & t1[i]; + } + + /* + * If P1 = 0, then we get z3 = 0 (which is invalid); if z1 is 0, + * then we want to replace the result with a copy of P2. The + * test on z1 was done at the start, in the zz mask. + */ + for (i = 0; i < 4; i ++) { + P1->x[i] ^= zz & (P1->x[i] ^ P2->x[i]); + P1->y[i] ^= zz & (P1->y[i] ^ P2->y[i]); + P1->z[i] ^= zz & (P1->z[i] ^ F256_R[i]); + } +} +#endif + +/* + * Inner function for computing a point multiplication. A window is + * provided, with points 1*P to 15*P in affine coordinates. + * + * Assumptions: + * - All provided points are valid points on the curve. + * - Multiplier is non-zero, and smaller than the curve order. + * - Everything is in Montgomery representation. + */ +static void +point_mul_inner(p256_jacobian *R, const p256_affine *W, + const unsigned char *k, size_t klen) +{ + p256_jacobian Q; + uint32_t qz; + + memset(&Q, 0, sizeof Q); + qz = 1; + while (klen -- > 0) { + int i; + unsigned bk; + + bk = *k ++; + for (i = 0; i < 2; i ++) { + uint32_t bits; + uint32_t bnz; + p256_affine T; + p256_jacobian U; + uint32_t n; + int j; + uint64_t m; + + p256_double(&Q); + p256_double(&Q); + p256_double(&Q); + p256_double(&Q); + bits = (bk >> 4) & 0x0F; + bnz = NEQ(bits, 0); + + /* + * Lookup point in window. If the bits are 0, + * we get something invalid, which is not a + * problem because we will use it only if the + * bits are non-zero. + */ + memset(&T, 0, sizeof T); + for (n = 0; n < 15; n ++) { + m = -(uint64_t)EQ(bits, n + 1); + T.x[0] |= m & W[n].x[0]; + T.x[1] |= m & W[n].x[1]; + T.x[2] |= m & W[n].x[2]; + T.x[3] |= m & W[n].x[3]; + T.y[0] |= m & W[n].y[0]; + T.y[1] |= m & W[n].y[1]; + T.y[2] |= m & W[n].y[2]; + T.y[3] |= m & W[n].y[3]; + } + + U = Q; + p256_add_mixed(&U, &T); + + /* + * If qz is still 1, then Q was all-zeros, and this + * is conserved through p256_double(). + */ + m = -(uint64_t)(bnz & qz); + for (j = 0; j < 4; j ++) { + Q.x[j] |= m & T.x[j]; + Q.y[j] |= m & T.y[j]; + Q.z[j] |= m & F256_R[j]; + } + CCOPY(bnz & ~qz, &Q, &U, sizeof Q); + qz &= ~bnz; + bk <<= 4; + } + } + *R = Q; +} + +/* + * Convert a window from Jacobian to affine coordinates. A single + * field inversion is used. This function works for windows up to + * 32 elements. + * + * The destination array (aff[]) and the source array (jac[]) may + * overlap, provided that the start of aff[] is not after the start of + * jac[]. Even if the arrays do _not_ overlap, the source array is + * modified. + */ +static void +window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) +{ + /* + * Convert the window points to affine coordinates. We use the + * following trick to mutualize the inversion computation: if + * we have z1, z2, z3, and z4, and want to inverse all of them, + * we compute u = 1/(z1*z2*z3*z4), and then we have: + * 1/z1 = u*z2*z3*z4 + * 1/z2 = u*z1*z3*z4 + * 1/z3 = u*z1*z2*z4 + * 1/z4 = u*z1*z2*z3 + * + * The partial products are computed recursively: + * + * - on input (z_1,z_2), return (z_2,z_1) and z_1*z_2 + * - on input (z_1,z_2,... z_n): + * recurse on (z_1,z_2,... z_(n/2)) -> r1 and m1 + * recurse on (z_(n/2+1),z_(n/2+2)... z_n) -> r2 and m2 + * multiply elements of r1 by m2 -> s1 + * multiply elements of r2 by m1 -> s2 + * return r1||r2 and m1*m2 + * + * In the example below, we suppose that we have 14 elements. + * Let z1, z2,... zE be the 14 values to invert (index noted in + * hexadecimal, starting at 1). + * + * - Depth 1: + * swap(z1, z2); z12 = z1*z2 + * swap(z3, z4); z34 = z3*z4 + * swap(z5, z6); z56 = z5*z6 + * swap(z7, z8); z78 = z7*z8 + * swap(z9, zA); z9A = z9*zA + * swap(zB, zC); zBC = zB*zC + * swap(zD, zE); zDE = zD*zE + * + * - Depth 2: + * z1 <- z1*z34, z2 <- z2*z34, z3 <- z3*z12, z4 <- z4*z12 + * z1234 = z12*z34 + * z5 <- z5*z78, z6 <- z6*z78, z7 <- z7*z56, z8 <- z8*z56 + * z5678 = z56*z78 + * z9 <- z9*zBC, zA <- zA*zBC, zB <- zB*z9A, zC <- zC*z9A + * z9ABC = z9A*zBC + * + * - Depth 3: + * z1 <- z1*z5678, z2 <- z2*z5678, z3 <- z3*z5678, z4 <- z4*z5678 + * z5 <- z5*z1234, z6 <- z6*z1234, z7 <- z7*z1234, z8 <- z8*z1234 + * z12345678 = z1234*z5678 + * z9 <- z9*zDE, zA <- zA*zDE, zB <- zB*zDE, zC <- zC*zDE + * zD <- zD*z9ABC, zE*z9ABC + * z9ABCDE = z9ABC*zDE + * + * - Depth 4: + * multiply z1..z8 by z9ABCDE + * multiply z9..zE by z12345678 + * final z = z12345678*z9ABCDE + */ + + uint64_t z[16][4]; + int i, k, s; +#define zt (z[15]) +#define zu (z[14]) +#define zv (z[13]) + + /* + * First recursion step (pairwise swapping and multiplication). + * If there is an odd number of elements, then we "invent" an + * extra one with coordinate Z = 1 (in Montgomery representation). + */ + for (i = 0; (i + 1) < num; i += 2) { + memcpy(zt, jac[i].z, sizeof zt); + memcpy(jac[i].z, jac[i + 1].z, sizeof zt); + memcpy(jac[i + 1].z, zt, sizeof zt); + f256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z); + } + if ((num & 1) != 0) { + memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); + memcpy(jac[num - 1].z, F256_R, sizeof F256_R); + } + + /* + * Perform further recursion steps. At the entry of each step, + * the process has been done for groups of 's' points. The + * integer k is the log2 of s. + */ + for (k = 1, s = 2; s < num; k ++, s <<= 1) { + int n; + + for (i = 0; i < num; i ++) { + f256_montymul(jac[i].z, jac[i].z, z[(i >> k) ^ 1]); + } + n = (num + s - 1) >> k; + for (i = 0; i < (n >> 1); i ++) { + f256_montymul(z[i], z[i << 1], z[(i << 1) + 1]); + } + if ((n & 1) != 0) { + memmove(z[n >> 1], z[n], sizeof zt); + } + } + + /* + * Invert the final result, and convert all points. + */ + f256_invert(zt, z[0]); + for (i = 0; i < num; i ++) { + f256_montymul(zv, jac[i].z, zt); + f256_montysquare(zu, zv); + f256_montymul(zv, zv, zu); + f256_montymul(aff[i].x, jac[i].x, zu); + f256_montymul(aff[i].y, jac[i].y, zv); + } +} + +/* + * Multiply the provided point by an integer. + * Assumptions: + * - Source point is a valid curve point. + * - Source point is not the point-at-infinity. + * - Integer is not 0, and is lower than the curve order. + * If these conditions are not met, then the result is indeterminate + * (but the process is still constant-time). + */ +static void +p256_mul(p256_jacobian *P, const unsigned char *k, size_t klen) +{ + union { + p256_affine aff[15]; + p256_jacobian jac[15]; + } window; + int i; + + /* + * Compute window, in Jacobian coordinates. + */ + window.jac[0] = *P; + for (i = 2; i < 16; i ++) { + window.jac[i - 1] = window.jac[(i >> 1) - 1]; + if ((i & 1) == 0) { + p256_double(&window.jac[i - 1]); + } else { + p256_add(&window.jac[i - 1], &window.jac[i >> 1]); + } + } + + /* + * Convert the window points to affine coordinates. Point + * window[0] is the source point, already in affine coordinates. + */ + window_to_affine(window.aff, window.jac, 15); + + /* + * Perform point multiplication. + */ + point_mul_inner(P, window.aff, k, klen); +} + +/* + * Precomputed window for the conventional generator: P256_Gwin[n] + * contains (n+1)*G (affine coordinates, in Montgomery representation). + */ +static const p256_affine P256_Gwin[] = { + { + { 0x79E730D418A9143C, 0x75BA95FC5FEDB601, + 0x79FB732B77622510, 0x18905F76A53755C6 }, + { 0xDDF25357CE95560A, 0x8B4AB8E4BA19E45C, + 0xD2E88688DD21F325, 0x8571FF1825885D85 } + }, + { + { 0x850046D410DDD64D, 0xAA6AE3C1A433827D, + 0x732205038D1490D9, 0xF6BB32E43DCF3A3B }, + { 0x2F3648D361BEE1A5, 0x152CD7CBEB236FF8, + 0x19A8FB0E92042DBE, 0x78C577510A5B8A3B } + }, + { + { 0xFFAC3F904EEBC127, 0xB027F84A087D81FB, + 0x66AD77DD87CBBC98, 0x26936A3FB6FF747E }, + { 0xB04C5C1FC983A7EB, 0x583E47AD0861FE1A, + 0x788208311A2EE98E, 0xD5F06A29E587CC07 } + }, + { + { 0x74B0B50D46918DCC, 0x4650A6EDC623C173, + 0x0CDAACACE8100AF2, 0x577362F541B0176B }, + { 0x2D96F24CE4CBABA6, 0x17628471FAD6F447, + 0x6B6C36DEE5DDD22E, 0x84B14C394C5AB863 } + }, + { + { 0xBE1B8AAEC45C61F5, 0x90EC649A94B9537D, + 0x941CB5AAD076C20C, 0xC9079605890523C8 }, + { 0xEB309B4AE7BA4F10, 0x73C568EFE5EB882B, + 0x3540A9877E7A1F68, 0x73A076BB2DD1E916 } + }, + { + { 0x403947373E77664A, 0x55AE744F346CEE3E, + 0xD50A961A5B17A3AD, 0x13074B5954213673 }, + { 0x93D36220D377E44B, 0x299C2B53ADFF14B5, + 0xF424D44CEF639F11, 0xA4C9916D4A07F75F } + }, + { + { 0x0746354EA0173B4F, 0x2BD20213D23C00F7, + 0xF43EAAB50C23BB08, 0x13BA5119C3123E03 }, + { 0x2847D0303F5B9D4D, 0x6742F2F25DA67BDD, + 0xEF933BDC77C94195, 0xEAEDD9156E240867 } + }, + { + { 0x27F14CD19499A78F, 0x462AB5C56F9B3455, + 0x8F90F02AF02CFC6B, 0xB763891EB265230D }, + { 0xF59DA3A9532D4977, 0x21E3327DCF9EBA15, + 0x123C7B84BE60BBF0, 0x56EC12F27706DF76 } + }, + { + { 0x75C96E8F264E20E8, 0xABE6BFED59A7A841, + 0x2CC09C0444C8EB00, 0xE05B3080F0C4E16B }, + { 0x1EB7777AA45F3314, 0x56AF7BEDCE5D45E3, + 0x2B6E019A88B12F1A, 0x086659CDFD835F9B } + }, + { + { 0x2C18DBD19DC21EC8, 0x98F9868A0FCF8139, + 0x737D2CD648250B49, 0xCC61C94724B3428F }, + { 0x0C2B407880DD9E76, 0xC43A8991383FBE08, + 0x5F7D2D65779BE5D2, 0x78719A54EB3B4AB5 } + }, + { + { 0xEA7D260A6245E404, 0x9DE407956E7FDFE0, + 0x1FF3A4158DAC1AB5, 0x3E7090F1649C9073 }, + { 0x1A7685612B944E88, 0x250F939EE57F61C8, + 0x0C0DAA891EAD643D, 0x68930023E125B88E } + }, + { + { 0x04B71AA7D2697768, 0xABDEDEF5CA345A33, + 0x2409D29DEE37385E, 0x4EE1DF77CB83E156 }, + { 0x0CAC12D91CBB5B43, 0x170ED2F6CA895637, + 0x28228CFA8ADE6D66, 0x7FF57C9553238ACA } + }, + { + { 0xCCC425634B2ED709, 0x0E356769856FD30D, + 0xBCBCD43F559E9811, 0x738477AC5395B759 }, + { 0x35752B90C00EE17F, 0x68748390742ED2E3, + 0x7CD06422BD1F5BC1, 0xFBC08769C9E7B797 } + }, + { + { 0xA242A35BB0CF664A, 0x126E48F77F9707E3, + 0x1717BF54C6832660, 0xFAAE7332FD12C72E }, + { 0x27B52DB7995D586B, 0xBE29569E832237C2, + 0xE8E4193E2A65E7DB, 0x152706DC2EAA1BBB } + }, + { + { 0x72BCD8B7BC60055B, 0x03CC23EE56E27E4B, + 0xEE337424E4819370, 0xE2AA0E430AD3DA09 }, + { 0x40B8524F6383C45D, 0xD766355442A41B25, + 0x64EFA6DE778A4797, 0x2042170A7079ADF4 } + } +}; + +/* + * Multiply the conventional generator of the curve by the provided + * integer. Return is written in *P. + * + * Assumptions: + * - Integer is not 0, and is lower than the curve order. + * If this conditions is not met, then the result is indeterminate + * (but the process is still constant-time). + */ +static void +p256_mulgen(p256_jacobian *P, const unsigned char *k, size_t klen) +{ + point_mul_inner(P, P256_Gwin, k, klen); +} + +/* + * Return 1 if all of the following hold: + * - klen <= 32 + * - k != 0 + * - k is lower than the curve order + * Otherwise, return 0. + * + * Constant-time behaviour: only klen may be observable. + */ +static uint32_t +check_scalar(const unsigned char *k, size_t klen) +{ + uint32_t z; + int32_t c; + size_t u; + + if (klen > 32) { + return 0; + } + z = 0; + for (u = 0; u < klen; u ++) { + z |= k[u]; + } + if (klen == 32) { + c = 0; + for (u = 0; u < klen; u ++) { + c |= -(int32_t)EQ0(c) & CMP(k[u], P256_N[u]); + } + } else { + c = -1; + } + return NEQ(z, 0) & LT0(c); +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *k, size_t klen, int curve) +{ + uint32_t r; + p256_jacobian P; + + (void)curve; + if (Glen != 65) { + return 0; + } + r = check_scalar(k, klen); + r &= point_decode(&P, G); + p256_mul(&P, k, klen); + r &= point_encode(G, &P); + return r; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *k, size_t klen, int curve) +{ + p256_jacobian P; + + (void)curve; + p256_mulgen(&P, k, klen); + point_encode(R, &P); + return 65; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + /* + * We might want to use Shamir's trick here: make a composite + * window of u*P+v*Q points, to merge the two doubling-ladders + * into one. This, however, has some complications: + * + * - During the computation, we may hit the point-at-infinity. + * Thus, we would need p256_add_complete_mixed() (complete + * formulas for point addition), with a higher cost (17 muls + * instead of 11). + * + * - A 4-bit window would be too large, since it would involve + * 16*16-1 = 255 points. For the same window size as in the + * p256_mul() case, we would need to reduce the window size + * to 2 bits, and thus perform twice as many non-doubling + * point additions. + * + * - The window may itself contain the point-at-infinity, and + * thus cannot be in all generality be made of affine points. + * Instead, we would need to make it a window of points in + * Jacobian coordinates. Even p256_add_complete_mixed() would + * be inappropriate. + * + * For these reasons, the code below performs two separate + * point multiplications, then computes the final point addition + * (which is both a "normal" addition, and a doubling, to handle + * all cases). + */ + + p256_jacobian P, Q; + uint32_t r, t, s; + uint64_t z; + + (void)curve; + if (len != 65) { + return 0; + } + r = point_decode(&P, A); + p256_mul(&P, x, xlen); + if (B == NULL) { + p256_mulgen(&Q, y, ylen); + } else { + r &= point_decode(&Q, B); + p256_mul(&Q, y, ylen); + } + + /* + * The final addition may fail in case both points are equal. + */ + t = p256_add(&P, &Q); + f256_final_reduce(P.z); + z = P.z[0] | P.z[1] | P.z[2] | P.z[3]; + s = EQ((uint32_t)(z | (z >> 32)), 0); + p256_double(&Q); + + /* + * If s is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we + * have the following: + * + * s = 0, t = 0 return P (normal addition) + * s = 0, t = 1 return P (normal addition) + * s = 1, t = 0 return Q (a 'double' case) + * s = 1, t = 1 report an error (P+Q = 0) + */ + CCOPY(s & ~t, &P, &Q, sizeof Q); + point_encode(A, &P); + r &= ~(s & t); + return r; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_p256_m64 = { + (uint32_t)0x00800000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_p256_m64_get(void) +{ + return &br_ec_p256_m64; +} + +#else + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_p256_m64_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/ec/ec_prime_i15.c b/BearSSL-OG/libbearssl/src/ec/ec_prime_i15.c new file mode 100644 index 0000000..d4f5c2c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_prime_i15.c @@ -0,0 +1,824 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Parameters for supported curves: + * - field modulus p + * - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p) + * - b*R mod p (b is the second curve equation parameter) + */ + +static const uint16_t P256_P[] = { + 0x0111, + 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x003F, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x4000, 0x7FFF, + 0x7FFF, 0x0001 +}; + +static const uint16_t P256_R2[] = { + 0x0111, + 0x0000, 0x6000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFC, 0x7FFF, + 0x7FBF, 0x7FFF, 0x7FBF, 0x7FFF, 0x7FFF, 0x7FFF, 0x77FF, 0x7FFF, + 0x4FFF, 0x0000 +}; + +static const uint16_t P256_B[] = { + 0x0111, + 0x770C, 0x5EEF, 0x29C4, 0x3EC4, 0x6273, 0x0486, 0x4543, 0x3993, + 0x3C01, 0x6B56, 0x212E, 0x57EE, 0x4882, 0x204B, 0x7483, 0x3C16, + 0x0187, 0x0000 +}; + +static const uint16_t P384_P[] = { + 0x0199, + 0x7FFF, 0x7FFF, 0x0003, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FFF, + 0x7EFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, + 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, + 0x7FFF, 0x01FF +}; + +static const uint16_t P384_R2[] = { + 0x0199, + 0x1000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x0001, 0x0000, 0x0010, + 0x0000, 0x0000, 0x0000, 0x7F00, 0x7FFF, 0x01FF, 0x0000, 0x1000, + 0x0000, 0x2000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000 +}; + +static const uint16_t P384_B[] = { + 0x0199, + 0x7333, 0x2096, 0x70D1, 0x2310, 0x3020, 0x6197, 0x1464, 0x35BB, + 0x70CA, 0x0117, 0x1920, 0x4136, 0x5FC8, 0x5713, 0x4938, 0x7DD2, + 0x4DD2, 0x4A71, 0x0220, 0x683E, 0x2C87, 0x4DB1, 0x7BFF, 0x6C09, + 0x0452, 0x0084 +}; + +static const uint16_t P521_P[] = { + 0x022B, + 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, + 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, + 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, + 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, + 0x7FFF, 0x7FFF, 0x07FF +}; + +static const uint16_t P521_R2[] = { + 0x022B, + 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000 +}; + +static const uint16_t P521_B[] = { + 0x022B, + 0x7002, 0x6A07, 0x751A, 0x228F, 0x71EF, 0x5869, 0x20F4, 0x1EFC, + 0x7357, 0x37E0, 0x4EEC, 0x605E, 0x1652, 0x26F6, 0x31FA, 0x4A8F, + 0x6193, 0x3C2A, 0x3C42, 0x48C7, 0x3489, 0x6771, 0x4C57, 0x5CCD, + 0x2725, 0x545B, 0x503B, 0x5B42, 0x21A0, 0x2534, 0x687E, 0x70E4, + 0x1618, 0x27D7, 0x0465 +}; + +typedef struct { + const uint16_t *p; + const uint16_t *b; + const uint16_t *R2; + uint16_t p0i; + size_t point_len; +} curve_params; + +static __inline const curve_params * +id_to_curve(int curve) +{ + static const curve_params pp[] = { + { P256_P, P256_B, P256_R2, 0x0001, 65 }, + { P384_P, P384_B, P384_R2, 0x0001, 97 }, + { P521_P, P521_B, P521_R2, 0x0001, 133 } + }; + + return &pp[curve - BR_EC_secp256r1]; +} + +#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15) + +/* + * Type for a point in Jacobian coordinates: + * -- three values, x, y and z, in Montgomery representation + * -- affine coordinates are X = x / z^2 and Y = y / z^3 + * -- for the point at infinity, z = 0 + */ +typedef struct { + uint16_t c[3][I15_LEN]; +} jacobian; + +/* + * We use a custom interpreter that uses a dozen registers, and + * only six operations: + * MSET(d, a) copy a into d + * MADD(d, a) d = d+a (modular) + * MSUB(d, a) d = d-a (modular) + * MMUL(d, a, b) d = a*b (Montgomery multiplication) + * MINV(d, a, b) invert d modulo p; a and b are used as scratch registers + * MTZ(d) clear return value if d = 0 + * Destination of MMUL (d) must be distinct from operands (a and b). + * There is no such constraint for MSUB and MADD. + * + * Registers include the operand coordinates, and temporaries. + */ +#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4)) +#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4)) +#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4)) +#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b)) +#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b)) +#define MTZ(d) (0x5000 + ((d) << 8)) +#define ENDCODE 0 + +/* + * Registers for the input operands. + */ +#define P1x 0 +#define P1y 1 +#define P1z 2 +#define P2x 3 +#define P2y 4 +#define P2z 5 + +/* + * Alternate names for the first input operand. + */ +#define Px 0 +#define Py 1 +#define Pz 2 + +/* + * Temporaries. + */ +#define t1 6 +#define t2 7 +#define t3 8 +#define t4 9 +#define t5 10 +#define t6 11 +#define t7 12 + +/* + * Extra scratch registers available when there is no second operand (e.g. + * for "double" and "affine"). + */ +#define t8 3 +#define t9 4 +#define t10 5 + +/* + * Doubling formulas are: + * + * s = 4*x*y^2 + * m = 3*(x + z^2)*(x - z^2) + * x' = m^2 - 2*s + * y' = m*(s - x') - 8*y^4 + * z' = 2*y*z + * + * If y = 0 (P has order 2) then this yields infinity (z' = 0), as it + * should. This case should not happen anyway, because our curves have + * prime order, and thus do not contain any point of order 2. + * + * If P is infinity (z = 0), then again the formulas yield infinity, + * which is correct. Thus, this code works for all points. + * + * Cost: 8 multiplications + */ +static const uint16_t code_double[] = { + /* + * Compute z^2 (in t1). + */ + MMUL(t1, Pz, Pz), + + /* + * Compute x-z^2 (in t2) and then x+z^2 (in t1). + */ + MSET(t2, Px), + MSUB(t2, t1), + MADD(t1, Px), + + /* + * Compute m = 3*(x+z^2)*(x-z^2) (in t1). + */ + MMUL(t3, t1, t2), + MSET(t1, t3), + MADD(t1, t3), + MADD(t1, t3), + + /* + * Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3). + */ + MMUL(t3, Py, Py), + MADD(t3, t3), + MMUL(t2, Px, t3), + MADD(t2, t2), + + /* + * Compute x' = m^2 - 2*s. + */ + MMUL(Px, t1, t1), + MSUB(Px, t2), + MSUB(Px, t2), + + /* + * Compute z' = 2*y*z. + */ + MMUL(t4, Py, Pz), + MSET(Pz, t4), + MADD(Pz, t4), + + /* + * Compute y' = m*(s - x') - 8*y^4. Note that we already have + * 2*y^2 in t3. + */ + MSUB(t2, Px), + MMUL(Py, t1, t2), + MMUL(t4, t3, t3), + MSUB(Py, t4), + MSUB(Py, t4), + + ENDCODE +}; + +/* + * Addtions formulas are: + * + * u1 = x1 * z2^2 + * u2 = x2 * z1^2 + * s1 = y1 * z2^3 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 * z2 + * + * If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that + * z3 == 0, so the result is correct. + * If either of P1 or P2 is infinity, but not both, then z3 == 0, which is + * not correct. + * h == 0 only if u1 == u2; this happens in two cases: + * -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2 + * -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity) + * + * Thus, the following situations are not handled correctly: + * -- P1 = 0 and P2 != 0 + * -- P1 != 0 and P2 = 0 + * -- P1 = P2 + * All other cases are properly computed. However, even in "incorrect" + * situations, the three coordinates still are properly formed field + * elements. + * + * The returned flag is cleared if r == 0. This happens in the following + * cases: + * -- Both points are on the same horizontal line (same Y coordinate). + * -- Both points are infinity. + * -- One point is infinity and the other is on line Y = 0. + * The third case cannot happen with our curves (there is no valid point + * on line Y = 0 since that would be a point of order 2). If the two + * source points are non-infinity, then remains only the case where the + * two points are on the same horizontal line. + * + * This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and + * P2 != 0: + * -- If the returned value is not the point at infinity, then it was properly + * computed. + * -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result + * is indeed the point at infinity. + * -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should + * use the 'double' code. + * + * Cost: 16 multiplications + */ +static const uint16_t code_add[] = { + /* + * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). + */ + MMUL(t3, P2z, P2z), + MMUL(t1, P1x, t3), + MMUL(t4, P2z, t3), + MMUL(t3, P1y, t4), + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + MMUL(t4, P1z, P1z), + MMUL(t2, P2x, t4), + MMUL(t5, P1z, t4), + MMUL(t4, P2y, t5), + + /* + * Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4). + */ + MSUB(t2, t1), + MSUB(t4, t3), + + /* + * Report cases where r = 0 through the returned flag. + */ + MTZ(t4), + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5). + */ + MMUL(t7, t2, t2), + MMUL(t6, t1, t7), + MMUL(t5, t7, t2), + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + * t1 and t7 can be used as scratch registers. + */ + MMUL(P1x, t4, t4), + MSUB(P1x, t5), + MSUB(P1x, t6), + MSUB(P1x, t6), + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + MSUB(t6, P1x), + MMUL(P1y, t4, t6), + MMUL(t1, t5, t3), + MSUB(P1y, t1), + + /* + * Compute z3 = h*z1*z2. + */ + MMUL(t1, P1z, P2z), + MMUL(P1z, t1, t2), + + ENDCODE +}; + +/* + * Check that the point is on the curve. This code snippet assumes the + * following conventions: + * -- Coordinates x and y have been freshly decoded in P1 (but not + * converted to Montgomery coordinates yet). + * -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1. + */ +static const uint16_t code_check[] = { + + /* Convert x and y to Montgomery representation. */ + MMUL(t1, P1x, P2x), + MMUL(t2, P1y, P2x), + MSET(P1x, t1), + MSET(P1y, t2), + + /* Compute x^3 in t1. */ + MMUL(t2, P1x, P1x), + MMUL(t1, P1x, t2), + + /* Subtract 3*x from t1. */ + MSUB(t1, P1x), + MSUB(t1, P1x), + MSUB(t1, P1x), + + /* Add b. */ + MADD(t1, P2y), + + /* Compute y^2 in t2. */ + MMUL(t2, P1y, P1y), + + /* Compare y^2 with x^3 - 3*x + b; they must match. */ + MSUB(t1, t2), + MTZ(t1), + + /* Set z to 1 (in Montgomery representation). */ + MMUL(P1z, P2x, P2z), + + ENDCODE +}; + +/* + * Conversion back to affine coordinates. This code snippet assumes that + * the z coordinate of P2 is set to 1 (not in Montgomery representation). + */ +static const uint16_t code_affine[] = { + + /* Save z*R in t1. */ + MSET(t1, P1z), + + /* Compute z^3 in t2. */ + MMUL(t2, P1z, P1z), + MMUL(t3, P1z, t2), + MMUL(t2, t3, P2z), + + /* Invert to (1/z^3) in t2. */ + MINV(t2, t3, t4), + + /* Compute y. */ + MSET(t3, P1y), + MMUL(P1y, t2, t3), + + /* Compute (1/z^2) in t3. */ + MMUL(t3, t2, t1), + + /* Compute x. */ + MSET(t2, P1x), + MMUL(P1x, t2, t3), + + ENDCODE +}; + +static uint32_t +run_code(jacobian *P1, const jacobian *P2, + const curve_params *cc, const uint16_t *code) +{ + uint32_t r; + uint16_t t[13][I15_LEN]; + size_t u; + + r = 1; + + /* + * Copy the two operands in the dedicated registers. + */ + memcpy(t[P1x], P1->c, 3 * I15_LEN * sizeof(uint16_t)); + memcpy(t[P2x], P2->c, 3 * I15_LEN * sizeof(uint16_t)); + + /* + * Run formulas. + */ + for (u = 0;; u ++) { + unsigned op, d, a, b; + + op = code[u]; + if (op == 0) { + break; + } + d = (op >> 8) & 0x0F; + a = (op >> 4) & 0x0F; + b = op & 0x0F; + op >>= 12; + switch (op) { + uint32_t ctl; + size_t plen; + unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3]; + + case 0: + memcpy(t[d], t[a], I15_LEN * sizeof(uint16_t)); + break; + case 1: + ctl = br_i15_add(t[d], t[a], 1); + ctl |= NOT(br_i15_sub(t[d], cc->p, 0)); + br_i15_sub(t[d], cc->p, ctl); + break; + case 2: + br_i15_add(t[d], cc->p, br_i15_sub(t[d], t[a], 1)); + break; + case 3: + br_i15_montymul(t[d], t[a], t[b], cc->p, cc->p0i); + break; + case 4: + plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3; + br_i15_encode(tp, plen, cc->p); + tp[plen - 1] -= 2; + br_i15_modpow(t[d], tp, plen, + cc->p, cc->p0i, t[a], t[b]); + break; + default: + r &= ~br_i15_iszero(t[d]); + break; + } + } + + /* + * Copy back result. + */ + memcpy(P1->c, t[P1x], 3 * I15_LEN * sizeof(uint16_t)); + return r; +} + +static void +set_one(uint16_t *x, const uint16_t *p) +{ + size_t plen; + + plen = (p[0] + 31) >> 4; + memset(x, 0, plen * sizeof *x); + x[0] = p[0]; + x[1] = 0x0001; +} + +static void +point_zero(jacobian *P, const curve_params *cc) +{ + memset(P, 0, sizeof *P); + P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0]; +} + +static __inline void +point_double(jacobian *P, const curve_params *cc) +{ + run_code(P, P, cc, code_double); +} + +static __inline uint32_t +point_add(jacobian *P1, const jacobian *P2, const curve_params *cc) +{ + return run_code(P1, P2, cc, code_add); +} + +static void +point_mul(jacobian *P, const unsigned char *x, size_t xlen, + const curve_params *cc) +{ + /* + * We do a simple double-and-add ladder with a 2-bit window + * to make only one add every two doublings. We thus first + * precompute 2P and 3P in some local buffers. + * + * We always perform two doublings and one addition; the + * addition is with P, 2P and 3P and is done in a temporary + * array. + * + * The addition code cannot handle cases where one of the + * operands is infinity, which is the case at the start of the + * ladder. We therefore need to maintain a flag that controls + * this situation. + */ + uint32_t qz; + jacobian P2, P3, Q, T, U; + + memcpy(&P2, P, sizeof P2); + point_double(&P2, cc); + memcpy(&P3, P, sizeof P3); + point_add(&P3, &P2, cc); + + point_zero(&Q, cc); + qz = 1; + while (xlen -- > 0) { + int k; + + for (k = 6; k >= 0; k -= 2) { + uint32_t bits; + uint32_t bnz; + + point_double(&Q, cc); + point_double(&Q, cc); + memcpy(&T, P, sizeof T); + memcpy(&U, &Q, sizeof U); + bits = (*x >> k) & (uint32_t)3; + bnz = NEQ(bits, 0); + CCOPY(EQ(bits, 2), &T, &P2, sizeof T); + CCOPY(EQ(bits, 3), &T, &P3, sizeof T); + point_add(&U, &T, cc); + CCOPY(bnz & qz, &Q, &T, sizeof Q); + CCOPY(bnz & ~qz, &Q, &U, sizeof Q); + qz &= ~bnz; + } + x ++; + } + memcpy(P, &Q, sizeof Q); +} + +/* + * Decode point into Jacobian coordinates. This function does not support + * the point at infinity. If the point is invalid then this returns 0, but + * the coordinates are still set to properly formed field elements. + */ +static uint32_t +point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc) +{ + /* + * Points must use uncompressed format: + * -- first byte is 0x04; + * -- coordinates X and Y use unsigned big-endian, with the same + * length as the field modulus. + * + * We don't support hybrid format (uncompressed, but first byte + * has value 0x06 or 0x07, depending on the least significant bit + * of Y) because it is rather useless, and explicitly forbidden + * by PKIX (RFC 5480, section 2.2). + * + * We don't support compressed format either, because it is not + * much used in practice (there are or were patent-related + * concerns about point compression, which explains the lack of + * generalised support). Also, point compression support would + * need a bit more code. + */ + const unsigned char *buf; + size_t plen, zlen; + uint32_t r; + jacobian Q; + + buf = src; + point_zero(P, cc); + plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3; + if (len != 1 + (plen << 1)) { + return 0; + } + r = br_i15_decode_mod(P->c[0], buf + 1, plen, cc->p); + r &= br_i15_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p); + + /* + * Check first byte. + */ + r &= EQ(buf[0], 0x04); + /* obsolete + r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06) + & ~(uint32_t)(buf[0] ^ buf[plen << 1])); + */ + + /* + * Convert coordinates and check that the point is valid. + */ + zlen = ((cc->p[0] + 31) >> 4) * sizeof(uint16_t); + memcpy(Q.c[0], cc->R2, zlen); + memcpy(Q.c[1], cc->b, zlen); + set_one(Q.c[2], cc->p); + r &= ~run_code(P, &Q, cc, code_check); + return r; +} + +/* + * Encode a point. This method assumes that the point is correct and is + * not the point at infinity. Encoded size is always 1+2*plen, where + * plen is the field modulus length, in bytes. + */ +static void +point_encode(void *dst, const jacobian *P, const curve_params *cc) +{ + unsigned char *buf; + size_t plen; + jacobian Q, T; + + buf = dst; + plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3; + buf[0] = 0x04; + memcpy(&Q, P, sizeof *P); + set_one(T.c[2], cc->p); + run_code(&Q, &T, cc, code_affine); + br_i15_encode(buf + 1, plen, Q.c[0]); + br_i15_encode(buf + 1 + plen, plen, Q.c[1]); +} + +static const br_ec_curve_def * +id_to_curve_def(int curve) +{ + switch (curve) { + case BR_EC_secp256r1: + return &br_secp256r1; + case BR_EC_secp384r1: + return &br_secp384r1; + case BR_EC_secp521r1: + return &br_secp521r1; + } + return NULL; +} + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + const br_ec_curve_def *cd; + + cd = id_to_curve_def(curve); + *len = cd->generator_len; + return cd->generator; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + const br_ec_curve_def *cd; + + cd = id_to_curve_def(curve); + *len = cd->order_len; + return cd->order; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + api_generator(curve, len); + *len >>= 1; + return 1; +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *x, size_t xlen, int curve) +{ + uint32_t r; + const curve_params *cc; + jacobian P; + + cc = id_to_curve(curve); + if (Glen != cc->point_len) { + return 0; + } + r = point_decode(&P, G, Glen, cc); + point_mul(&P, x, xlen, cc); + point_encode(G, &P, cc); + return r; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + const unsigned char *G; + size_t Glen; + + G = api_generator(curve, &Glen); + memcpy(R, G, Glen); + api_mul(R, Glen, x, xlen, curve); + return Glen; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + uint32_t r, t, z; + const curve_params *cc; + jacobian P, Q; + + /* + * TODO: see about merging the two ladders. Right now, we do + * two independent point multiplications, which is a bit + * wasteful of CPU resources (but yields short code). + */ + + cc = id_to_curve(curve); + if (len != cc->point_len) { + return 0; + } + r = point_decode(&P, A, len, cc); + if (B == NULL) { + size_t Glen; + + B = api_generator(curve, &Glen); + } + r &= point_decode(&Q, B, len, cc); + point_mul(&P, x, xlen, cc); + point_mul(&Q, y, ylen, cc); + + /* + * We want to compute P+Q. Since the base points A and B are distinct + * from infinity, and the multipliers are non-zero and lower than the + * curve order, then we know that P and Q are non-infinity. This + * leaves two special situations to test for: + * -- If P = Q then we must use point_double(). + * -- If P+Q = 0 then we must report an error. + */ + t = point_add(&P, &Q, cc); + point_double(&Q, cc); + z = br_i15_iszero(P.c[2]); + + /* + * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we + * have the following: + * + * z = 0, t = 0 return P (normal addition) + * z = 0, t = 1 return P (normal addition) + * z = 1, t = 0 return Q (a 'double' case) + * z = 1, t = 1 report an error (P+Q = 0) + */ + CCOPY(z & ~t, &P, &Q, sizeof Q); + point_encode(A, &P, cc); + r &= ~(z & t); + + return r; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_prime_i15 = { + (uint32_t)0x03800000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_prime_i31.c b/BearSSL-OG/libbearssl/src/ec/ec_prime_i31.c new file mode 100644 index 0000000..8a977bd --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_prime_i31.c @@ -0,0 +1,826 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * Parameters for supported curves (field modulus, and 'b' equation + * parameter; both values use the 'i31' format, and 'b' is in Montgomery + * representation). + */ + +static const uint32_t P256_P[] = { + 0x00000108, + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007, + 0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80, + 0x000000FF +}; + +static const uint32_t P256_R2[] = { + 0x00000108, + 0x00014000, 0x00018000, 0x00000000, 0x7FF40000, + 0x7FEFFFFF, 0x7FF7FFFF, 0x7FAFFFFF, 0x005FFFFF, + 0x00000000 +}; + +static const uint32_t P256_B[] = { + 0x00000108, + 0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA, + 0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D, + 0x0000000E +}; + +static const uint32_t P384_P[] = { + 0x0000018C, + 0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8, + 0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, + 0x00000FFF +}; + +static const uint32_t P384_R2[] = { + 0x0000018C, + 0x00000000, 0x00000080, 0x7FFFFE00, 0x000001FF, + 0x00000800, 0x00000000, 0x7FFFE000, 0x00001FFF, + 0x00008000, 0x00008000, 0x00000000, 0x00000000, + 0x00000000 +}; + +static const uint32_t P384_B[] = { + 0x0000018C, + 0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C, + 0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B, + 0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE, + 0x000008A5 +}; + +static const uint32_t P521_P[] = { + 0x00000219, + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, + 0x01FFFFFF +}; + +static const uint32_t P521_R2[] = { + 0x00000219, + 0x00001000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000 +}; + +static const uint32_t P521_B[] = { + 0x00000219, + 0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A, + 0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F, + 0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366, + 0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393, + 0x00654FAE +}; + +typedef struct { + const uint32_t *p; + const uint32_t *b; + const uint32_t *R2; + uint32_t p0i; + size_t point_len; +} curve_params; + +static __inline const curve_params * +id_to_curve(int curve) +{ + static const curve_params pp[] = { + { P256_P, P256_B, P256_R2, 0x00000001, 65 }, + { P384_P, P384_B, P384_R2, 0x00000001, 97 }, + { P521_P, P521_B, P521_R2, 0x00000001, 133 } + }; + + return &pp[curve - BR_EC_secp256r1]; +} + +#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31) + +/* + * Type for a point in Jacobian coordinates: + * -- three values, x, y and z, in Montgomery representation + * -- affine coordinates are X = x / z^2 and Y = y / z^3 + * -- for the point at infinity, z = 0 + */ +typedef struct { + uint32_t c[3][I31_LEN]; +} jacobian; + +/* + * We use a custom interpreter that uses a dozen registers, and + * only six operations: + * MSET(d, a) copy a into d + * MADD(d, a) d = d+a (modular) + * MSUB(d, a) d = d-a (modular) + * MMUL(d, a, b) d = a*b (Montgomery multiplication) + * MINV(d, a, b) invert d modulo p; a and b are used as scratch registers + * MTZ(d) clear return value if d = 0 + * Destination of MMUL (d) must be distinct from operands (a and b). + * There is no such constraint for MSUB and MADD. + * + * Registers include the operand coordinates, and temporaries. + */ +#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4)) +#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4)) +#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4)) +#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b)) +#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b)) +#define MTZ(d) (0x5000 + ((d) << 8)) +#define ENDCODE 0 + +/* + * Registers for the input operands. + */ +#define P1x 0 +#define P1y 1 +#define P1z 2 +#define P2x 3 +#define P2y 4 +#define P2z 5 + +/* + * Alternate names for the first input operand. + */ +#define Px 0 +#define Py 1 +#define Pz 2 + +/* + * Temporaries. + */ +#define t1 6 +#define t2 7 +#define t3 8 +#define t4 9 +#define t5 10 +#define t6 11 +#define t7 12 + +/* + * Extra scratch registers available when there is no second operand (e.g. + * for "double" and "affine"). + */ +#define t8 3 +#define t9 4 +#define t10 5 + +/* + * Doubling formulas are: + * + * s = 4*x*y^2 + * m = 3*(x + z^2)*(x - z^2) + * x' = m^2 - 2*s + * y' = m*(s - x') - 8*y^4 + * z' = 2*y*z + * + * If y = 0 (P has order 2) then this yields infinity (z' = 0), as it + * should. This case should not happen anyway, because our curves have + * prime order, and thus do not contain any point of order 2. + * + * If P is infinity (z = 0), then again the formulas yield infinity, + * which is correct. Thus, this code works for all points. + * + * Cost: 8 multiplications + */ +static const uint16_t code_double[] = { + /* + * Compute z^2 (in t1). + */ + MMUL(t1, Pz, Pz), + + /* + * Compute x-z^2 (in t2) and then x+z^2 (in t1). + */ + MSET(t2, Px), + MSUB(t2, t1), + MADD(t1, Px), + + /* + * Compute m = 3*(x+z^2)*(x-z^2) (in t1). + */ + MMUL(t3, t1, t2), + MSET(t1, t3), + MADD(t1, t3), + MADD(t1, t3), + + /* + * Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3). + */ + MMUL(t3, Py, Py), + MADD(t3, t3), + MMUL(t2, Px, t3), + MADD(t2, t2), + + /* + * Compute x' = m^2 - 2*s. + */ + MMUL(Px, t1, t1), + MSUB(Px, t2), + MSUB(Px, t2), + + /* + * Compute z' = 2*y*z. + */ + MMUL(t4, Py, Pz), + MSET(Pz, t4), + MADD(Pz, t4), + + /* + * Compute y' = m*(s - x') - 8*y^4. Note that we already have + * 2*y^2 in t3. + */ + MSUB(t2, Px), + MMUL(Py, t1, t2), + MMUL(t4, t3, t3), + MSUB(Py, t4), + MSUB(Py, t4), + + ENDCODE +}; + +/* + * Addtions formulas are: + * + * u1 = x1 * z2^2 + * u2 = x2 * z1^2 + * s1 = y1 * z2^3 + * s2 = y2 * z1^3 + * h = u2 - u1 + * r = s2 - s1 + * x3 = r^2 - h^3 - 2 * u1 * h^2 + * y3 = r * (u1 * h^2 - x3) - s1 * h^3 + * z3 = h * z1 * z2 + * + * If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that + * z3 == 0, so the result is correct. + * If either of P1 or P2 is infinity, but not both, then z3 == 0, which is + * not correct. + * h == 0 only if u1 == u2; this happens in two cases: + * -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2 + * -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity) + * + * Thus, the following situations are not handled correctly: + * -- P1 = 0 and P2 != 0 + * -- P1 != 0 and P2 = 0 + * -- P1 = P2 + * All other cases are properly computed. However, even in "incorrect" + * situations, the three coordinates still are properly formed field + * elements. + * + * The returned flag is cleared if r == 0. This happens in the following + * cases: + * -- Both points are on the same horizontal line (same Y coordinate). + * -- Both points are infinity. + * -- One point is infinity and the other is on line Y = 0. + * The third case cannot happen with our curves (there is no valid point + * on line Y = 0 since that would be a point of order 2). If the two + * source points are non-infinity, then remains only the case where the + * two points are on the same horizontal line. + * + * This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and + * P2 != 0: + * -- If the returned value is not the point at infinity, then it was properly + * computed. + * -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result + * is indeed the point at infinity. + * -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should + * use the 'double' code. + * + * Cost: 16 multiplications + */ +static const uint16_t code_add[] = { + /* + * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). + */ + MMUL(t3, P2z, P2z), + MMUL(t1, P1x, t3), + MMUL(t4, P2z, t3), + MMUL(t3, P1y, t4), + + /* + * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). + */ + MMUL(t4, P1z, P1z), + MMUL(t2, P2x, t4), + MMUL(t5, P1z, t4), + MMUL(t4, P2y, t5), + + /* + * Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4). + */ + MSUB(t2, t1), + MSUB(t4, t3), + + /* + * Report cases where r = 0 through the returned flag. + */ + MTZ(t4), + + /* + * Compute u1*h^2 (in t6) and h^3 (in t5). + */ + MMUL(t7, t2, t2), + MMUL(t6, t1, t7), + MMUL(t5, t7, t2), + + /* + * Compute x3 = r^2 - h^3 - 2*u1*h^2. + * t1 and t7 can be used as scratch registers. + */ + MMUL(P1x, t4, t4), + MSUB(P1x, t5), + MSUB(P1x, t6), + MSUB(P1x, t6), + + /* + * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. + */ + MSUB(t6, P1x), + MMUL(P1y, t4, t6), + MMUL(t1, t5, t3), + MSUB(P1y, t1), + + /* + * Compute z3 = h*z1*z2. + */ + MMUL(t1, P1z, P2z), + MMUL(P1z, t1, t2), + + ENDCODE +}; + +/* + * Check that the point is on the curve. This code snippet assumes the + * following conventions: + * -- Coordinates x and y have been freshly decoded in P1 (but not + * converted to Montgomery coordinates yet). + * -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1. + */ +static const uint16_t code_check[] = { + + /* Convert x and y to Montgomery representation. */ + MMUL(t1, P1x, P2x), + MMUL(t2, P1y, P2x), + MSET(P1x, t1), + MSET(P1y, t2), + + /* Compute x^3 in t1. */ + MMUL(t2, P1x, P1x), + MMUL(t1, P1x, t2), + + /* Subtract 3*x from t1. */ + MSUB(t1, P1x), + MSUB(t1, P1x), + MSUB(t1, P1x), + + /* Add b. */ + MADD(t1, P2y), + + /* Compute y^2 in t2. */ + MMUL(t2, P1y, P1y), + + /* Compare y^2 with x^3 - 3*x + b; they must match. */ + MSUB(t1, t2), + MTZ(t1), + + /* Set z to 1 (in Montgomery representation). */ + MMUL(P1z, P2x, P2z), + + ENDCODE +}; + +/* + * Conversion back to affine coordinates. This code snippet assumes that + * the z coordinate of P2 is set to 1 (not in Montgomery representation). + */ +static const uint16_t code_affine[] = { + + /* Save z*R in t1. */ + MSET(t1, P1z), + + /* Compute z^3 in t2. */ + MMUL(t2, P1z, P1z), + MMUL(t3, P1z, t2), + MMUL(t2, t3, P2z), + + /* Invert to (1/z^3) in t2. */ + MINV(t2, t3, t4), + + /* Compute y. */ + MSET(t3, P1y), + MMUL(P1y, t2, t3), + + /* Compute (1/z^2) in t3. */ + MMUL(t3, t2, t1), + + /* Compute x. */ + MSET(t2, P1x), + MMUL(P1x, t2, t3), + + ENDCODE +}; + +static uint32_t +run_code(jacobian *P1, const jacobian *P2, + const curve_params *cc, const uint16_t *code) +{ + uint32_t r; + uint32_t t[13][I31_LEN]; + size_t u; + + r = 1; + + /* + * Copy the two operands in the dedicated registers. + */ + memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t)); + memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t)); + + /* + * Run formulas. + */ + for (u = 0;; u ++) { + unsigned op, d, a, b; + + op = code[u]; + if (op == 0) { + break; + } + d = (op >> 8) & 0x0F; + a = (op >> 4) & 0x0F; + b = op & 0x0F; + op >>= 12; + switch (op) { + uint32_t ctl; + size_t plen; + unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3]; + + case 0: + memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t)); + break; + case 1: + ctl = br_i31_add(t[d], t[a], 1); + ctl |= NOT(br_i31_sub(t[d], cc->p, 0)); + br_i31_sub(t[d], cc->p, ctl); + break; + case 2: + br_i31_add(t[d], cc->p, br_i31_sub(t[d], t[a], 1)); + break; + case 3: + br_i31_montymul(t[d], t[a], t[b], cc->p, cc->p0i); + break; + case 4: + plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3; + br_i31_encode(tp, plen, cc->p); + tp[plen - 1] -= 2; + br_i31_modpow(t[d], tp, plen, + cc->p, cc->p0i, t[a], t[b]); + break; + default: + r &= ~br_i31_iszero(t[d]); + break; + } + } + + /* + * Copy back result. + */ + memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t)); + return r; +} + +static void +set_one(uint32_t *x, const uint32_t *p) +{ + size_t plen; + + plen = (p[0] + 63) >> 5; + memset(x, 0, plen * sizeof *x); + x[0] = p[0]; + x[1] = 0x00000001; +} + +static void +point_zero(jacobian *P, const curve_params *cc) +{ + memset(P, 0, sizeof *P); + P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0]; +} + +static __inline void +point_double(jacobian *P, const curve_params *cc) +{ + run_code(P, P, cc, code_double); +} + +static __inline uint32_t +point_add(jacobian *P1, const jacobian *P2, const curve_params *cc) +{ + return run_code(P1, P2, cc, code_add); +} + +static void +point_mul(jacobian *P, const unsigned char *x, size_t xlen, + const curve_params *cc) +{ + /* + * We do a simple double-and-add ladder with a 2-bit window + * to make only one add every two doublings. We thus first + * precompute 2P and 3P in some local buffers. + * + * We always perform two doublings and one addition; the + * addition is with P, 2P and 3P and is done in a temporary + * array. + * + * The addition code cannot handle cases where one of the + * operands is infinity, which is the case at the start of the + * ladder. We therefore need to maintain a flag that controls + * this situation. + */ + uint32_t qz; + jacobian P2, P3, Q, T, U; + + memcpy(&P2, P, sizeof P2); + point_double(&P2, cc); + memcpy(&P3, P, sizeof P3); + point_add(&P3, &P2, cc); + + point_zero(&Q, cc); + qz = 1; + while (xlen -- > 0) { + int k; + + for (k = 6; k >= 0; k -= 2) { + uint32_t bits; + uint32_t bnz; + + point_double(&Q, cc); + point_double(&Q, cc); + memcpy(&T, P, sizeof T); + memcpy(&U, &Q, sizeof U); + bits = (*x >> k) & (uint32_t)3; + bnz = NEQ(bits, 0); + CCOPY(EQ(bits, 2), &T, &P2, sizeof T); + CCOPY(EQ(bits, 3), &T, &P3, sizeof T); + point_add(&U, &T, cc); + CCOPY(bnz & qz, &Q, &T, sizeof Q); + CCOPY(bnz & ~qz, &Q, &U, sizeof Q); + qz &= ~bnz; + } + x ++; + } + memcpy(P, &Q, sizeof Q); +} + +/* + * Decode point into Jacobian coordinates. This function does not support + * the point at infinity. If the point is invalid then this returns 0, but + * the coordinates are still set to properly formed field elements. + */ +static uint32_t +point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc) +{ + /* + * Points must use uncompressed format: + * -- first byte is 0x04; + * -- coordinates X and Y use unsigned big-endian, with the same + * length as the field modulus. + * + * We don't support hybrid format (uncompressed, but first byte + * has value 0x06 or 0x07, depending on the least significant bit + * of Y) because it is rather useless, and explicitly forbidden + * by PKIX (RFC 5480, section 2.2). + * + * We don't support compressed format either, because it is not + * much used in practice (there are or were patent-related + * concerns about point compression, which explains the lack of + * generalised support). Also, point compression support would + * need a bit more code. + */ + const unsigned char *buf; + size_t plen, zlen; + uint32_t r; + jacobian Q; + + buf = src; + point_zero(P, cc); + plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3; + if (len != 1 + (plen << 1)) { + return 0; + } + r = br_i31_decode_mod(P->c[0], buf + 1, plen, cc->p); + r &= br_i31_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p); + + /* + * Check first byte. + */ + r &= EQ(buf[0], 0x04); + /* obsolete + r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06) + & ~(uint32_t)(buf[0] ^ buf[plen << 1])); + */ + + /* + * Convert coordinates and check that the point is valid. + */ + zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t); + memcpy(Q.c[0], cc->R2, zlen); + memcpy(Q.c[1], cc->b, zlen); + set_one(Q.c[2], cc->p); + r &= ~run_code(P, &Q, cc, code_check); + return r; +} + +/* + * Encode a point. This method assumes that the point is correct and is + * not the point at infinity. Encoded size is always 1+2*plen, where + * plen is the field modulus length, in bytes. + */ +static void +point_encode(void *dst, const jacobian *P, const curve_params *cc) +{ + unsigned char *buf; + uint32_t xbl; + size_t plen; + jacobian Q, T; + + buf = dst; + xbl = cc->p[0]; + xbl -= (xbl >> 5); + plen = (xbl + 7) >> 3; + buf[0] = 0x04; + memcpy(&Q, P, sizeof *P); + set_one(T.c[2], cc->p); + run_code(&Q, &T, cc, code_affine); + br_i31_encode(buf + 1, plen, Q.c[0]); + br_i31_encode(buf + 1 + plen, plen, Q.c[1]); +} + +static const br_ec_curve_def * +id_to_curve_def(int curve) +{ + switch (curve) { + case BR_EC_secp256r1: + return &br_secp256r1; + case BR_EC_secp384r1: + return &br_secp384r1; + case BR_EC_secp521r1: + return &br_secp521r1; + } + return NULL; +} + +static const unsigned char * +api_generator(int curve, size_t *len) +{ + const br_ec_curve_def *cd; + + cd = id_to_curve_def(curve); + *len = cd->generator_len; + return cd->generator; +} + +static const unsigned char * +api_order(int curve, size_t *len) +{ + const br_ec_curve_def *cd; + + cd = id_to_curve_def(curve); + *len = cd->order_len; + return cd->order; +} + +static size_t +api_xoff(int curve, size_t *len) +{ + api_generator(curve, len); + *len >>= 1; + return 1; +} + +static uint32_t +api_mul(unsigned char *G, size_t Glen, + const unsigned char *x, size_t xlen, int curve) +{ + uint32_t r; + const curve_params *cc; + jacobian P; + + cc = id_to_curve(curve); + if (Glen != cc->point_len) { + return 0; + } + r = point_decode(&P, G, Glen, cc); + point_mul(&P, x, xlen, cc); + point_encode(G, &P, cc); + return r; +} + +static size_t +api_mulgen(unsigned char *R, + const unsigned char *x, size_t xlen, int curve) +{ + const unsigned char *G; + size_t Glen; + + G = api_generator(curve, &Glen); + memcpy(R, G, Glen); + api_mul(R, Glen, x, xlen, curve); + return Glen; +} + +static uint32_t +api_muladd(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve) +{ + uint32_t r, t, z; + const curve_params *cc; + jacobian P, Q; + + /* + * TODO: see about merging the two ladders. Right now, we do + * two independent point multiplications, which is a bit + * wasteful of CPU resources (but yields short code). + */ + + cc = id_to_curve(curve); + if (len != cc->point_len) { + return 0; + } + r = point_decode(&P, A, len, cc); + if (B == NULL) { + size_t Glen; + + B = api_generator(curve, &Glen); + } + r &= point_decode(&Q, B, len, cc); + point_mul(&P, x, xlen, cc); + point_mul(&Q, y, ylen, cc); + + /* + * We want to compute P+Q. Since the base points A and B are distinct + * from infinity, and the multipliers are non-zero and lower than the + * curve order, then we know that P and Q are non-infinity. This + * leaves two special situations to test for: + * -- If P = Q then we must use point_double(). + * -- If P+Q = 0 then we must report an error. + */ + t = point_add(&P, &Q, cc); + point_double(&Q, cc); + z = br_i31_iszero(P.c[2]); + + /* + * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we + * have the following: + * + * z = 0, t = 0 return P (normal addition) + * z = 0, t = 1 return P (normal addition) + * z = 1, t = 0 return Q (a 'double' case) + * z = 1, t = 1 report an error (P+Q = 0) + */ + CCOPY(z & ~t, &P, &Q, sizeof Q); + point_encode(A, &P, cc); + r &= ~(z & t); + + return r; +} + +/* see bearssl_ec.h */ +const br_ec_impl br_ec_prime_i31 = { + (uint32_t)0x03800000, + &api_generator, + &api_order, + &api_xoff, + &api_mul, + &api_mulgen, + &api_muladd +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_pubkey.c b/BearSSL-OG/libbearssl/src/ec/ec_pubkey.c new file mode 100644 index 0000000..383ff28 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_pubkey.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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 const unsigned char POINT_LEN[] = { + 0, /* 0: not a valid curve ID */ + 43, /* sect163k1 */ + 43, /* sect163r1 */ + 43, /* sect163r2 */ + 51, /* sect193r1 */ + 51, /* sect193r2 */ + 61, /* sect233k1 */ + 61, /* sect233r1 */ + 61, /* sect239k1 */ + 73, /* sect283k1 */ + 73, /* sect283r1 */ + 105, /* sect409k1 */ + 105, /* sect409r1 */ + 145, /* sect571k1 */ + 145, /* sect571r1 */ + 41, /* secp160k1 */ + 41, /* secp160r1 */ + 41, /* secp160r2 */ + 49, /* secp192k1 */ + 49, /* secp192r1 */ + 57, /* secp224k1 */ + 57, /* secp224r1 */ + 65, /* secp256k1 */ + 65, /* secp256r1 */ + 97, /* secp384r1 */ + 133, /* secp521r1 */ + 65, /* brainpoolP256r1 */ + 97, /* brainpoolP384r1 */ + 129, /* brainpoolP512r1 */ + 32, /* curve25519 */ + 56, /* curve448 */ +}; + +/* see bearssl_ec.h */ +size_t +br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk, + void *kbuf, const br_ec_private_key *sk) +{ + int curve; + size_t len; + + curve = sk->curve; + if (curve < 0 || curve >= 32 || curve >= (int)(sizeof POINT_LEN) + || ((impl->supported_curves >> curve) & 1) == 0) + { + return 0; + } + if (kbuf == NULL) { + return POINT_LEN[curve]; + } + len = impl->mulgen(kbuf, sk->x, sk->xlen, curve); + if (pk != NULL) { + pk->curve = curve; + pk->q = kbuf; + pk->qlen = len; + } + return len; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ec_secp256r1.c b/BearSSL-OG/libbearssl/src/ec/ec_secp256r1.c new file mode 100644 index 0000000..a9d6c45 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_secp256r1.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 const unsigned char P256_N[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 +}; + +static const unsigned char P256_G[] = { + 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, + 0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, + 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, + 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, + 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, + 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, + 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, + 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, + 0xF5 +}; + +/* see inner.h */ +const br_ec_curve_def br_secp256r1 = { + BR_EC_secp256r1, + P256_N, sizeof P256_N, + P256_G, sizeof P256_G +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_secp384r1.c b/BearSSL-OG/libbearssl/src/ec/ec_secp384r1.c new file mode 100644 index 0000000..693d93e --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_secp384r1.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 const unsigned char P384_N[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, + 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, + 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 +}; + +static const unsigned char P384_G[] = { + 0x04, 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, + 0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, + 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, + 0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, + 0x38, 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, + 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, + 0xB7, 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, + 0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, + 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, + 0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, + 0xC0, 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, + 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, + 0x5F +}; + +/* see inner.h */ +const br_ec_curve_def br_secp384r1 = { + BR_EC_secp384r1, + P384_N, sizeof P384_N, + P384_G, sizeof P384_G +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ec_secp521r1.c b/BearSSL-OG/libbearssl/src/ec/ec_secp521r1.c new file mode 100644 index 0000000..161acd0 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ec_secp521r1.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 const unsigned char P521_N[] = { + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, + 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, + 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, + 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, + 0x64, 0x09 +}; + +static const unsigned char P521_G[] = { + 0x04, 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, + 0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23, + 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, + 0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, + 0x4D, 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF, + 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, + 0xFF, 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, + 0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2, + 0xE5, 0xBD, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6A, + 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F, + 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, + 0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD, + 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE, 0x72, + 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, + 0x01, 0x3F, 0xAD, 0x07, 0x61, 0x35, 0x3C, 0x70, + 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94, + 0x76, 0x9F, 0xD1, 0x66, 0x50 +}; + +/* see inner.h */ +const br_ec_curve_def br_secp521r1 = { + BR_EC_secp521r1, + P521_N, sizeof P521_N, + P521_G, sizeof P521_G +}; diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_atr.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_atr.c new file mode 100644 index 0000000..3a11226 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_atr.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ec.h */ +size_t +br_ecdsa_asn1_to_raw(void *sig, size_t sig_len) +{ + /* + * Note: this code is a bit lenient in that it accepts a few + * deviations to DER with regards to minimality of encoding of + * lengths and integer values. These deviations are still + * unambiguous. + * + * Signature format is a SEQUENCE of two INTEGER values. We + * support only integers of less than 127 bytes each (signed + * encoding) so the resulting raw signature will have length + * at most 254 bytes. + */ + + unsigned char *buf, *r, *s; + size_t zlen, rlen, slen, off; + unsigned char tmp[254]; + + buf = sig; + if (sig_len < 8) { + return 0; + } + + /* + * First byte is SEQUENCE tag. + */ + if (buf[0] != 0x30) { + return 0; + } + + /* + * The SEQUENCE length will be encoded over one or two bytes. We + * limit the total SEQUENCE contents to 255 bytes, because it + * makes things simpler; this is enough for subgroup orders up + * to 999 bits. + */ + zlen = buf[1]; + if (zlen > 0x80) { + if (zlen != 0x81) { + return 0; + } + zlen = buf[2]; + if (zlen != sig_len - 3) { + return 0; + } + off = 3; + } else { + if (zlen != sig_len - 2) { + return 0; + } + off = 2; + } + + /* + * First INTEGER (r). + */ + if (buf[off ++] != 0x02) { + return 0; + } + rlen = buf[off ++]; + if (rlen >= 0x80) { + return 0; + } + r = buf + off; + off += rlen; + + /* + * Second INTEGER (s). + */ + if (off + 2 > sig_len) { + return 0; + } + if (buf[off ++] != 0x02) { + return 0; + } + slen = buf[off ++]; + if (slen >= 0x80 || slen != sig_len - off) { + return 0; + } + s = buf + off; + + /* + * Removing leading zeros from r and s. + */ + while (rlen > 0 && *r == 0) { + rlen --; + r ++; + } + while (slen > 0 && *s == 0) { + slen --; + s ++; + } + + /* + * Compute common length for the two integers, then copy integers + * into the temporary buffer, and finally copy it back over the + * signature buffer. + */ + zlen = rlen > slen ? rlen : slen; + sig_len = zlen << 1; + memset(tmp, 0, sig_len); + memcpy(tmp + zlen - rlen, r, rlen); + memcpy(tmp + sig_len - slen, s, slen); + memcpy(sig, tmp, sig_len); + return sig_len; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_default_sign_asn1.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_default_sign_asn1.c new file mode 100644 index 0000000..afbf8ac --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_default_sign_asn1.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ec.h */ +br_ecdsa_sign +br_ecdsa_sign_asn1_get_default(void) +{ +#if BR_LOMUL + return &br_ecdsa_i15_sign_asn1; +#else + return &br_ecdsa_i31_sign_asn1; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_default_sign_raw.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_default_sign_raw.c new file mode 100644 index 0000000..287c970 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_default_sign_raw.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ec.h */ +br_ecdsa_sign +br_ecdsa_sign_raw_get_default(void) +{ +#if BR_LOMUL + return &br_ecdsa_i15_sign_raw; +#else + return &br_ecdsa_i31_sign_raw; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_default_vrfy_asn1.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_default_vrfy_asn1.c new file mode 100644 index 0000000..fe0996e --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_default_vrfy_asn1.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ec.h */ +br_ecdsa_vrfy +br_ecdsa_vrfy_asn1_get_default(void) +{ +#if BR_LOMUL + return &br_ecdsa_i15_vrfy_asn1; +#else + return &br_ecdsa_i31_vrfy_asn1; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_default_vrfy_raw.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_default_vrfy_raw.c new file mode 100644 index 0000000..e564a10 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_default_vrfy_raw.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ec.h */ +br_ecdsa_vrfy +br_ecdsa_vrfy_raw_get_default(void) +{ +#if BR_LOMUL + return &br_ecdsa_i15_vrfy_raw; +#else + return &br_ecdsa_i31_vrfy_raw; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_bits.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_bits.c new file mode 100644 index 0000000..402d14a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_bits.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_ecdsa_i15_bits2int(uint16_t *x, + const void *src, size_t len, uint32_t ebitlen) +{ + uint32_t bitlen, hbitlen; + int sc; + + bitlen = ebitlen - (ebitlen >> 4); + hbitlen = (uint32_t)len << 3; + if (hbitlen > bitlen) { + len = (bitlen + 7) >> 3; + sc = (int)((hbitlen - bitlen) & 7); + } else { + sc = 0; + } + br_i15_zero(x, ebitlen); + br_i15_decode(x, src, len); + br_i15_rshift(x, sc); + x[0] = ebitlen; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_sign_asn1.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_sign_asn1.c new file mode 100644 index 0000000..ab4a283 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_sign_asn1.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) + +/* see bearssl_ec.h */ +size_t +br_ecdsa_i15_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig) +{ + unsigned char rsig[(ORDER_LEN << 1) + 12]; + size_t sig_len; + + sig_len = br_ecdsa_i15_sign_raw(impl, hf, hash_value, sk, rsig); + if (sig_len == 0) { + return 0; + } + sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len); + memcpy(sig, rsig, sig_len); + return sig_len; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_sign_raw.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_sign_raw.c new file mode 100644 index 0000000..39b2e1d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_sign_raw.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15) +#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1)) +#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) + +/* see bearssl_ec.h */ +size_t +br_ecdsa_i15_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig) +{ + /* + * IMPORTANT: this code is fit only for curves with a prime + * order. This is needed so that modular reduction of the X + * coordinate of a point can be done with a simple subtraction. + * We also rely on the last byte of the curve order to be distinct + * from 0 and 1. + */ + const br_ec_curve_def *cd; + uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], x[I15_LEN]; + uint16_t m[I15_LEN], k[I15_LEN], t1[I15_LEN], t2[I15_LEN]; + unsigned char tt[ORDER_LEN << 1]; + unsigned char eU[POINT_LEN]; + size_t hash_len, nlen, ulen; + uint16_t n0i; + uint32_t ctl; + br_hmac_drbg_context drbg; + + /* + * If the curve is not supported, then exit with an error. + */ + if (((impl->supported_curves >> sk->curve) & 1) == 0) { + return 0; + } + + /* + * Get the curve parameters (generator and order). + */ + switch (sk->curve) { + case BR_EC_secp256r1: + cd = &br_secp256r1; + break; + case BR_EC_secp384r1: + cd = &br_secp384r1; + break; + case BR_EC_secp521r1: + cd = &br_secp521r1; + break; + default: + return 0; + } + + /* + * Get modulus. + */ + nlen = cd->order_len; + br_i15_decode(n, cd->order, nlen); + n0i = br_i15_ninv15(n[1]); + + /* + * Get private key as an i15 integer. This also checks that the + * private key is well-defined (not zero, and less than the + * curve order). + */ + if (!br_i15_decode_mod(x, sk->x, sk->xlen, n)) { + return 0; + } + if (br_i15_iszero(x)) { + return 0; + } + + /* + * Get hash length. + */ + hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; + + /* + * Truncate and reduce the hash value modulo the curve order. + */ + br_ecdsa_i15_bits2int(m, hash_value, hash_len, n[0]); + br_i15_sub(m, n, br_i15_sub(m, n, 0) ^ 1); + + /* + * RFC 6979 generation of the "k" value. + * + * The process uses HMAC_DRBG (with the hash function used to + * process the message that is to be signed). The seed is the + * concatenation of the encodings of the private key and + * the hash value (after truncation and modular reduction). + */ + br_i15_encode(tt, nlen, x); + br_i15_encode(tt + nlen, nlen, m); + br_hmac_drbg_init(&drbg, hf, tt, nlen << 1); + for (;;) { + br_hmac_drbg_generate(&drbg, tt, nlen); + br_ecdsa_i15_bits2int(k, tt, nlen, n[0]); + if (br_i15_iszero(k)) { + continue; + } + if (br_i15_sub(k, n, 0)) { + break; + } + } + + /* + * Compute k*G and extract the X coordinate, then reduce it + * modulo the curve order. Since we support only curves with + * prime order, that reduction is only a matter of computing + * a subtraction. + */ + br_i15_encode(tt, nlen, k); + ulen = impl->mulgen(eU, tt, nlen, sk->curve); + br_i15_zero(r, n[0]); + br_i15_decode(r, &eU[1], ulen >> 1); + r[0] = n[0]; + br_i15_sub(r, n, br_i15_sub(r, n, 0) ^ 1); + + /* + * Compute 1/k in double-Montgomery representation. We do so by + * first converting _from_ Montgomery representation (twice), + * then using a modular exponentiation. + */ + br_i15_from_monty(k, n, n0i); + br_i15_from_monty(k, n, n0i); + memcpy(tt, cd->order, nlen); + tt[nlen - 1] -= 2; + br_i15_modpow(k, tt, nlen, n, n0i, t1, t2); + + /* + * Compute s = (m+xr)/k (mod n). + * The k[] array contains R^2/k (double-Montgomery representation); + * we thus can use direct Montgomery multiplications and conversions + * from Montgomery, avoiding any call to br_i15_to_monty() (which + * is slower). + */ + br_i15_from_monty(m, n, n0i); + br_i15_montymul(t1, x, r, n, n0i); + ctl = br_i15_add(t1, m, 1); + ctl |= br_i15_sub(t1, n, 0) ^ 1; + br_i15_sub(t1, n, ctl); + br_i15_montymul(s, t1, k, n, n0i); + + /* + * Encode r and s in the signature. + */ + br_i15_encode(sig, nlen, r); + br_i15_encode((unsigned char *)sig + nlen, nlen, s); + return nlen << 1; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_vrfy_asn1.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_vrfy_asn1.c new file mode 100644 index 0000000..f4bef99 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_vrfy_asn1.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3) + +/* see bearssl_ec.h */ +uint32_t +br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, + const void *sig, size_t sig_len) +{ + /* + * We use a double-sized buffer because a malformed ASN.1 signature + * may trigger a size expansion when converting to "raw" format. + */ + unsigned char rsig[(FIELD_LEN << 2) + 24]; + + if (sig_len > ((sizeof rsig) >> 1)) { + return 0; + } + memcpy(rsig, sig, sig_len); + sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len); + return br_ecdsa_i15_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len); +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_vrfy_raw.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_vrfy_raw.c new file mode 100644 index 0000000..14dd5e4 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i15_vrfy_raw.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15) +#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1)) + +/* see bearssl_ec.h */ +uint32_t +br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, + const void *sig, size_t sig_len) +{ + /* + * IMPORTANT: this code is fit only for curves with a prime + * order. This is needed so that modular reduction of the X + * coordinate of a point can be done with a simple subtraction. + */ + const br_ec_curve_def *cd; + uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], t1[I15_LEN], t2[I15_LEN]; + unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3]; + unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3]; + unsigned char eU[POINT_LEN]; + size_t nlen, rlen, ulen; + uint16_t n0i; + uint32_t res; + + /* + * If the curve is not supported, then report an error. + */ + if (((impl->supported_curves >> pk->curve) & 1) == 0) { + return 0; + } + + /* + * Get the curve parameters (generator and order). + */ + switch (pk->curve) { + case BR_EC_secp256r1: + cd = &br_secp256r1; + break; + case BR_EC_secp384r1: + cd = &br_secp384r1; + break; + case BR_EC_secp521r1: + cd = &br_secp521r1; + break; + default: + return 0; + } + + /* + * Signature length must be even. + */ + if (sig_len & 1) { + return 0; + } + rlen = sig_len >> 1; + + /* + * Public key point must have the proper size for this curve. + */ + if (pk->qlen != cd->generator_len) { + return 0; + } + + /* + * Get modulus; then decode the r and s values. They must be + * lower than the modulus, and s must not be null. + */ + nlen = cd->order_len; + br_i15_decode(n, cd->order, nlen); + n0i = br_i15_ninv15(n[1]); + if (!br_i15_decode_mod(r, sig, rlen, n)) { + return 0; + } + if (!br_i15_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) { + return 0; + } + if (br_i15_iszero(s)) { + return 0; + } + + /* + * Invert s. We do that with a modular exponentiation; we use + * the fact that for all the curves we support, the least + * significant byte is not 0 or 1, so we can subtract 2 without + * any carry to process. + * We also want 1/s in Montgomery representation, which can be + * done by converting _from_ Montgomery representation before + * the inversion (because (1/s)*R = 1/(s/R)). + */ + br_i15_from_monty(s, n, n0i); + memcpy(tx, cd->order, nlen); + tx[nlen - 1] -= 2; + br_i15_modpow(s, tx, nlen, n, n0i, t1, t2); + + /* + * Truncate the hash to the modulus length (in bits) and reduce + * it modulo the curve order. The modular reduction can be done + * with a subtraction since the truncation already reduced the + * value to the modulus bit length. + */ + br_ecdsa_i15_bits2int(t1, hash, hash_len, n[0]); + br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1); + + /* + * Multiply the (truncated, reduced) hash value with 1/s, result in + * t2, encoded in ty. + */ + br_i15_montymul(t2, t1, s, n, n0i); + br_i15_encode(ty, nlen, t2); + + /* + * Multiply r with 1/s, result in t1, encoded in tx. + */ + br_i15_montymul(t1, r, s, n, n0i); + br_i15_encode(tx, nlen, t1); + + /* + * Compute the point x*Q + y*G. + */ + ulen = cd->generator_len; + memcpy(eU, pk->q, ulen); + res = impl->muladd(eU, NULL, ulen, + tx, nlen, ty, nlen, cd->curve); + + /* + * Get the X coordinate, reduce modulo the curve order, and + * compare with the 'r' value. + * + * The modular reduction can be done with subtractions because + * we work with curves of prime order, so the curve order is + * close to the field order (Hasse's theorem). + */ + br_i15_zero(t1, n[0]); + br_i15_decode(t1, &eU[1], ulen >> 1); + t1[0] = n[0]; + br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1); + res &= ~br_i15_sub(t1, r, 1); + res &= br_i15_iszero(t1); + return res; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_bits.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_bits.c new file mode 100644 index 0000000..9a8d673 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_bits.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_ecdsa_i31_bits2int(uint32_t *x, + const void *src, size_t len, uint32_t ebitlen) +{ + uint32_t bitlen, hbitlen; + int sc; + + bitlen = ebitlen - (ebitlen >> 5); + hbitlen = (uint32_t)len << 3; + if (hbitlen > bitlen) { + len = (bitlen + 7) >> 3; + sc = (int)((hbitlen - bitlen) & 7); + } else { + sc = 0; + } + br_i31_zero(x, ebitlen); + br_i31_decode(x, src, len); + br_i31_rshift(x, sc); + x[0] = ebitlen; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_sign_asn1.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_sign_asn1.c new file mode 100644 index 0000000..cf0d351 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_sign_asn1.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) + +/* see bearssl_ec.h */ +size_t +br_ecdsa_i31_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig) +{ + unsigned char rsig[(ORDER_LEN << 1) + 12]; + size_t sig_len; + + sig_len = br_ecdsa_i31_sign_raw(impl, hf, hash_value, sk, rsig); + if (sig_len == 0) { + return 0; + } + sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len); + memcpy(sig, rsig, sig_len); + return sig_len; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_sign_raw.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_sign_raw.c new file mode 100644 index 0000000..1df98fe --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_sign_raw.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31) +#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1)) +#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) + +/* see bearssl_ec.h */ +size_t +br_ecdsa_i31_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig) +{ + /* + * IMPORTANT: this code is fit only for curves with a prime + * order. This is needed so that modular reduction of the X + * coordinate of a point can be done with a simple subtraction. + * We also rely on the last byte of the curve order to be distinct + * from 0 and 1. + */ + const br_ec_curve_def *cd; + uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], x[I31_LEN]; + uint32_t m[I31_LEN], k[I31_LEN], t1[I31_LEN], t2[I31_LEN]; + unsigned char tt[ORDER_LEN << 1]; + unsigned char eU[POINT_LEN]; + size_t hash_len, nlen, ulen; + uint32_t n0i, ctl; + br_hmac_drbg_context drbg; + + /* + * If the curve is not supported, then exit with an error. + */ + if (((impl->supported_curves >> sk->curve) & 1) == 0) { + return 0; + } + + /* + * Get the curve parameters (generator and order). + */ + switch (sk->curve) { + case BR_EC_secp256r1: + cd = &br_secp256r1; + break; + case BR_EC_secp384r1: + cd = &br_secp384r1; + break; + case BR_EC_secp521r1: + cd = &br_secp521r1; + break; + default: + return 0; + } + + /* + * Get modulus. + */ + nlen = cd->order_len; + br_i31_decode(n, cd->order, nlen); + n0i = br_i31_ninv31(n[1]); + + /* + * Get private key as an i31 integer. This also checks that the + * private key is well-defined (not zero, and less than the + * curve order). + */ + if (!br_i31_decode_mod(x, sk->x, sk->xlen, n)) { + return 0; + } + if (br_i31_iszero(x)) { + return 0; + } + + /* + * Get hash length. + */ + hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; + + /* + * Truncate and reduce the hash value modulo the curve order. + */ + br_ecdsa_i31_bits2int(m, hash_value, hash_len, n[0]); + br_i31_sub(m, n, br_i31_sub(m, n, 0) ^ 1); + + /* + * RFC 6979 generation of the "k" value. + * + * The process uses HMAC_DRBG (with the hash function used to + * process the message that is to be signed). The seed is the + * concatenation of the encodings of the private key and + * the hash value (after truncation and modular reduction). + */ + br_i31_encode(tt, nlen, x); + br_i31_encode(tt + nlen, nlen, m); + br_hmac_drbg_init(&drbg, hf, tt, nlen << 1); + for (;;) { + br_hmac_drbg_generate(&drbg, tt, nlen); + br_ecdsa_i31_bits2int(k, tt, nlen, n[0]); + if (br_i31_iszero(k)) { + continue; + } + if (br_i31_sub(k, n, 0)) { + break; + } + } + + /* + * Compute k*G and extract the X coordinate, then reduce it + * modulo the curve order. Since we support only curves with + * prime order, that reduction is only a matter of computing + * a subtraction. + */ + br_i31_encode(tt, nlen, k); + ulen = impl->mulgen(eU, tt, nlen, sk->curve); + br_i31_zero(r, n[0]); + br_i31_decode(r, &eU[1], ulen >> 1); + r[0] = n[0]; + br_i31_sub(r, n, br_i31_sub(r, n, 0) ^ 1); + + /* + * Compute 1/k in double-Montgomery representation. We do so by + * first converting _from_ Montgomery representation (twice), + * then using a modular exponentiation. + */ + br_i31_from_monty(k, n, n0i); + br_i31_from_monty(k, n, n0i); + memcpy(tt, cd->order, nlen); + tt[nlen - 1] -= 2; + br_i31_modpow(k, tt, nlen, n, n0i, t1, t2); + + /* + * Compute s = (m+xr)/k (mod n). + * The k[] array contains R^2/k (double-Montgomery representation); + * we thus can use direct Montgomery multiplications and conversions + * from Montgomery, avoiding any call to br_i31_to_monty() (which + * is slower). + */ + br_i31_from_monty(m, n, n0i); + br_i31_montymul(t1, x, r, n, n0i); + ctl = br_i31_add(t1, m, 1); + ctl |= br_i31_sub(t1, n, 0) ^ 1; + br_i31_sub(t1, n, ctl); + br_i31_montymul(s, t1, k, n, n0i); + + /* + * Encode r and s in the signature. + */ + br_i31_encode(sig, nlen, r); + br_i31_encode((unsigned char *)sig + nlen, nlen, s); + return nlen << 1; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_vrfy_asn1.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_vrfy_asn1.c new file mode 100644 index 0000000..4161aaa --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_vrfy_asn1.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3) + +/* see bearssl_ec.h */ +uint32_t +br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, + const void *sig, size_t sig_len) +{ + /* + * We use a double-sized buffer because a malformed ASN.1 signature + * may trigger a size expansion when converting to "raw" format. + */ + unsigned char rsig[(FIELD_LEN << 2) + 24]; + + if (sig_len > ((sizeof rsig) >> 1)) { + return 0; + } + memcpy(rsig, sig, sig_len); + sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len); + return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len); +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_vrfy_raw.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_vrfy_raw.c new file mode 100644 index 0000000..259477f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_i31_vrfy_raw.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31) +#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1)) + +/* see bearssl_ec.h */ +uint32_t +br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, + const void *sig, size_t sig_len) +{ + /* + * IMPORTANT: this code is fit only for curves with a prime + * order. This is needed so that modular reduction of the X + * coordinate of a point can be done with a simple subtraction. + */ + const br_ec_curve_def *cd; + uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], t1[I31_LEN], t2[I31_LEN]; + unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3]; + unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3]; + unsigned char eU[POINT_LEN]; + size_t nlen, rlen, ulen; + uint32_t n0i, res; + + /* + * If the curve is not supported, then report an error. + */ + if (((impl->supported_curves >> pk->curve) & 1) == 0) { + return 0; + } + + /* + * Get the curve parameters (generator and order). + */ + switch (pk->curve) { + case BR_EC_secp256r1: + cd = &br_secp256r1; + break; + case BR_EC_secp384r1: + cd = &br_secp384r1; + break; + case BR_EC_secp521r1: + cd = &br_secp521r1; + break; + default: + return 0; + } + + /* + * Signature length must be even. + */ + if (sig_len & 1) { + return 0; + } + rlen = sig_len >> 1; + + /* + * Public key point must have the proper size for this curve. + */ + if (pk->qlen != cd->generator_len) { + return 0; + } + + /* + * Get modulus; then decode the r and s values. They must be + * lower than the modulus, and s must not be null. + */ + nlen = cd->order_len; + br_i31_decode(n, cd->order, nlen); + n0i = br_i31_ninv31(n[1]); + if (!br_i31_decode_mod(r, sig, rlen, n)) { + return 0; + } + if (!br_i31_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) { + return 0; + } + if (br_i31_iszero(s)) { + return 0; + } + + /* + * Invert s. We do that with a modular exponentiation; we use + * the fact that for all the curves we support, the least + * significant byte is not 0 or 1, so we can subtract 2 without + * any carry to process. + * We also want 1/s in Montgomery representation, which can be + * done by converting _from_ Montgomery representation before + * the inversion (because (1/s)*R = 1/(s/R)). + */ + br_i31_from_monty(s, n, n0i); + memcpy(tx, cd->order, nlen); + tx[nlen - 1] -= 2; + br_i31_modpow(s, tx, nlen, n, n0i, t1, t2); + + /* + * Truncate the hash to the modulus length (in bits) and reduce + * it modulo the curve order. The modular reduction can be done + * with a subtraction since the truncation already reduced the + * value to the modulus bit length. + */ + br_ecdsa_i31_bits2int(t1, hash, hash_len, n[0]); + br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1); + + /* + * Multiply the (truncated, reduced) hash value with 1/s, result in + * t2, encoded in ty. + */ + br_i31_montymul(t2, t1, s, n, n0i); + br_i31_encode(ty, nlen, t2); + + /* + * Multiply r with 1/s, result in t1, encoded in tx. + */ + br_i31_montymul(t1, r, s, n, n0i); + br_i31_encode(tx, nlen, t1); + + /* + * Compute the point x*Q + y*G. + */ + ulen = cd->generator_len; + memcpy(eU, pk->q, ulen); + res = impl->muladd(eU, NULL, ulen, + tx, nlen, ty, nlen, cd->curve); + + /* + * Get the X coordinate, reduce modulo the curve order, and + * compare with the 'r' value. + * + * The modular reduction can be done with subtractions because + * we work with curves of prime order, so the curve order is + * close to the field order (Hasse's theorem). + */ + br_i31_zero(t1, n[0]); + br_i31_decode(t1, &eU[1], ulen >> 1); + t1[0] = n[0]; + br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1); + res &= ~br_i31_sub(t1, r, 1); + res &= br_i31_iszero(t1); + return res; +} diff --git a/BearSSL-OG/libbearssl/src/ec/ecdsa_rta.c b/BearSSL-OG/libbearssl/src/ec/ecdsa_rta.c new file mode 100644 index 0000000..005c62c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ec/ecdsa_rta.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * Compute ASN.1 encoded length for the provided integer. The ASN.1 + * encoding is signed, so its leading bit must have value 0; it must + * also be of minimal length (so leading bytes of value 0 must be + * removed, except if that would contradict the rule about the sign + * bit). + */ +static size_t +asn1_int_length(const unsigned char *x, size_t xlen) +{ + while (xlen > 0 && *x == 0) { + x ++; + xlen --; + } + if (xlen == 0 || *x >= 0x80) { + xlen ++; + } + return xlen; +} + +/* see bearssl_ec.h */ +size_t +br_ecdsa_raw_to_asn1(void *sig, size_t sig_len) +{ + /* + * Internal buffer is large enough to accommodate a signature + * such that r and s fit on 125 bytes each (signed encoding), + * meaning a curve order of up to 999 bits. This is the limit + * that ensures "simple" length encodings. + */ + unsigned char *buf; + size_t hlen, rlen, slen, zlen, off; + unsigned char tmp[257]; + + buf = sig; + if ((sig_len & 1) != 0) { + return 0; + } + + /* + * Compute lengths for the two integers. + */ + hlen = sig_len >> 1; + rlen = asn1_int_length(buf, hlen); + slen = asn1_int_length(buf + hlen, hlen); + if (rlen > 125 || slen > 125) { + return 0; + } + + /* + * SEQUENCE header. + */ + tmp[0] = 0x30; + zlen = rlen + slen + 4; + if (zlen >= 0x80) { + tmp[1] = 0x81; + tmp[2] = zlen; + off = 3; + } else { + tmp[1] = zlen; + off = 2; + } + + /* + * First INTEGER (r). + */ + tmp[off ++] = 0x02; + tmp[off ++] = rlen; + if (rlen > hlen) { + tmp[off] = 0x00; + memcpy(tmp + off + 1, buf, hlen); + } else { + memcpy(tmp + off, buf + hlen - rlen, rlen); + } + off += rlen; + + /* + * Second INTEGER (s). + */ + tmp[off ++] = 0x02; + tmp[off ++] = slen; + if (slen > hlen) { + tmp[off] = 0x00; + memcpy(tmp + off + 1, buf + hlen, hlen); + } else { + memcpy(tmp + off, buf + sig_len - slen, slen); + } + off += slen; + + /* + * Return ASN.1 signature. + */ + memcpy(sig, tmp, off); + return off; +} diff --git a/BearSSL-OG/libbearssl/src/hash/dig_oid.c b/BearSSL-OG/libbearssl/src/hash/dig_oid.c new file mode 100644 index 0000000..cd9692c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/dig_oid.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * This file contains the encoded OID for the standard hash functions. + * Such OID appear in, for instance, the PKCS#1 v1.5 padding for RSA + * signatures. + */ + +static const unsigned char md5_OID[] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05 +}; + +static const unsigned char sha1_OID[] = { + 0x2B, 0x0E, 0x03, 0x02, 0x1A +}; + +static const unsigned char sha224_OID[] = { + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04 +}; + +static const unsigned char sha256_OID[] = { + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 +}; + +static const unsigned char sha384_OID[] = { + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 +}; + +static const unsigned char sha512_OID[] = { + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 +}; + +/* see inner.h */ +const unsigned char * +br_digest_OID(int digest_id, size_t *len) +{ + switch (digest_id) { + case br_md5_ID: + *len = sizeof md5_OID; + return md5_OID; + case br_sha1_ID: + *len = sizeof sha1_OID; + return sha1_OID; + case br_sha224_ID: + *len = sizeof sha224_OID; + return sha224_OID; + case br_sha256_ID: + *len = sizeof sha256_OID; + return sha256_OID; + case br_sha384_ID: + *len = sizeof sha384_OID; + return sha384_OID; + case br_sha512_ID: + *len = sizeof sha512_OID; + return sha512_OID; + default: + *len = 0; + return NULL; + } +} diff --git a/BearSSL-OG/libbearssl/src/hash/dig_size.c b/BearSSL-OG/libbearssl/src/hash/dig_size.c new file mode 100644 index 0000000..4625d2c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/dig_size.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +size_t +br_digest_size_by_ID(int digest_id) +{ + switch (digest_id) { + case br_md5sha1_ID: + return br_md5_SIZE + br_sha1_SIZE; + case br_md5_ID: + return br_md5_SIZE; + case br_sha1_ID: + return br_sha1_SIZE; + case br_sha224_ID: + return br_sha224_SIZE; + case br_sha256_ID: + return br_sha256_SIZE; + case br_sha384_ID: + return br_sha384_SIZE; + case br_sha512_ID: + return br_sha512_SIZE; + default: + /* abort(); */ + return 0; + } +} diff --git a/BearSSL-OG/libbearssl/src/hash/ghash_ctmul.c b/BearSSL-OG/libbearssl/src/hash/ghash_ctmul.c new file mode 100644 index 0000000..940a4e1 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/ghash_ctmul.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * We compute "carryless multiplications" through normal integer + * multiplications, masking out enough bits to create "holes" in which + * carries may expand without altering our bits; we really use 8 data + * bits per 32-bit word, spaced every fourth bit. Accumulated carries + * may not exceed 8 in total, which fits in 4 bits. + * + * It would be possible to use a 3-bit spacing, allowing two operands, + * one with 7 non-zero data bits, the other one with 10 or 11 non-zero + * data bits; this asymmetric splitting makes the overall code more + * complex with thresholds and exceptions, and does not appear to be + * worth the effort. + */ + +/* + * We cannot really autodetect whether multiplications are "slow" or + * not. A typical example is the ARM Cortex M0+, which exists in two + * versions: one with a 1-cycle multiplication opcode, the other with + * a 32-cycle multiplication opcode. They both use exactly the same + * architecture and ABI, and cannot be distinguished from each other + * at compile-time. + * + * Since most modern CPU (even embedded CPU) still have fast + * multiplications, we use the "fast mul" code by default. + */ + +#if BR_SLOW_MUL + +/* + * This implementation uses Karatsuba-like reduction to make fewer + * integer multiplications (9 instead of 16), at the expense of extra + * logical operations (XOR, shifts...). On modern x86 CPU that offer + * fast, pipelined multiplications, this code is about twice slower than + * the simpler code with 16 multiplications. This tendency may be + * reversed on low-end platforms with expensive multiplications. + */ + +#define MUL32(h, l, x, y) do { \ + uint64_t mul32tmp = MUL(x, y); \ + (h) = (uint32_t)(mul32tmp >> 32); \ + (l) = (uint32_t)mul32tmp; \ + } while (0) + +static inline void +bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint32_t a0, a1, a2, a3, a4, a5, a6, a7, a8; + uint32_t b0, b1, b2, b3, b4, b5, b6, b7, b8; + + x0 = x & (uint32_t)0x11111111; + x1 = x & (uint32_t)0x22222222; + x2 = x & (uint32_t)0x44444444; + x3 = x & (uint32_t)0x88888888; + y0 = y & (uint32_t)0x11111111; + y1 = y & (uint32_t)0x22222222; + y2 = y & (uint32_t)0x44444444; + y3 = y & (uint32_t)0x88888888; + + /* + * (x0+W*x1)*(y0+W*y1) -> a0:b0 + * (x2+W*x3)*(y2+W*y3) -> a3:b3 + * ((x0+x2)+W*(x1+x3))*((y0+y2)+W*(y1+y3)) -> a6:b6 + */ + a0 = x0; + b0 = y0; + a1 = x1 >> 1; + b1 = y1 >> 1; + a2 = a0 ^ a1; + b2 = b0 ^ b1; + a3 = x2 >> 2; + b3 = y2 >> 2; + a4 = x3 >> 3; + b4 = y3 >> 3; + a5 = a3 ^ a4; + b5 = b3 ^ b4; + a6 = a0 ^ a3; + b6 = b0 ^ b3; + a7 = a1 ^ a4; + b7 = b1 ^ b4; + a8 = a6 ^ a7; + b8 = b6 ^ b7; + + MUL32(b0, a0, b0, a0); + MUL32(b1, a1, b1, a1); + MUL32(b2, a2, b2, a2); + MUL32(b3, a3, b3, a3); + MUL32(b4, a4, b4, a4); + MUL32(b5, a5, b5, a5); + MUL32(b6, a6, b6, a6); + MUL32(b7, a7, b7, a7); + MUL32(b8, a8, b8, a8); + + a0 &= (uint32_t)0x11111111; + a1 &= (uint32_t)0x11111111; + a2 &= (uint32_t)0x11111111; + a3 &= (uint32_t)0x11111111; + a4 &= (uint32_t)0x11111111; + a5 &= (uint32_t)0x11111111; + a6 &= (uint32_t)0x11111111; + a7 &= (uint32_t)0x11111111; + a8 &= (uint32_t)0x11111111; + b0 &= (uint32_t)0x11111111; + b1 &= (uint32_t)0x11111111; + b2 &= (uint32_t)0x11111111; + b3 &= (uint32_t)0x11111111; + b4 &= (uint32_t)0x11111111; + b5 &= (uint32_t)0x11111111; + b6 &= (uint32_t)0x11111111; + b7 &= (uint32_t)0x11111111; + b8 &= (uint32_t)0x11111111; + + a2 ^= a0 ^ a1; + b2 ^= b0 ^ b1; + a0 ^= (a2 << 1) ^ (a1 << 2); + b0 ^= (b2 << 1) ^ (b1 << 2); + a5 ^= a3 ^ a4; + b5 ^= b3 ^ b4; + a3 ^= (a5 << 1) ^ (a4 << 2); + b3 ^= (b5 << 1) ^ (b4 << 2); + a8 ^= a6 ^ a7; + b8 ^= b6 ^ b7; + a6 ^= (a8 << 1) ^ (a7 << 2); + b6 ^= (b8 << 1) ^ (b7 << 2); + a6 ^= a0 ^ a3; + b6 ^= b0 ^ b3; + *lo = a0 ^ (a6 << 2) ^ (a3 << 4); + *hi = b0 ^ (b6 << 2) ^ (b3 << 4) ^ (a6 >> 30) ^ (a3 >> 28); +} + +#else + +/* + * Simple multiplication in GF(2)[X], using 16 integer multiplications. + */ + +static __inline void +bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint64_t z0, z1, z2, z3; + uint64_t z; + + x0 = x & (uint32_t)0x11111111; + x1 = x & (uint32_t)0x22222222; + x2 = x & (uint32_t)0x44444444; + x3 = x & (uint32_t)0x88888888; + y0 = y & (uint32_t)0x11111111; + y1 = y & (uint32_t)0x22222222; + y2 = y & (uint32_t)0x44444444; + y3 = y & (uint32_t)0x88888888; + z0 = MUL(x0, y0) ^ MUL(x1, y3) ^ MUL(x2, y2) ^ MUL(x3, y1); + z1 = MUL(x0, y1) ^ MUL(x1, y0) ^ MUL(x2, y3) ^ MUL(x3, y2); + z2 = MUL(x0, y2) ^ MUL(x1, y1) ^ MUL(x2, y0) ^ MUL(x3, y3); + z3 = MUL(x0, y3) ^ MUL(x1, y2) ^ MUL(x2, y1) ^ MUL(x3, y0); + z0 &= (uint64_t)0x1111111111111111; + z1 &= (uint64_t)0x2222222222222222; + z2 &= (uint64_t)0x4444444444444444; + z3 &= (uint64_t)0x8888888888888888; + z = z0 | z1 | z2 | z3; + *lo = (uint32_t)z; + *hi = (uint32_t)(z >> 32); +} + +#endif + +/* see bearssl_hash.h */ +void +br_ghash_ctmul(void *y, const void *h, const void *data, size_t len) +{ + const unsigned char *buf, *hb; + unsigned char *yb; + uint32_t yw[4]; + uint32_t hw[4]; + + /* + * Throughout the loop we handle the y and h values as arrays + * of 32-bit words. + */ + buf = data; + yb = y; + hb = h; + yw[3] = br_dec32be(yb); + yw[2] = br_dec32be(yb + 4); + yw[1] = br_dec32be(yb + 8); + yw[0] = br_dec32be(yb + 12); + hw[3] = br_dec32be(hb); + hw[2] = br_dec32be(hb + 4); + hw[1] = br_dec32be(hb + 8); + hw[0] = br_dec32be(hb + 12); + while (len > 0) { + const unsigned char *src; + unsigned char tmp[16]; + int i; + uint32_t a[9], b[9], zw[8]; + uint32_t c0, c1, c2, c3, d0, d1, d2, d3, e0, e1, e2, e3; + + /* + * Get the next 16-byte block (using zero-padding if + * necessary). + */ + if (len >= 16) { + src = buf; + buf += 16; + len -= 16; + } else { + memcpy(tmp, buf, len); + memset(tmp + len, 0, (sizeof tmp) - len); + src = tmp; + len = 0; + } + + /* + * Decode the block. The GHASH standard mandates + * big-endian encoding. + */ + yw[3] ^= br_dec32be(src); + yw[2] ^= br_dec32be(src + 4); + yw[1] ^= br_dec32be(src + 8); + yw[0] ^= br_dec32be(src + 12); + + /* + * We multiply two 128-bit field elements. We use + * Karatsuba to turn that into three 64-bit + * multiplications, which are themselves done with a + * total of nine 32-bit multiplications. + */ + + /* + * y[0,1]*h[0,1] -> 0..2 + * y[2,3]*h[2,3] -> 3..5 + * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6..8 + */ + a[0] = yw[0]; + b[0] = hw[0]; + a[1] = yw[1]; + b[1] = hw[1]; + a[2] = a[0] ^ a[1]; + b[2] = b[0] ^ b[1]; + + a[3] = yw[2]; + b[3] = hw[2]; + a[4] = yw[3]; + b[4] = hw[3]; + a[5] = a[3] ^ a[4]; + b[5] = b[3] ^ b[4]; + + a[6] = a[0] ^ a[3]; + b[6] = b[0] ^ b[3]; + a[7] = a[1] ^ a[4]; + b[7] = b[1] ^ b[4]; + a[8] = a[6] ^ a[7]; + b[8] = b[6] ^ b[7]; + + for (i = 0; i < 9; i ++) { + bmul(&b[i], &a[i], b[i], a[i]); + } + + c0 = a[0]; + c1 = b[0] ^ a[2] ^ a[0] ^ a[1]; + c2 = a[1] ^ b[2] ^ b[0] ^ b[1]; + c3 = b[1]; + d0 = a[3]; + d1 = b[3] ^ a[5] ^ a[3] ^ a[4]; + d2 = a[4] ^ b[5] ^ b[3] ^ b[4]; + d3 = b[4]; + e0 = a[6]; + e1 = b[6] ^ a[8] ^ a[6] ^ a[7]; + e2 = a[7] ^ b[8] ^ b[6] ^ b[7]; + e3 = b[7]; + + e0 ^= c0 ^ d0; + e1 ^= c1 ^ d1; + e2 ^= c2 ^ d2; + e3 ^= c3 ^ d3; + c2 ^= e0; + c3 ^= e1; + d0 ^= e2; + d1 ^= e3; + + /* + * GHASH specification has the bits "reversed" (most + * significant is in fact least significant), which does + * not matter for a carryless multiplication, except that + * the 255-bit result must be shifted by 1 bit. + */ + zw[0] = c0 << 1; + zw[1] = (c1 << 1) | (c0 >> 31); + zw[2] = (c2 << 1) | (c1 >> 31); + zw[3] = (c3 << 1) | (c2 >> 31); + zw[4] = (d0 << 1) | (c3 >> 31); + zw[5] = (d1 << 1) | (d0 >> 31); + zw[6] = (d2 << 1) | (d1 >> 31); + zw[7] = (d3 << 1) | (d2 >> 31); + + /* + * We now do the reduction modulo the field polynomial + * to get back to 128 bits. + */ + for (i = 0; i < 4; i ++) { + uint32_t lw; + + lw = zw[i]; + zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7); + zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25); + } + memcpy(yw, zw + 4, sizeof yw); + } + + /* + * Encode back the result. + */ + br_enc32be(yb, yw[3]); + br_enc32be(yb + 4, yw[2]); + br_enc32be(yb + 8, yw[1]); + br_enc32be(yb + 12, yw[0]); +} diff --git a/BearSSL-OG/libbearssl/src/hash/ghash_ctmul32.c b/BearSSL-OG/libbearssl/src/hash/ghash_ctmul32.c new file mode 100644 index 0000000..de02344 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/ghash_ctmul32.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * This implementation uses 32-bit multiplications, and only the low + * 32 bits for each multiplication result. This is meant primarily for + * the ARM Cortex M0 and M0+, whose multiplication opcode does not yield + * the upper 32 bits; but it might also be useful on architectures where + * access to the upper 32 bits requires use of specific registers that + * create contention (e.g. on i386, "mul" necessarily outputs the result + * in edx:eax, while "imul" can use any registers but is limited to the + * low 32 bits). + * + * The implementation trick that is used here is bit-reversing (bit 0 + * is swapped with bit 31, bit 1 with bit 30, and so on). In GF(2)[X], + * for all values x and y, we have: + * rev32(x) * rev32(y) = rev64(x * y) + * In other words, if we bit-reverse (over 32 bits) the operands, then we + * bit-reverse (over 64 bits) the result. + */ + +/* + * Multiplication in GF(2)[X], truncated to its low 32 bits. + */ +static __inline uint32_t +bmul32(uint32_t x, uint32_t y) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint32_t z0, z1, z2, z3; + + x0 = x & (uint32_t)0x11111111; + x1 = x & (uint32_t)0x22222222; + x2 = x & (uint32_t)0x44444444; + x3 = x & (uint32_t)0x88888888; + y0 = y & (uint32_t)0x11111111; + y1 = y & (uint32_t)0x22222222; + y2 = y & (uint32_t)0x44444444; + y3 = y & (uint32_t)0x88888888; + z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1); + z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2); + z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3); + z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0); + z0 &= (uint32_t)0x11111111; + z1 &= (uint32_t)0x22222222; + z2 &= (uint32_t)0x44444444; + z3 &= (uint32_t)0x88888888; + return z0 | z1 | z2 | z3; +} + +/* + * Bit-reverse a 32-bit word. + */ +static uint32_t +rev32(uint32_t x) +{ +#define RMS(m, s) do { \ + x = ((x & (uint32_t)(m)) << (s)) \ + | ((x >> (s)) & (uint32_t)(m)); \ + } while (0) + + RMS(0x55555555, 1); + RMS(0x33333333, 2); + RMS(0x0F0F0F0F, 4); + RMS(0x00FF00FF, 8); + return (x << 16) | (x >> 16); + +#undef RMS +} + +/* see bearssl_hash.h */ +void +br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len) +{ + /* + * This implementation is similar to br_ghash_ctmul() except + * that we have to do the multiplication twice, with the + * "normal" and "bit reversed" operands. Hence we end up with + * eighteen 32-bit multiplications instead of nine. + */ + + const unsigned char *buf, *hb; + unsigned char *yb; + uint32_t yw[4]; + uint32_t hw[4], hwr[4]; + + buf = data; + yb = y; + hb = h; + yw[3] = br_dec32be(yb); + yw[2] = br_dec32be(yb + 4); + yw[1] = br_dec32be(yb + 8); + yw[0] = br_dec32be(yb + 12); + hw[3] = br_dec32be(hb); + hw[2] = br_dec32be(hb + 4); + hw[1] = br_dec32be(hb + 8); + hw[0] = br_dec32be(hb + 12); + hwr[3] = rev32(hw[3]); + hwr[2] = rev32(hw[2]); + hwr[1] = rev32(hw[1]); + hwr[0] = rev32(hw[0]); + while (len > 0) { + const unsigned char *src; + unsigned char tmp[16]; + int i; + uint32_t a[18], b[18], c[18]; + uint32_t d0, d1, d2, d3, d4, d5, d6, d7; + uint32_t zw[8]; + + if (len >= 16) { + src = buf; + buf += 16; + len -= 16; + } else { + memcpy(tmp, buf, len); + memset(tmp + len, 0, (sizeof tmp) - len); + src = tmp; + len = 0; + } + yw[3] ^= br_dec32be(src); + yw[2] ^= br_dec32be(src + 4); + yw[1] ^= br_dec32be(src + 8); + yw[0] ^= br_dec32be(src + 12); + + /* + * We are using Karatsuba: the 128x128 multiplication is + * reduced to three 64x64 multiplications, hence nine + * 32x32 multiplications. With the bit-reversal trick, + * we have to perform 18 32x32 multiplications. + */ + + /* + * y[0,1]*h[0,1] -> 0,1,4 + * y[2,3]*h[2,3] -> 2,3,5 + * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,7,8 + */ + + a[0] = yw[0]; + a[1] = yw[1]; + a[2] = yw[2]; + a[3] = yw[3]; + a[4] = a[0] ^ a[1]; + a[5] = a[2] ^ a[3]; + a[6] = a[0] ^ a[2]; + a[7] = a[1] ^ a[3]; + a[8] = a[6] ^ a[7]; + + a[ 9] = rev32(yw[0]); + a[10] = rev32(yw[1]); + a[11] = rev32(yw[2]); + a[12] = rev32(yw[3]); + a[13] = a[ 9] ^ a[10]; + a[14] = a[11] ^ a[12]; + a[15] = a[ 9] ^ a[11]; + a[16] = a[10] ^ a[12]; + a[17] = a[15] ^ a[16]; + + b[0] = hw[0]; + b[1] = hw[1]; + b[2] = hw[2]; + b[3] = hw[3]; + b[4] = b[0] ^ b[1]; + b[5] = b[2] ^ b[3]; + b[6] = b[0] ^ b[2]; + b[7] = b[1] ^ b[3]; + b[8] = b[6] ^ b[7]; + + b[ 9] = hwr[0]; + b[10] = hwr[1]; + b[11] = hwr[2]; + b[12] = hwr[3]; + b[13] = b[ 9] ^ b[10]; + b[14] = b[11] ^ b[12]; + b[15] = b[ 9] ^ b[11]; + b[16] = b[10] ^ b[12]; + b[17] = b[15] ^ b[16]; + + for (i = 0; i < 18; i ++) { + c[i] = bmul32(a[i], b[i]); + } + + c[4] ^= c[0] ^ c[1]; + c[5] ^= c[2] ^ c[3]; + c[8] ^= c[6] ^ c[7]; + + c[13] ^= c[ 9] ^ c[10]; + c[14] ^= c[11] ^ c[12]; + c[17] ^= c[15] ^ c[16]; + + /* + * y[0,1]*h[0,1] -> 0,9^4,1^13,10 + * y[2,3]*h[2,3] -> 2,11^5,3^14,12 + * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,15^8,7^17,16 + */ + d0 = c[0]; + d1 = c[4] ^ (rev32(c[9]) >> 1); + d2 = c[1] ^ c[0] ^ c[2] ^ c[6] ^ (rev32(c[13]) >> 1); + d3 = c[4] ^ c[5] ^ c[8] + ^ (rev32(c[10] ^ c[9] ^ c[11] ^ c[15]) >> 1); + d4 = c[2] ^ c[1] ^ c[3] ^ c[7] + ^ (rev32(c[13] ^ c[14] ^ c[17]) >> 1); + d5 = c[5] ^ (rev32(c[11] ^ c[10] ^ c[12] ^ c[16]) >> 1); + d6 = c[3] ^ (rev32(c[14]) >> 1); + d7 = rev32(c[12]) >> 1; + + zw[0] = d0 << 1; + zw[1] = (d1 << 1) | (d0 >> 31); + zw[2] = (d2 << 1) | (d1 >> 31); + zw[3] = (d3 << 1) | (d2 >> 31); + zw[4] = (d4 << 1) | (d3 >> 31); + zw[5] = (d5 << 1) | (d4 >> 31); + zw[6] = (d6 << 1) | (d5 >> 31); + zw[7] = (d7 << 1) | (d6 >> 31); + + for (i = 0; i < 4; i ++) { + uint32_t lw; + + lw = zw[i]; + zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7); + zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25); + } + memcpy(yw, zw + 4, sizeof yw); + } + br_enc32be(yb, yw[3]); + br_enc32be(yb + 4, yw[2]); + br_enc32be(yb + 8, yw[1]); + br_enc32be(yb + 12, yw[0]); +} diff --git a/BearSSL-OG/libbearssl/src/hash/ghash_ctmul64.c b/BearSSL-OG/libbearssl/src/hash/ghash_ctmul64.c new file mode 100644 index 0000000..a5a5e36 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/ghash_ctmul64.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * This is the 64-bit variant of br_ghash_ctmul32(), with 64-bit operands + * and bit reversal of 64-bit words. + */ + +static __inline uint64_t +bmul64(uint64_t x, uint64_t y) +{ + uint64_t x0, x1, x2, x3; + uint64_t y0, y1, y2, y3; + uint64_t z0, z1, z2, z3; + + x0 = x & (uint64_t)0x1111111111111111; + x1 = x & (uint64_t)0x2222222222222222; + x2 = x & (uint64_t)0x4444444444444444; + x3 = x & (uint64_t)0x8888888888888888; + y0 = y & (uint64_t)0x1111111111111111; + y1 = y & (uint64_t)0x2222222222222222; + y2 = y & (uint64_t)0x4444444444444444; + y3 = y & (uint64_t)0x8888888888888888; + z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1); + z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2); + z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3); + z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0); + z0 &= (uint64_t)0x1111111111111111; + z1 &= (uint64_t)0x2222222222222222; + z2 &= (uint64_t)0x4444444444444444; + z3 &= (uint64_t)0x8888888888888888; + return z0 | z1 | z2 | z3; +} + +static uint64_t +rev64(uint64_t x) +{ +#define RMS(m, s) do { \ + x = ((x & (uint64_t)(m)) << (s)) \ + | ((x >> (s)) & (uint64_t)(m)); \ + } while (0) + + RMS(0x5555555555555555, 1); + RMS(0x3333333333333333, 2); + RMS(0x0F0F0F0F0F0F0F0F, 4); + RMS(0x00FF00FF00FF00FF, 8); + RMS(0x0000FFFF0000FFFF, 16); + return (x << 32) | (x >> 32); + +#undef RMS +} + +/* see bearssl_ghash.h */ +void +br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len) +{ + const unsigned char *buf, *hb; + unsigned char *yb; + uint64_t y0, y1; + uint64_t h0, h1, h2, h0r, h1r, h2r; + + buf = data; + yb = y; + hb = h; + y1 = br_dec64be(yb); + y0 = br_dec64be(yb + 8); + h1 = br_dec64be(hb); + h0 = br_dec64be(hb + 8); + h0r = rev64(h0); + h1r = rev64(h1); + h2 = h0 ^ h1; + h2r = h0r ^ h1r; + while (len > 0) { + const unsigned char *src; + unsigned char tmp[16]; + uint64_t y0r, y1r, y2, y2r; + uint64_t z0, z1, z2, z0h, z1h, z2h; + uint64_t v0, v1, v2, v3; + + if (len >= 16) { + src = buf; + buf += 16; + len -= 16; + } else { + memcpy(tmp, buf, len); + memset(tmp + len, 0, (sizeof tmp) - len); + src = tmp; + len = 0; + } + y1 ^= br_dec64be(src); + y0 ^= br_dec64be(src + 8); + + y0r = rev64(y0); + y1r = rev64(y1); + y2 = y0 ^ y1; + y2r = y0r ^ y1r; + + z0 = bmul64(y0, h0); + z1 = bmul64(y1, h1); + z2 = bmul64(y2, h2); + z0h = bmul64(y0r, h0r); + z1h = bmul64(y1r, h1r); + z2h = bmul64(y2r, h2r); + z2 ^= z0 ^ z1; + z2h ^= z0h ^ z1h; + z0h = rev64(z0h) >> 1; + z1h = rev64(z1h) >> 1; + z2h = rev64(z2h) >> 1; + + v0 = z0; + v1 = z0h ^ z2; + v2 = z1 ^ z2h; + v3 = z1h; + + v3 = (v3 << 1) | (v2 >> 63); + v2 = (v2 << 1) | (v1 >> 63); + v1 = (v1 << 1) | (v0 >> 63); + v0 = (v0 << 1); + + v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7); + v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57); + v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7); + v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57); + + y0 = v2; + y1 = v3; + } + + br_enc64be(yb, y1); + br_enc64be(yb + 8, y0); +} diff --git a/BearSSL-OG/libbearssl/src/hash/ghash_pclmul.c b/BearSSL-OG/libbearssl/src/hash/ghash_pclmul.c new file mode 100644 index 0000000..a58e7dc --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/ghash_pclmul.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_ENABLE_INTRINSICS 1 +#include "inner.h" + +/* + * This is the GHASH implementation that leverages the pclmulqdq opcode + * (from the AES-NI instructions). + */ + +#if BR_AES_X86NI + +/* + * Test CPU support for PCLMULQDQ. + */ +static inline int +pclmul_supported(void) +{ + /* + * Bit mask for features in ECX: + * 1 PCLMULQDQ support + */ + return br_cpuid(0, 0, 0x00000002, 0); +} + +/* see bearssl_hash.h */ +br_ghash +br_ghash_pclmul_get(void) +{ + return pclmul_supported() ? &br_ghash_pclmul : 0; +} + +BR_TARGETS_X86_UP + +/* + * GHASH is defined over elements of GF(2^128) with "full little-endian" + * representation: leftmost byte is least significant, and, within each + * byte, leftmost _bit_ is least significant. The natural ordering in + * x86 is "mixed little-endian": bytes are ordered from least to most + * significant, but bits within a byte are in most-to-least significant + * order. Going to full little-endian representation would require + * reversing bits within each byte, which is doable but expensive. + * + * Instead, we go to full big-endian representation, by swapping bytes + * around, which is done with a single _mm_shuffle_epi8() opcode (it + * comes with SSSE3; all CPU that offer pclmulqdq also have SSSE3). We + * can use a full big-endian representation because in a carryless + * multiplication, we have a nice bit reversal property: + * + * rev_128(x) * rev_128(y) = rev_255(x * y) + * + * So by using full big-endian, we still get the right result, except + * that it is right-shifted by 1 bit. The left-shift is relatively + * inexpensive, and it can be mutualised. + * + * + * Since SSE2 opcodes do not have facilities for shitfting full 128-bit + * values with bit precision, we have to break down values into 64-bit + * chunks. We number chunks from 0 to 3 in left to right order. + */ + +/* + * Byte-swap a complete 128-bit value. This normally uses + * _mm_shuffle_epi8(), which gets translated to pshufb (an SSSE3 opcode). + * However, this crashes old Clang versions, so, for Clang before 3.8, + * we use an alternate (and less efficient) version. + */ +#if BR_CLANG && !BR_CLANG_3_8 +#define BYTESWAP_DECL +#define BYTESWAP_PREP (void)0 +#define BYTESWAP(x) do { \ + __m128i byteswap1, byteswap2; \ + byteswap1 = (x); \ + byteswap2 = _mm_srli_epi16(byteswap1, 8); \ + byteswap1 = _mm_slli_epi16(byteswap1, 8); \ + byteswap1 = _mm_or_si128(byteswap1, byteswap2); \ + byteswap1 = _mm_shufflelo_epi16(byteswap1, 0x1B); \ + byteswap1 = _mm_shufflehi_epi16(byteswap1, 0x1B); \ + (x) = _mm_shuffle_epi32(byteswap1, 0x4E); \ + } while (0) +#else +#define BYTESWAP_DECL __m128i byteswap_index; +#define BYTESWAP_PREP do { \ + byteswap_index = _mm_set_epi8( \ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ + } while (0) +#define BYTESWAP(x) do { \ + (x) = _mm_shuffle_epi8((x), byteswap_index); \ + } while (0) +#endif + +/* + * Call pclmulqdq. Clang appears to have trouble with the intrinsic, so, + * for that compiler, we use inline assembly. Inline assembly is + * potentially a bit slower because the compiler does not understand + * what the opcode does, and thus cannot optimize instruction + * scheduling. + * + * We use a target of "sse2" only, so that Clang may still handle the + * '__m128i' type and allocate SSE2 registers. + */ +#if BR_CLANG +BR_TARGET("sse2") +static inline __m128i +pclmulqdq00(__m128i x, __m128i y) +{ + __asm__ ("pclmulqdq $0x00, %1, %0" : "+x" (x) : "x" (y)); + return x; +} +BR_TARGET("sse2") +static inline __m128i +pclmulqdq11(__m128i x, __m128i y) +{ + __asm__ ("pclmulqdq $0x11, %1, %0" : "+x" (x) : "x" (y)); + return x; +} +#else +#define pclmulqdq00(x, y) _mm_clmulepi64_si128(x, y, 0x00) +#define pclmulqdq11(x, y) _mm_clmulepi64_si128(x, y, 0x11) +#endif + +/* + * From a 128-bit value kw, compute kx as the XOR of the two 64-bit + * halves of kw (into the right half of kx; left half is unspecified). + */ +#define BK(kw, kx) do { \ + kx = _mm_xor_si128(kw, _mm_shuffle_epi32(kw, 0x0E)); \ + } while (0) + +/* + * Combine two 64-bit values (k0:k1) into a 128-bit (kw) value and + * the XOR of the two values (kx). + */ +#define PBK(k0, k1, kw, kx) do { \ + kw = _mm_unpacklo_epi64(k1, k0); \ + kx = _mm_xor_si128(k0, k1); \ + } while (0) + +/* + * Left-shift by 1 bit a 256-bit value (in four 64-bit words). + */ +#define SL_256(x0, x1, x2, x3) do { \ + x0 = _mm_or_si128( \ + _mm_slli_epi64(x0, 1), \ + _mm_srli_epi64(x1, 63)); \ + x1 = _mm_or_si128( \ + _mm_slli_epi64(x1, 1), \ + _mm_srli_epi64(x2, 63)); \ + x2 = _mm_or_si128( \ + _mm_slli_epi64(x2, 1), \ + _mm_srli_epi64(x3, 63)); \ + x3 = _mm_slli_epi64(x3, 1); \ + } while (0) + +/* + * Perform reduction in GF(2^128). The 256-bit value is in x0..x3; + * result is written in x0..x1. + */ +#define REDUCE_F128(x0, x1, x2, x3) do { \ + x1 = _mm_xor_si128( \ + x1, \ + _mm_xor_si128( \ + _mm_xor_si128( \ + x3, \ + _mm_srli_epi64(x3, 1)), \ + _mm_xor_si128( \ + _mm_srli_epi64(x3, 2), \ + _mm_srli_epi64(x3, 7)))); \ + x2 = _mm_xor_si128( \ + _mm_xor_si128( \ + x2, \ + _mm_slli_epi64(x3, 63)), \ + _mm_xor_si128( \ + _mm_slli_epi64(x3, 62), \ + _mm_slli_epi64(x3, 57))); \ + x0 = _mm_xor_si128( \ + x0, \ + _mm_xor_si128( \ + _mm_xor_si128( \ + x2, \ + _mm_srli_epi64(x2, 1)), \ + _mm_xor_si128( \ + _mm_srli_epi64(x2, 2), \ + _mm_srli_epi64(x2, 7)))); \ + x1 = _mm_xor_si128( \ + _mm_xor_si128( \ + x1, \ + _mm_slli_epi64(x2, 63)), \ + _mm_xor_si128( \ + _mm_slli_epi64(x2, 62), \ + _mm_slli_epi64(x2, 57))); \ + } while (0) + +/* + * Square value kw into (dw,dx). + */ +#define SQUARE_F128(kw, dw, dx) do { \ + __m128i z0, z1, z2, z3; \ + z1 = pclmulqdq11(kw, kw); \ + z3 = pclmulqdq00(kw, kw); \ + z0 = _mm_shuffle_epi32(z1, 0x0E); \ + z2 = _mm_shuffle_epi32(z3, 0x0E); \ + SL_256(z0, z1, z2, z3); \ + REDUCE_F128(z0, z1, z2, z3); \ + PBK(z0, z1, dw, dx); \ + } while (0) + +/* see bearssl_hash.h */ +BR_TARGET("ssse3,pclmul") +void +br_ghash_pclmul(void *y, const void *h, const void *data, size_t len) +{ + const unsigned char *buf1, *buf2; + unsigned char tmp[64]; + size_t num4, num1; + __m128i yw, h1w, h1x; + BYTESWAP_DECL + + /* + * We split data into two chunks. First chunk starts at buf1 + * and contains num4 blocks of 64-byte values. Second chunk + * starts at buf2 and contains num1 blocks of 16-byte values. + * We want the first chunk to be as large as possible. + */ + buf1 = data; + num4 = len >> 6; + len &= 63; + buf2 = buf1 + (num4 << 6); + num1 = (len + 15) >> 4; + if ((len & 15) != 0) { + memcpy(tmp, buf2, len); + memset(tmp + len, 0, (num1 << 4) - len); + buf2 = tmp; + } + + /* + * Preparatory step for endian conversions. + */ + BYTESWAP_PREP; + + /* + * Load y and h. + */ + yw = _mm_loadu_si128(y); + h1w = _mm_loadu_si128(h); + BYTESWAP(yw); + BYTESWAP(h1w); + BK(h1w, h1x); + + if (num4 > 0) { + __m128i h2w, h2x, h3w, h3x, h4w, h4x; + __m128i t0, t1, t2, t3; + + /* + * Compute h2 = h^2. + */ + SQUARE_F128(h1w, h2w, h2x); + + /* + * Compute h3 = h^3 = h*(h^2). + */ + t1 = pclmulqdq11(h1w, h2w); + t3 = pclmulqdq00(h1w, h2w); + t2 = _mm_xor_si128(pclmulqdq00(h1x, h2x), + _mm_xor_si128(t1, t3)); + t0 = _mm_shuffle_epi32(t1, 0x0E); + t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); + t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); + SL_256(t0, t1, t2, t3); + REDUCE_F128(t0, t1, t2, t3); + PBK(t0, t1, h3w, h3x); + + /* + * Compute h4 = h^4 = (h^2)^2. + */ + SQUARE_F128(h2w, h4w, h4x); + + while (num4 -- > 0) { + __m128i aw0, aw1, aw2, aw3; + __m128i ax0, ax1, ax2, ax3; + + aw0 = _mm_loadu_si128((void *)(buf1 + 0)); + aw1 = _mm_loadu_si128((void *)(buf1 + 16)); + aw2 = _mm_loadu_si128((void *)(buf1 + 32)); + aw3 = _mm_loadu_si128((void *)(buf1 + 48)); + BYTESWAP(aw0); + BYTESWAP(aw1); + BYTESWAP(aw2); + BYTESWAP(aw3); + buf1 += 64; + + aw0 = _mm_xor_si128(aw0, yw); + BK(aw1, ax1); + BK(aw2, ax2); + BK(aw3, ax3); + BK(aw0, ax0); + + t1 = _mm_xor_si128( + _mm_xor_si128( + pclmulqdq11(aw0, h4w), + pclmulqdq11(aw1, h3w)), + _mm_xor_si128( + pclmulqdq11(aw2, h2w), + pclmulqdq11(aw3, h1w))); + t3 = _mm_xor_si128( + _mm_xor_si128( + pclmulqdq00(aw0, h4w), + pclmulqdq00(aw1, h3w)), + _mm_xor_si128( + pclmulqdq00(aw2, h2w), + pclmulqdq00(aw3, h1w))); + t2 = _mm_xor_si128( + _mm_xor_si128( + pclmulqdq00(ax0, h4x), + pclmulqdq00(ax1, h3x)), + _mm_xor_si128( + pclmulqdq00(ax2, h2x), + pclmulqdq00(ax3, h1x))); + t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3)); + t0 = _mm_shuffle_epi32(t1, 0x0E); + t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); + t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); + SL_256(t0, t1, t2, t3); + REDUCE_F128(t0, t1, t2, t3); + yw = _mm_unpacklo_epi64(t1, t0); + } + } + + while (num1 -- > 0) { + __m128i aw, ax; + __m128i t0, t1, t2, t3; + + aw = _mm_loadu_si128((void *)buf2); + BYTESWAP(aw); + buf2 += 16; + + aw = _mm_xor_si128(aw, yw); + BK(aw, ax); + + t1 = pclmulqdq11(aw, h1w); + t3 = pclmulqdq00(aw, h1w); + t2 = pclmulqdq00(ax, h1x); + t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3)); + t0 = _mm_shuffle_epi32(t1, 0x0E); + t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); + t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); + SL_256(t0, t1, t2, t3); + REDUCE_F128(t0, t1, t2, t3); + yw = _mm_unpacklo_epi64(t1, t0); + } + + BYTESWAP(yw); + _mm_storeu_si128(y, yw); +} + +BR_TARGETS_X86_DOWN + +#else + +/* see bearssl_hash.h */ +br_ghash +br_ghash_pclmul_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/hash/ghash_pwr8.c b/BearSSL-OG/libbearssl/src/hash/ghash_pwr8.c new file mode 100644 index 0000000..2e7b0f4 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/ghash_pwr8.c @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_POWER_ASM_MACROS 1 +#include "inner.h" + +/* + * This is the GHASH implementation that leverages the POWER8 opcodes. + */ + +#if BR_POWER8 + +/* + * Some symbolic names for registers. + * HB0 = 16 bytes of value 0 + * HB1 = 16 bytes of value 1 + * HB2 = 16 bytes of value 2 + * HB6 = 16 bytes of value 6 + * HB7 = 16 bytes of value 7 + * TT0, TT1 and TT2 are temporaries + * + * BSW holds the pattern for byteswapping 32-bit words; this is set only + * on little-endian systems. XBSW is the same register with the +32 offset + * for access with the VSX opcodes. + */ +#define HB0 0 +#define HB1 1 +#define HB2 2 +#define HB6 3 +#define HB7 4 +#define TT0 5 +#define TT1 6 +#define TT2 7 + +#define BSW 8 +#define XBSW 40 + +/* + * Macro to initialise the constants. + */ +#define INIT \ + vxor(HB0, HB0, HB0) \ + vspltisb(HB1, 1) \ + vspltisb(HB2, 2) \ + vspltisb(HB6, 6) \ + vspltisb(HB7, 7) \ + INIT_BSW + +/* + * Fix endianness of a value after reading it or before writing it, if + * necessary. + */ +#if BR_POWER8_LE +#define INIT_BSW lxvw4x(XBSW, 0, %[idx2be]) +#define FIX_ENDIAN(xx) vperm(xx, xx, xx, BSW) +#else +#define INIT_BSW +#define FIX_ENDIAN(xx) +#endif + +/* + * Left-shift x0:x1 by one bit to the left. This is a corrective action + * needed because GHASH is defined in full little-endian specification, + * while the opcodes use full big-endian convention, so the 255-bit product + * ends up one bit to the right. + */ +#define SL_256(x0, x1) \ + vsldoi(TT0, HB0, x1, 1) \ + vsl(x0, x0, HB1) \ + vsr(TT0, TT0, HB7) \ + vsl(x1, x1, HB1) \ + vxor(x0, x0, TT0) + +/* + * Reduce x0:x1 in GF(2^128), result in xd (register xd may be the same as + * x0 or x1, or a different register). x0 and x1 are modified. + */ +#define REDUCE_F128(xd, x0, x1) \ + vxor(x0, x0, x1) \ + vsr(TT0, x1, HB1) \ + vsr(TT1, x1, HB2) \ + vsr(TT2, x1, HB7) \ + vxor(x0, x0, TT0) \ + vxor(TT1, TT1, TT2) \ + vxor(x0, x0, TT1) \ + vsldoi(x1, x1, HB0, 15) \ + vsl(TT1, x1, HB6) \ + vsl(TT2, x1, HB1) \ + vxor(x1, TT1, TT2) \ + vsr(TT0, x1, HB1) \ + vsr(TT1, x1, HB2) \ + vsr(TT2, x1, HB7) \ + vxor(x0, x0, x1) \ + vxor(x0, x0, TT0) \ + vxor(TT1, TT1, TT2) \ + vxor(xd, x0, TT1) + +/* see bearssl_hash.h */ +void +br_ghash_pwr8(void *y, const void *h, const void *data, size_t len) +{ + const unsigned char *buf1, *buf2; + size_t num4, num1; + unsigned char tmp[64]; + long cc0, cc1, cc2, cc3; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + buf1 = data; + + /* + * Assembly code requires data into two chunks; first chunk + * must contain a number of blocks which is a multiple of 4. + * Since the processing for the first chunk is faster, we want + * to make it as big as possible. + * + * For the remainder, there are two possibilities: + * -- if the remainder size is a multiple of 16, then use it + * in place; + * -- otherwise, copy it to the tmp[] array and pad it with + * zeros. + */ + num4 = len >> 6; + buf2 = buf1 + (num4 << 6); + len &= 63; + num1 = (len + 15) >> 4; + if ((len & 15) != 0) { + memcpy(tmp, buf2, len); + memset(tmp + len, 0, (num1 << 4) - len); + buf2 = tmp; + } + + cc0 = 0; + cc1 = 16; + cc2 = 32; + cc3 = 48; + asm volatile ( + INIT + + /* + * Load current h (denoted hereafter h1) in v9. + */ + lxvw4x(41, 0, %[h]) + FIX_ENDIAN(9) + + /* + * Load current y into v28. + */ + lxvw4x(60, 0, %[y]) + FIX_ENDIAN(28) + + /* + * Split h1 into three registers: + * v17 = h1_1:h1_0 + * v18 = 0:h1_0 + * v19 = h1_1:0 + */ + xxpermdi(49, 41, 41, 2) + vsldoi(18, HB0, 9, 8) + vsldoi(19, 9, HB0, 8) + + /* + * If num4 is 0, skip directly to the second chunk. + */ + cmpldi(%[num4], 0) + beq(chunk1) + + /* + * Compute h2 = h*h in v10. + */ + vpmsumd(10, 18, 18) + vpmsumd(11, 19, 19) + SL_256(10, 11) + REDUCE_F128(10, 10, 11) + + /* + * Compute h3 = h*h*h in v11. + * We first split h2 into: + * v10 = h2_0:h2_1 + * v11 = 0:h2_0 + * v12 = h2_1:0 + * Then we do the product with h1, and reduce into v11. + */ + vsldoi(11, HB0, 10, 8) + vsldoi(12, 10, HB0, 8) + vpmsumd(13, 10, 17) + vpmsumd(11, 11, 18) + vpmsumd(12, 12, 19) + vsldoi(14, HB0, 13, 8) + vsldoi(15, 13, HB0, 8) + vxor(11, 11, 14) + vxor(12, 12, 15) + SL_256(11, 12) + REDUCE_F128(11, 11, 12) + + /* + * Compute h4 = h*h*h*h in v12. This is done by squaring h2. + */ + vsldoi(12, HB0, 10, 8) + vsldoi(13, 10, HB0, 8) + vpmsumd(12, 12, 12) + vpmsumd(13, 13, 13) + SL_256(12, 13) + REDUCE_F128(12, 12, 13) + + /* + * Repack h1, h2, h3 and h4: + * v13 = h4_0:h3_0 + * v14 = h4_1:h3_1 + * v15 = h2_0:h1_0 + * v16 = h2_1:h1_1 + */ + xxpermdi(45, 44, 43, 0) + xxpermdi(46, 44, 43, 3) + xxpermdi(47, 42, 41, 0) + xxpermdi(48, 42, 41, 3) + + /* + * Loop for each group of four blocks. + */ + mtctr(%[num4]) + label(loop4) + /* + * Read the four next blocks. + * v20 = y + a0 = b0 + * v21 = a1 = b1 + * v22 = a2 = b2 + * v23 = a3 = b3 + */ + lxvw4x(52, %[cc0], %[buf1]) + lxvw4x(53, %[cc1], %[buf1]) + lxvw4x(54, %[cc2], %[buf1]) + lxvw4x(55, %[cc3], %[buf1]) + FIX_ENDIAN(20) + FIX_ENDIAN(21) + FIX_ENDIAN(22) + FIX_ENDIAN(23) + addi(%[buf1], %[buf1], 64) + vxor(20, 20, 28) + + /* + * Repack the blocks into v9, v10, v11 and v12. + * v9 = b0_0:b1_0 + * v10 = b0_1:b1_1 + * v11 = b2_0:b3_0 + * v12 = b2_1:b3_1 + */ + xxpermdi(41, 52, 53, 0) + xxpermdi(42, 52, 53, 3) + xxpermdi(43, 54, 55, 0) + xxpermdi(44, 54, 55, 3) + + /* + * Compute the products. + * v20 = b0_0*h4_0 + b1_0*h3_0 + * v21 = b0_1*h4_0 + b1_1*h3_0 + * v22 = b0_0*h4_1 + b1_0*h3_1 + * v23 = b0_1*h4_1 + b1_1*h3_1 + * v24 = b2_0*h2_0 + b3_0*h1_0 + * v25 = b2_1*h2_0 + b3_1*h1_0 + * v26 = b2_0*h2_1 + b3_0*h1_1 + * v27 = b2_1*h2_1 + b3_1*h1_1 + */ + vpmsumd(20, 13, 9) + vpmsumd(21, 13, 10) + vpmsumd(22, 14, 9) + vpmsumd(23, 14, 10) + vpmsumd(24, 15, 11) + vpmsumd(25, 15, 12) + vpmsumd(26, 16, 11) + vpmsumd(27, 16, 12) + + /* + * Sum products into a single 256-bit result in v11:v12. + */ + vxor(11, 20, 24) + vxor(12, 23, 27) + vxor( 9, 21, 22) + vxor(10, 25, 26) + vxor(20, 9, 10) + vsldoi( 9, HB0, 20, 8) + vsldoi(10, 20, HB0, 8) + vxor(11, 11, 9) + vxor(12, 12, 10) + + /* + * Fix and reduce in GF(2^128); this is the new y (in v28). + */ + SL_256(11, 12) + REDUCE_F128(28, 11, 12) + + /* + * Loop for next group of four blocks. + */ + bdnz(loop4) + + /* + * Process second chunk, one block at a time. + */ + label(chunk1) + cmpldi(%[num1], 0) + beq(done) + + mtctr(%[num1]) + label(loop1) + /* + * Load next data block and XOR it into y. + */ + lxvw4x(41, 0, %[buf2]) +#if BR_POWER8_LE + FIX_ENDIAN(9) +#endif + addi(%[buf2], %[buf2], 16) + vxor(9, 28, 9) + + /* + * Split y into doublewords: + * v9 = y_0:y_1 + * v10 = 0:y_0 + * v11 = y_1:0 + */ + vsldoi(10, HB0, 9, 8) + vsldoi(11, 9, HB0, 8) + + /* + * Compute products with h: + * v12 = y_0 * h_0 + * v13 = y_1 * h_1 + * v14 = y_1 * h_0 + y_0 * h_1 + */ + vpmsumd(14, 9, 17) + vpmsumd(12, 10, 18) + vpmsumd(13, 11, 19) + + /* + * Propagate v14 into v12:v13 to finalise product. + */ + vsldoi(10, HB0, 14, 8) + vsldoi(11, 14, HB0, 8) + vxor(12, 12, 10) + vxor(13, 13, 11) + + /* + * Fix result and reduce into v28 (next value for y). + */ + SL_256(12, 13) + REDUCE_F128(28, 12, 13) + bdnz(loop1) + + label(done) + /* + * Write back the new y. + */ + FIX_ENDIAN(28) + stxvw4x(60, 0, %[y]) + +: [buf1] "+b" (buf1), [buf2] "+b" (buf2) +: [y] "b" (y), [h] "b" (h), [num4] "b" (num4), [num1] "b" (num1), + [cc0] "b" (cc0), [cc1] "b" (cc1), [cc2] "b" (cc2), [cc3] "b" (cc3) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", + "ctr", "memory" + ); +} + +/* see bearssl_hash.h */ +br_ghash +br_ghash_pwr8_get(void) +{ + return &br_ghash_pwr8; +} + +#else + +/* see bearssl_hash.h */ +br_ghash +br_ghash_pwr8_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/hash/md5.c b/BearSSL-OG/libbearssl/src/hash/md5.c new file mode 100644 index 0000000..0df7abe --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/md5.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D)) +#define G(B, C, D) ((((C) ^ (B)) & (D)) ^ (C)) +#define H(B, C, D) ((B) ^ (C) ^ (D)) +#define I(B, C, D) ((C) ^ ((B) | ~(D))) + +#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +/* see inner.h */ +const uint32_t br_md5_IV[4] = { + 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 +}; + +static const uint32_t K[64] = { + 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, + 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, + 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, + 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, + + 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, + 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, + 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, + 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, + + 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, + 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, + 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, + 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, + + 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, + 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, + 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, + 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 +}; + +static const unsigned char MP[48] = { + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 +}; + +/* see inner.h */ +void +br_md5_round(const unsigned char *buf, uint32_t *val) +{ + uint32_t m[16]; + uint32_t a, b, c, d; + int i; + + a = val[0]; + b = val[1]; + c = val[2]; + d = val[3]; + /* obsolete + for (i = 0; i < 16; i ++) { + m[i] = br_dec32le(buf + (i << 2)); + } + */ + br_range_dec32le(m, 16, buf); + + for (i = 0; i < 16; i += 4) { + a = b + ROTL(a + F(b, c, d) + m[i + 0] + K[i + 0], 7); + d = a + ROTL(d + F(a, b, c) + m[i + 1] + K[i + 1], 12); + c = d + ROTL(c + F(d, a, b) + m[i + 2] + K[i + 2], 17); + b = c + ROTL(b + F(c, d, a) + m[i + 3] + K[i + 3], 22); + } + for (i = 16; i < 32; i += 4) { + a = b + ROTL(a + G(b, c, d) + m[MP[i - 16]] + K[i + 0], 5); + d = a + ROTL(d + G(a, b, c) + m[MP[i - 15]] + K[i + 1], 9); + c = d + ROTL(c + G(d, a, b) + m[MP[i - 14]] + K[i + 2], 14); + b = c + ROTL(b + G(c, d, a) + m[MP[i - 13]] + K[i + 3], 20); + } + for (i = 32; i < 48; i += 4) { + a = b + ROTL(a + H(b, c, d) + m[MP[i - 16]] + K[i + 0], 4); + d = a + ROTL(d + H(a, b, c) + m[MP[i - 15]] + K[i + 1], 11); + c = d + ROTL(c + H(d, a, b) + m[MP[i - 14]] + K[i + 2], 16); + b = c + ROTL(b + H(c, d, a) + m[MP[i - 13]] + K[i + 3], 23); + } + for (i = 48; i < 64; i += 4) { + a = b + ROTL(a + I(b, c, d) + m[MP[i - 16]] + K[i + 0], 6); + d = a + ROTL(d + I(a, b, c) + m[MP[i - 15]] + K[i + 1], 10); + c = d + ROTL(c + I(d, a, b) + m[MP[i - 14]] + K[i + 2], 15); + b = c + ROTL(b + I(c, d, a) + m[MP[i - 13]] + K[i + 3], 21); + } + + val[0] += a; + val[1] += b; + val[2] += c; + val[3] += d; +} + +/* see bearssl.h */ +void +br_md5_init(br_md5_context *cc) +{ + cc->vtable = &br_md5_vtable; + memcpy(cc->val, br_md5_IV, sizeof cc->val); + cc->count = 0; +} + +/* see bearssl.h */ +void +br_md5_update(br_md5_context *cc, const void *data, size_t len) +{ + const unsigned char *buf; + size_t ptr; + + buf = data; + ptr = (size_t)cc->count & 63; + while (len > 0) { + size_t clen; + + clen = 64 - ptr; + if (clen > len) { + clen = len; + } + memcpy(cc->buf + ptr, buf, clen); + ptr += clen; + buf += clen; + len -= clen; + cc->count += (uint64_t)clen; + if (ptr == 64) { + br_md5_round(cc->buf, cc->val); + ptr = 0; + } + } +} + +/* see bearssl.h */ +void +br_md5_out(const br_md5_context *cc, void *dst) +{ + unsigned char buf[64]; + uint32_t val[4]; + size_t ptr; + + ptr = (size_t)cc->count & 63; + memcpy(buf, cc->buf, ptr); + memcpy(val, cc->val, sizeof val); + buf[ptr ++] = 0x80; + if (ptr > 56) { + memset(buf + ptr, 0, 64 - ptr); + br_md5_round(buf, val); + memset(buf, 0, 56); + } else { + memset(buf + ptr, 0, 56 - ptr); + } + br_enc64le(buf + 56, cc->count << 3); + br_md5_round(buf, val); + br_range_enc32le(dst, val, 4); +} + +/* see bearssl.h */ +uint64_t +br_md5_state(const br_md5_context *cc, void *dst) +{ + br_range_enc32le(dst, cc->val, 4); + return cc->count; +} + +/* see bearssl.h */ +void +br_md5_set_state(br_md5_context *cc, const void *stb, uint64_t count) +{ + br_range_dec32le(cc->val, 4, stb); + cc->count = count; +} + +/* see bearssl.h */ +const br_hash_class br_md5_vtable = { + sizeof(br_md5_context), + BR_HASHDESC_ID(br_md5_ID) + | BR_HASHDESC_OUT(16) + | BR_HASHDESC_STATE(16) + | BR_HASHDESC_LBLEN(6) + | BR_HASHDESC_MD_PADDING, + (void (*)(const br_hash_class **))&br_md5_init, + (void (*)(const br_hash_class **, const void *, size_t))&br_md5_update, + (void (*)(const br_hash_class *const *, void *))&br_md5_out, + (uint64_t (*)(const br_hash_class *const *, void *))&br_md5_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) + &br_md5_set_state +}; diff --git a/BearSSL-OG/libbearssl/src/hash/md5sha1.c b/BearSSL-OG/libbearssl/src/hash/md5sha1.c new file mode 100644 index 0000000..f701aee --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/md5sha1.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl.h */ +void +br_md5sha1_init(br_md5sha1_context *cc) +{ + cc->vtable = &br_md5sha1_vtable; + memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5); + memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1); + cc->count = 0; +} + +/* see bearssl.h */ +void +br_md5sha1_update(br_md5sha1_context *cc, const void *data, size_t len) +{ + const unsigned char *buf; + size_t ptr; + + buf = data; + ptr = (size_t)cc->count & 63; + while (len > 0) { + size_t clen; + + clen = 64 - ptr; + if (clen > len) { + clen = len; + } + memcpy(cc->buf + ptr, buf, clen); + ptr += clen; + buf += clen; + len -= clen; + cc->count += (uint64_t)clen; + if (ptr == 64) { + br_md5_round(cc->buf, cc->val_md5); + br_sha1_round(cc->buf, cc->val_sha1); + ptr = 0; + } + } +} + +/* see bearssl.h */ +void +br_md5sha1_out(const br_md5sha1_context *cc, void *dst) +{ + unsigned char buf[64]; + uint32_t val_md5[4]; + uint32_t val_sha1[5]; + size_t ptr; + unsigned char *out; + uint64_t count; + + count = cc->count; + ptr = (size_t)count & 63; + memcpy(buf, cc->buf, ptr); + memcpy(val_md5, cc->val_md5, sizeof val_md5); + memcpy(val_sha1, cc->val_sha1, sizeof val_sha1); + buf[ptr ++] = 0x80; + if (ptr > 56) { + memset(buf + ptr, 0, 64 - ptr); + br_md5_round(buf, val_md5); + br_sha1_round(buf, val_sha1); + memset(buf, 0, 56); + } else { + memset(buf + ptr, 0, 56 - ptr); + } + count <<= 3; + br_enc64le(buf + 56, count); + br_md5_round(buf, val_md5); + br_enc64be(buf + 56, count); + br_sha1_round(buf, val_sha1); + out = dst; + br_range_enc32le(out, val_md5, 4); + br_range_enc32be(out + 16, val_sha1, 5); +} + +/* see bearssl.h */ +uint64_t +br_md5sha1_state(const br_md5sha1_context *cc, void *dst) +{ + unsigned char *out; + + out = dst; + br_range_enc32le(out, cc->val_md5, 4); + br_range_enc32be(out + 16, cc->val_sha1, 5); + return cc->count; +} + +/* see bearssl.h */ +void +br_md5sha1_set_state(br_md5sha1_context *cc, const void *stb, uint64_t count) +{ + const unsigned char *buf; + + buf = stb; + br_range_dec32le(cc->val_md5, 4, buf); + br_range_dec32be(cc->val_sha1, 5, buf + 16); + cc->count = count; +} + +/* see bearssl.h */ +const br_hash_class br_md5sha1_vtable = { + sizeof(br_md5sha1_context), + BR_HASHDESC_ID(br_md5sha1_ID) + | BR_HASHDESC_OUT(36) + | BR_HASHDESC_STATE(36) + | BR_HASHDESC_LBLEN(6), + (void (*)(const br_hash_class **))&br_md5sha1_init, + (void (*)(const br_hash_class **, const void *, size_t)) + &br_md5sha1_update, + (void (*)(const br_hash_class *const *, void *)) + &br_md5sha1_out, + (uint64_t (*)(const br_hash_class *const *, void *)) + &br_md5sha1_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) + &br_md5sha1_set_state +}; diff --git a/BearSSL-OG/libbearssl/src/hash/mgf1.c b/BearSSL-OG/libbearssl/src/hash/mgf1.c new file mode 100644 index 0000000..7a23588 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/mgf1.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_mgf1_xor(void *data, size_t len, + const br_hash_class *dig, const void *seed, size_t seed_len) +{ + unsigned char *buf; + size_t u, hlen; + uint32_t c; + + buf = data; + hlen = br_digest_size(dig); + for (u = 0, c = 0; u < len; u += hlen, c ++) { + br_hash_compat_context hc; + unsigned char tmp[64]; + size_t v; + + hc.vtable = dig; + dig->init(&hc.vtable); + dig->update(&hc.vtable, seed, seed_len); + br_enc32be(tmp, c); + dig->update(&hc.vtable, tmp, 4); + dig->out(&hc.vtable, tmp); + for (v = 0; v < hlen; v ++) { + if ((u + v) >= len) { + break; + } + buf[u + v] ^= tmp[v]; + } + } +} diff --git a/BearSSL-OG/libbearssl/src/hash/multihash.c b/BearSSL-OG/libbearssl/src/hash/multihash.c new file mode 100644 index 0000000..b6df2e0 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/multihash.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * An aggregate context that is large enough for all supported hash + * functions. + */ +typedef union { + const br_hash_class *vtable; + br_md5_context md5; + br_sha1_context sha1; + br_sha224_context sha224; + br_sha256_context sha256; + br_sha384_context sha384; + br_sha512_context sha512; +} gen_hash_context; + +/* + * Get the offset to the state for a specific hash function within the + * context structure. This shall be called only for the supported hash + * functions, + */ +static size_t +get_state_offset(int id) +{ + if (id >= 5) { + /* + * SHA-384 has id 5, and SHA-512 has id 6. Both use + * eight 64-bit words for their state. + */ + return offsetof(br_multihash_context, val_64) + + ((size_t)(id - 5) * (8 * sizeof(uint64_t))); + } else { + /* + * MD5 has id 1, SHA-1 has id 2, SHA-224 has id 3 and + * SHA-256 has id 4. They use 32-bit words for their + * states (4 words for MD5, 5 for SHA-1, 8 for SHA-224 + * and 8 for SHA-256). + */ + unsigned x; + + x = id - 1; + x = ((x + (x & (x >> 1))) << 2) + (x >> 1); + return offsetof(br_multihash_context, val_32) + + x * sizeof(uint32_t); + } +} + +/* see bearssl_hash.h */ +void +br_multihash_zero(br_multihash_context *ctx) +{ + /* + * This is not standard, but yields very short and efficient code, + * and it works "everywhere". + */ + memset(ctx, 0, sizeof *ctx); +} + +/* see bearssl_hash.h */ +void +br_multihash_init(br_multihash_context *ctx) +{ + int i; + + ctx->count = 0; + for (i = 1; i <= 6; i ++) { + const br_hash_class *hc; + + hc = ctx->impl[i - 1]; + if (hc != NULL) { + gen_hash_context g; + + hc->init(&g.vtable); + hc->state(&g.vtable, + (unsigned char *)ctx + get_state_offset(i)); + } + } +} + +/* see bearssl_hash.h */ +void +br_multihash_update(br_multihash_context *ctx, const void *data, size_t len) +{ + const unsigned char *buf; + size_t ptr; + + buf = data; + ptr = (size_t)ctx->count & 127; + while (len > 0) { + size_t clen; + + clen = 128 - ptr; + if (clen > len) { + clen = len; + } + memcpy(ctx->buf + ptr, buf, clen); + ptr += clen; + buf += clen; + len -= clen; + ctx->count += (uint64_t)clen; + if (ptr == 128) { + int i; + + for (i = 1; i <= 6; i ++) { + const br_hash_class *hc; + + hc = ctx->impl[i - 1]; + if (hc != NULL) { + gen_hash_context g; + unsigned char *state; + + state = (unsigned char *)ctx + + get_state_offset(i); + hc->set_state(&g.vtable, + state, ctx->count - 128); + hc->update(&g.vtable, ctx->buf, 128); + hc->state(&g.vtable, state); + } + } + ptr = 0; + } + } +} + +/* see bearssl_hash.h */ +size_t +br_multihash_out(const br_multihash_context *ctx, int id, void *dst) +{ + const br_hash_class *hc; + gen_hash_context g; + const unsigned char *state; + + hc = ctx->impl[id - 1]; + if (hc == NULL) { + return 0; + } + state = (const unsigned char *)ctx + get_state_offset(id); + hc->set_state(&g.vtable, state, ctx->count & ~(uint64_t)127); + hc->update(&g.vtable, ctx->buf, ctx->count & (uint64_t)127); + hc->out(&g.vtable, dst); + return (hc->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; +} diff --git a/BearSSL-OG/libbearssl/src/hash/sha1.c b/BearSSL-OG/libbearssl/src/hash/sha1.c new file mode 100644 index 0000000..4f65d84 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/sha1.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D)) +#define G(B, C, D) ((B) ^ (C) ^ (D)) +#define H(B, C, D) (((D) & (C)) | (((D) | (C)) & (B))) +#define I(B, C, D) G(B, C, D) + +#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +#define K1 ((uint32_t)0x5A827999) +#define K2 ((uint32_t)0x6ED9EBA1) +#define K3 ((uint32_t)0x8F1BBCDC) +#define K4 ((uint32_t)0xCA62C1D6) + +/* see inner.h */ +const uint32_t br_sha1_IV[5] = { + 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 +}; + +/* see inner.h */ +void +br_sha1_round(const unsigned char *buf, uint32_t *val) +{ + uint32_t m[80]; + uint32_t a, b, c, d, e; + int i; + + a = val[0]; + b = val[1]; + c = val[2]; + d = val[3]; + e = val[4]; + br_range_dec32be(m, 16, buf); + for (i = 16; i < 80; i ++) { + uint32_t x = m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]; + m[i] = ROTL(x, 1); + } + + for (i = 0; i < 20; i += 5) { + e += ROTL(a, 5) + F(b, c, d) + K1 + m[i + 0]; b = ROTL(b, 30); + d += ROTL(e, 5) + F(a, b, c) + K1 + m[i + 1]; a = ROTL(a, 30); + c += ROTL(d, 5) + F(e, a, b) + K1 + m[i + 2]; e = ROTL(e, 30); + b += ROTL(c, 5) + F(d, e, a) + K1 + m[i + 3]; d = ROTL(d, 30); + a += ROTL(b, 5) + F(c, d, e) + K1 + m[i + 4]; c = ROTL(c, 30); + } + for (i = 20; i < 40; i += 5) { + e += ROTL(a, 5) + G(b, c, d) + K2 + m[i + 0]; b = ROTL(b, 30); + d += ROTL(e, 5) + G(a, b, c) + K2 + m[i + 1]; a = ROTL(a, 30); + c += ROTL(d, 5) + G(e, a, b) + K2 + m[i + 2]; e = ROTL(e, 30); + b += ROTL(c, 5) + G(d, e, a) + K2 + m[i + 3]; d = ROTL(d, 30); + a += ROTL(b, 5) + G(c, d, e) + K2 + m[i + 4]; c = ROTL(c, 30); + } + for (i = 40; i < 60; i += 5) { + e += ROTL(a, 5) + H(b, c, d) + K3 + m[i + 0]; b = ROTL(b, 30); + d += ROTL(e, 5) + H(a, b, c) + K3 + m[i + 1]; a = ROTL(a, 30); + c += ROTL(d, 5) + H(e, a, b) + K3 + m[i + 2]; e = ROTL(e, 30); + b += ROTL(c, 5) + H(d, e, a) + K3 + m[i + 3]; d = ROTL(d, 30); + a += ROTL(b, 5) + H(c, d, e) + K3 + m[i + 4]; c = ROTL(c, 30); + } + for (i = 60; i < 80; i += 5) { + e += ROTL(a, 5) + I(b, c, d) + K4 + m[i + 0]; b = ROTL(b, 30); + d += ROTL(e, 5) + I(a, b, c) + K4 + m[i + 1]; a = ROTL(a, 30); + c += ROTL(d, 5) + I(e, a, b) + K4 + m[i + 2]; e = ROTL(e, 30); + b += ROTL(c, 5) + I(d, e, a) + K4 + m[i + 3]; d = ROTL(d, 30); + a += ROTL(b, 5) + I(c, d, e) + K4 + m[i + 4]; c = ROTL(c, 30); + } + + val[0] += a; + val[1] += b; + val[2] += c; + val[3] += d; + val[4] += e; +} + +/* see bearssl.h */ +void +br_sha1_init(br_sha1_context *cc) +{ + cc->vtable = &br_sha1_vtable; + memcpy(cc->val, br_sha1_IV, sizeof cc->val); + cc->count = 0; +} + +/* see bearssl.h */ +void +br_sha1_update(br_sha1_context *cc, const void *data, size_t len) +{ + const unsigned char *buf; + size_t ptr; + + buf = data; + ptr = (size_t)cc->count & 63; + while (len > 0) { + size_t clen; + + clen = 64 - ptr; + if (clen > len) { + clen = len; + } + memcpy(cc->buf + ptr, buf, clen); + ptr += clen; + buf += clen; + len -= clen; + cc->count += (uint64_t)clen; + if (ptr == 64) { + br_sha1_round(cc->buf, cc->val); + ptr = 0; + } + } +} + +/* see bearssl.h */ +void +br_sha1_out(const br_sha1_context *cc, void *dst) +{ + unsigned char buf[64]; + uint32_t val[5]; + size_t ptr; + + ptr = (size_t)cc->count & 63; + memcpy(buf, cc->buf, ptr); + memcpy(val, cc->val, sizeof val); + buf[ptr ++] = 0x80; + if (ptr > 56) { + memset(buf + ptr, 0, 64 - ptr); + br_sha1_round(buf, val); + memset(buf, 0, 56); + } else { + memset(buf + ptr, 0, 56 - ptr); + } + br_enc64be(buf + 56, cc->count << 3); + br_sha1_round(buf, val); + br_range_enc32be(dst, val, 5); +} + +/* see bearssl.h */ +uint64_t +br_sha1_state(const br_sha1_context *cc, void *dst) +{ + br_range_enc32be(dst, cc->val, 5); + return cc->count; +} + +/* see bearssl.h */ +void +br_sha1_set_state(br_sha1_context *cc, const void *stb, uint64_t count) +{ + br_range_dec32be(cc->val, 5, stb); + cc->count = count; +} + +/* see bearssl.h */ +const br_hash_class br_sha1_vtable = { + sizeof(br_sha1_context), + BR_HASHDESC_ID(br_sha1_ID) + | BR_HASHDESC_OUT(20) + | BR_HASHDESC_STATE(20) + | BR_HASHDESC_LBLEN(6) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE, + (void (*)(const br_hash_class **))&br_sha1_init, + (void (*)(const br_hash_class **, const void *, size_t))&br_sha1_update, + (void (*)(const br_hash_class *const *, void *))&br_sha1_out, + (uint64_t (*)(const br_hash_class *const *, void *))&br_sha1_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) + &br_sha1_set_state +}; diff --git a/BearSSL-OG/libbearssl/src/hash/sha2big.c b/BearSSL-OG/libbearssl/src/hash/sha2big.c new file mode 100644 index 0000000..5be92ed --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/sha2big.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z)) +#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X))) + +#define ROTR(x, n) (((uint64_t)(x) << (64 - (n))) | ((uint64_t)(x) >> (n))) + +#define BSG5_0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) +#define BSG5_1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) +#define SSG5_0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ (uint64_t)((x) >> 7)) +#define SSG5_1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ (uint64_t)((x) >> 6)) + +static const uint64_t IV384[8] = { + 0xCBBB9D5DC1059ED8, 0x629A292A367CD507, + 0x9159015A3070DD17, 0x152FECD8F70E5939, + 0x67332667FFC00B31, 0x8EB44A8768581511, + 0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4 +}; + +static const uint64_t IV512[8] = { + 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, + 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, + 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, + 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 +}; + +static const uint64_t K[80] = { + 0x428A2F98D728AE22, 0x7137449123EF65CD, + 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC, + 0x3956C25BF348B538, 0x59F111F1B605D019, + 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118, + 0xD807AA98A3030242, 0x12835B0145706FBE, + 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2, + 0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1, + 0x9BDC06A725C71235, 0xC19BF174CF692694, + 0xE49B69C19EF14AD2, 0xEFBE4786384F25E3, + 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65, + 0x2DE92C6F592B0275, 0x4A7484AA6EA6E483, + 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5, + 0x983E5152EE66DFAB, 0xA831C66D2DB43210, + 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4, + 0xC6E00BF33DA88FC2, 0xD5A79147930AA725, + 0x06CA6351E003826F, 0x142929670A0E6E70, + 0x27B70A8546D22FFC, 0x2E1B21385C26C926, + 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF, + 0x650A73548BAF63DE, 0x766A0ABB3C77B2A8, + 0x81C2C92E47EDAEE6, 0x92722C851482353B, + 0xA2BFE8A14CF10364, 0xA81A664BBC423001, + 0xC24B8B70D0F89791, 0xC76C51A30654BE30, + 0xD192E819D6EF5218, 0xD69906245565A910, + 0xF40E35855771202A, 0x106AA07032BBD1B8, + 0x19A4C116B8D2D0C8, 0x1E376C085141AB53, + 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8, + 0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB, + 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3, + 0x748F82EE5DEFB2FC, 0x78A5636F43172F60, + 0x84C87814A1F0AB72, 0x8CC702081A6439EC, + 0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9, + 0xBEF9A3F7B2C67915, 0xC67178F2E372532B, + 0xCA273ECEEA26619C, 0xD186B8C721C0C207, + 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178, + 0x06F067AA72176FBA, 0x0A637DC5A2C898A6, + 0x113F9804BEF90DAE, 0x1B710B35131C471B, + 0x28DB77F523047D84, 0x32CAAB7B40C72493, + 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C, + 0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A, + 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817 +}; + +static void +sha2big_round(const unsigned char *buf, uint64_t *val) +{ + +#define SHA2BIG_STEP(A, B, C, D, E, F, G, H, j) do { \ + uint64_t T1, T2; \ + T1 = H + BSG5_1(E) + CH(E, F, G) + K[j] + w[j]; \ + T2 = BSG5_0(A) + MAJ(A, B, C); \ + D += T1; \ + H = T1 + T2; \ + } while (0) + + int i; + uint64_t a, b, c, d, e, f, g, h; + uint64_t w[80]; + + br_range_dec64be(w, 16, buf); + for (i = 16; i < 80; i ++) { + w[i] = SSG5_1(w[i - 2]) + w[i - 7] + + SSG5_0(w[i - 15]) + w[i - 16]; + } + a = val[0]; + b = val[1]; + c = val[2]; + d = val[3]; + e = val[4]; + f = val[5]; + g = val[6]; + h = val[7]; + for (i = 0; i < 80; i += 8) { + SHA2BIG_STEP(a, b, c, d, e, f, g, h, i + 0); + SHA2BIG_STEP(h, a, b, c, d, e, f, g, i + 1); + SHA2BIG_STEP(g, h, a, b, c, d, e, f, i + 2); + SHA2BIG_STEP(f, g, h, a, b, c, d, e, i + 3); + SHA2BIG_STEP(e, f, g, h, a, b, c, d, i + 4); + SHA2BIG_STEP(d, e, f, g, h, a, b, c, i + 5); + SHA2BIG_STEP(c, d, e, f, g, h, a, b, i + 6); + SHA2BIG_STEP(b, c, d, e, f, g, h, a, i + 7); + } + val[0] += a; + val[1] += b; + val[2] += c; + val[3] += d; + val[4] += e; + val[5] += f; + val[6] += g; + val[7] += h; +} + +static void +sha2big_update(br_sha384_context *cc, const void *data, size_t len) +{ + const unsigned char *buf; + size_t ptr; + + buf = data; + ptr = (size_t)cc->count & 127; + cc->count += (uint64_t)len; + while (len > 0) { + size_t clen; + + clen = 128 - ptr; + if (clen > len) { + clen = len; + } + memcpy(cc->buf + ptr, buf, clen); + ptr += clen; + buf += clen; + len -= clen; + if (ptr == 128) { + sha2big_round(cc->buf, cc->val); + ptr = 0; + } + } +} + +static void +sha2big_out(const br_sha384_context *cc, void *dst, int num) +{ + unsigned char buf[128]; + uint64_t val[8]; + size_t ptr; + + ptr = (size_t)cc->count & 127; + memcpy(buf, cc->buf, ptr); + memcpy(val, cc->val, sizeof val); + buf[ptr ++] = 0x80; + if (ptr > 112) { + memset(buf + ptr, 0, 128 - ptr); + sha2big_round(buf, val); + memset(buf, 0, 112); + } else { + memset(buf + ptr, 0, 112 - ptr); + } + br_enc64be(buf + 112, cc->count >> 61); + br_enc64be(buf + 120, cc->count << 3); + sha2big_round(buf, val); + br_range_enc64be(dst, val, num); +} + +/* see bearssl.h */ +void +br_sha384_init(br_sha384_context *cc) +{ + cc->vtable = &br_sha384_vtable; + memcpy(cc->val, IV384, sizeof IV384); + cc->count = 0; +} + +/* see bearssl.h */ +void +br_sha384_update(br_sha384_context *cc, const void *data, size_t len) +{ + sha2big_update(cc, data, len); +} + +/* see bearssl.h */ +void +br_sha384_out(const br_sha384_context *cc, void *dst) +{ + sha2big_out(cc, dst, 6); +} + +/* see bearssl.h */ +uint64_t +br_sha384_state(const br_sha384_context *cc, void *dst) +{ + br_range_enc64be(dst, cc->val, 8); + return cc->count; +} + +/* see bearssl.h */ +void +br_sha384_set_state(br_sha384_context *cc, const void *stb, uint64_t count) +{ + br_range_dec64be(cc->val, 8, stb); + cc->count = count; +} + +/* see bearssl.h */ +void +br_sha512_init(br_sha512_context *cc) +{ + cc->vtable = &br_sha512_vtable; + memcpy(cc->val, IV512, sizeof IV512); + cc->count = 0; +} + +/* see bearssl.h */ +void +br_sha512_out(const br_sha512_context *cc, void *dst) +{ + sha2big_out(cc, dst, 8); +} + +/* see bearssl.h */ +const br_hash_class br_sha384_vtable = { + sizeof(br_sha384_context), + BR_HASHDESC_ID(br_sha384_ID) + | BR_HASHDESC_OUT(48) + | BR_HASHDESC_STATE(64) + | BR_HASHDESC_LBLEN(7) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE + | BR_HASHDESC_MD_PADDING_128, + (void (*)(const br_hash_class **))&br_sha384_init, + (void (*)(const br_hash_class **, const void *, size_t)) + &br_sha384_update, + (void (*)(const br_hash_class *const *, void *))&br_sha384_out, + (uint64_t (*)(const br_hash_class *const *, void *))&br_sha384_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) + &br_sha384_set_state +}; + +/* see bearssl.h */ +const br_hash_class br_sha512_vtable = { + sizeof(br_sha512_context), + BR_HASHDESC_ID(br_sha512_ID) + | BR_HASHDESC_OUT(64) + | BR_HASHDESC_STATE(64) + | BR_HASHDESC_LBLEN(7) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE + | BR_HASHDESC_MD_PADDING_128, + (void (*)(const br_hash_class **))&br_sha512_init, + (void (*)(const br_hash_class **, const void *, size_t)) + &br_sha512_update, + (void (*)(const br_hash_class *const *, void *))&br_sha512_out, + (uint64_t (*)(const br_hash_class *const *, void *))&br_sha512_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) + &br_sha512_set_state +}; diff --git a/BearSSL-OG/libbearssl/src/hash/sha2small.c b/BearSSL-OG/libbearssl/src/hash/sha2small.c new file mode 100644 index 0000000..ca19655 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/hash/sha2small.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z)) +#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X))) + +#define ROTR(x, n) (((uint32_t)(x) << (32 - (n))) | ((uint32_t)(x) >> (n))) + +#define BSG2_0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define BSG2_1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SSG2_0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ (uint32_t)((x) >> 3)) +#define SSG2_1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ (uint32_t)((x) >> 10)) + +/* see inner.h */ +const uint32_t br_sha224_IV[8] = { + 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, + 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4 +}; + +/* see inner.h */ +const uint32_t br_sha256_IV[8] = { + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 +}; + +static const uint32_t K[64] = { + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 +}; + +/* see inner.h */ +void +br_sha2small_round(const unsigned char *buf, uint32_t *val) +{ + +#define SHA2_STEP(A, B, C, D, E, F, G, H, j) do { \ + uint32_t T1, T2; \ + T1 = H + BSG2_1(E) + CH(E, F, G) + K[j] + w[j]; \ + T2 = BSG2_0(A) + MAJ(A, B, C); \ + D += T1; \ + H = T1 + T2; \ + } while (0) + + int i; + uint32_t a, b, c, d, e, f, g, h; + uint32_t w[64]; + + br_range_dec32be(w, 16, buf); + for (i = 16; i < 64; i ++) { + w[i] = SSG2_1(w[i - 2]) + w[i - 7] + + SSG2_0(w[i - 15]) + w[i - 16]; + } + a = val[0]; + b = val[1]; + c = val[2]; + d = val[3]; + e = val[4]; + f = val[5]; + g = val[6]; + h = val[7]; + for (i = 0; i < 64; i += 8) { + SHA2_STEP(a, b, c, d, e, f, g, h, i + 0); + SHA2_STEP(h, a, b, c, d, e, f, g, i + 1); + SHA2_STEP(g, h, a, b, c, d, e, f, i + 2); + SHA2_STEP(f, g, h, a, b, c, d, e, i + 3); + SHA2_STEP(e, f, g, h, a, b, c, d, i + 4); + SHA2_STEP(d, e, f, g, h, a, b, c, i + 5); + SHA2_STEP(c, d, e, f, g, h, a, b, i + 6); + SHA2_STEP(b, c, d, e, f, g, h, a, i + 7); + } + val[0] += a; + val[1] += b; + val[2] += c; + val[3] += d; + val[4] += e; + val[5] += f; + val[6] += g; + val[7] += h; + +#if 0 +/* obsolete */ +#define SHA2_MEXP1(pc) do { \ + W[pc] = br_dec32be(buf + ((pc) << 2)); \ + } while (0) + +#define SHA2_MEXP2(pc) do { \ + W[(pc) & 0x0F] = SSG2_1(W[((pc) - 2) & 0x0F]) \ + + W[((pc) - 7) & 0x0F] \ + + SSG2_0(W[((pc) - 15) & 0x0F]) + W[(pc) & 0x0F]; \ + } while (0) + +#define SHA2_STEPn(n, a, b, c, d, e, f, g, h, pc) do { \ + uint32_t t1, t2; \ + SHA2_MEXP ## n(pc); \ + t1 = h + BSG2_1(e) + CH(e, f, g) \ + + K[pcount + (pc)] + W[(pc) & 0x0F]; \ + t2 = BSG2_0(a) + MAJ(a, b, c); \ + d += t1; \ + h = t1 + t2; \ + } while (0) + +#define SHA2_STEP1(a, b, c, d, e, f, g, h, pc) \ + SHA2_STEPn(1, a, b, c, d, e, f, g, h, pc) +#define SHA2_STEP2(a, b, c, d, e, f, g, h, pc) \ + SHA2_STEPn(2, a, b, c, d, e, f, g, h, pc) + + uint32_t A, B, C, D, E, F, G, H; + uint32_t W[16]; + unsigned pcount; + + A = val[0]; + B = val[1]; + C = val[2]; + D = val[3]; + E = val[4]; + F = val[5]; + G = val[6]; + H = val[7]; + pcount = 0; + SHA2_STEP1(A, B, C, D, E, F, G, H, 0); + SHA2_STEP1(H, A, B, C, D, E, F, G, 1); + SHA2_STEP1(G, H, A, B, C, D, E, F, 2); + SHA2_STEP1(F, G, H, A, B, C, D, E, 3); + SHA2_STEP1(E, F, G, H, A, B, C, D, 4); + SHA2_STEP1(D, E, F, G, H, A, B, C, 5); + SHA2_STEP1(C, D, E, F, G, H, A, B, 6); + SHA2_STEP1(B, C, D, E, F, G, H, A, 7); + SHA2_STEP1(A, B, C, D, E, F, G, H, 8); + SHA2_STEP1(H, A, B, C, D, E, F, G, 9); + SHA2_STEP1(G, H, A, B, C, D, E, F, 10); + SHA2_STEP1(F, G, H, A, B, C, D, E, 11); + SHA2_STEP1(E, F, G, H, A, B, C, D, 12); + SHA2_STEP1(D, E, F, G, H, A, B, C, 13); + SHA2_STEP1(C, D, E, F, G, H, A, B, 14); + SHA2_STEP1(B, C, D, E, F, G, H, A, 15); + for (pcount = 16; pcount < 64; pcount += 16) { + SHA2_STEP2(A, B, C, D, E, F, G, H, 0); + SHA2_STEP2(H, A, B, C, D, E, F, G, 1); + SHA2_STEP2(G, H, A, B, C, D, E, F, 2); + SHA2_STEP2(F, G, H, A, B, C, D, E, 3); + SHA2_STEP2(E, F, G, H, A, B, C, D, 4); + SHA2_STEP2(D, E, F, G, H, A, B, C, 5); + SHA2_STEP2(C, D, E, F, G, H, A, B, 6); + SHA2_STEP2(B, C, D, E, F, G, H, A, 7); + SHA2_STEP2(A, B, C, D, E, F, G, H, 8); + SHA2_STEP2(H, A, B, C, D, E, F, G, 9); + SHA2_STEP2(G, H, A, B, C, D, E, F, 10); + SHA2_STEP2(F, G, H, A, B, C, D, E, 11); + SHA2_STEP2(E, F, G, H, A, B, C, D, 12); + SHA2_STEP2(D, E, F, G, H, A, B, C, 13); + SHA2_STEP2(C, D, E, F, G, H, A, B, 14); + SHA2_STEP2(B, C, D, E, F, G, H, A, 15); + } + val[0] += A; + val[1] += B; + val[2] += C; + val[3] += D; + val[4] += E; + val[5] += F; + val[6] += G; + val[7] += H; +#endif +} + +static void +sha2small_update(br_sha224_context *cc, const void *data, size_t len) +{ + const unsigned char *buf; + size_t ptr; + + buf = data; + ptr = (size_t)cc->count & 63; + cc->count += (uint64_t)len; + while (len > 0) { + size_t clen; + + clen = 64 - ptr; + if (clen > len) { + clen = len; + } + memcpy(cc->buf + ptr, buf, clen); + ptr += clen; + buf += clen; + len -= clen; + if (ptr == 64) { + br_sha2small_round(cc->buf, cc->val); + ptr = 0; + } + } +} + +static void +sha2small_out(const br_sha224_context *cc, void *dst, int num) +{ + unsigned char buf[64]; + uint32_t val[8]; + size_t ptr; + + ptr = (size_t)cc->count & 63; + memcpy(buf, cc->buf, ptr); + memcpy(val, cc->val, sizeof val); + buf[ptr ++] = 0x80; + if (ptr > 56) { + memset(buf + ptr, 0, 64 - ptr); + br_sha2small_round(buf, val); + memset(buf, 0, 56); + } else { + memset(buf + ptr, 0, 56 - ptr); + } + br_enc64be(buf + 56, cc->count << 3); + br_sha2small_round(buf, val); + br_range_enc32be(dst, val, num); +} + +/* see bearssl.h */ +void +br_sha224_init(br_sha224_context *cc) +{ + cc->vtable = &br_sha224_vtable; + memcpy(cc->val, br_sha224_IV, sizeof cc->val); + cc->count = 0; +} + +/* see bearssl.h */ +void +br_sha224_update(br_sha224_context *cc, const void *data, size_t len) +{ + sha2small_update(cc, data, len); +} + +/* see bearssl.h */ +void +br_sha224_out(const br_sha224_context *cc, void *dst) +{ + sha2small_out(cc, dst, 7); +} + +/* see bearssl.h */ +uint64_t +br_sha224_state(const br_sha224_context *cc, void *dst) +{ + br_range_enc32be(dst, cc->val, 8); + return cc->count; +} + +/* see bearssl.h */ +void +br_sha224_set_state(br_sha224_context *cc, const void *stb, uint64_t count) +{ + br_range_dec32be(cc->val, 8, stb); + cc->count = count; +} + +/* see bearssl.h */ +void +br_sha256_init(br_sha256_context *cc) +{ + cc->vtable = &br_sha256_vtable; + memcpy(cc->val, br_sha256_IV, sizeof cc->val); + cc->count = 0; +} + +/* see bearssl.h */ +void +br_sha256_out(const br_sha256_context *cc, void *dst) +{ + sha2small_out(cc, dst, 8); +} + +/* see bearssl.h */ +const br_hash_class br_sha224_vtable = { + sizeof(br_sha224_context), + BR_HASHDESC_ID(br_sha224_ID) + | BR_HASHDESC_OUT(28) + | BR_HASHDESC_STATE(32) + | BR_HASHDESC_LBLEN(6) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE, + (void (*)(const br_hash_class **))&br_sha224_init, + (void (*)(const br_hash_class **, + const void *, size_t))&br_sha224_update, + (void (*)(const br_hash_class *const *, void *))&br_sha224_out, + (uint64_t (*)(const br_hash_class *const *, void *))&br_sha224_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) + &br_sha224_set_state +}; + +/* see bearssl.h */ +const br_hash_class br_sha256_vtable = { + sizeof(br_sha256_context), + BR_HASHDESC_ID(br_sha256_ID) + | BR_HASHDESC_OUT(32) + | BR_HASHDESC_STATE(32) + | BR_HASHDESC_LBLEN(6) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE, + (void (*)(const br_hash_class **))&br_sha256_init, + (void (*)(const br_hash_class **, + const void *, size_t))&br_sha256_update, + (void (*)(const br_hash_class *const *, void *))&br_sha256_out, + (uint64_t (*)(const br_hash_class *const *, void *))&br_sha256_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) + &br_sha256_set_state +}; diff --git a/BearSSL-OG/libbearssl/src/inner.h b/BearSSL-OG/libbearssl/src/inner.h new file mode 100644 index 0000000..acb5b9a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/inner.h @@ -0,0 +1,2584 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef INNER_H__ +#define INNER_H__ + +#include +#include + +#include "config.h" +#include "bearssl.h" + +/* + * On MSVC, disable the warning about applying unary minus on an + * unsigned type: it is standard, we do it all the time, and for + * good reasons. + */ +#if _MSC_VER +#pragma warning( disable : 4146 ) +#endif + +/* + * Maximum size for a RSA modulus (in bits). Allocated stack buffers + * depend on that size, so this value should be kept small. Currently, + * 2048-bit RSA keys offer adequate security, and should still do so for + * the next few decades; however, a number of widespread PKI have + * already set their root keys to RSA-4096, so we should be able to + * process such keys. + * + * This value MUST be a multiple of 64. This value MUST NOT exceed 47666 + * (some computations in RSA key generation rely on the factor size being + * no more than 23833 bits). RSA key sizes beyond 3072 bits don't make a + * lot of sense anyway. + */ +#define BR_MAX_RSA_SIZE 4096 + +/* + * Minimum size for a RSA modulus (in bits); this value is used only to + * filter out invalid parameters for key pair generation. Normally, + * applications should not use RSA keys smaller than 2048 bits; but some + * specific cases might need shorter keys, for legacy or research + * purposes. + */ +#define BR_MIN_RSA_SIZE 512 + +/* + * Maximum size for a RSA factor (in bits). This is for RSA private-key + * operations. Default is to support factors up to a bit more than half + * the maximum modulus size. + * + * This value MUST be a multiple of 32. + */ +#define BR_MAX_RSA_FACTOR ((BR_MAX_RSA_SIZE + 64) >> 1) + +/* + * Maximum size for an EC curve (modulus or order), in bits. Size of + * stack buffers depends on that parameter. This size MUST be a multiple + * of 8 (so that decoding an integer with that many bytes does not + * overflow). + */ +#define BR_MAX_EC_SIZE 528 + +/* + * Some macros to recognize the current architecture. Right now, we are + * interested into automatically recognizing architecture with efficient + * 64-bit types so that we may automatically use implementations that + * use 64-bit registers in that case. Future versions may detect, e.g., + * availability of SSE2 intrinsics. + * + * If 'unsigned long' is a 64-bit type, then we assume that 64-bit types + * are efficient. Otherwise, we rely on macros that depend on compiler, + * OS and architecture. In any case, failure to detect the architecture + * as 64-bit means that the 32-bit code will be used, and that code + * works also on 64-bit architectures (the 64-bit code may simply be + * more efficient). + * + * The test on 'unsigned long' should already catch most cases, the one + * notable exception being Windows code where 'unsigned long' is kept to + * 32-bit for compatibility with all the legacy code that liberally uses + * the 'DWORD' type for 32-bit values. + * + * Macro names are taken from: http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros + */ +#ifndef BR_64 +#if ((ULONG_MAX >> 31) >> 31) == 3 +#define BR_64 1 +#elif defined(__ia64) || defined(__itanium__) || defined(_M_IA64) +#define BR_64 1 +#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) \ + || defined(__64BIT__) || defined(_LP64) || defined(__LP64__) +#define BR_64 1 +#elif defined(__sparc64__) +#define BR_64 1 +#elif defined(__x86_64__) || defined(_M_X64) +#define BR_64 1 +#elif defined(__aarch64__) || defined(_M_ARM64) +#define BR_64 1 +#elif defined(__mips64) +#define BR_64 1 +#endif +#endif + +/* + * Set BR_LOMUL on platforms where it makes sense. + */ +#ifndef BR_LOMUL +#if BR_ARMEL_CORTEXM_GCC +#define BR_LOMUL 1 +#endif +#endif + +/* + * Architecture detection. + */ +#ifndef BR_i386 +#if __i386__ || _M_IX86 +#define BR_i386 1 +#endif +#endif + +#ifndef BR_amd64 +#if __x86_64__ || _M_X64 +#define BR_amd64 1 +#endif +#endif + +/* + * Compiler brand and version. + * + * Implementations that use intrinsics need to detect the compiler type + * and version because some specific actions may be needed to activate + * the corresponding opcodes, both for header inclusion, and when using + * them in a function. + * + * BR_GCC, BR_CLANG and BR_MSC will be set to 1 for, respectively, GCC, + * Clang and MS Visual C. For each of them, sub-macros will be defined + * for versions; each sub-macro is set whenever the compiler version is + * at least as recent as the one corresponding to the macro. + */ + +/* + * GCC thresholds are on versions 4.4 to 4.9 and 5.0. + */ +#ifndef BR_GCC +#if __GNUC__ && !__clang__ +#define BR_GCC 1 + +#if __GNUC__ > 4 +#define BR_GCC_5_0 1 +#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 +#define BR_GCC_4_9 1 +#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 8 +#define BR_GCC_4_8 1 +#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 7 +#define BR_GCC_4_7 1 +#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 6 +#define BR_GCC_4_6 1 +#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 5 +#define BR_GCC_4_5 1 +#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 4 +#define BR_GCC_4_4 1 +#endif + +#if BR_GCC_5_0 +#define BR_GCC_4_9 1 +#endif +#if BR_GCC_4_9 +#define BR_GCC_4_8 1 +#endif +#if BR_GCC_4_8 +#define BR_GCC_4_7 1 +#endif +#if BR_GCC_4_7 +#define BR_GCC_4_6 1 +#endif +#if BR_GCC_4_6 +#define BR_GCC_4_5 1 +#endif +#if BR_GCC_4_5 +#define BR_GCC_4_4 1 +#endif + +#endif +#endif + +/* + * Clang thresholds are on versions 3.7.0 and 3.8.0. + */ +#ifndef BR_CLANG +#if __clang__ +#define BR_CLANG 1 + +#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8) +#define BR_CLANG_3_8 1 +#elif __clang_major__ == 3 && __clang_minor__ >= 7 +#define BR_CLANG_3_7 1 +#endif + +#if BR_CLANG_3_8 +#define BR_CLANG_3_7 1 +#endif + +#endif +#endif + +/* + * MS Visual C thresholds are on Visual Studio 2005 to 2015. + */ +#ifndef BR_MSC +#if _MSC_VER && !defined(_XBOX) +#define BR_MSC 1 + +#if _MSC_VER >= 1900 +#define BR_MSC_2015 1 +#elif _MSC_VER >= 1800 +#define BR_MSC_2013 1 +#elif _MSC_VER >= 1700 +#define BR_MSC_2012 1 +#elif _MSC_VER >= 1600 +#define BR_MSC_2010 1 +#elif _MSC_VER >= 1500 +#define BR_MSC_2008 1 +#elif _MSC_VER >= 1400 +#define BR_MSC_2005 1 +#endif + +#if BR_MSC_2015 +#define BR_MSC_2013 1 +#endif +#if BR_MSC_2013 +#define BR_MSC_2012 1 +#endif +#if BR_MSC_2012 +#define BR_MSC_2010 1 +#endif +#if BR_MSC_2010 +#define BR_MSC_2008 1 +#endif +#if BR_MSC_2008 +#define BR_MSC_2005 1 +#endif + +#endif +#endif + +/* + * GCC 4.4+ and Clang 3.7+ allow tagging specific functions with a + * 'target' attribute that activates support for specific opcodes. + */ +#if BR_GCC_4_4 || BR_CLANG_3_7 +#define BR_TARGET(x) __attribute__((target(x))) +#else +#define BR_TARGET(x) +#endif + +/* + * AES-NI intrinsics are available on x86 (32-bit and 64-bit) with + * GCC 4.8+, Clang 3.7+ and MSC 2012+. + */ +#ifndef BR_AES_X86NI +#if (BR_i386 || BR_amd64) && (BR_GCC_4_8 || BR_CLANG_3_7 || BR_MSC_2012) +#define BR_AES_X86NI 1 +#endif +#endif + +/* + * SSE2 intrinsics are available on x86 (32-bit and 64-bit) with + * GCC 4.4+, Clang 3.7+ and MSC 2005+. + */ +#ifndef BR_SSE2 +#if (BR_i386 || BR_amd64) && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005) +#define BR_SSE2 1 +#endif +#endif + +/* + * RDRAND intrinsics are available on x86 (32-bit and 64-bit) with + * GCC 4.6+, Clang 3.7+ and MSC 2012+. + */ +#ifndef BR_RDRAND +#if (BR_i386 || BR_amd64) && (BR_GCC_4_6 || BR_CLANG_3_7 || BR_MSC_2012) +#define BR_RDRAND 1 +#endif +#endif + +/* + * Determine type of OS for random number generation. Macro names and + * values are documented on: + * https://sourceforge.net/p/predef/wiki/OperatingSystems/ + * + * Win32's CryptGenRandom() should be available on Windows systems. + * + * /dev/urandom should work on all Unix-like systems (including macOS X). + * + * getentropy() is present on Linux (Glibc 2.25+), FreeBSD (12.0+) and + * OpenBSD (5.6+). For OpenBSD, there does not seem to be easy to use + * macros to test the minimum version, so we just assume that it is + * recent enough (last version without getentropy() has gone out of + * support in May 2015). + * + * Ideally we should use getentropy() on macOS (10.12+) too, but I don't + * know how to test the exact OS version with preprocessor macros. + * + * TODO: enrich the list of detected system. + */ + +#ifndef BR_USE_URANDOM +#if defined _AIX \ + || defined __ANDROID__ \ + || defined __FreeBSD__ \ + || defined __NetBSD__ \ + || defined __OpenBSD__ \ + || defined __DragonFly__ \ + || defined __linux__ \ + || (defined __sun && (defined __SVR4 || defined __svr4__)) \ + || (defined __APPLE__ && defined __MACH__) +#define BR_USE_URANDOM 1 +#endif +#endif + +#ifndef BR_USE_GETENTROPY +#if (defined __linux__ \ + && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))) \ + || (defined __FreeBSD__ && __FreeBSD__ >= 12) \ + || defined __OpenBSD__ +#define BR_USE_GETENTROPY 1 +#endif +#endif + +#ifndef _XBOX +#ifndef BR_USE_WIN32_RAND +#if defined _WIN32 || defined _WIN64 +#define BR_USE_WIN32_RAND 1 +#endif +#endif +#endif + +#ifdef _XBOX +#define BR_USE_XBOX_RAND 1 +#endif + + +/* + * POWER8 crypto support. We rely on compiler macros for the + * architecture, since we do not have a reliable, simple way to detect + * the required support at runtime (we could try running an opcode, and + * trapping the exception or signal on illegal instruction, but this + * induces some non-trivial OS dependencies that we would prefer to + * avoid if possible). + */ +#ifndef BR_POWER8 +#if __GNUC__ && ((_ARCH_PWR8 || _ARCH_PPC) && __CRYPTO__) +#define BR_POWER8 1 +#endif +#endif + +/* + * Detect endinanness on POWER8. + */ +#if BR_POWER8 +#if defined BR_POWER8_LE +#undef BR_POWER8_BE +#if BR_POWER8_LE +#define BR_POWER8_BE 0 +#else +#define BR_POWER8_BE 1 +#endif +#elif defined BR_POWER8_BE +#undef BR_POWER8_LE +#if BR_POWER8_BE +#define BR_POWER8_LE 0 +#else +#define BR_POWER8_LE 1 +#endif +#else +#if __LITTLE_ENDIAN__ +#define BR_POWER8_LE 1 +#define BR_POWER8_BE 0 +#else +#define BR_POWER8_LE 0 +#define BR_POWER8_BE 1 +#endif +#endif +#endif + +/* + * Detect support for 128-bit integers. + */ +#if !defined BR_INT128 && !defined BR_UMUL128 +#ifdef __SIZEOF_INT128__ +#define BR_INT128 1 +#elif _M_X64 +#define BR_UMUL128 1 +#endif +#endif + +/* + * Detect support for unaligned accesses with known endianness. + * + * x86 (both 32-bit and 64-bit) is little-endian and allows unaligned + * accesses. + * + * POWER/PowerPC allows unaligned accesses when big-endian. POWER8 and + * later also allow unaligned accesses when little-endian. + */ +#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED + +#if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64 +#define BR_LE_UNALIGNED 1 +#elif BR_POWER8_BE +#define BR_BE_UNALIGNED 1 +#elif BR_POWER8_LE +#define BR_LE_UNALIGNED 1 +#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \ + && __BIG_ENDIAN__ +#define BR_BE_UNALIGNED 1 +#endif + +#endif + +/* + * Detect support for an OS-provided time source. + */ + +#ifndef BR_USE_UNIX_TIME +#if defined __unix__ || defined __linux__ \ + || defined _POSIX_SOURCE || defined _POSIX_C_SOURCE \ + || (defined __APPLE__ && defined __MACH__) +#define BR_USE_UNIX_TIME 1 +#endif +#endif + +#ifndef BR_USE_WIN32_TIME +#if defined _WIN32 || defined _WIN64 || defined _XBOX +#define BR_USE_WIN32_TIME 1 +#endif +#endif + +/* ==================================================================== */ +/* + * Encoding/decoding functions. + * + * 32-bit and 64-bit decoding, both little-endian and big-endian, is + * implemented with the inline functions below. + * + * When allowed by some compile-time options (autodetected or provided), + * optimised code is used, to perform direct memory access when the + * underlying architecture supports it, both for endianness and + * alignment. This, however, may trigger strict aliasing issues; the + * code below uses unions to perform (supposedly) safe type punning. + * Since the C aliasing rules are relatively complex and were amended, + * or at least re-explained with different phrasing, in all successive + * versions of the C standard, it is always a bit risky to bet that any + * specific version of a C compiler got it right, for some notion of + * "right". + */ + +typedef union { + uint16_t u; + unsigned char b[sizeof(uint16_t)]; +} br_union_u16; + +typedef union { + uint32_t u; + unsigned char b[sizeof(uint32_t)]; +} br_union_u32; + +typedef union { + uint64_t u; + unsigned char b[sizeof(uint64_t)]; +} br_union_u64; + +static __inline void +br_enc16le(void *dst, unsigned x) +{ +#if BR_LE_UNALIGNED + ((br_union_u16 *)dst)->u = x; +#else + unsigned char *buf; + + buf = dst; + buf[0] = (unsigned char)x; + buf[1] = (unsigned char)(x >> 8); +#endif +} + +static __inline void +br_enc16be(void *dst, unsigned x) +{ +#if BR_BE_UNALIGNED + ((br_union_u16 *)dst)->u = x; +#else + unsigned char *buf; + + buf = dst; + buf[0] = (unsigned char)(x >> 8); + buf[1] = (unsigned char)x; +#endif +} + +static __inline unsigned +br_dec16le(const void *src) +{ +#if BR_LE_UNALIGNED + return ((const br_union_u16 *)src)->u; +#else + const unsigned char *buf; + + buf = src; + return (unsigned)buf[0] | ((unsigned)buf[1] << 8); +#endif +} + +static __inline unsigned +br_dec16be(const void *src) +{ +#if BR_BE_UNALIGNED + return ((const br_union_u16 *)src)->u; +#else + const unsigned char *buf; + + buf = src; + return ((unsigned)buf[0] << 8) | (unsigned)buf[1]; +#endif +} + +static __inline void +br_enc32le(void *dst, uint32_t x) +{ +#if BR_LE_UNALIGNED + ((br_union_u32 *)dst)->u = x; +#else + unsigned char *buf; + + buf = dst; + buf[0] = (unsigned char)x; + buf[1] = (unsigned char)(x >> 8); + buf[2] = (unsigned char)(x >> 16); + buf[3] = (unsigned char)(x >> 24); +#endif +} + +static __inline void +br_enc32be(void *dst, uint32_t x) +{ +#if BR_BE_UNALIGNED + ((br_union_u32 *)dst)->u = x; +#else + unsigned char *buf; + + buf = dst; + buf[0] = (unsigned char)(x >> 24); + buf[1] = (unsigned char)(x >> 16); + buf[2] = (unsigned char)(x >> 8); + buf[3] = (unsigned char)x; +#endif +} + +static __inline uint32_t +br_dec32le(const void *src) +{ +#if BR_LE_UNALIGNED + return ((const br_union_u32 *)src)->u; +#else + const unsigned char *buf; + + buf = src; + return (uint32_t)buf[0] + | ((uint32_t)buf[1] << 8) + | ((uint32_t)buf[2] << 16) + | ((uint32_t)buf[3] << 24); +#endif +} + +static __inline uint32_t +br_dec32be(const void *src) +{ +#if BR_BE_UNALIGNED + return ((const br_union_u32 *)src)->u; +#else + const unsigned char *buf; + + buf = src; + return ((uint32_t)buf[0] << 24) + | ((uint32_t)buf[1] << 16) + | ((uint32_t)buf[2] << 8) + | (uint32_t)buf[3]; +#endif +} + +static __inline void +br_enc64le(void *dst, uint64_t x) +{ +#if BR_LE_UNALIGNED + ((br_union_u64 *)dst)->u = x; +#else + unsigned char *buf; + + buf = dst; + br_enc32le(buf, (uint32_t)x); + br_enc32le(buf + 4, (uint32_t)(x >> 32)); +#endif +} + +static __inline void +br_enc64be(void *dst, uint64_t x) +{ +#if BR_BE_UNALIGNED + ((br_union_u64 *)dst)->u = x; +#else + unsigned char *buf; + + buf = dst; + br_enc32be(buf, (uint32_t)(x >> 32)); + br_enc32be(buf + 4, (uint32_t)x); +#endif +} + +static __inline uint64_t +br_dec64le(const void *src) +{ +#if BR_LE_UNALIGNED + return ((const br_union_u64 *)src)->u; +#else + const unsigned char *buf; + + buf = src; + return (uint64_t)br_dec32le(buf) + | ((uint64_t)br_dec32le(buf + 4) << 32); +#endif +} + +static __inline uint64_t +br_dec64be(const void *src) +{ +#if BR_BE_UNALIGNED + return ((const br_union_u64 *)src)->u; +#else + const unsigned char *buf; + + buf = src; + return ((uint64_t)br_dec32be(buf) << 32) + | (uint64_t)br_dec32be(buf + 4); +#endif +} + +/* + * Range decoding and encoding (for several successive values). + */ +void br_range_dec16le(uint16_t *v, size_t num, const void *src); +void br_range_dec16be(uint16_t *v, size_t num, const void *src); +void br_range_enc16le(void *dst, const uint16_t *v, size_t num); +void br_range_enc16be(void *dst, const uint16_t *v, size_t num); + +void br_range_dec32le(uint32_t *v, size_t num, const void *src); +void br_range_dec32be(uint32_t *v, size_t num, const void *src); +void br_range_enc32le(void *dst, const uint32_t *v, size_t num); +void br_range_enc32be(void *dst, const uint32_t *v, size_t num); + +void br_range_dec64le(uint64_t *v, size_t num, const void *src); +void br_range_dec64be(uint64_t *v, size_t num, const void *src); +void br_range_enc64le(void *dst, const uint64_t *v, size_t num); +void br_range_enc64be(void *dst, const uint64_t *v, size_t num); + +/* + * Byte-swap a 32-bit integer. + */ +static __inline uint32_t +br_swap32(uint32_t x) +{ + x = ((x & (uint32_t)0x00FF00FF) << 8) + | ((x >> 8) & (uint32_t)0x00FF00FF); + return (x << 16) | (x >> 16); +} + +/* ==================================================================== */ +/* + * Support code for hash functions. + */ + +/* + * IV for MD5, SHA-1, SHA-224 and SHA-256. + */ +extern const uint32_t br_md5_IV[]; +extern const uint32_t br_sha1_IV[]; +extern const uint32_t br_sha224_IV[]; +extern const uint32_t br_sha256_IV[]; + +/* + * Round functions for MD5, SHA-1, SHA-224 and SHA-256 (SHA-224 and + * SHA-256 use the same round function). + */ +void br_md5_round(const unsigned char *buf, uint32_t *val); +void br_sha1_round(const unsigned char *buf, uint32_t *val); +void br_sha2small_round(const unsigned char *buf, uint32_t *val); + +/* + * The core function for the TLS PRF. It computes + * P_hash(secret, label + seed), and XORs the result into the dst buffer. + */ +void br_tls_phash(void *dst, size_t len, + const br_hash_class *dig, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/* + * Copy all configured hash implementations from a multihash context + * to another. + */ +static __inline void +br_multihash_copyimpl(br_multihash_context *dst, + const br_multihash_context *src) +{ + memcpy((void *)dst->impl, src->impl, sizeof src->impl); +} + +/* ==================================================================== */ +/* + * Constant-time primitives. These functions manipulate 32-bit values in + * order to provide constant-time comparisons and multiplexers. + * + * Boolean values (the "ctl" bits) MUST have value 0 or 1. + * + * Implementation notes: + * ===================== + * + * The uintN_t types are unsigned and with width exactly N bits; the C + * standard guarantees that computations are performed modulo 2^N, and + * there can be no overflow. Negation (unary '-') works on unsigned types + * as well. + * + * The intN_t types are guaranteed to have width exactly N bits, with no + * padding bit, and using two's complement representation. Casting + * intN_t to uintN_t really is conversion modulo 2^N. Beware that intN_t + * types, being signed, trigger implementation-defined behaviour on + * overflow (including raising some signal): with GCC, while modular + * arithmetics are usually applied, the optimizer may assume that + * overflows don't occur (unless the -fwrapv command-line option is + * added); Clang has the additional -ftrapv option to explicitly trap on + * integer overflow or underflow. + */ + +/* + * Negate a boolean. + */ +static __inline uint32_t +NOT(uint32_t ctl) +{ + return ctl ^ 1; +} + +/* + * Multiplexer: returns x if ctl == 1, y if ctl == 0. + */ +static __inline uint32_t +MUX(uint32_t ctl, uint32_t x, uint32_t y) +{ + return y ^ (-ctl & (x ^ y)); +} + +/* + * Equality check: returns 1 if x == y, 0 otherwise. + */ +static __inline uint32_t +EQ(uint32_t x, uint32_t y) +{ + uint32_t q; + + q = x ^ y; + return NOT((q | -q) >> 31); +} + +/* + * Inequality check: returns 1 if x != y, 0 otherwise. + */ +static __inline uint32_t +NEQ(uint32_t x, uint32_t y) +{ + uint32_t q; + + q = x ^ y; + return (q | -q) >> 31; +} + +/* + * Comparison: returns 1 if x > y, 0 otherwise. + */ +static __inline uint32_t +GT(uint32_t x, uint32_t y) +{ + /* + * If both x < 2^31 and x < 2^31, then y-x will have its high + * bit set if x > y, cleared otherwise. + * + * If either x >= 2^31 or y >= 2^31 (but not both), then the + * result is the high bit of x. + * + * If both x >= 2^31 and y >= 2^31, then we can virtually + * subtract 2^31 from both, and we are back to the first case. + * Since (y-2^31)-(x-2^31) = y-x, the subtraction is already + * fine. + */ + uint32_t z; + + z = y - x; + return (z ^ ((x ^ y) & (x ^ z))) >> 31; +} + +/* + * Other comparisons (greater-or-equal, lower-than, lower-or-equal). + */ +#define GE(x, y) NOT(GT(y, x)) +#define LT(x, y) GT(y, x) +#define LE(x, y) NOT(GT(x, y)) + +/* + * General comparison: returned value is -1, 0 or 1, depending on + * whether x is lower than, equal to, or greater than y. + */ +static __inline int32_t +CMP(uint32_t x, uint32_t y) +{ + return (int32_t)GT(x, y) | -(int32_t)GT(y, x); +} + +/* + * Returns 1 if x == 0, 0 otherwise. Take care that the operand is signed. + */ +static __inline uint32_t +EQ0(int32_t x) +{ + uint32_t q; + + q = (uint32_t)x; + return ~(q | -q) >> 31; +} + +/* + * Returns 1 if x > 0, 0 otherwise. Take care that the operand is signed. + */ +static __inline uint32_t +GT0(int32_t x) +{ + /* + * High bit of -x is 0 if x == 0, but 1 if x > 0. + */ + uint32_t q; + + q = (uint32_t)x; + return (~q & -q) >> 31; +} + +/* + * Returns 1 if x >= 0, 0 otherwise. Take care that the operand is signed. + */ +static __inline uint32_t +GE0(int32_t x) +{ + return ~(uint32_t)x >> 31; +} + +/* + * Returns 1 if x < 0, 0 otherwise. Take care that the operand is signed. + */ +static __inline uint32_t +LT0(int32_t x) +{ + return (uint32_t)x >> 31; +} + +/* + * Returns 1 if x <= 0, 0 otherwise. Take care that the operand is signed. + */ +static __inline uint32_t +LE0(int32_t x) +{ + uint32_t q; + + /* + * ~-x has its high bit set if and only if -x is nonnegative (as + * a signed int), i.e. x is in the -(2^31-1) to 0 range. We must + * do an OR with x itself to account for x = -2^31. + */ + q = (uint32_t)x; + return (q | ~-q) >> 31; +} + +/* + * Conditional copy: src[] is copied into dst[] if and only if ctl is 1. + * dst[] and src[] may overlap completely (but not partially). + */ +void br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len); + +#define CCOPY br_ccopy + +/* + * Compute the bit length of a 32-bit integer. Returned value is between 0 + * and 32 (inclusive). + */ +static __inline uint32_t +BIT_LENGTH(uint32_t x) +{ + uint32_t k, c; + + k = NEQ(x, 0); + c = GT(x, 0xFFFF); x = MUX(c, x >> 16, x); k += c << 4; + c = GT(x, 0x00FF); x = MUX(c, x >> 8, x); k += c << 3; + c = GT(x, 0x000F); x = MUX(c, x >> 4, x); k += c << 2; + c = GT(x, 0x0003); x = MUX(c, x >> 2, x); k += c << 1; + k += GT(x, 0x0001); + return k; +} + +/* + * Compute the minimum of x and y. + */ +static __inline uint32_t +MIN(uint32_t x, uint32_t y) +{ + return MUX(GT(x, y), y, x); +} + +/* + * Compute the maximum of x and y. + */ +static __inline uint32_t +MAX(uint32_t x, uint32_t y) +{ + return MUX(GT(x, y), x, y); +} + +/* + * Multiply two 32-bit integers, with a 64-bit result. This default + * implementation assumes that the basic multiplication operator + * yields constant-time code. + */ +#define MUL(x, y) ((uint64_t)(x) * (uint64_t)(y)) + +#if BR_CT_MUL31 + +/* + * Alternate implementation of MUL31, that will be constant-time on some + * (old) platforms where the default MUL31 is not. Unfortunately, it is + * also substantially slower, and yields larger code, on more modern + * platforms, which is why it is deactivated by default. + * + * MUL31_lo() must do some extra work because on some platforms, the + * _signed_ multiplication may return early if the top bits are 1. + * Simply truncating (casting) the output of MUL31() would not be + * sufficient, because the compiler may notice that we keep only the low + * word, and then replace automatically the unsigned multiplication with + * a signed multiplication opcode. + */ +#define MUL31(x, y) ((uint64_t)((x) | (uint32_t)0x80000000) \ + * (uint64_t)((y) | (uint32_t)0x80000000) \ + - ((uint64_t)(x) << 31) - ((uint64_t)(y) << 31) \ + - ((uint64_t)1 << 62)) +static __inline uint32_t +MUL31_lo(uint32_t x, uint32_t y) +{ + uint32_t xl, xh; + uint32_t yl, yh; + + xl = (x & 0xFFFF) | (uint32_t)0x80000000; + xh = (x >> 16) | (uint32_t)0x80000000; + yl = (y & 0xFFFF) | (uint32_t)0x80000000; + yh = (y >> 16) | (uint32_t)0x80000000; + return (xl * yl + ((xl * yh + xh * yl) << 16)) & (uint32_t)0x7FFFFFFF; +} + +#else + +/* + * Multiply two 31-bit integers, with a 62-bit result. This default + * implementation assumes that the basic multiplication operator + * yields constant-time code. + * The MUL31_lo() macro returns only the low 31 bits of the product. + */ +#define MUL31(x, y) ((uint64_t)(x) * (uint64_t)(y)) +#define MUL31_lo(x, y) (((uint32_t)(x) * (uint32_t)(y)) & (uint32_t)0x7FFFFFFF) + +#endif + +/* + * Multiply two words together; the sum of the lengths of the two + * operands must not exceed 31 (for instance, one operand may use 16 + * bits if the other fits on 15). If BR_CT_MUL15 is non-zero, then the + * macro will contain some extra operations that help in making the + * operation constant-time on some platforms, where the basic 32-bit + * multiplication is not constant-time. + */ +#if BR_CT_MUL15 +#define MUL15(x, y) (((uint32_t)(x) | (uint32_t)0x80000000) \ + * ((uint32_t)(y) | (uint32_t)0x80000000) \ + & (uint32_t)0x7FFFFFFF) +#else +#define MUL15(x, y) ((uint32_t)(x) * (uint32_t)(y)) +#endif + +/* + * Arithmetic right shift (sign bit is copied). What happens when + * right-shifting a negative value is _implementation-defined_, so it + * does not trigger undefined behaviour, but it is still up to each + * compiler to define (and document) what it does. Most/all compilers + * will do an arithmetic shift, the sign bit being used to fill the + * holes; this is a native operation on the underlying CPU, and it would + * make little sense for the compiler to do otherwise. GCC explicitly + * documents that it follows that convention. + * + * Still, if BR_NO_ARITH_SHIFT is defined (and non-zero), then an + * alternate version will be used, that does not rely on such + * implementation-defined behaviour. Unfortunately, it is also slower + * and yields bigger code, which is why it is deactivated by default. + */ +#if BR_NO_ARITH_SHIFT +#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ + | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) +#else +#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) +#endif + +/* + * Constant-time division. The dividend hi:lo is divided by the + * divisor d; the quotient is returned and the remainder is written + * in *r. If hi == d, then the quotient does not fit on 32 bits; + * returned value is thus truncated. If hi > d, returned values are + * indeterminate. + */ +uint32_t br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r); + +/* + * Wrapper for br_divrem(); the remainder is returned, and the quotient + * is discarded. + */ +static __inline uint32_t +br_rem(uint32_t hi, uint32_t lo, uint32_t d) +{ + uint32_t r; + + br_divrem(hi, lo, d, &r); + return r; +} + +/* + * Wrapper for br_divrem(); the quotient is returned, and the remainder + * is discarded. + */ +static __inline uint32_t +br_div(uint32_t hi, uint32_t lo, uint32_t d) +{ + uint32_t r; + + return br_divrem(hi, lo, d, &r); +} + +/* ==================================================================== */ + +/* + * Integers 'i32' + * -------------- + * + * The 'i32' functions implement computations on big integers using + * an internal representation as an array of 32-bit integers. For + * an array x[]: + * -- x[0] contains the "announced bit length" of the integer + * -- x[1], x[2]... contain the value in little-endian order (x[1] + * contains the least significant 32 bits) + * + * Multiplications rely on the elementary 32x32->64 multiplication. + * + * The announced bit length specifies the number of bits that are + * significant in the subsequent 32-bit words. Unused bits in the + * last (most significant) word are set to 0; subsequent words are + * uninitialized and need not exist at all. + * + * The execution time and memory access patterns of all computations + * depend on the announced bit length, but not on the actual word + * values. For modular integers, the announced bit length of any integer + * modulo n is equal to the actual bit length of n; thus, computations + * on modular integers are "constant-time" (only the modulus length may + * leak). + */ + +/* + * Compute the actual bit length of an integer. The argument x should + * point to the first (least significant) value word of the integer. + * The len 'xlen' contains the number of 32-bit words to access. + * + * CT: value or length of x does not leak. + */ +uint32_t br_i32_bit_length(uint32_t *x, size_t xlen); + +/* + * Decode an integer from its big-endian unsigned representation. The + * "true" bit length of the integer is computed, but all words of x[] + * corresponding to the full 'len' bytes of the source are set. + * + * CT: value or length of x does not leak. + */ +void br_i32_decode(uint32_t *x, const void *src, size_t len); + +/* + * Decode an integer from its big-endian unsigned representation. The + * integer MUST be lower than m[]; the announced bit length written in + * x[] will be equal to that of m[]. All 'len' bytes from the source are + * read. + * + * Returned value is 1 if the decode value fits within the modulus, 0 + * otherwise. In the latter case, the x[] buffer will be set to 0 (but + * still with the announced bit length of m[]). + * + * CT: value or length of x does not leak. Memory access pattern depends + * only of 'len' and the announced bit length of m. Whether x fits or + * not does not leak either. + */ +uint32_t br_i32_decode_mod(uint32_t *x, + const void *src, size_t len, const uint32_t *m); + +/* + * Reduce an integer (a[]) modulo another (m[]). The result is written + * in x[] and its announced bit length is set to be equal to that of m[]. + * + * x[] MUST be distinct from a[] and m[]. + * + * CT: only announced bit lengths leak, not values of x, a or m. + */ +void br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m); + +/* + * Decode an integer from its big-endian unsigned representation, and + * reduce it modulo the provided modulus m[]. The announced bit length + * of the result is set to be equal to that of the modulus. + * + * x[] MUST be distinct from m[]. + */ +void br_i32_decode_reduce(uint32_t *x, + const void *src, size_t len, const uint32_t *m); + +/* + * Encode an integer into its big-endian unsigned representation. The + * output length in bytes is provided (parameter 'len'); if the length + * is too short then the integer is appropriately truncated; if it is + * too long then the extra bytes are set to 0. + */ +void br_i32_encode(void *dst, size_t len, const uint32_t *x); + +/* + * Multiply x[] by 2^32 and then add integer z, modulo m[]. This + * function assumes that x[] and m[] have the same announced bit + * length, and the announced bit length of m[] matches its true + * bit length. + * + * x[] and m[] MUST be distinct arrays. + * + * CT: only the common announced bit length of x and m leaks, not + * the values of x, z or m. + */ +void br_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m); + +/* + * Extract one word from an integer. The offset is counted in bits. + * The word MUST entirely fit within the word elements corresponding + * to the announced bit length of a[]. + */ +static __inline uint32_t +br_i32_word(const uint32_t *a, uint32_t off) +{ + size_t u; + unsigned j; + + u = (size_t)(off >> 5) + 1; + j = (unsigned)off & 31; + if (j == 0) { + return a[u]; + } else { + return (a[u] >> j) | (a[u + 1] << (32 - j)); + } +} + +/* + * Test whether an integer is zero. + */ +uint32_t br_i32_iszero(const uint32_t *x); + +/* + * Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[] + * is unmodified, but the carry is still computed and returned. The + * arrays a[] and b[] MUST have the same announced bit length. + * + * a[] and b[] MAY be the same array, but partial overlap is not allowed. + */ +uint32_t br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl); + +/* + * Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0, + * then a[] is unmodified, but the carry is still computed and returned. + * The arrays a[] and b[] MUST have the same announced bit length. + * + * a[] and b[] MAY be the same array, but partial overlap is not allowed. + */ +uint32_t br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl); + +/* + * Compute d+a*b, result in d. The initial announced bit length of d[] + * MUST match that of a[]. The d[] array MUST be large enough to + * accommodate the full result, plus (possibly) an extra word. The + * resulting announced bit length of d[] will be the sum of the announced + * bit lengths of a[] and b[] (therefore, it may be larger than the actual + * bit length of the numerical result). + * + * a[] and b[] may be the same array. d[] must be disjoint from both a[] + * and b[]. + */ +void br_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b); + +/* + * Zeroize an integer. The announced bit length is set to the provided + * value, and the corresponding words are set to 0. + */ +static __inline void +br_i32_zero(uint32_t *x, uint32_t bit_len) +{ + *x ++ = bit_len; + memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); +} + +/* + * Compute -(1/x) mod 2^32. If x is even, then this function returns 0. + */ +uint32_t br_i32_ninv32(uint32_t x); + +/* + * Convert a modular integer to Montgomery representation. The integer x[] + * MUST be lower than m[], but with the same announced bit length. + */ +void br_i32_to_monty(uint32_t *x, const uint32_t *m); + +/* + * Convert a modular integer back from Montgomery representation. The + * integer x[] MUST be lower than m[], but with the same announced bit + * length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is + * the least significant value word of m[] (this works only if m[] is + * an odd integer). + */ +void br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i); + +/* + * Compute a modular Montgomery multiplication. d[] is filled with the + * value of x*y/R modulo m[] (where R is the Montgomery factor). The + * array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be + * numerically lower than m[]. x[] and y[] MAY be the same array. The + * "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least + * significant value word of m[] (this works only if m[] is an odd + * integer). + */ +void br_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y, + const uint32_t *m, uint32_t m0i); + +/* + * Compute a modular exponentiation. x[] MUST be an integer modulo m[] + * (same announced bit length, lower value). m[] MUST be odd. The + * exponent is in big-endian unsigned notation, over 'elen' bytes. The + * "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least + * significant value word of m[] (this works only if m[] is an odd + * integer). The t1[] and t2[] parameters must be temporary arrays, + * each large enough to accommodate an integer with the same size as m[]. + */ +void br_i32_modpow(uint32_t *x, const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2); + +/* ==================================================================== */ + +/* + * Integers 'i31' + * -------------- + * + * The 'i31' functions implement computations on big integers using + * an internal representation as an array of 32-bit integers. For + * an array x[]: + * -- x[0] encodes the array length and the "announced bit length" + * of the integer: namely, if the announced bit length is k, + * then x[0] = ((k / 31) << 5) + (k % 31). + * -- x[1], x[2]... contain the value in little-endian order, 31 + * bits per word (x[1] contains the least significant 31 bits). + * The upper bit of each word is 0. + * + * Multiplications rely on the elementary 32x32->64 multiplication. + * + * The announced bit length specifies the number of bits that are + * significant in the subsequent 32-bit words. Unused bits in the + * last (most significant) word are set to 0; subsequent words are + * uninitialized and need not exist at all. + * + * The execution time and memory access patterns of all computations + * depend on the announced bit length, but not on the actual word + * values. For modular integers, the announced bit length of any integer + * modulo n is equal to the actual bit length of n; thus, computations + * on modular integers are "constant-time" (only the modulus length may + * leak). + */ + +/* + * Test whether an integer is zero. + */ +uint32_t br_i31_iszero(const uint32_t *x); + +/* + * Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[] + * is unmodified, but the carry is still computed and returned. The + * arrays a[] and b[] MUST have the same announced bit length. + * + * a[] and b[] MAY be the same array, but partial overlap is not allowed. + */ +uint32_t br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl); + +/* + * Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0, + * then a[] is unmodified, but the carry is still computed and returned. + * The arrays a[] and b[] MUST have the same announced bit length. + * + * a[] and b[] MAY be the same array, but partial overlap is not allowed. + */ +uint32_t br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl); + +/* + * Compute the ENCODED actual bit length of an integer. The argument x + * should point to the first (least significant) value word of the + * integer. The len 'xlen' contains the number of 32-bit words to + * access. The upper bit of each value word MUST be 0. + * Returned value is ((k / 31) << 5) + (k % 31) if the bit length is k. + * + * CT: value or length of x does not leak. + */ +uint32_t br_i31_bit_length(uint32_t *x, size_t xlen); + +/* + * Decode an integer from its big-endian unsigned representation. The + * "true" bit length of the integer is computed and set in the encoded + * announced bit length (x[0]), but all words of x[] corresponding to + * the full 'len' bytes of the source are set. + * + * CT: value or length of x does not leak. + */ +void br_i31_decode(uint32_t *x, const void *src, size_t len); + +/* + * Decode an integer from its big-endian unsigned representation. The + * integer MUST be lower than m[]; the (encoded) announced bit length + * written in x[] will be equal to that of m[]. All 'len' bytes from the + * source are read. + * + * Returned value is 1 if the decode value fits within the modulus, 0 + * otherwise. In the latter case, the x[] buffer will be set to 0 (but + * still with the announced bit length of m[]). + * + * CT: value or length of x does not leak. Memory access pattern depends + * only of 'len' and the announced bit length of m. Whether x fits or + * not does not leak either. + */ +uint32_t br_i31_decode_mod(uint32_t *x, + const void *src, size_t len, const uint32_t *m); + +/* + * Zeroize an integer. The announced bit length is set to the provided + * value, and the corresponding words are set to 0. The ENCODED bit length + * is expected here. + */ +static __inline void +br_i31_zero(uint32_t *x, uint32_t bit_len) +{ + *x ++ = bit_len; + memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); +} + +/* + * Right-shift an integer. The shift amount must be lower than 31 + * bits. + */ +void br_i31_rshift(uint32_t *x, int count); + +/* + * Reduce an integer (a[]) modulo another (m[]). The result is written + * in x[] and its announced bit length is set to be equal to that of m[]. + * + * x[] MUST be distinct from a[] and m[]. + * + * CT: only announced bit lengths leak, not values of x, a or m. + */ +void br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m); + +/* + * Decode an integer from its big-endian unsigned representation, and + * reduce it modulo the provided modulus m[]. The announced bit length + * of the result is set to be equal to that of the modulus. + * + * x[] MUST be distinct from m[]. + */ +void br_i31_decode_reduce(uint32_t *x, + const void *src, size_t len, const uint32_t *m); + +/* + * Multiply x[] by 2^31 and then add integer z, modulo m[]. This + * function assumes that x[] and m[] have the same announced bit + * length, the announced bit length of m[] matches its true + * bit length. + * + * x[] and m[] MUST be distinct arrays. z MUST fit in 31 bits (upper + * bit set to 0). + * + * CT: only the common announced bit length of x and m leaks, not + * the values of x, z or m. + */ +void br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m); + +/* + * Encode an integer into its big-endian unsigned representation. The + * output length in bytes is provided (parameter 'len'); if the length + * is too short then the integer is appropriately truncated; if it is + * too long then the extra bytes are set to 0. + */ +void br_i31_encode(void *dst, size_t len, const uint32_t *x); + +/* + * Compute -(1/x) mod 2^31. If x is even, then this function returns 0. + */ +uint32_t br_i31_ninv31(uint32_t x); + +/* + * Compute a modular Montgomery multiplication. d[] is filled with the + * value of x*y/R modulo m[] (where R is the Montgomery factor). The + * array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be + * numerically lower than m[]. x[] and y[] MAY be the same array. The + * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least + * significant value word of m[] (this works only if m[] is an odd + * integer). + */ +void br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y, + const uint32_t *m, uint32_t m0i); + +/* + * Convert a modular integer to Montgomery representation. The integer x[] + * MUST be lower than m[], but with the same announced bit length. + */ +void br_i31_to_monty(uint32_t *x, const uint32_t *m); + +/* + * Convert a modular integer back from Montgomery representation. The + * integer x[] MUST be lower than m[], but with the same announced bit + * length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is + * the least significant value word of m[] (this works only if m[] is + * an odd integer). + */ +void br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i); + +/* + * Compute a modular exponentiation. x[] MUST be an integer modulo m[] + * (same announced bit length, lower value). m[] MUST be odd. The + * exponent is in big-endian unsigned notation, over 'elen' bytes. The + * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least + * significant value word of m[] (this works only if m[] is an odd + * integer). The t1[] and t2[] parameters must be temporary arrays, + * each large enough to accommodate an integer with the same size as m[]. + */ +void br_i31_modpow(uint32_t *x, const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2); + +/* + * Compute a modular exponentiation. x[] MUST be an integer modulo m[] + * (same announced bit length, lower value). m[] MUST be odd. The + * exponent is in big-endian unsigned notation, over 'elen' bytes. The + * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least + * significant value word of m[] (this works only if m[] is an odd + * integer). The tmp[] array is used for temporaries, and has size + * 'twlen' words; it must be large enough to accommodate at least two + * temporary values with the same size as m[] (including the leading + * "bit length" word). If there is room for more temporaries, then this + * function may use the extra room for window-based optimisation, + * resulting in faster computations. + * + * Returned value is 1 on success, 0 on error. An error is reported if + * the provided tmp[] array is too short. + */ +uint32_t br_i31_modpow_opt(uint32_t *x, const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen); + +/* + * Compute d+a*b, result in d. The initial announced bit length of d[] + * MUST match that of a[]. The d[] array MUST be large enough to + * accommodate the full result, plus (possibly) an extra word. The + * resulting announced bit length of d[] will be the sum of the announced + * bit lengths of a[] and b[] (therefore, it may be larger than the actual + * bit length of the numerical result). + * + * a[] and b[] may be the same array. d[] must be disjoint from both a[] + * and b[]. + */ +void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b); + +/* + * Compute x/y mod m, result in x. Values x and y must be between 0 and + * m-1, and have the same announced bit length as m. Modulus m must be + * odd. The "m0i" parameter is equal to -1/m mod 2^31. The array 't' + * must point to a temporary area that can hold at least three integers + * of the size of m. + * + * m may not overlap x and y. x and y may overlap each other (this can + * be useful to test whether a value is invertible modulo m). t must be + * disjoint from all other arrays. + * + * Returned value is 1 on success, 0 otherwise. Success is attained if + * y is invertible modulo m. + */ +uint32_t br_i31_moddiv(uint32_t *x, const uint32_t *y, + const uint32_t *m, uint32_t m0i, uint32_t *t); + +/* ==================================================================== */ + +/* + * FIXME: document "i15" functions. + */ + +static __inline void +br_i15_zero(uint16_t *x, uint16_t bit_len) +{ + *x ++ = bit_len; + memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x); +} + +uint32_t br_i15_iszero(const uint16_t *x); + +uint16_t br_i15_ninv15(uint16_t x); + +uint32_t br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl); + +uint32_t br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl); + +void br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m); + +void br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y, + const uint16_t *m, uint16_t m0i); + +void br_i15_to_monty(uint16_t *x, const uint16_t *m); + +void br_i15_modpow(uint16_t *x, const unsigned char *e, size_t elen, + const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2); + +uint32_t br_i15_modpow_opt(uint16_t *x, const unsigned char *e, size_t elen, + const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen); + +void br_i15_encode(void *dst, size_t len, const uint16_t *x); + +uint32_t br_i15_decode_mod(uint16_t *x, + const void *src, size_t len, const uint16_t *m); + +void br_i15_rshift(uint16_t *x, int count); + +uint32_t br_i15_bit_length(uint16_t *x, size_t xlen); + +void br_i15_decode(uint16_t *x, const void *src, size_t len); + +void br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i); + +void br_i15_decode_reduce(uint16_t *x, + const void *src, size_t len, const uint16_t *m); + +void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m); + +void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b); + +uint32_t br_i15_moddiv(uint16_t *x, const uint16_t *y, + const uint16_t *m, uint16_t m0i, uint16_t *t); + +/* + * Variant of br_i31_modpow_opt() that internally uses 64x64->128 + * multiplications. It expects the same parameters as br_i31_modpow_opt(), + * except that the temporaries should be 64-bit integers, not 32-bit + * integers. + */ +uint32_t br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, + const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen); + +/* + * Type for a function with the same API as br_i31_modpow_opt() (some + * implementations of this type may have stricter alignment requirements + * on the temporaries). + */ +typedef uint32_t (*br_i31_modpow_opt_type)(uint32_t *x, + const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen); + +/* + * Wrapper for br_i62_modpow_opt() that uses the same type as + * br_i31_modpow_opt(); however, it requires its 'tmp' argument to the + * 64-bit aligned. + */ +uint32_t br_i62_modpow_opt_as_i31(uint32_t *x, + const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen); + +/* ==================================================================== */ + +static __inline size_t +br_digest_size(const br_hash_class *digest_class) +{ + return (size_t)(digest_class->desc >> BR_HASHDESC_OUT_OFF) + & BR_HASHDESC_OUT_MASK; +} + +/* + * Get the output size (in bytes) of a hash function. + */ +size_t br_digest_size_by_ID(int digest_id); + +/* + * Get the OID (encoded OBJECT IDENTIFIER value, without tag and length) + * for a hash function. If digest_id is not a supported digest identifier + * (in particular if it is equal to 0, i.e. br_md5sha1_ID), then NULL is + * returned and *len is set to 0. + */ +const unsigned char *br_digest_OID(int digest_id, size_t *len); + +/* ==================================================================== */ +/* + * DES support functions. + */ + +/* + * Apply DES Initial Permutation. + */ +void br_des_do_IP(uint32_t *xl, uint32_t *xr); + +/* + * Apply DES Final Permutation (inverse of IP). + */ +void br_des_do_invIP(uint32_t *xl, uint32_t *xr); + +/* + * Key schedule unit: for a DES key (8 bytes), compute 16 subkeys. Each + * subkey is two 28-bit words represented as two 32-bit words; the PC-2 + * bit extration is NOT applied. + */ +void br_des_keysched_unit(uint32_t *skey, const void *key); + +/* + * Reversal of 16 DES sub-keys (for decryption). + */ +void br_des_rev_skey(uint32_t *skey); + +/* + * DES/3DES key schedule for 'des_tab' (encryption direction). Returned + * value is the number of rounds. + */ +unsigned br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len); + +/* + * DES/3DES key schedule for 'des_ct' (encryption direction). Returned + * value is the number of rounds. + */ +unsigned br_des_ct_keysched(uint32_t *skey, const void *key, size_t key_len); + +/* + * DES/3DES subkey decompression (from the compressed bitsliced subkeys). + */ +void br_des_ct_skey_expand(uint32_t *sk_exp, + unsigned num_rounds, const uint32_t *skey); + +/* + * DES/3DES block encryption/decryption ('des_tab'). + */ +void br_des_tab_process_block(unsigned num_rounds, + const uint32_t *skey, void *block); + +/* + * DES/3DES block encryption/decryption ('des_ct'). + */ +void br_des_ct_process_block(unsigned num_rounds, + const uint32_t *skey, void *block); + +/* ==================================================================== */ +/* + * AES support functions. + */ + +/* + * The AES S-box (256-byte table). + */ +extern const unsigned char br_aes_S[]; + +/* + * AES key schedule. skey[] is filled with n+1 128-bit subkeys, where n + * is the number of rounds (10 to 14, depending on key size). The number + * of rounds is returned. If the key size is invalid (not 16, 24 or 32), + * then 0 is returned. + * + * This implementation uses a 256-byte table and is NOT constant-time. + */ +unsigned br_aes_keysched(uint32_t *skey, const void *key, size_t key_len); + +/* + * AES key schedule for decryption ('aes_big' implementation). + */ +unsigned br_aes_big_keysched_inv(uint32_t *skey, + const void *key, size_t key_len); + +/* + * AES block encryption with the 'aes_big' implementation (fast, but + * not constant-time). This function encrypts a single block "in place". + */ +void br_aes_big_encrypt(unsigned num_rounds, const uint32_t *skey, void *data); + +/* + * AES block decryption with the 'aes_big' implementation (fast, but + * not constant-time). This function decrypts a single block "in place". + */ +void br_aes_big_decrypt(unsigned num_rounds, const uint32_t *skey, void *data); + +/* + * AES block encryption with the 'aes_small' implementation (small, but + * slow and not constant-time). This function encrypts a single block + * "in place". + */ +void br_aes_small_encrypt(unsigned num_rounds, + const uint32_t *skey, void *data); + +/* + * AES block decryption with the 'aes_small' implementation (small, but + * slow and not constant-time). This function decrypts a single block + * "in place". + */ +void br_aes_small_decrypt(unsigned num_rounds, + const uint32_t *skey, void *data); + +/* + * The constant-time implementation is "bitsliced": the 128-bit state is + * split over eight 32-bit words q* in the following way: + * + * -- Input block consists in 16 bytes: + * a00 a10 a20 a30 a01 a11 a21 a31 a02 a12 a22 a32 a03 a13 a23 a33 + * In the terminology of FIPS 197, this is a 4x4 matrix which is read + * column by column. + * + * -- Each byte is split into eight bits which are distributed over the + * eight words, at the same rank. Thus, for a byte x at rank k, bit 0 + * (least significant) of x will be at rank k in q0 (if that bit is b, + * then it contributes "b << k" to the value of q0), bit 1 of x will be + * at rank k in q1, and so on. + * + * -- Ranks given to bits are in "row order" and are either all even, or + * all odd. Two independent AES states are thus interleaved, one using + * the even ranks, the other the odd ranks. Row order means: + * a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 a30 a31 a32 a33 + * + * Converting input bytes from two AES blocks to bitslice representation + * is done in the following way: + * -- Decode first block into the four words q0 q2 q4 q6, in that order, + * using little-endian convention. + * -- Decode second block into the four words q1 q3 q5 q7, in that order, + * using little-endian convention. + * -- Call br_aes_ct_ortho(). + * + * Converting back to bytes is done by using the reverse operations. Note + * that br_aes_ct_ortho() is its own inverse. + */ + +/* + * Perform bytewise orthogonalization of eight 32-bit words. Bytes + * of q0..q7 are spread over all words: for a byte x that occurs + * at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit + * of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j. + * + * This operation is an involution. + */ +void br_aes_ct_ortho(uint32_t *q); + +/* + * The AES S-box, as a bitsliced constant-time version. The input array + * consists in eight 32-bit words; 32 S-box instances are computed in + * parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant) + * are spread over the words 0 to 7, at the same rank. + */ +void br_aes_ct_bitslice_Sbox(uint32_t *q); + +/* + * Like br_aes_bitslice_Sbox(), but for the inverse S-box. + */ +void br_aes_ct_bitslice_invSbox(uint32_t *q); + +/* + * Compute AES encryption on bitsliced data. Since input is stored on + * eight 32-bit words, two block encryptions are actually performed + * in parallel. + */ +void br_aes_ct_bitslice_encrypt(unsigned num_rounds, + const uint32_t *skey, uint32_t *q); + +/* + * Compute AES decryption on bitsliced data. Since input is stored on + * eight 32-bit words, two block decryptions are actually performed + * in parallel. + */ +void br_aes_ct_bitslice_decrypt(unsigned num_rounds, + const uint32_t *skey, uint32_t *q); + +/* + * AES key schedule, constant-time version. skey[] is filled with n+1 + * 128-bit subkeys, where n is the number of rounds (10 to 14, depending + * on key size). The number of rounds is returned. If the key size is + * invalid (not 16, 24 or 32), then 0 is returned. + */ +unsigned br_aes_ct_keysched(uint32_t *comp_skey, + const void *key, size_t key_len); + +/* + * Expand AES subkeys as produced by br_aes_ct_keysched(), into + * a larger array suitable for br_aes_ct_bitslice_encrypt() and + * br_aes_ct_bitslice_decrypt(). + */ +void br_aes_ct_skey_expand(uint32_t *skey, + unsigned num_rounds, const uint32_t *comp_skey); + +/* + * For the ct64 implementation, the same bitslicing technique is used, + * but four instances are interleaved. First instance uses bits 0, 4, + * 8, 12,... of each word; second instance uses bits 1, 5, 9, 13,... + * and so on. + */ + +/* + * Perform bytewise orthogonalization of eight 64-bit words. Bytes + * of q0..q7 are spread over all words: for a byte x that occurs + * at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit + * of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j. + * + * This operation is an involution. + */ +void br_aes_ct64_ortho(uint64_t *q); + +/* + * Interleave bytes for an AES input block. If input bytes are + * denoted 0123456789ABCDEF, and have been decoded with little-endian + * convention (w[0] contains 0123, with '3' being most significant; + * w[1] contains 4567, and so on), then output word q0 will be + * set to 08192A3B (again little-endian convention) and q1 will + * be set to 4C5D6E7F. + */ +void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w); + +/* + * Perform the opposite of br_aes_ct64_interleave_in(). + */ +void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1); + +/* + * The AES S-box, as a bitsliced constant-time version. The input array + * consists in eight 64-bit words; 64 S-box instances are computed in + * parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant) + * are spread over the words 0 to 7, at the same rank. + */ +void br_aes_ct64_bitslice_Sbox(uint64_t *q); + +/* + * Like br_aes_bitslice_Sbox(), but for the inverse S-box. + */ +void br_aes_ct64_bitslice_invSbox(uint64_t *q); + +/* + * Compute AES encryption on bitsliced data. Since input is stored on + * eight 64-bit words, four block encryptions are actually performed + * in parallel. + */ +void br_aes_ct64_bitslice_encrypt(unsigned num_rounds, + const uint64_t *skey, uint64_t *q); + +/* + * Compute AES decryption on bitsliced data. Since input is stored on + * eight 64-bit words, four block decryptions are actually performed + * in parallel. + */ +void br_aes_ct64_bitslice_decrypt(unsigned num_rounds, + const uint64_t *skey, uint64_t *q); + +/* + * AES key schedule, constant-time version. skey[] is filled with n+1 + * 128-bit subkeys, where n is the number of rounds (10 to 14, depending + * on key size). The number of rounds is returned. If the key size is + * invalid (not 16, 24 or 32), then 0 is returned. + */ +unsigned br_aes_ct64_keysched(uint64_t *comp_skey, + const void *key, size_t key_len); + +/* + * Expand AES subkeys as produced by br_aes_ct64_keysched(), into + * a larger array suitable for br_aes_ct64_bitslice_encrypt() and + * br_aes_ct64_bitslice_decrypt(). + */ +void br_aes_ct64_skey_expand(uint64_t *skey, + unsigned num_rounds, const uint64_t *comp_skey); + +/* + * Test support for AES-NI opcodes. + */ +int br_aes_x86ni_supported(void); + +/* + * AES key schedule, using x86 AES-NI instructions. This yields the + * subkeys in the encryption direction. Number of rounds is returned. + * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned. + */ +unsigned br_aes_x86ni_keysched_enc(unsigned char *skni, + const void *key, size_t len); + +/* + * AES key schedule, using x86 AES-NI instructions. This yields the + * subkeys in the decryption direction. Number of rounds is returned. + * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned. + */ +unsigned br_aes_x86ni_keysched_dec(unsigned char *skni, + const void *key, size_t len); + +/* + * Test support for AES POWER8 opcodes. + */ +int br_aes_pwr8_supported(void); + +/* + * AES key schedule, using POWER8 instructions. This yields the + * subkeys in the encryption direction. Number of rounds is returned. + * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned. + */ +unsigned br_aes_pwr8_keysched(unsigned char *skni, + const void *key, size_t len); + +/* ==================================================================== */ +/* + * RSA. + */ + +/* + * Apply proper PKCS#1 v1.5 padding (for signatures). 'hash_oid' is + * the encoded hash function OID, or NULL. + */ +uint32_t br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + uint32_t n_bitlen, unsigned char *x); + +/* + * Check PKCS#1 v1.5 padding (for signatures). 'hash_oid' is the encoded + * hash function OID, or NULL. The provided 'sig' value is _after_ the + * modular exponentiation, i.e. it should be the padded hash. On + * success, the hashed message is extracted. + */ +uint32_t br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, + const unsigned char *hash_oid, size_t hash_len, + unsigned char *hash_out); + +/* + * Apply proper PSS padding. The 'x' buffer is output only: it + * receives the value that is to be exponentiated. + */ +uint32_t br_rsa_pss_sig_pad(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash, size_t salt_len, + uint32_t n_bitlen, unsigned char *x); + +/* + * Check PSS padding. The provided value is the one _after_ + * the modular exponentiation; it is modified by this function. + * This function infers the signature length from the public key + * size, i.e. it assumes that this has already been verified (as + * part of the exponentiation). + */ +uint32_t br_rsa_pss_sig_unpad( + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash, size_t salt_len, + const br_rsa_public_key *pk, unsigned char *x); + +/* + * Apply OAEP padding. Returned value is the actual padded string length, + * or zero on error. + */ +size_t br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, const br_rsa_public_key *pk, + void *dst, size_t dst_nax_len, const void *src, size_t src_len); + +/* + * Unravel and check OAEP padding. If the padding is correct, then 1 is + * returned, '*len' is adjusted to the length of the message, and the + * data is moved to the start of the 'data' buffer. If the padding is + * incorrect, then 0 is returned and '*len' is untouched. Either way, + * the complete buffer contents are altered. + */ +uint32_t br_rsa_oaep_unpad(const br_hash_class *dig, + const void *label, size_t label_len, void *data, size_t *len); + +/* + * Compute MGF1 for a given seed, and XOR the output into the provided + * buffer. + */ +void br_mgf1_xor(void *data, size_t len, + const br_hash_class *dig, const void *seed, size_t seed_len); + +/* + * Inner function for RSA key generation; used by the "i31" and "i62" + * implementations. + */ +uint32_t br_rsa_i31_keygen_inner(const br_prng_class **rng, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31); + +/* ==================================================================== */ +/* + * Elliptic curves. + */ + +/* + * Type for generic EC parameters: curve order (unsigned big-endian + * encoding) and encoded conventional generator. + */ +typedef struct { + int curve; + const unsigned char *order; + size_t order_len; + const unsigned char *generator; + size_t generator_len; +} br_ec_curve_def; + +extern const br_ec_curve_def br_secp256r1; +extern const br_ec_curve_def br_secp384r1; +extern const br_ec_curve_def br_secp521r1; + +/* + * For Curve25519, the advertised "order" really is 2^255-1, since the + * point multipliction function really works over arbitrary 255-bit + * scalars. This value is only meant as a hint for ECDH key generation; + * only ECDSA uses the exact curve order, and ECDSA is not used with + * that specific curve. + */ +extern const br_ec_curve_def br_curve25519; + +/* + * Decode some bytes as an i31 integer, with truncation (corresponding + * to the 'bits2int' operation in RFC 6979). The target ENCODED bit + * length is provided as last parameter. The resulting value will have + * this declared bit length, and consists the big-endian unsigned decoding + * of exactly that many bits in the source (capped at the source length). + */ +void br_ecdsa_i31_bits2int(uint32_t *x, + const void *src, size_t len, uint32_t ebitlen); + +/* + * Decode some bytes as an i15 integer, with truncation (corresponding + * to the 'bits2int' operation in RFC 6979). The target ENCODED bit + * length is provided as last parameter. The resulting value will have + * this declared bit length, and consists the big-endian unsigned decoding + * of exactly that many bits in the source (capped at the source length). + */ +void br_ecdsa_i15_bits2int(uint16_t *x, + const void *src, size_t len, uint32_t ebitlen); + +/* ==================================================================== */ +/* + * ASN.1 support functions. + */ + +/* + * A br_asn1_uint structure contains encoding information about an + * INTEGER nonnegative value: pointer to the integer contents (unsigned + * big-endian representation), length of the integer contents, + * and length of the encoded value. The data shall have minimal length: + * - If the integer value is zero, then 'len' must be zero. + * - If the integer value is not zero, then data[0] must be non-zero. + * + * Under these conditions, 'asn1len' is necessarily equal to either len + * or len+1. + */ +typedef struct { + const unsigned char *data; + size_t len; + size_t asn1len; +} br_asn1_uint; + +/* + * Given an encoded integer (unsigned big-endian, with possible leading + * bytes of value 0), returned the "prepared INTEGER" structure. + */ +br_asn1_uint br_asn1_uint_prepare(const void *xdata, size_t xlen); + +/* + * Encode an ASN.1 length. The length of the encoded length is returned. + * If 'dest' is NULL, then no encoding is performed, but the length of + * the encoded length is still computed and returned. + */ +size_t br_asn1_encode_length(void *dest, size_t len); + +/* + * Convenient macro for computing lengths of lengths. + */ +#define len_of_len(len) br_asn1_encode_length(NULL, len) + +/* + * Encode a (prepared) ASN.1 INTEGER. The encoded length is returned. + * If 'dest' is NULL, then no encoding is performed, but the length of + * the encoded integer is still computed and returned. + */ +size_t br_asn1_encode_uint(void *dest, br_asn1_uint pp); + +/* + * Get the OID that identifies an elliptic curve. Returned value is + * the DER-encoded OID, with the length (always one byte) but without + * the tag. Thus, the first byte of the returned buffer contains the + * number of subsequent bytes in the value. If the curve is not + * recognised, NULL is returned. + */ +const unsigned char *br_get_curve_OID(int curve); + +/* + * Inner function for EC private key encoding. This is equivalent to + * the API function br_encode_ec_raw_der(), except for an extra + * parameter: if 'include_curve_oid' is zero, then the curve OID is + * _not_ included in the output blob (this is for PKCS#8 support). + */ +size_t br_encode_ec_raw_der_inner(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk, + int include_curve_oid); + +/* ==================================================================== */ +/* + * SSL/TLS support functions. + */ + +/* + * Record types. + */ +#define BR_SSL_CHANGE_CIPHER_SPEC 20 +#define BR_SSL_ALERT 21 +#define BR_SSL_HANDSHAKE 22 +#define BR_SSL_APPLICATION_DATA 23 + +/* + * Handshake message types. + */ +#define BR_SSL_HELLO_REQUEST 0 +#define BR_SSL_CLIENT_HELLO 1 +#define BR_SSL_SERVER_HELLO 2 +#define BR_SSL_CERTIFICATE 11 +#define BR_SSL_SERVER_KEY_EXCHANGE 12 +#define BR_SSL_CERTIFICATE_REQUEST 13 +#define BR_SSL_SERVER_HELLO_DONE 14 +#define BR_SSL_CERTIFICATE_VERIFY 15 +#define BR_SSL_CLIENT_KEY_EXCHANGE 16 +#define BR_SSL_FINISHED 20 + +/* + * Alert levels. + */ +#define BR_LEVEL_WARNING 1 +#define BR_LEVEL_FATAL 2 + +/* + * Low-level I/O state. + */ +#define BR_IO_FAILED 0 +#define BR_IO_IN 1 +#define BR_IO_OUT 2 +#define BR_IO_INOUT 3 + +/* + * Mark a SSL engine as failed. The provided error code is recorded if + * the engine was not already marked as failed. If 'err' is 0, then the + * engine is marked as closed (without error). + */ +void br_ssl_engine_fail(br_ssl_engine_context *cc, int err); + +/* + * Test whether the engine is closed (normally or as a failure). + */ +static __inline int +br_ssl_engine_closed(const br_ssl_engine_context *cc) +{ + return cc->iomode == BR_IO_FAILED; +} + +/* + * Configure a new maximum fragment length. If possible, the maximum + * length for outgoing records is immediately adjusted (if there are + * not already too many buffered bytes for that). + */ +void br_ssl_engine_new_max_frag_len( + br_ssl_engine_context *rc, unsigned max_frag_len); + +/* + * Test whether the current incoming record has been fully received + * or not. This functions returns 0 only if a complete record header + * has been received, but some of the (possibly encrypted) payload + * has not yet been obtained. + */ +int br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc); + +/* + * Flush the current record (if not empty). This is meant to be called + * from the handshake processor only. + */ +void br_ssl_engine_flush_record(br_ssl_engine_context *cc); + +/* + * Test whether there is some accumulated payload to send. + */ +static __inline int +br_ssl_engine_has_pld_to_send(const br_ssl_engine_context *rc) +{ + return rc->oxa != rc->oxb && rc->oxa != rc->oxc; +} + +/* + * Initialize RNG in engine. Returned value is 1 on success, 0 on error. + * This function will try to use the OS-provided RNG, if available. If + * there is no OS-provided RNG, or if it failed, and no entropy was + * injected by the caller, then a failure will be reported. On error, + * the context error code is set. + */ +int br_ssl_engine_init_rand(br_ssl_engine_context *cc); + +/* + * Reset the handshake-related parts of the engine. + */ +void br_ssl_engine_hs_reset(br_ssl_engine_context *cc, + void (*hsinit)(void *), void (*hsrun)(void *)); + +/* + * Get the PRF to use for this context, for the provided PRF hash + * function ID. + */ +br_tls_prf_impl br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id); + +/* + * Consume the provided pre-master secret and compute the corresponding + * master secret. The 'prf_id' is the ID of the hash function to use + * with the TLS 1.2 PRF (ignored if the version is TLS 1.0 or 1.1). + */ +void br_ssl_engine_compute_master(br_ssl_engine_context *cc, + int prf_id, const void *pms, size_t len); + +/* + * Switch to CBC decryption for incoming records. + * cc the engine context + * is_client non-zero for a client, zero for a server + * prf_id id of hash function for PRF (ignored if not TLS 1.2+) + * mac_id id of hash function for HMAC + * bc_impl block cipher implementation (CBC decryption) + * cipher_key_len block cipher key length (in bytes) + */ +void br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc, + int is_client, int prf_id, int mac_id, + const br_block_cbcdec_class *bc_impl, size_t cipher_key_len); + +/* + * Switch to CBC encryption for outgoing records. + * cc the engine context + * is_client non-zero for a client, zero for a server + * prf_id id of hash function for PRF (ignored if not TLS 1.2+) + * mac_id id of hash function for HMAC + * bc_impl block cipher implementation (CBC encryption) + * cipher_key_len block cipher key length (in bytes) + */ +void br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc, + int is_client, int prf_id, int mac_id, + const br_block_cbcenc_class *bc_impl, size_t cipher_key_len); + +/* + * Switch to GCM decryption for incoming records. + * cc the engine context + * is_client non-zero for a client, zero for a server + * prf_id id of hash function for PRF + * bc_impl block cipher implementation (CTR) + * cipher_key_len block cipher key length (in bytes) + */ +void br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc, + int is_client, int prf_id, + const br_block_ctr_class *bc_impl, size_t cipher_key_len); + +/* + * Switch to GCM encryption for outgoing records. + * cc the engine context + * is_client non-zero for a client, zero for a server + * prf_id id of hash function for PRF + * bc_impl block cipher implementation (CTR) + * cipher_key_len block cipher key length (in bytes) + */ +void br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc, + int is_client, int prf_id, + const br_block_ctr_class *bc_impl, size_t cipher_key_len); + +/* + * Switch to ChaCha20+Poly1305 decryption for incoming records. + * cc the engine context + * is_client non-zero for a client, zero for a server + * prf_id id of hash function for PRF + */ +void br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc, + int is_client, int prf_id); + +/* + * Switch to ChaCha20+Poly1305 encryption for outgoing records. + * cc the engine context + * is_client non-zero for a client, zero for a server + * prf_id id of hash function for PRF + */ +void br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc, + int is_client, int prf_id); + +/* + * Switch to CCM decryption for incoming records. + * cc the engine context + * is_client non-zero for a client, zero for a server + * prf_id id of hash function for PRF + * bc_impl block cipher implementation (CTR+CBC) + * cipher_key_len block cipher key length (in bytes) + * tag_len tag length (in bytes) + */ +void br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc, + int is_client, int prf_id, + const br_block_ctrcbc_class *bc_impl, + size_t cipher_key_len, size_t tag_len); + +/* + * Switch to GCM encryption for outgoing records. + * cc the engine context + * is_client non-zero for a client, zero for a server + * prf_id id of hash function for PRF + * bc_impl block cipher implementation (CTR+CBC) + * cipher_key_len block cipher key length (in bytes) + * tag_len tag length (in bytes) + */ +void br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc, + int is_client, int prf_id, + const br_block_ctrcbc_class *bc_impl, + size_t cipher_key_len, size_t tag_len); + +/* + * Calls to T0-generated code. + */ +void br_ssl_hs_client_init_main(void *ctx); +void br_ssl_hs_client_run(void *ctx); +void br_ssl_hs_server_init_main(void *ctx); +void br_ssl_hs_server_run(void *ctx); + +/* + * Get the hash function to use for signatures, given a bit mask of + * supported hash functions. This implements a strict choice order + * (namely SHA-256, SHA-384, SHA-512, SHA-224, SHA-1). If the mask + * does not document support of any of these hash functions, then this + * functions returns 0. + */ +int br_ssl_choose_hash(unsigned bf); + +/* ==================================================================== */ + +/* + * PowerPC / POWER assembly stuff. The special BR_POWER_ASM_MACROS macro + * must be defined before including this file; this is done by source + * files that use some inline assembly for PowerPC / POWER machines. + */ + +#if BR_POWER_ASM_MACROS + +#define lxvw4x(xt, ra, rb) lxvw4x_(xt, ra, rb) +#define stxvw4x(xt, ra, rb) stxvw4x_(xt, ra, rb) + +#define bdnz(foo) bdnz_(foo) +#define bdz(foo) bdz_(foo) +#define beq(foo) beq_(foo) + +#define li(rx, value) li_(rx, value) +#define addi(rx, ra, imm) addi_(rx, ra, imm) +#define cmpldi(rx, imm) cmpldi_(rx, imm) +#define mtctr(rx) mtctr_(rx) +#define vspltb(vrt, vrb, uim) vspltb_(vrt, vrb, uim) +#define vspltw(vrt, vrb, uim) vspltw_(vrt, vrb, uim) +#define vspltisb(vrt, imm) vspltisb_(vrt, imm) +#define vspltisw(vrt, imm) vspltisw_(vrt, imm) +#define vrlw(vrt, vra, vrb) vrlw_(vrt, vra, vrb) +#define vsbox(vrt, vra) vsbox_(vrt, vra) +#define vxor(vrt, vra, vrb) vxor_(vrt, vra, vrb) +#define vand(vrt, vra, vrb) vand_(vrt, vra, vrb) +#define vsro(vrt, vra, vrb) vsro_(vrt, vra, vrb) +#define vsl(vrt, vra, vrb) vsl_(vrt, vra, vrb) +#define vsldoi(vt, va, vb, sh) vsldoi_(vt, va, vb, sh) +#define vsr(vrt, vra, vrb) vsr_(vrt, vra, vrb) +#define vaddcuw(vrt, vra, vrb) vaddcuw_(vrt, vra, vrb) +#define vadduwm(vrt, vra, vrb) vadduwm_(vrt, vra, vrb) +#define vsububm(vrt, vra, vrb) vsububm_(vrt, vra, vrb) +#define vsubuwm(vrt, vra, vrb) vsubuwm_(vrt, vra, vrb) +#define vsrw(vrt, vra, vrb) vsrw_(vrt, vra, vrb) +#define vcipher(vt, va, vb) vcipher_(vt, va, vb) +#define vcipherlast(vt, va, vb) vcipherlast_(vt, va, vb) +#define vncipher(vt, va, vb) vncipher_(vt, va, vb) +#define vncipherlast(vt, va, vb) vncipherlast_(vt, va, vb) +#define vperm(vt, va, vb, vc) vperm_(vt, va, vb, vc) +#define vpmsumd(vt, va, vb) vpmsumd_(vt, va, vb) +#define xxpermdi(vt, va, vb, d) xxpermdi_(vt, va, vb, d) + +#define lxvw4x_(xt, ra, rb) "\tlxvw4x\t" #xt "," #ra "," #rb "\n" +#define stxvw4x_(xt, ra, rb) "\tstxvw4x\t" #xt "," #ra "," #rb "\n" + +#define label(foo) #foo "%=:\n" +#define bdnz_(foo) "\tbdnz\t" #foo "%=\n" +#define bdz_(foo) "\tbdz\t" #foo "%=\n" +#define beq_(foo) "\tbeq\t" #foo "%=\n" + +#define li_(rx, value) "\tli\t" #rx "," #value "\n" +#define addi_(rx, ra, imm) "\taddi\t" #rx "," #ra "," #imm "\n" +#define cmpldi_(rx, imm) "\tcmpldi\t" #rx "," #imm "\n" +#define mtctr_(rx) "\tmtctr\t" #rx "\n" +#define vspltb_(vrt, vrb, uim) "\tvspltb\t" #vrt "," #vrb "," #uim "\n" +#define vspltw_(vrt, vrb, uim) "\tvspltw\t" #vrt "," #vrb "," #uim "\n" +#define vspltisb_(vrt, imm) "\tvspltisb\t" #vrt "," #imm "\n" +#define vspltisw_(vrt, imm) "\tvspltisw\t" #vrt "," #imm "\n" +#define vrlw_(vrt, vra, vrb) "\tvrlw\t" #vrt "," #vra "," #vrb "\n" +#define vsbox_(vrt, vra) "\tvsbox\t" #vrt "," #vra "\n" +#define vxor_(vrt, vra, vrb) "\tvxor\t" #vrt "," #vra "," #vrb "\n" +#define vand_(vrt, vra, vrb) "\tvand\t" #vrt "," #vra "," #vrb "\n" +#define vsro_(vrt, vra, vrb) "\tvsro\t" #vrt "," #vra "," #vrb "\n" +#define vsl_(vrt, vra, vrb) "\tvsl\t" #vrt "," #vra "," #vrb "\n" +#define vsldoi_(vt, va, vb, sh) "\tvsldoi\t" #vt "," #va "," #vb "," #sh "\n" +#define vsr_(vrt, vra, vrb) "\tvsr\t" #vrt "," #vra "," #vrb "\n" +#define vaddcuw_(vrt, vra, vrb) "\tvaddcuw\t" #vrt "," #vra "," #vrb "\n" +#define vadduwm_(vrt, vra, vrb) "\tvadduwm\t" #vrt "," #vra "," #vrb "\n" +#define vsububm_(vrt, vra, vrb) "\tvsububm\t" #vrt "," #vra "," #vrb "\n" +#define vsubuwm_(vrt, vra, vrb) "\tvsubuwm\t" #vrt "," #vra "," #vrb "\n" +#define vsrw_(vrt, vra, vrb) "\tvsrw\t" #vrt "," #vra "," #vrb "\n" +#define vcipher_(vt, va, vb) "\tvcipher\t" #vt "," #va "," #vb "\n" +#define vcipherlast_(vt, va, vb) "\tvcipherlast\t" #vt "," #va "," #vb "\n" +#define vncipher_(vt, va, vb) "\tvncipher\t" #vt "," #va "," #vb "\n" +#define vncipherlast_(vt, va, vb) "\tvncipherlast\t" #vt "," #va "," #vb "\n" +#define vperm_(vt, va, vb, vc) "\tvperm\t" #vt "," #va "," #vb "," #vc "\n" +#define vpmsumd_(vt, va, vb) "\tvpmsumd\t" #vt "," #va "," #vb "\n" +#define xxpermdi_(vt, va, vb, d) "\txxpermdi\t" #vt "," #va "," #vb "," #d "\n" + +#endif + +/* ==================================================================== */ +/* + * Special "activate intrinsics" code, needed for some compiler versions. + * This is defined at the end of this file, so that it won't impact any + * of the inline functions defined previously; and it is controlled by + * a specific macro defined in the caller code. + * + * Calling code conventions: + * + * - Caller must define BR_ENABLE_INTRINSICS before including "inner.h". + * - Functions that use intrinsics must be enclosed in an "enabled" + * region (between BR_TARGETS_X86_UP and BR_TARGETS_X86_DOWN). + * - Functions that use intrinsics must be tagged with the appropriate + * BR_TARGET(). + */ + +#if BR_ENABLE_INTRINSICS && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005) + +/* + * x86 intrinsics (both 32-bit and 64-bit). + */ +#if BR_i386 || BR_amd64 + +/* + * On GCC before version 5.0, we need to use the pragma to enable the + * target options globally, because the 'target' function attribute + * appears to be unreliable. Before 4.6 we must also avoid the + * push_options / pop_options mechanism, because it tends to trigger + * some internal compiler errors. + */ +#if BR_GCC && !BR_GCC_5_0 +#if BR_GCC_4_6 +#define BR_TARGETS_X86_UP \ + _Pragma("GCC push_options") \ + _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul,rdrnd\")") +#define BR_TARGETS_X86_DOWN \ + _Pragma("GCC pop_options") +#else +#define BR_TARGETS_X86_UP \ + _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul\")") +#define BR_TARGETS_X86_DOWN +#endif +#pragma GCC diagnostic ignored "-Wpsabi" +#endif + +#if BR_CLANG && !BR_CLANG_3_8 +#undef __SSE2__ +#undef __SSE3__ +#undef __SSSE3__ +#undef __SSE4_1__ +#undef __AES__ +#undef __PCLMUL__ +#undef __RDRND__ +#define __SSE2__ 1 +#define __SSE3__ 1 +#define __SSSE3__ 1 +#define __SSE4_1__ 1 +#define __AES__ 1 +#define __PCLMUL__ 1 +#define __RDRND__ 1 +#endif + +#ifndef BR_TARGETS_X86_UP +#define BR_TARGETS_X86_UP +#endif +#ifndef BR_TARGETS_X86_DOWN +#define BR_TARGETS_X86_DOWN +#endif + +#if BR_GCC || BR_CLANG +BR_TARGETS_X86_UP +#include +#include +#define br_bswap32 __builtin_bswap32 +BR_TARGETS_X86_DOWN +#endif + +#if BR_MSC +#include +#include +#include +#define br_bswap32 _byteswap_ulong +#endif + +static __inline int +br_cpuid(uint32_t mask_eax, uint32_t mask_ebx, + uint32_t mask_ecx, uint32_t mask_edx) +{ +#if BR_GCC || BR_CLANG + unsigned eax, ebx, ecx, edx; + + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { + if ((eax & mask_eax) == mask_eax + && (ebx & mask_ebx) == mask_ebx + && (ecx & mask_ecx) == mask_ecx + && (edx & mask_edx) == mask_edx) + { + return 1; + } + } +#elif BR_MSC + int info[4]; + + __cpuid(info, 1); + if (((uint32_t)info[0] & mask_eax) == mask_eax + && ((uint32_t)info[1] & mask_ebx) == mask_ebx + && ((uint32_t)info[2] & mask_ecx) == mask_ecx + && ((uint32_t)info[3] & mask_edx) == mask_edx) + { + return 1; + } +#endif + return 0; +} + +#endif + +#endif + +/* ==================================================================== */ + +#endif diff --git a/BearSSL-OG/libbearssl/src/int/i15_add.c b/BearSSL-OG/libbearssl/src/int/i15_add.c new file mode 100644 index 0000000..97e29b8 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_add.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl) +{ + uint32_t cc; + size_t u, m; + + cc = 0; + m = (a[0] + 31) >> 4; + for (u = 1; u < m; u ++) { + uint32_t aw, bw, naw; + + aw = a[u]; + bw = b[u]; + naw = aw + bw + cc; + cc = naw >> 15; + a[u] = MUX(ctl, naw & 0x7FFF, aw); + } + return cc; +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_bitlen.c b/BearSSL-OG/libbearssl/src/int/i15_bitlen.c new file mode 100644 index 0000000..ad74467 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_bitlen.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i15_bit_length(uint16_t *x, size_t xlen) +{ + uint32_t tw, twk; + + tw = 0; + twk = 0; + while (xlen -- > 0) { + uint32_t w, c; + + c = EQ(tw, 0); + w = x[xlen]; + tw = MUX(c, w, tw); + twk = MUX(c, (uint32_t)xlen, twk); + } + return (twk << 4) + BIT_LENGTH(tw); +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_decmod.c b/BearSSL-OG/libbearssl/src/int/i15_decmod.c new file mode 100644 index 0000000..6076c57 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_decmod.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i15_decode_mod(uint16_t *x, const void *src, size_t len, const uint16_t *m) +{ + /* + * Two-pass algorithm: in the first pass, we determine whether the + * value fits; in the second pass, we do the actual write. + * + * During the first pass, 'r' contains the comparison result so + * far: + * 0x00000000 value is equal to the modulus + * 0x00000001 value is greater than the modulus + * 0xFFFFFFFF value is lower than the modulus + * + * Since we iterate starting with the least significant bytes (at + * the end of src[]), each new comparison overrides the previous + * except when the comparison yields 0 (equal). + * + * During the second pass, 'r' is either 0xFFFFFFFF (value fits) + * or 0x00000000 (value does not fit). + * + * We must iterate over all bytes of the source, _and_ possibly + * some extra virtual bytes (with value 0) so as to cover the + * complete modulus as well. We also add 4 such extra bytes beyond + * the modulus length because it then guarantees that no accumulated + * partial word remains to be processed. + */ + const unsigned char *buf; + size_t mlen, tlen; + int pass; + uint32_t r; + + buf = src; + mlen = (m[0] + 15) >> 4; + tlen = (mlen << 1); + if (tlen < len) { + tlen = len; + } + tlen += 4; + r = 0; + for (pass = 0; pass < 2; pass ++) { + size_t u, v; + uint32_t acc; + int acc_len; + + v = 1; + acc = 0; + acc_len = 0; + for (u = 0; u < tlen; u ++) { + uint32_t b; + + if (u < len) { + b = buf[len - 1 - u]; + } else { + b = 0; + } + acc |= (b << acc_len); + acc_len += 8; + if (acc_len >= 15) { + uint32_t xw; + + xw = acc & (uint32_t)0x7FFF; + acc_len -= 15; + acc = b >> (8 - acc_len); + if (v <= mlen) { + if (pass) { + x[v] = r & xw; + } else { + uint32_t cc; + + cc = (uint32_t)CMP(xw, m[v]); + r = MUX(EQ(cc, 0), r, cc); + } + } else { + if (!pass) { + r = MUX(EQ(xw, 0), r, 1); + } + } + v ++; + } + } + + /* + * When we reach this point at the end of the first pass: + * r is either 0, 1 or -1; we want to set r to 0 if it + * is equal to 0 or 1, and leave it to -1 otherwise. + * + * When we reach this point at the end of the second pass: + * r is either 0 or -1; we want to leave that value + * untouched. This is a subcase of the previous. + */ + r >>= 1; + r |= (r << 1); + } + + x[0] = m[0]; + return r & (uint32_t)1; +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_decode.c b/BearSSL-OG/libbearssl/src/int/i15_decode.c new file mode 100644 index 0000000..fc2c0be --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_decode.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_decode(uint16_t *x, const void *src, size_t len) +{ + const unsigned char *buf; + size_t v; + uint32_t acc; + int acc_len; + + buf = src; + v = 1; + acc = 0; + acc_len = 0; + while (len -- > 0) { + uint32_t b; + + b = buf[len]; + acc |= (b << acc_len); + acc_len += 8; + if (acc_len >= 15) { + x[v ++] = acc & 0x7FFF; + acc_len -= 15; + acc >>= 15; + } + } + if (acc_len != 0) { + x[v ++] = acc; + } + x[0] = br_i15_bit_length(x + 1, v - 1); +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_decred.c b/BearSSL-OG/libbearssl/src/int/i15_decred.c new file mode 100644 index 0000000..81e7dd1 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_decred.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_decode_reduce(uint16_t *x, + const void *src, size_t len, const uint16_t *m) +{ + uint32_t m_ebitlen, m_rbitlen; + size_t mblen, k; + const unsigned char *buf; + uint32_t acc; + int acc_len; + + /* + * Get the encoded bit length. + */ + m_ebitlen = m[0]; + + /* + * Special case for an invalid (null) modulus. + */ + if (m_ebitlen == 0) { + x[0] = 0; + return; + } + + /* + * Clear the destination. + */ + br_i15_zero(x, m_ebitlen); + + /* + * First decode directly as many bytes as possible. This requires + * computing the actual bit length. + */ + m_rbitlen = m_ebitlen >> 4; + m_rbitlen = (m_ebitlen & 15) + (m_rbitlen << 4) - m_rbitlen; + mblen = (m_rbitlen + 7) >> 3; + k = mblen - 1; + if (k >= len) { + br_i15_decode(x, src, len); + x[0] = m_ebitlen; + return; + } + buf = src; + br_i15_decode(x, buf, k); + x[0] = m_ebitlen; + + /* + * Input remaining bytes, using 15-bit words. + */ + acc = 0; + acc_len = 0; + while (k < len) { + uint32_t v; + + v = buf[k ++]; + acc = (acc << 8) | v; + acc_len += 8; + if (acc_len >= 15) { + br_i15_muladd_small(x, acc >> (acc_len - 15), m); + acc_len -= 15; + acc &= ~((uint32_t)-1 << acc_len); + } + } + + /* + * We may have some bits accumulated. We then perform a shift to + * be able to inject these bits as a full 15-bit word. + */ + if (acc_len != 0) { + acc = (acc | (x[1] << acc_len)) & 0x7FFF; + br_i15_rshift(x, 15 - acc_len); + br_i15_muladd_small(x, acc, m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_encode.c b/BearSSL-OG/libbearssl/src/int/i15_encode.c new file mode 100644 index 0000000..50668f4 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_encode.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_encode(void *dst, size_t len, const uint16_t *x) +{ + unsigned char *buf; + size_t u, xlen; + uint32_t acc; + int acc_len; + + xlen = (x[0] + 15) >> 4; + if (xlen == 0) { + memset(dst, 0, len); + return; + } + u = 1; + acc = 0; + acc_len = 0; + buf = dst; + while (len -- > 0) { + if (acc_len < 8) { + if (u <= xlen) { + acc += (uint32_t)x[u ++] << acc_len; + } + acc_len += 15; + } + buf[len] = (unsigned char)acc; + acc >>= 8; + acc_len -= 8; + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_fmont.c b/BearSSL-OG/libbearssl/src/int/i15_fmont.c new file mode 100644 index 0000000..3450b72 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_fmont.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i) +{ + size_t len, u, v; + + len = (m[0] + 15) >> 4; + for (u = 0; u < len; u ++) { + uint32_t f, cc; + + f = MUL15(x[1], m0i) & 0x7FFF; + cc = 0; + for (v = 0; v < len; v ++) { + uint32_t z; + + z = (uint32_t)x[v + 1] + MUL15(f, m[v + 1]) + cc; + cc = z >> 15; + if (v != 0) { + x[v] = z & 0x7FFF; + } + } + x[len] = cc; + } + + /* + * We may have to do an extra subtraction, but only if the + * value in x[] is indeed greater than or equal to that of m[], + * which is why we must do two calls (first call computes the + * carry, second call performs the subtraction only if the carry + * is 0). + */ + br_i15_sub(x, m, NOT(br_i15_sub(x, m, 0))); +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_iszero.c b/BearSSL-OG/libbearssl/src/int/i15_iszero.c new file mode 100644 index 0000000..d4b6f10 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_iszero.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i15_iszero(const uint16_t *x) +{ + uint32_t z; + size_t u; + + z = 0; + for (u = (x[0] + 15) >> 4; u > 0; u --) { + z |= x[u]; + } + return ~(z | -z) >> 31; +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_moddiv.c b/BearSSL-OG/libbearssl/src/int/i15_moddiv.c new file mode 100644 index 0000000..45af756 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_moddiv.c @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * In this file, we handle big integers with a custom format, i.e. + * without the usual one-word header. Value is split into 15-bit words, + * each stored in a 16-bit slot (top bit is zero) in little-endian + * order. The length (in words) is provided explicitly. In some cases, + * the value can be negative (using two's complement representation). In + * some cases, the top word is allowed to have a 16th bit. + */ + +/* + * Negate big integer conditionally. The value consists of 'len' words, + * with 15 bits in each word (the top bit of each word should be 0, + * except possibly for the last word). If 'ctl' is 1, the negation is + * computed; otherwise, if 'ctl' is 0, then the value is unchanged. + */ +static void +cond_negate(uint16_t *a, size_t len, uint32_t ctl) +{ + size_t k; + uint32_t cc, xm; + + cc = ctl; + xm = 0x7FFF & -ctl; + for (k = 0; k < len; k ++) { + uint32_t aw; + + aw = a[k]; + aw = (aw ^ xm) + cc; + a[k] = aw & 0x7FFF; + cc = (aw >> 15) & 1; + } +} + +/* + * Finish modular reduction. Rules on input parameters: + * + * if neg = 1, then -m <= a < 0 + * if neg = 0, then 0 <= a < 2*m + * + * If neg = 0, then the top word of a[] may use 16 bits. + * + * Also, modulus m must be odd. + */ +static void +finish_mod(uint16_t *a, size_t len, const uint16_t *m, uint32_t neg) +{ + size_t k; + uint32_t cc, xm, ym; + + /* + * First pass: compare a (assumed nonnegative) with m. + */ + cc = 0; + for (k = 0; k < len; k ++) { + uint32_t aw, mw; + + aw = a[k]; + mw = m[k]; + cc = (aw - mw - cc) >> 31; + } + + /* + * At this point: + * if neg = 1, then we must add m (regardless of cc) + * if neg = 0 and cc = 0, then we must subtract m + * if neg = 0 and cc = 1, then we must do nothing + */ + xm = 0x7FFF & -neg; + ym = -(neg | (1 - cc)); + cc = neg; + for (k = 0; k < len; k ++) { + uint32_t aw, mw; + + aw = a[k]; + mw = (m[k] ^ xm) & ym; + aw = aw - mw - cc; + a[k] = aw & 0x7FFF; + cc = aw >> 31; + } +} + +/* + * Compute: + * a <- (a*pa+b*pb)/(2^15) + * b <- (a*qa+b*qb)/(2^15) + * The division is assumed to be exact (i.e. the low word is dropped). + * If the final a is negative, then it is negated. Similarly for b. + * Returned value is the combination of two bits: + * bit 0: 1 if a had to be negated, 0 otherwise + * bit 1: 1 if b had to be negated, 0 otherwise + * + * Factors pa, pb, qa and qb must be at most 2^15 in absolute value. + * Source integers a and b must be nonnegative; top word is not allowed + * to contain an extra 16th bit. + */ +static uint32_t +co_reduce(uint16_t *a, uint16_t *b, size_t len, + int32_t pa, int32_t pb, int32_t qa, int32_t qb) +{ + size_t k; + int32_t cca, ccb; + uint32_t nega, negb; + + cca = 0; + ccb = 0; + for (k = 0; k < len; k ++) { + uint32_t wa, wb, za, zb; + uint16_t tta, ttb; + + /* + * Since: + * |pa| <= 2^15 + * |pb| <= 2^15 + * 0 <= wa <= 2^15 - 1 + * 0 <= wb <= 2^15 - 1 + * |cca| <= 2^16 - 1 + * Then: + * |za| <= (2^15-1)*(2^16) + (2^16-1) = 2^31 - 1 + * + * Thus, the new value of cca is such that |cca| <= 2^16 - 1. + * The same applies to ccb. + */ + wa = a[k]; + wb = b[k]; + za = wa * (uint32_t)pa + wb * (uint32_t)pb + (uint32_t)cca; + zb = wa * (uint32_t)qa + wb * (uint32_t)qb + (uint32_t)ccb; + if (k > 0) { + a[k - 1] = za & 0x7FFF; + b[k - 1] = zb & 0x7FFF; + } + tta = za >> 15; + ttb = zb >> 15; + cca = *(int16_t *)&tta; + ccb = *(int16_t *)&ttb; + } + a[len - 1] = (uint16_t)cca; + b[len - 1] = (uint16_t)ccb; + nega = (uint32_t)cca >> 31; + negb = (uint32_t)ccb >> 31; + cond_negate(a, len, nega); + cond_negate(b, len, negb); + return nega | (negb << 1); +} + +/* + * Compute: + * a <- (a*pa+b*pb)/(2^15) mod m + * b <- (a*qa+b*qb)/(2^15) mod m + * + * m0i is equal to -1/m[0] mod 2^15. + * + * Factors pa, pb, qa and qb must be at most 2^15 in absolute value. + * Source integers a and b must be nonnegative; top word is not allowed + * to contain an extra 16th bit. + */ +static void +co_reduce_mod(uint16_t *a, uint16_t *b, size_t len, + int32_t pa, int32_t pb, int32_t qa, int32_t qb, + const uint16_t *m, uint16_t m0i) +{ + size_t k; + int32_t cca, ccb, fa, fb; + + cca = 0; + ccb = 0; + fa = ((a[0] * (uint32_t)pa + b[0] * (uint32_t)pb) * m0i) & 0x7FFF; + fb = ((a[0] * (uint32_t)qa + b[0] * (uint32_t)qb) * m0i) & 0x7FFF; + for (k = 0; k < len; k ++) { + uint32_t wa, wb, za, zb; + uint32_t tta, ttb; + + /* + * In this loop, carries 'cca' and 'ccb' always fit on + * 17 bits (in absolute value). + */ + wa = a[k]; + wb = b[k]; + za = wa * (uint32_t)pa + wb * (uint32_t)pb + + m[k] * (uint32_t)fa + (uint32_t)cca; + zb = wa * (uint32_t)qa + wb * (uint32_t)qb + + m[k] * (uint32_t)fb + (uint32_t)ccb; + if (k > 0) { + a[k - 1] = za & 0x7FFF; + b[k - 1] = zb & 0x7FFF; + } + + /* + * The XOR-and-sub construction below does an arithmetic + * right shift in a portable way (technically, right-shifting + * a negative signed value is implementation-defined in C). + */ +#define M ((uint32_t)1 << 16) + tta = za >> 15; + ttb = zb >> 15; + tta = (tta ^ M) - M; + ttb = (ttb ^ M) - M; + cca = *(int32_t *)&tta; + ccb = *(int32_t *)&ttb; +#undef M + } + a[len - 1] = (uint32_t)cca; + b[len - 1] = (uint32_t)ccb; + + /* + * At this point: + * -m <= a < 2*m + * -m <= b < 2*m + * (this is a case of Montgomery reduction) + * The top word of 'a' and 'b' may have a 16-th bit set. + * We may have to add or subtract the modulus. + */ + finish_mod(a, len, m, (uint32_t)cca >> 31); + finish_mod(b, len, m, (uint32_t)ccb >> 31); +} + +/* see inner.h */ +uint32_t +br_i15_moddiv(uint16_t *x, const uint16_t *y, const uint16_t *m, uint16_t m0i, + uint16_t *t) +{ + /* + * Algorithm is an extended binary GCD. We maintain four values + * a, b, u and v, with the following invariants: + * + * a * x = y * u mod m + * b * x = y * v mod m + * + * Starting values are: + * + * a = y + * b = m + * u = x + * v = 0 + * + * The formal definition of the algorithm is a sequence of steps: + * + * - If a is even, then a <- a/2 and u <- u/2 mod m. + * - Otherwise, if b is even, then b <- b/2 and v <- v/2 mod m. + * - Otherwise, if a > b, then a <- (a-b)/2 and u <- (u-v)/2 mod m. + * - Otherwise, b <- (b-a)/2 and v <- (v-u)/2 mod m. + * + * Algorithm stops when a = b. At that point, they both are equal + * to GCD(y,m); the modular division succeeds if that value is 1. + * The result of the modular division is then u (or v: both are + * equal at that point). + * + * Each step makes either a or b shrink by at least one bit; hence, + * if m has bit length k bits, then 2k-2 steps are sufficient. + * + * + * Though complexity is quadratic in the size of m, the bit-by-bit + * processing is not very efficient. We can speed up processing by + * remarking that the decisions are taken based only on observation + * of the top and low bits of a and b. + * + * In the loop below, at each iteration, we use the two top words + * of a and b, and the low words of a and b, to compute reduction + * parameters pa, pb, qa and qb such that the new values for a + * and b are: + * + * a' = (a*pa + b*pb) / (2^15) + * b' = (a*qa + b*qb) / (2^15) + * + * the division being exact. + * + * Since the choices are based on the top words, they may be slightly + * off, requiring an optional correction: if a' < 0, then we replace + * pa with -pa, and pb with -pb. The total length of a and b is + * thus reduced by at least 14 bits at each iteration. + * + * The stopping conditions are still the same, though: when a + * and b become equal, they must be both odd (since m is odd, + * the GCD cannot be even), therefore the next operation is a + * subtraction, and one of the values becomes 0. At that point, + * nothing else happens, i.e. one value is stuck at 0, and the + * other one is the GCD. + */ + size_t len, k; + uint16_t *a, *b, *u, *v; + uint32_t num, r; + + len = (m[0] + 15) >> 4; + a = t; + b = a + len; + u = x + 1; + v = b + len; + memcpy(a, y + 1, len * sizeof *y); + memcpy(b, m + 1, len * sizeof *m); + memset(v, 0, len * sizeof *v); + + /* + * Loop below ensures that a and b are reduced by some bits each, + * for a total of at least 14 bits. + */ + for (num = ((m[0] - (m[0] >> 4)) << 1) + 14; num >= 14; num -= 14) { + size_t j; + uint32_t c0, c1; + uint32_t a0, a1, b0, b1; + uint32_t a_hi, b_hi, a_lo, b_lo; + int32_t pa, pb, qa, qb; + int i; + + /* + * Extract top words of a and b. If j is the highest + * index >= 1 such that a[j] != 0 or b[j] != 0, then we want + * (a[j] << 15) + a[j - 1], and (b[j] << 15) + b[j - 1]. + * If a and b are down to one word each, then we use a[0] + * and b[0]. + */ + c0 = (uint32_t)-1; + c1 = (uint32_t)-1; + a0 = 0; + a1 = 0; + b0 = 0; + b1 = 0; + j = len; + while (j -- > 0) { + uint32_t aw, bw; + + aw = a[j]; + bw = b[j]; + a0 ^= (a0 ^ aw) & c0; + a1 ^= (a1 ^ aw) & c1; + b0 ^= (b0 ^ bw) & c0; + b1 ^= (b1 ^ bw) & c1; + c1 = c0; + c0 &= (((aw | bw) + 0xFFFF) >> 16) - (uint32_t)1; + } + + /* + * If c1 = 0, then we grabbed two words for a and b. + * If c1 != 0 but c0 = 0, then we grabbed one word. It + * is not possible that c1 != 0 and c0 != 0, because that + * would mean that both integers are zero. + */ + a1 |= a0 & c1; + a0 &= ~c1; + b1 |= b0 & c1; + b0 &= ~c1; + a_hi = (a0 << 15) + a1; + b_hi = (b0 << 15) + b1; + a_lo = a[0]; + b_lo = b[0]; + + /* + * Compute reduction factors: + * + * a' = a*pa + b*pb + * b' = a*qa + b*qb + * + * such that a' and b' are both multiple of 2^15, but are + * only marginally larger than a and b. + */ + pa = 1; + pb = 0; + qa = 0; + qb = 1; + for (i = 0; i < 15; i ++) { + /* + * At each iteration: + * + * a <- (a-b)/2 if: a is odd, b is odd, a_hi > b_hi + * b <- (b-a)/2 if: a is odd, b is odd, a_hi <= b_hi + * a <- a/2 if: a is even + * b <- b/2 if: a is odd, b is even + * + * We multiply a_lo and b_lo by 2 at each + * iteration, thus a division by 2 really is a + * non-multiplication by 2. + */ + uint32_t r, oa, ob, cAB, cBA, cA; + + /* + * cAB = 1 if b must be subtracted from a + * cBA = 1 if a must be subtracted from b + * cA = 1 if a is divided by 2, 0 otherwise + * + * Rules: + * + * cAB and cBA cannot be both 1. + * if a is not divided by 2, b is. + */ + r = GT(a_hi, b_hi); + oa = (a_lo >> i) & 1; + ob = (b_lo >> i) & 1; + cAB = oa & ob & r; + cBA = oa & ob & NOT(r); + cA = cAB | NOT(oa); + + /* + * Conditional subtractions. + */ + a_lo -= b_lo & -cAB; + a_hi -= b_hi & -cAB; + pa -= qa & -(int32_t)cAB; + pb -= qb & -(int32_t)cAB; + b_lo -= a_lo & -cBA; + b_hi -= a_hi & -cBA; + qa -= pa & -(int32_t)cBA; + qb -= pb & -(int32_t)cBA; + + /* + * Shifting. + */ + a_lo += a_lo & (cA - 1); + pa += pa & ((int32_t)cA - 1); + pb += pb & ((int32_t)cA - 1); + a_hi ^= (a_hi ^ (a_hi >> 1)) & -cA; + b_lo += b_lo & -cA; + qa += qa & -(int32_t)cA; + qb += qb & -(int32_t)cA; + b_hi ^= (b_hi ^ (b_hi >> 1)) & (cA - 1); + } + + /* + * Replace a and b with new values a' and b'. + */ + r = co_reduce(a, b, len, pa, pb, qa, qb); + pa -= pa * ((r & 1) << 1); + pb -= pb * ((r & 1) << 1); + qa -= qa * (r & 2); + qb -= qb * (r & 2); + co_reduce_mod(u, v, len, pa, pb, qa, qb, m + 1, m0i); + } + + /* + * Now one of the arrays should be 0, and the other contains + * the GCD. If a is 0, then u is 0 as well, and v contains + * the division result. + * Result is correct if and only if GCD is 1. + */ + r = (a[0] | b[0]) ^ 1; + u[0] |= v[0]; + for (k = 1; k < len; k ++) { + r |= a[k] | b[k]; + u[k] |= v[k]; + } + return EQ0(r); +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_modpow.c b/BearSSL-OG/libbearssl/src/int/i15_modpow.c new file mode 100644 index 0000000..9bf304e --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_modpow.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_modpow(uint16_t *x, + const unsigned char *e, size_t elen, + const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2) +{ + size_t mlen; + unsigned k; + + mlen = ((m[0] + 31) >> 4) * sizeof m[0]; + memcpy(t1, x, mlen); + br_i15_to_monty(t1, m); + br_i15_zero(x, m[0]); + x[1] = 1; + for (k = 0; k < ((unsigned)elen << 3); k ++) { + uint32_t ctl; + + ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1; + br_i15_montymul(t2, x, t1, m, m0i); + CCOPY(ctl, x, t2, mlen); + br_i15_montymul(t2, t1, t1, m, m0i); + memcpy(t1, t2, mlen); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_modpow2.c b/BearSSL-OG/libbearssl/src/int/i15_modpow2.c new file mode 100644 index 0000000..4b32118 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_modpow2.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i15_modpow_opt(uint16_t *x, + const unsigned char *e, size_t elen, + const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen) +{ + size_t mlen, mwlen; + uint16_t *t1, *t2, *base; + size_t u, v; + uint32_t acc; + int acc_len, win_len; + + /* + * Get modulus size. + */ + mwlen = (m[0] + 31) >> 4; + mlen = mwlen * sizeof m[0]; + mwlen += (mwlen & 1); + t1 = tmp; + t2 = tmp + mwlen; + + /* + * Compute possible window size, with a maximum of 5 bits. + * When the window has size 1 bit, we use a specific code + * that requires only two temporaries. Otherwise, for a + * window of k bits, we need 2^k+1 temporaries. + */ + if (twlen < (mwlen << 1)) { + return 0; + } + for (win_len = 5; win_len > 1; win_len --) { + if ((((uint32_t)1 << win_len) + 1) * mwlen <= twlen) { + break; + } + } + + /* + * Everything is done in Montgomery representation. + */ + br_i15_to_monty(x, m); + + /* + * Compute window contents. If the window has size one bit only, + * then t2 is set to x; otherwise, t2[0] is left untouched, and + * t2[k] is set to x^k (for k >= 1). + */ + if (win_len == 1) { + memcpy(t2, x, mlen); + } else { + memcpy(t2 + mwlen, x, mlen); + base = t2 + mwlen; + for (u = 2; u < ((unsigned)1 << win_len); u ++) { + br_i15_montymul(base + mwlen, base, x, m, m0i); + base += mwlen; + } + } + + /* + * We need to set x to 1, in Montgomery representation. This can + * be done efficiently by setting the high word to 1, then doing + * one word-sized shift. + */ + br_i15_zero(x, m[0]); + x[(m[0] + 15) >> 4] = 1; + br_i15_muladd_small(x, 0, m); + + /* + * We process bits from most to least significant. At each + * loop iteration, we have acc_len bits in acc. + */ + acc = 0; + acc_len = 0; + while (acc_len > 0 || elen > 0) { + int i, k; + uint32_t bits; + + /* + * Get the next bits. + */ + k = win_len; + if (acc_len < win_len) { + if (elen > 0) { + acc = (acc << 8) | *e ++; + elen --; + acc_len += 8; + } else { + k = acc_len; + } + } + bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1); + acc_len -= k; + + /* + * We could get exactly k bits. Compute k squarings. + */ + for (i = 0; i < k; i ++) { + br_i15_montymul(t1, x, x, m, m0i); + memcpy(x, t1, mlen); + } + + /* + * Window lookup: we want to set t2 to the window + * lookup value, assuming the bits are non-zero. If + * the window length is 1 bit only, then t2 is + * already set; otherwise, we do a constant-time lookup. + */ + if (win_len > 1) { + br_i15_zero(t2, m[0]); + base = t2 + mwlen; + for (u = 1; u < ((uint32_t)1 << k); u ++) { + uint32_t mask; + + mask = -EQ(u, bits); + for (v = 1; v < mwlen; v ++) { + t2[v] |= mask & base[v]; + } + base += mwlen; + } + } + + /* + * Multiply with the looked-up value. We keep the + * product only if the exponent bits are not all-zero. + */ + br_i15_montymul(t1, x, t2, m, m0i); + CCOPY(NEQ(bits, 0), x, t1, mlen); + } + + /* + * Convert back from Montgomery representation, and exit. + */ + br_i15_from_monty(x, m, m0i); + return 1; +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_montmul.c b/BearSSL-OG/libbearssl/src/int/i15_montmul.c new file mode 100644 index 0000000..e98bc32 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_montmul.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y, + const uint16_t *m, uint16_t m0i) +{ + size_t len, len4, u, v; + uint32_t dh; + + len = (m[0] + 15) >> 4; + len4 = len & ~(size_t)3; + br_i15_zero(d, m[0]); + dh = 0; + for (u = 0; u < len; u ++) { + uint32_t f, xu, r, zh; + + xu = x[u + 1]; + f = MUL15((d[1] + MUL15(x[u + 1], y[1])) & 0x7FFF, m0i) + & 0x7FFF; +#if BR_ARMEL_CORTEXM_GCC + if (len4 != 0) { + uint16_t *limit; + + limit = d + len4; + asm volatile ( +"\n\ + @ carry: r=r2 \n\ + @ multipliers: xu=r3 f=r4 \n\ + @ base registers: d+v=r5 y+v=r6 m+v=r7 \n\ + @ r8 contains 0x7FFF \n\ + @ r9 contains d+len4 \n\ + ldr r0, %[limit] \n\ + ldr r3, %[xu] \n\ + mov r9, r0 \n\ + ldr r4, %[f] \n\ + eor r2, r2 \n\ + ldr r5, %[d] \n\ + sub r1, r2, #1 \n\ + ldr r6, %[y] \n\ + lsr r1, r1, #17 \n\ + ldr r7, %[m] \n\ + mov r8, r1 \n\ +loop%=: \n\ + ldrh r0, [r6, #2] \n\ + ldrh r1, [r7, #2] \n\ + mul r0, r3 \n\ + mul r1, r4 \n\ + add r2, r0, r2 \n\ + ldrh r0, [r5, #2] \n\ + add r2, r1, r2 \n\ + mov r1, r8 \n\ + add r2, r0, r2 \n\ + and r1, r2 \n\ + lsr r2, r2, #15 \n\ + strh r1, [r5, #0] \n\ + \n\ + ldrh r0, [r6, #4] \n\ + ldrh r1, [r7, #4] \n\ + mul r0, r3 \n\ + mul r1, r4 \n\ + add r2, r0, r2 \n\ + ldrh r0, [r5, #4] \n\ + add r2, r1, r2 \n\ + mov r1, r8 \n\ + add r2, r0, r2 \n\ + and r1, r2 \n\ + lsr r2, r2, #15 \n\ + strh r1, [r5, #2] \n\ + \n\ + ldrh r0, [r6, #6] \n\ + ldrh r1, [r7, #6] \n\ + mul r0, r3 \n\ + mul r1, r4 \n\ + add r2, r0, r2 \n\ + ldrh r0, [r5, #6] \n\ + add r2, r1, r2 \n\ + mov r1, r8 \n\ + add r2, r0, r2 \n\ + and r1, r2 \n\ + lsr r2, r2, #15 \n\ + strh r1, [r5, #4] \n\ + \n\ + ldrh r0, [r6, #8] \n\ + ldrh r1, [r7, #8] \n\ + mul r0, r3 \n\ + mul r1, r4 \n\ + add r2, r0, r2 \n\ + ldrh r0, [r5, #8] \n\ + add r2, r1, r2 \n\ + mov r1, r8 \n\ + add r2, r0, r2 \n\ + and r1, r2 \n\ + lsr r2, r2, #15 \n\ + strh r1, [r5, #6] \n\ + \n\ + add r5, r5, #8 \n\ + add r6, r6, #8 \n\ + add r7, r7, #8 \n\ + cmp r5, r9 \n\ + bne loop%= \n\ + \n\ + str r2, %[carry] \n\ +" +: [carry] "=m" (r) +: [xu] "m" (xu), [f] "m" (f), [d] "m" (d), [y] "m" (y), + [m] "m" (m), [limit] "m" (limit) +: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + } else { + r = 0; + } + v = len4; +#else + r = 0; + for (v = 0; v < len4; v += 4) { + uint32_t z; + + z = d[v + 1] + MUL15(xu, y[v + 1]) + + MUL15(f, m[v + 1]) + r; + r = z >> 15; + d[v + 0] = z & 0x7FFF; + z = d[v + 2] + MUL15(xu, y[v + 2]) + + MUL15(f, m[v + 2]) + r; + r = z >> 15; + d[v + 1] = z & 0x7FFF; + z = d[v + 3] + MUL15(xu, y[v + 3]) + + MUL15(f, m[v + 3]) + r; + r = z >> 15; + d[v + 2] = z & 0x7FFF; + z = d[v + 4] + MUL15(xu, y[v + 4]) + + MUL15(f, m[v + 4]) + r; + r = z >> 15; + d[v + 3] = z & 0x7FFF; + } +#endif + for (; v < len; v ++) { + uint32_t z; + + z = d[v + 1] + MUL15(xu, y[v + 1]) + + MUL15(f, m[v + 1]) + r; + r = z >> 15; + d[v + 0] = z & 0x7FFF; + } + + zh = dh + r; + d[len] = zh & 0x7FFF; + dh = zh >> 15; + } + + /* + * Restore the bit length (it was overwritten in the loop above). + */ + d[0] = m[0]; + + /* + * d[] may be greater than m[], but it is still lower than twice + * the modulus. + */ + br_i15_sub(d, m, NEQ(dh, 0) | NOT(br_i15_sub(d, m, 0))); +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_mulacc.c b/BearSSL-OG/libbearssl/src/int/i15_mulacc.c new file mode 100644 index 0000000..7a073ac --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_mulacc.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b) +{ + size_t alen, blen, u; + unsigned dl, dh; + + alen = (a[0] + 15) >> 4; + blen = (b[0] + 15) >> 4; + + /* + * Announced bit length of d[] will be the sum of the announced + * bit lengths of a[] and b[]; but the lengths are encoded. + */ + dl = (a[0] & 15) + (b[0] & 15); + dh = (a[0] >> 4) + (b[0] >> 4); + d[0] = (dh << 4) + dl + (~(uint32_t)(dl - 15) >> 31); + + for (u = 0; u < blen; u ++) { + uint32_t f; + size_t v; + uint32_t cc; + + f = b[1 + u]; + cc = 0; + for (v = 0; v < alen; v ++) { + uint32_t z; + + z = (uint32_t)d[1 + u + v] + MUL15(f, a[1 + v]) + cc; + cc = z >> 15; + d[1 + u + v] = z & 0x7FFF; + } + d[1 + u + alen] = cc; + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_muladd.c b/BearSSL-OG/libbearssl/src/int/i15_muladd.c new file mode 100644 index 0000000..c4b7216 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_muladd.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Constant-time division. The divisor must not be larger than 16 bits, + * and the quotient must fit on 17 bits. + */ +static uint32_t +divrem16(uint32_t x, uint32_t d, uint32_t *r) +{ + int i; + uint32_t q; + + q = 0; + d <<= 16; + for (i = 16; i >= 0; i --) { + uint32_t ctl; + + ctl = LE(d, x); + q |= ctl << i; + x -= (-ctl) & d; + d >>= 1; + } + if (r != NULL) { + *r = x; + } + return q; +} + +/* see inner.h */ +void +br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m) +{ + /* + * Constant-time: we accept to leak the exact bit length of the + * modulus m. + */ + unsigned m_bitlen, mblr; + size_t u, mlen; + uint32_t hi, a0, a, b, q; + uint32_t cc, tb, over, under; + + /* + * Simple case: the modulus fits on one word. + */ + m_bitlen = m[0]; + if (m_bitlen == 0) { + return; + } + if (m_bitlen <= 15) { + uint32_t rem; + + divrem16(((uint32_t)x[1] << 15) | z, m[1], &rem); + x[1] = rem; + return; + } + mlen = (m_bitlen + 15) >> 4; + mblr = m_bitlen & 15; + + /* + * Principle: we estimate the quotient (x*2^15+z)/m by + * doing a 30/15 division with the high words. + * + * Let: + * w = 2^15 + * a = (w*a0 + a1) * w^N + a2 + * b = b0 * w^N + b2 + * such that: + * 0 <= a0 < w + * 0 <= a1 < w + * 0 <= a2 < w^N + * w/2 <= b0 < w + * 0 <= b2 < w^N + * a < w*b + * I.e. the two top words of a are a0:a1, the top word of b is + * b0, we ensured that b0 is "full" (high bit set), and a is + * such that the quotient q = a/b fits on one word (0 <= q < w). + * + * If a = b*q + r (with 0 <= r < q), then we can estimate q by + * using a division on the top words: + * a0*w + a1 = b0*u + v (with 0 <= v < b0) + * Then the following holds: + * 0 <= u <= w + * u-2 <= q <= u + */ + hi = x[mlen]; + if (mblr == 0) { + a0 = x[mlen]; + memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + x[1] = z; + a = (a0 << 15) + x[mlen]; + b = m[mlen]; + } else { + a0 = (x[mlen] << (15 - mblr)) | (x[mlen - 1] >> mblr); + memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + x[1] = z; + a = (a0 << 15) | (((x[mlen] << (15 - mblr)) + | (x[mlen - 1] >> mblr)) & 0x7FFF); + b = (m[mlen] << (15 - mblr)) | (m[mlen - 1] >> mblr); + } + q = divrem16(a, b, NULL); + + /* + * We computed an estimate for q, but the real one may be q, + * q-1 or q-2; moreover, the division may have returned a value + * 8000 or even 8001 if the two high words were identical, and + * we want to avoid values beyond 7FFF. We thus adjust q so + * that the "true" multiplier will be q+1, q or q-1, and q is + * in the 0000..7FFF range. + */ + q = MUX(EQ(b, a0), 0x7FFF, q - 1 + ((q - 1) >> 31)); + + /* + * We subtract q*m from x (x has an extra high word of value 'hi'). + * Since q may be off by 1 (in either direction), we may have to + * add or subtract m afterwards. + * + * The 'tb' flag will be true (1) at the end of the loop if the + * result is greater than or equal to the modulus (not counting + * 'hi' or the carry). + */ + cc = 0; + tb = 1; + for (u = 1; u <= mlen; u ++) { + uint32_t mw, zl, xw, nxw; + + mw = m[u]; + zl = MUL15(mw, q) + cc; + cc = zl >> 15; + zl &= 0x7FFF; + xw = x[u]; + nxw = xw - zl; + cc += nxw >> 31; + nxw &= 0x7FFF; + x[u] = nxw; + tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw)); + } + + /* + * If we underestimated q, then either cc < hi (one extra bit + * beyond the top array word), or cc == hi and tb is true (no + * extra bit, but the result is not lower than the modulus). + * + * If we overestimated q, then cc > hi. + */ + over = GT(cc, hi); + under = ~over & (tb | LT(cc, hi)); + br_i15_add(x, m, over); + br_i15_sub(x, m, under); +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_ninv15.c b/BearSSL-OG/libbearssl/src/int/i15_ninv15.c new file mode 100644 index 0000000..de3a3ba --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_ninv15.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint16_t +br_i15_ninv15(uint16_t x) +{ + uint32_t y; + + y = 2 - x; + y = MUL15(y, 2 - MUL15(x, y)); + y = MUL15(y, 2 - MUL15(x, y)); + y = MUL15(y, 2 - MUL15(x, y)); + return MUX(x & 1, -y, 0) & 0x7FFF; +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_reduce.c b/BearSSL-OG/libbearssl/src/int/i15_reduce.c new file mode 100644 index 0000000..0931b10 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_reduce.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m) +{ + uint32_t m_bitlen, a_bitlen; + size_t mlen, alen, u; + + m_bitlen = m[0]; + mlen = (m_bitlen + 15) >> 4; + + x[0] = m_bitlen; + if (m_bitlen == 0) { + return; + } + + /* + * If the source is shorter, then simply copy all words from a[] + * and zero out the upper words. + */ + a_bitlen = a[0]; + alen = (a_bitlen + 15) >> 4; + if (a_bitlen < m_bitlen) { + memcpy(x + 1, a + 1, alen * sizeof *a); + for (u = alen; u < mlen; u ++) { + x[u + 1] = 0; + } + return; + } + + /* + * The source length is at least equal to that of the modulus. + * We must thus copy N-1 words, and input the remaining words + * one by one. + */ + memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); + x[mlen] = 0; + for (u = 1 + alen - mlen; u > 0; u --) { + br_i15_muladd_small(x, a[u], m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_rshift.c b/BearSSL-OG/libbearssl/src/int/i15_rshift.c new file mode 100644 index 0000000..f9991ab --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_rshift.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_rshift(uint16_t *x, int count) +{ + size_t u, len; + unsigned r; + + len = (x[0] + 15) >> 4; + if (len == 0) { + return; + } + r = x[1] >> count; + for (u = 2; u <= len; u ++) { + unsigned w; + + w = x[u]; + x[u - 1] = ((w << (15 - count)) | r) & 0x7FFF; + r = w >> count; + } + x[len] = r; +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_sub.c b/BearSSL-OG/libbearssl/src/int/i15_sub.c new file mode 100644 index 0000000..1983c4d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_sub.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl) +{ + uint32_t cc; + size_t u, m; + + cc = 0; + m = (a[0] + 31) >> 4; + for (u = 1; u < m; u ++) { + uint32_t aw, bw, naw; + + aw = a[u]; + bw = b[u]; + naw = aw - bw - cc; + cc = naw >> 31; + a[u] = MUX(ctl, naw & 0x7FFF, aw); + } + return cc; +} diff --git a/BearSSL-OG/libbearssl/src/int/i15_tmont.c b/BearSSL-OG/libbearssl/src/int/i15_tmont.c new file mode 100644 index 0000000..d5c4b8b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i15_tmont.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i15_to_monty(uint16_t *x, const uint16_t *m) +{ + unsigned k; + + for (k = (m[0] + 15) >> 4; k > 0; k --) { + br_i15_muladd_small(x, 0, m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_add.c b/BearSSL-OG/libbearssl/src/int/i31_add.c new file mode 100644 index 0000000..2ca47c6 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_add.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl) +{ + uint32_t cc; + size_t u, m; + + cc = 0; + m = (a[0] + 63) >> 5; + for (u = 1; u < m; u ++) { + uint32_t aw, bw, naw; + + aw = a[u]; + bw = b[u]; + naw = aw + bw + cc; + cc = naw >> 31; + a[u] = MUX(ctl, naw & (uint32_t)0x7FFFFFFF, aw); + } + return cc; +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_bitlen.c b/BearSSL-OG/libbearssl/src/int/i31_bitlen.c new file mode 100644 index 0000000..3e127c2 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_bitlen.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i31_bit_length(uint32_t *x, size_t xlen) +{ + uint32_t tw, twk; + + tw = 0; + twk = 0; + while (xlen -- > 0) { + uint32_t w, c; + + c = EQ(tw, 0); + w = x[xlen]; + tw = MUX(c, w, tw); + twk = MUX(c, (uint32_t)xlen, twk); + } + return (twk << 5) + BIT_LENGTH(tw); +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_decmod.c b/BearSSL-OG/libbearssl/src/int/i31_decmod.c new file mode 100644 index 0000000..3cd7bfe --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_decmod.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i31_decode_mod(uint32_t *x, const void *src, size_t len, const uint32_t *m) +{ + /* + * Two-pass algorithm: in the first pass, we determine whether the + * value fits; in the second pass, we do the actual write. + * + * During the first pass, 'r' contains the comparison result so + * far: + * 0x00000000 value is equal to the modulus + * 0x00000001 value is greater than the modulus + * 0xFFFFFFFF value is lower than the modulus + * + * Since we iterate starting with the least significant bytes (at + * the end of src[]), each new comparison overrides the previous + * except when the comparison yields 0 (equal). + * + * During the second pass, 'r' is either 0xFFFFFFFF (value fits) + * or 0x00000000 (value does not fit). + * + * We must iterate over all bytes of the source, _and_ possibly + * some extra virtual bytes (with value 0) so as to cover the + * complete modulus as well. We also add 4 such extra bytes beyond + * the modulus length because it then guarantees that no accumulated + * partial word remains to be processed. + */ + const unsigned char *buf; + size_t mlen, tlen; + int pass; + uint32_t r; + + buf = src; + mlen = (m[0] + 31) >> 5; + tlen = (mlen << 2); + if (tlen < len) { + tlen = len; + } + tlen += 4; + r = 0; + for (pass = 0; pass < 2; pass ++) { + size_t u, v; + uint32_t acc; + int acc_len; + + v = 1; + acc = 0; + acc_len = 0; + for (u = 0; u < tlen; u ++) { + uint32_t b; + + if (u < len) { + b = buf[len - 1 - u]; + } else { + b = 0; + } + acc |= (b << acc_len); + acc_len += 8; + if (acc_len >= 31) { + uint32_t xw; + + xw = acc & (uint32_t)0x7FFFFFFF; + acc_len -= 31; + acc = b >> (8 - acc_len); + if (v <= mlen) { + if (pass) { + x[v] = r & xw; + } else { + uint32_t cc; + + cc = (uint32_t)CMP(xw, m[v]); + r = MUX(EQ(cc, 0), r, cc); + } + } else { + if (!pass) { + r = MUX(EQ(xw, 0), r, 1); + } + } + v ++; + } + } + + /* + * When we reach this point at the end of the first pass: + * r is either 0, 1 or -1; we want to set r to 0 if it + * is equal to 0 or 1, and leave it to -1 otherwise. + * + * When we reach this point at the end of the second pass: + * r is either 0 or -1; we want to leave that value + * untouched. This is a subcase of the previous. + */ + r >>= 1; + r |= (r << 1); + } + + x[0] = m[0]; + return r & (uint32_t)1; +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_decode.c b/BearSSL-OG/libbearssl/src/int/i31_decode.c new file mode 100644 index 0000000..8ec6d90 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_decode.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_decode(uint32_t *x, const void *src, size_t len) +{ + const unsigned char *buf; + size_t u, v; + uint32_t acc; + int acc_len; + + buf = src; + u = len; + v = 1; + acc = 0; + acc_len = 0; + while (u -- > 0) { + uint32_t b; + + b = buf[u]; + acc |= (b << acc_len); + acc_len += 8; + if (acc_len >= 31) { + x[v ++] = acc & (uint32_t)0x7FFFFFFF; + acc_len -= 31; + acc = b >> (8 - acc_len); + } + } + if (acc_len != 0) { + x[v ++] = acc; + } + x[0] = br_i31_bit_length(x + 1, v - 1); +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_decred.c b/BearSSL-OG/libbearssl/src/int/i31_decred.c new file mode 100644 index 0000000..43db662 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_decred.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_decode_reduce(uint32_t *x, + const void *src, size_t len, const uint32_t *m) +{ + uint32_t m_ebitlen, m_rbitlen; + size_t mblen, k; + const unsigned char *buf; + uint32_t acc; + int acc_len; + + /* + * Get the encoded bit length. + */ + m_ebitlen = m[0]; + + /* + * Special case for an invalid (null) modulus. + */ + if (m_ebitlen == 0) { + x[0] = 0; + return; + } + + /* + * Clear the destination. + */ + br_i31_zero(x, m_ebitlen); + + /* + * First decode directly as many bytes as possible. This requires + * computing the actual bit length. + */ + m_rbitlen = m_ebitlen >> 5; + m_rbitlen = (m_ebitlen & 31) + (m_rbitlen << 5) - m_rbitlen; + mblen = (m_rbitlen + 7) >> 3; + k = mblen - 1; + if (k >= len) { + br_i31_decode(x, src, len); + x[0] = m_ebitlen; + return; + } + buf = src; + br_i31_decode(x, buf, k); + x[0] = m_ebitlen; + + /* + * Input remaining bytes, using 31-bit words. + */ + acc = 0; + acc_len = 0; + while (k < len) { + uint32_t v; + + v = buf[k ++]; + if (acc_len >= 23) { + acc_len -= 23; + acc <<= (8 - acc_len); + acc |= v >> acc_len; + br_i31_muladd_small(x, acc, m); + acc = v & (0xFF >> (8 - acc_len)); + } else { + acc = (acc << 8) | v; + acc_len += 8; + } + } + + /* + * We may have some bits accumulated. We then perform a shift to + * be able to inject these bits as a full 31-bit word. + */ + if (acc_len != 0) { + acc = (acc | (x[1] << acc_len)) & 0x7FFFFFFF; + br_i31_rshift(x, 31 - acc_len); + br_i31_muladd_small(x, acc, m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_encode.c b/BearSSL-OG/libbearssl/src/int/i31_encode.c new file mode 100644 index 0000000..b6b40c4 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_encode.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_encode(void *dst, size_t len, const uint32_t *x) +{ + unsigned char *buf; + size_t k, xlen; + uint32_t acc; + int acc_len; + + xlen = (x[0] + 31) >> 5; + if (xlen == 0) { + memset(dst, 0, len); + return; + } + buf = (unsigned char *)dst + len; + k = 1; + acc = 0; + acc_len = 0; + while (len != 0) { + uint32_t w; + + w = (k <= xlen) ? x[k] : 0; + k ++; + if (acc_len == 0) { + acc = w; + acc_len = 31; + } else { + uint32_t z; + + z = acc | (w << acc_len); + acc_len --; + acc = w >> (31 - acc_len); + if (len >= 4) { + buf -= 4; + len -= 4; + br_enc32be(buf, z); + } else { + switch (len) { + case 3: + buf[-3] = (unsigned char)(z >> 16); + /* fall through */ + case 2: + buf[-2] = (unsigned char)(z >> 8); + /* fall through */ + case 1: + buf[-1] = (unsigned char)z; + break; + } + return; + } + } + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_fmont.c b/BearSSL-OG/libbearssl/src/int/i31_fmont.c new file mode 100644 index 0000000..c24b417 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_fmont.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i) +{ + size_t len, u, v; + + len = (m[0] + 31) >> 5; + for (u = 0; u < len; u ++) { + uint32_t f; + uint64_t cc; + + f = MUL31_lo(x[1], m0i); + cc = 0; + for (v = 0; v < len; v ++) { + uint64_t z; + + z = (uint64_t)x[v + 1] + MUL31(f, m[v + 1]) + cc; + cc = z >> 31; + if (v != 0) { + x[v] = (uint32_t)z & 0x7FFFFFFF; + } + } + x[len] = (uint32_t)cc; + } + + /* + * We may have to do an extra subtraction, but only if the + * value in x[] is indeed greater than or equal to that of m[], + * which is why we must do two calls (first call computes the + * carry, second call performs the subtraction only if the carry + * is 0). + */ + br_i31_sub(x, m, NOT(br_i31_sub(x, m, 0))); +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_iszero.c b/BearSSL-OG/libbearssl/src/int/i31_iszero.c new file mode 100644 index 0000000..8a7ea44 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_iszero.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i31_iszero(const uint32_t *x) +{ + uint32_t z; + size_t u; + + z = 0; + for (u = (x[0] + 31) >> 5; u > 0; u --) { + z |= x[u]; + } + return ~(z | -z) >> 31; +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_moddiv.c b/BearSSL-OG/libbearssl/src/int/i31_moddiv.c new file mode 100644 index 0000000..9950591 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_moddiv.c @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * In this file, we handle big integers with a custom format, i.e. + * without the usual one-word header. Value is split into 31-bit words, + * each stored in a 32-bit slot (top bit is zero) in little-endian + * order. The length (in words) is provided explicitly. In some cases, + * the value can be negative (using two's complement representation). In + * some cases, the top word is allowed to have a 32th bit. + */ + +/* + * Negate big integer conditionally. The value consists of 'len' words, + * with 31 bits in each word (the top bit of each word should be 0, + * except possibly for the last word). If 'ctl' is 1, the negation is + * computed; otherwise, if 'ctl' is 0, then the value is unchanged. + */ +static void +cond_negate(uint32_t *a, size_t len, uint32_t ctl) +{ + size_t k; + uint32_t cc, xm; + + cc = ctl; + xm = -ctl >> 1; + for (k = 0; k < len; k ++) { + uint32_t aw; + + aw = a[k]; + aw = (aw ^ xm) + cc; + a[k] = aw & 0x7FFFFFFF; + cc = aw >> 31; + } +} + +/* + * Finish modular reduction. Rules on input parameters: + * + * if neg = 1, then -m <= a < 0 + * if neg = 0, then 0 <= a < 2*m + * + * If neg = 0, then the top word of a[] may use 32 bits. + * + * Also, modulus m must be odd. + */ +static void +finish_mod(uint32_t *a, size_t len, const uint32_t *m, uint32_t neg) +{ + size_t k; + uint32_t cc, xm, ym; + + /* + * First pass: compare a (assumed nonnegative) with m. + * Note that if the final word uses the top extra bit, then + * subtracting m must yield a value less than 2^31, since we + * assumed that a < 2*m. + */ + cc = 0; + for (k = 0; k < len; k ++) { + uint32_t aw, mw; + + aw = a[k]; + mw = m[k]; + cc = (aw - mw - cc) >> 31; + } + + /* + * At this point: + * if neg = 1, then we must add m (regardless of cc) + * if neg = 0 and cc = 0, then we must subtract m + * if neg = 0 and cc = 1, then we must do nothing + */ + xm = -neg >> 1; + ym = -(neg | (1 - cc)); + cc = neg; + for (k = 0; k < len; k ++) { + uint32_t aw, mw; + + aw = a[k]; + mw = (m[k] ^ xm) & ym; + aw = aw - mw - cc; + a[k] = aw & 0x7FFFFFFF; + cc = aw >> 31; + } +} + +/* + * Compute: + * a <- (a*pa+b*pb)/(2^31) + * b <- (a*qa+b*qb)/(2^31) + * The division is assumed to be exact (i.e. the low word is dropped). + * If the final a is negative, then it is negated. Similarly for b. + * Returned value is the combination of two bits: + * bit 0: 1 if a had to be negated, 0 otherwise + * bit 1: 1 if b had to be negated, 0 otherwise + * + * Factors pa, pb, qa and qb must be at most 2^31 in absolute value. + * Source integers a and b must be nonnegative; top word is not allowed + * to contain an extra 32th bit. + */ +static uint32_t +co_reduce(uint32_t *a, uint32_t *b, size_t len, + int64_t pa, int64_t pb, int64_t qa, int64_t qb) +{ + size_t k; + int64_t cca, ccb; + uint32_t nega, negb; + + cca = 0; + ccb = 0; + for (k = 0; k < len; k ++) { + uint32_t wa, wb; + uint64_t za, zb; + uint64_t tta, ttb; + + /* + * Since: + * |pa| <= 2^31 + * |pb| <= 2^31 + * 0 <= wa <= 2^31 - 1 + * 0 <= wb <= 2^31 - 1 + * |cca| <= 2^32 - 1 + * Then: + * |za| <= (2^31-1)*(2^32) + (2^32-1) = 2^63 - 1 + * + * Thus, the new value of cca is such that |cca| <= 2^32 - 1. + * The same applies to ccb. + */ + wa = a[k]; + wb = b[k]; + za = wa * (uint64_t)pa + wb * (uint64_t)pb + (uint64_t)cca; + zb = wa * (uint64_t)qa + wb * (uint64_t)qb + (uint64_t)ccb; + if (k > 0) { + a[k - 1] = za & 0x7FFFFFFF; + b[k - 1] = zb & 0x7FFFFFFF; + } + + /* + * For the new values of cca and ccb, we need a signed + * right-shift; since, in C, right-shifting a signed + * negative value is implementation-defined, we use a + * custom portable sign extension expression. + */ +#define M ((uint64_t)1 << 32) + tta = za >> 31; + ttb = zb >> 31; + tta = (tta ^ M) - M; + ttb = (ttb ^ M) - M; + cca = *(int64_t *)&tta; + ccb = *(int64_t *)&ttb; +#undef M + } + a[len - 1] = (uint32_t)cca; + b[len - 1] = (uint32_t)ccb; + + nega = (uint32_t)((uint64_t)cca >> 63); + negb = (uint32_t)((uint64_t)ccb >> 63); + cond_negate(a, len, nega); + cond_negate(b, len, negb); + return nega | (negb << 1); +} + +/* + * Compute: + * a <- (a*pa+b*pb)/(2^31) mod m + * b <- (a*qa+b*qb)/(2^31) mod m + * + * m0i is equal to -1/m[0] mod 2^31. + * + * Factors pa, pb, qa and qb must be at most 2^31 in absolute value. + * Source integers a and b must be nonnegative; top word is not allowed + * to contain an extra 32th bit. + */ +static void +co_reduce_mod(uint32_t *a, uint32_t *b, size_t len, + int64_t pa, int64_t pb, int64_t qa, int64_t qb, + const uint32_t *m, uint32_t m0i) +{ + size_t k; + int64_t cca, ccb; + uint32_t fa, fb; + + cca = 0; + ccb = 0; + fa = ((a[0] * (uint32_t)pa + b[0] * (uint32_t)pb) * m0i) & 0x7FFFFFFF; + fb = ((a[0] * (uint32_t)qa + b[0] * (uint32_t)qb) * m0i) & 0x7FFFFFFF; + for (k = 0; k < len; k ++) { + uint32_t wa, wb; + uint64_t za, zb; + uint64_t tta, ttb; + + /* + * In this loop, carries 'cca' and 'ccb' always fit on + * 33 bits (in absolute value). + */ + wa = a[k]; + wb = b[k]; + za = wa * (uint64_t)pa + wb * (uint64_t)pb + + m[k] * (uint64_t)fa + (uint64_t)cca; + zb = wa * (uint64_t)qa + wb * (uint64_t)qb + + m[k] * (uint64_t)fb + (uint64_t)ccb; + if (k > 0) { + a[k - 1] = (uint32_t)za & 0x7FFFFFFF; + b[k - 1] = (uint32_t)zb & 0x7FFFFFFF; + } + +#define M ((uint64_t)1 << 32) + tta = za >> 31; + ttb = zb >> 31; + tta = (tta ^ M) - M; + ttb = (ttb ^ M) - M; + cca = *(int64_t *)&tta; + ccb = *(int64_t *)&ttb; +#undef M + } + a[len - 1] = (uint32_t)cca; + b[len - 1] = (uint32_t)ccb; + + /* + * At this point: + * -m <= a < 2*m + * -m <= b < 2*m + * (this is a case of Montgomery reduction) + * The top word of 'a' and 'b' may have a 32-th bit set. + * We may have to add or subtract the modulus. + */ + finish_mod(a, len, m, (uint32_t)((uint64_t)cca >> 63)); + finish_mod(b, len, m, (uint32_t)((uint64_t)ccb >> 63)); +} + +/* see inner.h */ +uint32_t +br_i31_moddiv(uint32_t *x, const uint32_t *y, const uint32_t *m, uint32_t m0i, + uint32_t *t) +{ + /* + * Algorithm is an extended binary GCD. We maintain four values + * a, b, u and v, with the following invariants: + * + * a * x = y * u mod m + * b * x = y * v mod m + * + * Starting values are: + * + * a = y + * b = m + * u = x + * v = 0 + * + * The formal definition of the algorithm is a sequence of steps: + * + * - If a is even, then a <- a/2 and u <- u/2 mod m. + * - Otherwise, if b is even, then b <- b/2 and v <- v/2 mod m. + * - Otherwise, if a > b, then a <- (a-b)/2 and u <- (u-v)/2 mod m. + * - Otherwise, b <- (b-a)/2 and v <- (v-u)/2 mod m. + * + * Algorithm stops when a = b. At that point, they both are equal + * to GCD(y,m); the modular division succeeds if that value is 1. + * The result of the modular division is then u (or v: both are + * equal at that point). + * + * Each step makes either a or b shrink by at least one bit; hence, + * if m has bit length k bits, then 2k-2 steps are sufficient. + * + * + * Though complexity is quadratic in the size of m, the bit-by-bit + * processing is not very efficient. We can speed up processing by + * remarking that the decisions are taken based only on observation + * of the top and low bits of a and b. + * + * In the loop below, at each iteration, we use the two top words + * of a and b, and the low words of a and b, to compute reduction + * parameters pa, pb, qa and qb such that the new values for a + * and b are: + * + * a' = (a*pa + b*pb) / (2^31) + * b' = (a*qa + b*qb) / (2^31) + * + * the division being exact. + * + * Since the choices are based on the top words, they may be slightly + * off, requiring an optional correction: if a' < 0, then we replace + * pa with -pa, and pb with -pb. The total length of a and b is + * thus reduced by at least 30 bits at each iteration. + * + * The stopping conditions are still the same, though: when a + * and b become equal, they must be both odd (since m is odd, + * the GCD cannot be even), therefore the next operation is a + * subtraction, and one of the values becomes 0. At that point, + * nothing else happens, i.e. one value is stuck at 0, and the + * other one is the GCD. + */ + size_t len, k; + uint32_t *a, *b, *u, *v; + uint32_t num, r; + + len = (m[0] + 31) >> 5; + a = t; + b = a + len; + u = x + 1; + v = b + len; + memcpy(a, y + 1, len * sizeof *y); + memcpy(b, m + 1, len * sizeof *m); + memset(v, 0, len * sizeof *v); + + /* + * Loop below ensures that a and b are reduced by some bits each, + * for a total of at least 30 bits. + */ + for (num = ((m[0] - (m[0] >> 5)) << 1) + 30; num >= 30; num -= 30) { + size_t j; + uint32_t c0, c1; + uint32_t a0, a1, b0, b1; + uint64_t a_hi, b_hi; + uint32_t a_lo, b_lo; + int64_t pa, pb, qa, qb; + int i; + + /* + * Extract top words of a and b. If j is the highest + * index >= 1 such that a[j] != 0 or b[j] != 0, then we want + * (a[j] << 31) + a[j - 1], and (b[j] << 31) + b[j - 1]. + * If a and b are down to one word each, then we use a[0] + * and b[0]. + */ + c0 = (uint32_t)-1; + c1 = (uint32_t)-1; + a0 = 0; + a1 = 0; + b0 = 0; + b1 = 0; + j = len; + while (j -- > 0) { + uint32_t aw, bw; + + aw = a[j]; + bw = b[j]; + a0 ^= (a0 ^ aw) & c0; + a1 ^= (a1 ^ aw) & c1; + b0 ^= (b0 ^ bw) & c0; + b1 ^= (b1 ^ bw) & c1; + c1 = c0; + c0 &= (((aw | bw) + 0x7FFFFFFF) >> 31) - (uint32_t)1; + } + + /* + * If c1 = 0, then we grabbed two words for a and b. + * If c1 != 0 but c0 = 0, then we grabbed one word. It + * is not possible that c1 != 0 and c0 != 0, because that + * would mean that both integers are zero. + */ + a1 |= a0 & c1; + a0 &= ~c1; + b1 |= b0 & c1; + b0 &= ~c1; + a_hi = ((uint64_t)a0 << 31) + a1; + b_hi = ((uint64_t)b0 << 31) + b1; + a_lo = a[0]; + b_lo = b[0]; + + /* + * Compute reduction factors: + * + * a' = a*pa + b*pb + * b' = a*qa + b*qb + * + * such that a' and b' are both multiple of 2^31, but are + * only marginally larger than a and b. + */ + pa = 1; + pb = 0; + qa = 0; + qb = 1; + for (i = 0; i < 31; i ++) { + /* + * At each iteration: + * + * a <- (a-b)/2 if: a is odd, b is odd, a_hi > b_hi + * b <- (b-a)/2 if: a is odd, b is odd, a_hi <= b_hi + * a <- a/2 if: a is even + * b <- b/2 if: a is odd, b is even + * + * We multiply a_lo and b_lo by 2 at each + * iteration, thus a division by 2 really is a + * non-multiplication by 2. + */ + uint32_t r, oa, ob, cAB, cBA, cA; + uint64_t rz; + + /* + * r = GT(a_hi, b_hi) + * But the GT() function works on uint32_t operands, + * so we inline a 64-bit version here. + */ + rz = b_hi - a_hi; + r = (uint32_t)((rz ^ ((a_hi ^ b_hi) + & (a_hi ^ rz))) >> 63); + + /* + * cAB = 1 if b must be subtracted from a + * cBA = 1 if a must be subtracted from b + * cA = 1 if a is divided by 2, 0 otherwise + * + * Rules: + * + * cAB and cBA cannot be both 1. + * if a is not divided by 2, b is. + */ + oa = (a_lo >> i) & 1; + ob = (b_lo >> i) & 1; + cAB = oa & ob & r; + cBA = oa & ob & NOT(r); + cA = cAB | NOT(oa); + + /* + * Conditional subtractions. + */ + a_lo -= b_lo & -cAB; + a_hi -= b_hi & -(uint64_t)cAB; + pa -= qa & -(int64_t)cAB; + pb -= qb & -(int64_t)cAB; + b_lo -= a_lo & -cBA; + b_hi -= a_hi & -(uint64_t)cBA; + qa -= pa & -(int64_t)cBA; + qb -= pb & -(int64_t)cBA; + + /* + * Shifting. + */ + a_lo += a_lo & (cA - 1); + pa += pa & ((int64_t)cA - 1); + pb += pb & ((int64_t)cA - 1); + a_hi ^= (a_hi ^ (a_hi >> 1)) & -(uint64_t)cA; + b_lo += b_lo & -cA; + qa += qa & -(int64_t)cA; + qb += qb & -(int64_t)cA; + b_hi ^= (b_hi ^ (b_hi >> 1)) & ((uint64_t)cA - 1); + } + + /* + * Replace a and b with new values a' and b'. + */ + r = co_reduce(a, b, len, pa, pb, qa, qb); + pa -= pa * ((r & 1) << 1); + pb -= pb * ((r & 1) << 1); + qa -= qa * (r & 2); + qb -= qb * (r & 2); + co_reduce_mod(u, v, len, pa, pb, qa, qb, m + 1, m0i); + } + + /* + * Now one of the arrays should be 0, and the other contains + * the GCD. If a is 0, then u is 0 as well, and v contains + * the division result. + * Result is correct if and only if GCD is 1. + */ + r = (a[0] | b[0]) ^ 1; + u[0] |= v[0]; + for (k = 1; k < len; k ++) { + r |= a[k] | b[k]; + u[k] |= v[k]; + } + return EQ0(r); +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_modpow.c b/BearSSL-OG/libbearssl/src/int/i31_modpow.c new file mode 100644 index 0000000..4ef3f5d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_modpow.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_modpow(uint32_t *x, + const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2) +{ + size_t mlen; + uint32_t k; + + /* + * 'mlen' is the length of m[] expressed in bytes (including + * the "bit length" first field). + */ + mlen = ((m[0] + 63) >> 5) * sizeof m[0]; + + /* + * Throughout the algorithm: + * -- t1[] is in Montgomery representation; it contains x, x^2, + * x^4, x^8... + * -- The result is accumulated, in normal representation, in + * the x[] array. + * -- t2[] is used as destination buffer for each multiplication. + * + * Note that there is no need to call br_i32_from_monty(). + */ + memcpy(t1, x, mlen); + br_i31_to_monty(t1, m); + br_i31_zero(x, m[0]); + x[1] = 1; + for (k = 0; k < ((uint32_t)elen << 3); k ++) { + uint32_t ctl; + + ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1; + br_i31_montymul(t2, x, t1, m, m0i); + CCOPY(ctl, x, t2, mlen); + br_i31_montymul(t2, t1, t1, m, m0i); + memcpy(t1, t2, mlen); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_modpow2.c b/BearSSL-OG/libbearssl/src/int/i31_modpow2.c new file mode 100644 index 0000000..0b8f8cf --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_modpow2.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i31_modpow_opt(uint32_t *x, + const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen) +{ + size_t mlen, mwlen; + uint32_t *t1, *t2, *base; + size_t u, v; + uint32_t acc; + int acc_len, win_len; + + /* + * Get modulus size. + */ + mwlen = (m[0] + 63) >> 5; + mlen = mwlen * sizeof m[0]; + mwlen += (mwlen & 1); + t1 = tmp; + t2 = tmp + mwlen; + + /* + * Compute possible window size, with a maximum of 5 bits. + * When the window has size 1 bit, we use a specific code + * that requires only two temporaries. Otherwise, for a + * window of k bits, we need 2^k+1 temporaries. + */ + if (twlen < (mwlen << 1)) { + return 0; + } + for (win_len = 5; win_len > 1; win_len --) { + if ((((uint32_t)1 << win_len) + 1) * mwlen <= twlen) { + break; + } + } + + /* + * Everything is done in Montgomery representation. + */ + br_i31_to_monty(x, m); + + /* + * Compute window contents. If the window has size one bit only, + * then t2 is set to x; otherwise, t2[0] is left untouched, and + * t2[k] is set to x^k (for k >= 1). + */ + if (win_len == 1) { + memcpy(t2, x, mlen); + } else { + memcpy(t2 + mwlen, x, mlen); + base = t2 + mwlen; + for (u = 2; u < ((unsigned)1 << win_len); u ++) { + br_i31_montymul(base + mwlen, base, x, m, m0i); + base += mwlen; + } + } + + /* + * We need to set x to 1, in Montgomery representation. This can + * be done efficiently by setting the high word to 1, then doing + * one word-sized shift. + */ + br_i31_zero(x, m[0]); + x[(m[0] + 31) >> 5] = 1; + br_i31_muladd_small(x, 0, m); + + /* + * We process bits from most to least significant. At each + * loop iteration, we have acc_len bits in acc. + */ + acc = 0; + acc_len = 0; + while (acc_len > 0 || elen > 0) { + int i, k; + uint32_t bits; + + /* + * Get the next bits. + */ + k = win_len; + if (acc_len < win_len) { + if (elen > 0) { + acc = (acc << 8) | *e ++; + elen --; + acc_len += 8; + } else { + k = acc_len; + } + } + bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1); + acc_len -= k; + + /* + * We could get exactly k bits. Compute k squarings. + */ + for (i = 0; i < k; i ++) { + br_i31_montymul(t1, x, x, m, m0i); + memcpy(x, t1, mlen); + } + + /* + * Window lookup: we want to set t2 to the window + * lookup value, assuming the bits are non-zero. If + * the window length is 1 bit only, then t2 is + * already set; otherwise, we do a constant-time lookup. + */ + if (win_len > 1) { + br_i31_zero(t2, m[0]); + base = t2 + mwlen; + for (u = 1; u < ((uint32_t)1 << k); u ++) { + uint32_t mask; + + mask = -EQ(u, bits); + for (v = 1; v < mwlen; v ++) { + t2[v] |= mask & base[v]; + } + base += mwlen; + } + } + + /* + * Multiply with the looked-up value. We keep the + * product only if the exponent bits are not all-zero. + */ + br_i31_montymul(t1, x, t2, m, m0i); + CCOPY(NEQ(bits, 0), x, t1, mlen); + } + + /* + * Convert back from Montgomery representation, and exit. + */ + br_i31_from_monty(x, m, m0i); + return 1; +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_montmul.c b/BearSSL-OG/libbearssl/src/int/i31_montmul.c new file mode 100644 index 0000000..758f8f4 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_montmul.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y, + const uint32_t *m, uint32_t m0i) +{ + /* + * Each outer loop iteration computes: + * d <- (d + xu*y + f*m) / 2^31 + * We have xu <= 2^31-1 and f <= 2^31-1. + * Thus, if d <= 2*m-1 on input, then: + * 2*m-1 + 2*(2^31-1)*m <= (2^32)*m-1 + * and the new d value is less than 2*m. + * + * We represent d over 31-bit words, with an extra word 'dh' + * which can thus be only 0 or 1. + */ + size_t len, len4, u, v; + uint32_t dh; + + len = (m[0] + 31) >> 5; + len4 = len & ~(size_t)3; + br_i31_zero(d, m[0]); + dh = 0; + for (u = 0; u < len; u ++) { + /* + * The carry for each operation fits on 32 bits: + * d[v+1] <= 2^31-1 + * xu*y[v+1] <= (2^31-1)*(2^31-1) + * f*m[v+1] <= (2^31-1)*(2^31-1) + * r <= 2^32-1 + * (2^31-1) + 2*(2^31-1)*(2^31-1) + (2^32-1) = 2^63 - 2^31 + * After division by 2^31, the new r is then at most 2^32-1 + * + * Using a 32-bit carry has performance benefits on 32-bit + * systems; however, on 64-bit architectures, we prefer to + * keep the carry (r) in a 64-bit register, thus avoiding some + * "clear high bits" operations. + */ + uint32_t f, xu; +#if BR_64 + uint64_t r; +#else + uint32_t r; +#endif + + xu = x[u + 1]; + f = MUL31_lo((d[1] + MUL31_lo(x[u + 1], y[1])), m0i); + + r = 0; + for (v = 0; v < len4; v += 4) { + uint64_t z; + + z = (uint64_t)d[v + 1] + MUL31(xu, y[v + 1]) + + MUL31(f, m[v + 1]) + r; + r = z >> 31; + d[v + 0] = (uint32_t)z & 0x7FFFFFFF; + z = (uint64_t)d[v + 2] + MUL31(xu, y[v + 2]) + + MUL31(f, m[v + 2]) + r; + r = z >> 31; + d[v + 1] = (uint32_t)z & 0x7FFFFFFF; + z = (uint64_t)d[v + 3] + MUL31(xu, y[v + 3]) + + MUL31(f, m[v + 3]) + r; + r = z >> 31; + d[v + 2] = (uint32_t)z & 0x7FFFFFFF; + z = (uint64_t)d[v + 4] + MUL31(xu, y[v + 4]) + + MUL31(f, m[v + 4]) + r; + r = z >> 31; + d[v + 3] = (uint32_t)z & 0x7FFFFFFF; + } + for (; v < len; v ++) { + uint64_t z; + + z = (uint64_t)d[v + 1] + MUL31(xu, y[v + 1]) + + MUL31(f, m[v + 1]) + r; + r = z >> 31; + d[v] = (uint32_t)z & 0x7FFFFFFF; + } + + /* + * Since the new dh can only be 0 or 1, the addition of + * the old dh with the carry MUST fit on 32 bits, and + * thus can be done into dh itself. + */ + dh += r; + d[len] = dh & 0x7FFFFFFF; + dh >>= 31; + } + + /* + * We must write back the bit length because it was overwritten in + * the loop (not overwriting it would require a test in the loop, + * which would yield bigger and slower code). + */ + d[0] = m[0]; + + /* + * d[] may still be greater than m[] at that point; notably, the + * 'dh' word may be non-zero. + */ + br_i31_sub(d, m, NEQ(dh, 0) | NOT(br_i31_sub(d, m, 0))); +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_mulacc.c b/BearSSL-OG/libbearssl/src/int/i31_mulacc.c new file mode 100644 index 0000000..7410e54 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_mulacc.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + size_t alen, blen, u; + uint32_t dl, dh; + + alen = (a[0] + 31) >> 5; + blen = (b[0] + 31) >> 5; + + /* + * We want to add the two bit lengths, but these are encoded, + * which requires some extra care. + */ + dl = (a[0] & 31) + (b[0] & 31); + dh = (a[0] >> 5) + (b[0] >> 5); + d[0] = (dh << 5) + dl + (~(uint32_t)(dl - 31) >> 31); + + for (u = 0; u < blen; u ++) { + uint32_t f; + size_t v; + + /* + * Carry always fits on 31 bits; we want to keep it in a + * 32-bit register on 32-bit architectures (on a 64-bit + * architecture, cast down from 64 to 32 bits means + * clearing the high bits, which is not free; on a 32-bit + * architecture, the same operation really means ignoring + * the top register, which has negative or zero cost). + */ +#if BR_64 + uint64_t cc; +#else + uint32_t cc; +#endif + + f = b[1 + u]; + cc = 0; + for (v = 0; v < alen; v ++) { + uint64_t z; + + z = (uint64_t)d[1 + u + v] + MUL31(f, a[1 + v]) + cc; + cc = z >> 31; + d[1 + u + v] = (uint32_t)z & 0x7FFFFFFF; + } + d[1 + u + alen] = (uint32_t)cc; + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_muladd.c b/BearSSL-OG/libbearssl/src/int/i31_muladd.c new file mode 100644 index 0000000..eecd9e2 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_muladd.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m) +{ + uint32_t m_bitlen; + unsigned mblr; + size_t u, mlen; + uint32_t a0, a1, b0, hi, g, q, tb; + uint32_t under, over; + uint32_t cc; + + /* + * We can test on the modulus bit length since we accept to + * leak that length. + */ + m_bitlen = m[0]; + if (m_bitlen == 0) { + return; + } + if (m_bitlen <= 31) { + uint32_t lo; + + hi = x[1] >> 1; + lo = (x[1] << 31) | z; + x[1] = br_rem(hi, lo, m[1]); + return; + } + mlen = (m_bitlen + 31) >> 5; + mblr = (unsigned)m_bitlen & 31; + + /* + * Principle: we estimate the quotient (x*2^31+z)/m by + * doing a 64/32 division with the high words. + * + * Let: + * w = 2^31 + * a = (w*a0 + a1) * w^N + a2 + * b = b0 * w^N + b2 + * such that: + * 0 <= a0 < w + * 0 <= a1 < w + * 0 <= a2 < w^N + * w/2 <= b0 < w + * 0 <= b2 < w^N + * a < w*b + * I.e. the two top words of a are a0:a1, the top word of b is + * b0, we ensured that b0 is "full" (high bit set), and a is + * such that the quotient q = a/b fits on one word (0 <= q < w). + * + * If a = b*q + r (with 0 <= r < q), we can estimate q by + * doing an Euclidean division on the top words: + * a0*w+a1 = b0*u + v (with 0 <= v < b0) + * Then the following holds: + * 0 <= u <= w + * u-2 <= q <= u + */ + hi = x[mlen]; + if (mblr == 0) { + a0 = x[mlen]; + memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + x[1] = z; + a1 = x[mlen]; + b0 = m[mlen]; + } else { + a0 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) + & 0x7FFFFFFF; + memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + x[1] = z; + a1 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) + & 0x7FFFFFFF; + b0 = ((m[mlen] << (31 - mblr)) | (m[mlen - 1] >> mblr)) + & 0x7FFFFFFF; + } + + /* + * We estimate a divisor q. If the quotient returned by br_div() + * is g: + * -- If a0 == b0 then g == 0; we want q = 0x7FFFFFFF. + * -- Otherwise: + * -- if g == 0 then we set q = 0; + * -- otherwise, we set q = g - 1. + * The properties described above then ensure that the true + * quotient is q-1, q or q+1. + * + * Take care that a0, a1 and b0 are 31-bit words, not 32-bit. We + * must adjust the parameters to br_div() accordingly. + */ + g = br_div(a0 >> 1, a1 | (a0 << 31), b0); + q = MUX(EQ(a0, b0), 0x7FFFFFFF, MUX(EQ(g, 0), 0, g - 1)); + + /* + * We subtract q*m from x (with the extra high word of value 'hi'). + * Since q may be off by 1 (in either direction), we may have to + * add or subtract m afterwards. + * + * The 'tb' flag will be true (1) at the end of the loop if the + * result is greater than or equal to the modulus (not counting + * 'hi' or the carry). + */ + cc = 0; + tb = 1; + for (u = 1; u <= mlen; u ++) { + uint32_t mw, zw, xw, nxw; + uint64_t zl; + + mw = m[u]; + zl = MUL31(mw, q) + cc; + cc = (uint32_t)(zl >> 31); + zw = (uint32_t)zl & (uint32_t)0x7FFFFFFF; + xw = x[u]; + nxw = xw - zw; + cc += nxw >> 31; + nxw &= 0x7FFFFFFF; + x[u] = nxw; + tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw)); + } + + /* + * If we underestimated q, then either cc < hi (one extra bit + * beyond the top array word), or cc == hi and tb is true (no + * extra bit, but the result is not lower than the modulus). In + * these cases we must subtract m once. + * + * Otherwise, we may have overestimated, which will show as + * cc > hi (thus a negative result). Correction is adding m once. + */ + over = GT(cc, hi); + under = ~over & (tb | LT(cc, hi)); + br_i31_add(x, m, over); + br_i31_sub(x, m, under); +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_ninv31.c b/BearSSL-OG/libbearssl/src/int/i31_ninv31.c new file mode 100644 index 0000000..dd83c96 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_ninv31.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i31_ninv31(uint32_t x) +{ + uint32_t y; + + y = 2 - x; + y *= 2 - y * x; + y *= 2 - y * x; + y *= 2 - y * x; + y *= 2 - y * x; + return MUX(x & 1, -y, 0) & 0x7FFFFFFF; +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_reduce.c b/BearSSL-OG/libbearssl/src/int/i31_reduce.c new file mode 100644 index 0000000..5c9523e --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_reduce.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m) +{ + uint32_t m_bitlen, a_bitlen; + size_t mlen, alen, u; + + m_bitlen = m[0]; + mlen = (m_bitlen + 31) >> 5; + + x[0] = m_bitlen; + if (m_bitlen == 0) { + return; + } + + /* + * If the source is shorter, then simply copy all words from a[] + * and zero out the upper words. + */ + a_bitlen = a[0]; + alen = (a_bitlen + 31) >> 5; + if (a_bitlen < m_bitlen) { + memcpy(x + 1, a + 1, alen * sizeof *a); + for (u = alen; u < mlen; u ++) { + x[u + 1] = 0; + } + return; + } + + /* + * The source length is at least equal to that of the modulus. + * We must thus copy N-1 words, and input the remaining words + * one by one. + */ + memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); + x[mlen] = 0; + for (u = 1 + alen - mlen; u > 0; u --) { + br_i31_muladd_small(x, a[u], m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_rshift.c b/BearSSL-OG/libbearssl/src/int/i31_rshift.c new file mode 100644 index 0000000..db6ba0b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_rshift.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_rshift(uint32_t *x, int count) +{ + size_t u, len; + uint32_t r; + + len = (x[0] + 31) >> 5; + if (len == 0) { + return; + } + r = x[1] >> count; + for (u = 2; u <= len; u ++) { + uint32_t w; + + w = x[u]; + x[u - 1] = ((w << (31 - count)) | r) & 0x7FFFFFFF; + r = w >> count; + } + x[len] = r; +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_sub.c b/BearSSL-OG/libbearssl/src/int/i31_sub.c new file mode 100644 index 0000000..3910895 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_sub.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl) +{ + uint32_t cc; + size_t u, m; + + cc = 0; + m = (a[0] + 63) >> 5; + for (u = 1; u < m; u ++) { + uint32_t aw, bw, naw; + + aw = a[u]; + bw = b[u]; + naw = aw - bw - cc; + cc = naw >> 31; + a[u] = MUX(ctl, naw & 0x7FFFFFFF, aw); + } + return cc; +} diff --git a/BearSSL-OG/libbearssl/src/int/i31_tmont.c b/BearSSL-OG/libbearssl/src/int/i31_tmont.c new file mode 100644 index 0000000..4798ff6 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i31_tmont.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i31_to_monty(uint32_t *x, const uint32_t *m) +{ + uint32_t k; + + for (k = (m[0] + 31) >> 5; k > 0; k --) { + br_i31_muladd_small(x, 0, m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_add.c b/BearSSL-OG/libbearssl/src/int/i32_add.c new file mode 100644 index 0000000..620baff --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_add.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl) +{ + uint32_t cc; + size_t u, m; + + cc = 0; + m = (a[0] + 63) >> 5; + for (u = 1; u < m; u ++) { + uint32_t aw, bw, naw; + + aw = a[u]; + bw = b[u]; + naw = aw + bw + cc; + + /* + * Carry is 1 if naw < aw. Carry is also 1 if naw == aw + * AND the carry was already 1. + */ + cc = (cc & EQ(naw, aw)) | LT(naw, aw); + a[u] = MUX(ctl, naw, aw); + } + return cc; +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_bitlen.c b/BearSSL-OG/libbearssl/src/int/i32_bitlen.c new file mode 100644 index 0000000..40ce9fa --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_bitlen.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i32_bit_length(uint32_t *x, size_t xlen) +{ + uint32_t tw, twk; + + tw = 0; + twk = 0; + while (xlen -- > 0) { + uint32_t w, c; + + c = EQ(tw, 0); + w = x[xlen]; + tw = MUX(c, w, tw); + twk = MUX(c, (uint32_t)xlen, twk); + } + return (twk << 5) + BIT_LENGTH(tw); +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_decmod.c b/BearSSL-OG/libbearssl/src/int/i32_decmod.c new file mode 100644 index 0000000..a859af1 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_decmod.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i32_decode_mod(uint32_t *x, const void *src, size_t len, const uint32_t *m) +{ + const unsigned char *buf; + uint32_t r; + size_t u, v, mlen; + + buf = src; + + /* + * First pass: determine whether the value fits. The 'r' value + * will contain the comparison result, as 0x00000000 (value is + * equal to the modulus), 0x00000001 (value is greater than the + * modulus), or 0xFFFFFFFF (value is lower than the modulus). + */ + mlen = (m[0] + 7) >> 3; + r = 0; + for (u = (mlen > len) ? mlen : len; u > 0; u --) { + uint32_t mb, xb; + + v = u - 1; + if (v >= mlen) { + mb = 0; + } else { + mb = (m[1 + (v >> 2)] >> ((v & 3) << 3)) & 0xFF; + } + if (v >= len) { + xb = 0; + } else { + xb = buf[len - u]; + } + r = MUX(EQ(r, 0), (uint32_t)CMP(xb, mb), r); + } + + /* + * Only r == 0xFFFFFFFF is acceptable. We want to set r to 0xFF if + * the value fits, 0x00 otherwise. + */ + r >>= 24; + br_i32_zero(x, m[0]); + u = (mlen > len) ? len : mlen; + while (u > 0) { + uint32_t xb; + + xb = buf[len - u] & r; + u --; + x[1 + (u >> 2)] |= xb << ((u & 3) << 3); + } + return r >> 7; +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_decode.c b/BearSSL-OG/libbearssl/src/int/i32_decode.c new file mode 100644 index 0000000..f289038 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_decode.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_decode(uint32_t *x, const void *src, size_t len) +{ + const unsigned char *buf; + size_t u, v; + + buf = src; + u = len; + v = 1; + for (;;) { + if (u < 4) { + uint32_t w; + + if (u < 2) { + if (u == 0) { + break; + } else { + w = buf[0]; + } + } else { + if (u == 2) { + w = br_dec16be(buf); + } else { + w = ((uint32_t)buf[0] << 16) + | br_dec16be(buf + 1); + } + } + x[v ++] = w; + break; + } else { + u -= 4; + x[v ++] = br_dec32be(buf + u); + } + } + x[0] = br_i32_bit_length(x + 1, v - 1); +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_decred.c b/BearSSL-OG/libbearssl/src/int/i32_decred.c new file mode 100644 index 0000000..dc476db --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_decred.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_decode_reduce(uint32_t *x, + const void *src, size_t len, const uint32_t *m) +{ + uint32_t m_bitlen; + size_t mblen, k, q; + const unsigned char *buf; + + m_bitlen = m[0]; + + /* + * Special case for an invalid modulus. + */ + if (m_bitlen == 0) { + x[0] = 0; + return; + } + + /* + * Clear the destination. + */ + br_i32_zero(x, m_bitlen); + + /* + * First decode directly as many bytes as possible without + * reduction, taking care to leave a number of bytes which + * is a multiple of 4. + */ + mblen = (m_bitlen + 7) >> 3; + k = mblen - 1; + + /* + * Up to k bytes can be safely decoded. + */ + if (k >= len) { + br_i32_decode(x, src, len); + x[0] = m_bitlen; + return; + } + + /* + * We want to first inject some bytes with direct decoding, + * then extra bytes by whole 32-bit words. First compute + * the size that should be injected that way. + */ + buf = src; + q = (len - k + 3) & ~(size_t)3; + + /* + * It may happen that this is more than what we already have + * (by at most 3 bytes). Such a case may happen only with + * a very short modulus. In that case, we must process the first + * bytes "manually". + */ + if (q > len) { + int i; + uint32_t w; + + w = 0; + for (i = 0; i < 4; i ++) { + w <<= 8; + if (q <= len) { + w |= buf[len - q]; + } + q --; + } + br_i32_muladd_small(x, w, m); + } else { + br_i32_decode(x, buf, len - q); + x[0] = m_bitlen; + } + + /* + * At that point, we have exactly q bytes to inject, and q is + * a multiple of 4. + */ + for (k = len - q; k < len; k += 4) { + br_i32_muladd_small(x, br_dec32be(buf + k), m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_div32.c b/BearSSL-OG/libbearssl/src/int/i32_div32.c new file mode 100644 index 0000000..d8b8023 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_div32.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r) +{ + /* TODO: optimize this */ + uint32_t q; + uint32_t ch, cf; + int k; + + q = 0; + ch = EQ(hi, d); + hi = MUX(ch, 0, hi); + for (k = 31; k > 0; k --) { + int j; + uint32_t w, ctl, hi2, lo2; + + j = 32 - k; + w = (hi << j) | (lo >> k); + ctl = GE(w, d) | (hi >> k); + hi2 = (w - d) >> j; + lo2 = lo - (d << k); + hi = MUX(ctl, hi2, hi); + lo = MUX(ctl, lo2, lo); + q |= ctl << k; + } + cf = GE(lo, d) | hi; + q |= cf; + *r = MUX(cf, lo - d, lo); + return q; +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_encode.c b/BearSSL-OG/libbearssl/src/int/i32_encode.c new file mode 100644 index 0000000..303652f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_encode.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_encode(void *dst, size_t len, const uint32_t *x) +{ + unsigned char *buf; + size_t k; + + buf = dst; + + /* + * Compute the announced size of x in bytes; extra bytes are + * filled with zeros. + */ + k = (x[0] + 7) >> 3; + while (len > k) { + *buf ++ = 0; + len --; + } + + /* + * Now we use k as index within x[]. That index starts at 1; + * we initialize it to the topmost complete word, and process + * any remaining incomplete word. + */ + k = (len + 3) >> 2; + switch (len & 3) { + case 3: + *buf ++ = x[k] >> 16; + /* fall through */ + case 2: + *buf ++ = x[k] >> 8; + /* fall through */ + case 1: + *buf ++ = x[k]; + k --; + } + + /* + * Encode all complete words. + */ + while (k > 0) { + br_enc32be(buf, x[k]); + k --; + buf += 4; + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_fmont.c b/BearSSL-OG/libbearssl/src/int/i32_fmont.c new file mode 100644 index 0000000..dc1c934 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_fmont.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i) +{ + size_t len, u, v; + + len = (m[0] + 31) >> 5; + for (u = 0; u < len; u ++) { + uint32_t f; + uint64_t cc; + + f = x[1] * m0i; + cc = 0; + for (v = 0; v < len; v ++) { + uint64_t z; + + z = (uint64_t)x[v + 1] + MUL(f, m[v + 1]) + cc; + cc = z >> 32; + if (v != 0) { + x[v] = (uint32_t)z; + } + } + x[len] = (uint32_t)cc; + } + + /* + * We may have to do an extra subtraction, but only if the + * value in x[] is indeed greater than or equal to that of m[], + * which is why we must do two calls (first call computes the + * carry, second call performs the subtraction only if the carry + * is 0). + */ + br_i32_sub(x, m, NOT(br_i32_sub(x, m, 0))); +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_iszero.c b/BearSSL-OG/libbearssl/src/int/i32_iszero.c new file mode 100644 index 0000000..659df7f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_iszero.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i32_iszero(const uint32_t *x) +{ + uint32_t z; + size_t u; + + z = 0; + for (u = (x[0] + 31) >> 5; u > 0; u --) { + z |= x[u]; + } + return ~(z | -z) >> 31; +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_modpow.c b/BearSSL-OG/libbearssl/src/int/i32_modpow.c new file mode 100644 index 0000000..034aba0 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_modpow.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_modpow(uint32_t *x, + const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2) +{ + size_t mlen; + uint32_t k; + + /* + * 'mlen' is the length of m[] expressed in bytes (including + * the "bit length" first field). + */ + mlen = ((m[0] + 63) >> 5) * sizeof m[0]; + + /* + * Throughout the algorithm: + * -- t1[] is in Montgomery representation; it contains x, x^2, + * x^4, x^8... + * -- The result is accumulated, in normal representation, in + * the x[] array. + * -- t2[] is used as destination buffer for each multiplication. + * + * Note that there is no need to call br_i32_from_monty(). + */ + memcpy(t1, x, mlen); + br_i32_to_monty(t1, m); + br_i32_zero(x, m[0]); + x[1] = 1; + for (k = 0; k < ((uint32_t)elen << 3); k ++) { + uint32_t ctl; + + ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1; + br_i32_montymul(t2, x, t1, m, m0i); + CCOPY(ctl, x, t2, mlen); + br_i32_montymul(t2, t1, t1, m, m0i); + memcpy(t1, t2, mlen); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_montmul.c b/BearSSL-OG/libbearssl/src/int/i32_montmul.c new file mode 100644 index 0000000..7edb376 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_montmul.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y, + const uint32_t *m, uint32_t m0i) +{ + size_t len, u, v; + uint64_t dh; + + len = (m[0] + 31) >> 5; + br_i32_zero(d, m[0]); + dh = 0; + for (u = 0; u < len; u ++) { + uint32_t f, xu; + uint64_t r1, r2, zh; + + xu = x[u + 1]; + f = (d[1] + x[u + 1] * y[1]) * m0i; + r1 = 0; + r2 = 0; + for (v = 0; v < len; v ++) { + uint64_t z; + uint32_t t; + + z = (uint64_t)d[v + 1] + MUL(xu, y[v + 1]) + r1; + r1 = z >> 32; + t = (uint32_t)z; + z = (uint64_t)t + MUL(f, m[v + 1]) + r2; + r2 = z >> 32; + if (v != 0) { + d[v] = (uint32_t)z; + } + } + zh = dh + r1 + r2; + d[len] = (uint32_t)zh; + dh = zh >> 32; + } + + /* + * d[] may still be greater than m[] at that point; notably, the + * 'dh' word may be non-zero. + */ + br_i32_sub(d, m, NEQ(dh, 0) | NOT(br_i32_sub(d, m, 0))); +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_mulacc.c b/BearSSL-OG/libbearssl/src/int/i32_mulacc.c new file mode 100644 index 0000000..55da385 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_mulacc.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b) +{ + size_t alen, blen, u; + + alen = (a[0] + 31) >> 5; + blen = (b[0] + 31) >> 5; + d[0] = a[0] + b[0]; + for (u = 0; u < blen; u ++) { + uint32_t f; + size_t v; +#if BR_64 + uint64_t cc; +#else + uint32_t cc; +#endif + + f = b[1 + u]; + cc = 0; + for (v = 0; v < alen; v ++) { + uint64_t z; + + z = (uint64_t)d[1 + u + v] + MUL(f, a[1 + v]) + cc; + cc = z >> 32; + d[1 + u + v] = (uint32_t)z; + } + d[1 + u + alen] = (uint32_t)cc; + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_muladd.c b/BearSSL-OG/libbearssl/src/int/i32_muladd.c new file mode 100644 index 0000000..dd526ad --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_muladd.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m) +{ + uint32_t m_bitlen; + size_t u, mlen; + uint32_t a0, a1, b0, hi, g, q, tb; + uint32_t chf, clow, under, over; + uint64_t cc; + + /* + * We can test on the modulus bit length since we accept to + * leak that length. + */ + m_bitlen = m[0]; + if (m_bitlen == 0) { + return; + } + if (m_bitlen <= 32) { + x[1] = br_rem(x[1], z, m[1]); + return; + } + mlen = (m_bitlen + 31) >> 5; + + /* + * Principle: we estimate the quotient (x*2^32+z)/m by + * doing a 64/32 division with the high words. + * + * Let: + * w = 2^32 + * a = (w*a0 + a1) * w^N + a2 + * b = b0 * w^N + b2 + * such that: + * 0 <= a0 < w + * 0 <= a1 < w + * 0 <= a2 < w^N + * w/2 <= b0 < w + * 0 <= b2 < w^N + * a < w*b + * I.e. the two top words of a are a0:a1, the top word of b is + * b0, we ensured that b0 is "full" (high bit set), and a is + * such that the quotient q = a/b fits on one word (0 <= q < w). + * + * If a = b*q + r (with 0 <= r < q), we can estimate q by + * doing an Euclidean division on the top words: + * a0*w+a1 = b0*u + v (with 0 <= v < w) + * Then the following holds: + * 0 <= u <= w + * u-2 <= q <= u + */ + a0 = br_i32_word(x, m_bitlen - 32); + hi = x[mlen]; + memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + x[1] = z; + a1 = br_i32_word(x, m_bitlen - 32); + b0 = br_i32_word(m, m_bitlen - 32); + + /* + * We estimate a divisor q. If the quotient returned by br_div() + * is g: + * -- If a0 == b0 then g == 0; we want q = 0xFFFFFFFF. + * -- Otherwise: + * -- if g == 0 then we set q = 0; + * -- otherwise, we set q = g - 1. + * The properties described above then ensure that the true + * quotient is q-1, q or q+1. + */ + g = br_div(a0, a1, b0); + q = MUX(EQ(a0, b0), 0xFFFFFFFF, MUX(EQ(g, 0), 0, g - 1)); + + /* + * We subtract q*m from x (with the extra high word of value 'hi'). + * Since q may be off by 1 (in either direction), we may have to + * add or subtract m afterwards. + * + * The 'tb' flag will be true (1) at the end of the loop if the + * result is greater than or equal to the modulus (not counting + * 'hi' or the carry). + */ + cc = 0; + tb = 1; + for (u = 1; u <= mlen; u ++) { + uint32_t mw, zw, xw, nxw; + uint64_t zl; + + mw = m[u]; + zl = MUL(mw, q) + cc; + cc = (uint32_t)(zl >> 32); + zw = (uint32_t)zl; + xw = x[u]; + nxw = xw - zw; + cc += (uint64_t)GT(nxw, xw); + x[u] = nxw; + tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw)); + } + + /* + * If we underestimated q, then either cc < hi (one extra bit + * beyond the top array word), or cc == hi and tb is true (no + * extra bit, but the result is not lower than the modulus). In + * these cases we must subtract m once. + * + * Otherwise, we may have overestimated, which will show as + * cc > hi (thus a negative result). Correction is adding m once. + */ + chf = (uint32_t)(cc >> 32); + clow = (uint32_t)cc; + over = chf | GT(clow, hi); + under = ~over & (tb | (~chf & LT(clow, hi))); + br_i32_add(x, m, over); + br_i32_sub(x, m, under); +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_ninv32.c b/BearSSL-OG/libbearssl/src/int/i32_ninv32.c new file mode 100644 index 0000000..6564434 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_ninv32.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i32_ninv32(uint32_t x) +{ + uint32_t y; + + y = 2 - x; + y *= 2 - y * x; + y *= 2 - y * x; + y *= 2 - y * x; + y *= 2 - y * x; + return MUX(x & 1, -y, 0); +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_reduce.c b/BearSSL-OG/libbearssl/src/int/i32_reduce.c new file mode 100644 index 0000000..90fff09 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_reduce.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m) +{ + uint32_t m_bitlen, a_bitlen; + size_t mlen, alen, u; + + m_bitlen = m[0]; + mlen = (m_bitlen + 31) >> 5; + + x[0] = m_bitlen; + if (m_bitlen == 0) { + return; + } + + /* + * If the source is shorter, then simply copy all words from a[] + * and zero out the upper words. + */ + a_bitlen = a[0]; + alen = (a_bitlen + 31) >> 5; + if (a_bitlen < m_bitlen) { + memcpy(x + 1, a + 1, alen * sizeof *a); + for (u = alen; u < mlen; u ++) { + x[u + 1] = 0; + } + return; + } + + /* + * The source length is at least equal to that of the modulus. + * We must thus copy N-1 words, and input the remaining words + * one by one. + */ + memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); + x[mlen] = 0; + for (u = 1 + alen - mlen; u > 0; u --) { + br_i32_muladd_small(x, a[u], m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_sub.c b/BearSSL-OG/libbearssl/src/int/i32_sub.c new file mode 100644 index 0000000..9c50023 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_sub.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl) +{ + uint32_t cc; + size_t u, m; + + cc = 0; + m = (a[0] + 63) >> 5; + for (u = 1; u < m; u ++) { + uint32_t aw, bw, naw; + + aw = a[u]; + bw = b[u]; + naw = aw - bw - cc; + + /* + * Carry is 1 if naw > aw. Carry is 1 also if naw == aw + * AND the carry was already 1. + */ + cc = (cc & EQ(naw, aw)) | GT(naw, aw); + a[u] = MUX(ctl, naw, aw); + } + return cc; +} diff --git a/BearSSL-OG/libbearssl/src/int/i32_tmont.c b/BearSSL-OG/libbearssl/src/int/i32_tmont.c new file mode 100644 index 0000000..058cd88 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i32_tmont.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_i32_to_monty(uint32_t *x, const uint32_t *m) +{ + uint32_t k; + + for (k = (m[0] + 31) >> 5; k > 0; k --) { + br_i32_muladd_small(x, 0, m); + } +} diff --git a/BearSSL-OG/libbearssl/src/int/i62_modpow2.c b/BearSSL-OG/libbearssl/src/int/i62_modpow2.c new file mode 100644 index 0000000..2db537f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/int/i62_modpow2.c @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +#if BR_INT128 + +/* + * Compute x*y+v1+v2. Operands are 64-bit, and result is 128-bit, with + * high word in "hi" and low word in "lo". + */ +#define FMA1(hi, lo, x, y, v1, v2) do { \ + unsigned __int128 fmaz; \ + fmaz = (unsigned __int128)(x) * (unsigned __int128)(y) \ + + (unsigned __int128)(v1) + (unsigned __int128)(v2); \ + (hi) = (uint64_t)(fmaz >> 64); \ + (lo) = (uint64_t)fmaz; \ + } while (0) + +/* + * Compute x1*y1+x2*y2+v1+v2. Operands are 64-bit, and result is 128-bit, + * with high word in "hi" and low word in "lo". + * + * Callers should ensure that the two inner products, and the v1 and v2 + * operands, are multiple of 4 (this is not used by this specific definition + * but may help other implementations). + */ +#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \ + unsigned __int128 fmaz; \ + fmaz = (unsigned __int128)(x1) * (unsigned __int128)(y1) \ + + (unsigned __int128)(x2) * (unsigned __int128)(y2) \ + + (unsigned __int128)(v1) + (unsigned __int128)(v2); \ + (hi) = (uint64_t)(fmaz >> 64); \ + (lo) = (uint64_t)fmaz; \ + } while (0) + +#elif BR_UMUL128 + +#include + +#define FMA1(hi, lo, x, y, v1, v2) do { \ + uint64_t fmahi, fmalo; \ + unsigned char fmacc; \ + fmalo = _umul128((x), (y), &fmahi); \ + fmacc = _addcarry_u64(0, fmalo, (v1), &fmalo); \ + _addcarry_u64(fmacc, fmahi, 0, &fmahi); \ + fmacc = _addcarry_u64(0, fmalo, (v2), &(lo)); \ + _addcarry_u64(fmacc, fmahi, 0, &(hi)); \ + } while (0) + +/* + * Normally we should use _addcarry_u64() for FMA2 too, but it makes + * Visual Studio crash. Instead we use this version, which leverages + * the fact that the vx operands, and the products, are multiple of 4. + * This is unfortunately slower. + */ +#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \ + uint64_t fma1hi, fma1lo; \ + uint64_t fma2hi, fma2lo; \ + uint64_t fmatt; \ + fma1lo = _umul128((x1), (y1), &fma1hi); \ + fma2lo = _umul128((x2), (y2), &fma2hi); \ + fmatt = (fma1lo >> 2) + (fma2lo >> 2) \ + + ((v1) >> 2) + ((v2) >> 2); \ + (lo) = fmatt << 2; \ + (hi) = fma1hi + fma2hi + (fmatt >> 62); \ + } while (0) + +/* + * The FMA2 macro definition we would prefer to use, but it triggers + * an internal compiler error in Visual Studio 2015. + * +#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \ + uint64_t fma1hi, fma1lo; \ + uint64_t fma2hi, fma2lo; \ + unsigned char fmacc; \ + fma1lo = _umul128((x1), (y1), &fma1hi); \ + fma2lo = _umul128((x2), (y2), &fma2hi); \ + fmacc = _addcarry_u64(0, fma1lo, (v1), &fma1lo); \ + _addcarry_u64(fmacc, fma1hi, 0, &fma1hi); \ + fmacc = _addcarry_u64(0, fma2lo, (v2), &fma2lo); \ + _addcarry_u64(fmacc, fma2hi, 0, &fma2hi); \ + fmacc = _addcarry_u64(0, fma1lo, fma2lo, &(lo)); \ + _addcarry_u64(fmacc, fma1hi, fma2hi, &(hi)); \ + } while (0) + */ + +#endif + +#define MASK62 ((uint64_t)0x3FFFFFFFFFFFFFFF) +#define MUL62_lo(x, y) (((uint64_t)(x) * (uint64_t)(y)) & MASK62) + +/* + * Subtract b from a, and return the final carry. If 'ctl32' is 0, then + * a[] is kept unmodified, but the final carry is still computed and + * returned. + */ +static uint32_t +i62_sub(uint64_t *a, const uint64_t *b, size_t num, uint32_t ctl32) +{ + uint64_t cc, mask; + size_t u; + + cc = 0; + ctl32 = -ctl32; + mask = (uint64_t)ctl32 | ((uint64_t)ctl32 << 32); + for (u = 0; u < num; u ++) { + uint64_t aw, bw, dw; + + aw = a[u]; + bw = b[u]; + dw = aw - bw - cc; + cc = dw >> 63; + dw &= MASK62; + a[u] = aw ^ (mask & (dw ^ aw)); + } + return (uint32_t)cc; +} + +/* + * Montgomery multiplication, over arrays of 62-bit values. The + * destination array (d) must be distinct from the other operands + * (x, y and m). All arrays are in little-endian format (least + * significant word comes first) over 'num' words. + */ +static void +montymul(uint64_t *d, const uint64_t *x, const uint64_t *y, + const uint64_t *m, size_t num, uint64_t m0i) +{ + uint64_t dh; + size_t u, num4; + + num4 = 1 + ((num - 1) & ~(size_t)3); + memset(d, 0, num * sizeof *d); + dh = 0; + for (u = 0; u < num; u ++) { + size_t v; + uint64_t f, xu; + uint64_t r, zh; + uint64_t hi, lo; + + xu = x[u] << 2; + f = MUL62_lo(d[0] + MUL62_lo(x[u], y[0]), m0i) << 2; + + FMA2(hi, lo, xu, y[0], f, m[0], d[0] << 2, 0); + r = hi; + + for (v = 1; v < num4; v += 4) { + FMA2(hi, lo, xu, y[v + 0], + f, m[v + 0], d[v + 0] << 2, r << 2); + r = hi + (r >> 62); + d[v - 1] = lo >> 2; + FMA2(hi, lo, xu, y[v + 1], + f, m[v + 1], d[v + 1] << 2, r << 2); + r = hi + (r >> 62); + d[v + 0] = lo >> 2; + FMA2(hi, lo, xu, y[v + 2], + f, m[v + 2], d[v + 2] << 2, r << 2); + r = hi + (r >> 62); + d[v + 1] = lo >> 2; + FMA2(hi, lo, xu, y[v + 3], + f, m[v + 3], d[v + 3] << 2, r << 2); + r = hi + (r >> 62); + d[v + 2] = lo >> 2; + } + for (; v < num; v ++) { + FMA2(hi, lo, xu, y[v], f, m[v], d[v] << 2, r << 2); + r = hi + (r >> 62); + d[v - 1] = lo >> 2; + } + + zh = dh + r; + d[num - 1] = zh & MASK62; + dh = zh >> 62; + } + i62_sub(d, m, num, (uint32_t)dh | NOT(i62_sub(d, m, num, 0))); +} + +/* + * Conversion back from Montgomery representation. + */ +static void +frommonty(uint64_t *x, const uint64_t *m, size_t num, uint64_t m0i) +{ + size_t u, v; + + for (u = 0; u < num; u ++) { + uint64_t f, cc; + + f = MUL62_lo(x[0], m0i) << 2; + cc = 0; + for (v = 0; v < num; v ++) { + uint64_t hi, lo; + + FMA1(hi, lo, f, m[v], x[v] << 2, cc); + cc = hi << 2; + if (v != 0) { + x[v - 1] = lo >> 2; + } + } + x[num - 1] = cc >> 2; + } + i62_sub(x, m, num, NOT(i62_sub(x, m, num, 0))); +} + +/* see inner.h */ +uint32_t +br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, + const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen) +{ + size_t u, mw31num, mw62num; + uint64_t *x, *m, *t1, *t2; + uint64_t m0i; + uint32_t acc; + int win_len, acc_len; + + /* + * Get modulus size, in words. + */ + mw31num = (m31[0] + 31) >> 5; + mw62num = (mw31num + 1) >> 1; + + /* + * In order to apply this function, we must have enough room to + * copy the operand and modulus into the temporary array, along + * with at least two temporaries. If there is not enough room, + * switch to br_i31_modpow(). We also use br_i31_modpow() if the + * modulus length is not at least four words (94 bits or more). + */ + if (mw31num < 4 || (mw62num << 2) > twlen) { + /* + * We assume here that we can split an aligned uint64_t + * into two properly aligned uint32_t. Since both types + * are supposed to have an exact width with no padding, + * then this property must hold. + */ + size_t txlen; + + txlen = mw31num + 1; + if (twlen < txlen) { + return 0; + } + br_i31_modpow(x31, e, elen, m31, m0i31, + (uint32_t *)tmp, (uint32_t *)tmp + txlen); + return 1; + } + + /* + * Convert x to Montgomery representation: this means that + * we replace x with x*2^z mod m, where z is the smallest multiple + * of the word size such that 2^z >= m. We want to reuse the 31-bit + * functions here (for constant-time operation), but we need z + * for a 62-bit word size. + */ + for (u = 0; u < mw62num; u ++) { + br_i31_muladd_small(x31, 0, m31); + br_i31_muladd_small(x31, 0, m31); + } + + /* + * Assemble operands into arrays of 62-bit words. Note that + * all the arrays of 62-bit words that we will handle here + * are without any leading size word. + * + * We also adjust tmp and twlen to account for the words used + * for these extra arrays. + */ + m = tmp; + x = tmp + mw62num; + tmp += (mw62num << 1); + twlen -= (mw62num << 1); + for (u = 0; u < mw31num; u += 2) { + size_t v; + + v = u >> 1; + if ((u + 1) == mw31num) { + m[v] = (uint64_t)m31[u + 1]; + x[v] = (uint64_t)x31[u + 1]; + } else { + m[v] = (uint64_t)m31[u + 1] + + ((uint64_t)m31[u + 2] << 31); + x[v] = (uint64_t)x31[u + 1] + + ((uint64_t)x31[u + 2] << 31); + } + } + + /* + * Compute window size. We support windows up to 5 bits; for a + * window of size k bits, we need 2^k+1 temporaries (for k = 1, + * we use special code that uses only 2 temporaries). + */ + for (win_len = 5; win_len > 1; win_len --) { + if ((((uint32_t)1 << win_len) + 1) * mw62num <= twlen) { + break; + } + } + + t1 = tmp; + t2 = tmp + mw62num; + + /* + * Compute m0i, which is equal to -(1/m0) mod 2^62. We were + * provided with m0i31, which already fulfills this property + * modulo 2^31; the single expression below is then sufficient. + */ + m0i = (uint64_t)m0i31; + m0i = MUL62_lo(m0i, (uint64_t)2 + MUL62_lo(m0i, m[0])); + + /* + * Compute window contents. If the window has size one bit only, + * then t2 is set to x; otherwise, t2[0] is left untouched, and + * t2[k] is set to x^k (for k >= 1). + */ + if (win_len == 1) { + memcpy(t2, x, mw62num * sizeof *x); + } else { + uint64_t *base; + + memcpy(t2 + mw62num, x, mw62num * sizeof *x); + base = t2 + mw62num; + for (u = 2; u < ((unsigned)1 << win_len); u ++) { + montymul(base + mw62num, base, x, m, mw62num, m0i); + base += mw62num; + } + } + + /* + * Set x to 1, in Montgomery representation. We again use the + * 31-bit code. + */ + br_i31_zero(x31, m31[0]); + x31[(m31[0] + 31) >> 5] = 1; + br_i31_muladd_small(x31, 0, m31); + if (mw31num & 1) { + br_i31_muladd_small(x31, 0, m31); + } + for (u = 0; u < mw31num; u += 2) { + size_t v; + + v = u >> 1; + if ((u + 1) == mw31num) { + x[v] = (uint64_t)x31[u + 1]; + } else { + x[v] = (uint64_t)x31[u + 1] + + ((uint64_t)x31[u + 2] << 31); + } + } + + /* + * We process bits from most to least significant. At each + * loop iteration, we have acc_len bits in acc. + */ + acc = 0; + acc_len = 0; + while (acc_len > 0 || elen > 0) { + int i, k; + uint32_t bits; + uint64_t mask1, mask2; + + /* + * Get the next bits. + */ + k = win_len; + if (acc_len < win_len) { + if (elen > 0) { + acc = (acc << 8) | *e ++; + elen --; + acc_len += 8; + } else { + k = acc_len; + } + } + bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1); + acc_len -= k; + + /* + * We could get exactly k bits. Compute k squarings. + */ + for (i = 0; i < k; i ++) { + montymul(t1, x, x, m, mw62num, m0i); + memcpy(x, t1, mw62num * sizeof *x); + } + + /* + * Window lookup: we want to set t2 to the window + * lookup value, assuming the bits are non-zero. If + * the window length is 1 bit only, then t2 is + * already set; otherwise, we do a constant-time lookup. + */ + if (win_len > 1) { + uint64_t *base; + + memset(t2, 0, mw62num * sizeof *t2); + base = t2 + mw62num; + for (u = 1; u < ((uint32_t)1 << k); u ++) { + uint64_t mask; + size_t v; + + mask = -(uint64_t)EQ(u, bits); + for (v = 0; v < mw62num; v ++) { + t2[v] |= mask & base[v]; + } + base += mw62num; + } + } + + /* + * Multiply with the looked-up value. We keep the product + * only if the exponent bits are not all-zero. + */ + montymul(t1, x, t2, m, mw62num, m0i); + mask1 = -(uint64_t)EQ(bits, 0); + mask2 = ~mask1; + for (u = 0; u < mw62num; u ++) { + x[u] = (mask1 & x[u]) | (mask2 & t1[u]); + } + } + + /* + * Convert back from Montgomery representation. + */ + frommonty(x, m, mw62num, m0i); + + /* + * Convert result into 31-bit words. + */ + for (u = 0; u < mw31num; u += 2) { + uint64_t zw; + + zw = x[u >> 1]; + x31[u + 1] = (uint32_t)zw & 0x7FFFFFFF; + if ((u + 1) < mw31num) { + x31[u + 2] = (uint32_t)(zw >> 31); + } + } + return 1; +} + +#else + +/* see inner.h */ +uint32_t +br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, + const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen) +{ + size_t mwlen; + + mwlen = (m31[0] + 63) >> 5; + if (twlen < mwlen) { + return 0; + } + return br_i31_modpow_opt(x31, e, elen, m31, m0i31, + (uint32_t *)tmp, twlen << 1); +} + +#endif + +/* see inner.h */ +uint32_t +br_i62_modpow_opt_as_i31(uint32_t *x31, const unsigned char *e, size_t elen, + const uint32_t *m31, uint32_t m0i31, uint32_t *tmp, size_t twlen) +{ + /* + * As documented, this function expects the 'tmp' argument to be + * 64-bit aligned. This is OK since this function is internal (it + * is not part of BearSSL's public API). + */ + return br_i62_modpow_opt(x31, e, elen, m31, m0i31, + (uint64_t *)tmp, twlen >> 1); +} diff --git a/BearSSL-OG/libbearssl/src/kdf/hkdf.c b/BearSSL-OG/libbearssl/src/kdf/hkdf.c new file mode 100644 index 0000000..6a36851 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/kdf/hkdf.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +const unsigned char br_hkdf_no_salt = 0; + +/* see bearssl_kdf.h */ +void +br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable, + const void *salt, size_t salt_len) +{ + br_hmac_key_context kc; + unsigned char tmp[64]; + + if (salt == BR_HKDF_NO_SALT) { + salt = tmp; + salt_len = br_digest_size(digest_vtable); + memset(tmp, 0, salt_len); + } + br_hmac_key_init(&kc, digest_vtable, salt, salt_len); + br_hmac_init(&hc->u.hmac_ctx, &kc, 0); + hc->dig_len = br_hmac_size(&hc->u.hmac_ctx); +} + +/* see bearssl_kdf.h */ +void +br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len) +{ + br_hmac_update(&hc->u.hmac_ctx, ikm, ikm_len); +} + +/* see bearssl_kdf.h */ +void +br_hkdf_flip(br_hkdf_context *hc) +{ + unsigned char tmp[64]; + + br_hmac_out(&hc->u.hmac_ctx, tmp); + br_hmac_key_init(&hc->u.prk_ctx, + br_hmac_get_digest(&hc->u.hmac_ctx), tmp, hc->dig_len); + hc->ptr = hc->dig_len; + hc->chunk_num = 0; +} + +/* see bearssl_kdf.h */ +size_t +br_hkdf_produce(br_hkdf_context *hc, + const void *info, size_t info_len, void *out, size_t out_len) +{ + size_t tlen; + + tlen = 0; + while (out_len > 0) { + size_t clen; + + if (hc->ptr == hc->dig_len) { + br_hmac_context hmac_ctx; + unsigned char x; + + hc->chunk_num ++; + if (hc->chunk_num == 256) { + return tlen; + } + x = hc->chunk_num; + br_hmac_init(&hmac_ctx, &hc->u.prk_ctx, 0); + if (x != 1) { + br_hmac_update(&hmac_ctx, hc->buf, hc->dig_len); + } + br_hmac_update(&hmac_ctx, info, info_len); + br_hmac_update(&hmac_ctx, &x, 1); + br_hmac_out(&hmac_ctx, hc->buf); + hc->ptr = 0; + } + clen = hc->dig_len - hc->ptr; + if (clen > out_len) { + clen = out_len; + } + memcpy(out, hc->buf + hc->ptr, clen); + out = (unsigned char *)out + clen; + out_len -= clen; + hc->ptr += clen; + tlen += clen; + } + return tlen; +} diff --git a/BearSSL-OG/libbearssl/src/kdf/shake.c b/BearSSL-OG/libbearssl/src/kdf/shake.c new file mode 100644 index 0000000..80d7176 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/kdf/shake.c @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * Round constants. + */ +static const uint64_t RC[] = { + 0x0000000000000001, 0x0000000000008082, + 0x800000000000808A, 0x8000000080008000, + 0x000000000000808B, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, + 0x000000000000008A, 0x0000000000000088, + 0x0000000080008009, 0x000000008000000A, + 0x000000008000808B, 0x800000000000008B, + 0x8000000000008089, 0x8000000000008003, + 0x8000000000008002, 0x8000000000000080, + 0x000000000000800A, 0x800000008000000A, + 0x8000000080008081, 0x8000000000008080, + 0x0000000080000001, 0x8000000080008008 +}; + +/* + * XOR a block of data into the provided state. This supports only + * blocks whose length is a multiple of 64 bits. + */ +static void +xor_block(uint64_t *A, const void *data, size_t rate) +{ + size_t u; + + for (u = 0; u < rate; u += 8) { + A[u >> 3] ^= br_dec64le((const unsigned char *)data + u); + } +} + +/* + * Process a block with the provided data. The data length must be a + * multiple of 8 (in bytes); normally, this is the "rate". + */ +static void +process_block(uint64_t *A) +{ + uint64_t t0, t1, t2, t3, t4; + uint64_t tt0, tt1, tt2, tt3; + uint64_t t, kt; + uint64_t c0, c1, c2, c3, c4, bnn; + int j; + + /* + * Compute the 24 rounds. This loop is partially unrolled (each + * iteration computes two rounds). + */ + for (j = 0; j < 24; j += 2) { + + tt0 = A[ 1] ^ A[ 6]; + tt1 = A[11] ^ A[16]; + tt0 ^= A[21] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[ 4] ^ A[ 9]; + tt3 = A[14] ^ A[19]; + tt0 ^= A[24]; + tt2 ^= tt3; + t0 = tt0 ^ tt2; + + tt0 = A[ 2] ^ A[ 7]; + tt1 = A[12] ^ A[17]; + tt0 ^= A[22] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[ 0] ^ A[ 5]; + tt3 = A[10] ^ A[15]; + tt0 ^= A[20]; + tt2 ^= tt3; + t1 = tt0 ^ tt2; + + tt0 = A[ 3] ^ A[ 8]; + tt1 = A[13] ^ A[18]; + tt0 ^= A[23] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[ 1] ^ A[ 6]; + tt3 = A[11] ^ A[16]; + tt0 ^= A[21]; + tt2 ^= tt3; + t2 = tt0 ^ tt2; + + tt0 = A[ 4] ^ A[ 9]; + tt1 = A[14] ^ A[19]; + tt0 ^= A[24] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[ 2] ^ A[ 7]; + tt3 = A[12] ^ A[17]; + tt0 ^= A[22]; + tt2 ^= tt3; + t3 = tt0 ^ tt2; + + tt0 = A[ 0] ^ A[ 5]; + tt1 = A[10] ^ A[15]; + tt0 ^= A[20] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[ 3] ^ A[ 8]; + tt3 = A[13] ^ A[18]; + tt0 ^= A[23]; + tt2 ^= tt3; + t4 = tt0 ^ tt2; + + A[ 0] = A[ 0] ^ t0; + A[ 5] = A[ 5] ^ t0; + A[10] = A[10] ^ t0; + A[15] = A[15] ^ t0; + A[20] = A[20] ^ t0; + A[ 1] = A[ 1] ^ t1; + A[ 6] = A[ 6] ^ t1; + A[11] = A[11] ^ t1; + A[16] = A[16] ^ t1; + A[21] = A[21] ^ t1; + A[ 2] = A[ 2] ^ t2; + A[ 7] = A[ 7] ^ t2; + A[12] = A[12] ^ t2; + A[17] = A[17] ^ t2; + A[22] = A[22] ^ t2; + A[ 3] = A[ 3] ^ t3; + A[ 8] = A[ 8] ^ t3; + A[13] = A[13] ^ t3; + A[18] = A[18] ^ t3; + A[23] = A[23] ^ t3; + A[ 4] = A[ 4] ^ t4; + A[ 9] = A[ 9] ^ t4; + A[14] = A[14] ^ t4; + A[19] = A[19] ^ t4; + A[24] = A[24] ^ t4; + A[ 5] = (A[ 5] << 36) | (A[ 5] >> (64 - 36)); + A[10] = (A[10] << 3) | (A[10] >> (64 - 3)); + A[15] = (A[15] << 41) | (A[15] >> (64 - 41)); + A[20] = (A[20] << 18) | (A[20] >> (64 - 18)); + A[ 1] = (A[ 1] << 1) | (A[ 1] >> (64 - 1)); + A[ 6] = (A[ 6] << 44) | (A[ 6] >> (64 - 44)); + A[11] = (A[11] << 10) | (A[11] >> (64 - 10)); + A[16] = (A[16] << 45) | (A[16] >> (64 - 45)); + A[21] = (A[21] << 2) | (A[21] >> (64 - 2)); + A[ 2] = (A[ 2] << 62) | (A[ 2] >> (64 - 62)); + A[ 7] = (A[ 7] << 6) | (A[ 7] >> (64 - 6)); + A[12] = (A[12] << 43) | (A[12] >> (64 - 43)); + A[17] = (A[17] << 15) | (A[17] >> (64 - 15)); + A[22] = (A[22] << 61) | (A[22] >> (64 - 61)); + A[ 3] = (A[ 3] << 28) | (A[ 3] >> (64 - 28)); + A[ 8] = (A[ 8] << 55) | (A[ 8] >> (64 - 55)); + A[13] = (A[13] << 25) | (A[13] >> (64 - 25)); + A[18] = (A[18] << 21) | (A[18] >> (64 - 21)); + A[23] = (A[23] << 56) | (A[23] >> (64 - 56)); + A[ 4] = (A[ 4] << 27) | (A[ 4] >> (64 - 27)); + A[ 9] = (A[ 9] << 20) | (A[ 9] >> (64 - 20)); + A[14] = (A[14] << 39) | (A[14] >> (64 - 39)); + A[19] = (A[19] << 8) | (A[19] >> (64 - 8)); + A[24] = (A[24] << 14) | (A[24] >> (64 - 14)); + bnn = ~A[12]; + kt = A[ 6] | A[12]; + c0 = A[ 0] ^ kt; + kt = bnn | A[18]; + c1 = A[ 6] ^ kt; + kt = A[18] & A[24]; + c2 = A[12] ^ kt; + kt = A[24] | A[ 0]; + c3 = A[18] ^ kt; + kt = A[ 0] & A[ 6]; + c4 = A[24] ^ kt; + A[ 0] = c0; + A[ 6] = c1; + A[12] = c2; + A[18] = c3; + A[24] = c4; + bnn = ~A[22]; + kt = A[ 9] | A[10]; + c0 = A[ 3] ^ kt; + kt = A[10] & A[16]; + c1 = A[ 9] ^ kt; + kt = A[16] | bnn; + c2 = A[10] ^ kt; + kt = A[22] | A[ 3]; + c3 = A[16] ^ kt; + kt = A[ 3] & A[ 9]; + c4 = A[22] ^ kt; + A[ 3] = c0; + A[ 9] = c1; + A[10] = c2; + A[16] = c3; + A[22] = c4; + bnn = ~A[19]; + kt = A[ 7] | A[13]; + c0 = A[ 1] ^ kt; + kt = A[13] & A[19]; + c1 = A[ 7] ^ kt; + kt = bnn & A[20]; + c2 = A[13] ^ kt; + kt = A[20] | A[ 1]; + c3 = bnn ^ kt; + kt = A[ 1] & A[ 7]; + c4 = A[20] ^ kt; + A[ 1] = c0; + A[ 7] = c1; + A[13] = c2; + A[19] = c3; + A[20] = c4; + bnn = ~A[17]; + kt = A[ 5] & A[11]; + c0 = A[ 4] ^ kt; + kt = A[11] | A[17]; + c1 = A[ 5] ^ kt; + kt = bnn | A[23]; + c2 = A[11] ^ kt; + kt = A[23] & A[ 4]; + c3 = bnn ^ kt; + kt = A[ 4] | A[ 5]; + c4 = A[23] ^ kt; + A[ 4] = c0; + A[ 5] = c1; + A[11] = c2; + A[17] = c3; + A[23] = c4; + bnn = ~A[ 8]; + kt = bnn & A[14]; + c0 = A[ 2] ^ kt; + kt = A[14] | A[15]; + c1 = bnn ^ kt; + kt = A[15] & A[21]; + c2 = A[14] ^ kt; + kt = A[21] | A[ 2]; + c3 = A[15] ^ kt; + kt = A[ 2] & A[ 8]; + c4 = A[21] ^ kt; + A[ 2] = c0; + A[ 8] = c1; + A[14] = c2; + A[15] = c3; + A[21] = c4; + A[ 0] = A[ 0] ^ RC[j + 0]; + + tt0 = A[ 6] ^ A[ 9]; + tt1 = A[ 7] ^ A[ 5]; + tt0 ^= A[ 8] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[24] ^ A[22]; + tt3 = A[20] ^ A[23]; + tt0 ^= A[21]; + tt2 ^= tt3; + t0 = tt0 ^ tt2; + + tt0 = A[12] ^ A[10]; + tt1 = A[13] ^ A[11]; + tt0 ^= A[14] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[ 0] ^ A[ 3]; + tt3 = A[ 1] ^ A[ 4]; + tt0 ^= A[ 2]; + tt2 ^= tt3; + t1 = tt0 ^ tt2; + + tt0 = A[18] ^ A[16]; + tt1 = A[19] ^ A[17]; + tt0 ^= A[15] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[ 6] ^ A[ 9]; + tt3 = A[ 7] ^ A[ 5]; + tt0 ^= A[ 8]; + tt2 ^= tt3; + t2 = tt0 ^ tt2; + + tt0 = A[24] ^ A[22]; + tt1 = A[20] ^ A[23]; + tt0 ^= A[21] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[12] ^ A[10]; + tt3 = A[13] ^ A[11]; + tt0 ^= A[14]; + tt2 ^= tt3; + t3 = tt0 ^ tt2; + + tt0 = A[ 0] ^ A[ 3]; + tt1 = A[ 1] ^ A[ 4]; + tt0 ^= A[ 2] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >> 63); + tt2 = A[18] ^ A[16]; + tt3 = A[19] ^ A[17]; + tt0 ^= A[15]; + tt2 ^= tt3; + t4 = tt0 ^ tt2; + + A[ 0] = A[ 0] ^ t0; + A[ 3] = A[ 3] ^ t0; + A[ 1] = A[ 1] ^ t0; + A[ 4] = A[ 4] ^ t0; + A[ 2] = A[ 2] ^ t0; + A[ 6] = A[ 6] ^ t1; + A[ 9] = A[ 9] ^ t1; + A[ 7] = A[ 7] ^ t1; + A[ 5] = A[ 5] ^ t1; + A[ 8] = A[ 8] ^ t1; + A[12] = A[12] ^ t2; + A[10] = A[10] ^ t2; + A[13] = A[13] ^ t2; + A[11] = A[11] ^ t2; + A[14] = A[14] ^ t2; + A[18] = A[18] ^ t3; + A[16] = A[16] ^ t3; + A[19] = A[19] ^ t3; + A[17] = A[17] ^ t3; + A[15] = A[15] ^ t3; + A[24] = A[24] ^ t4; + A[22] = A[22] ^ t4; + A[20] = A[20] ^ t4; + A[23] = A[23] ^ t4; + A[21] = A[21] ^ t4; + A[ 3] = (A[ 3] << 36) | (A[ 3] >> (64 - 36)); + A[ 1] = (A[ 1] << 3) | (A[ 1] >> (64 - 3)); + A[ 4] = (A[ 4] << 41) | (A[ 4] >> (64 - 41)); + A[ 2] = (A[ 2] << 18) | (A[ 2] >> (64 - 18)); + A[ 6] = (A[ 6] << 1) | (A[ 6] >> (64 - 1)); + A[ 9] = (A[ 9] << 44) | (A[ 9] >> (64 - 44)); + A[ 7] = (A[ 7] << 10) | (A[ 7] >> (64 - 10)); + A[ 5] = (A[ 5] << 45) | (A[ 5] >> (64 - 45)); + A[ 8] = (A[ 8] << 2) | (A[ 8] >> (64 - 2)); + A[12] = (A[12] << 62) | (A[12] >> (64 - 62)); + A[10] = (A[10] << 6) | (A[10] >> (64 - 6)); + A[13] = (A[13] << 43) | (A[13] >> (64 - 43)); + A[11] = (A[11] << 15) | (A[11] >> (64 - 15)); + A[14] = (A[14] << 61) | (A[14] >> (64 - 61)); + A[18] = (A[18] << 28) | (A[18] >> (64 - 28)); + A[16] = (A[16] << 55) | (A[16] >> (64 - 55)); + A[19] = (A[19] << 25) | (A[19] >> (64 - 25)); + A[17] = (A[17] << 21) | (A[17] >> (64 - 21)); + A[15] = (A[15] << 56) | (A[15] >> (64 - 56)); + A[24] = (A[24] << 27) | (A[24] >> (64 - 27)); + A[22] = (A[22] << 20) | (A[22] >> (64 - 20)); + A[20] = (A[20] << 39) | (A[20] >> (64 - 39)); + A[23] = (A[23] << 8) | (A[23] >> (64 - 8)); + A[21] = (A[21] << 14) | (A[21] >> (64 - 14)); + bnn = ~A[13]; + kt = A[ 9] | A[13]; + c0 = A[ 0] ^ kt; + kt = bnn | A[17]; + c1 = A[ 9] ^ kt; + kt = A[17] & A[21]; + c2 = A[13] ^ kt; + kt = A[21] | A[ 0]; + c3 = A[17] ^ kt; + kt = A[ 0] & A[ 9]; + c4 = A[21] ^ kt; + A[ 0] = c0; + A[ 9] = c1; + A[13] = c2; + A[17] = c3; + A[21] = c4; + bnn = ~A[14]; + kt = A[22] | A[ 1]; + c0 = A[18] ^ kt; + kt = A[ 1] & A[ 5]; + c1 = A[22] ^ kt; + kt = A[ 5] | bnn; + c2 = A[ 1] ^ kt; + kt = A[14] | A[18]; + c3 = A[ 5] ^ kt; + kt = A[18] & A[22]; + c4 = A[14] ^ kt; + A[18] = c0; + A[22] = c1; + A[ 1] = c2; + A[ 5] = c3; + A[14] = c4; + bnn = ~A[23]; + kt = A[10] | A[19]; + c0 = A[ 6] ^ kt; + kt = A[19] & A[23]; + c1 = A[10] ^ kt; + kt = bnn & A[ 2]; + c2 = A[19] ^ kt; + kt = A[ 2] | A[ 6]; + c3 = bnn ^ kt; + kt = A[ 6] & A[10]; + c4 = A[ 2] ^ kt; + A[ 6] = c0; + A[10] = c1; + A[19] = c2; + A[23] = c3; + A[ 2] = c4; + bnn = ~A[11]; + kt = A[ 3] & A[ 7]; + c0 = A[24] ^ kt; + kt = A[ 7] | A[11]; + c1 = A[ 3] ^ kt; + kt = bnn | A[15]; + c2 = A[ 7] ^ kt; + kt = A[15] & A[24]; + c3 = bnn ^ kt; + kt = A[24] | A[ 3]; + c4 = A[15] ^ kt; + A[24] = c0; + A[ 3] = c1; + A[ 7] = c2; + A[11] = c3; + A[15] = c4; + bnn = ~A[16]; + kt = bnn & A[20]; + c0 = A[12] ^ kt; + kt = A[20] | A[ 4]; + c1 = bnn ^ kt; + kt = A[ 4] & A[ 8]; + c2 = A[20] ^ kt; + kt = A[ 8] | A[12]; + c3 = A[ 4] ^ kt; + kt = A[12] & A[16]; + c4 = A[ 8] ^ kt; + A[12] = c0; + A[16] = c1; + A[20] = c2; + A[ 4] = c3; + A[ 8] = c4; + A[ 0] = A[ 0] ^ RC[j + 1]; + t = A[ 5]; + A[ 5] = A[18]; + A[18] = A[11]; + A[11] = A[10]; + A[10] = A[ 6]; + A[ 6] = A[22]; + A[22] = A[20]; + A[20] = A[12]; + A[12] = A[19]; + A[19] = A[15]; + A[15] = A[24]; + A[24] = A[ 8]; + A[ 8] = t; + t = A[ 1]; + A[ 1] = A[ 9]; + A[ 9] = A[14]; + A[14] = A[ 2]; + A[ 2] = A[13]; + A[13] = A[23]; + A[23] = A[ 4]; + A[ 4] = A[21]; + A[21] = A[16]; + A[16] = A[ 3]; + A[ 3] = A[17]; + A[17] = A[ 7]; + A[ 7] = t; + } +} + +/* see bearssl_kdf.h */ +void +br_shake_init(br_shake_context *sc, int security_level) +{ + sc->rate = 200 - (size_t)(security_level >> 2); + sc->dptr = 0; + memset(sc->A, 0, sizeof sc->A); + sc->A[ 1] = ~(uint64_t)0; + sc->A[ 2] = ~(uint64_t)0; + sc->A[ 8] = ~(uint64_t)0; + sc->A[12] = ~(uint64_t)0; + sc->A[17] = ~(uint64_t)0; + sc->A[20] = ~(uint64_t)0; +} + +/* see bearssl_kdf.h */ +void +br_shake_inject(br_shake_context *sc, const void *data, size_t len) +{ + const unsigned char *buf; + size_t rate, dptr; + + buf = data; + rate = sc->rate; + dptr = sc->dptr; + while (len > 0) { + size_t clen; + + clen = rate - dptr; + if (clen > len) { + clen = len; + } + memcpy(sc->dbuf + dptr, buf, clen); + dptr += clen; + buf += clen; + len -= clen; + if (dptr == rate) { + xor_block(sc->A, sc->dbuf, rate); + process_block(sc->A); + dptr = 0; + } + } + sc->dptr = dptr; +} + +/* see bearssl_kdf.h */ +void +br_shake_flip(br_shake_context *sc) +{ + /* + * We apply padding and pre-XOR the value into the state. We + * set dptr to the end of the buffer, so that first call to + * shake_extract() will process the block. + */ + if ((sc->dptr + 1) == sc->rate) { + sc->dbuf[sc->dptr ++] = 0x9F; + } else { + sc->dbuf[sc->dptr ++] = 0x1F; + memset(sc->dbuf + sc->dptr, 0x00, sc->rate - sc->dptr - 1); + sc->dbuf[sc->rate - 1] = 0x80; + sc->dptr = sc->rate; + } + xor_block(sc->A, sc->dbuf, sc->rate); +} + +/* see bearssl_kdf.h */ +void +br_shake_produce(br_shake_context *sc, void *out, size_t len) +{ + unsigned char *buf; + size_t dptr, rate; + + buf = out; + dptr = sc->dptr; + rate = sc->rate; + while (len > 0) { + size_t clen; + + if (dptr == rate) { + unsigned char *dbuf; + uint64_t *A; + + A = sc->A; + dbuf = sc->dbuf; + process_block(A); + br_enc64le(dbuf + 0, A[ 0]); + br_enc64le(dbuf + 8, ~A[ 1]); + br_enc64le(dbuf + 16, ~A[ 2]); + br_enc64le(dbuf + 24, A[ 3]); + br_enc64le(dbuf + 32, A[ 4]); + br_enc64le(dbuf + 40, A[ 5]); + br_enc64le(dbuf + 48, A[ 6]); + br_enc64le(dbuf + 56, A[ 7]); + br_enc64le(dbuf + 64, ~A[ 8]); + br_enc64le(dbuf + 72, A[ 9]); + br_enc64le(dbuf + 80, A[10]); + br_enc64le(dbuf + 88, A[11]); + br_enc64le(dbuf + 96, ~A[12]); + br_enc64le(dbuf + 104, A[13]); + br_enc64le(dbuf + 112, A[14]); + br_enc64le(dbuf + 120, A[15]); + br_enc64le(dbuf + 128, A[16]); + br_enc64le(dbuf + 136, ~A[17]); + br_enc64le(dbuf + 144, A[18]); + br_enc64le(dbuf + 152, A[19]); + br_enc64le(dbuf + 160, ~A[20]); + br_enc64le(dbuf + 168, A[21]); + br_enc64le(dbuf + 176, A[22]); + br_enc64le(dbuf + 184, A[23]); + br_enc64le(dbuf + 192, A[24]); + dptr = 0; + } + clen = rate - dptr; + if (clen > len) { + clen = len; + } + memcpy(buf, sc->dbuf + dptr, clen); + dptr += clen; + buf += clen; + len -= clen; + } + sc->dptr = dptr; +} diff --git a/BearSSL-OG/libbearssl/src/mac/hmac.c b/BearSSL-OG/libbearssl/src/mac/hmac.c new file mode 100644 index 0000000..5de836d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/mac/hmac.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 __inline size_t +block_size(const br_hash_class *dig) +{ + unsigned ls; + + ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF) + & BR_HASHDESC_LBLEN_MASK; + return (size_t)1 << ls; +} + +static void +process_key(const br_hash_class **hc, void *ks, + const void *key, size_t key_len, unsigned bb) +{ + unsigned char tmp[256]; + size_t blen, u; + + blen = block_size(*hc); + memcpy(tmp, key, key_len); + for (u = 0; u < key_len; u ++) { + tmp[u] ^= (unsigned char)bb; + } + memset(tmp + key_len, bb, blen - key_len); + (*hc)->init(hc); + (*hc)->update(hc, tmp, blen); + (*hc)->state(hc, ks); +} + +/* see bearssl.h */ +void +br_hmac_key_init(br_hmac_key_context *kc, + const br_hash_class *dig, const void *key, size_t key_len) +{ + br_hash_compat_context hc; + unsigned char kbuf[64]; + + kc->dig_vtable = dig; + hc.vtable = dig; + if (key_len > block_size(dig)) { + dig->init(&hc.vtable); + dig->update(&hc.vtable, key, key_len); + dig->out(&hc.vtable, kbuf); + key = kbuf; + key_len = br_digest_size(dig); + } + process_key(&hc.vtable, kc->ksi, key, key_len, 0x36); + process_key(&hc.vtable, kc->kso, key, key_len, 0x5C); +} + +/* see bearssl.h */ +void +br_hmac_init(br_hmac_context *ctx, + const br_hmac_key_context *kc, size_t out_len) +{ + const br_hash_class *dig; + size_t blen, hlen; + + dig = kc->dig_vtable; + blen = block_size(dig); + dig->init(&ctx->dig.vtable); + dig->set_state(&ctx->dig.vtable, kc->ksi, (uint64_t)blen); + memcpy(ctx->kso, kc->kso, sizeof kc->kso); + hlen = br_digest_size(dig); + if (out_len > 0 && out_len < hlen) { + hlen = out_len; + } + ctx->out_len = hlen; +} + +/* see bearssl.h */ +void +br_hmac_update(br_hmac_context *ctx, const void *data, size_t len) +{ + ctx->dig.vtable->update(&ctx->dig.vtable, data, len); +} + +/* see bearssl.h */ +size_t +br_hmac_out(const br_hmac_context *ctx, void *out) +{ + const br_hash_class *dig; + br_hash_compat_context hc; + unsigned char tmp[64]; + size_t blen, hlen; + + dig = ctx->dig.vtable; + dig->out(&ctx->dig.vtable, tmp); + blen = block_size(dig); + dig->init(&hc.vtable); + dig->set_state(&hc.vtable, ctx->kso, (uint64_t)blen); + hlen = br_digest_size(dig); + dig->update(&hc.vtable, tmp, hlen); + dig->out(&hc.vtable, tmp); + memcpy(out, tmp, ctx->out_len); + return ctx->out_len; +} diff --git a/BearSSL-OG/libbearssl/src/mac/hmac_ct.c b/BearSSL-OG/libbearssl/src/mac/hmac_ct.c new file mode 100644 index 0000000..30b3363 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/mac/hmac_ct.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 __inline size_t +hash_size(const br_hash_class *dig) +{ + return (unsigned)(dig->desc >> BR_HASHDESC_OUT_OFF) + & BR_HASHDESC_OUT_MASK; +} + +static __inline size_t +block_size(const br_hash_class *dig) +{ + unsigned ls; + + ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF) + & BR_HASHDESC_LBLEN_MASK; + return (size_t)1 << ls; +} + +/* see bearssl.h */ +size_t +br_hmac_outCT(const br_hmac_context *ctx, + const void *data, size_t len, size_t min_len, size_t max_len, + void *out) +{ + /* + * Method implemented here is inspired from the descriptions on: + * https://www.imperialviolet.org/2013/02/04/luckythirteen.html + * + * Principle: we input bytes one by one. We use a MUX to push + * padding bytes instead of data bytes when appropriate. At each + * block limit, we get the current hash function state: this is + * a potential output, since we handle MD padding ourselves. + * + * be 1 for big-endian, 0 for little-endian + * po minimal MD padding length + * bs block size (always a power of 2) + * hlen hash output size + */ + + const br_hash_class *dig; + br_hash_compat_context hc; + int be; + uint32_t po, bs; + uint32_t kr, km, kl, kz, u; + uint64_t count, ncount, bit_len; + unsigned char tmp1[64], tmp2[64]; + size_t hlen; + + /* + * Copy the current hash context. + */ + hc = ctx->dig; + + /* + * Get function-specific information. + */ + dig = hc.vtable; + be = (dig->desc & BR_HASHDESC_MD_PADDING_BE) != 0; + po = 9; + if (dig->desc & BR_HASHDESC_MD_PADDING_128) { + po += 8; + } + bs = block_size(dig); + hlen = hash_size(dig); + + /* + * Get current input length and compute total bit length. + */ + count = dig->state(&hc.vtable, tmp1); + bit_len = (count + (uint64_t)len) << 3; + + /* + * We can input the blocks that we are sure we will use. + * This offers better performance (no MUX for these blocks) + * and also ensures that the remaining lengths fit on 32 bits. + */ + ncount = (count + (uint64_t)min_len) & ~(uint64_t)(bs - 1); + if (ncount > count) { + size_t zlen; + + zlen = (size_t)(ncount - count); + dig->update(&hc.vtable, data, zlen); + data = (const unsigned char *)data + zlen; + len -= zlen; + max_len -= zlen; + count = ncount; + } + + /* + * At that point: + * -- 'count' contains the number of bytes already processed + * (in total). + * -- We must input 'len' bytes. 'min_len' is unimportant: we + * used it to know how many full blocks we could process + * directly. Now only len and max_len matter. + * + * We compute kr, kl, kz and km. + * kr number of input bytes already in the current block + * km index of the first byte after the end of the last padding + * block, if length is max_len + * kz index of the last byte of the actual last padding block + * kl index of the start of the encoded length + * + * km, kz and kl are counted from the current offset in the + * input data. + */ + kr = (uint32_t)count & (bs - 1); + kz = ((kr + (uint32_t)len + po + bs - 1) & ~(bs - 1)) - 1 - kr; + kl = kz - 7; + km = ((kr + (uint32_t)max_len + po + bs - 1) & ~(bs - 1)) - kr; + + /* + * We must now process km bytes. For index u from 0 to km-1: + * d is from data[] if u < max_len, 0x00 otherwise + * e is an encoded length byte or 0x00, depending on u + * The tests for d and e need not be constant-time, since + * they relate only to u and max_len, not to the actual length. + * + * Actual input length is then: + * d if u < len + * 0x80 if u == len + * 0x00 if u > len and u < kl + * e if u >= kl + * + * Hash state is obtained whenever we reach a full block. This + * is the result we want if and only if u == kz. + */ + memset(tmp2, 0, sizeof tmp2); + for (u = 0; u < km; u ++) { + uint32_t v; + uint32_t d, e, x0, x1; + unsigned char x[1]; + + d = (u < max_len) ? ((const unsigned char *)data)[u] : 0x00; + v = (kr + u) & (bs - 1); + if (v >= (bs - 8)) { + unsigned j; + + j = (v - (bs - 8)) << 3; + if (be) { + e = (uint32_t)(bit_len >> (56 - j)); + } else { + e = (uint32_t)(bit_len >> j); + } + e &= 0xFF; + } else { + e = 0x00; + } + x0 = MUX(EQ(u, (uint32_t)len), 0x80, d); + x1 = MUX(LT(u, kl), 0x00, e); + x[0] = MUX(LE(u, (uint32_t)len), x0, x1); + dig->update(&hc.vtable, x, 1); + if (v == (bs - 1)) { + dig->state(&hc.vtable, tmp1); + CCOPY(EQ(u, kz), tmp2, tmp1, hlen); + } + } + + /* + * Inner hash output is in tmp2[]; we finish processing. + */ + dig->init(&hc.vtable); + dig->set_state(&hc.vtable, ctx->kso, (uint64_t)bs); + dig->update(&hc.vtable, tmp2, hlen); + dig->out(&hc.vtable, tmp2); + memcpy(out, tmp2, ctx->out_len); + return ctx->out_len; +} diff --git a/BearSSL-OG/libbearssl/src/rand/aesctr_drbg.c b/BearSSL-OG/libbearssl/src/rand/aesctr_drbg.c new file mode 100644 index 0000000..8dbd501 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rand/aesctr_drbg.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rand.h */ +void +br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, + const br_block_ctr_class *aesctr, + const void *seed, size_t len) +{ + unsigned char tmp[16]; + + ctx->vtable = &br_aesctr_drbg_vtable; + memset(tmp, 0, sizeof tmp); + aesctr->init(&ctx->sk.vtable, tmp, 16); + ctx->cc = 0; + br_aesctr_drbg_update(ctx, seed, len); +} + +/* see bearssl_rand.h */ +void +br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len) +{ + unsigned char *buf; + unsigned char iv[12]; + + buf = out; + memset(iv, 0, sizeof iv); + while (len > 0) { + size_t clen; + + /* + * We generate data by blocks of at most 65280 bytes. This + * allows for unambiguously testing the counter overflow + * condition; also, it should work on 16-bit architectures + * (where 'size_t' is 16 bits only). + */ + clen = len; + if (clen > 65280) { + clen = 65280; + } + + /* + * We make sure that the counter won't exceed the configured + * limit. + */ + if ((uint32_t)(ctx->cc + ((clen + 15) >> 4)) > 32768) { + clen = (32768 - ctx->cc) << 4; + if (clen > len) { + clen = len; + } + } + + /* + * Run CTR. + */ + memset(buf, 0, clen); + ctx->cc = ctx->sk.vtable->run(&ctx->sk.vtable, + iv, ctx->cc, buf, clen); + buf += clen; + len -= clen; + + /* + * Every 32768 blocks, we force a state update. + */ + if (ctx->cc >= 32768) { + br_aesctr_drbg_update(ctx, NULL, 0); + } + } +} + +/* see bearssl_rand.h */ +void +br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) +{ + /* + * We use a Hirose construction on AES-256 to make a hash function. + * Function definition: + * - running state consists in two 16-byte blocks G and H + * - initial values of G and H are conventional + * - there is a fixed block-sized constant C + * - for next data block m: + * set AES key to H||m + * G' = E(G) xor G + * H' = E(G xor C) xor G xor C + * G <- G', H <- H' + * - once all blocks have been processed, output is H||G + * + * Constants: + * G_init = B6 B6 ... B6 + * H_init = A5 A5 ... A5 + * C = 01 00 ... 00 + * + * With this hash function h(), we compute the new state as + * follows: + * - produce a state-dependent value s as encryption of an + * all-one block with AES and the current key + * - compute the new key as the first 128 bits of h(s||seed) + * + * Original Hirose article: + * https://www.iacr.org/archive/fse2006/40470213/40470213.pdf + */ + + unsigned char s[16], iv[12]; + unsigned char G[16], H[16]; + int first; + + /* + * Use an all-one IV to get a fresh output block that depends on the + * current seed. + */ + memset(iv, 0xFF, sizeof iv); + memset(s, 0, 16); + ctx->sk.vtable->run(&ctx->sk.vtable, iv, 0xFFFFFFFF, s, 16); + + /* + * Set G[] and H[] to conventional start values. + */ + memset(G, 0xB6, sizeof G); + memset(H, 0x5A, sizeof H); + + /* + * Process the concatenation of the current state and the seed + * with the custom hash function. + */ + first = 1; + for (;;) { + unsigned char tmp[32]; + unsigned char newG[16]; + + /* + * Assemble new key H||m into tmp[]. + */ + memcpy(tmp, H, 16); + if (first) { + memcpy(tmp + 16, s, 16); + first = 0; + } else { + size_t clen; + + if (len == 0) { + break; + } + clen = len < 16 ? len : 16; + memcpy(tmp + 16, seed, clen); + memset(tmp + 16 + clen, 0, 16 - clen); + seed = (const unsigned char *)seed + clen; + len -= clen; + } + ctx->sk.vtable->init(&ctx->sk.vtable, tmp, 32); + + /* + * Compute new G and H values. + */ + memcpy(iv, G, 12); + memcpy(newG, G, 16); + ctx->sk.vtable->run(&ctx->sk.vtable, iv, + br_dec32be(G + 12), newG, 16); + iv[0] ^= 0x01; + memcpy(H, G, 16); + H[0] ^= 0x01; + ctx->sk.vtable->run(&ctx->sk.vtable, iv, + br_dec32be(G + 12), H, 16); + memcpy(G, newG, 16); + } + + /* + * Output hash value is H||G. We truncate it to its first 128 bits, + * i.e. H; that's our new AES key. + */ + ctx->sk.vtable->init(&ctx->sk.vtable, H, 16); + ctx->cc = 0; +} + +/* see bearssl_rand.h */ +const br_prng_class br_aesctr_drbg_vtable = { + sizeof(br_aesctr_drbg_context), + (void (*)(const br_prng_class **, const void *, const void *, size_t)) + &br_aesctr_drbg_init, + (void (*)(const br_prng_class **, void *, size_t)) + &br_aesctr_drbg_generate, + (void (*)(const br_prng_class **, const void *, size_t)) + &br_aesctr_drbg_update +}; diff --git a/BearSSL-OG/libbearssl/src/rand/hmac_drbg.c b/BearSSL-OG/libbearssl/src/rand/hmac_drbg.c new file mode 100644 index 0000000..d746756 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rand/hmac_drbg.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl.h */ +void +br_hmac_drbg_init(br_hmac_drbg_context *ctx, + const br_hash_class *digest_class, const void *seed, size_t len) +{ + size_t hlen; + + ctx->vtable = &br_hmac_drbg_vtable; + hlen = br_digest_size(digest_class); + memset(ctx->K, 0x00, hlen); + memset(ctx->V, 0x01, hlen); + ctx->digest_class = digest_class; + br_hmac_drbg_update(ctx, seed, len); +} + +/* see bearssl.h */ +void +br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len) +{ + const br_hash_class *dig; + br_hmac_key_context kc; + br_hmac_context hc; + size_t hlen; + unsigned char *buf; + unsigned char x; + + dig = ctx->digest_class; + hlen = br_digest_size(dig); + br_hmac_key_init(&kc, dig, ctx->K, hlen); + buf = out; + while (len > 0) { + size_t clen; + + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, ctx->V, hlen); + br_hmac_out(&hc, ctx->V); + clen = hlen; + if (clen > len) { + clen = len; + } + memcpy(buf, ctx->V, clen); + buf += clen; + len -= clen; + } + + /* + * To prepare the state for the next request, we should call + * br_hmac_drbg_update() with an empty additional seed. However, + * we already have an initialized HMAC context with the right + * initial key, and we don't want to push another one on the + * stack, so we inline that update() call here. + */ + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, ctx->V, hlen); + x = 0x00; + br_hmac_update(&hc, &x, 1); + br_hmac_out(&hc, ctx->K); + br_hmac_key_init(&kc, dig, ctx->K, hlen); + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, ctx->V, hlen); + br_hmac_out(&hc, ctx->V); +} + +/* see bearssl.h */ +void +br_hmac_drbg_update(br_hmac_drbg_context *ctx, const void *seed, size_t len) +{ + const br_hash_class *dig; + br_hmac_key_context kc; + br_hmac_context hc; + size_t hlen; + unsigned char x; + + dig = ctx->digest_class; + hlen = br_digest_size(dig); + + /* + * 1. K = HMAC(K, V || 0x00 || seed) + */ + br_hmac_key_init(&kc, dig, ctx->K, hlen); + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, ctx->V, hlen); + x = 0x00; + br_hmac_update(&hc, &x, 1); + br_hmac_update(&hc, seed, len); + br_hmac_out(&hc, ctx->K); + br_hmac_key_init(&kc, dig, ctx->K, hlen); + + /* + * 2. V = HMAC(K, V) + */ + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, ctx->V, hlen); + br_hmac_out(&hc, ctx->V); + + /* + * 3. If the additional seed is empty, then stop here. + */ + if (len == 0) { + return; + } + + /* + * 4. K = HMAC(K, V || 0x01 || seed) + */ + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, ctx->V, hlen); + x = 0x01; + br_hmac_update(&hc, &x, 1); + br_hmac_update(&hc, seed, len); + br_hmac_out(&hc, ctx->K); + br_hmac_key_init(&kc, dig, ctx->K, hlen); + + /* + * 5. V = HMAC(K, V) + */ + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, ctx->V, hlen); + br_hmac_out(&hc, ctx->V); +} + +/* see bearssl.h */ +const br_prng_class br_hmac_drbg_vtable = { + sizeof(br_hmac_drbg_context), + (void (*)(const br_prng_class **, const void *, const void *, size_t)) + &br_hmac_drbg_init, + (void (*)(const br_prng_class **, void *, size_t)) + &br_hmac_drbg_generate, + (void (*)(const br_prng_class **, const void *, size_t)) + &br_hmac_drbg_update +}; diff --git a/BearSSL-OG/libbearssl/src/rand/sysrng.c b/BearSSL-OG/libbearssl/src/rand/sysrng.c new file mode 100644 index 0000000..b39f25d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rand/sysrng.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_ENABLE_INTRINSICS 1 +#include "inner.h" + +#if BR_USE_GETENTROPY +#include +#endif + +#if BR_USE_URANDOM +#include +#include +#include +#include +#endif + +#if BR_USE_WIN32_RAND +#include +#include +#pragma comment(lib, "advapi32") +#endif + +#if BR_USE_XBOX_RAND +#include +#endif + +/* + * Seeder that uses the RDRAND opcodes (on x86 CPU). + */ +#if BR_RDRAND +BR_TARGETS_X86_UP +BR_TARGET("rdrnd") +static int +seeder_rdrand(const br_prng_class **ctx) +{ + unsigned char tmp[32]; + size_t u; + + for (u = 0; u < sizeof tmp; u += sizeof(uint32_t)) { + int j; + uint32_t x; + + /* + * We use the 32-bit intrinsic so that code is compatible + * with both 32-bit and 64-bit architectures. + * + * Intel recommends trying at least 10 times in case of + * failure. + * + * AMD bug: there are reports that some AMD processors + * have a bug that makes them fail silently after a + * suspend/resume cycle, in which case RDRAND will report + * a success but always return 0xFFFFFFFF. + * see: https://bugzilla.kernel.org/show_bug.cgi?id=85911 + * + * As a mitigation, if the 32-bit value is 0 or -1, then + * it is considered a failure and tried again. This should + * reliably detect the buggy case, at least. This also + * implies that the selected seed values can never be + * 0x00000000 or 0xFFFFFFFF, which is not a problem since + * we are generating a seed for a PRNG, and we overdo it + * a bit (we generate 32 bytes of randomness, and 256 bits + * of entropy are really overkill). + */ + for (j = 0; j < 10; j ++) { + if (_rdrand32_step(&x) && x != 0 && x != (uint32_t)-1) { + goto next_word; + } + } + return 0; + next_word: + br_enc32le(tmp + u, x); + } + (*ctx)->update(ctx, tmp, sizeof tmp); + return 1; +} +BR_TARGETS_X86_DOWN + +static int +rdrand_supported(void) +{ + /* + * The RDRND support is bit 30 of ECX, as returned by CPUID. + */ + return br_cpuid(0, 0, 0x40000000, 0); +} +#endif + +/* + * Seeder that uses /dev/urandom (on Unix-like systems). + */ +#if BR_USE_URANDOM +static int +seeder_urandom(const br_prng_class **ctx) +{ + int f; + + f = open("/dev/urandom", O_RDONLY); + if (f >= 0) { + unsigned char tmp[32]; + size_t u; + + for (u = 0; u < sizeof tmp;) { + ssize_t len; + + len = read(f, tmp + u, (sizeof tmp) - u); + if (len < 0) { + if (errno == EINTR) { + continue; + } + break; + } + u += (size_t)len; + } + close(f); + if (u == sizeof tmp) { + (*ctx)->update(ctx, tmp, sizeof tmp); + return 1; + } + } + return 0; +} +#endif + +/* + * Seeder that uses getentropy() (backed by getrandom() on some systems, + * e.g. Linux). On failure, it will use the /dev/urandom seeder (if + * enabled). + */ +#if BR_USE_GETENTROPY +static int +seeder_getentropy(const br_prng_class **ctx) +{ + unsigned char tmp[32]; + + if (getentropy(tmp, sizeof tmp) == 0) { + (*ctx)->update(ctx, tmp, sizeof tmp); + return 1; + } +#if BR_USE_URANDOM + return seeder_urandom(ctx); +#else + return 0; +#endif +} +#endif + +/* + * Seeder that uses CryptGenRandom() (on Windows). + */ +#if BR_USE_WIN32_RAND +static int +seeder_win32(const br_prng_class **ctx) +{ + HCRYPTPROV hp; + + if (CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + { + BYTE buf[32]; + BOOL r; + + r = CryptGenRandom(hp, sizeof buf, buf); + CryptReleaseContext(hp, 0); + if (r) { + (*ctx)->update(ctx, buf, sizeof buf); + return 1; + } + } + return 0; +} +#endif + +#if BR_USE_XBOX_RAND +#include /* For XNetRandom() */ + +static int +seeder_xbox(const br_prng_class **ctx) +{ + unsigned char buf[32]; + + /* + * Use Xbox's XNetRandom() for cryptographically secure random data. + * This function provides hardware-backed random bytes suitable for + * TLS key generation and other cryptographic operations. + * + * Note: XNetStartup() must have been called before using this. + */ + XNetRandom(buf, sizeof(buf)); + + (*ctx)->update(ctx, buf, sizeof(buf)); + return 1; +} +#endif + +/* + * An aggregate seeder that uses RDRAND, and falls back to an OS-provided + * source if RDRAND fails. + */ +#if BR_RDRAND && (BR_USE_GETENTROPY || BR_USE_URANDOM || BR_USE_WIN32_RAND || BR_USE_XBOX_RAND) +static int +seeder_rdrand_with_fallback(const br_prng_class **ctx) +{ + if (!seeder_rdrand(ctx)) { +#if BR_USE_GETENTROPY + return seeder_getentropy(ctx); +#elif BR_USE_URANDOM + return seeder_urandom(ctx); +#elif BR_USE_WIN32_RAND + return seeder_win32(ctx); +#elif BR_USE_XBOX_RAND + return seeder_xbox(ctx); +#else +#error "macro selection has gone wrong" +#endif + } + return 1; +} +#endif + +/* see bearssl_rand.h */ +br_prng_seeder +br_prng_seeder_system(const char **name) +{ +#if BR_RDRAND + if (rdrand_supported()) { + if (name != NULL) { + *name = "rdrand"; + } +#if BR_USE_GETENTROPY || BR_USE_URANDOM || BR_USE_WIN32_RAND || BR_USE_XBOX_RAND + return &seeder_rdrand_with_fallback; +#else + return &seeder_rdrand; +#endif + } +#endif +#if BR_USE_GETENTROPY + if (name != NULL) { + *name = "getentropy"; + } + return &seeder_getentropy; +#elif BR_USE_URANDOM + if (name != NULL) { + *name = "urandom"; + } + return &seeder_urandom; +#elif BR_USE_WIN32_RAND + if (name != NULL) { + *name = "win32"; + } + return &seeder_win32; +#elif BR_USE_XBOX_RAND + if (name != NULL) { + *name = "xbox"; + } + return &seeder_xbox; +#else + if (name != NULL) { + *name = "none"; + } + return 0; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_keygen.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_keygen.c new file mode 100644 index 0000000..f2e83c8 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_keygen.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_keygen +br_rsa_keygen_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_keygen; +#elif BR_LOMUL + return &br_rsa_i15_keygen; +#else + return &br_rsa_i31_keygen; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_modulus.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_modulus.c new file mode 100644 index 0000000..57d4be5 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_modulus.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_compute_modulus +br_rsa_compute_modulus_get_default(void) +{ +#if BR_LOMUL + return &br_rsa_i15_compute_modulus; +#else + return &br_rsa_i31_compute_modulus; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_oaep_decrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_oaep_decrypt.c new file mode 100644 index 0000000..7345d64 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_oaep_decrypt.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_oaep_decrypt +br_rsa_oaep_decrypt_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_oaep_decrypt; +#elif BR_LOMUL + return &br_rsa_i15_oaep_decrypt; +#else + return &br_rsa_i31_oaep_decrypt; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_oaep_encrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_oaep_encrypt.c new file mode 100644 index 0000000..ae33fcc --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_oaep_encrypt.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_oaep_encrypt +br_rsa_oaep_encrypt_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_oaep_encrypt; +#elif BR_LOMUL + return &br_rsa_i15_oaep_encrypt; +#else + return &br_rsa_i31_oaep_encrypt; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_pkcs1_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pkcs1_sign.c new file mode 100644 index 0000000..e926704 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pkcs1_sign.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_pkcs1_sign +br_rsa_pkcs1_sign_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_pkcs1_sign; +#elif BR_LOMUL + return &br_rsa_i15_pkcs1_sign; +#else + return &br_rsa_i31_pkcs1_sign; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_pkcs1_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pkcs1_vrfy.c new file mode 100644 index 0000000..b3dbeb7 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pkcs1_vrfy.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_pkcs1_vrfy +br_rsa_pkcs1_vrfy_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_pkcs1_vrfy; +#elif BR_LOMUL + return &br_rsa_i15_pkcs1_vrfy; +#else + return &br_rsa_i31_pkcs1_vrfy; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_priv.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_priv.c new file mode 100644 index 0000000..bb0b2c0 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_priv.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_private +br_rsa_private_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_private; +#elif BR_LOMUL + return &br_rsa_i15_private; +#else + return &br_rsa_i31_private; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_privexp.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_privexp.c new file mode 100644 index 0000000..cda4555 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_privexp.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_compute_privexp +br_rsa_compute_privexp_get_default(void) +{ +#if BR_LOMUL + return &br_rsa_i15_compute_privexp; +#else + return &br_rsa_i31_compute_privexp; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_pss_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pss_sign.c new file mode 100644 index 0000000..ce4f3e0 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pss_sign.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_pss_sign +br_rsa_pss_sign_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_pss_sign; +#elif BR_LOMUL + return &br_rsa_i15_pss_sign; +#else + return &br_rsa_i31_pss_sign; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_pss_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pss_vrfy.c new file mode 100644 index 0000000..e3a9ad9 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pss_vrfy.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_pss_vrfy +br_rsa_pss_vrfy_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_pss_vrfy; +#elif BR_LOMUL + return &br_rsa_i15_pss_vrfy; +#else + return &br_rsa_i31_pss_vrfy; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_pub.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pub.c new file mode 100644 index 0000000..a1f03ef --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pub.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_public +br_rsa_public_get_default(void) +{ +#if BR_INT128 || BR_UMUL128 + return &br_rsa_i62_public; +#elif BR_LOMUL + return &br_rsa_i15_public; +#else + return &br_rsa_i31_public; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_default_pubexp.c b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pubexp.c new file mode 100644 index 0000000..47bc000 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_default_pubexp.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +br_rsa_compute_pubexp +br_rsa_compute_pubexp_get_default(void) +{ +#if BR_LOMUL + return &br_rsa_i15_compute_pubexp; +#else + return &br_rsa_i31_compute_pubexp; +#endif +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_keygen.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_keygen.c new file mode 100644 index 0000000..e8da419 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_keygen.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * Make a random integer of the provided size. The size is encoded. + * The header word is untouched. + */ +static void +mkrand(const br_prng_class **rng, uint16_t *x, uint32_t esize) +{ + size_t u, len; + unsigned m; + + len = (esize + 15) >> 4; + (*rng)->generate(rng, x + 1, len * sizeof(uint16_t)); + for (u = 1; u < len; u ++) { + x[u] &= 0x7FFF; + } + m = esize & 15; + if (m == 0) { + x[len] &= 0x7FFF; + } else { + x[len] &= 0x7FFF >> (15 - m); + } +} + +/* + * This is the big-endian unsigned representation of the product of + * all small primes from 13 to 1481. + */ +static const unsigned char SMALL_PRIMES[] = { + 0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A, + 0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7, + 0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37, + 0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5, + 0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E, + 0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6, + 0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C, + 0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40, + 0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50, + 0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7, + 0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3, + 0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E, + 0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC, + 0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08, + 0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B, + 0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22, + 0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77, + 0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E, + 0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80, + 0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8, + 0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2, + 0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC, + 0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54, + 0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74, + 0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C, + 0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD +}; + +/* + * We need temporary values for at least 7 integers of the same size + * as a factor (including header word); more space helps with performance + * (in modular exponentiations), but we much prefer to remain under + * 2 kilobytes in total, to save stack space. The macro TEMPS below + * exceeds 1024 (which is a count in 16-bit words) when BR_MAX_RSA_SIZE + * is greater than 4350 (default value is 4096, so the 2-kB limit is + * maintained unless BR_MAX_RSA_SIZE was modified). + */ +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define TEMPS MAX(1024, 7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 29) / 15)) + +/* + * Perform trial division on a candidate prime. This computes + * y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The + * br_i15_moddiv() function will report an error if y is not invertible + * modulo x. Returned value is 1 on success (none of the small primes + * divides x), 0 on error (a non-trivial GCD is obtained). + * + * This function assumes that x is odd. + */ +static uint32_t +trial_divisions(const uint16_t *x, uint16_t *t) +{ + uint16_t *y; + uint16_t x0i; + + y = t; + t += 1 + ((x[0] + 15) >> 4); + x0i = br_i15_ninv15(x[1]); + br_i15_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x); + return br_i15_moddiv(y, y, x, x0i, t); +} + +/* + * Perform n rounds of Miller-Rabin on the candidate prime x. This + * function assumes that x = 3 mod 4. + * + * Returned value is 1 on success (all rounds completed successfully), + * 0 otherwise. + */ +static uint32_t +miller_rabin(const br_prng_class **rng, const uint16_t *x, int n, + uint16_t *t, size_t tlen) +{ + /* + * Since x = 3 mod 4, the Miller-Rabin test is simple: + * - get a random base a (such that 1 < a < x-1) + * - compute z = a^((x-1)/2) mod x + * - if z != 1 and z != x-1, the number x is composite + * + * We generate bases 'a' randomly with a size which is + * one bit less than x, which ensures that a < x-1. It + * is not useful to verify that a > 1 because the probability + * that we get a value a equal to 0 or 1 is much smaller + * than the probability of our Miller-Rabin tests not to + * detect a composite, which is already quite smaller than the + * probability of the hardware misbehaving and return a + * composite integer because of some glitch (e.g. bad RAM + * or ill-timed cosmic ray). + */ + unsigned char *xm1d2; + size_t xlen, xm1d2_len, xm1d2_len_u16, u; + uint32_t asize; + unsigned cc; + uint16_t x0i; + + /* + * Compute (x-1)/2 (encoded). + */ + xm1d2 = (unsigned char *)t; + xm1d2_len = ((x[0] - (x[0] >> 4)) + 7) >> 3; + br_i15_encode(xm1d2, xm1d2_len, x); + cc = 0; + for (u = 0; u < xm1d2_len; u ++) { + unsigned w; + + w = xm1d2[u]; + xm1d2[u] = (unsigned char)((w >> 1) | cc); + cc = w << 7; + } + + /* + * We used some words of the provided buffer for (x-1)/2. + */ + xm1d2_len_u16 = (xm1d2_len + 1) >> 1; + t += xm1d2_len_u16; + tlen -= xm1d2_len_u16; + + xlen = (x[0] + 15) >> 4; + asize = x[0] - 1 - EQ0(x[0] & 15); + x0i = br_i15_ninv15(x[1]); + while (n -- > 0) { + uint16_t *a; + uint32_t eq1, eqm1; + + /* + * Generate a random base. We don't need the base to be + * really uniform modulo x, so we just get a random + * number which is one bit shorter than x. + */ + a = t; + a[0] = x[0]; + a[xlen] = 0; + mkrand(rng, a, asize); + + /* + * Compute a^((x-1)/2) mod x. We assume here that the + * function will not fail (the temporary array is large + * enough). + */ + br_i15_modpow_opt(a, xm1d2, xm1d2_len, + x, x0i, t + 1 + xlen, tlen - 1 - xlen); + + /* + * We must obtain either 1 or x-1. Note that x is odd, + * hence x-1 differs from x only in its low word (no + * carry). + */ + eq1 = a[1] ^ 1; + eqm1 = a[1] ^ (x[1] - 1); + for (u = 2; u <= xlen; u ++) { + eq1 |= a[u]; + eqm1 |= a[u] ^ x[u]; + } + + if ((EQ0(eq1) | EQ0(eqm1)) == 0) { + return 0; + } + } + return 1; +} + +/* + * Create a random prime of the provided size. 'size' is the _encoded_ + * bit length. The two top bits and the two bottom bits are set to 1. + */ +static void +mkprime(const br_prng_class **rng, uint16_t *x, uint32_t esize, + uint32_t pubexp, uint16_t *t, size_t tlen) +{ + size_t len; + + x[0] = esize; + len = (esize + 15) >> 4; + for (;;) { + size_t u; + uint32_t m3, m5, m7, m11; + int rounds; + + /* + * Generate random bits. We force the two top bits and the + * two bottom bits to 1. + */ + mkrand(rng, x, esize); + if ((esize & 15) == 0) { + x[len] |= 0x6000; + } else if ((esize & 15) == 1) { + x[len] |= 0x0001; + x[len - 1] |= 0x4000; + } else { + x[len] |= 0x0003 << ((esize & 15) - 2); + } + x[1] |= 0x0003; + + /* + * Trial division with low primes (3, 5, 7 and 11). We + * use the following properties: + * + * 2^2 = 1 mod 3 + * 2^4 = 1 mod 5 + * 2^3 = 1 mod 7 + * 2^10 = 1 mod 11 + */ + m3 = 0; + m5 = 0; + m7 = 0; + m11 = 0; + for (u = 0; u < len; u ++) { + uint32_t w; + + w = x[1 + u]; + m3 += w << (u & 1); + m3 = (m3 & 0xFF) + (m3 >> 8); + m5 += w << ((4 - u) & 3); + m5 = (m5 & 0xFF) + (m5 >> 8); + m7 += w; + m7 = (m7 & 0x1FF) + (m7 >> 9); + m11 += w << (5 & -(u & 1)); + m11 = (m11 & 0x3FF) + (m11 >> 10); + } + + /* + * Maximum values of m* at this point: + * m3: 511 + * m5: 2310 + * m7: 510 + * m11: 2047 + * We use the same properties to make further reductions. + */ + + m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 46 */ + m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 16 */ + m3 = ((m3 * 43) >> 5) & 3; + + m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 263 */ + m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 30 */ + m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 15 */ + m5 -= 10 & -GT(m5, 9); + m5 -= 5 & -GT(m5, 4); + + m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 69 */ + m7 = (m7 & 7) + (m7 >> 3); /* max: 14 */ + m7 = ((m7 * 147) >> 7) & 7; + + /* + * 2^5 = 32 = -1 mod 11. + */ + m11 = (m11 & 0x1F) + 66 - (m11 >> 5); /* max: 97 */ + m11 -= 88 & -GT(m11, 87); + m11 -= 44 & -GT(m11, 43); + m11 -= 22 & -GT(m11, 21); + m11 -= 11 & -GT(m11, 10); + + /* + * If any of these modulo is 0, then the candidate is + * not prime. Also, if pubexp is 3, 5, 7 or 11, and the + * corresponding modulus is 1, then the candidate must + * be rejected, because we need e to be invertible + * modulo p-1. We can use simple comparisons here + * because they won't leak information on a candidate + * that we keep, only on one that we reject (and is thus + * not secret). + */ + if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) { + continue; + } + if ((pubexp == 3 && m3 == 1) + || (pubexp == 5 && m5 == 1) + || (pubexp == 7 && m7 == 1) + || (pubexp == 11 && m11 == 1)) + { + continue; + } + + /* + * More trial divisions. + */ + if (!trial_divisions(x, t)) { + continue; + } + + /* + * Miller-Rabin algorithm. Since we selected a random + * integer, not a maliciously crafted integer, we can use + * relatively few rounds to lower the risk of a false + * positive (i.e. declaring prime a non-prime) under + * 2^(-80). It is not useful to lower the probability much + * below that, since that would be substantially below + * the probability of the hardware misbehaving. Sufficient + * numbers of rounds are extracted from the Handbook of + * Applied Cryptography, note 4.49 (page 149). + * + * Since we work on the encoded size (esize), we need to + * compare with encoded thresholds. + */ + if (esize < 320) { + rounds = 12; + } else if (esize < 480) { + rounds = 9; + } else if (esize < 693) { + rounds = 6; + } else if (esize < 906) { + rounds = 4; + } else if (esize < 1386) { + rounds = 3; + } else { + rounds = 2; + } + + if (miller_rabin(rng, x, rounds, t, tlen)) { + return; + } + } +} + +/* + * Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided + * as parameter (with announced bit length equal to that of p). This + * function computes d = 1/e mod p-1 (for an odd integer e). Returned + * value is 1 on success, 0 on error (an error is reported if e is not + * invertible modulo p-1). + * + * The temporary buffer (t) must have room for at least 4 integers of + * the size of p. + */ +static uint32_t +invert_pubexp(uint16_t *d, const uint16_t *m, uint32_t e, uint16_t *t) +{ + uint16_t *f; + uint32_t r; + + f = t; + t += 1 + ((m[0] + 15) >> 4); + + /* + * Compute d = 1/e mod m. Since p = 3 mod 4, m is odd. + */ + br_i15_zero(d, m[0]); + d[1] = 1; + br_i15_zero(f, m[0]); + f[1] = e & 0x7FFF; + f[2] = (e >> 15) & 0x7FFF; + f[3] = e >> 30; + r = br_i15_moddiv(d, f, m, br_i15_ninv15(m[1]), t); + + /* + * We really want d = 1/e mod p-1, with p = 2m. By the CRT, + * the result is either the d we got, or d + m. + * + * Let's write e*d = 1 + k*m, for some integer k. Integers e + * and m are odd. If d is odd, then e*d is odd, which implies + * that k must be even; in that case, e*d = 1 + (k/2)*2m, and + * thus d is already fine. Conversely, if d is even, then k + * is odd, and we must add m to d in order to get the correct + * result. + */ + br_i15_add(d, m, (uint32_t)(1 - (d[1] & 1))); + + return r; +} + +/* + * Swap two buffers in RAM. They must be disjoint. + */ +static void +bufswap(void *b1, void *b2, size_t len) +{ + size_t u; + unsigned char *buf1, *buf2; + + buf1 = b1; + buf2 = b2; + for (u = 0; u < len; u ++) { + unsigned w; + + w = buf1[u]; + buf1[u] = buf2[u]; + buf2[u] = w; + } +} + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_keygen(const br_prng_class **rng, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp) +{ + uint32_t esize_p, esize_q; + size_t plen, qlen, tlen; + uint16_t *p, *q, *t; + uint16_t tmp[TEMPS]; + uint32_t r; + + if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) { + return 0; + } + if (pubexp == 0) { + pubexp = 3; + } else if (pubexp == 1 || (pubexp & 1) == 0) { + return 0; + } + + esize_p = (size + 1) >> 1; + esize_q = size - esize_p; + sk->n_bitlen = size; + sk->p = kbuf_priv; + sk->plen = (esize_p + 7) >> 3; + sk->q = sk->p + sk->plen; + sk->qlen = (esize_q + 7) >> 3; + sk->dp = sk->q + sk->qlen; + sk->dplen = sk->plen; + sk->dq = sk->dp + sk->dplen; + sk->dqlen = sk->qlen; + sk->iq = sk->dq + sk->dqlen; + sk->iqlen = sk->plen; + + if (pk != NULL) { + pk->n = kbuf_pub; + pk->nlen = (size + 7) >> 3; + pk->e = pk->n + pk->nlen; + pk->elen = 4; + br_enc32be(pk->e, pubexp); + while (*pk->e == 0) { + pk->e ++; + pk->elen --; + } + } + + /* + * We now switch to encoded sizes. + * + * floor((x * 17477) / (2^18)) is equal to floor(x/15) for all + * integers x from 0 to 23833. + */ + esize_p += MUL15(esize_p, 17477) >> 18; + esize_q += MUL15(esize_q, 17477) >> 18; + plen = (esize_p + 15) >> 4; + qlen = (esize_q + 15) >> 4; + p = tmp; + q = p + 1 + plen; + t = q + 1 + qlen; + tlen = ((sizeof tmp) / sizeof(uint16_t)) - (2 + plen + qlen); + + /* + * When looking for primes p and q, we temporarily divide + * candidates by 2, in order to compute the inverse of the + * public exponent. + */ + + for (;;) { + mkprime(rng, p, esize_p, pubexp, t, tlen); + br_i15_rshift(p, 1); + if (invert_pubexp(t, p, pubexp, t + 1 + plen)) { + br_i15_add(p, p, 1); + p[1] |= 1; + br_i15_encode(sk->p, sk->plen, p); + br_i15_encode(sk->dp, sk->dplen, t); + break; + } + } + + for (;;) { + mkprime(rng, q, esize_q, pubexp, t, tlen); + br_i15_rshift(q, 1); + if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) { + br_i15_add(q, q, 1); + q[1] |= 1; + br_i15_encode(sk->q, sk->qlen, q); + br_i15_encode(sk->dq, sk->dqlen, t); + break; + } + } + + /* + * If p and q have the same size, then it is possible that q > p + * (when the target modulus size is odd, we generate p with a + * greater bit length than q). If q > p, we want to swap p and q + * (and also dp and dq) for two reasons: + * - The final step below (inversion of q modulo p) is easier if + * p > q. + * - While BearSSL's RSA code is perfectly happy with RSA keys such + * that p < q, some other implementations have restrictions and + * require p > q. + * + * Note that we can do a simple non-constant-time swap here, + * because the only information we leak here is that we insist on + * returning p and q such that p > q, which is not a secret. + */ + if (esize_p == esize_q && br_i15_sub(p, q, 0) == 1) { + bufswap(p, q, (1 + plen) * sizeof *p); + bufswap(sk->p, sk->q, sk->plen); + bufswap(sk->dp, sk->dq, sk->dplen); + } + + /* + * We have produced p, q, dp and dq. We can now compute iq = 1/d mod p. + * + * We ensured that p >= q, so this is just a matter of updating the + * header word for q (and possibly adding an extra word). + * + * Theoretically, the call below may fail, in case we were + * extraordinarily unlucky, and p = q. Another failure case is if + * Miller-Rabin failed us _twice_, and p and q are non-prime and + * have a factor is common. We report the error mostly because it + * is cheap and we can, but in practice this never happens (or, at + * least, it happens way less often than hardware glitches). + */ + q[0] = p[0]; + if (plen > qlen) { + q[plen] = 0; + t ++; + tlen --; + } + br_i15_zero(t, p[0]); + t[1] = 1; + r = br_i15_moddiv(t, q, p, br_i15_ninv15(p[1]), t + 1 + plen); + br_i15_encode(sk->iq, sk->iqlen, t); + + /* + * Compute the public modulus too, if required. + */ + if (pk != NULL) { + br_i15_zero(t, p[0]); + br_i15_mulacc(t, p, q); + br_i15_encode(pk->n, pk->nlen, t); + } + + return r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_modulus.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_modulus.c new file mode 100644 index 0000000..16458c3 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_modulus.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +size_t +br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk) +{ + uint16_t tmp[4 * (((BR_MAX_RSA_SIZE / 2) + 14) / 15) + 5]; + uint16_t *t, *p, *q; + const unsigned char *pbuf, *qbuf; + size_t nlen, plen, qlen, tlen; + + /* + * Compute actual byte and lengths for p and q. + */ + pbuf = sk->p; + plen = sk->plen; + while (plen > 0 && *pbuf == 0) { + pbuf ++; + plen --; + } + qbuf = sk->q; + qlen = sk->qlen; + while (qlen > 0 && *qbuf == 0) { + qbuf ++; + qlen --; + } + + t = tmp; + tlen = (sizeof tmp) / (sizeof tmp[0]); + + /* + * Decode p. + */ + if ((15 * tlen) < (plen << 3) + 15) { + return 0; + } + br_i15_decode(t, pbuf, plen); + p = t; + plen = (p[0] + 31) >> 4; + t += plen; + tlen -= plen; + + /* + * Decode q. + */ + if ((15 * tlen) < (qlen << 3) + 15) { + return 0; + } + br_i15_decode(t, qbuf, qlen); + q = t; + qlen = (q[0] + 31) >> 4; + t += qlen; + tlen -= qlen; + + /* + * Computation can proceed only if we have enough room for the + * modulus. + */ + if (tlen < (plen + qlen + 1)) { + return 0; + } + + /* + * Private key already contains the modulus bit length, from which + * we can infer the output length. Even if n is NULL, we still had + * to decode p and q to make sure that the product can be computed. + */ + nlen = (sk->n_bitlen + 7) >> 3; + if (n != NULL) { + br_i15_zero(t, p[0]); + br_i15_mulacc(t, p, q); + br_i15_encode(n, nlen, t); + } + return nlen; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_oaep_decrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_oaep_decrypt.c new file mode 100644 index 0000000..927eecd --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_oaep_decrypt.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_oaep_decrypt(const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len) +{ + uint32_t r; + + if (*len != ((sk->n_bitlen + 7) >> 3)) { + return 0; + } + r = br_rsa_i15_private(data, sk); + r &= br_rsa_oaep_unpad(dig, label, label_len, data, len); + return r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_oaep_encrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_oaep_encrypt.c new file mode 100644 index 0000000..b9a6cfa --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_oaep_encrypt.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +size_t +br_rsa_i15_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len) +{ + size_t dlen; + + dlen = br_rsa_oaep_pad(rnd, dig, label, label_len, + pk, dst, dst_max_len, src, src_len); + if (dlen == 0) { + return 0; + } + return dlen & -(size_t)br_rsa_i15_public(dst, dlen, pk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pkcs1_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pkcs1_sign.c new file mode 100644 index 0000000..f519423 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pkcs1_sign.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x) +{ + if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) { + return 0; + } + return br_rsa_i15_private(x, sk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pkcs1_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pkcs1_vrfy.c new file mode 100644 index 0000000..2c35184 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pkcs1_vrfy.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out) +{ + unsigned char sig[BR_MAX_RSA_SIZE >> 3]; + + if (xlen > (sizeof sig)) { + return 0; + } + memcpy(sig, x, xlen); + if (!br_rsa_i15_public(sig, xlen, pk)) { + return 0; + } + return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_priv.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_priv.c new file mode 100644 index 0000000..177cc3a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_priv.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15)) +#define TLEN (8 * U) + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk) +{ + const unsigned char *p, *q; + size_t plen, qlen; + size_t fwlen; + uint16_t p0i, q0i; + size_t xlen, u; + uint16_t tmp[1 + TLEN]; + long z; + uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; + uint32_t r; + + /* + * Compute the actual lengths of p and q, in bytes. + * These lengths are not considered secret (we cannot really hide + * them anyway in constant-time code). + */ + p = sk->p; + plen = sk->plen; + while (plen > 0 && *p == 0) { + p ++; + plen --; + } + q = sk->q; + qlen = sk->qlen; + while (qlen > 0 && *q == 0) { + q ++; + qlen --; + } + + /* + * Compute the maximum factor length, in words. + */ + z = (long)(plen > qlen ? plen : qlen) << 3; + fwlen = 1; + while (z > 0) { + z -= 15; + fwlen ++; + } + /* + * Round up the word length to an even number. + */ + fwlen += (fwlen & 1); + + /* + * We need to fit at least 6 values in the stack buffer. + */ + if (6 * fwlen > TLEN) { + return 0; + } + + /* + * Compute signature length (in bytes). + */ + xlen = (sk->n_bitlen + 7) >> 3; + + /* + * Ensure 32-bit alignment for value words. + */ + mq = tmp; + if (((uintptr_t)mq & 2) == 0) { + mq ++; + } + + /* + * Decode q. + */ + br_i15_decode(mq, q, qlen); + + /* + * Decode p. + */ + t1 = mq + fwlen; + br_i15_decode(t1, p, plen); + + /* + * Compute the modulus (product of the two factors), to compare + * it with the source value. We use br_i15_mulacc(), since it's + * already used later on. + */ + t2 = mq + 2 * fwlen; + br_i15_zero(t2, mq[0]); + br_i15_mulacc(t2, mq, t1); + + /* + * We encode the modulus into bytes, to perform the comparison + * with bytes. We know that the product length, in bytes, is + * exactly xlen. + * The comparison actually computes the carry when subtracting + * the modulus from the source value; that carry must be 1 for + * a value in the correct range. We keep it in r, which is our + * accumulator for the error code. + */ + t3 = mq + 4 * fwlen; + br_i15_encode(t3, xlen, t2); + u = xlen; + r = 0; + while (u > 0) { + uint32_t wn, wx; + + u --; + wn = ((unsigned char *)t3)[u]; + wx = x[u]; + r = ((wx - (wn + r)) >> 8) & 1; + } + + /* + * Move the decoded p to another temporary buffer. + */ + mp = mq + 2 * fwlen; + memmove(mp, t1, fwlen * sizeof *t1); + + /* + * Compute s2 = x^dq mod q. + */ + q0i = br_i15_ninv15(mq[1]); + s2 = mq + fwlen; + br_i15_decode_reduce(s2, x, xlen, mq); + r &= br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i, + mq + 3 * fwlen, TLEN - 3 * fwlen); + + /* + * Compute s1 = x^dq mod q. + */ + p0i = br_i15_ninv15(mp[1]); + s1 = mq + 3 * fwlen; + br_i15_decode_reduce(s1, x, xlen, mp); + r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i, + mq + 4 * fwlen, TLEN - 4 * fwlen); + + /* + * Compute: + * h = (s1 - s2)*(1/q) mod p + * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is + * unclear about whether p may be lower than q (some existing, + * widely deployed implementations of RSA don't tolerate p < q), + * but we want to support that occurrence, so we need to use the + * reduction function. + * + * Since we use br_i15_decode_reduce() for iq (purportedly, the + * inverse of q modulo p), we also tolerate improperly large + * values for this parameter. + */ + t1 = mq + 4 * fwlen; + t2 = mq + 5 * fwlen; + br_i15_reduce(t2, s2, mp); + br_i15_add(s1, mp, br_i15_sub(s1, t2, 1)); + br_i15_to_monty(s1, mp); + br_i15_decode_reduce(t1, sk->iq, sk->iqlen, mp); + br_i15_montymul(t2, s1, t1, mp, p0i); + + /* + * h is now in t2. We compute the final result: + * s = s2 + q*h + * All these operations are non-modular. + * + * We need mq, s2 and t2. We use the t3 buffer as destination. + * The buffers mp, s1 and t1 are no longer needed, so we can + * reuse them for t3. Moreover, the first step of the computation + * is to copy s2 into t3, after which s2 is not needed. Right + * now, mq is in slot 0, s2 is in slot 1, and t2 in slot 5. + * Therefore, we have ample room for t3 by simply using s2. + */ + t3 = s2; + br_i15_mulacc(t3, mq, t2); + + /* + * Encode the result. Since we already checked the value of xlen, + * we can just use it right away. + */ + br_i15_encode(x, xlen, t3); + + /* + * The only error conditions remaining at that point are invalid + * values for p and q (even integers). + */ + return p0i & q0i & r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_privexp.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_privexp.c new file mode 100644 index 0000000..57d6918 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_privexp.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +size_t +br_rsa_i15_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t e) +{ + /* + * We want to invert e modulo phi = (p-1)(q-1). This first + * requires computing phi, which is easy since we have the factors + * p and q in the private key structure. + * + * Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer. + * We could invert e modulo phi/4 then patch the result to + * modulo phi, but this would involve assembling three modulus-wide + * values (phi/4, 1 and e) and calling moddiv, that requires + * three more temporaries, for a total of six big integers, or + * slightly more than 3 kB of stack space for RSA-4096. This + * exceeds our stack requirements. + * + * Instead, we first use one step of the extended GCD: + * + * - We compute phi = k*e + r (Euclidean division of phi by e). + * If public exponent e is correct, then r != 0 (e must be + * invertible modulo phi). We also have k != 0 since we + * enforce non-ridiculously-small factors. + * + * - We find small u, v such that u*e - v*r = 1 (using a + * binary GCD; we can arrange for u < r and v < e, i.e. all + * values fit on 32 bits). + * + * - Solution is: d = u + v*k + * This last computation is exact: since u < r and v < e, + * the above implies d < r + e*((phi-r)/e) = phi + */ + + uint16_t tmp[4 * ((BR_MAX_RSA_FACTOR + 14) / 15) + 12]; + uint16_t *p, *q, *k, *m, *z, *phi; + const unsigned char *pbuf, *qbuf; + size_t plen, qlen, u, len, dlen; + uint32_t r, a, b, u0, v0, u1, v1, he, hr; + int i; + + /* + * Check that e is correct. + */ + if (e < 3 || (e & 1) == 0) { + return 0; + } + + /* + * Check lengths of p and q, and that they are both odd. + */ + pbuf = sk->p; + plen = sk->plen; + while (plen > 0 && *pbuf == 0) { + pbuf ++; + plen --; + } + if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8) + || (pbuf[plen - 1] & 1) != 1) + { + return 0; + } + qbuf = sk->q; + qlen = sk->qlen; + while (qlen > 0 && *qbuf == 0) { + qbuf ++; + qlen --; + } + if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8) + || (qbuf[qlen - 1] & 1) != 1) + { + return 0; + } + + /* + * Output length is that of the modulus. + */ + dlen = (sk->n_bitlen + 7) >> 3; + if (d == NULL) { + return dlen; + } + + p = tmp; + br_i15_decode(p, pbuf, plen); + plen = (p[0] + 15) >> 4; + q = p + 1 + plen; + br_i15_decode(q, qbuf, qlen); + qlen = (q[0] + 15) >> 4; + + /* + * Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that + * we do not need anymore). The mulacc function sets the announced + * bit length of t to be the sum of the announced bit lengths of + * p-1 and q-1, which is usually exact but may overshoot by one 1 + * bit in some cases; we readjust it to its true length. + */ + p[1] --; + q[1] --; + phi = q + 1 + qlen; + br_i15_zero(phi, p[0]); + br_i15_mulacc(phi, p, q); + len = (phi[0] + 15) >> 4; + memmove(tmp, phi, (1 + len) * sizeof *phi); + phi = tmp; + phi[0] = br_i15_bit_length(phi + 1, len); + len = (phi[0] + 15) >> 4; + + /* + * Divide phi by public exponent e. The final remainder r must be + * non-zero (otherwise, the key is invalid). The quotient is k, + * which we write over phi, since we don't need phi after that. + */ + r = 0; + for (u = len; u >= 1; u --) { + /* + * Upon entry, r < e, and phi[u] < 2^15; hence, + * hi:lo < e*2^15. Thus, the produced word k[u] + * must be lower than 2^15, and the new remainder r + * is lower than e. + */ + uint32_t hi, lo; + + hi = r >> 17; + lo = (r << 15) + phi[u]; + phi[u] = br_divrem(hi, lo, e, &r); + } + if (r == 0) { + return 0; + } + k = phi; + + /* + * Compute u and v such that u*e - v*r = GCD(e,r). We use + * a binary GCD algorithm, with 6 extra integers a, b, + * u0, u1, v0 and v1. Initial values are: + * a = e u0 = 1 v0 = 0 + * b = r u1 = r v1 = e-1 + * The following invariants are maintained: + * a = u0*e - v0*r + * b = u1*e - v1*r + * 0 < a <= e + * 0 < b <= r + * 0 <= u0 <= r + * 0 <= v0 <= e + * 0 <= u1 <= r + * 0 <= v1 <= e + * + * At each iteration, we reduce either a or b by one bit, and + * adjust u0, u1, v0 and v1 to maintain the invariants: + * - if a is even, then a <- a/2 + * - otherwise, if b is even, then b <- b/2 + * - otherwise, if a > b, then a <- (a-b)/2 + * - otherwise, if b > a, then b <- (b-a)/2 + * Algorithm stops when a = b. At that point, the common value + * is the GCD of e and r; it must be 1 (otherwise, the private + * key or public exponent is not valid). The (u0,v0) or (u1,v1) + * pairs are the solution we are looking for. + * + * Since either a or b is reduced by at least 1 bit at each + * iteration, 62 iterations are enough to reach the end + * condition. + * + * To maintain the invariants, we must compute the same operations + * on the u* and v* values that we do on a and b: + * - When a is divided by 2, u0 and v0 must be divided by 2. + * - When b is divided by 2, u1 and v1 must be divided by 2. + * - When b is subtracted from a, u1 and v1 are subtracted from + * u0 and v0, respectively. + * - When a is subtracted from b, u0 and v0 are subtracted from + * u1 and v1, respectively. + * + * However, we want to keep the u* and v* values in their proper + * ranges. The following remarks apply: + * + * - When a is divided by 2, then a is even. Therefore: + * + * * If r is odd, then u0 and v0 must have the same parity; + * if they are both odd, then adding r to u0 and e to v0 + * makes them both even, and the division by 2 brings them + * back to the proper range. + * + * * If r is even, then u0 must be even; if v0 is odd, then + * adding r to u0 and e to v0 makes them both even, and the + * division by 2 brings them back to the proper range. + * + * Thus, all we need to do is to look at the parity of v0, + * and add (r,e) to (u0,v0) when v0 is odd. In order to avoid + * a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the + * division (r+1 does not overflow since r < e; and (e/2)+1 + * is equal to (e+1)/2 since e is odd). + * + * - When we subtract b from a, three cases may occur: + * + * * u1 <= u0 and v1 <= v0: just do the subtractions + * + * * u1 > u0 and v1 > v0: compute: + * (u0, v0) <- (u0 + r - u1, v0 + e - v1) + * + * * u1 <= u0 and v1 > v0: compute: + * (u0, v0) <- (u0 + r - u1, v0 + e - v1) + * + * The fourth case (u1 > u0 and v1 <= v0) is not possible + * because it would contradict "b < a" (which is the reason + * why we subtract b from a). + * + * The tricky case is the third one: from the equations, it + * seems that u0 may go out of range. However, the invariants + * and ranges of other values imply that, in that case, the + * new u0 does not actually exceed the range. + * + * We can thus handle the subtraction by adding (r,e) based + * solely on the comparison between v0 and v1. + */ + a = e; + b = r; + u0 = 1; + v0 = 0; + u1 = r; + v1 = e - 1; + hr = (r + 1) >> 1; + he = (e >> 1) + 1; + for (i = 0; i < 62; i ++) { + uint32_t oa, ob, agtb, bgta; + uint32_t sab, sba, da, db; + uint32_t ctl; + + oa = a & 1; /* 1 if a is odd */ + ob = b & 1; /* 1 if b is odd */ + agtb = GT(a, b); /* 1 if a > b */ + bgta = GT(b, a); /* 1 if b > a */ + + sab = oa & ob & agtb; /* 1 if a <- a-b */ + sba = oa & ob & bgta; /* 1 if b <- b-a */ + + /* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */ + ctl = GT(v1, v0); + a -= b & -sab; + u0 -= (u1 - (r & -ctl)) & -sab; + v0 -= (v1 - (e & -ctl)) & -sab; + + /* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */ + ctl = GT(v0, v1); + b -= a & -sba; + u1 -= (u0 - (r & -ctl)) & -sba; + v1 -= (v0 - (e & -ctl)) & -sba; + + da = NOT(oa) | sab; /* 1 if a <- a/2 */ + db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */ + + /* a <- a/2, u0 <- u0/2, v0 <- v0/2 */ + ctl = v0 & 1; + a ^= (a ^ (a >> 1)) & -da; + u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da; + v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da; + + /* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */ + ctl = v1 & 1; + b ^= (b ^ (b >> 1)) & -db; + u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db; + v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db; + } + + /* + * Check that the GCD is indeed 1. If not, then the key is invalid + * (and there's no harm in leaking that piece of information). + */ + if (a != 1) { + return 0; + } + + /* + * Now we have u0*e - v0*r = 1. Let's compute the result as: + * d = u0 + v0*k + * We still have k in the tmp[] array, and its announced bit + * length is that of phi. + */ + m = k + 1 + len; + m[0] = (2 << 4) + 2; /* bit length is 32 bits, encoded */ + m[1] = v0 & 0x7FFF; + m[2] = (v0 >> 15) & 0x7FFF; + m[3] = v0 >> 30; + z = m + 4; + br_i15_zero(z, k[0]); + z[1] = u0 & 0x7FFF; + z[2] = (u0 >> 15) & 0x7FFF; + z[3] = u0 >> 30; + br_i15_mulacc(z, k, m); + + /* + * Encode the result. + */ + br_i15_encode(d, dlen, z); + return dlen; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pss_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pss_sign.c new file mode 100644 index 0000000..dd9385b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pss_sign.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x) +{ + if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash, + salt_len, sk->n_bitlen, x)) + { + return 0; + } + return br_rsa_i15_private(x, sk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pss_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pss_vrfy.c new file mode 100644 index 0000000..7d9f2cb --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pss_vrfy.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk) +{ + unsigned char sig[BR_MAX_RSA_SIZE >> 3]; + + if (xlen > (sizeof sig)) { + return 0; + } + memcpy(sig, x, xlen); + if (!br_rsa_i15_public(sig, xlen, pk)) { + return 0; + } + return br_rsa_pss_sig_unpad(hf_data, hf_mgf1, + hash, salt_len, pk, sig); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pub.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pub.c new file mode 100644 index 0000000..9eab5e8 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pub.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * As a strict minimum, we need four buffers that can hold a + * modular integer. + */ +#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 14) / 15))) + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk) +{ + const unsigned char *n; + size_t nlen; + uint16_t tmp[1 + TLEN]; + uint16_t *m, *a, *t; + size_t fwlen; + long z; + uint16_t m0i; + uint32_t r; + + /* + * Get the actual length of the modulus, and see if it fits within + * our stack buffer. We also check that the length of x[] is valid. + */ + n = pk->n; + nlen = pk->nlen; + while (nlen > 0 && *n == 0) { + n ++; + nlen --; + } + if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) { + return 0; + } + z = (long)nlen << 3; + fwlen = 1; + while (z > 0) { + z -= 15; + fwlen ++; + } + /* + * Round up length to an even number. + */ + fwlen += (fwlen & 1); + + /* + * The modulus gets decoded into m[]. + * The value to exponentiate goes into a[]. + * The temporaries for modular exponentiations are in t[]. + * + * We want the first value word of each integer to be aligned + * on a 32-bit boundary. + */ + m = tmp; + if (((uintptr_t)m & 2) == 0) { + m ++; + } + a = m + fwlen; + t = m + 2 * fwlen; + + /* + * Decode the modulus. + */ + br_i15_decode(m, n, nlen); + m0i = br_i15_ninv15(m[1]); + + /* + * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be + * an odd integer. + */ + r = m0i & 1; + + /* + * Decode x[] into a[]; we also check that its value is proper. + */ + r &= br_i15_decode_mod(a, x, xlen, m); + + /* + * Compute the modular exponentiation. + */ + br_i15_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen); + + /* + * Encode the result. + */ + br_i15_encode(x, xlen, a); + return r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pubexp.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pubexp.c new file mode 100644 index 0000000..803bff7 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i15_pubexp.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * Recompute public exponent, based on factor p and reduced private + * exponent dp. + */ +static uint32_t +get_pubexp(const unsigned char *pbuf, size_t plen, + const unsigned char *dpbuf, size_t dplen) +{ + /* + * dp is the inverse of e modulo p-1. If p = 3 mod 4, then + * p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1; + * thus, dp must be odd. + * + * We compute the inverse of dp modulo (p-1)/2. This requires + * first reducing dp modulo (p-1)/2 (this can be done with a + * conditional subtract, no need to use the generic modular + * reduction function); then, we use moddiv. + */ + + uint16_t tmp[6 * ((BR_MAX_RSA_FACTOR + 29) / 15)]; + uint16_t *p, *dp, *x; + size_t len; + uint32_t e; + + /* + * Compute actual factor length (in bytes) and check that it fits + * under our size constraints. + */ + while (plen > 0 && *pbuf == 0) { + pbuf ++; + plen --; + } + if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) { + return 0; + } + + /* + * Compute actual reduced exponent length (in bytes) and check that + * it is not longer than p. + */ + while (dplen > 0 && *dpbuf == 0) { + dpbuf ++; + dplen --; + } + if (dplen > plen || dplen == 0 + || (dplen == plen && dpbuf[0] > pbuf[0])) + { + return 0; + } + + /* + * Verify that p = 3 mod 4 and that dp is odd. + */ + if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) { + return 0; + } + + /* + * Decode p and compute (p-1)/2. + */ + p = tmp; + br_i15_decode(p, pbuf, plen); + len = (p[0] + 31) >> 4; + br_i15_rshift(p, 1); + + /* + * Decode dp and make sure its announced bit length matches that of + * p (we already know that the size of dp, in bits, does not exceed + * the size of p, so we just have to copy the header word). + */ + dp = p + len; + memset(dp, 0, len * sizeof *dp); + br_i15_decode(dp, dpbuf, dplen); + dp[0] = p[0]; + + /* + * Subtract (p-1)/2 from dp if necessary. + */ + br_i15_sub(dp, p, NOT(br_i15_sub(dp, p, 0))); + + /* + * If another subtraction is needed, then this means that the + * value was invalid. We don't care to leak information about + * invalid keys. + */ + if (br_i15_sub(dp, p, 0) == 0) { + return 0; + } + + /* + * Invert dp modulo (p-1)/2. If the inversion fails, then the + * key value was invalid. + */ + x = dp + len; + br_i15_zero(x, p[0]); + x[1] = 1; + if (br_i15_moddiv(x, dp, p, br_i15_ninv15(p[1]), x + len) == 0) { + return 0; + } + + /* + * We now have an inverse. We must set it to zero (error) if its + * length is greater than 32 bits and/or if it is an even integer. + * Take care that the bit_length function returns an encoded + * bit length. + */ + e = (uint32_t)x[1] | ((uint32_t)x[2] << 15) | ((uint32_t)x[3] << 30); + e &= -LT(br_i15_bit_length(x + 1, len - 1), 35); + e &= -(e & 1); + return e; +} + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk) +{ + /* + * Get the public exponent from both p and q. This is the right + * exponent if we get twice the same value. + */ + uint32_t ep, eq; + + ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen); + eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen); + return ep & -EQ(ep, eq); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_keygen.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_keygen.c new file mode 100644 index 0000000..77708f8 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_keygen.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_keygen(const br_prng_class **rng, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp) +{ + return br_rsa_i31_keygen_inner(rng, + sk, kbuf_priv, pk, kbuf_pub, size, pubexp, + &br_i31_modpow_opt); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_keygen_inner.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_keygen_inner.c new file mode 100644 index 0000000..98df445 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_keygen_inner.c @@ -0,0 +1,608 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * Make a random integer of the provided size. The size is encoded. + * The header word is untouched. + */ +static void +mkrand(const br_prng_class **rng, uint32_t *x, uint32_t esize) +{ + size_t u, len; + unsigned m; + + len = (esize + 31) >> 5; + (*rng)->generate(rng, x + 1, len * sizeof(uint32_t)); + for (u = 1; u < len; u ++) { + x[u] &= 0x7FFFFFFF; + } + m = esize & 31; + if (m == 0) { + x[len] &= 0x7FFFFFFF; + } else { + x[len] &= 0x7FFFFFFF >> (31 - m); + } +} + +/* + * This is the big-endian unsigned representation of the product of + * all small primes from 13 to 1481. + */ +static const unsigned char SMALL_PRIMES[] = { + 0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A, + 0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7, + 0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37, + 0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5, + 0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E, + 0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6, + 0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C, + 0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40, + 0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50, + 0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7, + 0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3, + 0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E, + 0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC, + 0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08, + 0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B, + 0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22, + 0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77, + 0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E, + 0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80, + 0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8, + 0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2, + 0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC, + 0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54, + 0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74, + 0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C, + 0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD +}; + +/* + * We need temporary values for at least 7 integers of the same size + * as a factor (including header word); more space helps with performance + * (in modular exponentiations), but we much prefer to remain under + * 2 kilobytes in total, to save stack space. The macro TEMPS below + * exceeds 512 (which is a count in 32-bit words) when BR_MAX_RSA_SIZE + * is greater than 4464 (default value is 4096, so the 2-kB limit is + * maintained unless BR_MAX_RSA_SIZE was modified). + */ +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define ROUND2(x) ((((x) + 1) >> 1) << 1) + +#define TEMPS MAX(512, ROUND2(7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 61) / 31))) + +/* + * Perform trial division on a candidate prime. This computes + * y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The + * br_i31_moddiv() function will report an error if y is not invertible + * modulo x. Returned value is 1 on success (none of the small primes + * divides x), 0 on error (a non-trivial GCD is obtained). + * + * This function assumes that x is odd. + */ +static uint32_t +trial_divisions(const uint32_t *x, uint32_t *t) +{ + uint32_t *y; + uint32_t x0i; + + y = t; + t += 1 + ((x[0] + 31) >> 5); + x0i = br_i31_ninv31(x[1]); + br_i31_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x); + return br_i31_moddiv(y, y, x, x0i, t); +} + +/* + * Perform n rounds of Miller-Rabin on the candidate prime x. This + * function assumes that x = 3 mod 4. + * + * Returned value is 1 on success (all rounds completed successfully), + * 0 otherwise. + */ +static uint32_t +miller_rabin(const br_prng_class **rng, const uint32_t *x, int n, + uint32_t *t, size_t tlen, br_i31_modpow_opt_type mp31) +{ + /* + * Since x = 3 mod 4, the Miller-Rabin test is simple: + * - get a random base a (such that 1 < a < x-1) + * - compute z = a^((x-1)/2) mod x + * - if z != 1 and z != x-1, the number x is composite + * + * We generate bases 'a' randomly with a size which is + * one bit less than x, which ensures that a < x-1. It + * is not useful to verify that a > 1 because the probability + * that we get a value a equal to 0 or 1 is much smaller + * than the probability of our Miller-Rabin tests not to + * detect a composite, which is already quite smaller than the + * probability of the hardware misbehaving and return a + * composite integer because of some glitch (e.g. bad RAM + * or ill-timed cosmic ray). + */ + unsigned char *xm1d2; + size_t xlen, xm1d2_len, xm1d2_len_u32, u; + uint32_t asize; + unsigned cc; + uint32_t x0i; + + /* + * Compute (x-1)/2 (encoded). + */ + xm1d2 = (unsigned char *)t; + xm1d2_len = ((x[0] - (x[0] >> 5)) + 7) >> 3; + br_i31_encode(xm1d2, xm1d2_len, x); + cc = 0; + for (u = 0; u < xm1d2_len; u ++) { + unsigned w; + + w = xm1d2[u]; + xm1d2[u] = (unsigned char)((w >> 1) | cc); + cc = w << 7; + } + + /* + * We used some words of the provided buffer for (x-1)/2. + */ + xm1d2_len_u32 = (xm1d2_len + 3) >> 2; + t += xm1d2_len_u32; + tlen -= xm1d2_len_u32; + + xlen = (x[0] + 31) >> 5; + asize = x[0] - 1 - EQ0(x[0] & 31); + x0i = br_i31_ninv31(x[1]); + while (n -- > 0) { + uint32_t *a, *t2; + uint32_t eq1, eqm1; + size_t t2len; + + /* + * Generate a random base. We don't need the base to be + * really uniform modulo x, so we just get a random + * number which is one bit shorter than x. + */ + a = t; + a[0] = x[0]; + a[xlen] = 0; + mkrand(rng, a, asize); + + /* + * Compute a^((x-1)/2) mod x. We assume here that the + * function will not fail (the temporary array is large + * enough). + */ + t2 = t + 1 + xlen; + t2len = tlen - 1 - xlen; + if ((t2len & 1) != 0) { + /* + * Since the source array is 64-bit aligned and + * has an even number of elements (TEMPS), we + * can use the parity of the remaining length to + * detect and adjust alignment. + */ + t2 ++; + t2len --; + } + mp31(a, xm1d2, xm1d2_len, x, x0i, t2, t2len); + + /* + * We must obtain either 1 or x-1. Note that x is odd, + * hence x-1 differs from x only in its low word (no + * carry). + */ + eq1 = a[1] ^ 1; + eqm1 = a[1] ^ (x[1] - 1); + for (u = 2; u <= xlen; u ++) { + eq1 |= a[u]; + eqm1 |= a[u] ^ x[u]; + } + + if ((EQ0(eq1) | EQ0(eqm1)) == 0) { + return 0; + } + } + return 1; +} + +/* + * Create a random prime of the provided size. 'size' is the _encoded_ + * bit length. The two top bits and the two bottom bits are set to 1. + */ +static void +mkprime(const br_prng_class **rng, uint32_t *x, uint32_t esize, + uint32_t pubexp, uint32_t *t, size_t tlen, br_i31_modpow_opt_type mp31) +{ + size_t len; + + x[0] = esize; + len = (esize + 31) >> 5; + for (;;) { + size_t u; + uint32_t m3, m5, m7, m11; + int rounds, s7, s11; + + /* + * Generate random bits. We force the two top bits and the + * two bottom bits to 1. + */ + mkrand(rng, x, esize); + if ((esize & 31) == 0) { + x[len] |= 0x60000000; + } else if ((esize & 31) == 1) { + x[len] |= 0x00000001; + x[len - 1] |= 0x40000000; + } else { + x[len] |= 0x00000003 << ((esize & 31) - 2); + } + x[1] |= 0x00000003; + + /* + * Trial division with low primes (3, 5, 7 and 11). We + * use the following properties: + * + * 2^2 = 1 mod 3 + * 2^4 = 1 mod 5 + * 2^3 = 1 mod 7 + * 2^10 = 1 mod 11 + */ + m3 = 0; + m5 = 0; + m7 = 0; + m11 = 0; + s7 = 0; + s11 = 0; + for (u = 0; u < len; u ++) { + uint32_t w, w3, w5, w7, w11; + + w = x[1 + u]; + w3 = (w & 0xFFFF) + (w >> 16); /* max: 98302 */ + w5 = (w & 0xFFFF) + (w >> 16); /* max: 98302 */ + w7 = (w & 0x7FFF) + (w >> 15); /* max: 98302 */ + w11 = (w & 0xFFFFF) + (w >> 20); /* max: 1050622 */ + + m3 += w3 << (u & 1); + m3 = (m3 & 0xFF) + (m3 >> 8); /* max: 1025 */ + + m5 += w5 << ((4 - u) & 3); + m5 = (m5 & 0xFFF) + (m5 >> 12); /* max: 4479 */ + + m7 += w7 << s7; + m7 = (m7 & 0x1FF) + (m7 >> 9); /* max: 1280 */ + if (++ s7 == 3) { + s7 = 0; + } + + m11 += w11 << s11; + if (++ s11 == 10) { + s11 = 0; + } + m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 526847 */ + } + + m3 = (m3 & 0x3F) + (m3 >> 6); /* max: 78 */ + m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 18 */ + m3 = ((m3 * 43) >> 5) & 3; + + m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 271 */ + m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 31 */ + m5 -= 20 & -GT(m5, 19); + m5 -= 10 & -GT(m5, 9); + m5 -= 5 & -GT(m5, 4); + + m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 82 */ + m7 = (m7 & 0x07) + (m7 >> 3); /* max: 16 */ + m7 = ((m7 * 147) >> 7) & 7; + + /* + * 2^5 = 32 = -1 mod 11. + */ + m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 1536 */ + m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 1023 */ + m11 = (m11 & 0x1F) + 33 - (m11 >> 5); /* max: 64 */ + m11 -= 44 & -GT(m11, 43); + m11 -= 22 & -GT(m11, 21); + m11 -= 11 & -GT(m11, 10); + + /* + * If any of these modulo is 0, then the candidate is + * not prime. Also, if pubexp is 3, 5, 7 or 11, and the + * corresponding modulus is 1, then the candidate must + * be rejected, because we need e to be invertible + * modulo p-1. We can use simple comparisons here + * because they won't leak information on a candidate + * that we keep, only on one that we reject (and is thus + * not secret). + */ + if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) { + continue; + } + if ((pubexp == 3 && m3 == 1) + || (pubexp == 5 && m5 == 1) + || (pubexp == 7 && m7 == 1) + || (pubexp == 11 && m11 == 1)) + { + continue; + } + + /* + * More trial divisions. + */ + if (!trial_divisions(x, t)) { + continue; + } + + /* + * Miller-Rabin algorithm. Since we selected a random + * integer, not a maliciously crafted integer, we can use + * relatively few rounds to lower the risk of a false + * positive (i.e. declaring prime a non-prime) under + * 2^(-80). It is not useful to lower the probability much + * below that, since that would be substantially below + * the probability of the hardware misbehaving. Sufficient + * numbers of rounds are extracted from the Handbook of + * Applied Cryptography, note 4.49 (page 149). + * + * Since we work on the encoded size (esize), we need to + * compare with encoded thresholds. + */ + if (esize < 309) { + rounds = 12; + } else if (esize < 464) { + rounds = 9; + } else if (esize < 670) { + rounds = 6; + } else if (esize < 877) { + rounds = 4; + } else if (esize < 1341) { + rounds = 3; + } else { + rounds = 2; + } + + if (miller_rabin(rng, x, rounds, t, tlen, mp31)) { + return; + } + } +} + +/* + * Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided + * as parameter (with announced bit length equal to that of p). This + * function computes d = 1/e mod p-1 (for an odd integer e). Returned + * value is 1 on success, 0 on error (an error is reported if e is not + * invertible modulo p-1). + * + * The temporary buffer (t) must have room for at least 4 integers of + * the size of p. + */ +static uint32_t +invert_pubexp(uint32_t *d, const uint32_t *m, uint32_t e, uint32_t *t) +{ + uint32_t *f; + uint32_t r; + + f = t; + t += 1 + ((m[0] + 31) >> 5); + + /* + * Compute d = 1/e mod m. Since p = 3 mod 4, m is odd. + */ + br_i31_zero(d, m[0]); + d[1] = 1; + br_i31_zero(f, m[0]); + f[1] = e & 0x7FFFFFFF; + f[2] = e >> 31; + r = br_i31_moddiv(d, f, m, br_i31_ninv31(m[1]), t); + + /* + * We really want d = 1/e mod p-1, with p = 2m. By the CRT, + * the result is either the d we got, or d + m. + * + * Let's write e*d = 1 + k*m, for some integer k. Integers e + * and m are odd. If d is odd, then e*d is odd, which implies + * that k must be even; in that case, e*d = 1 + (k/2)*2m, and + * thus d is already fine. Conversely, if d is even, then k + * is odd, and we must add m to d in order to get the correct + * result. + */ + br_i31_add(d, m, (uint32_t)(1 - (d[1] & 1))); + + return r; +} + +/* + * Swap two buffers in RAM. They must be disjoint. + */ +static void +bufswap(void *b1, void *b2, size_t len) +{ + size_t u; + unsigned char *buf1, *buf2; + + buf1 = b1; + buf2 = b2; + for (u = 0; u < len; u ++) { + unsigned w; + + w = buf1[u]; + buf1[u] = buf2[u]; + buf2[u] = w; + } +} + +/* see inner.h */ +uint32_t +br_rsa_i31_keygen_inner(const br_prng_class **rng, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31) +{ + uint32_t esize_p, esize_q; + size_t plen, qlen, tlen; + uint32_t *p, *q, *t; + union { + uint32_t t32[TEMPS]; + uint64_t t64[TEMPS >> 1]; /* for 64-bit alignment */ + } tmp; + uint32_t r; + + if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) { + return 0; + } + if (pubexp == 0) { + pubexp = 3; + } else if (pubexp == 1 || (pubexp & 1) == 0) { + return 0; + } + + esize_p = (size + 1) >> 1; + esize_q = size - esize_p; + sk->n_bitlen = size; + sk->p = kbuf_priv; + sk->plen = (esize_p + 7) >> 3; + sk->q = sk->p + sk->plen; + sk->qlen = (esize_q + 7) >> 3; + sk->dp = sk->q + sk->qlen; + sk->dplen = sk->plen; + sk->dq = sk->dp + sk->dplen; + sk->dqlen = sk->qlen; + sk->iq = sk->dq + sk->dqlen; + sk->iqlen = sk->plen; + + if (pk != NULL) { + pk->n = kbuf_pub; + pk->nlen = (size + 7) >> 3; + pk->e = pk->n + pk->nlen; + pk->elen = 4; + br_enc32be(pk->e, pubexp); + while (*pk->e == 0) { + pk->e ++; + pk->elen --; + } + } + + /* + * We now switch to encoded sizes. + * + * floor((x * 16913) / (2^19)) is equal to floor(x/31) for all + * integers x from 0 to 34966; the intermediate product fits on + * 30 bits, thus we can use MUL31(). + */ + esize_p += MUL31(esize_p, 16913) >> 19; + esize_q += MUL31(esize_q, 16913) >> 19; + plen = (esize_p + 31) >> 5; + qlen = (esize_q + 31) >> 5; + p = tmp.t32; + q = p + 1 + plen; + t = q + 1 + qlen; + tlen = ((sizeof tmp.t32) / sizeof(uint32_t)) - (2 + plen + qlen); + + /* + * When looking for primes p and q, we temporarily divide + * candidates by 2, in order to compute the inverse of the + * public exponent. + */ + + for (;;) { + mkprime(rng, p, esize_p, pubexp, t, tlen, mp31); + br_i31_rshift(p, 1); + if (invert_pubexp(t, p, pubexp, t + 1 + plen)) { + br_i31_add(p, p, 1); + p[1] |= 1; + br_i31_encode(sk->p, sk->plen, p); + br_i31_encode(sk->dp, sk->dplen, t); + break; + } + } + + for (;;) { + mkprime(rng, q, esize_q, pubexp, t, tlen, mp31); + br_i31_rshift(q, 1); + if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) { + br_i31_add(q, q, 1); + q[1] |= 1; + br_i31_encode(sk->q, sk->qlen, q); + br_i31_encode(sk->dq, sk->dqlen, t); + break; + } + } + + /* + * If p and q have the same size, then it is possible that q > p + * (when the target modulus size is odd, we generate p with a + * greater bit length than q). If q > p, we want to swap p and q + * (and also dp and dq) for two reasons: + * - The final step below (inversion of q modulo p) is easier if + * p > q. + * - While BearSSL's RSA code is perfectly happy with RSA keys such + * that p < q, some other implementations have restrictions and + * require p > q. + * + * Note that we can do a simple non-constant-time swap here, + * because the only information we leak here is that we insist on + * returning p and q such that p > q, which is not a secret. + */ + if (esize_p == esize_q && br_i31_sub(p, q, 0) == 1) { + bufswap(p, q, (1 + plen) * sizeof *p); + bufswap(sk->p, sk->q, sk->plen); + bufswap(sk->dp, sk->dq, sk->dplen); + } + + /* + * We have produced p, q, dp and dq. We can now compute iq = 1/d mod p. + * + * We ensured that p >= q, so this is just a matter of updating the + * header word for q (and possibly adding an extra word). + * + * Theoretically, the call below may fail, in case we were + * extraordinarily unlucky, and p = q. Another failure case is if + * Miller-Rabin failed us _twice_, and p and q are non-prime and + * have a factor is common. We report the error mostly because it + * is cheap and we can, but in practice this never happens (or, at + * least, it happens way less often than hardware glitches). + */ + q[0] = p[0]; + if (plen > qlen) { + q[plen] = 0; + t ++; + tlen --; + } + br_i31_zero(t, p[0]); + t[1] = 1; + r = br_i31_moddiv(t, q, p, br_i31_ninv31(p[1]), t + 1 + plen); + br_i31_encode(sk->iq, sk->iqlen, t); + + /* + * Compute the public modulus too, if required. + */ + if (pk != NULL) { + br_i31_zero(t, p[0]); + br_i31_mulacc(t, p, q); + br_i31_encode(pk->n, pk->nlen, t); + } + + return r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_modulus.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_modulus.c new file mode 100644 index 0000000..f5f997f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_modulus.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +size_t +br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk) +{ + uint32_t tmp[4 * (((BR_MAX_RSA_SIZE / 2) + 30) / 31) + 5]; + uint32_t *t, *p, *q; + const unsigned char *pbuf, *qbuf; + size_t nlen, plen, qlen, tlen; + + /* + * Compute actual byte and lengths for p and q. + */ + pbuf = sk->p; + plen = sk->plen; + while (plen > 0 && *pbuf == 0) { + pbuf ++; + plen --; + } + qbuf = sk->q; + qlen = sk->qlen; + while (qlen > 0 && *qbuf == 0) { + qbuf ++; + qlen --; + } + + t = tmp; + tlen = (sizeof tmp) / (sizeof tmp[0]); + + /* + * Decode p. + */ + if ((31 * tlen) < (plen << 3) + 31) { + return 0; + } + br_i31_decode(t, pbuf, plen); + p = t; + plen = (p[0] + 63) >> 5; + t += plen; + tlen -= plen; + + /* + * Decode q. + */ + if ((31 * tlen) < (qlen << 3) + 31) { + return 0; + } + br_i31_decode(t, qbuf, qlen); + q = t; + qlen = (q[0] + 63) >> 5; + t += qlen; + tlen -= qlen; + + /* + * Computation can proceed only if we have enough room for the + * modulus. + */ + if (tlen < (plen + qlen + 1)) { + return 0; + } + + /* + * Private key already contains the modulus bit length, from which + * we can infer the output length. Even if n is NULL, we still had + * to decode p and q to make sure that the product can be computed. + */ + nlen = (sk->n_bitlen + 7) >> 3; + if (n != NULL) { + br_i31_zero(t, p[0]); + br_i31_mulacc(t, p, q); + br_i31_encode(n, nlen, t); + } + return nlen; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_oaep_decrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_oaep_decrypt.c new file mode 100644 index 0000000..06fdd93 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_oaep_decrypt.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_oaep_decrypt(const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len) +{ + uint32_t r; + + if (*len != ((sk->n_bitlen + 7) >> 3)) { + return 0; + } + r = br_rsa_i31_private(data, sk); + r &= br_rsa_oaep_unpad(dig, label, label_len, data, len); + return r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_oaep_encrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_oaep_encrypt.c new file mode 100644 index 0000000..367008c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_oaep_encrypt.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +size_t +br_rsa_i31_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len) +{ + size_t dlen; + + dlen = br_rsa_oaep_pad(rnd, dig, label, label_len, + pk, dst, dst_max_len, src, src_len); + if (dlen == 0) { + return 0; + } + return dlen & -(size_t)br_rsa_i31_public(dst, dlen, pk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pkcs1_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pkcs1_sign.c new file mode 100644 index 0000000..784d3c2 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pkcs1_sign.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x) +{ + if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) { + return 0; + } + return br_rsa_i31_private(x, sk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pkcs1_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pkcs1_vrfy.c new file mode 100644 index 0000000..e79a002 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pkcs1_vrfy.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out) +{ + unsigned char sig[BR_MAX_RSA_SIZE >> 3]; + + if (xlen > (sizeof sig)) { + return 0; + } + memcpy(sig, x, xlen); + if (!br_rsa_i31_public(sig, xlen, pk)) { + return 0; + } + return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_priv.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_priv.c new file mode 100644 index 0000000..b1e1244 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_priv.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define U (2 + ((BR_MAX_RSA_FACTOR + 30) / 31)) +#define TLEN (8 * U) + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk) +{ + const unsigned char *p, *q; + size_t plen, qlen; + size_t fwlen; + uint32_t p0i, q0i; + size_t xlen, u; + uint32_t tmp[1 + TLEN]; + long z; + uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; + uint32_t r; + + /* + * Compute the actual lengths of p and q, in bytes. + * These lengths are not considered secret (we cannot really hide + * them anyway in constant-time code). + */ + p = sk->p; + plen = sk->plen; + while (plen > 0 && *p == 0) { + p ++; + plen --; + } + q = sk->q; + qlen = sk->qlen; + while (qlen > 0 && *q == 0) { + q ++; + qlen --; + } + + /* + * Compute the maximum factor length, in words. + */ + z = (long)(plen > qlen ? plen : qlen) << 3; + fwlen = 1; + while (z > 0) { + z -= 31; + fwlen ++; + } + + /* + * Round up the word length to an even number. + */ + fwlen += (fwlen & 1); + + /* + * We need to fit at least 6 values in the stack buffer. + */ + if (6 * fwlen > TLEN) { + return 0; + } + + /* + * Compute modulus length (in bytes). + */ + xlen = (sk->n_bitlen + 7) >> 3; + + /* + * Decode q. + */ + mq = tmp; + br_i31_decode(mq, q, qlen); + + /* + * Decode p. + */ + t1 = mq + fwlen; + br_i31_decode(t1, p, plen); + + /* + * Compute the modulus (product of the two factors), to compare + * it with the source value. We use br_i31_mulacc(), since it's + * already used later on. + */ + t2 = mq + 2 * fwlen; + br_i31_zero(t2, mq[0]); + br_i31_mulacc(t2, mq, t1); + + /* + * We encode the modulus into bytes, to perform the comparison + * with bytes. We know that the product length, in bytes, is + * exactly xlen. + * The comparison actually computes the carry when subtracting + * the modulus from the source value; that carry must be 1 for + * a value in the correct range. We keep it in r, which is our + * accumulator for the error code. + */ + t3 = mq + 4 * fwlen; + br_i31_encode(t3, xlen, t2); + u = xlen; + r = 0; + while (u > 0) { + uint32_t wn, wx; + + u --; + wn = ((unsigned char *)t3)[u]; + wx = x[u]; + r = ((wx - (wn + r)) >> 8) & 1; + } + + /* + * Move the decoded p to another temporary buffer. + */ + mp = mq + 2 * fwlen; + memmove(mp, t1, fwlen * sizeof *t1); + + /* + * Compute s2 = x^dq mod q. + */ + q0i = br_i31_ninv31(mq[1]); + s2 = mq + fwlen; + br_i31_decode_reduce(s2, x, xlen, mq); + r &= br_i31_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i, + mq + 3 * fwlen, TLEN - 3 * fwlen); + + /* + * Compute s1 = x^dp mod p. + */ + p0i = br_i31_ninv31(mp[1]); + s1 = mq + 3 * fwlen; + br_i31_decode_reduce(s1, x, xlen, mp); + r &= br_i31_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i, + mq + 4 * fwlen, TLEN - 4 * fwlen); + + /* + * Compute: + * h = (s1 - s2)*(1/q) mod p + * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is + * unclear about whether p may be lower than q (some existing, + * widely deployed implementations of RSA don't tolerate p < q), + * but we want to support that occurrence, so we need to use the + * reduction function. + * + * Since we use br_i31_decode_reduce() for iq (purportedly, the + * inverse of q modulo p), we also tolerate improperly large + * values for this parameter. + */ + t1 = mq + 4 * fwlen; + t2 = mq + 5 * fwlen; + br_i31_reduce(t2, s2, mp); + br_i31_add(s1, mp, br_i31_sub(s1, t2, 1)); + br_i31_to_monty(s1, mp); + br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp); + br_i31_montymul(t2, s1, t1, mp, p0i); + + /* + * h is now in t2. We compute the final result: + * s = s2 + q*h + * All these operations are non-modular. + * + * We need mq, s2 and t2. We use the t3 buffer as destination. + * The buffers mp, s1 and t1 are no longer needed, so we can + * reuse them for t3. Moreover, the first step of the computation + * is to copy s2 into t3, after which s2 is not needed. Right + * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5. + * Therefore, we have ample room for t3 by simply using s2. + */ + t3 = s2; + br_i31_mulacc(t3, mq, t2); + + /* + * Encode the result. Since we already checked the value of xlen, + * we can just use it right away. + */ + br_i31_encode(x, xlen, t3); + + /* + * The only error conditions remaining at that point are invalid + * values for p and q (even integers). + */ + return p0i & q0i & r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_privexp.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_privexp.c new file mode 100644 index 0000000..eee62a0 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_privexp.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +size_t +br_rsa_i31_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t e) +{ + /* + * We want to invert e modulo phi = (p-1)(q-1). This first + * requires computing phi, which is easy since we have the factors + * p and q in the private key structure. + * + * Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer. + * We could invert e modulo phi/4 then patch the result to + * modulo phi, but this would involve assembling three modulus-wide + * values (phi/4, 1 and e) and calling moddiv, that requires + * three more temporaries, for a total of six big integers, or + * slightly more than 3 kB of stack space for RSA-4096. This + * exceeds our stack requirements. + * + * Instead, we first use one step of the extended GCD: + * + * - We compute phi = k*e + r (Euclidean division of phi by e). + * If public exponent e is correct, then r != 0 (e must be + * invertible modulo phi). We also have k != 0 since we + * enforce non-ridiculously-small factors. + * + * - We find small u, v such that u*e - v*r = 1 (using a + * binary GCD; we can arrange for u < r and v < e, i.e. all + * values fit on 32 bits). + * + * - Solution is: d = u + v*k + * This last computation is exact: since u < r and v < e, + * the above implies d < r + e*((phi-r)/e) = phi + */ + + uint32_t tmp[4 * ((BR_MAX_RSA_FACTOR + 30) / 31) + 12]; + uint32_t *p, *q, *k, *m, *z, *phi; + const unsigned char *pbuf, *qbuf; + size_t plen, qlen, u, len, dlen; + uint32_t r, a, b, u0, v0, u1, v1, he, hr; + int i; + + /* + * Check that e is correct. + */ + if (e < 3 || (e & 1) == 0) { + return 0; + } + + /* + * Check lengths of p and q, and that they are both odd. + */ + pbuf = sk->p; + plen = sk->plen; + while (plen > 0 && *pbuf == 0) { + pbuf ++; + plen --; + } + if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8) + || (pbuf[plen - 1] & 1) != 1) + { + return 0; + } + qbuf = sk->q; + qlen = sk->qlen; + while (qlen > 0 && *qbuf == 0) { + qbuf ++; + qlen --; + } + if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8) + || (qbuf[qlen - 1] & 1) != 1) + { + return 0; + } + + /* + * Output length is that of the modulus. + */ + dlen = (sk->n_bitlen + 7) >> 3; + if (d == NULL) { + return dlen; + } + + p = tmp; + br_i31_decode(p, pbuf, plen); + plen = (p[0] + 31) >> 5; + q = p + 1 + plen; + br_i31_decode(q, qbuf, qlen); + qlen = (q[0] + 31) >> 5; + + /* + * Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that + * we do not need anymore). The mulacc function sets the announced + * bit length of t to be the sum of the announced bit lengths of + * p-1 and q-1, which is usually exact but may overshoot by one 1 + * bit in some cases; we readjust it to its true length. + */ + p[1] --; + q[1] --; + phi = q + 1 + qlen; + br_i31_zero(phi, p[0]); + br_i31_mulacc(phi, p, q); + len = (phi[0] + 31) >> 5; + memmove(tmp, phi, (1 + len) * sizeof *phi); + phi = tmp; + phi[0] = br_i31_bit_length(phi + 1, len); + len = (phi[0] + 31) >> 5; + + /* + * Divide phi by public exponent e. The final remainder r must be + * non-zero (otherwise, the key is invalid). The quotient is k, + * which we write over phi, since we don't need phi after that. + */ + r = 0; + for (u = len; u >= 1; u --) { + /* + * Upon entry, r < e, and phi[u] < 2^31; hence, + * hi:lo < e*2^31. Thus, the produced word k[u] + * must be lower than 2^31, and the new remainder r + * is lower than e. + */ + uint32_t hi, lo; + + hi = r >> 1; + lo = (r << 31) + phi[u]; + phi[u] = br_divrem(hi, lo, e, &r); + } + if (r == 0) { + return 0; + } + k = phi; + + /* + * Compute u and v such that u*e - v*r = GCD(e,r). We use + * a binary GCD algorithm, with 6 extra integers a, b, + * u0, u1, v0 and v1. Initial values are: + * a = e u0 = 1 v0 = 0 + * b = r u1 = r v1 = e-1 + * The following invariants are maintained: + * a = u0*e - v0*r + * b = u1*e - v1*r + * 0 < a <= e + * 0 < b <= r + * 0 <= u0 <= r + * 0 <= v0 <= e + * 0 <= u1 <= r + * 0 <= v1 <= e + * + * At each iteration, we reduce either a or b by one bit, and + * adjust u0, u1, v0 and v1 to maintain the invariants: + * - if a is even, then a <- a/2 + * - otherwise, if b is even, then b <- b/2 + * - otherwise, if a > b, then a <- (a-b)/2 + * - otherwise, if b > a, then b <- (b-a)/2 + * Algorithm stops when a = b. At that point, the common value + * is the GCD of e and r; it must be 1 (otherwise, the private + * key or public exponent is not valid). The (u0,v0) or (u1,v1) + * pairs are the solution we are looking for. + * + * Since either a or b is reduced by at least 1 bit at each + * iteration, 62 iterations are enough to reach the end + * condition. + * + * To maintain the invariants, we must compute the same operations + * on the u* and v* values that we do on a and b: + * - When a is divided by 2, u0 and v0 must be divided by 2. + * - When b is divided by 2, u1 and v1 must be divided by 2. + * - When b is subtracted from a, u1 and v1 are subtracted from + * u0 and v0, respectively. + * - When a is subtracted from b, u0 and v0 are subtracted from + * u1 and v1, respectively. + * + * However, we want to keep the u* and v* values in their proper + * ranges. The following remarks apply: + * + * - When a is divided by 2, then a is even. Therefore: + * + * * If r is odd, then u0 and v0 must have the same parity; + * if they are both odd, then adding r to u0 and e to v0 + * makes them both even, and the division by 2 brings them + * back to the proper range. + * + * * If r is even, then u0 must be even; if v0 is odd, then + * adding r to u0 and e to v0 makes them both even, and the + * division by 2 brings them back to the proper range. + * + * Thus, all we need to do is to look at the parity of v0, + * and add (r,e) to (u0,v0) when v0 is odd. In order to avoid + * a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the + * division (r+1 does not overflow since r < e; and (e/2)+1 + * is equal to (e+1)/2 since e is odd). + * + * - When we subtract b from a, three cases may occur: + * + * * u1 <= u0 and v1 <= v0: just do the subtractions + * + * * u1 > u0 and v1 > v0: compute: + * (u0, v0) <- (u0 + r - u1, v0 + e - v1) + * + * * u1 <= u0 and v1 > v0: compute: + * (u0, v0) <- (u0 + r - u1, v0 + e - v1) + * + * The fourth case (u1 > u0 and v1 <= v0) is not possible + * because it would contradict "b < a" (which is the reason + * why we subtract b from a). + * + * The tricky case is the third one: from the equations, it + * seems that u0 may go out of range. However, the invariants + * and ranges of other values imply that, in that case, the + * new u0 does not actually exceed the range. + * + * We can thus handle the subtraction by adding (r,e) based + * solely on the comparison between v0 and v1. + */ + a = e; + b = r; + u0 = 1; + v0 = 0; + u1 = r; + v1 = e - 1; + hr = (r + 1) >> 1; + he = (e >> 1) + 1; + for (i = 0; i < 62; i ++) { + uint32_t oa, ob, agtb, bgta; + uint32_t sab, sba, da, db; + uint32_t ctl; + + oa = a & 1; /* 1 if a is odd */ + ob = b & 1; /* 1 if b is odd */ + agtb = GT(a, b); /* 1 if a > b */ + bgta = GT(b, a); /* 1 if b > a */ + + sab = oa & ob & agtb; /* 1 if a <- a-b */ + sba = oa & ob & bgta; /* 1 if b <- b-a */ + + /* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */ + ctl = GT(v1, v0); + a -= b & -sab; + u0 -= (u1 - (r & -ctl)) & -sab; + v0 -= (v1 - (e & -ctl)) & -sab; + + /* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */ + ctl = GT(v0, v1); + b -= a & -sba; + u1 -= (u0 - (r & -ctl)) & -sba; + v1 -= (v0 - (e & -ctl)) & -sba; + + da = NOT(oa) | sab; /* 1 if a <- a/2 */ + db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */ + + /* a <- a/2, u0 <- u0/2, v0 <- v0/2 */ + ctl = v0 & 1; + a ^= (a ^ (a >> 1)) & -da; + u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da; + v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da; + + /* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */ + ctl = v1 & 1; + b ^= (b ^ (b >> 1)) & -db; + u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db; + v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db; + } + + /* + * Check that the GCD is indeed 1. If not, then the key is invalid + * (and there's no harm in leaking that piece of information). + */ + if (a != 1) { + return 0; + } + + /* + * Now we have u0*e - v0*r = 1. Let's compute the result as: + * d = u0 + v0*k + * We still have k in the tmp[] array, and its announced bit + * length is that of phi. + */ + m = k + 1 + len; + m[0] = (1 << 5) + 1; /* bit length is 32 bits, encoded */ + m[1] = v0 & 0x7FFFFFFF; + m[2] = v0 >> 31; + z = m + 3; + br_i31_zero(z, k[0]); + z[1] = u0 & 0x7FFFFFFF; + z[2] = u0 >> 31; + br_i31_mulacc(z, k, m); + + /* + * Encode the result. + */ + br_i31_encode(d, dlen, z); + return dlen; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pss_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pss_sign.c new file mode 100644 index 0000000..b06f3e2 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pss_sign.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x) +{ + if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash, + salt_len, sk->n_bitlen, x)) + { + return 0; + } + return br_rsa_i31_private(x, sk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pss_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pss_vrfy.c new file mode 100644 index 0000000..77a9b28 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pss_vrfy.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk) +{ + unsigned char sig[BR_MAX_RSA_SIZE >> 3]; + + if (xlen > (sizeof sig)) { + return 0; + } + memcpy(sig, x, xlen); + if (!br_rsa_i31_public(sig, xlen, pk)) { + return 0; + } + return br_rsa_pss_sig_unpad(hf_data, hf_mgf1, + hash, salt_len, pk, sig); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pub.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pub.c new file mode 100644 index 0000000..d5f3fe2 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pub.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * As a strict minimum, we need four buffers that can hold a + * modular integer. + */ +#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 30) / 31))) + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk) +{ + const unsigned char *n; + size_t nlen; + uint32_t tmp[1 + TLEN]; + uint32_t *m, *a, *t; + size_t fwlen; + long z; + uint32_t m0i, r; + + /* + * Get the actual length of the modulus, and see if it fits within + * our stack buffer. We also check that the length of x[] is valid. + */ + n = pk->n; + nlen = pk->nlen; + while (nlen > 0 && *n == 0) { + n ++; + nlen --; + } + if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) { + return 0; + } + z = (long)nlen << 3; + fwlen = 1; + while (z > 0) { + z -= 31; + fwlen ++; + } + /* + * Round up length to an even number. + */ + fwlen += (fwlen & 1); + + /* + * The modulus gets decoded into m[]. + * The value to exponentiate goes into a[]. + * The temporaries for modular exponentiation are in t[]. + */ + m = tmp; + a = m + fwlen; + t = m + 2 * fwlen; + + /* + * Decode the modulus. + */ + br_i31_decode(m, n, nlen); + m0i = br_i31_ninv31(m[1]); + + /* + * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be + * an odd integer. + */ + r = m0i & 1; + + /* + * Decode x[] into a[]; we also check that its value is proper. + */ + r &= br_i31_decode_mod(a, x, xlen, m); + + /* + * Compute the modular exponentiation. + */ + br_i31_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen); + + /* + * Encode the result. + */ + br_i31_encode(x, xlen, a); + return r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pubexp.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pubexp.c new file mode 100644 index 0000000..f26537d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i31_pubexp.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * Recompute public exponent, based on factor p and reduced private + * exponent dp. + */ +static uint32_t +get_pubexp(const unsigned char *pbuf, size_t plen, + const unsigned char *dpbuf, size_t dplen) +{ + /* + * dp is the inverse of e modulo p-1. If p = 3 mod 4, then + * p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1; + * thus, dp must be odd. + * + * We compute the inverse of dp modulo (p-1)/2. This requires + * first reducing dp modulo (p-1)/2 (this can be done with a + * conditional subtract, no need to use the generic modular + * reduction function); then, we use moddiv. + */ + + uint32_t tmp[6 * ((BR_MAX_RSA_FACTOR + 61) / 31)]; + uint32_t *p, *dp, *x; + size_t len; + uint32_t e; + + /* + * Compute actual factor length (in bytes) and check that it fits + * under our size constraints. + */ + while (plen > 0 && *pbuf == 0) { + pbuf ++; + plen --; + } + if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) { + return 0; + } + + /* + * Compute actual reduced exponent length (in bytes) and check that + * it is not longer than p. + */ + while (dplen > 0 && *dpbuf == 0) { + dpbuf ++; + dplen --; + } + if (dplen > plen || dplen == 0 + || (dplen == plen && dpbuf[0] > pbuf[0])) + { + return 0; + } + + /* + * Verify that p = 3 mod 4 and that dp is odd. + */ + if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) { + return 0; + } + + /* + * Decode p and compute (p-1)/2. + */ + p = tmp; + br_i31_decode(p, pbuf, plen); + len = (p[0] + 63) >> 5; + br_i31_rshift(p, 1); + + /* + * Decode dp and make sure its announced bit length matches that of + * p (we already know that the size of dp, in bits, does not exceed + * the size of p, so we just have to copy the header word). + */ + dp = p + len; + memset(dp, 0, len * sizeof *dp); + br_i31_decode(dp, dpbuf, dplen); + dp[0] = p[0]; + + /* + * Subtract (p-1)/2 from dp if necessary. + */ + br_i31_sub(dp, p, NOT(br_i31_sub(dp, p, 0))); + + /* + * If another subtraction is needed, then this means that the + * value was invalid. We don't care to leak information about + * invalid keys. + */ + if (br_i31_sub(dp, p, 0) == 0) { + return 0; + } + + /* + * Invert dp modulo (p-1)/2. If the inversion fails, then the + * key value was invalid. + */ + x = dp + len; + br_i31_zero(x, p[0]); + x[1] = 1; + if (br_i31_moddiv(x, dp, p, br_i31_ninv31(p[1]), x + len) == 0) { + return 0; + } + + /* + * We now have an inverse. We must set it to zero (error) if its + * length is greater than 32 bits and/or if it is an even integer. + * Take care that the bit_length function returns an encoded + * bit length. + */ + e = (uint32_t)x[1] | ((uint32_t)x[2] << 31); + e &= -LT(br_i31_bit_length(x + 1, len - 1), 34); + e &= -(e & 1); + return e; +} + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk) +{ + /* + * Get the public exponent from both p and q. This is the right + * exponent if we get twice the same value. + */ + uint32_t ep, eq; + + ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen); + eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen); + return ep & -EQ(ep, eq); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i32_oaep_decrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_oaep_decrypt.c new file mode 100644 index 0000000..ecfd92b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_oaep_decrypt.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i32_oaep_decrypt(const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len) +{ + uint32_t r; + + if (*len != ((sk->n_bitlen + 7) >> 3)) { + return 0; + } + r = br_rsa_i32_private(data, sk); + r &= br_rsa_oaep_unpad(dig, label, label_len, data, len); + return r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i32_oaep_encrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_oaep_encrypt.c new file mode 100644 index 0000000..dc17f3f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_oaep_encrypt.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +size_t +br_rsa_i32_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len) +{ + size_t dlen; + + dlen = br_rsa_oaep_pad(rnd, dig, label, label_len, + pk, dst, dst_max_len, src, src_len); + if (dlen == 0) { + return 0; + } + return dlen & -(size_t)br_rsa_i32_public(dst, dlen, pk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pkcs1_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pkcs1_sign.c new file mode 100644 index 0000000..44b6e6d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pkcs1_sign.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x) +{ + if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) { + return 0; + } + return br_rsa_i32_private(x, sk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pkcs1_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pkcs1_vrfy.c new file mode 100644 index 0000000..6ee7a19 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pkcs1_vrfy.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out) +{ + unsigned char sig[BR_MAX_RSA_SIZE >> 3]; + + if (xlen > (sizeof sig)) { + return 0; + } + memcpy(sig, x, xlen); + if (!br_rsa_i32_public(sig, xlen, pk)) { + return 0; + } + return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i32_priv.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_priv.c new file mode 100644 index 0000000..05c22ec --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_priv.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define U (1 + (BR_MAX_RSA_FACTOR >> 5)) + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i32_private(unsigned char *x, const br_rsa_private_key *sk) +{ + const unsigned char *p, *q; + size_t plen, qlen; + uint32_t tmp[6 * U]; + uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; + uint32_t p0i, q0i; + size_t xlen, u; + uint32_t r; + + /* + * All our temporary buffers are from the tmp[] array. + * + * The mp, mq, s1, s2, t1 and t2 buffers are large enough to + * contain a RSA factor. The t3 buffer can contain a complete + * RSA modulus. t3 shares its storage space with s2, s1 and t1, + * in that order (this is important, see below). + */ + mq = tmp; + mp = tmp + U; + t2 = tmp + 2 * U; + s2 = tmp + 3 * U; + s1 = tmp + 4 * U; + t1 = tmp + 5 * U; + t3 = s2; + + /* + * Compute the actual lengths (in bytes) of p and q, and check + * that they fit within our stack buffers. + */ + p = sk->p; + plen = sk->plen; + while (plen > 0 && *p == 0) { + p ++; + plen --; + } + q = sk->q; + qlen = sk->qlen; + while (qlen > 0 && *q == 0) { + q ++; + qlen --; + } + if (plen > (BR_MAX_RSA_FACTOR >> 3) + || qlen > (BR_MAX_RSA_FACTOR >> 3)) + { + return 0; + } + + /* + * Decode p and q. + */ + br_i32_decode(mp, p, plen); + br_i32_decode(mq, q, qlen); + + /* + * Recompute modulus, to compare with the source value. + */ + br_i32_zero(t2, mp[0]); + br_i32_mulacc(t2, mp, mq); + xlen = (sk->n_bitlen + 7) >> 3; + br_i32_encode(t2 + 2 * U, xlen, t2); + u = xlen; + r = 0; + while (u > 0) { + uint32_t wn, wx; + + u --; + wn = ((unsigned char *)(t2 + 2 * U))[u]; + wx = x[u]; + r = ((wx - (wn + r)) >> 8) & 1; + } + + /* + * Compute s1 = x^dp mod p. + */ + p0i = br_i32_ninv32(mp[1]); + br_i32_decode_reduce(s1, x, xlen, mp); + br_i32_modpow(s1, sk->dp, sk->dplen, mp, p0i, t1, t2); + + /* + * Compute s2 = x^dq mod q. + */ + q0i = br_i32_ninv32(mq[1]); + br_i32_decode_reduce(s2, x, xlen, mq); + br_i32_modpow(s2, sk->dq, sk->dqlen, mq, q0i, t1, t2); + + /* + * Compute: + * h = (s1 - s2)*(1/q) mod p + * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is + * unclear about whether p may be lower than q (some existing, + * widely deployed implementations of RSA don't tolerate p < q), + * but we want to support that occurrence, so we need to use the + * reduction function. + * + * Since we use br_i32_decode_reduce() for iq (purportedly, the + * inverse of q modulo p), we also tolerate improperly large + * values for this parameter. + */ + br_i32_reduce(t2, s2, mp); + br_i32_add(s1, mp, br_i32_sub(s1, t2, 1)); + br_i32_to_monty(s1, mp); + br_i32_decode_reduce(t1, sk->iq, sk->iqlen, mp); + br_i32_montymul(t2, s1, t1, mp, p0i); + + /* + * h is now in t2. We compute the final result: + * s = s2 + q*h + * All these operations are non-modular. + * + * We need mq, s2 and t2. We use the t3 buffer as destination. + * The buffers mp, s1 and t1 are no longer needed. Moreover, + * the first step is to copy s2 into the destination buffer t3. + * We thus arranged for t3 to actually share space with s2, and + * to be followed by the space formerly used by s1 and t1. + */ + br_i32_mulacc(t3, mq, t2); + + /* + * Encode the result. Since we already checked the value of xlen, + * we can just use it right away. + */ + br_i32_encode(x, xlen, t3); + + /* + * The only error conditions remaining at that point are invalid + * values for p and q (even integers). + */ + return p0i & q0i & r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pss_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pss_sign.c new file mode 100644 index 0000000..0f72f92 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pss_sign.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i32_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x) +{ + if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash, + salt_len, sk->n_bitlen, x)) + { + return 0; + } + return br_rsa_i32_private(x, sk); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pss_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pss_vrfy.c new file mode 100644 index 0000000..2e70d23 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pss_vrfy.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk) +{ + unsigned char sig[BR_MAX_RSA_SIZE >> 3]; + + if (xlen > (sizeof sig)) { + return 0; + } + memcpy(sig, x, xlen); + if (!br_rsa_i32_public(sig, xlen, pk)) { + return 0; + } + return br_rsa_pss_sig_unpad(hf_data, hf_mgf1, + hash, salt_len, pk, sig); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pub.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pub.c new file mode 100644 index 0000000..6e8d8e3 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i32_pub.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i32_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk) +{ + const unsigned char *n; + size_t nlen; + uint32_t m[1 + (BR_MAX_RSA_SIZE >> 5)]; + uint32_t a[1 + (BR_MAX_RSA_SIZE >> 5)]; + uint32_t t1[1 + (BR_MAX_RSA_SIZE >> 5)]; + uint32_t t2[1 + (BR_MAX_RSA_SIZE >> 5)]; + uint32_t m0i, r; + + /* + * Get the actual length of the modulus, and see if it fits within + * our stack buffer. We also check that the length of x[] is valid. + */ + n = pk->n; + nlen = pk->nlen; + while (nlen > 0 && *n == 0) { + n ++; + nlen --; + } + if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) { + return 0; + } + br_i32_decode(m, n, nlen); + m0i = br_i32_ninv32(m[1]); + + /* + * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be + * an odd integer. + */ + r = m0i & 1; + + /* + * Decode x[] into a[]; we also check that its value is proper. + */ + r &= br_i32_decode_mod(a, x, xlen, m); + + /* + * Compute the modular exponentiation. + */ + br_i32_modpow(a, pk->e, pk->elen, m, m0i, t1, t2); + + /* + * Encode the result. + */ + br_i32_encode(x, xlen, a); + return r; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_keygen.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_keygen.c new file mode 100644 index 0000000..992fe97 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_keygen.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i62_keygen(const br_prng_class **rng, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp) +{ + return br_rsa_i31_keygen_inner(rng, + sk, kbuf_priv, pk, kbuf_pub, size, pubexp, + &br_i62_modpow_opt_as_i31); +} + +/* see bearssl_rsa.h */ +br_rsa_keygen +br_rsa_i62_keygen_get(void) +{ + return &br_rsa_i62_keygen; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_keygen +br_rsa_i62_keygen_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_oaep_decrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_oaep_decrypt.c new file mode 100644 index 0000000..38470dd --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_oaep_decrypt.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i62_oaep_decrypt(const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len) +{ + uint32_t r; + + if (*len != ((sk->n_bitlen + 7) >> 3)) { + return 0; + } + r = br_rsa_i62_private(data, sk); + r &= br_rsa_oaep_unpad(dig, label, label_len, data, len); + return r; +} + +/* see bearssl_rsa.h */ +br_rsa_oaep_decrypt +br_rsa_i62_oaep_decrypt_get(void) +{ + return &br_rsa_i62_oaep_decrypt; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_oaep_decrypt +br_rsa_i62_oaep_decrypt_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_oaep_encrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_oaep_encrypt.c new file mode 100644 index 0000000..cf41ecb --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_oaep_encrypt.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +/* see bearssl_rsa.h */ +size_t +br_rsa_i62_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len) +{ + size_t dlen; + + dlen = br_rsa_oaep_pad(rnd, dig, label, label_len, + pk, dst, dst_max_len, src, src_len); + if (dlen == 0) { + return 0; + } + return dlen & -(size_t)br_rsa_i62_public(dst, dlen, pk); +} + +/* see bearssl_rsa.h */ +br_rsa_oaep_encrypt +br_rsa_i62_oaep_encrypt_get(void) +{ + return &br_rsa_i62_oaep_encrypt; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_oaep_encrypt +br_rsa_i62_oaep_encrypt_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pkcs1_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pkcs1_sign.c new file mode 100644 index 0000000..a20a084 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pkcs1_sign.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x) +{ + if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) { + return 0; + } + return br_rsa_i62_private(x, sk); +} + +/* see bearssl_rsa.h */ +br_rsa_pkcs1_sign +br_rsa_i62_pkcs1_sign_get(void) +{ + return &br_rsa_i62_pkcs1_sign; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_pkcs1_sign +br_rsa_i62_pkcs1_sign_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pkcs1_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pkcs1_vrfy.c new file mode 100644 index 0000000..6519161 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pkcs1_vrfy.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out) +{ + unsigned char sig[BR_MAX_RSA_SIZE >> 3]; + + if (xlen > (sizeof sig)) { + return 0; + } + memcpy(sig, x, xlen); + if (!br_rsa_i62_public(sig, xlen, pk)) { + return 0; + } + return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out); +} + +/* see bearssl_rsa.h */ +br_rsa_pkcs1_vrfy +br_rsa_i62_pkcs1_vrfy_get(void) +{ + return &br_rsa_i62_pkcs1_vrfy; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_pkcs1_vrfy +br_rsa_i62_pkcs1_vrfy_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_priv.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_priv.c new file mode 100644 index 0000000..f0da600 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_priv.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +#define U (2 + ((BR_MAX_RSA_FACTOR + 30) / 31)) +#define TLEN (4 * U) /* TLEN is counted in 64-bit words */ + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i62_private(unsigned char *x, const br_rsa_private_key *sk) +{ + const unsigned char *p, *q; + size_t plen, qlen; + size_t fwlen; + uint32_t p0i, q0i; + size_t xlen, u; + uint64_t tmp[TLEN]; + long z; + uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; + uint32_t r; + + /* + * Compute the actual lengths of p and q, in bytes. + * These lengths are not considered secret (we cannot really hide + * them anyway in constant-time code). + */ + p = sk->p; + plen = sk->plen; + while (plen > 0 && *p == 0) { + p ++; + plen --; + } + q = sk->q; + qlen = sk->qlen; + while (qlen > 0 && *q == 0) { + q ++; + qlen --; + } + + /* + * Compute the maximum factor length, in words. + */ + z = (long)(plen > qlen ? plen : qlen) << 3; + fwlen = 1; + while (z > 0) { + z -= 31; + fwlen ++; + } + + /* + * Convert size to 62-bit words. + */ + fwlen = (fwlen + 1) >> 1; + + /* + * We need to fit at least 6 values in the stack buffer. + */ + if (6 * fwlen > TLEN) { + return 0; + } + + /* + * Compute signature length (in bytes). + */ + xlen = (sk->n_bitlen + 7) >> 3; + + /* + * Decode q. + */ + mq = (uint32_t *)tmp; + br_i31_decode(mq, q, qlen); + + /* + * Decode p. + */ + t1 = (uint32_t *)(tmp + fwlen); + br_i31_decode(t1, p, plen); + + /* + * Compute the modulus (product of the two factors), to compare + * it with the source value. We use br_i31_mulacc(), since it's + * already used later on. + */ + t2 = (uint32_t *)(tmp + 2 * fwlen); + br_i31_zero(t2, mq[0]); + br_i31_mulacc(t2, mq, t1); + + /* + * We encode the modulus into bytes, to perform the comparison + * with bytes. We know that the product length, in bytes, is + * exactly xlen. + * The comparison actually computes the carry when subtracting + * the modulus from the source value; that carry must be 1 for + * a value in the correct range. We keep it in r, which is our + * accumulator for the error code. + */ + t3 = (uint32_t *)(tmp + 4 * fwlen); + br_i31_encode(t3, xlen, t2); + u = xlen; + r = 0; + while (u > 0) { + uint32_t wn, wx; + + u --; + wn = ((unsigned char *)t3)[u]; + wx = x[u]; + r = ((wx - (wn + r)) >> 8) & 1; + } + + /* + * Move the decoded p to another temporary buffer. + */ + mp = (uint32_t *)(tmp + 2 * fwlen); + memmove(mp, t1, 2 * fwlen * sizeof *t1); + + /* + * Compute s2 = x^dq mod q. + */ + q0i = br_i31_ninv31(mq[1]); + s2 = (uint32_t *)(tmp + fwlen); + br_i31_decode_reduce(s2, x, xlen, mq); + r &= br_i62_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i, + tmp + 3 * fwlen, TLEN - 3 * fwlen); + + /* + * Compute s1 = x^dp mod p. + */ + p0i = br_i31_ninv31(mp[1]); + s1 = (uint32_t *)(tmp + 3 * fwlen); + br_i31_decode_reduce(s1, x, xlen, mp); + r &= br_i62_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i, + tmp + 4 * fwlen, TLEN - 4 * fwlen); + + /* + * Compute: + * h = (s1 - s2)*(1/q) mod p + * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is + * unclear about whether p may be lower than q (some existing, + * widely deployed implementations of RSA don't tolerate p < q), + * but we want to support that occurrence, so we need to use the + * reduction function. + * + * Since we use br_i31_decode_reduce() for iq (purportedly, the + * inverse of q modulo p), we also tolerate improperly large + * values for this parameter. + */ + t1 = (uint32_t *)(tmp + 4 * fwlen); + t2 = (uint32_t *)(tmp + 5 * fwlen); + br_i31_reduce(t2, s2, mp); + br_i31_add(s1, mp, br_i31_sub(s1, t2, 1)); + br_i31_to_monty(s1, mp); + br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp); + br_i31_montymul(t2, s1, t1, mp, p0i); + + /* + * h is now in t2. We compute the final result: + * s = s2 + q*h + * All these operations are non-modular. + * + * We need mq, s2 and t2. We use the t3 buffer as destination. + * The buffers mp, s1 and t1 are no longer needed, so we can + * reuse them for t3. Moreover, the first step of the computation + * is to copy s2 into t3, after which s2 is not needed. Right + * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5. + * Therefore, we have ample room for t3 by simply using s2. + */ + t3 = s2; + br_i31_mulacc(t3, mq, t2); + + /* + * Encode the result. Since we already checked the value of xlen, + * we can just use it right away. + */ + br_i31_encode(x, xlen, t3); + + /* + * The only error conditions remaining at that point are invalid + * values for p and q (even integers). + */ + return p0i & q0i & r; +} + +/* see bearssl_rsa.h */ +br_rsa_private +br_rsa_i62_private_get(void) +{ + return &br_rsa_i62_private; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_private +br_rsa_i62_private_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pss_sign.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pss_sign.c new file mode 100644 index 0000000..7232f6d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pss_sign.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i62_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x) +{ + if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash, + salt_len, sk->n_bitlen, x)) + { + return 0; + } + return br_rsa_i62_private(x, sk); +} + +/* see bearssl_rsa.h */ +br_rsa_pss_sign +br_rsa_i62_pss_sign_get(void) +{ + return &br_rsa_i62_pss_sign; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_pss_sign +br_rsa_i62_pss_sign_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pss_vrfy.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pss_vrfy.c new file mode 100644 index 0000000..e726e82 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pss_vrfy.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk) +{ + unsigned char sig[BR_MAX_RSA_SIZE >> 3]; + + if (xlen > (sizeof sig)) { + return 0; + } + memcpy(sig, x, xlen); + if (!br_rsa_i62_public(sig, xlen, pk)) { + return 0; + } + return br_rsa_pss_sig_unpad(hf_data, hf_mgf1, + hash, salt_len, pk, sig); +} + +/* see bearssl_rsa.h */ +br_rsa_pss_vrfy +br_rsa_i62_pss_vrfy_get(void) +{ + return &br_rsa_i62_pss_vrfy; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_pss_vrfy +br_rsa_i62_pss_vrfy_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pub.c b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pub.c new file mode 100644 index 0000000..70cf61b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_i62_pub.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +/* + * As a strict minimum, we need four buffers that can hold a + * modular integer. But TLEN is expressed in 64-bit words. + */ +#define TLEN (2 * (2 + ((BR_MAX_RSA_SIZE + 30) / 31))) + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_i62_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk) +{ + const unsigned char *n; + size_t nlen; + uint64_t tmp[TLEN]; + uint32_t *m, *a; + size_t fwlen; + long z; + uint32_t m0i, r; + + /* + * Get the actual length of the modulus, and see if it fits within + * our stack buffer. We also check that the length of x[] is valid. + */ + n = pk->n; + nlen = pk->nlen; + while (nlen > 0 && *n == 0) { + n ++; + nlen --; + } + if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) { + return 0; + } + z = (long)nlen << 3; + fwlen = 1; + while (z > 0) { + z -= 31; + fwlen ++; + } + /* + * Convert fwlen to a count in 62-bit words. + */ + fwlen = (fwlen + 1) >> 1; + + /* + * The modulus gets decoded into m[]. + * The value to exponentiate goes into a[]. + */ + m = (uint32_t *)tmp; + a = (uint32_t *)(tmp + fwlen); + + /* + * Decode the modulus. + */ + br_i31_decode(m, n, nlen); + m0i = br_i31_ninv31(m[1]); + + /* + * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be + * an odd integer. + */ + r = m0i & 1; + + /* + * Decode x[] into a[]; we also check that its value is proper. + */ + r &= br_i31_decode_mod(a, x, xlen, m); + + /* + * Compute the modular exponentiation. + */ + br_i62_modpow_opt(a, pk->e, pk->elen, m, m0i, + tmp + 2 * fwlen, TLEN - 2 * fwlen); + + /* + * Encode the result. + */ + br_i31_encode(x, xlen, a); + return r; +} + +/* see bearssl_rsa.h */ +br_rsa_public +br_rsa_i62_public_get(void) +{ + return &br_rsa_i62_public; +} + +#else + +/* see bearssl_rsa.h */ +br_rsa_public +br_rsa_i62_public_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_oaep_pad.c b/BearSSL-OG/libbearssl/src/rsa/rsa_oaep_pad.c new file mode 100644 index 0000000..5327dc2 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_oaep_pad.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * Hash some data. This is put as a separate function so that stack + * allocation of the hash function context is done only for the duration + * of the hash. + */ +static void +hash_data(const br_hash_class *dig, void *dst, const void *src, size_t len) +{ + br_hash_compat_context hc; + + hc.vtable = dig; + dig->init(&hc.vtable); + dig->update(&hc.vtable, src, len); + dig->out(&hc.vtable, dst); +} + +/* see inner.h */ +size_t +br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len) +{ + size_t k, hlen; + unsigned char *buf; + + hlen = br_digest_size(dig); + + /* + * Compute actual modulus length (in bytes). + */ + k = pk->nlen; + while (k > 0 && pk->n[k - 1] == 0) { + k --; + } + + /* + * An error is reported if: + * - the modulus is too short; + * - the source message length is too long; + * - the destination buffer is too short. + */ + if (k < ((hlen << 1) + 2) + || src_len > (k - (hlen << 1) - 2) + || dst_max_len < k) + { + return 0; + } + + /* + * Apply padding. At this point, things cannot fail. + */ + buf = dst; + + /* + * Assemble: DB = lHash || PS || 0x01 || M + * We first place the source message M with memmove(), so that + * overlaps between source and destination buffers are supported. + */ + memmove(buf + k - src_len, src, src_len); + hash_data(dig, buf + 1 + hlen, label, label_len); + memset(buf + 1 + (hlen << 1), 0, k - src_len - (hlen << 1) - 2); + buf[k - src_len - 1] = 0x01; + + /* + * Make the random seed. + */ + (*rnd)->generate(rnd, buf + 1, hlen); + + /* + * Mask DB with the mask generated from the seed. + */ + br_mgf1_xor(buf + 1 + hlen, k - hlen - 1, dig, buf + 1, hlen); + + /* + * Mask the seed with the mask generated from the masked DB. + */ + br_mgf1_xor(buf + 1, hlen, dig, buf + 1 + hlen, k - hlen - 1); + + /* + * Padding result: EM = 0x00 || maskedSeed || maskedDB. + */ + buf[0] = 0x00; + return k; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_oaep_unpad.c b/BearSSL-OG/libbearssl/src/rsa/rsa_oaep_unpad.c new file mode 100644 index 0000000..7c4be6a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_oaep_unpad.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * Hash some data and XOR the result into the provided buffer. This is put + * as a separate function so that stack allocation of the hash function + * context is done only for the duration of the hash. + */ +static void +xor_hash_data(const br_hash_class *dig, void *dst, const void *src, size_t len) +{ + br_hash_compat_context hc; + unsigned char tmp[64]; + unsigned char *buf; + size_t u, hlen; + + hc.vtable = dig; + dig->init(&hc.vtable); + dig->update(&hc.vtable, src, len); + dig->out(&hc.vtable, tmp); + buf = dst; + hlen = br_digest_size(dig); + for (u = 0; u < hlen; u ++) { + buf[u] ^= tmp[u]; + } +} + +/* see inner.h */ +uint32_t +br_rsa_oaep_unpad(const br_hash_class *dig, + const void *label, size_t label_len, + void *data, size_t *len) +{ + size_t u, k, hlen; + unsigned char *buf; + uint32_t r, s, zlen; + + hlen = br_digest_size(dig); + k = *len; + buf = data; + + /* + * There must be room for the padding. + */ + if (k < ((hlen << 1) + 2)) { + return 0; + } + + /* + * Unmask the seed, then the DB value. + */ + br_mgf1_xor(buf + 1, hlen, dig, buf + 1 + hlen, k - hlen - 1); + br_mgf1_xor(buf + 1 + hlen, k - hlen - 1, dig, buf + 1, hlen); + + /* + * Hash the label and XOR it with the value in the array; if + * they are equal then these should yield only zeros. + */ + xor_hash_data(dig, buf + 1 + hlen, label, label_len); + + /* + * At that point, if the padding was correct, when we should + * have: 0x00 || seed || 0x00 ... 0x00 0x01 || M + * Padding is valid as long as: + * - There is at least hlen+1 leading bytes of value 0x00. + * - There is at least one non-zero byte. + * - The first (leftmost) non-zero byte has value 0x01. + * + * Ultimately, we may leak the resulting message length, i.e. + * the position of the byte of value 0x01, but we must take care + * to do so only if the number of zero bytes has been verified + * to be at least hlen+1. + * + * The loop below counts the number of bytes of value 0x00, and + * checks that the next byte has value 0x01, in constant-time. + * + * - If the initial byte (before the seed) is not 0x00, then + * r and s are set to 0, and stay there. + * - Value r is 1 until the first non-zero byte is reached + * (after the seed); it switches to 0 at that point. + * - Value s is set to 1 if and only if the data encountered + * at the time of the transition of r from 1 to 0 has value + * exactly 0x01. + * - Value zlen counts the number of leading bytes of value zero + * (after the seed). + */ + r = 1 - ((buf[0] + 0xFF) >> 8); + s = 0; + zlen = 0; + for (u = hlen + 1; u < k; u ++) { + uint32_t w, nz; + + w = buf[u]; + + /* + * nz == 1 only for the first non-zero byte. + */ + nz = r & ((w + 0xFF) >> 8); + s |= nz & EQ(w, 0x01); + r &= NOT(nz); + zlen += r; + } + + /* + * Padding is correct only if s == 1, _and_ zlen >= hlen. + */ + s &= GE(zlen, (uint32_t)hlen); + + /* + * At that point, padding was verified, and we are now allowed + * to make conditional jumps. + */ + if (s) { + size_t plen; + + plen = 2 + hlen + zlen; + k -= plen; + memmove(buf, buf + plen, k); + *len = k; + } + return s; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_pkcs1_sig_pad.c b/BearSSL-OG/libbearssl/src/rsa/rsa_pkcs1_sig_pad.c new file mode 100644 index 0000000..06c3bd7 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_pkcs1_sig_pad.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + uint32_t n_bitlen, unsigned char *x) +{ + size_t u, x3, xlen; + + /* + * Padded hash value has format: + * 00 01 FF .. FF 00 30 x1 30 x2 06 x3 OID 05 00 04 x4 HASH + * + * with the following rules: + * + * -- Total length is equal to the modulus length (unsigned + * encoding). + * + * -- There must be at least eight bytes of value 0xFF. + * + * -- x4 is equal to the hash length (hash_len). + * + * -- x3 is equal to the encoded OID value length (hash_oid[0]). + * + * -- x2 = x3 + 4. + * + * -- x1 = x2 + x4 + 4 = x3 + x4 + 8. + * + * Note: the "05 00" is optional (signatures with and without + * that sequence exist in practice), but notes in PKCS#1 seem to + * indicate that the presence of that sequence (specifically, + * an ASN.1 NULL value for the hash parameters) may be slightly + * more "standard" than the opposite. + */ + xlen = (n_bitlen + 7) >> 3; + + if (hash_oid == NULL) { + if (xlen < hash_len + 11) { + return 0; + } + x[0] = 0x00; + x[1] = 0x01; + u = xlen - hash_len; + memset(x + 2, 0xFF, u - 3); + x[u - 1] = 0x00; + } else { + x3 = hash_oid[0]; + + /* + * Check that there is enough room for all the elements, + * including at least eight bytes of value 0xFF. + */ + if (xlen < (x3 + hash_len + 21)) { + return 0; + } + x[0] = 0x00; + x[1] = 0x01; + u = xlen - x3 - hash_len - 11; + memset(x + 2, 0xFF, u - 2); + x[u] = 0x00; + x[u + 1] = 0x30; + x[u + 2] = x3 + hash_len + 8; + x[u + 3] = 0x30; + x[u + 4] = x3 + 4; + x[u + 5] = 0x06; + memcpy(x + u + 6, hash_oid, x3 + 1); + u += x3 + 7; + x[u ++] = 0x05; + x[u ++] = 0x00; + x[u ++] = 0x04; + x[u ++] = hash_len; + } + memcpy(x + u, hash, hash_len); + return 1; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_pkcs1_sig_unpad.c b/BearSSL-OG/libbearssl/src/rsa/rsa_pkcs1_sig_unpad.c new file mode 100644 index 0000000..c8ae08f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_pkcs1_sig_unpad.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, + const unsigned char *hash_oid, size_t hash_len, + unsigned char *hash_out) +{ + static const unsigned char pad1[] = { + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + + unsigned char pad2[43]; + size_t u, x2, x3, pad_len, zlen; + + if (sig_len < 11) { + return 0; + } + + /* + * Expected format: + * 00 01 FF ... FF 00 30 x1 30 x2 06 x3 OID [ 05 00 ] 04 x4 HASH + * + * with the following rules: + * + * -- Total length is that of the modulus and the signature + * (this was already verified by br_rsa_i31_public()). + * + * -- There are at least eight bytes of value 0xFF. + * + * -- x4 is equal to the hash length (hash_len). + * + * -- x3 is equal to the encoded OID value length (so x3 is the + * first byte of hash_oid[]). + * + * -- If the "05 00" is present, then x2 == x3 + 4; otherwise, + * x2 == x3 + 2. + * + * -- x1 == x2 + x4 + 4. + * + * So the total length after the last "FF" is either x3 + x4 + 11 + * (with the "05 00") or x3 + x4 + 9 (without the "05 00"). + */ + + /* + * Check the "00 01 FF .. FF 00" with at least eight 0xFF bytes. + * The comparison is valid because we made sure that the signature + * is at least 11 bytes long. + */ + if (memcmp(sig, pad1, sizeof pad1) != 0) { + return 0; + } + for (u = sizeof pad1; u < sig_len; u ++) { + if (sig[u] != 0xFF) { + break; + } + } + + /* + * Remaining length is sig_len - u bytes (including the 00 just + * after the last FF). This must be equal to one of the two + * possible values (depending on whether the "05 00" sequence is + * present or not). + */ + if (hash_oid == NULL) { + if (sig_len - u != hash_len + 1 || sig[u] != 0x00) { + return 0; + } + } else { + x3 = hash_oid[0]; + pad_len = x3 + 9; + memset(pad2, 0, pad_len); + zlen = sig_len - u - hash_len; + if (zlen == pad_len) { + x2 = x3 + 2; + } else if (zlen == pad_len + 2) { + x2 = x3 + 4; + pad_len = zlen; + pad2[pad_len - 4] = 0x05; + } else { + return 0; + } + pad2[1] = 0x30; + pad2[2] = x2 + hash_len + 4; + pad2[3] = 0x30; + pad2[4] = x2; + pad2[5] = 0x06; + memcpy(pad2 + 6, hash_oid, x3 + 1); + pad2[pad_len - 2] = 0x04; + pad2[pad_len - 1] = hash_len; + if (memcmp(pad2, sig + u, pad_len) != 0) { + return 0; + } + } + memcpy(hash_out, sig + sig_len - hash_len, hash_len); + return 1; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_pss_sig_pad.c b/BearSSL-OG/libbearssl/src/rsa/rsa_pss_sig_pad.c new file mode 100644 index 0000000..13e9027 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_pss_sig_pad.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_rsa_pss_sig_pad(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash, size_t salt_len, + uint32_t n_bitlen, unsigned char *x) +{ + size_t xlen, hash_len; + br_hash_compat_context hc; + unsigned char *salt, *seed; + + hash_len = br_digest_size(hf_data); + + /* + * The padded string is one bit smaller than the modulus; + * notably, if the modulus length is equal to 1 modulo 8, then + * the padded string will be one _byte_ smaller, and the first + * byte will be set to 0. We apply these transformations here. + */ + n_bitlen --; + if ((n_bitlen & 7) == 0) { + *x ++ = 0; + } + xlen = (n_bitlen + 7) >> 3; + + /* + * Check that the modulus is large enough for the hash value + * length combined with the intended salt length. + */ + if (hash_len > xlen || salt_len > xlen + || (hash_len + salt_len + 2) > xlen) + { + return 0; + } + + /* + * Produce a random salt. + */ + salt = x + xlen - hash_len - salt_len - 1; + if (salt_len != 0) { + (*rng)->generate(rng, salt, salt_len); + } + + /* + * Compute the seed for MGF1. + */ + seed = x + xlen - hash_len - 1; + hf_data->init(&hc.vtable); + memset(seed, 0, 8); + hf_data->update(&hc.vtable, seed, 8); + hf_data->update(&hc.vtable, hash, hash_len); + hf_data->update(&hc.vtable, salt, salt_len); + hf_data->out(&hc.vtable, seed); + + /* + * Prepare string PS (padded salt). The salt is already at the + * right place. + */ + memset(x, 0, xlen - salt_len - hash_len - 2); + x[xlen - salt_len - hash_len - 2] = 0x01; + + /* + * Generate the mask and XOR it into PS. + */ + br_mgf1_xor(x, xlen - hash_len - 1, hf_mgf1, seed, hash_len); + + /* + * Clear the top bits to ensure the value is lower than the + * modulus. + */ + x[0] &= 0xFF >> (((uint32_t)xlen << 3) - n_bitlen); + + /* + * The seed (H) is already in the right place. We just set the + * last byte. + */ + x[xlen - 1] = 0xBC; + + return 1; +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_pss_sig_unpad.c b/BearSSL-OG/libbearssl/src/rsa/rsa_pss_sig_unpad.c new file mode 100644 index 0000000..0c6ae99 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_pss_sig_unpad.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see inner.h */ +uint32_t +br_rsa_pss_sig_unpad(const br_hash_class *hf_data, + const br_hash_class *hf_mgf1, + const unsigned char *hash, size_t salt_len, + const br_rsa_public_key *pk, unsigned char *x) +{ + size_t u, xlen, hash_len; + br_hash_compat_context hc; + unsigned char *seed, *salt; + unsigned char tmp[64]; + uint32_t r, n_bitlen; + + hash_len = br_digest_size(hf_data); + + /* + * Value r will be set to a non-zero value is any test fails. + */ + r = 0; + + /* + * The value bit length (as an integer) must be strictly less than + * that of the modulus. + */ + for (u = 0; u < pk->nlen; u ++) { + if (pk->n[u] != 0) { + break; + } + } + if (u == pk->nlen) { + return 0; + } + n_bitlen = BIT_LENGTH(pk->n[u]) + ((uint32_t)(pk->nlen - u - 1) << 3); + n_bitlen --; + if ((n_bitlen & 7) == 0) { + r |= *x ++; + } else { + r |= x[0] & (0xFF << (n_bitlen & 7)); + } + xlen = (n_bitlen + 7) >> 3; + + /* + * Check that the modulus is large enough for the hash value + * length combined with the intended salt length. + */ + if (hash_len > xlen || salt_len > xlen + || (hash_len + salt_len + 2) > xlen) + { + return 0; + } + + /* + * Check value of rightmost byte. + */ + r |= x[xlen - 1] ^ 0xBC; + + /* + * Generate the mask and XOR it into the first bytes to reveal PS; + * we must also mask out the leading bits. + */ + seed = x + xlen - hash_len - 1; + br_mgf1_xor(x, xlen - hash_len - 1, hf_mgf1, seed, hash_len); + if ((n_bitlen & 7) != 0) { + x[0] &= 0xFF >> (8 - (n_bitlen & 7)); + } + + /* + * Check that all padding bytes have the expected value. + */ + for (u = 0; u < (xlen - hash_len - salt_len - 2); u ++) { + r |= x[u]; + } + r |= x[xlen - hash_len - salt_len - 2] ^ 0x01; + + /* + * Recompute H. + */ + salt = x + xlen - hash_len - salt_len - 1; + hf_data->init(&hc.vtable); + memset(tmp, 0, 8); + hf_data->update(&hc.vtable, tmp, 8); + hf_data->update(&hc.vtable, hash, hash_len); + hf_data->update(&hc.vtable, salt, salt_len); + hf_data->out(&hc.vtable, tmp); + + /* + * Check that the recomputed H value matches the one appearing + * in the string. + */ + for (u = 0; u < hash_len; u ++) { + r |= tmp[u] ^ x[(xlen - hash_len - 1) + u]; + } + + return EQ0(r); +} diff --git a/BearSSL-OG/libbearssl/src/rsa/rsa_ssl_decrypt.c b/BearSSL-OG/libbearssl/src/rsa/rsa_ssl_decrypt.c new file mode 100644 index 0000000..047eb18 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/rsa/rsa_ssl_decrypt.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_rsa.h */ +uint32_t +br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk, + unsigned char *data, size_t len) +{ + uint32_t x; + size_t u; + + /* + * A first check on length. Since this test works only on the + * buffer length, it needs not (and cannot) be constant-time. + */ + if (len < 59 || len != (sk->n_bitlen + 7) >> 3) { + return 0; + } + x = core(data, sk); + + x &= EQ(data[0], 0x00); + x &= EQ(data[1], 0x02); + for (u = 2; u < (len - 49); u ++) { + x &= NEQ(data[u], 0); + } + x &= EQ(data[len - 49], 0x00); + memmove(data, data + len - 48, 48); + return x; +} diff --git a/BearSSL-OG/libbearssl/src/settings.c b/BearSSL-OG/libbearssl/src/settings.c new file mode 100644 index 0000000..0014609 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/settings.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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 const br_config_option config[] = { + { "BR_64", +#if BR_64 + 1 +#else + 0 +#endif + }, + { "BR_AES_X86NI", +#if BR_AES_X86NI + 1 +#else + 0 +#endif + }, + { "BR_amd64", +#if BR_amd64 + 1 +#else + 0 +#endif + }, + { "BR_ARMEL_CORTEXM_GCC", +#if BR_ARMEL_CORTEXM_GCC + 1 +#else + 0 +#endif + }, + { "BR_BE_UNALIGNED", +#if BR_BE_UNALIGNED + 1 +#else + 0 +#endif + }, + { "BR_CLANG", +#if BR_CLANG + 1 +#else + 0 +#endif + }, + { "BR_CLANG_3_7", +#if BR_CLANG_3_7 + 1 +#else + 0 +#endif + }, + { "BR_CLANG_3_8", +#if BR_CLANG_3_8 + 1 +#else + 0 +#endif + }, + { "BR_CT_MUL15", +#if BR_CT_MUL15 + 1 +#else + 0 +#endif + }, + { "BR_CT_MUL31", +#if BR_CT_MUL31 + 1 +#else + 0 +#endif + }, + { "BR_GCC", +#if BR_GCC + 1 +#else + 0 +#endif + }, + { "BR_GCC_4_4", +#if BR_GCC_4_4 + 1 +#else + 0 +#endif + }, + { "BR_GCC_4_5", +#if BR_GCC_4_5 + 1 +#else + 0 +#endif + }, + { "BR_GCC_4_6", +#if BR_GCC_4_6 + 1 +#else + 0 +#endif + }, + { "BR_GCC_4_7", +#if BR_GCC_4_7 + 1 +#else + 0 +#endif + }, + { "BR_GCC_4_8", +#if BR_GCC_4_8 + 1 +#else + 0 +#endif + }, + { "BR_GCC_4_9", +#if BR_GCC_4_9 + 1 +#else + 0 +#endif + }, + { "BR_GCC_5_0", +#if BR_GCC_5_0 + 1 +#else + 0 +#endif + }, + { "BR_i386", +#if BR_i386 + 1 +#else + 0 +#endif + }, + { "BR_INT128", +#if BR_INT128 + 1 +#else + 0 +#endif + }, + { "BR_LE_UNALIGNED", +#if BR_LE_UNALIGNED + 1 +#else + 0 +#endif + }, + { "BR_LOMUL", +#if BR_LOMUL + 1 +#else + 0 +#endif + }, + { "BR_MAX_EC_SIZE", BR_MAX_EC_SIZE }, + { "BR_MAX_RSA_SIZE", BR_MAX_RSA_SIZE }, + { "BR_MAX_RSA_FACTOR", BR_MAX_RSA_FACTOR }, + { "BR_MSC", +#if BR_MSC + 1 +#else + 0 +#endif + }, + { "BR_MSC_2005", +#if BR_MSC_2005 + 1 +#else + 0 +#endif + }, + { "BR_MSC_2008", +#if BR_MSC_2008 + 1 +#else + 0 +#endif + }, + { "BR_MSC_2010", +#if BR_MSC_2010 + 1 +#else + 0 +#endif + }, + { "BR_MSC_2012", +#if BR_MSC_2012 + 1 +#else + 0 +#endif + }, + { "BR_MSC_2013", +#if BR_MSC_2013 + 1 +#else + 0 +#endif + }, + { "BR_MSC_2015", +#if BR_MSC_2015 + 1 +#else + 0 +#endif + }, + { "BR_POWER8", +#if BR_POWER8 + 1 +#else + 0 +#endif + }, + { "BR_RDRAND", +#if BR_RDRAND + 1 +#else + 0 +#endif + }, + { "BR_SLOW_MUL", +#if BR_SLOW_MUL + 1 +#else + 0 +#endif + }, + { "BR_SLOW_MUL15", +#if BR_SLOW_MUL15 + 1 +#else + 0 +#endif + }, + { "BR_SSE2", +#if BR_SSE2 + 1 +#else + 0 +#endif + }, + { "BR_UMUL128", +#if BR_UMUL128 + 1 +#else + 0 +#endif + }, + { "BR_USE_UNIX_TIME", +#if BR_USE_UNIX_TIME + 1 +#else + 0 +#endif + }, + { "BR_USE_WIN32_RAND", +#if BR_USE_WIN32_RAND + 1 +#else + 0 +#endif + }, + { "BR_USE_XBOX_RAND", +#if BR_USE_XBOX_RAND + 1 +#else + 0 +#endif + }, + { "BR_USE_WIN32_TIME", +#if BR_USE_WIN32_TIME + 1 +#else + 0 +#endif + }, + + { NULL, 0 } +}; + +/* see bearssl.h */ +const br_config_option * +br_get_config(void) +{ + return config; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/prf.c b/BearSSL-OG/libbearssl/src/ssl/prf.c new file mode 100644 index 0000000..f04a5fb --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/prf.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_tls_phash(void *dst, size_t len, + const br_hash_class *dig, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed) +{ + unsigned char *buf; + unsigned char tmp[64], a[64]; + br_hmac_key_context kc; + br_hmac_context hc; + size_t label_len, hlen, u; + + if (len == 0) { + return; + } + buf = dst; + for (label_len = 0; label[label_len]; label_len ++); + hlen = br_digest_size(dig); + br_hmac_key_init(&kc, dig, secret, secret_len); + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, label, label_len); + for (u = 0; u < seed_num; u ++) { + br_hmac_update(&hc, seed[u].data, seed[u].len); + } + br_hmac_out(&hc, a); + for (;;) { + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, a, hlen); + br_hmac_update(&hc, label, label_len); + for (u = 0; u < seed_num; u ++) { + br_hmac_update(&hc, seed[u].data, seed[u].len); + } + br_hmac_out(&hc, tmp); + for (u = 0; u < hlen && u < len; u ++) { + buf[u] ^= tmp[u]; + } + buf += u; + len -= u; + if (len == 0) { + return; + } + br_hmac_init(&hc, &kc, 0); + br_hmac_update(&hc, a, hlen); + br_hmac_out(&hc, a); + } +} diff --git a/BearSSL-OG/libbearssl/src/ssl/prf_md5sha1.c b/BearSSL-OG/libbearssl/src/ssl/prf_md5sha1.c new file mode 100644 index 0000000..3212833 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/prf_md5sha1.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl.h */ +void +br_tls10_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed) +{ + const unsigned char *s1; + size_t slen; + + s1 = secret; + slen = (secret_len + 1) >> 1; + memset(dst, 0, len); + br_tls_phash(dst, len, &br_md5_vtable, + s1, slen, label, seed_num, seed); + br_tls_phash(dst, len, &br_sha1_vtable, + s1 + secret_len - slen, slen, label, seed_num, seed); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/prf_sha256.c b/BearSSL-OG/libbearssl/src/ssl/prf_sha256.c new file mode 100644 index 0000000..76041de --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/prf_sha256.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl.h */ +void +br_tls12_sha256_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed) +{ + memset(dst, 0, len); + br_tls_phash(dst, len, &br_sha256_vtable, + secret, secret_len, label, seed_num, seed); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/prf_sha384.c b/BearSSL-OG/libbearssl/src/ssl/prf_sha384.c new file mode 100644 index 0000000..c20c4e6 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/prf_sha384.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl.h */ +void +br_tls12_sha384_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed) +{ + memset(dst, 0, len); + br_tls_phash(dst, len, &br_sha384_vtable, + secret, secret_len, label, seed_num, seed); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_ccert_single_ec.c b/BearSSL-OG/libbearssl/src/ssl/ssl_ccert_single_ec.c new file mode 100644 index 0000000..2e1e54f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_ccert_single_ec.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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; + return; + } + } + + /* + * 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; + uint32_t r; + size_t xoff, xlen; + + zc = (br_ssl_client_certificate_ec_context *)pctx; + r = zc->iec->mul(data, *len, zc->sk->x, zc->sk->xlen, zc->sk->curve); + xoff = zc->iec->xoff(zc->sk->curve, &xlen); + memmove(data, data + xoff, xlen); + *len = xlen; + return r; +} + +static size_t +cc_do_sign(const br_ssl_client_certificate_class **pctx, + int hash_id, size_t hv_len, unsigned char *data, size_t len) +{ + br_ssl_client_certificate_ec_context *zc; + unsigned char hv[64]; + const br_hash_class *hc; + + zc = (br_ssl_client_certificate_ec_context *)pctx; + memcpy(hv, data, hv_len); + hc = br_multihash_getimpl(zc->mhash, hash_id); + if (hc == NULL) { + return 0; + } + if (len < 139) { + return 0; + } + return zc->iecdsa(zc->iec, hc, hv, zc->sk, data); +} + +static const br_ssl_client_certificate_class ccert_vtable = { + sizeof(br_ssl_client_certificate_ec_context), + cc_none0, /* start_name_list */ + cc_none1, /* start_name */ + cc_none2, /* append_name */ + cc_none0, /* end_name */ + cc_none0, /* end_name_list */ + cc_choose, + cc_do_keyx, + cc_do_sign +}; + +/* see bearssl_ssl.h */ +void +br_ssl_client_set_single_ec(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa) +{ + cc->client_auth.single_ec.vtable = &ccert_vtable; + cc->client_auth.single_ec.chain = chain; + cc->client_auth.single_ec.chain_len = chain_len; + cc->client_auth.single_ec.sk = sk; + cc->client_auth.single_ec.allowed_usages = allowed_usages; + cc->client_auth.single_ec.issuer_key_type = cert_issuer_key_type; + cc->client_auth.single_ec.mhash = &cc->eng.mhash; + cc->client_auth.single_ec.iec = iec; + cc->client_auth.single_ec.iecdsa = iecdsa; + cc->client_auth_vtable = &cc->client_auth.single_ec.vtable; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_ccert_single_rsa.c b/BearSSL-OG/libbearssl/src/ssl/ssl_ccert_single_rsa.c new file mode 100644 index 0000000..690df20 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_ccert_single_rsa.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_client.c b/BearSSL-OG/libbearssl/src/ssl/ssl_client.c new file mode 100644 index 0000000..28c404b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_client.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_client_zero(br_ssl_client_context *cc) +{ + /* + * For really standard C, we should explicitly set to NULL all + * pointers, and 0 all other fields. However, on all our target + * architectures, a direct memset() will work, be faster, and + * use a lot less code. + */ + memset(cc, 0, sizeof *cc); +} + +/* see bearssl_ssl.h */ +int +br_ssl_client_reset(br_ssl_client_context *cc, + const char *server_name, int resume_session) +{ + size_t n; + + br_ssl_engine_set_buffer(&cc->eng, NULL, 0, 0); + cc->eng.version_out = cc->eng.version_min; + if (!resume_session) { + br_ssl_client_forget_session(cc); + } + if (!br_ssl_engine_init_rand(&cc->eng)) { + return 0; + } + + /* + * We always set back the "reneg" flag to 0 because we use it + * to distinguish between first handshake and renegotiation. + * Note that "renegotiation" and "session resumption" are two + * different things. + */ + cc->eng.reneg = 0; + + if (server_name == NULL) { + cc->eng.server_name[0] = 0; + } else { + n = strlen(server_name) + 1; + if (n > sizeof cc->eng.server_name) { + br_ssl_engine_fail(&cc->eng, BR_ERR_BAD_PARAM); + return 0; + } + memcpy(cc->eng.server_name, server_name, n); + } + + br_ssl_engine_hs_reset(&cc->eng, + br_ssl_hs_client_init_main, br_ssl_hs_client_run); + return br_ssl_engine_last_error(&cc->eng) == BR_ERR_OK; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_client_default_rsapub.c b/BearSSL-OG/libbearssl/src/ssl/ssl_client_default_rsapub.c new file mode 100644 index 0000000..2cdaab8 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_client_default_rsapub.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_client_set_default_rsapub(br_ssl_client_context *cc) +{ + br_ssl_client_set_rsapub(cc, br_rsa_public_get_default()); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_client_full.c b/BearSSL-OG/libbearssl/src/ssl/ssl_client_full.c new file mode 100644 index 0000000..9814349 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_client_full.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_client_init_full(br_ssl_client_context *cc, + br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) +{ + /* + * The "full" profile supports all implemented cipher suites. + * + * Rationale for suite order, from most important to least + * important rule: + * + * -- Don't use 3DES if AES or ChaCha20 is available. + * -- Try to have Forward Secrecy (ECDHE suite) if possible. + * -- When not using Forward Secrecy, ECDH key exchange is + * better than RSA key exchange (slightly more expensive on the + * client, but much cheaper on the server, and it implies smaller + * messages). + * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller code). + * -- GCM is better than CCM and CBC. CCM is better than CBC. + * -- CCM is preferable over CCM_8 (with CCM_8, forgeries may succeed + * with probability 2^(-64)). + * -- AES-128 is preferred over AES-256 (AES-128 is already + * strong enough, and AES-256 is 40% more expensive). + */ + static const uint16_t suites[] = { + BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + BR_TLS_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_RSA_WITH_AES_128_CCM, + BR_TLS_RSA_WITH_AES_256_CCM, + BR_TLS_RSA_WITH_AES_128_CCM_8, + BR_TLS_RSA_WITH_AES_256_CCM_8, + BR_TLS_RSA_WITH_AES_128_CBC_SHA256, + BR_TLS_RSA_WITH_AES_256_CBC_SHA256, + BR_TLS_RSA_WITH_AES_128_CBC_SHA, + BR_TLS_RSA_WITH_AES_256_CBC_SHA, + BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA + }; + + /* + * All hash functions are activated. + * Note: the X.509 validation engine will nonetheless refuse to + * validate signatures that use MD5 as hash function. + */ + static const br_hash_class *hashes[] = { + &br_md5_vtable, + &br_sha1_vtable, + &br_sha224_vtable, + &br_sha256_vtable, + &br_sha384_vtable, + &br_sha512_vtable + }; + + int id; + + /* + * Reset client context and set supported versions from TLS-1.0 + * to TLS-1.2 (inclusive). + */ + br_ssl_client_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12); + + /* + * X.509 engine uses SHA-256 to hash certificate DN (for + * comparisons). + */ + br_x509_minimal_init(xc, &br_sha256_vtable, + trust_anchors, trust_anchors_num); + + /* + * Set suites and asymmetric crypto implementations. We use the + * "i31" code for RSA (it is somewhat faster than the "i32" + * implementation). + * TODO: change that when better implementations are made available. + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + br_ssl_client_set_default_rsapub(cc); + br_ssl_engine_set_default_rsavrfy(&cc->eng); + br_ssl_engine_set_default_ecdsa(&cc->eng); + br_x509_minimal_set_rsa(xc, br_ssl_engine_get_rsavrfy(&cc->eng)); + br_x509_minimal_set_ecdsa(xc, + br_ssl_engine_get_ec(&cc->eng), + br_ssl_engine_get_ecdsa(&cc->eng)); + + /* + * Set supported hash functions, for the SSL engine and for the + * X.509 engine. + */ + for (id = br_md5_ID; id <= br_sha512_ID; id ++) { + const br_hash_class *hc; + + hc = hashes[id - 1]; + br_ssl_engine_set_hash(&cc->eng, id, hc); + br_x509_minimal_set_hash(xc, id, hc); + } + + /* + * Link the X.509 engine in the SSL engine. + */ + br_ssl_engine_set_x509(&cc->eng, &xc->vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf); + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); + + /* + * Symmetric encryption. We use the "default" implementations + * (fastest among constant-time implementations). + */ + br_ssl_engine_set_default_aes_cbc(&cc->eng); + br_ssl_engine_set_default_aes_ccm(&cc->eng); + br_ssl_engine_set_default_aes_gcm(&cc->eng); + br_ssl_engine_set_default_des_cbc(&cc->eng); + br_ssl_engine_set_default_chapol(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine.c new file mode 100644 index 0000000..fc8b05a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine.c @@ -0,0 +1,1589 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#if 0 +/* obsolete */ + +/* + * If BR_USE_URANDOM is not defined, then try to autodetect its presence + * through compiler macros. + */ +#ifndef BR_USE_URANDOM + +/* + * Macro values documented on: + * https://sourceforge.net/p/predef/wiki/OperatingSystems/ + * + * Only the most common systems have been included here for now. This + * should be enriched later on. + */ +#if defined _AIX \ + || defined __ANDROID__ \ + || defined __FreeBSD__ \ + || defined __NetBSD__ \ + || defined __OpenBSD__ \ + || defined __DragonFly__ \ + || defined __linux__ \ + || (defined __sun && (defined __SVR4 || defined __svr4__)) \ + || (defined __APPLE__ && defined __MACH__) +#define BR_USE_URANDOM 1 +#endif + +#endif + +/* + * If BR_USE_WIN32_RAND is not defined, perform autodetection here. + */ +#ifndef _XBOX +#ifndef BR_USE_WIN32_RAND +#if defined _WIN32 || defined _WIN64 +#define BR_USE_WIN32_RAND 1 +#endif +#endif + +#ifdef _XBOX +#define BR_USE_XBOX_RAND 1 +#endif + +#endif + +#if BR_USE_URANDOM +#include +#include +#include +#include +#endif + +#if BR_USE_WIN32_RAND +#include +#include +#pragma comment(lib, "advapi32") +#endif + +#endif + +/* ==================================================================== */ +/* + * This part of the file does the low-level record management. + */ + +/* + * IMPLEMENTATION NOTES + * ==================== + * + * In this file, we designate by "input" (and the "i" letter) the "recv" + * operations: incoming records from the peer, from which payload data + * is obtained, and must be extracted by the application (or the SSL + * handshake engine). Similarly, "output" (and the "o" letter) is for + * "send": payload data injected by the application (and SSL handshake + * engine), to be wrapped into records, that are then conveyed to the + * peer over the transport medium. + * + * The input and output buffers may be distinct or shared. When + * shared, input and output cannot occur concurrently; the caller + * must make sure that it never needs to output data while input + * data has been received. In practice, a shared buffer prevents + * pipelining of HTTP requests, or similar protocols; however, a + * shared buffer saves RAM. + * + * The input buffer is pointed to by 'ibuf' and has size 'ibuf_len'; + * the output buffer is pointed to by 'obuf' and has size 'obuf_len'. + * From the size of these buffers is derived the maximum fragment + * length, which will be honoured upon sending records; regardless of + * that length, incoming records will be processed as long as they + * fit in the input buffer, and their length still complies with the + * protocol specification (maximum plaintext payload length is 16384 + * bytes). + * + * Three registers are used to manage buffering in ibuf, called ixa, + * ixb and ixc. Similarly, three registers are used to manage buffering + * in obuf, called oxa, oxb and oxc. + * + * + * At any time, the engine is in one of the following modes: + * -- Failed mode: an error occurs, no I/O can happen. + * -- Input mode: the engine can either receive record bytes from the + * transport layer, or it has some buffered payload bytes to yield. + * -- Output mode: the engine can either receive payload bytes, or it + * has some record bytes to send to the transport layer. + * -- Input/Output mode: both input and output modes are active. When + * the buffer is shared, this can happen only when the buffer is empty + * (no buffered payload bytes or record bytes in either direction). + * + * + * Failed mode: + * ------------ + * + * I/O failed for some reason (invalid received data, not enough room + * for the next record...). No I/O may ever occur again for this context, + * until an explicit reset is performed. This mode, and the error code, + * are also used for protocol errors, especially handshake errors. + * + * + * Input mode: + * ----------- + * + * ixa index within ibuf[] for the currently read data + * ixb maximum index within ibuf[] for the currently read data + * ixc number of bytes not yet received for the current record + * + * -- When ixa == ixb, there is no available data for readers. When + * ixa != ixb, there is available data and it starts at offset ixa. + * + * -- When waiting for the next record header, ixa and ixb are equal + * and contain a value ranging from 0 to 4; ixc is equal to 5-ixa. + * + * -- When the header has been received, record data is obtained. The + * ixc field records how many bytes are still needed to reach the + * end of the current record. + * + * ** If encryption is active, then ixa and ixb are kept equal, and + * point to the end of the currently received record bytes. When + * ixc reaches 0, decryption/MAC is applied, and ixa and ixb are + * adjusted. + * + * ** If encryption is not active, then ixa and ixb are distinct + * and data can be read right away. Additional record data is + * obtained only when ixa == ixb. + * + * Note: in input mode and no encryption, records larger than the buffer + * size are allowed. When encryption is active, the complete record must + * fit within the buffer, since it cannot be decrypted/MACed until it + * has been completely received. + * + * -- When receiving the next record header, 'version_in' contains the + * expected input version (0 if not expecting a specific version); on + * mismatch, the mode switches to 'failed'. + * + * -- When the header has been received, 'version_in' contains the received + * version. It is up to the caller to check and adjust the 'version_in' field + * to implement the required semantics. + * + * -- The 'record_type_in' field is updated with the incoming record type + * when the next record header has been received. + * + * + * Output mode: + * ------------ + * + * oxa index within obuf[] for the currently accumulated data + * oxb maximum index within obuf[] for record data + * oxc pointer for start of record data, and for record sending + * + * -- When oxa != oxb, more data can be accumulated into the current + * record; when oxa == oxb, a closed record is being sent. + * + * -- When accumulating data, oxc points to the start of the data. + * + * -- During record sending, oxa (and oxb) point to the next record byte + * to send, and oxc indicates the end of the current record. + * + * Note: sent records must fit within the buffer, since the header is + * adjusted only when the complete record has been assembled. + * + * -- The 'version_out' and 'record_type_out' fields are used to build the + * record header when the mode is switched to 'sending'. + * + * + * Modes: + * ------ + * + * The state register iomode contains one of the following values: + * + * BR_IO_FAILED I/O failed + * BR_IO_IN input mode + * BR_IO_OUT output mode + * BR_IO_INOUT input/output mode + * + * Whether encryption is active on incoming records is indicated by the + * incrypt flag. For outgoing records, there is no such flag; "encryption" + * is always considered active, but initially uses functions that do not + * encrypt anything. The 'incrypt' flag is needed because when there is + * no active encryption, records larger than the I/O buffer are accepted. + * + * Note: we do not support no-encryption modes (MAC only). + * + * TODO: implement GCM support + * + * + * Misc: + * ----- + * + * 'max_frag_len' is the maximum plaintext size for an outgoing record. + * By default, it is set to the maximum value that fits in the provided + * buffers, in the following list: 512, 1024, 2048, 4096, 16384. The + * caller may change it if needed, but the new value MUST still fit in + * the buffers, and it MUST be one of the list above for compatibility + * with the Maximum Fragment Length extension. + * + * For incoming records, only the total buffer length and current + * encryption mode impact the maximum length for incoming records. The + * 'max_frag_len' value is still adjusted so that records up to that + * length can be both received and sent. + * + * + * Offsets and lengths: + * -------------------- + * + * When sending fragments with TLS-1.1+, the maximum overhead is: + * 5 bytes for the record header + * 16 bytes for the explicit IV + * 48 bytes for the MAC (HMAC/SHA-384) + * 16 bytes for the padding (AES) + * so a total of 85 extra bytes. Note that we support block cipher sizes + * up to 16 bytes (AES) and HMAC output sizes up to 48 bytes (SHA-384). + * + * With TLS-1.0 and CBC mode, we apply a 1/n-1 split, for a maximum + * overhead of: + * 5 bytes for the first record header + * 32 bytes for the first record payload (AES-CBC + HMAC/SHA-1) + * 5 bytes for the second record header + * 20 bytes for the MAC (HMAC/SHA-1) + * 16 bytes for the padding (AES) + * -1 byte to account for the payload byte in the first record + * so a total of 77 extra bytes at most, less than the 85 bytes above. + * Note that with TLS-1.0, the MAC is HMAC with either MD5 or SHA-1, but + * no other hash function. + * + * The implementation does not try to send larger records when the current + * encryption mode has less overhead. + * + * Maximum input record overhead is: + * 5 bytes for the record header + * 16 bytes for the explicit IV (TLS-1.1+) + * 48 bytes for the MAC (HMAC/SHA-384) + * 256 bytes for the padding + * so a total of 325 extra bytes. + * + * When receiving the next record header, it is written into the buffer + * bytes 0 to 4 (inclusive). Record data is always written into buf[] + * starting at offset 5. When encryption is active, the plaintext data + * may start at a larger offset (e.g. because of an explicit IV). + */ + +#define MAX_OUT_OVERHEAD 85 +#define MAX_IN_OVERHEAD 325 + +/* see inner.h */ +void +br_ssl_engine_fail(br_ssl_engine_context *rc, int err) +{ + if (rc->iomode != BR_IO_FAILED) { + rc->iomode = BR_IO_FAILED; + rc->err = err; + } +} + +/* + * Adjust registers for a new incoming record. + */ +static void +make_ready_in(br_ssl_engine_context *rc) +{ + rc->ixa = rc->ixb = 0; + rc->ixc = 5; + if (rc->iomode == BR_IO_IN) { + rc->iomode = BR_IO_INOUT; + } +} + +/* + * Adjust registers for a new outgoing record. + */ +static void +make_ready_out(br_ssl_engine_context *rc) +{ + size_t a, b; + + a = 5; + b = rc->obuf_len - a; + rc->out.vtable->max_plaintext(&rc->out.vtable, &a, &b); + if ((b - a) > rc->max_frag_len) { + b = a + rc->max_frag_len; + } + rc->oxa = a; + rc->oxb = b; + rc->oxc = a; + if (rc->iomode == BR_IO_OUT) { + rc->iomode = BR_IO_INOUT; + } +} + +/* see inner.h */ +void +br_ssl_engine_new_max_frag_len(br_ssl_engine_context *rc, unsigned max_frag_len) +{ + size_t nxb; + + rc->max_frag_len = max_frag_len; + nxb = rc->oxc + max_frag_len; + if (rc->oxa < rc->oxb && rc->oxb > nxb && rc->oxa < nxb) { + rc->oxb = nxb; + } +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_buffer(br_ssl_engine_context *rc, + void *buf, size_t buf_len, int bidi) +{ + if (buf == NULL) { + br_ssl_engine_set_buffers_bidi(rc, NULL, 0, NULL, 0); + } else { + /* + * In bidirectional mode, we want to maximise input + * buffer size, since we support arbitrary fragmentation + * when sending, but the peer will not necessarily + * comply to any low fragment length (in particular if + * we are the server, because the maximum fragment + * length extension is under client control). + * + * We keep a minimum size of 512 bytes for the plaintext + * of our outgoing records. + * + * br_ssl_engine_set_buffers_bidi() will compute the maximum + * fragment length for outgoing records by using the minimum + * of allocated spaces for both input and output records, + * rounded down to a standard length. + */ + if (bidi) { + size_t w; + + if (buf_len < (512 + MAX_IN_OVERHEAD + + 512 + MAX_OUT_OVERHEAD)) + { + rc->iomode = BR_IO_FAILED; + rc->err = BR_ERR_BAD_PARAM; + return; + } else if (buf_len < (16384 + MAX_IN_OVERHEAD + + 512 + MAX_OUT_OVERHEAD)) + { + w = 512 + MAX_OUT_OVERHEAD; + } else { + w = buf_len - (16384 + MAX_IN_OVERHEAD); + } + br_ssl_engine_set_buffers_bidi(rc, + buf, buf_len - w, + (unsigned char *)buf + w, w); + } else { + br_ssl_engine_set_buffers_bidi(rc, + buf, buf_len, NULL, 0); + } + } +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *rc, + void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len) +{ + rc->iomode = BR_IO_INOUT; + rc->incrypt = 0; + rc->err = BR_ERR_OK; + rc->version_in = 0; + rc->record_type_in = 0; + rc->version_out = 0; + rc->record_type_out = 0; + if (ibuf == NULL) { + if (rc->ibuf == NULL) { + br_ssl_engine_fail(rc, BR_ERR_BAD_PARAM); + } + } else { + unsigned u; + + rc->ibuf = ibuf; + rc->ibuf_len = ibuf_len; + if (obuf == NULL) { + obuf = ibuf; + obuf_len = ibuf_len; + } + rc->obuf = obuf; + rc->obuf_len = obuf_len; + + /* + * Compute the maximum fragment length, that fits for + * both incoming and outgoing records. This length will + * be used in fragment length negotiation, so we must + * honour it both ways. Regardless, larger incoming + * records will be accepted, as long as they fit in the + * actual buffer size. + */ + for (u = 14; u >= 9; u --) { + size_t flen; + + flen = (size_t)1 << u; + if (obuf_len >= flen + MAX_OUT_OVERHEAD + && ibuf_len >= flen + MAX_IN_OVERHEAD) + { + break; + } + } + if (u == 8) { + br_ssl_engine_fail(rc, BR_ERR_BAD_PARAM); + return; + } else if (u == 13) { + u = 12; + } + rc->max_frag_len = (size_t)1 << u; + rc->log_max_frag_len = u; + rc->peer_log_max_frag_len = 0; + } + rc->out.vtable = &br_sslrec_out_clear_vtable; + make_ready_in(rc); + make_ready_out(rc); +} + +/* + * Clear buffers in both directions. + */ +static void +engine_clearbuf(br_ssl_engine_context *rc) +{ + make_ready_in(rc); + make_ready_out(rc); +} + +/* + * Make sure the internal PRNG is initialised (but not necessarily + * seeded properly yet). + */ +static int +rng_init(br_ssl_engine_context *cc) +{ + const br_hash_class *h; + + if (cc->rng_init_done != 0) { + return 1; + } + + /* + * If using TLS-1.2, then SHA-256 or SHA-384 must be present (or + * both); we prefer SHA-256 which is faster for 32-bit systems. + * + * If using TLS-1.0 or 1.1 then SHA-1 must be present. + * + * Though HMAC_DRBG/SHA-1 is, as far as we know, as safe as + * these things can be, we still prefer the SHA-2 functions over + * SHA-1, if only for public relations (known theoretical + * weaknesses of SHA-1 with regards to collisions are mostly + * irrelevant here, but they still make people nervous). + */ + h = br_multihash_getimpl(&cc->mhash, br_sha256_ID); + if (!h) { + h = br_multihash_getimpl(&cc->mhash, br_sha384_ID); + if (!h) { + h = br_multihash_getimpl(&cc->mhash, + br_sha1_ID); + if (!h) { + br_ssl_engine_fail(cc, BR_ERR_BAD_STATE); + return 0; + } + } + } + br_hmac_drbg_init(&cc->rng, h, NULL, 0); + cc->rng_init_done = 1; + return 1; +} + +/* see inner.h */ +int +br_ssl_engine_init_rand(br_ssl_engine_context *cc) +{ + if (!rng_init(cc)) { + return 0; + } + + /* + * We always try OS/hardware seeding once. If it works, then + * we assume proper seeding. If not, then external entropy must + * have been injected; otherwise, we report an error. + */ + if (!cc->rng_os_rand_done) { + br_prng_seeder sd; + + sd = br_prng_seeder_system(NULL); + if (sd != 0 && sd(&cc->rng.vtable)) { + cc->rng_init_done = 2; + } + cc->rng_os_rand_done = 1; + } + if (cc->rng_init_done < 2) { + br_ssl_engine_fail(cc, BR_ERR_NO_RANDOM); + return 0; + } + return 1; +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_inject_entropy(br_ssl_engine_context *cc, + const void *data, size_t len) +{ + /* + * Externally provided entropy is assumed to be "good enough" + * (we cannot really test its quality) so if the RNG structure + * could be initialised at all, then we marked the RNG as + * "properly seeded". + */ + if (!rng_init(cc)) { + return; + } + br_hmac_drbg_update(&cc->rng, data, len); + cc->rng_init_done = 2; +} + +/* + * We define a few internal functions that implement the low-level engine + * API for I/O; the external API (br_ssl_engine_sendapp_buf() and similar + * functions) is built upon these function, with special processing for + * records which are not of type "application data". + * + * recvrec_buf, recvrec_ack receives bytes from transport medium + * sendrec_buf, sendrec_ack send bytes to transport medium + * recvpld_buf, recvpld_ack receives payload data from engine + * sendpld_buf, sendpld_ack send payload data to engine + */ + +static unsigned char * +recvrec_buf(const br_ssl_engine_context *rc, size_t *len) +{ + if (rc->shutdown_recv) { + *len = 0; + return NULL; + } + + /* + * Bytes from the transport can be injected only if the mode is + * compatible (in or in/out), and ixa == ixb; ixc then contains + * the number of bytes that are still expected (but it may + * exceed our buffer size). + * + * We cannot get "stuck" here (buffer is full, but still more + * data is expected) because oversized records are detected when + * their header is processed. + */ + switch (rc->iomode) { + case BR_IO_IN: + case BR_IO_INOUT: + if (rc->ixa == rc->ixb) { + size_t z; + + z = rc->ixc; + if (z > rc->ibuf_len - rc->ixa) { + z = rc->ibuf_len - rc->ixa; + } + *len = z; + return rc->ibuf + rc->ixa; + } + break; + } + *len = 0; + return NULL; +} + +static void +recvrec_ack(br_ssl_engine_context *rc, size_t len) +{ + unsigned char *pbuf; + size_t pbuf_len; + + /* + * Adjust state if necessary (for a shared input/output buffer): + * we got some incoming bytes, so we cannot (temporarily) handle + * outgoing data. + */ + if (rc->iomode == BR_IO_INOUT && rc->ibuf == rc->obuf) { + rc->iomode = BR_IO_IN; + } + + /* + * Adjust data pointers. + */ + rc->ixb = (rc->ixa += len); + rc->ixc -= len; + + /* + * If we are receiving a header and did not fully obtained it + * yet, then just wait for the next bytes. + */ + if (rc->ixa < 5) { + return; + } + + /* + * If we just obtained a full header, process it. + */ + if (rc->ixa == 5) { + unsigned version; + unsigned rlen; + + /* + * Get record type and version. We support only versions + * 3.x (if the version major number does not match, then + * we suppose that the record format is too alien for us + * to process it). + * + * Note: right now, we reject clients that try to send + * a ClientHello in a format compatible with SSL-2.0. It + * is unclear whether this will ever be supported; and + * if we want to support it, then this might be done in + * in the server-specific code, not here. + */ + rc->record_type_in = rc->ibuf[0]; + version = br_dec16be(rc->ibuf + 1); + if ((version >> 8) != 3) { + br_ssl_engine_fail(rc, BR_ERR_UNSUPPORTED_VERSION); + return; + } + + /* + * We ensure that successive records have the same + * version. The handshake code must check and adjust the + * variables when necessary to accommodate the protocol + * negotiation details. + */ + if (rc->version_in != 0 && rc->version_in != version) { + br_ssl_engine_fail(rc, BR_ERR_BAD_VERSION); + return; + } + rc->version_in = version; + + /* + * Decode record length. We must check that the length + * is valid (relatively to the current encryption mode) + * and also (if encryption is active) that the record + * will fit in our buffer. + * + * When no encryption is active, we can process records + * by chunks, and thus accept any record up to the + * maximum allowed plaintext length (16384 bytes). + */ + rlen = br_dec16be(rc->ibuf + 3); + if (rc->incrypt) { + if (!rc->in.vtable->check_length( + &rc->in.vtable, rlen)) + { + br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH); + return; + } + if (rlen > (rc->ibuf_len - 5)) { + br_ssl_engine_fail(rc, BR_ERR_TOO_LARGE); + return; + } + } else { + if (rlen > 16384) { + br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH); + return; + } + } + + /* + * If the record is completely empty then we must switch + * to a new record. Note that, in that case, we + * completely ignore the record type, which is fitting + * since we received no actual data of that type. + * + * A completely empty record is technically allowed as + * long as encryption/MAC is not active, i.e. before + * completion of the first handshake. It it still weird; + * it might conceptually be useful as a heartbeat or + * keep-alive mechanism while some lengthy operation is + * going on, e.g. interaction with a human user. + */ + if (rlen == 0) { + make_ready_in(rc); + } else { + rc->ixa = rc->ixb = 5; + rc->ixc = rlen; + } + return; + } + + /* + * If there is no active encryption, then the data can be read + * right away. Note that we do not receive bytes from the + * transport medium when we still have payload bytes to be + * acknowledged. + */ + if (!rc->incrypt) { + rc->ixa = 5; + return; + } + + /* + * Since encryption is active, we must wait for a full record + * before processing it. + */ + if (rc->ixc != 0) { + return; + } + + /* + * We got the full record. Decrypt it. + */ + pbuf_len = rc->ixa - 5; + pbuf = rc->in.vtable->decrypt(&rc->in.vtable, + rc->record_type_in, rc->version_in, rc->ibuf + 5, &pbuf_len); + if (pbuf == 0) { + br_ssl_engine_fail(rc, BR_ERR_BAD_MAC); + return; + } + rc->ixa = (size_t)(pbuf - rc->ibuf); + rc->ixb = rc->ixa + pbuf_len; + + /* + * Decryption may have yielded an empty record, in which case + * we get back to "ready" state immediately. + */ + if (rc->ixa == rc->ixb) { + make_ready_in(rc); + } +} + +/* see inner.h */ +int +br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc) +{ + switch (rc->iomode) { + case BR_IO_IN: + case BR_IO_INOUT: + return rc->ixc == 0 || rc->ixa < 5; + default: + return 1; + } +} + +static unsigned char * +recvpld_buf(const br_ssl_engine_context *rc, size_t *len) +{ + /* + * There is payload data to be read only if the mode is + * compatible, and ixa != ixb. + */ + switch (rc->iomode) { + case BR_IO_IN: + case BR_IO_INOUT: + *len = rc->ixb - rc->ixa; + return (*len == 0) ? NULL : (rc->ibuf + rc->ixa); + default: + *len = 0; + return NULL; + } +} + +static void +recvpld_ack(br_ssl_engine_context *rc, size_t len) +{ + rc->ixa += len; + + /* + * If we read all the available data, then we either expect + * the remainder of the current record (if the current record + * was not finished; this may happen when encryption is not + * active), or go to "ready" state. + */ + if (rc->ixa == rc->ixb) { + if (rc->ixc == 0) { + make_ready_in(rc); + } else { + rc->ixa = rc->ixb = 5; + } + } +} + +static unsigned char * +sendpld_buf(const br_ssl_engine_context *rc, size_t *len) +{ + /* + * Payload data can be injected only if the current mode is + * compatible, and oxa != oxb. + */ + switch (rc->iomode) { + case BR_IO_OUT: + case BR_IO_INOUT: + *len = rc->oxb - rc->oxa; + return (*len == 0) ? NULL : (rc->obuf + rc->oxa); + default: + *len = 0; + return NULL; + } +} + +/* + * If some payload bytes have been accumulated, then wrap them into + * an outgoing record. Otherwise, this function does nothing, unless + * 'force' is non-zero, in which case an empty record is assembled. + * + * The caller must take care not to invoke this function if the engine + * is not currently ready to receive payload bytes to send. + */ +static void +sendpld_flush(br_ssl_engine_context *rc, int force) +{ + size_t xlen; + unsigned char *buf; + + if (rc->oxa == rc->oxb) { + return; + } + xlen = rc->oxa - rc->oxc; + if (xlen == 0 && !force) { + return; + } + buf = rc->out.vtable->encrypt(&rc->out.vtable, + rc->record_type_out, rc->version_out, + rc->obuf + rc->oxc, &xlen); + rc->oxb = rc->oxa = (size_t)(buf - rc->obuf); + rc->oxc = rc->oxa + xlen; +} + +static void +sendpld_ack(br_ssl_engine_context *rc, size_t len) +{ + /* + * If using a shared buffer, then we may have to modify the + * current mode. + */ + if (rc->iomode == BR_IO_INOUT && rc->ibuf == rc->obuf) { + rc->iomode = BR_IO_OUT; + } + rc->oxa += len; + if (rc->oxa >= rc->oxb) { + /* + * Set oxb to one more than oxa so that sendpld_flush() + * does not mistakingly believe that a record is + * already prepared and being sent. + */ + rc->oxb = rc->oxa + 1; + sendpld_flush(rc, 0); + } +} + +static unsigned char * +sendrec_buf(const br_ssl_engine_context *rc, size_t *len) +{ + /* + * When still gathering payload bytes, oxc points to the start + * of the record data, so oxc <= oxa. However, when a full + * record has been completed, oxc points to the end of the record, + * so oxc > oxa. + */ + switch (rc->iomode) { + case BR_IO_OUT: + case BR_IO_INOUT: + if (rc->oxc > rc->oxa) { + *len = rc->oxc - rc->oxa; + return rc->obuf + rc->oxa; + } + break; + } + *len = 0; + return NULL; +} + +static void +sendrec_ack(br_ssl_engine_context *rc, size_t len) +{ + rc->oxb = (rc->oxa += len); + if (rc->oxa == rc->oxc) { + make_ready_out(rc); + } +} + +/* + * Test whether there is some buffered outgoing record that still must + * sent. + */ +static __inline int +has_rec_tosend(const br_ssl_engine_context *rc) +{ + return rc->oxa == rc->oxb && rc->oxa != rc->oxc; +} + +/* + * The "no encryption" mode has no overhead. It limits the payload size + * to the maximum size allowed by the standard (16384 bytes); the caller + * is responsible for possibly enforcing a smaller fragment length. + */ +static void +clear_max_plaintext(const br_sslrec_out_clear_context *cc, + size_t *start, size_t *end) +{ + size_t len; + + (void)cc; + len = *end - *start; + if (len > 16384) { + *end = *start + 16384; + } +} + +/* + * In "no encryption" mode, encryption is trivial (a no-operation) so + * we just have to encode the header. + */ +static unsigned char * +clear_encrypt(br_sslrec_out_clear_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + unsigned char *buf; + + (void)cc; + buf = (unsigned char *)data - 5; + buf[0] = record_type; + br_enc16be(buf + 1, version); + br_enc16be(buf + 3, *data_len); + *data_len += 5; + return buf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_out_class br_sslrec_out_clear_vtable = { + sizeof(br_sslrec_out_clear_context), + (void (*)(const br_sslrec_out_class *const *, size_t *, size_t *)) + &clear_max_plaintext, + (unsigned char *(*)(const br_sslrec_out_class **, + int, unsigned, void *, size_t *)) + &clear_encrypt +}; + +/* ==================================================================== */ +/* + * In this part of the file, we handle the various record types, and + * communications with the handshake processor. + */ + +/* + * IMPLEMENTATION NOTES + * ==================== + * + * The handshake processor is written in T0 and runs as a coroutine. + * It receives the contents of all records except application data, and + * is responsible for producing the contents of all records except + * application data. + * + * A state flag is maintained, which specifies whether application data + * is acceptable or not. When it is set: + * + * -- Application data can be injected as payload data (provided that + * the output buffer is ready for that). + * + * -- Incoming application data records are accepted, and yield data + * that the caller may retrieve. + * + * When the flag is cleared, application data is not accepted from the + * application, and incoming application data records trigger an error. + * + * + * Records of type handshake, alert or change-cipher-spec are handled + * by the handshake processor. The handshake processor is written in T0 + * and runs as a coroutine; it gets invoked whenever one of the following + * situations is reached: + * + * -- An incoming record has type handshake, alert or change-cipher-spec, + * and yields data that can be read (zero-length records are thus + * ignored). + * + * -- An outgoing record has just finished being sent, and the "application + * data" flag is cleared. + * + * -- The caller wishes to perform a close (call to br_ssl_engine_close()). + * + * -- The caller wishes to perform a renegotiation (call to + * br_ssl_engine_renegotiate()). + * + * Whenever the handshake processor is entered, access to the payload + * buffers is provided, along with some information about explicit + * closures or renegotiations. + */ + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_suites(br_ssl_engine_context *cc, + const uint16_t *suites, size_t suites_num) +{ + if ((suites_num * sizeof *suites) > sizeof cc->suites_buf) { + br_ssl_engine_fail(cc, BR_ERR_BAD_PARAM); + return; + } + memcpy(cc->suites_buf, suites, suites_num * sizeof *suites); + cc->suites_num = suites_num; +} + +/* + * Give control to handshake processor. 'action' is 1 for a close, + * 2 for a renegotiation, or 0 for a jump due to I/O completion. + */ +static void +jump_handshake(br_ssl_engine_context *cc, int action) +{ + /* + * We use a loop because the handshake processor actions may + * allow for more actions; namely, if the processor reads all + * input data, then it may allow for output data to be produced, + * in case of a shared in/out buffer. + */ + for (;;) { + size_t hlen_in, hlen_out; + + /* + * Get input buffer. We do not want to provide + * application data to the handshake processor (we could + * get called with an explicit close or renegotiation + * while there is application data ready to be read). + */ + cc->hbuf_in = recvpld_buf(cc, &hlen_in); + if (cc->hbuf_in != NULL + && cc->record_type_in == BR_SSL_APPLICATION_DATA) + { + hlen_in = 0; + } + + /* + * Get output buffer. The handshake processor never + * leaves an unfinished outgoing record, so if there is + * buffered output, then it MUST be some application + * data, so the processor cannot write to it. + */ + cc->saved_hbuf_out = cc->hbuf_out = sendpld_buf(cc, &hlen_out); + if (cc->hbuf_out != NULL && br_ssl_engine_has_pld_to_send(cc)) { + hlen_out = 0; + } + + /* + * Note: hlen_in and hlen_out can be both non-zero only if + * the input and output buffers are disjoint. Thus, we can + * offer both buffers to the handshake code. + */ + + cc->hlen_in = hlen_in; + cc->hlen_out = hlen_out; + cc->action = action; + cc->hsrun(&cc->cpu); + if (br_ssl_engine_closed(cc)) { + return; + } + if (cc->hbuf_out != cc->saved_hbuf_out) { + sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out); + } + if (hlen_in != cc->hlen_in) { + recvpld_ack(cc, hlen_in - cc->hlen_in); + if (cc->hlen_in == 0) { + /* + * We read all data bytes, which may have + * released the output buffer in case it + * is shared with the input buffer, and + * the handshake code might be waiting for + * that. + */ + action = 0; + continue; + } + } + break; + } +} + +/* see inner.h */ +void +br_ssl_engine_flush_record(br_ssl_engine_context *cc) +{ + if (cc->hbuf_out != cc->saved_hbuf_out) { + sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out); + } + if (br_ssl_engine_has_pld_to_send(cc)) { + sendpld_flush(cc, 0); + } + cc->saved_hbuf_out = cc->hbuf_out = sendpld_buf(cc, &cc->hlen_out); +} + +/* see bearssl_ssl.h */ +unsigned char * +br_ssl_engine_sendapp_buf(const br_ssl_engine_context *cc, size_t *len) +{ + if (!(cc->application_data & 1)) { + *len = 0; + return NULL; + } + return sendpld_buf(cc, len); +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len) +{ + sendpld_ack(cc, len); +} + +/* see bearssl_ssl.h */ +unsigned char * +br_ssl_engine_recvapp_buf(const br_ssl_engine_context *cc, size_t *len) +{ + if (!(cc->application_data & 1) + || cc->record_type_in != BR_SSL_APPLICATION_DATA) + { + *len = 0; + return NULL; + } + return recvpld_buf(cc, len); +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len) +{ + recvpld_ack(cc, len); +} + +/* see bearssl_ssl.h */ +unsigned char * +br_ssl_engine_sendrec_buf(const br_ssl_engine_context *cc, size_t *len) +{ + return sendrec_buf(cc, len); +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len) +{ + sendrec_ack(cc, len); + if (len != 0 && !has_rec_tosend(cc) + && (cc->record_type_out != BR_SSL_APPLICATION_DATA + || (cc->application_data & 1) == 0)) + { + jump_handshake(cc, 0); + } +} + +/* see bearssl_ssl.h */ +unsigned char * +br_ssl_engine_recvrec_buf(const br_ssl_engine_context *cc, size_t *len) +{ + return recvrec_buf(cc, len); +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len) +{ + unsigned char *buf; + + recvrec_ack(cc, len); + if (br_ssl_engine_closed(cc)) { + return; + } + + /* + * We just received some bytes from the peer. This may have + * yielded some payload bytes, in which case we must process + * them according to the record type. + */ + buf = recvpld_buf(cc, &len); + if (buf != NULL) { + switch (cc->record_type_in) { + case BR_SSL_CHANGE_CIPHER_SPEC: + case BR_SSL_ALERT: + case BR_SSL_HANDSHAKE: + jump_handshake(cc, 0); + break; + case BR_SSL_APPLICATION_DATA: + if (cc->application_data == 1) { + break; + } + + /* + * If we are currently closing, and waiting for + * a close_notify from the peer, then incoming + * application data should be discarded. + */ + if (cc->application_data == 2) { + recvpld_ack(cc, len); + break; + } + + /* Fall through */ + default: + br_ssl_engine_fail(cc, BR_ERR_UNEXPECTED); + break; + } + } +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_close(br_ssl_engine_context *cc) +{ + if (!br_ssl_engine_closed(cc)) { + /* + * If we are not already closed, then we need to + * initiate the closure. Once closing, any incoming + * application data is discarded; we should also discard + * application data which is already there but has not + * been acknowledged by the application yet (this mimics + * usual semantics on BSD sockets: you cannot read() + * once you called close(), even if there was some + * unread data already buffered). + */ + size_t len; + + if (br_ssl_engine_recvapp_buf(cc, &len) != NULL && len != 0) { + br_ssl_engine_recvapp_ack(cc, len); + } + jump_handshake(cc, 1); + } +} + +/* see bearssl_ssl.h */ +int +br_ssl_engine_renegotiate(br_ssl_engine_context *cc) +{ + size_t len; + + if (br_ssl_engine_closed(cc) || cc->reneg == 1 + || (cc->flags & BR_OPT_NO_RENEGOTIATION) != 0 + || br_ssl_engine_recvapp_buf(cc, &len) != NULL) + { + return 0; + } + jump_handshake(cc, 2); + return 1; +} + +/* see bearssl.h */ +unsigned +br_ssl_engine_current_state(const br_ssl_engine_context *cc) +{ + unsigned s; + size_t len; + + if (br_ssl_engine_closed(cc)) { + return BR_SSL_CLOSED; + } + + s = 0; + if (br_ssl_engine_sendrec_buf(cc, &len) != NULL) { + s |= BR_SSL_SENDREC; + } + if (br_ssl_engine_recvrec_buf(cc, &len) != NULL) { + s |= BR_SSL_RECVREC; + } + if (br_ssl_engine_sendapp_buf(cc, &len) != NULL) { + s |= BR_SSL_SENDAPP; + } + if (br_ssl_engine_recvapp_buf(cc, &len) != NULL) { + s |= BR_SSL_RECVAPP; + } + return s; +} + +/* see bearssl_ssl.h */ +void +br_ssl_engine_flush(br_ssl_engine_context *cc, int force) +{ + if (!br_ssl_engine_closed(cc) && (cc->application_data & 1) != 0) { + sendpld_flush(cc, force); + } +} + +/* see inner.h */ +void +br_ssl_engine_hs_reset(br_ssl_engine_context *cc, + void (*hsinit)(void *), void (*hsrun)(void *)) +{ + engine_clearbuf(cc); + cc->cpu.dp = cc->dp_stack; + cc->cpu.rp = cc->rp_stack; + hsinit(&cc->cpu); + cc->hsrun = hsrun; + cc->shutdown_recv = 0; + cc->application_data = 0; + cc->alert = 0; + jump_handshake(cc, 0); +} + +/* see inner.h */ +br_tls_prf_impl +br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id) +{ + if (cc->session.version >= BR_TLS12) { + if (prf_id == br_sha384_ID) { + return cc->prf_sha384; + } else { + return cc->prf_sha256; + } + } else { + return cc->prf10; + } +} + +/* see inner.h */ +void +br_ssl_engine_compute_master(br_ssl_engine_context *cc, + int prf_id, const void *pms, size_t pms_len) +{ + br_tls_prf_impl iprf; + br_tls_prf_seed_chunk seed[2] = { + { cc->client_random, sizeof cc->client_random }, + { cc->server_random, sizeof cc->server_random } + }; + + iprf = br_ssl_engine_get_PRF(cc, prf_id); + iprf(cc->session.master_secret, sizeof cc->session.master_secret, + pms, pms_len, "master secret", 2, seed); +} + +/* + * Compute key block. + */ +static void +compute_key_block(br_ssl_engine_context *cc, int prf_id, + size_t half_len, unsigned char *kb) +{ + br_tls_prf_impl iprf; + br_tls_prf_seed_chunk seed[2] = { + { cc->server_random, sizeof cc->server_random }, + { cc->client_random, sizeof cc->client_random } + }; + + iprf = br_ssl_engine_get_PRF(cc, prf_id); + iprf(kb, half_len << 1, + cc->session.master_secret, sizeof cc->session.master_secret, + "key expansion", 2, seed); +} + +/* see inner.h */ +void +br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc, + int is_client, int prf_id, int mac_id, + const br_block_cbcdec_class *bc_impl, size_t cipher_key_len) +{ + unsigned char kb[192]; + unsigned char *cipher_key, *mac_key, *iv; + const br_hash_class *imh; + size_t mac_key_len, mac_out_len, iv_len; + + imh = br_ssl_engine_get_hash(cc, mac_id); + mac_out_len = (imh->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; + mac_key_len = mac_out_len; + + /* + * TLS 1.1+ uses per-record explicit IV, so no IV to generate here. + */ + if (cc->session.version >= BR_TLS11) { + iv_len = 0; + } else { + iv_len = bc_impl->block_size; + } + compute_key_block(cc, prf_id, + mac_key_len + cipher_key_len + iv_len, kb); + if (is_client) { + mac_key = &kb[mac_key_len]; + cipher_key = &kb[(mac_key_len << 1) + cipher_key_len]; + iv = &kb[((mac_key_len + cipher_key_len) << 1) + iv_len]; + } else { + mac_key = &kb[0]; + cipher_key = &kb[mac_key_len << 1]; + iv = &kb[(mac_key_len + cipher_key_len) << 1]; + } + if (iv_len == 0) { + iv = NULL; + } + cc->icbc_in->init(&cc->in.cbc.vtable, + bc_impl, cipher_key, cipher_key_len, + imh, mac_key, mac_key_len, mac_out_len, iv); + cc->incrypt = 1; +} + +/* see inner.h */ +void +br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc, + int is_client, int prf_id, int mac_id, + const br_block_cbcenc_class *bc_impl, size_t cipher_key_len) +{ + unsigned char kb[192]; + unsigned char *cipher_key, *mac_key, *iv; + const br_hash_class *imh; + size_t mac_key_len, mac_out_len, iv_len; + + imh = br_ssl_engine_get_hash(cc, mac_id); + mac_out_len = (imh->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; + mac_key_len = mac_out_len; + + /* + * TLS 1.1+ uses per-record explicit IV, so no IV to generate here. + */ + if (cc->session.version >= BR_TLS11) { + iv_len = 0; + } else { + iv_len = bc_impl->block_size; + } + compute_key_block(cc, prf_id, + mac_key_len + cipher_key_len + iv_len, kb); + if (is_client) { + mac_key = &kb[0]; + cipher_key = &kb[mac_key_len << 1]; + iv = &kb[(mac_key_len + cipher_key_len) << 1]; + } else { + mac_key = &kb[mac_key_len]; + cipher_key = &kb[(mac_key_len << 1) + cipher_key_len]; + iv = &kb[((mac_key_len + cipher_key_len) << 1) + iv_len]; + } + if (iv_len == 0) { + iv = NULL; + } + cc->icbc_out->init(&cc->out.cbc.vtable, + bc_impl, cipher_key, cipher_key_len, + imh, mac_key, mac_key_len, mac_out_len, iv); +} + +/* see inner.h */ +void +br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc, + int is_client, int prf_id, + const br_block_ctr_class *bc_impl, size_t cipher_key_len) +{ + unsigned char kb[72]; + unsigned char *cipher_key, *iv; + + compute_key_block(cc, prf_id, cipher_key_len + 4, kb); + if (is_client) { + cipher_key = &kb[cipher_key_len]; + iv = &kb[(cipher_key_len << 1) + 4]; + } else { + cipher_key = &kb[0]; + iv = &kb[cipher_key_len << 1]; + } + cc->igcm_in->init(&cc->in.gcm.vtable.in, + bc_impl, cipher_key, cipher_key_len, cc->ighash, iv); + cc->incrypt = 1; +} + +/* see inner.h */ +void +br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc, + int is_client, int prf_id, + const br_block_ctr_class *bc_impl, size_t cipher_key_len) +{ + unsigned char kb[72]; + unsigned char *cipher_key, *iv; + + compute_key_block(cc, prf_id, cipher_key_len + 4, kb); + if (is_client) { + cipher_key = &kb[0]; + iv = &kb[cipher_key_len << 1]; + } else { + cipher_key = &kb[cipher_key_len]; + iv = &kb[(cipher_key_len << 1) + 4]; + } + cc->igcm_out->init(&cc->out.gcm.vtable.out, + bc_impl, cipher_key, cipher_key_len, cc->ighash, iv); +} + +/* see inner.h */ +void +br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc, + int is_client, int prf_id) +{ + unsigned char kb[88]; + unsigned char *cipher_key, *iv; + + compute_key_block(cc, prf_id, 44, kb); + if (is_client) { + cipher_key = &kb[32]; + iv = &kb[76]; + } else { + cipher_key = &kb[0]; + iv = &kb[64]; + } + cc->ichapol_in->init(&cc->in.chapol.vtable.in, + cc->ichacha, cc->ipoly, cipher_key, iv); + cc->incrypt = 1; +} + +/* see inner.h */ +void +br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc, + int is_client, int prf_id) +{ + unsigned char kb[88]; + unsigned char *cipher_key, *iv; + + compute_key_block(cc, prf_id, 44, kb); + if (is_client) { + cipher_key = &kb[0]; + iv = &kb[64]; + } else { + cipher_key = &kb[32]; + iv = &kb[76]; + } + cc->ichapol_out->init(&cc->out.chapol.vtable.out, + cc->ichacha, cc->ipoly, cipher_key, iv); +} + +/* see inner.h */ +void +br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc, + int is_client, int prf_id, + const br_block_ctrcbc_class *bc_impl, + size_t cipher_key_len, size_t tag_len) +{ + unsigned char kb[72]; + unsigned char *cipher_key, *iv; + + compute_key_block(cc, prf_id, cipher_key_len + 4, kb); + if (is_client) { + cipher_key = &kb[cipher_key_len]; + iv = &kb[(cipher_key_len << 1) + 4]; + } else { + cipher_key = &kb[0]; + iv = &kb[cipher_key_len << 1]; + } + cc->iccm_in->init(&cc->in.ccm.vtable.in, + bc_impl, cipher_key, cipher_key_len, iv, tag_len); + cc->incrypt = 1; +} + +/* see inner.h */ +void +br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc, + int is_client, int prf_id, + const br_block_ctrcbc_class *bc_impl, + size_t cipher_key_len, size_t tag_len) +{ + unsigned char kb[72]; + unsigned char *cipher_key, *iv; + + compute_key_block(cc, prf_id, cipher_key_len + 4, kb); + if (is_client) { + cipher_key = &kb[0]; + iv = &kb[cipher_key_len << 1]; + } else { + cipher_key = &kb[cipher_key_len]; + iv = &kb[(cipher_key_len << 1) + 4]; + } + cc->iccm_out->init(&cc->out.ccm.vtable.out, + bc_impl, cipher_key, cipher_key_len, iv, tag_len); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aescbc.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aescbc.c new file mode 100644 index 0000000..8c5cdb5 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aescbc.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc) +{ +#if BR_AES_X86NI || BR_POWER8 + const br_block_cbcenc_class *ienc; + const br_block_cbcdec_class *idec; +#endif + + br_ssl_engine_set_cbc(cc, + &br_sslrec_in_cbc_vtable, + &br_sslrec_out_cbc_vtable); +#if BR_AES_X86NI + ienc = br_aes_x86ni_cbcenc_get_vtable(); + idec = br_aes_x86ni_cbcdec_get_vtable(); + if (ienc != NULL && idec != NULL) { + br_ssl_engine_set_aes_cbc(cc, ienc, idec); + return; + } +#endif +#if BR_POWER8 + ienc = br_aes_pwr8_cbcenc_get_vtable(); + idec = br_aes_pwr8_cbcdec_get_vtable(); + if (ienc != NULL && idec != NULL) { + br_ssl_engine_set_aes_cbc(cc, ienc, idec); + return; + } +#endif +#if BR_64 + br_ssl_engine_set_aes_cbc(cc, + &br_aes_ct64_cbcenc_vtable, + &br_aes_ct64_cbcdec_vtable); +#else + br_ssl_engine_set_aes_cbc(cc, + &br_aes_ct_cbcenc_vtable, + &br_aes_ct_cbcdec_vtable); +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aesccm.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aesccm.c new file mode 100644 index 0000000..15c0a78 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aesccm.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc) +{ +#if BR_AES_X86NI || BR_POWER8 + const br_block_ctrcbc_class *ictrcbc; +#endif + + br_ssl_engine_set_ccm(cc, + &br_sslrec_in_ccm_vtable, + &br_sslrec_out_ccm_vtable); +#if BR_AES_X86NI + ictrcbc = br_aes_x86ni_ctrcbc_get_vtable(); + if (ictrcbc != NULL) { + br_ssl_engine_set_aes_ctrcbc(cc, ictrcbc); + } else { +#if BR_64 + br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable); +#else + br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable); +#endif + } +#elif BR_POWER8 + ictrcbc = br_aes_pwr8_ctrcbc_get_vtable(); + if (ictrcbc != NULL) { + br_ssl_engine_set_aes_ctrcbc(cc, ictrcbc); + } else { +#if BR_64 + br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable); +#else + br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable); +#endif + } +#else +#if BR_64 + br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable); +#else + br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable); +#endif +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aesgcm.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aesgcm.c new file mode 100644 index 0000000..c44a707 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_aesgcm.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc) +{ +#if BR_AES_X86NI || BR_POWER8 + const br_block_ctr_class *ictr; + br_ghash ighash; +#endif + + br_ssl_engine_set_gcm(cc, + &br_sslrec_in_gcm_vtable, + &br_sslrec_out_gcm_vtable); +#if BR_AES_X86NI + ictr = br_aes_x86ni_ctr_get_vtable(); + if (ictr != NULL) { + br_ssl_engine_set_aes_ctr(cc, ictr); + } else { +#if BR_64 + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable); +#else + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable); +#endif + } +#elif BR_POWER8 + ictr = br_aes_pwr8_ctr_get_vtable(); + if (ictr != NULL) { + br_ssl_engine_set_aes_ctr(cc, ictr); + } else { +#if BR_64 + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable); +#else + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable); +#endif + } +#else +#if BR_64 + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable); +#else + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable); +#endif +#endif +#if BR_AES_X86NI + ighash = br_ghash_pclmul_get(); + if (ighash != 0) { + br_ssl_engine_set_ghash(cc, ighash); + return; + } +#endif +#if BR_POWER8 + ighash = br_ghash_pwr8_get(); + if (ighash != 0) { + br_ssl_engine_set_ghash(cc, ighash); + return; + } +#endif +#if BR_LOMUL + br_ssl_engine_set_ghash(cc, &br_ghash_ctmul32); +#elif BR_64 + br_ssl_engine_set_ghash(cc, &br_ghash_ctmul64); +#else + br_ssl_engine_set_ghash(cc, &br_ghash_ctmul); +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_chapol.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_chapol.c new file mode 100644 index 0000000..47a0c98 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_chapol.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc) +{ +#if BR_INT128 || BR_UMUL128 + br_poly1305_run bp; +#endif +#if BR_SSE2 + br_chacha20_run bc; +#endif + + br_ssl_engine_set_chapol(cc, + &br_sslrec_in_chapol_vtable, + &br_sslrec_out_chapol_vtable); +#if BR_SSE2 + bc = br_chacha20_sse2_get(); + if (bc) { + br_ssl_engine_set_chacha20(cc, bc); + } else { +#endif + br_ssl_engine_set_chacha20(cc, &br_chacha20_ct_run); +#if BR_SSE2 + } +#endif +#if BR_INT128 || BR_UMUL128 + bp = br_poly1305_ctmulq_get(); + if (bp) { + br_ssl_engine_set_poly1305(cc, bp); + } else { +#endif +#if BR_LOMUL + br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul32_run); +#else + br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul_run); +#endif +#if BR_INT128 || BR_UMUL128 + } +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_descbc.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_descbc.c new file mode 100644 index 0000000..0253cb2 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_descbc.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc) +{ + br_ssl_engine_set_cbc(cc, + &br_sslrec_in_cbc_vtable, + &br_sslrec_out_cbc_vtable); + br_ssl_engine_set_des_cbc(cc, + &br_des_ct_cbcenc_vtable, + &br_des_ct_cbcdec_vtable); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_ec.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_ec.c new file mode 100644 index 0000000..0213ae6 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_ec.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_ec(br_ssl_engine_context *cc) +{ +#if BR_LOMUL + br_ssl_engine_set_ec(cc, &br_ec_all_m15); +#else + br_ssl_engine_set_ec(cc, &br_ec_all_m31); +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_ecdsa.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_ecdsa.c new file mode 100644 index 0000000..1304002 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_ecdsa.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc) +{ +#if BR_LOMUL + br_ssl_engine_set_ec(cc, &br_ec_all_m15); + br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i15_vrfy_asn1); +#else + br_ssl_engine_set_ec(cc, &br_ec_all_m31); + br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1); +#endif +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_rsavrfy.c b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_rsavrfy.c new file mode 100644 index 0000000..ad0628a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_engine_default_rsavrfy.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc) +{ + br_ssl_engine_set_rsavrfy(cc, br_rsa_pkcs1_vrfy_get_default()); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_hashes.c b/BearSSL-OG/libbearssl/src/ssl/ssl_hashes.c new file mode 100644 index 0000000..e10a980 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_hashes.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +int +br_ssl_choose_hash(unsigned bf) +{ + static const unsigned char pref[] = { + br_sha256_ID, br_sha384_ID, br_sha512_ID, + br_sha224_ID, br_sha1_ID + }; + size_t u; + + for (u = 0; u < sizeof pref; u ++) { + int x; + + x = pref[u]; + if ((bf >> x) & 1) { + return x; + } + } + return 0; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.c b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.c new file mode 100644 index 0000000..3fc96d0 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.c @@ -0,0 +1,1967 @@ +/* Automatically generated code; do not modify directly. */ + +#include +#include + +typedef struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; +} t0_context; + +static uint32_t +t0_parse7E_unsigned(const unsigned char **p) +{ + uint32_t x; + + x = 0; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + return x; + } + } +} + +static int32_t +t0_parse7E_signed(const unsigned char **p) +{ + int neg; + uint32_t x; + + neg = ((**p) >> 6) & 1; + x = (uint32_t)-neg; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + if (neg) { + return -(int32_t)~x - 1; + } else { + return (int32_t)x; + } + } + } +} + +#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) +#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) +#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) +#define T0_INT1(x) T0_FBYTE(x, 0) +#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) + +/* static const unsigned char t0_datablock[]; */ + + +void br_ssl_hs_client_init_main(void *t0ctx); + +void br_ssl_hs_client_run(void *t0ctx); + + + +#include +#include + +#include "inner.h" + +/* + * This macro evaluates to a pointer to the current engine context. + */ +#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu))) + + + + + +/* + * This macro evaluates to a pointer to the client context, under that + * specific name. It must be noted that since the engine context is the + * first field of the br_ssl_client_context structure ('eng'), then + * pointers values of both types are interchangeable, modulo an + * appropriate cast. This also means that "addresses" computed as offsets + * within the structure work for both kinds of context. + */ +#define CTX ((br_ssl_client_context *)ENG) + +/* + * Generate the pre-master secret for RSA key exchange, and encrypt it + * with the server's public key. Returned value is either the encrypted + * data length (in bytes), or -x on error, with 'x' being an error code. + * + * This code assumes that the public key has been already verified (it + * was properly obtained by the X.509 engine, and it has the right type, + * i.e. it is of type RSA and suitable for encryption). + */ +static int +make_pms_rsa(br_ssl_client_context *ctx, int prf_id) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + const unsigned char *n; + unsigned char *pms; + size_t nlen, u; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + + /* + * Compute actual RSA key length, in case there are leading zeros. + */ + n = pk->key.rsa.n; + nlen = pk->key.rsa.nlen; + while (nlen > 0 && *n == 0) { + n ++; + nlen --; + } + + /* + * We need at least 59 bytes (48 bytes for pre-master secret, and + * 11 bytes for the PKCS#1 type 2 padding). Note that the X.509 + * minimal engine normally blocks RSA keys shorter than 128 bytes, + * so this is mostly for public keys provided explicitly by the + * caller. + */ + if (nlen < 59) { + return -BR_ERR_X509_WEAK_PUBLIC_KEY; + } + if (nlen > sizeof ctx->eng.pad) { + return -BR_ERR_LIMIT_EXCEEDED; + } + + /* + * Make PMS. + */ + pms = ctx->eng.pad + nlen - 48; + br_enc16be(pms, ctx->eng.version_max); + br_hmac_drbg_generate(&ctx->eng.rng, pms + 2, 46); + br_ssl_engine_compute_master(&ctx->eng, prf_id, pms, 48); + + /* + * Apply PKCS#1 type 2 padding. + */ + ctx->eng.pad[0] = 0x00; + ctx->eng.pad[1] = 0x02; + ctx->eng.pad[nlen - 49] = 0x00; + br_hmac_drbg_generate(&ctx->eng.rng, ctx->eng.pad + 2, nlen - 51); + for (u = 2; u < nlen - 49; u ++) { + while (ctx->eng.pad[u] == 0) { + br_hmac_drbg_generate(&ctx->eng.rng, + &ctx->eng.pad[u], 1); + } + } + + /* + * Compute RSA encryption. + */ + if (!ctx->irsapub(ctx->eng.pad, nlen, &pk->key.rsa)) { + return -BR_ERR_LIMIT_EXCEEDED; + } + return (int)nlen; +} + +/* + * OID for hash functions in RSA signatures. + */ +static const unsigned char *HASH_OID[] = { + BR_HASH_OID_SHA1, + BR_HASH_OID_SHA224, + BR_HASH_OID_SHA256, + BR_HASH_OID_SHA384, + BR_HASH_OID_SHA512 +}; + +/* + * 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 +verify_SKE_sig(br_ssl_client_context *ctx, + int hash, int use_rsa, size_t sig_len) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + br_multihash_context mhc; + unsigned char hv[64], head[4]; + size_t hv_len; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + br_multihash_zero(&mhc); + br_multihash_copyimpl(&mhc, &ctx->eng.mhash); + br_multihash_init(&mhc); + br_multihash_update(&mhc, + ctx->eng.client_random, sizeof ctx->eng.client_random); + br_multihash_update(&mhc, + ctx->eng.server_random, sizeof ctx->eng.server_random); + head[0] = 3; + head[1] = 0; + head[2] = ctx->eng.ecdhe_curve; + head[3] = ctx->eng.ecdhe_point_len; + br_multihash_update(&mhc, head, sizeof head); + br_multihash_update(&mhc, + ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len); + if (hash) { + hv_len = br_multihash_out(&mhc, hash, hv); + if (hv_len == 0) { + return BR_ERR_INVALID_ALGORITHM; + } + } else { + if (!br_multihash_out(&mhc, br_md5_ID, hv) + || !br_multihash_out(&mhc, br_sha1_ID, hv + 16)) + { + return BR_ERR_INVALID_ALGORITHM; + } + hv_len = 36; + } + if (use_rsa) { + unsigned char tmp[64]; + const unsigned char *hash_oid; + + if (hash) { + hash_oid = HASH_OID[hash - 2]; + } else { + hash_oid = NULL; + } + 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->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec, + ctx->eng.pad, sig_len)) + { + return BR_ERR_BAD_SIGNATURE; + } + } + return 0; +} + +/* + * Perform client-side ECDH (or ECDHE). The point that should be sent to + * the server is written in the pad; returned value is either the point + * length (in bytes), or -x on error, with 'x' being an error code. + * + * The point _from_ the server is taken from ecdhe_point[] if 'ecdhe' + * is non-zero, or from the X.509 engine context if 'ecdhe' is zero + * (for static ECDH). + */ +static int +make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) +{ + int curve; + unsigned char key[66], point[133]; + const unsigned char *order, *point_src; + size_t glen, olen, point_len, xoff, xlen; + unsigned char mask; + + if (ecdhe) { + curve = ctx->eng.ecdhe_curve; + point_src = ctx->eng.ecdhe_point; + point_len = ctx->eng.ecdhe_point_len; + } else { + const br_x509_class **xc; + const br_x509_pkey *pk; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + curve = pk->key.ec.curve; + point_src = pk->key.ec.q; + point_len = pk->key.ec.qlen; + } + if ((ctx->eng.iec->supported_curves & ((uint32_t)1 << curve)) == 0) { + return -BR_ERR_INVALID_ALGORITHM; + } + + /* + * We need to generate our key, as a non-zero random value which + * is lower than the curve order, in a "large enough" range. We + * force top bit to 0 and bottom bit to 1, which guarantees that + * the value is in the proper range. + */ + order = ctx->eng.iec->order(curve, &olen); + mask = 0xFF; + while (mask >= order[0]) { + mask >>= 1; + } + br_hmac_drbg_generate(&ctx->eng.rng, key, olen); + key[0] &= mask; + key[olen - 1] |= 0x01; + + /* + * Compute the common ECDH point, whose X coordinate is the + * pre-master secret. + */ + ctx->eng.iec->generator(curve, &glen); + if (glen != point_len) { + return -BR_ERR_INVALID_ALGORITHM; + } + + memcpy(point, point_src, glen); + if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) { + return -BR_ERR_INVALID_ALGORITHM; + } + + /* + * The pre-master secret is the X coordinate. + */ + xoff = ctx->eng.iec->xoff(curve, &xlen); + br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen); + + ctx->eng.iec->mulgen(point, key, olen, curve); + memcpy(ctx->eng.pad, point, glen); + return (int)glen; +} + +/* + * Perform full static ECDH. This occurs only in the context of client + * authentication with certificates: the server uses an EC public key, + * the cipher suite is of type ECDH (not ECDHE), the server requested a + * client certificate and accepts static ECDH, the client has a + * certificate with an EC public key in the same curve, and accepts + * static ECDH as well. + * + * Returned value is 0 on success, -1 on error. + */ +static int +make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id) +{ + unsigned char point[133]; + size_t point_len; + const br_x509_class **xc; + const br_x509_pkey *pk; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + point_len = pk->key.ec.qlen; + if (point_len > sizeof point) { + return -1; + } + memcpy(point, pk->key.ec.q, point_len); + if (!(*ctx->client_auth_vtable)->do_keyx( + ctx->client_auth_vtable, point, &point_len)) + { + return -1; + } + br_ssl_engine_compute_master(&ctx->eng, + prf_id, point, point_len); + return 0; +} + +/* + * Compute the client-side signature. This is invoked only when a + * signature-based client authentication was selected. The computed + * signature is in the pad; its length (in bytes) is returned. On + * error, 0 is returned. + */ +static size_t +make_client_sign(br_ssl_client_context *ctx) +{ + size_t hv_len; + + /* + * Compute hash of handshake messages so far. This "cannot" fail + * because the list of supported hash functions provided to the + * client certificate handler was trimmed to include only the + * hash functions that the multi-hasher supports. + */ + if (ctx->hash_id) { + hv_len = br_multihash_out(&ctx->eng.mhash, + ctx->hash_id, ctx->eng.pad); + } else { + br_multihash_out(&ctx->eng.mhash, + br_md5_ID, ctx->eng.pad); + br_multihash_out(&ctx->eng.mhash, + br_sha1_ID, ctx->eng.pad + 16); + hv_len = 36; + } + return (*ctx->client_auth_vtable)->do_sign( + ctx->client_auth_vtable, ctx->hash_id, hv_len, + ctx->eng.pad, sizeof ctx->eng.pad); +} + + + +static const unsigned char t0_datablock[] = { + 0x00, 0x00, 0x0A, 0x00, 0x24, 0x00, 0x2F, 0x01, 0x24, 0x00, 0x35, 0x02, + 0x24, 0x00, 0x3C, 0x01, 0x44, 0x00, 0x3D, 0x02, 0x44, 0x00, 0x9C, 0x03, + 0x04, 0x00, 0x9D, 0x04, 0x05, 0xC0, 0x03, 0x40, 0x24, 0xC0, 0x04, 0x41, + 0x24, 0xC0, 0x05, 0x42, 0x24, 0xC0, 0x08, 0x20, 0x24, 0xC0, 0x09, 0x21, + 0x24, 0xC0, 0x0A, 0x22, 0x24, 0xC0, 0x0D, 0x30, 0x24, 0xC0, 0x0E, 0x31, + 0x24, 0xC0, 0x0F, 0x32, 0x24, 0xC0, 0x12, 0x10, 0x24, 0xC0, 0x13, 0x11, + 0x24, 0xC0, 0x14, 0x12, 0x24, 0xC0, 0x23, 0x21, 0x44, 0xC0, 0x24, 0x22, + 0x55, 0xC0, 0x25, 0x41, 0x44, 0xC0, 0x26, 0x42, 0x55, 0xC0, 0x27, 0x11, + 0x44, 0xC0, 0x28, 0x12, 0x55, 0xC0, 0x29, 0x31, 0x44, 0xC0, 0x2A, 0x32, + 0x55, 0xC0, 0x2B, 0x23, 0x04, 0xC0, 0x2C, 0x24, 0x05, 0xC0, 0x2D, 0x43, + 0x04, 0xC0, 0x2E, 0x44, 0x05, 0xC0, 0x2F, 0x13, 0x04, 0xC0, 0x30, 0x14, + 0x05, 0xC0, 0x31, 0x33, 0x04, 0xC0, 0x32, 0x34, 0x05, 0xC0, 0x9C, 0x06, + 0x04, 0xC0, 0x9D, 0x07, 0x04, 0xC0, 0xA0, 0x08, 0x04, 0xC0, 0xA1, 0x09, + 0x04, 0xC0, 0xAC, 0x26, 0x04, 0xC0, 0xAD, 0x27, 0x04, 0xC0, 0xAE, 0x28, + 0x04, 0xC0, 0xAF, 0x29, 0x04, 0xCC, 0xA8, 0x15, 0x04, 0xCC, 0xA9, 0x25, + 0x04, 0x00, 0x00 +}; + +static const unsigned char t0_codeblock[] = { + 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01, + 0x00, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x01, 0x08, + 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00, + 0x01, 0x02, 0x09, 0x00, 0x00, 0x26, 0x26, 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_CIPHER_SUITE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_COMPRESSION), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_HELLO_DONE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_SNI), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_BAD_VERSION), + 0x00, 0x00, 0x01, T0_INT1(BR_ERR_EXTRA_EXTENSION), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK), + 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_RESUME_MISMATCH), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_UNSUPPORTED_VERSION), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_client_context, auth_type)), 0x00, 0x00, + 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, client_random)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, close_received)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_curve)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hash_id)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hashes)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_client_context, min_clienthello_len)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, protocol_names_num)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, record_type_in)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, record_type_out)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, reneg)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, saved_finished)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, selected_protocol)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, server_name)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, server_random)), 0x00, 0x00, + 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id_len)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_ticket)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_ticket_len)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session_ticket_ok)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, shutdown_recv)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_buf)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_num)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, version)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_in)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)), + 0x00, 0x00, 0x09, 0x27, 0x5A, 0x06, 0x02, 0x6A, 0x29, 0x00, 0x00, 0x06, + 0x08, 0x2D, 0x0E, 0x05, 0x02, 0x73, 0x29, 0x04, 0x01, 0x3E, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x01, 0x03, 0x00, 0x9E, 0x27, 0x60, 0x46, 0xA2, 0x27, + 0x05, 0x04, 0x62, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0E, 0x06, 0x02, 0xA2, + 0x00, 0x60, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x6A, 0x29, 0x00, 0x00, 0x27, + 0x8B, 0x46, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x46, 0x7B, 0x2D, 0xB1, 0x1C, + 0x86, 0x01, 0x0C, 0x32, 0x00, 0x00, 0x27, 0x1F, 0x01, 0x08, 0x0B, 0x46, + 0x5E, 0x1F, 0x08, 0x00, 0x01, 0x03, 0x00, 0x79, 0x2F, 0x02, 0x00, 0x37, + 0x17, 0x01, 0x01, 0x0B, 0x79, 0x40, 0x2A, 0x1A, 0x37, 0x06, 0x07, 0x02, + 0x00, 0xD7, 0x03, 0x00, 0x04, 0x75, 0x01, 0x00, 0xCD, 0x02, 0x00, 0x27, + 0x1A, 0x17, 0x06, 0x02, 0x71, 0x29, 0xD7, 0x04, 0x76, 0x02, 0x01, 0x00, + 0x79, 0x40, 0x01, 0x16, 0x89, 0x40, 0x01, 0x00, 0x8C, 0x3E, 0x01, 0x00, + 0x93, 0x40, 0x35, 0xDD, 0x2A, 0xBC, 0x01, 0x00, 0x03, 0x00, 0x05, 0x34, + 0x93, 0x2F, 0x92, 0x2D, 0x01, 0x00, 0x0F, 0x17, 0x06, 0x28, 0x30, 0x37, + 0x06, 0x0C, 0xD6, 0x01, 0x07, 0x17, 0x27, 0x5C, 0x06, 0x03, 0x26, 0x04, + 0x75, 0x26, 0x88, 0x2F, 0x01, 0x14, 0x0E, 0x06, 0x06, 0x01, 0x7F, 0x03, + 0x00, 0x04, 0x0B, 0x3A, 0x01, 0x04, 0x0E, 0x06, 0x05, 0xBB, 0x01, 0x7F, + 0x03, 0x00, 0x04, 0x04, 0x01, 0x7F, 0x03, 0x00, 0x02, 0x00, 0x06, 0x09, + 0x01, 0x7F, 0xB6, 0x01, 0x7F, 0xDA, 0x04, 0x80, 0x53, 0xB8, 0x7B, 0x2D, + 0xA6, 0x01, T0_INT1(BR_KEYTYPE_SIGN), 0x17, 0x06, 0x01, 0xBD, 0xC0, + 0x27, 0x01, 0x0D, 0x0E, 0x06, 0x07, 0x26, 0xBF, 0xC0, 0x01, 0x7F, 0x04, + 0x02, 0x01, 0x00, 0x03, 0x01, 0x01, 0x0E, 0x0E, 0x05, 0x02, 0x74, 0x29, + 0x06, 0x02, 0x69, 0x29, 0x34, 0x06, 0x02, 0x74, 0x29, 0x02, 0x01, 0x06, + 0x1C, 0xDB, 0x82, 0x2F, 0x01, 0x81, 0x7F, 0x0E, 0x06, 0x0D, 0x26, 0x01, + 0x10, 0xE6, 0x01, 0x00, 0xE5, 0x7B, 0x2D, 0xB1, 0x25, 0x04, 0x04, 0xDE, + 0x06, 0x01, 0xDC, 0x04, 0x01, 0xDE, 0x01, 0x7F, 0xDA, 0x01, 0x7F, 0xB6, + 0x01, 0x01, 0x79, 0x40, 0x01, 0x17, 0x89, 0x40, 0x00, 0x00, 0x39, 0x39, + 0x00, 0x00, 0x9F, 0x01, 0x0C, 0x11, 0x01, 0x00, 0x39, 0x0E, 0x06, 0x05, + 0x26, 0x01, T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX), 0x04, 0x30, + 0x01, 0x01, 0x39, 0x0E, 0x06, 0x05, 0x26, 0x01, + T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN), 0x04, 0x25, 0x01, 0x02, + 0x39, 0x0E, 0x06, 0x05, 0x26, 0x01, + T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_SIGN), 0x04, 0x1A, 0x01, 0x03, + 0x39, 0x0E, 0x06, 0x05, 0x26, 0x01, + T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x0F, 0x01, 0x04, + 0x39, 0x0E, 0x06, 0x05, 0x26, 0x01, + T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x04, 0x01, 0x00, + 0x46, 0x26, 0x00, 0x00, 0x84, 0x2F, 0x01, 0x0E, 0x0E, 0x06, 0x04, 0x01, + 0x00, 0x04, 0x02, 0x01, 0x05, 0x00, 0x00, 0x42, 0x06, 0x04, 0x01, 0x06, + 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x8A, 0x2F, 0x27, 0x06, 0x08, 0x01, + 0x01, 0x09, 0x01, 0x11, 0x07, 0x04, 0x03, 0x26, 0x01, 0x05, 0x00, 0x00, + 0x92, 0x2D, 0x01, 0x04, 0x08, 0x00, 0x01, 0x43, 0x03, 0x00, 0x26, 0x01, + 0x00, 0x45, 0x06, 0x03, 0x02, 0x00, 0x08, 0x44, 0x06, 0x03, 0x02, 0x00, + 0x08, 0x27, 0x06, 0x06, 0x01, 0x01, 0x0B, 0x01, 0x06, 0x08, 0x00, 0x00, + 0x8D, 0x41, 0x27, 0x06, 0x03, 0x01, 0x09, 0x08, 0x00, 0x01, 0x42, 0x27, + 0x06, 0x1E, 0x01, 0x00, 0x03, 0x00, 0x27, 0x06, 0x0E, 0x27, 0x01, 0x01, + 0x17, 0x02, 0x00, 0x08, 0x03, 0x00, 0x01, 0x01, 0x11, 0x04, 0x6F, 0x26, + 0x02, 0x00, 0x01, 0x01, 0x0B, 0x01, 0x06, 0x08, 0x00, 0x00, 0x81, 0x2E, + 0x46, 0x11, 0x01, 0x01, 0x17, 0x36, 0x00, 0x00, 0xA4, 0xD6, 0x27, 0x01, + 0x07, 0x17, 0x01, 0x00, 0x39, 0x0E, 0x06, 0x09, 0x26, 0x01, 0x10, 0x17, + 0x06, 0x01, 0xA4, 0x04, 0x35, 0x01, 0x01, 0x39, 0x0E, 0x06, 0x2C, 0x26, + 0x26, 0x01, 0x00, 0x79, 0x40, 0xBA, 0x8A, 0x2F, 0x01, 0x01, 0x0E, 0x01, + 0x01, 0xAE, 0x38, 0x06, 0x17, 0x2A, 0x1A, 0x37, 0x06, 0x04, 0xD6, 0x26, + 0x04, 0x78, 0x01, 0x80, 0x64, 0xCD, 0x01, 0x01, 0x79, 0x40, 0x01, 0x17, + 0x89, 0x40, 0x04, 0x01, 0xA4, 0x04, 0x03, 0x74, 0x29, 0x26, 0x04, 0xFF, + 0x34, 0x01, 0x27, 0x03, 0x00, 0x09, 0x27, 0x5A, 0x06, 0x02, 0x6A, 0x29, + 0x02, 0x00, 0x00, 0x00, 0x9F, 0x01, 0x0F, 0x17, 0x00, 0x00, 0x78, 0x2F, + 0x01, 0x00, 0x39, 0x0E, 0x06, 0x10, 0x26, 0x27, 0x01, 0x01, 0x0D, 0x06, + 0x03, 0x26, 0x01, 0x02, 0x78, 0x40, 0x01, 0x00, 0x04, 0x21, 0x01, 0x01, + 0x39, 0x0E, 0x06, 0x14, 0x26, 0x01, 0x00, 0x78, 0x40, 0x27, 0x01, 0x80, + 0x64, 0x0E, 0x06, 0x05, 0x01, 0x82, 0x00, 0x08, 0x29, 0x5C, 0x04, 0x07, + 0x26, 0x01, 0x82, 0x00, 0x08, 0x29, 0x26, 0x00, 0x00, 0x01, 0x00, 0x30, + 0x06, 0x05, 0x3C, 0xB2, 0x38, 0x04, 0x78, 0x27, 0x06, 0x04, 0x01, 0x01, + 0x94, 0x40, 0x00, 0x01, 0xC7, 0xB0, 0xC7, 0xB0, 0xC9, 0x86, 0x46, 0x27, + 0x03, 0x00, 0xBE, 0xA0, 0xA0, 0x02, 0x00, 0x4F, 0x27, 0x5A, 0x06, 0x0A, + 0x01, 0x03, 0xAE, 0x06, 0x02, 0x74, 0x29, 0x26, 0x04, 0x03, 0x5E, 0x8C, + 0x3E, 0x00, 0x00, 0x30, 0x06, 0x0B, 0x88, 0x2F, 0x01, 0x14, 0x0D, 0x06, + 0x02, 0x74, 0x29, 0x04, 0x11, 0xD6, 0x01, 0x07, 0x17, 0x27, 0x01, 0x02, + 0x0D, 0x06, 0x06, 0x06, 0x02, 0x74, 0x29, 0x04, 0x70, 0x26, 0xCA, 0x01, + 0x01, 0x0D, 0x34, 0x38, 0x06, 0x02, 0x63, 0x29, 0x27, 0x01, 0x01, 0xD0, + 0x37, 0xB9, 0x00, 0x00, 0x93, 0x2F, 0x06, 0x2A, 0x30, 0x06, 0x0A, 0x88, + 0x2F, 0x01, 0x16, 0x0E, 0x06, 0x01, 0xBB, 0x04, 0x1D, 0xD6, 0x01, 0x07, + 0x17, 0x27, 0x01, 0x01, 0x0E, 0x06, 0x04, 0x26, 0xBB, 0x01, 0x00, 0x27, + 0x01, 0x02, 0x0D, 0x06, 0x08, 0x27, 0x06, 0x02, 0x74, 0x29, 0x26, 0x04, + 0x64, 0x26, 0xB5, 0x00, 0x01, 0xC0, 0x01, 0x0B, 0x0E, 0x05, 0x02, 0x74, + 0x29, 0x27, 0x01, 0x03, 0x0E, 0x06, 0x08, 0xC8, 0x06, 0x02, 0x6A, 0x29, + 0x46, 0x26, 0x00, 0x46, 0x59, 0xC8, 0xB0, 0x27, 0x06, 0x23, 0xC8, 0xB0, + 0x27, 0x58, 0x27, 0x06, 0x18, 0x27, 0x01, 0x82, 0x00, 0x0F, 0x06, 0x05, + 0x01, 0x82, 0x00, 0x04, 0x01, 0x27, 0x03, 0x00, 0x86, 0x02, 0x00, 0xBE, + 0x02, 0x00, 0x55, 0x04, 0x65, 0xA0, 0x56, 0x04, 0x5A, 0xA0, 0xA0, 0x57, + 0x27, 0x06, 0x02, 0x36, 0x00, 0x26, 0x2C, 0x00, 0x00, 0x7B, 0x2D, 0xA6, + 0x01, 0x7F, 0xB7, 0x27, 0x5A, 0x06, 0x02, 0x36, 0x29, 0x27, 0x05, 0x02, + 0x74, 0x29, 0x39, 0x17, 0x0D, 0x06, 0x02, 0x76, 0x29, 0x3D, 0x00, 0x00, + 0xA1, 0xC0, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x74, 0x29, 0x86, 0x01, 0x0C, + 0x08, 0x01, 0x0C, 0xBE, 0xA0, 0x86, 0x27, 0x01, 0x0C, 0x08, 0x01, 0x0C, + 0x31, 0x05, 0x02, 0x66, 0x29, 0x00, 0x00, 0xC1, 0x06, 0x02, 0x74, 0x29, + 0x06, 0x02, 0x68, 0x29, 0x00, 0x01, 0xC0, 0x01, 0x04, 0x0E, 0x05, 0x02, + 0x74, 0x29, 0xC7, 0x26, 0xC7, 0x26, 0xC7, 0x03, 0x00, 0x02, 0x00, 0x01, + 0x88, 0x00, 0x0F, 0x06, 0x09, 0x02, 0x00, 0xCE, 0x01, 0x00, 0x92, 0x3E, + 0x04, 0x08, 0x91, 0x02, 0x00, 0xBE, 0x02, 0x00, 0x92, 0x3E, 0x02, 0x00, + 0x20, 0xA0, 0x00, 0x0B, 0xC0, 0x01, 0x02, 0x0E, 0x05, 0x02, 0x74, 0x29, + 0xC7, 0x03, 0x00, 0x02, 0x00, 0x9A, 0x2D, 0x0A, 0x02, 0x00, 0x99, 0x2D, + 0x0F, 0x38, 0x06, 0x02, 0x75, 0x29, 0x02, 0x00, 0x98, 0x2D, 0x0D, 0x06, + 0x02, 0x6D, 0x29, 0x02, 0x00, 0x9B, 0x3E, 0x8E, 0x01, 0x20, 0xBE, 0x01, + 0x00, 0x03, 0x01, 0xC9, 0x03, 0x02, 0x02, 0x02, 0x01, 0x20, 0x0F, 0x06, + 0x02, 0x72, 0x29, 0x86, 0x02, 0x02, 0xBE, 0x02, 0x02, 0x90, 0x2F, 0x0E, + 0x02, 0x02, 0x01, 0x00, 0x0F, 0x17, 0x06, 0x0B, 0x8F, 0x86, 0x02, 0x02, + 0x31, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x01, 0x8F, 0x86, 0x02, 0x02, 0x32, + 0x02, 0x02, 0x90, 0x40, 0x02, 0x00, 0x97, 0x02, 0x01, 0x9D, 0xC7, 0x27, + 0xCB, 0x5A, 0x06, 0x02, 0x64, 0x29, 0x27, 0xD5, 0x02, 0x00, 0x01, 0x86, + 0x03, 0x0A, 0x17, 0x06, 0x02, 0x64, 0x29, 0x7B, 0x02, 0x01, 0x9D, 0xC9, + 0x06, 0x02, 0x65, 0x29, 0x27, 0x06, 0x81, 0x64, 0xC7, 0xB0, 0xAC, 0x03, + 0x03, 0xA9, 0x03, 0x04, 0xA7, 0x03, 0x05, 0xAB, 0x03, 0x06, 0xAD, 0x03, + 0x07, 0xA8, 0x03, 0x08, 0xAA, 0x03, 0x09, 0x28, 0x03, 0x0A, 0x27, 0x06, + 0x81, 0x32, 0xC7, 0x01, 0x00, 0x39, 0x0E, 0x06, 0x0F, 0x26, 0x02, 0x03, + 0x05, 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, 0x03, 0xC6, 0x04, 0x81, 0x19, + 0x01, 0x01, 0x39, 0x0E, 0x06, 0x0F, 0x26, 0x02, 0x05, 0x05, 0x02, 0x6E, + 0x29, 0x01, 0x00, 0x03, 0x05, 0xC4, 0x04, 0x81, 0x04, 0x01, 0x83, 0xFE, + 0x01, 0x39, 0x0E, 0x06, 0x0F, 0x26, 0x02, 0x04, 0x05, 0x02, 0x6E, 0x29, + 0x01, 0x00, 0x03, 0x04, 0xC5, 0x04, 0x80, 0x6D, 0x01, 0x0D, 0x39, 0x0E, + 0x06, 0x0F, 0x26, 0x02, 0x06, 0x05, 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, + 0x06, 0xC2, 0x04, 0x80, 0x58, 0x01, 0x0A, 0x39, 0x0E, 0x06, 0x0F, 0x26, + 0x02, 0x07, 0x05, 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, 0x07, 0xC2, 0x04, + 0x80, 0x43, 0x01, 0x0B, 0x39, 0x0E, 0x06, 0x0E, 0x26, 0x02, 0x08, 0x05, + 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, 0x08, 0xC2, 0x04, 0x2F, 0x01, 0x10, + 0x39, 0x0E, 0x06, 0x0E, 0x26, 0x02, 0x0A, 0x05, 0x02, 0x6E, 0x29, 0x01, + 0x00, 0x03, 0x0A, 0xB4, 0x04, 0x1B, 0x01, 0x23, 0x39, 0x0E, 0x06, 0x12, + 0x26, 0x02, 0x09, 0x05, 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, 0x09, 0xC2, + 0x01, 0x01, 0x93, 0x40, 0x04, 0x03, 0x6E, 0x29, 0x26, 0x04, 0xFE, 0x4A, + 0x02, 0x04, 0x06, 0x0D, 0x02, 0x04, 0x01, 0x05, 0x0F, 0x06, 0x02, 0x6B, + 0x29, 0x01, 0x01, 0x8A, 0x40, 0xA0, 0x04, 0x0C, 0xA9, 0x01, 0x05, 0x0F, + 0x06, 0x02, 0x6B, 0x29, 0x01, 0x01, 0x8A, 0x40, 0xA0, 0x02, 0x01, 0x00, + 0x04, 0xC0, 0x01, 0x0C, 0x0E, 0x05, 0x02, 0x74, 0x29, 0xC9, 0x01, 0x03, + 0x0E, 0x05, 0x02, 0x6F, 0x29, 0xC7, 0x27, 0x7E, 0x40, 0x27, 0x01, 0x20, + 0x10, 0x06, 0x02, 0x6F, 0x29, 0x42, 0x46, 0x11, 0x01, 0x01, 0x17, 0x05, + 0x02, 0x6F, 0x29, 0xC9, 0x27, 0x01, 0x81, 0x05, 0x0F, 0x06, 0x02, 0x6F, + 0x29, 0x27, 0x80, 0x40, 0x7F, 0x46, 0xBE, 0x97, 0x2D, 0x01, 0x86, 0x03, + 0x10, 0x03, 0x00, 0x7B, 0x2D, 0xD3, 0x03, 0x01, 0x01, 0x02, 0x03, 0x02, + 0x02, 0x00, 0x06, 0x21, 0xC9, 0x27, 0x27, 0x01, 0x02, 0x0A, 0x46, 0x01, + 0x06, 0x0F, 0x38, 0x06, 0x02, 0x6F, 0x29, 0x03, 0x02, 0xC9, 0x02, 0x01, + 0x01, 0x01, 0x0B, 0x01, 0x03, 0x08, 0x0E, 0x05, 0x02, 0x6F, 0x29, 0x04, + 0x08, 0x02, 0x01, 0x06, 0x04, 0x01, 0x00, 0x03, 0x02, 0xC7, 0x27, 0x03, + 0x03, 0x27, 0x01, 0x84, 0x00, 0x0F, 0x06, 0x02, 0x70, 0x29, 0x86, 0x46, + 0xBE, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x52, 0x27, 0x06, 0x01, 0x29, + 0x26, 0xA0, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00, 0x9C, 0x02, + 0x01, 0x02, 0x00, 0x3B, 0x27, 0x01, 0x00, 0x0E, 0x06, 0x02, 0x62, 0x00, + 0xD8, 0x04, 0x74, 0x02, 0x01, 0x00, 0x03, 0x00, 0xC9, 0xB0, 0x27, 0x06, + 0x80, 0x43, 0xC9, 0x01, 0x01, 0x39, 0x0E, 0x06, 0x06, 0x26, 0x01, 0x81, + 0x7F, 0x04, 0x2E, 0x01, 0x80, 0x40, 0x39, 0x0E, 0x06, 0x07, 0x26, 0x01, + 0x83, 0xFE, 0x00, 0x04, 0x20, 0x01, 0x80, 0x41, 0x39, 0x0E, 0x06, 0x07, + 0x26, 0x01, 0x84, 0x80, 0x00, 0x04, 0x12, 0x01, 0x80, 0x42, 0x39, 0x0E, + 0x06, 0x07, 0x26, 0x01, 0x88, 0x80, 0x00, 0x04, 0x04, 0x01, 0x00, 0x46, + 0x26, 0x02, 0x00, 0x38, 0x03, 0x00, 0x04, 0xFF, 0x39, 0xA0, 0x7B, 0x2D, + 0xD1, 0x05, 0x09, 0x02, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x17, 0x03, 0x00, + 0x97, 0x2D, 0x01, 0x86, 0x03, 0x10, 0x06, 0x3A, 0xC3, 0x27, 0x83, 0x3F, + 0x43, 0x26, 0x27, 0x01, 0x08, 0x0B, 0x38, 0x01, 0x8C, 0x80, 0x00, 0x38, + 0x17, 0x02, 0x00, 0x17, 0x02, 0x00, 0x01, 0x8C, 0x80, 0x00, 0x17, 0x06, + 0x19, 0x27, 0x01, 0x81, 0x7F, 0x17, 0x06, 0x05, 0x01, 0x84, 0x80, 0x00, + 0x38, 0x27, 0x01, 0x83, 0xFE, 0x00, 0x17, 0x06, 0x05, 0x01, 0x88, 0x80, + 0x00, 0x38, 0x03, 0x00, 0x04, 0x09, 0x02, 0x00, 0x01, 0x8C, 0x88, 0x01, + 0x17, 0x03, 0x00, 0x16, 0xC7, 0xB0, 0x27, 0x06, 0x23, 0xC7, 0xB0, 0x27, + 0x15, 0x27, 0x06, 0x18, 0x27, 0x01, 0x82, 0x00, 0x0F, 0x06, 0x05, 0x01, + 0x82, 0x00, 0x04, 0x01, 0x27, 0x03, 0x01, 0x86, 0x02, 0x01, 0xBE, 0x02, + 0x01, 0x12, 0x04, 0x65, 0xA0, 0x13, 0x04, 0x5A, 0xA0, 0x14, 0xA0, 0x02, + 0x00, 0x2B, 0x00, 0x00, 0xC1, 0x27, 0x5C, 0x06, 0x07, 0x26, 0x06, 0x02, + 0x68, 0x29, 0x04, 0x74, 0x00, 0x00, 0xCA, 0x01, 0x03, 0xC8, 0x46, 0x26, + 0x46, 0x00, 0x00, 0xC7, 0xCE, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 0xC7, + 0xB0, 0x27, 0x06, 0x80, 0x50, 0xC9, 0x03, 0x01, 0xC9, 0x03, 0x02, 0x02, + 0x01, 0x01, 0x08, 0x0E, 0x06, 0x16, 0x02, 0x02, 0x01, 0x0F, 0x0C, 0x06, + 0x0D, 0x01, 0x01, 0x02, 0x02, 0x01, 0x10, 0x08, 0x0B, 0x02, 0x00, 0x38, + 0x03, 0x00, 0x04, 0x2A, 0x02, 0x01, 0x01, 0x02, 0x10, 0x02, 0x01, 0x01, + 0x06, 0x0C, 0x17, 0x02, 0x02, 0x01, 0x01, 0x0E, 0x02, 0x02, 0x01, 0x03, + 0x0E, 0x38, 0x17, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x5F, + 0x01, 0x02, 0x0B, 0x02, 0x01, 0x08, 0x0B, 0x38, 0x03, 0x00, 0x04, 0xFF, + 0x2C, 0xA0, 0x02, 0x00, 0x00, 0x00, 0xC7, 0x01, 0x01, 0x0E, 0x05, 0x02, + 0x67, 0x29, 0xC9, 0x01, 0x08, 0x08, 0x84, 0x2F, 0x0E, 0x05, 0x02, 0x67, + 0x29, 0x00, 0x00, 0xC7, 0x8A, 0x2F, 0x05, 0x15, 0x01, 0x01, 0x0E, 0x05, + 0x02, 0x6B, 0x29, 0xC9, 0x01, 0x00, 0x0E, 0x05, 0x02, 0x6B, 0x29, 0x01, + 0x02, 0x8A, 0x40, 0x04, 0x1C, 0x01, 0x19, 0x0E, 0x05, 0x02, 0x6B, 0x29, + 0xC9, 0x01, 0x18, 0x0E, 0x05, 0x02, 0x6B, 0x29, 0x86, 0x01, 0x18, 0xBE, + 0x8B, 0x86, 0x01, 0x18, 0x31, 0x05, 0x02, 0x6B, 0x29, 0x00, 0x00, 0xC7, + 0x06, 0x02, 0x6C, 0x29, 0x00, 0x00, 0x01, 0x02, 0x9C, 0xCA, 0x01, 0x08, + 0x0B, 0xCA, 0x08, 0x00, 0x00, 0x01, 0x03, 0x9C, 0xCA, 0x01, 0x08, 0x0B, + 0xCA, 0x08, 0x01, 0x08, 0x0B, 0xCA, 0x08, 0x00, 0x00, 0x01, 0x01, 0x9C, + 0xCA, 0x00, 0x00, 0x3C, 0x27, 0x5A, 0x05, 0x01, 0x00, 0x26, 0xD8, 0x04, + 0x76, 0x02, 0x03, 0x00, 0x96, 0x2F, 0x03, 0x01, 0x01, 0x00, 0x27, 0x02, + 0x01, 0x0A, 0x06, 0x10, 0x27, 0x01, 0x01, 0x0B, 0x95, 0x08, 0x2D, 0x02, + 0x00, 0x0E, 0x06, 0x01, 0x00, 0x5E, 0x04, 0x6A, 0x26, 0x01, 0x7F, 0x00, + 0x00, 0x01, 0x15, 0x89, 0x40, 0x46, 0x54, 0x26, 0x54, 0x26, 0x2A, 0x00, + 0x00, 0x01, 0x01, 0x46, 0xCC, 0x00, 0x00, 0x46, 0x39, 0x9C, 0x46, 0x27, + 0x06, 0x05, 0xCA, 0x26, 0x5F, 0x04, 0x78, 0x26, 0x00, 0x00, 0x27, 0x01, + 0x81, 0xAC, 0x00, 0x0E, 0x06, 0x04, 0x26, 0x01, 0x7F, 0x00, 0x9F, 0x5B, + 0x00, 0x02, 0x03, 0x00, 0x7B, 0x2D, 0x9F, 0x03, 0x01, 0x02, 0x01, 0x01, + 0x0F, 0x17, 0x02, 0x01, 0x01, 0x04, 0x11, 0x01, 0x0F, 0x17, 0x02, 0x01, + 0x01, 0x08, 0x11, 0x01, 0x0F, 0x17, 0x01, 0x00, 0x39, 0x0E, 0x06, 0x10, + 0x26, 0x01, 0x00, 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x4B, 0x04, 0x01, + 0x4C, 0x04, 0x81, 0x0D, 0x01, 0x01, 0x39, 0x0E, 0x06, 0x10, 0x26, 0x01, + 0x01, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x4B, 0x04, 0x01, 0x4C, 0x04, + 0x80, 0x77, 0x01, 0x02, 0x39, 0x0E, 0x06, 0x10, 0x26, 0x01, 0x01, 0x01, + 0x20, 0x02, 0x00, 0x06, 0x03, 0x4B, 0x04, 0x01, 0x4C, 0x04, 0x80, 0x61, + 0x01, 0x03, 0x39, 0x0E, 0x06, 0x0F, 0x26, 0x26, 0x01, 0x10, 0x02, 0x00, + 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, 0x04, 0x80, 0x4C, 0x01, 0x04, 0x39, + 0x0E, 0x06, 0x0E, 0x26, 0x26, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x49, + 0x04, 0x01, 0x4A, 0x04, 0x38, 0x01, 0x05, 0x39, 0x0E, 0x06, 0x0C, 0x26, + 0x26, 0x02, 0x00, 0x06, 0x03, 0x4D, 0x04, 0x01, 0x4E, 0x04, 0x26, 0x27, + 0x01, 0x09, 0x0F, 0x06, 0x02, 0x6A, 0x29, 0x46, 0x26, 0x27, 0x01, 0x01, + 0x17, 0x01, 0x04, 0x0B, 0x01, 0x10, 0x08, 0x46, 0x01, 0x08, 0x17, 0x01, + 0x10, 0x46, 0x09, 0x02, 0x00, 0x06, 0x03, 0x47, 0x04, 0x01, 0x48, 0x00, + 0x26, 0x00, 0x00, 0x9F, 0x01, 0x0C, 0x11, 0x01, 0x02, 0x0F, 0x00, 0x00, + 0x9F, 0x01, 0x0C, 0x11, 0x27, 0x5D, 0x46, 0x01, 0x03, 0x0A, 0x17, 0x00, + 0x00, 0x9F, 0x01, 0x0C, 0x11, 0x01, 0x01, 0x0E, 0x00, 0x00, 0x9F, 0x01, + 0x0C, 0x11, 0x5C, 0x00, 0x00, 0x9F, 0x01, 0x81, 0x70, 0x17, 0x01, 0x20, + 0x0D, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x77, 0x2F, 0x27, 0x06, 0x22, 0x01, + 0x01, 0x39, 0x0E, 0x06, 0x06, 0x26, 0x01, 0x00, 0xA3, 0x04, 0x14, 0x01, + 0x02, 0x39, 0x0E, 0x06, 0x0D, 0x26, 0x79, 0x2F, 0x01, 0x01, 0x0E, 0x06, + 0x03, 0x01, 0x10, 0x38, 0x04, 0x01, 0x26, 0x04, 0x01, 0x26, 0x7D, 0x2F, + 0x05, 0x33, 0x30, 0x06, 0x30, 0x88, 0x2F, 0x01, 0x14, 0x39, 0x0E, 0x06, + 0x06, 0x26, 0x01, 0x02, 0x38, 0x04, 0x22, 0x01, 0x15, 0x39, 0x0E, 0x06, + 0x09, 0x26, 0xB3, 0x06, 0x03, 0x01, 0x7F, 0xA3, 0x04, 0x13, 0x01, 0x16, + 0x39, 0x0E, 0x06, 0x06, 0x26, 0x01, 0x01, 0x38, 0x04, 0x07, 0x26, 0x01, + 0x04, 0x38, 0x01, 0x00, 0x26, 0x1A, 0x06, 0x03, 0x01, 0x08, 0x38, 0x00, + 0x00, 0x1B, 0x27, 0x05, 0x13, 0x30, 0x06, 0x10, 0x88, 0x2F, 0x01, 0x15, + 0x0E, 0x06, 0x08, 0x26, 0xB3, 0x01, 0x00, 0x79, 0x40, 0x04, 0x01, 0x21, + 0x00, 0x00, 0xD6, 0x01, 0x07, 0x17, 0x01, 0x01, 0x0F, 0x06, 0x02, 0x74, + 0x29, 0x00, 0x01, 0x03, 0x00, 0x2A, 0x1A, 0x06, 0x05, 0x02, 0x00, 0x89, + 0x40, 0x00, 0xD6, 0x26, 0x04, 0x74, 0x00, 0x01, 0x14, 0xD9, 0x01, 0x01, + 0xE6, 0x2A, 0x27, 0x01, 0x00, 0xD0, 0x01, 0x16, 0xD9, 0xDF, 0x2A, 0x00, + 0x00, 0x01, 0x0B, 0xE6, 0x50, 0x27, 0x27, 0x01, 0x03, 0x08, 0xE5, 0xE5, + 0x18, 0x27, 0x5A, 0x06, 0x02, 0x26, 0x00, 0xE5, 0x1D, 0x27, 0x06, 0x05, + 0x86, 0x46, 0xE0, 0x04, 0x77, 0x26, 0x04, 0x6C, 0x00, 0x22, 0x01, 0x0F, + 0xE6, 0x27, 0x97, 0x2D, 0x01, 0x86, 0x03, 0x10, 0x06, 0x0C, 0x01, 0x04, + 0x08, 0xE5, 0x82, 0x2F, 0xE6, 0x7A, 0x2F, 0xE6, 0x04, 0x02, 0x60, 0xE5, + 0x27, 0xE4, 0x86, 0x46, 0xE0, 0x00, 0x02, 0xA9, 0xAC, 0x08, 0xA7, 0x08, + 0xAB, 0x08, 0xAD, 0x08, 0xA8, 0x08, 0x28, 0x08, 0xAA, 0x08, 0x03, 0x00, + 0x01, 0x01, 0xE6, 0x01, 0x27, 0x90, 0x2F, 0x08, 0x96, 0x2F, 0x01, 0x01, + 0x0B, 0x08, 0x02, 0x00, 0x06, 0x04, 0x60, 0x02, 0x00, 0x08, 0x85, 0x2D, + 0x39, 0x09, 0x27, 0x5D, 0x06, 0x24, 0x02, 0x00, 0x05, 0x04, 0x46, 0x60, + 0x46, 0x61, 0x01, 0x04, 0x09, 0x27, 0x5A, 0x06, 0x03, 0x26, 0x01, 0x00, + 0x27, 0x01, 0x04, 0x08, 0x02, 0x00, 0x08, 0x03, 0x00, 0x46, 0x01, 0x04, + 0x08, 0x39, 0x08, 0x46, 0x04, 0x03, 0x26, 0x01, 0x7F, 0x03, 0x01, 0xE5, + 0x99, 0x2D, 0xE4, 0x7C, 0x01, 0x04, 0x19, 0x7C, 0x01, 0x04, 0x08, 0x01, + 0x1C, 0x33, 0x7C, 0x01, 0x20, 0xE0, 0x8F, 0x90, 0x2F, 0xE2, 0x96, 0x2F, + 0x27, 0x01, 0x01, 0x0B, 0xE4, 0x95, 0x46, 0x27, 0x06, 0x0F, 0x5F, 0x39, + 0x2D, 0x27, 0xCF, 0x05, 0x02, 0x64, 0x29, 0xE4, 0x46, 0x60, 0x46, 0x04, + 0x6E, 0x62, 0x01, 0x01, 0xE6, 0x01, 0x00, 0xE6, 0x02, 0x00, 0x06, 0x81, + 0x6A, 0x02, 0x00, 0xE4, 0xA9, 0x06, 0x0E, 0x01, 0x83, 0xFE, 0x01, 0xE4, + 0x8B, 0xA9, 0x01, 0x04, 0x09, 0x27, 0xE4, 0x5F, 0xE2, 0xAC, 0x06, 0x16, + 0x01, 0x00, 0xE4, 0x8D, 0xAC, 0x01, 0x04, 0x09, 0x27, 0xE4, 0x01, 0x02, + 0x09, 0x27, 0xE4, 0x01, 0x00, 0xE6, 0x01, 0x03, 0x09, 0xE1, 0xA7, 0x06, + 0x0C, 0x01, 0x01, 0xE4, 0x01, 0x01, 0xE4, 0x84, 0x2F, 0x01, 0x08, 0x09, + 0xE6, 0xAB, 0x06, 0x19, 0x01, 0x0D, 0xE4, 0xAB, 0x01, 0x04, 0x09, 0x27, + 0xE4, 0x01, 0x02, 0x09, 0xE4, 0x44, 0x06, 0x03, 0x01, 0x03, 0xE3, 0x45, + 0x06, 0x03, 0x01, 0x01, 0xE3, 0xAD, 0x27, 0x06, 0x36, 0x01, 0x0A, 0xE4, + 0x01, 0x04, 0x09, 0x27, 0xE4, 0x61, 0xE4, 0x42, 0x01, 0x00, 0x27, 0x01, + 0x82, 0x80, 0x80, 0x80, 0x00, 0x17, 0x06, 0x0A, 0x01, 0xFD, 0xFF, 0xFF, + 0xFF, 0x7F, 0x17, 0x01, 0x1D, 0xE4, 0x27, 0x01, 0x20, 0x0A, 0x06, 0x0C, + 0xA5, 0x11, 0x01, 0x01, 0x17, 0x06, 0x02, 0x27, 0xE4, 0x5E, 0x04, 0x6E, + 0x62, 0x04, 0x01, 0x26, 0xA8, 0x06, 0x0A, 0x01, 0x0B, 0xE4, 0x01, 0x02, + 0xE4, 0x01, 0x82, 0x00, 0xE4, 0x28, 0x27, 0x06, 0x1F, 0x01, 0x10, 0xE4, + 0x01, 0x04, 0x09, 0x27, 0xE4, 0x61, 0xE4, 0x87, 0x2D, 0x01, 0x00, 0xA5, + 0x0F, 0x06, 0x0A, 0x27, 0x1E, 0x27, 0xE6, 0x86, 0x46, 0xE0, 0x5E, 0x04, + 0x72, 0x62, 0x04, 0x01, 0x26, 0x01, 0x23, 0xE4, 0x92, 0x2D, 0x27, 0xE4, + 0x27, 0x06, 0x05, 0x91, 0x46, 0xE0, 0x04, 0x01, 0x26, 0x02, 0x01, 0x5A, + 0x05, 0x11, 0x01, 0x15, 0xE4, 0x02, 0x01, 0x27, 0xE4, 0x27, 0x06, 0x06, + 0x5F, 0x01, 0x00, 0xE6, 0x04, 0x77, 0x26, 0x00, 0x00, 0x01, 0x10, 0xE6, + 0x7B, 0x2D, 0x27, 0xD4, 0x06, 0x0C, 0xB1, 0x24, 0x27, 0x60, 0xE5, 0x27, + 0xE4, 0x86, 0x46, 0xE0, 0x04, 0x0D, 0x27, 0xD2, 0x46, 0xB1, 0x23, 0x27, + 0x5E, 0xE5, 0x27, 0xE6, 0x86, 0x46, 0xE0, 0x00, 0x00, 0xA1, 0x01, 0x14, + 0xE6, 0x01, 0x0C, 0xE5, 0x86, 0x01, 0x0C, 0xE0, 0x00, 0x00, 0x53, 0x27, + 0x01, 0x00, 0x0E, 0x06, 0x02, 0x62, 0x00, 0xD6, 0x26, 0x04, 0x73, 0x00, + 0x27, 0xE4, 0xE0, 0x00, 0x00, 0x27, 0xE6, 0xE0, 0x00, 0x01, 0x03, 0x00, + 0x43, 0x26, 0x27, 0x01, 0x10, 0x17, 0x06, 0x06, 0x01, 0x04, 0xE6, 0x02, + 0x00, 0xE6, 0x27, 0x01, 0x08, 0x17, 0x06, 0x06, 0x01, 0x03, 0xE6, 0x02, + 0x00, 0xE6, 0x27, 0x01, 0x20, 0x17, 0x06, 0x06, 0x01, 0x05, 0xE6, 0x02, + 0x00, 0xE6, 0x27, 0x01, 0x80, 0x40, 0x17, 0x06, 0x06, 0x01, 0x06, 0xE6, + 0x02, 0x00, 0xE6, 0x01, 0x04, 0x17, 0x06, 0x06, 0x01, 0x02, 0xE6, 0x02, + 0x00, 0xE6, 0x00, 0x00, 0x27, 0x01, 0x08, 0x51, 0xE6, 0xE6, 0x00, 0x00, + 0x27, 0x01, 0x10, 0x51, 0xE6, 0xE4, 0x00, 0x00, 0x27, 0x54, 0x06, 0x02, + 0x26, 0x00, 0xD6, 0x26, 0x04, 0x76 +}; + +static const uint16_t t0_caddr[] = { + 0, + 5, + 10, + 15, + 20, + 25, + 30, + 35, + 40, + 44, + 48, + 52, + 56, + 60, + 64, + 68, + 72, + 76, + 80, + 84, + 88, + 92, + 96, + 100, + 104, + 108, + 112, + 116, + 120, + 124, + 129, + 134, + 139, + 144, + 149, + 154, + 159, + 164, + 169, + 174, + 179, + 184, + 189, + 194, + 199, + 204, + 209, + 214, + 219, + 224, + 229, + 234, + 239, + 244, + 249, + 254, + 259, + 264, + 269, + 274, + 279, + 284, + 289, + 294, + 299, + 304, + 309, + 318, + 331, + 335, + 360, + 366, + 385, + 396, + 437, + 625, + 629, + 694, + 709, + 720, + 738, + 745, + 774, + 784, + 820, + 830, + 908, + 922, + 928, + 987, + 1006, + 1041, + 1090, + 1139, + 1215, + 1242, + 1273, + 1284, + 1330, + 1711, + 1858, + 1882, + 2098, + 2112, + 2121, + 2125, + 2220, + 2241, + 2297, + 2304, + 2315, + 2331, + 2337, + 2348, + 2383, + 2395, + 2401, + 2416, + 2432, + 2625, + 2634, + 2647, + 2656, + 2663, + 2673, + 2779, + 2804, + 2817, + 2833, + 2851, + 2883, + 2917, + 3303, + 3339, + 3352, + 3366, + 3371, + 3376, + 3442, + 3450, + 3458 +}; + +#define T0_INTERPRETED 90 + +#define T0_ENTER(ip, rp, slot) do { \ + const unsigned char *t0_newip; \ + uint32_t t0_lnum; \ + t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ + t0_lnum = t0_parse7E_unsigned(&t0_newip); \ + (rp) += t0_lnum; \ + *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ + (ip) = t0_newip; \ + } while (0) + +#define T0_DEFENTRY(name, slot) \ +void \ +name(void *ctx) \ +{ \ + t0_context *t0ctx = ctx; \ + t0ctx->ip = &t0_codeblock[0]; \ + T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ +} + +T0_DEFENTRY(br_ssl_hs_client_init_main, 175) + +#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) + +void +br_ssl_hs_client_run(void *t0ctx) +{ + uint32_t *dp, *rp; + const unsigned char *ip; + +#define T0_LOCAL(x) (*(rp - 2 - (x))) +#define T0_POP() (*-- dp) +#define T0_POPi() (*(int32_t *)(-- dp)) +#define T0_PEEK(x) (*(dp - 1 - (x))) +#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) +#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) +#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) +#define T0_RPOP() (*-- rp) +#define T0_RPOPi() (*(int32_t *)(-- rp)) +#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) +#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) +#define T0_ROLL(x) do { \ + size_t t0len = (size_t)(x); \ + uint32_t t0tmp = *(dp - 1 - t0len); \ + memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_SWAP() do { \ + uint32_t t0tmp = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_ROT() do { \ + uint32_t t0tmp = *(dp - 3); \ + *(dp - 3) = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_NROT() do { \ + uint32_t t0tmp = *(dp - 1); \ + *(dp - 1) = *(dp - 2); \ + *(dp - 2) = *(dp - 3); \ + *(dp - 3) = t0tmp; \ +} while (0) +#define T0_PICK(x) do { \ + uint32_t t0depth = (x); \ + T0_PUSH(T0_PEEK(t0depth)); \ +} while (0) +#define T0_CO() do { \ + goto t0_exit; \ +} while (0) +#define T0_RET() goto t0_next + + dp = ((t0_context *)t0ctx)->dp; + rp = ((t0_context *)t0ctx)->rp; + ip = ((t0_context *)t0ctx)->ip; + goto t0_next; + for (;;) { + uint32_t t0x; + + t0_next: + t0x = T0_NEXT(&ip); + if (t0x < T0_INTERPRETED) { + switch (t0x) { + int32_t t0off; + + case 0: /* ret */ + t0x = T0_RPOP(); + rp -= (t0x >> 16); + t0x &= 0xFFFF; + if (t0x == 0) { + ip = NULL; + goto t0_exit; + } + ip = &t0_codeblock[t0x]; + break; + case 1: /* literal constant */ + T0_PUSHi(t0_parse7E_signed(&ip)); + break; + case 2: /* read local */ + T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); + break; + case 3: /* write local */ + T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); + break; + case 4: /* jump */ + t0off = t0_parse7E_signed(&ip); + ip += t0off; + break; + case 5: /* jump if */ + t0off = t0_parse7E_signed(&ip); + if (T0_POP()) { + ip += t0off; + } + break; + case 6: /* jump if not */ + t0off = t0_parse7E_signed(&ip); + if (!T0_POP()) { + ip += t0off; + } + break; + case 7: { + /* * */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a * b); + + } + break; + case 8: { + /* + */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a + b); + + } + break; + case 9: { + /* - */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a - b); + + } + break; + case 10: { + /* < */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a < b)); + + } + break; + case 11: { + /* << */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x << c); + + } + break; + case 12: { + /* <= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a <= b)); + + } + break; + case 13: { + /* <> */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a != b)); + + } + break; + case 14: { + /* = */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a == b)); + + } + break; + case 15: { + /* > */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a > b)); + + } + break; + case 16: { + /* >= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a >= b)); + + } + break; + case 17: { + /* >> */ + + int c = (int)T0_POPi(); + int32_t x = T0_POPi(); + T0_PUSHi(x >> c); + + } + break; + case 18: { + /* anchor-dn-append-name */ + + size_t len; + + len = T0_POP(); + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->append_name( + CTX->client_auth_vtable, ENG->pad, len); + } + + } + break; + case 19: { + /* anchor-dn-end-name */ + + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->end_name( + CTX->client_auth_vtable); + } + + } + break; + case 20: { + /* anchor-dn-end-name-list */ + + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->end_name_list( + CTX->client_auth_vtable); + } + + } + break; + case 21: { + /* anchor-dn-start-name */ + + size_t len; + + len = T0_POP(); + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->start_name( + CTX->client_auth_vtable, len); + } + + } + break; + case 22: { + /* anchor-dn-start-name-list */ + + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->start_name_list( + CTX->client_auth_vtable); + } + + } + break; + case 23: { + /* and */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a & b); + + } + break; + case 24: { + /* begin-cert */ + + if (ENG->chain_len == 0) { + T0_PUSHi(-1); + } else { + ENG->cert_cur = ENG->chain->data; + ENG->cert_len = ENG->chain->data_len; + ENG->chain ++; + ENG->chain_len --; + T0_PUSH(ENG->cert_len); + } + + } + break; + case 25: { + /* bzero */ + + size_t len = (size_t)T0_POP(); + void *addr = (unsigned char *)ENG + (size_t)T0_POP(); + memset(addr, 0, len); + + } + break; + case 26: { + /* can-output? */ + + T0_PUSHi(-(ENG->hlen_out > 0)); + + } + break; + case 27: { + /* co */ + T0_CO(); + } + break; + case 28: { + /* compute-Finished-inner */ + + int prf_id = T0_POP(); + int from_client = T0_POPi(); + unsigned char tmp[48]; + br_tls_prf_seed_chunk seed; + + br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id); + seed.data = tmp; + if (ENG->session.version >= BR_TLS12) { + seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp); + } else { + br_multihash_out(&ENG->mhash, br_md5_ID, tmp); + br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16); + seed.len = 36; + } + prf(ENG->pad, 12, ENG->session.master_secret, + sizeof ENG->session.master_secret, + from_client ? "client finished" : "server finished", + 1, &seed); + + } + break; + case 29: { + /* copy-cert-chunk */ + + size_t clen; + + clen = ENG->cert_len; + if (clen > sizeof ENG->pad) { + clen = sizeof ENG->pad; + } + memcpy(ENG->pad, ENG->cert_cur, clen); + ENG->cert_cur += clen; + ENG->cert_len -= clen; + T0_PUSH(clen); + + } + break; + case 30: { + /* copy-protocol-name */ + + size_t idx = T0_POP(); + size_t len = strlen(ENG->protocol_names[idx]); + memcpy(ENG->pad, ENG->protocol_names[idx], len); + T0_PUSH(len); + + } + break; + case 31: { + /* data-get8 */ + + size_t addr = T0_POP(); + T0_PUSH(t0_datablock[addr]); + + } + break; + case 32: { + /* debug-session-ticket */ + + extern void __stdcall OutputDebugStringA(const char *); + extern int sprintf(char *, const char *, ...); + char buf[80]; + size_t len = T0_POP(); + sprintf(buf, "BearSSL: NewSessionTicket received (%u bytes)\r\n", + (unsigned)len); + OutputDebugStringA(buf); + + } + break; + case 33: { + /* discard-input */ + + ENG->hlen_in = 0; + + } + break; + case 34: { + /* do-client-sign */ + + size_t sig_len; + + sig_len = make_client_sign(CTX); + if (sig_len == 0) { + br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM); + T0_CO(); + } + T0_PUSH(sig_len); + + } + break; + case 35: { + /* do-ecdh */ + + unsigned prf_id = T0_POP(); + unsigned ecdhe = T0_POP(); + int x; + + x = make_pms_ecdh(CTX, ecdhe, prf_id); + if (x < 0) { + br_ssl_engine_fail(ENG, -x); + T0_CO(); + } else { + T0_PUSH(x); + } + + } + break; + case 36: { + /* do-rsa-encrypt */ + + int x; + + x = make_pms_rsa(CTX, T0_POP()); + if (x < 0) { + br_ssl_engine_fail(ENG, -x); + T0_CO(); + } else { + T0_PUSH(x); + } + + } + break; + case 37: { + /* do-static-ecdh */ + + unsigned prf_id = T0_POP(); + + if (make_pms_static_ecdh(CTX, prf_id) < 0) { + br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM); + T0_CO(); + } + + } + break; + case 38: { + /* drop */ + (void)T0_POP(); + } + break; + case 39: { + /* dup */ + T0_PUSH(T0_PEEK(0)); + } + break; + case 40: { + /* ext-ALPN-length */ + + size_t u, len; + + if (ENG->protocol_names_num == 0) { + T0_PUSH(0); + T0_RET(); + } + len = 6; + for (u = 0; u < ENG->protocol_names_num; u ++) { + len += 1 + strlen(ENG->protocol_names[u]); + } + T0_PUSH(len); + + } + break; + case 41: { + /* fail */ + + br_ssl_engine_fail(ENG, (int)T0_POPi()); + T0_CO(); + + } + break; + case 42: { + /* flush-record */ + + br_ssl_engine_flush_record(ENG); + + } + break; + case 43: { + /* get-client-chain */ + + uint32_t auth_types; + + auth_types = T0_POP(); + if (CTX->client_auth_vtable != NULL) { + br_ssl_client_certificate ux; + + (*CTX->client_auth_vtable)->choose(CTX->client_auth_vtable, + CTX, auth_types, &ux); + CTX->auth_type = (unsigned char)ux.auth_type; + CTX->hash_id = (unsigned char)ux.hash_id; + ENG->chain = ux.chain; + ENG->chain_len = ux.chain_len; + } else { + CTX->hash_id = 0; + ENG->chain_len = 0; + } + + } + break; + case 44: { + /* get-key-type-usages */ + + const br_x509_class *xc; + const br_x509_pkey *pk; + unsigned usages; + + xc = *(ENG->x509ctx); + pk = xc->get_pkey(ENG->x509ctx, &usages); + if (pk == NULL) { + T0_PUSH(0); + } else { + T0_PUSH(pk->key_type | usages); + } + + } + break; + case 45: { + /* get16 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr)); + + } + break; + case 46: { + /* get32 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr)); + + } + break; + case 47: { + /* get8 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*((unsigned char *)ENG + addr)); + + } + break; + case 48: { + /* has-input? */ + + T0_PUSHi(-(ENG->hlen_in != 0)); + + } + break; + case 49: { + /* memcmp */ + + size_t len = (size_t)T0_POP(); + void *addr2 = (unsigned char *)ENG + (size_t)T0_POP(); + void *addr1 = (unsigned char *)ENG + (size_t)T0_POP(); + int x = memcmp(addr1, addr2, len); + T0_PUSH((uint32_t)-(x == 0)); + + } + break; + case 50: { + /* memcpy */ + + size_t len = (size_t)T0_POP(); + void *src = (unsigned char *)ENG + (size_t)T0_POP(); + void *dst = (unsigned char *)ENG + (size_t)T0_POP(); + memcpy(dst, src, len); + + } + break; + case 51: { + /* mkrand */ + + size_t len = (size_t)T0_POP(); + void *addr = (unsigned char *)ENG + (size_t)T0_POP(); + br_hmac_drbg_generate(&ENG->rng, addr, len); + + } + break; + case 52: { + /* more-incoming-bytes? */ + + T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG)); + + } + break; + case 53: { + /* multihash-init */ + + br_multihash_init(&ENG->mhash); + + } + break; + case 54: { + /* neg */ + + uint32_t a = T0_POP(); + T0_PUSH(-a); + + } + break; + case 55: { + /* not */ + + uint32_t a = T0_POP(); + T0_PUSH(~a); + + } + break; + case 56: { + /* or */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a | b); + + } + break; + case 57: { + /* over */ + T0_PUSH(T0_PEEK(1)); + } + break; + case 58: { + /* peek-hs-msg-type */ + + if (ENG->hlen_in > 0) { + T0_PUSH(*ENG->hbuf_in); + } else { + T0_PUSHi(-1); + } + + } + break; + case 59: { + /* read-chunk-native */ + + size_t clen = ENG->hlen_in; + if (clen > 0) { + uint32_t addr, len; + + len = T0_POP(); + addr = T0_POP(); + if ((size_t)len < clen) { + clen = (size_t)len; + } + memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); + if (ENG->record_type_in == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen); + } + T0_PUSH(addr + (uint32_t)clen); + T0_PUSH(len - (uint32_t)clen); + ENG->hbuf_in += clen; + ENG->hlen_in -= clen; + } + + } + break; + case 60: { + /* read8-native */ + + if (ENG->hlen_in > 0) { + unsigned char x; + + x = *ENG->hbuf_in ++; + if (ENG->record_type_in == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, &x, 1); + } + T0_PUSH(x); + ENG->hlen_in --; + } else { + T0_PUSHi(-1); + } + + } + break; + case 61: { + /* set-server-curve */ + + const br_x509_class *xc; + const br_x509_pkey *pk; + + xc = *(ENG->x509ctx); + pk = xc->get_pkey(ENG->x509ctx, NULL); + CTX->server_curve = + (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0; + + } + break; + case 62: { + /* set16 */ + + size_t addr = (size_t)T0_POP(); + *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP(); + + } + break; + case 63: { + /* set32 */ + + size_t addr = (size_t)T0_POP(); + *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP(); + + } + break; + case 64: { + /* set8 */ + + size_t addr = (size_t)T0_POP(); + *((unsigned char *)ENG + addr) = (unsigned char)T0_POP(); + + } + break; + case 65: { + /* strlen */ + + void *str = (unsigned char *)ENG + (size_t)T0_POP(); + T0_PUSH((uint32_t)strlen(str)); + + } + break; + case 66: { + /* supported-curves */ + + uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves; + T0_PUSH(x); + + } + break; + case 67: { + /* supported-hash-functions */ + + int i; + unsigned x, num; + + x = 0; + num = 0; + for (i = br_sha1_ID; i <= br_sha512_ID; i ++) { + if (br_multihash_getimpl(&ENG->mhash, i)) { + x |= 1U << i; + num ++; + } + } + T0_PUSH(x); + T0_PUSH(num); + + } + break; + case 68: { + /* supports-ecdsa? */ + + T0_PUSHi(-(ENG->iecdsa != 0)); + + } + break; + case 69: { + /* supports-rsa-sign? */ + + T0_PUSHi(-(ENG->irsavrfy != 0)); + + } + break; + case 70: { + /* swap */ + T0_SWAP(); + } + break; + case 71: { + /* switch-aesccm-in */ + + int is_client, prf_id; + unsigned cipher_key_len, tag_len; + + tag_len = T0_POP(); + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id, + ENG->iaes_ctrcbc, cipher_key_len, tag_len); + + } + break; + case 72: { + /* switch-aesccm-out */ + + int is_client, prf_id; + unsigned cipher_key_len, tag_len; + + tag_len = T0_POP(); + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id, + ENG->iaes_ctrcbc, cipher_key_len, tag_len); + + } + break; + case 73: { + /* switch-aesgcm-in */ + + int is_client, prf_id; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id, + ENG->iaes_ctr, cipher_key_len); + + } + break; + case 74: { + /* switch-aesgcm-out */ + + int is_client, prf_id; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id, + ENG->iaes_ctr, cipher_key_len); + + } + break; + case 75: { + /* switch-cbc-in */ + + int is_client, prf_id, mac_id, aes; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + aes = T0_POP(); + mac_id = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id, + aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len); + + } + break; + case 76: { + /* switch-cbc-out */ + + int is_client, prf_id, mac_id, aes; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + aes = T0_POP(); + mac_id = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id, + aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len); + + } + break; + case 77: { + /* switch-chapol-in */ + + int is_client, prf_id; + + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id); + + } + break; + case 78: { + /* switch-chapol-out */ + + int is_client, prf_id; + + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id); + + } + break; + case 79: { + /* test-protocol-name */ + + size_t len = T0_POP(); + size_t u; + + for (u = 0; u < ENG->protocol_names_num; u ++) { + const char *name; + + name = ENG->protocol_names[u]; + if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) { + T0_PUSH(u); + T0_RET(); + } + } + T0_PUSHi(-1); + + } + break; + case 80: { + /* total-chain-length */ + + size_t u; + uint32_t total; + + total = 0; + for (u = 0; u < ENG->chain_len; u ++) { + total += 3 + (uint32_t)ENG->chain[u].data_len; + } + T0_PUSH(total); + + } + break; + case 81: { + /* u>> */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x >> c); + + } + break; + case 82: { + /* verify-SKE-sig */ + + size_t sig_len = T0_POP(); + int use_rsa = T0_POPi(); + int hash = T0_POPi(); + + T0_PUSH(verify_SKE_sig(CTX, hash, use_rsa, sig_len)); + + } + break; + case 83: { + /* write-blob-chunk */ + + size_t clen = ENG->hlen_out; + if (clen > 0) { + uint32_t addr, len; + + len = T0_POP(); + addr = T0_POP(); + if ((size_t)len < clen) { + clen = (size_t)len; + } + memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); + if (ENG->record_type_out == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen); + } + T0_PUSH(addr + (uint32_t)clen); + T0_PUSH(len - (uint32_t)clen); + ENG->hbuf_out += clen; + ENG->hlen_out -= clen; + } + + } + break; + case 84: { + /* write8-native */ + + unsigned char x; + + x = (unsigned char)T0_POP(); + if (ENG->hlen_out > 0) { + if (ENG->record_type_out == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, &x, 1); + } + *ENG->hbuf_out ++ = x; + ENG->hlen_out --; + T0_PUSHi(-1); + } else { + T0_PUSHi(0); + } + + } + break; + case 85: { + /* x509-append */ + + const br_x509_class *xc; + size_t len; + + xc = *(ENG->x509ctx); + len = T0_POP(); + xc->append(ENG->x509ctx, ENG->pad, len); + + } + break; + case 86: { + /* x509-end-cert */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + xc->end_cert(ENG->x509ctx); + + } + break; + case 87: { + /* x509-end-chain */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + T0_PUSH(xc->end_chain(ENG->x509ctx)); + + } + break; + case 88: { + /* x509-start-cert */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + xc->start_cert(ENG->x509ctx, T0_POP()); + + } + break; + case 89: { + /* x509-start-chain */ + + const br_x509_class *xc; + uint32_t bc; + + bc = T0_POP(); + xc = *(ENG->x509ctx); + xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL); + + } + break; + } + + } else { + T0_ENTER(ip, rp, t0x); + } + } +t0_exit: + ((t0_context *)t0ctx)->dp = dp; + ((t0_context *)t0ctx)->rp = rp; + ((t0_context *)t0ctx)->ip = ip; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.t0 b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.t0 new file mode 100644 index 0000000..69a1d94 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_client.t0 @@ -0,0 +1,1398 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +\ ---------------------------------------------------------------------- +\ Handshake processing code, for the client. +\ The common T0 code (ssl_hs_common.t0) shall be read first. + +preamble { + +/* + * This macro evaluates to a pointer to the client context, under that + * specific name. It must be noted that since the engine context is the + * first field of the br_ssl_client_context structure ('eng'), then + * pointers values of both types are interchangeable, modulo an + * appropriate cast. This also means that "addresses" computed as offsets + * within the structure work for both kinds of context. + */ +#define CTX ((br_ssl_client_context *)ENG) + +/* + * Generate the pre-master secret for RSA key exchange, and encrypt it + * with the server's public key. Returned value is either the encrypted + * data length (in bytes), or -x on error, with 'x' being an error code. + * + * This code assumes that the public key has been already verified (it + * was properly obtained by the X.509 engine, and it has the right type, + * i.e. it is of type RSA and suitable for encryption). + */ +static int +make_pms_rsa(br_ssl_client_context *ctx, int prf_id) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + const unsigned char *n; + unsigned char *pms; + size_t nlen, u; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + + /* + * Compute actual RSA key length, in case there are leading zeros. + */ + n = pk->key.rsa.n; + nlen = pk->key.rsa.nlen; + while (nlen > 0 && *n == 0) { + n ++; + nlen --; + } + + /* + * We need at least 59 bytes (48 bytes for pre-master secret, and + * 11 bytes for the PKCS#1 type 2 padding). Note that the X.509 + * minimal engine normally blocks RSA keys shorter than 128 bytes, + * so this is mostly for public keys provided explicitly by the + * caller. + */ + if (nlen < 59) { + return -BR_ERR_X509_WEAK_PUBLIC_KEY; + } + if (nlen > sizeof ctx->eng.pad) { + return -BR_ERR_LIMIT_EXCEEDED; + } + + /* + * Make PMS. + */ + pms = ctx->eng.pad + nlen - 48; + br_enc16be(pms, ctx->eng.version_max); + br_hmac_drbg_generate(&ctx->eng.rng, pms + 2, 46); + br_ssl_engine_compute_master(&ctx->eng, prf_id, pms, 48); + + /* + * Apply PKCS#1 type 2 padding. + */ + ctx->eng.pad[0] = 0x00; + ctx->eng.pad[1] = 0x02; + ctx->eng.pad[nlen - 49] = 0x00; + br_hmac_drbg_generate(&ctx->eng.rng, ctx->eng.pad + 2, nlen - 51); + for (u = 2; u < nlen - 49; u ++) { + while (ctx->eng.pad[u] == 0) { + br_hmac_drbg_generate(&ctx->eng.rng, + &ctx->eng.pad[u], 1); + } + } + + /* + * Compute RSA encryption. + */ + if (!ctx->irsapub(ctx->eng.pad, nlen, &pk->key.rsa)) { + return -BR_ERR_LIMIT_EXCEEDED; + } + return (int)nlen; +} + +/* + * OID for hash functions in RSA signatures. + */ +static const unsigned char *HASH_OID[] = { + BR_HASH_OID_SHA1, + BR_HASH_OID_SHA224, + BR_HASH_OID_SHA256, + BR_HASH_OID_SHA384, + BR_HASH_OID_SHA512 +}; + +/* + * 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 +verify_SKE_sig(br_ssl_client_context *ctx, + int hash, int use_rsa, size_t sig_len) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + br_multihash_context mhc; + unsigned char hv[64], head[4]; + size_t hv_len; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + br_multihash_zero(&mhc); + br_multihash_copyimpl(&mhc, &ctx->eng.mhash); + br_multihash_init(&mhc); + br_multihash_update(&mhc, + ctx->eng.client_random, sizeof ctx->eng.client_random); + br_multihash_update(&mhc, + ctx->eng.server_random, sizeof ctx->eng.server_random); + head[0] = 3; + head[1] = 0; + head[2] = ctx->eng.ecdhe_curve; + head[3] = ctx->eng.ecdhe_point_len; + br_multihash_update(&mhc, head, sizeof head); + br_multihash_update(&mhc, + ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len); + if (hash) { + hv_len = br_multihash_out(&mhc, hash, hv); + if (hv_len == 0) { + return BR_ERR_INVALID_ALGORITHM; + } + } else { + if (!br_multihash_out(&mhc, br_md5_ID, hv) + || !br_multihash_out(&mhc, br_sha1_ID, hv + 16)) + { + return BR_ERR_INVALID_ALGORITHM; + } + hv_len = 36; + } + if (use_rsa) { + unsigned char tmp[64]; + const unsigned char *hash_oid; + + if (hash) { + hash_oid = HASH_OID[hash - 2]; + } else { + hash_oid = NULL; + } + 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->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec, + ctx->eng.pad, sig_len)) + { + return BR_ERR_BAD_SIGNATURE; + } + } + return 0; +} + +/* + * Perform client-side ECDH (or ECDHE). The point that should be sent to + * the server is written in the pad; returned value is either the point + * length (in bytes), or -x on error, with 'x' being an error code. + * + * The point _from_ the server is taken from ecdhe_point[] if 'ecdhe' + * is non-zero, or from the X.509 engine context if 'ecdhe' is zero + * (for static ECDH). + */ +static int +make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) +{ + int curve; + unsigned char key[66], point[133]; + const unsigned char *order, *point_src; + size_t glen, olen, point_len, xoff, xlen; + unsigned char mask; + + if (ecdhe) { + curve = ctx->eng.ecdhe_curve; + point_src = ctx->eng.ecdhe_point; + point_len = ctx->eng.ecdhe_point_len; + } else { + const br_x509_class **xc; + const br_x509_pkey *pk; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + curve = pk->key.ec.curve; + point_src = pk->key.ec.q; + point_len = pk->key.ec.qlen; + } + if ((ctx->eng.iec->supported_curves & ((uint32_t)1 << curve)) == 0) { + return -BR_ERR_INVALID_ALGORITHM; + } + + /* + * We need to generate our key, as a non-zero random value which + * is lower than the curve order, in a "large enough" range. We + * force top bit to 0 and bottom bit to 1, which guarantees that + * the value is in the proper range. + */ + order = ctx->eng.iec->order(curve, &olen); + mask = 0xFF; + while (mask >= order[0]) { + mask >>= 1; + } + br_hmac_drbg_generate(&ctx->eng.rng, key, olen); + key[0] &= mask; + key[olen - 1] |= 0x01; + + /* + * Compute the common ECDH point, whose X coordinate is the + * pre-master secret. + */ + ctx->eng.iec->generator(curve, &glen); + if (glen != point_len) { + return -BR_ERR_INVALID_ALGORITHM; + } + + memcpy(point, point_src, glen); + if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) { + return -BR_ERR_INVALID_ALGORITHM; + } + + /* + * The pre-master secret is the X coordinate. + */ + xoff = ctx->eng.iec->xoff(curve, &xlen); + br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen); + + ctx->eng.iec->mulgen(point, key, olen, curve); + memcpy(ctx->eng.pad, point, glen); + return (int)glen; +} + +/* + * Perform full static ECDH. This occurs only in the context of client + * authentication with certificates: the server uses an EC public key, + * the cipher suite is of type ECDH (not ECDHE), the server requested a + * client certificate and accepts static ECDH, the client has a + * certificate with an EC public key in the same curve, and accepts + * static ECDH as well. + * + * Returned value is 0 on success, -1 on error. + */ +static int +make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id) +{ + unsigned char point[133]; + size_t point_len; + const br_x509_class **xc; + const br_x509_pkey *pk; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + point_len = pk->key.ec.qlen; + if (point_len > sizeof point) { + return -1; + } + memcpy(point, pk->key.ec.q, point_len); + if (!(*ctx->client_auth_vtable)->do_keyx( + ctx->client_auth_vtable, point, &point_len)) + { + return -1; + } + br_ssl_engine_compute_master(&ctx->eng, + prf_id, point, point_len); + 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); +} + +} + +\ ======================================================================= + +: addr-ctx: + next-word { field } + "addr-" field + 0 1 define-word + 0 8191 "offsetof(br_ssl_client_context, " field + ")" + make-CX + 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 +\ extension), or 0 if we know that the server does not support the +\ extension. +: ext-reneg-length ( -- n ) + addr-reneg get8 dup if 1 - 17 * else drop 5 then ; + +\ Length of SNI extension. +: ext-sni-length ( -- len ) + addr-server_name strlen dup if 9 + then ; + +\ Length of Maximum Fragment Length extension. +: ext-frag-length ( -- len ) + addr-log_max_frag_len get8 14 = if 0 else 5 then ; + +\ Length of Signatures extension. +: ext-signatures-length ( -- len ) + supported-hash-functions { num } drop 0 + supports-rsa-sign? if num + then + supports-ecdsa? if num + then + dup if 1 << 6 + then ; + +\ Write supported hash functions ( sign -- ) +: write-hashes + { sign } + supported-hash-functions drop + \ We advertise hash functions in the following preference order: + \ SHA-256 SHA-224 SHA-384 SHA-512 SHA-1 + \ Rationale: + \ -- SHA-256 and SHA-224 are more efficient on 32-bit architectures + \ -- SHA-1 is less than ideally collision-resistant + dup 0x10 and if 4 write8 sign write8 then + dup 0x08 and if 3 write8 sign write8 then + dup 0x20 and if 5 write8 sign write8 then + dup 0x40 and if 6 write8 sign write8 then + 0x04 and if 2 write8 sign write8 then ; + +\ Length of Supported Curves extension. +: ext-supported-curves-length ( -- len ) + supported-curves dup if + 0 { x } + begin dup while + dup 1 and x + >x + 1 >> + repeat + drop x 1 << 6 + + then ; + +\ Length of Supported Point Formats extension. +: ext-point-format-length ( -- len ) + supported-curves if 6 else 0 then ; + +\ Length of ALPN extension. +cc: ext-ALPN-length ( -- len ) { + size_t u, len; + + if (ENG->protocol_names_num == 0) { + T0_PUSH(0); + T0_RET(); + } + len = 6; + for (u = 0; u < ENG->protocol_names_num; u ++) { + len += 1 + strlen(ENG->protocol_names[u]); + } + T0_PUSH(len); +} + +\ Length of Session Ticket extension (RFC 5077). +\ Always sent (to signal support). If we have a stored ticket, include it. +: ext-session-ticket-length ( -- len ) + addr-session_ticket_len get16 4 + ; + +\ Write handshake message: ClientHello +: write-ClientHello ( -- ) + { ; total-ext-length } + + \ Compute length for extensions (without the general two-byte header). + \ This does not take padding extension into account. + ext-reneg-length ext-sni-length + ext-frag-length + + ext-signatures-length + + ext-supported-curves-length + ext-point-format-length + + ext-ALPN-length + + ext-session-ticket-length + + >total-ext-length + + \ ClientHello type + 1 write8 + + \ Compute and write length + 39 addr-session_id_len get8 + addr-suites_num get8 1 << + + total-ext-length if 2+ total-ext-length + then + \ Compute padding (if requested). + addr-min_clienthello_len get16 over - dup 0> if + \ We well add a Pad ClientHello extension, which has its + \ own header (4 bytes) and might be the only extension + \ (2 extra bytes for the extension list header). + total-ext-length ifnot swap 2+ swap 2- then + \ Account for the extension header. + 4 - dup 0< if drop 0 then + \ Adjust total extension length. + dup 4 + total-ext-length + >total-ext-length + \ Adjust ClientHello length. + swap 4 + over + swap + else + drop + -1 + then + { ext-padding-amount } + write24 + + \ Protocol version + addr-version_max get16 write16 + + \ Client random + addr-client_random 4 bzero + addr-client_random 4 + 28 mkrand + addr-client_random 32 write-blob + + \ Session ID + addr-session_id addr-session_id_len get8 write-blob-head8 + + \ Supported cipher suites. We also check here that we indeed + \ support all these suites. + addr-suites_num get8 dup 1 << write16 + addr-suites_buf swap + begin + dup while 1- + over get16 + dup suite-supported? ifnot ERR_BAD_CIPHER_SUITE fail then + write16 + swap 2+ swap + repeat + 2drop + + \ Compression methods (only "null" compression) + 1 write8 0 write8 + + \ Extensions + total-ext-length if + total-ext-length write16 + ext-reneg-length if + 0xFF01 write16 \ extension type (0xFF01) + addr-saved_finished + ext-reneg-length 4 - dup write16 \ extension length + 1- write-blob-head8 \ verify data + then + ext-sni-length if + 0x0000 write16 \ extension type (0) + addr-server_name + ext-sni-length 4 - dup write16 \ extension length + 2 - dup write16 \ ServerNameList length + 0 write8 \ name type: host_name + 3 - write-blob-head16 \ the name itself + then + ext-frag-length if + 0x0001 write16 \ extension type (1) + 0x0001 write16 \ extension length + addr-log_max_frag_len get8 8 - write8 + then + ext-signatures-length if + 0x000D write16 \ extension type (13) + ext-signatures-length 4 - dup write16 \ extension length + 2 - write16 \ list length + supports-ecdsa? if 3 write-hashes then + supports-rsa-sign? if 1 write-hashes then + then + \ TODO: add an API to specify preference order for curves. + \ Right now we send Curve25519 first, then other curves in + \ increasing ID values (hence P-256 in second). + ext-supported-curves-length dup if + 0x000A write16 \ extension type (10) + 4 - dup write16 \ extension length + 2- write16 \ list length + supported-curves 0 + dup 0x20000000 and if + 0xDFFFFFFF and 29 write16 + then + begin dup 32 < while + dup2 >> 1 and if dup write16 then + 1+ + repeat + 2drop + else + drop + then + ext-point-format-length if + 0x000B write16 \ extension type (11) + 0x0002 write16 \ extension length + 0x0100 write16 \ value: 1 format: uncompressed + then + ext-ALPN-length dup if + 0x0010 write16 \ extension type (16) + 4 - dup write16 \ extension length + 2- write16 \ list length + addr-protocol_names_num get16 0 + begin + dup2 > while + dup copy-protocol-name + dup write8 addr-pad swap write-blob + 1+ + repeat + 2drop + else + drop + then + \ Session Ticket extension (RFC 5077). + 0x0023 write16 \ extension type (35) + addr-session_ticket_len get16 + dup write16 \ extension data length + dup if + addr-session_ticket swap write-blob + else + drop + then + ext-padding-amount 0< ifnot + 0x0015 write16 \ extension value (21) + ext-padding-amount + dup write16 \ extension length + begin dup while + 1- 0 write8 repeat \ value (only zeros) + drop + then + then + ; + +\ ======================================================================= + +\ Parse server SNI extension. If present, then it should be empty. +: read-server-sni ( lim -- lim ) + read16 if ERR_BAD_SNI fail then ; + +\ Parse server Max Fragment Length extension. If present, then it should +\ advertise the same length as the client. Note that whether the server +\ sends it or not changes nothing for us: we won't send any record larger +\ than the advertised value anyway, and we will accept incoming records +\ up to our input buffer length. +: read-server-frag ( lim -- lim ) + read16 1 = ifnot ERR_BAD_FRAGLEN fail then + read8 8 + addr-log_max_frag_len get8 = ifnot ERR_BAD_FRAGLEN fail then ; + +\ Parse server Secure Renegotiation extension. This is called only if +\ the client sent that extension, so we only have two cases to +\ distinguish: first handshake, and renegotiation; in the latter case, +\ we know that the server supports the extension, otherwise the client +\ would not have sent it. +: read-server-reneg ( lim -- lim ) + read16 + addr-reneg get8 ifnot + \ "reneg" is 0, so this is a first handshake. The server's + \ extension MUST be empty. We also learn that the server + \ supports the extension. + 1 = ifnot ERR_BAD_SECRENEG fail then + read8 0 = ifnot ERR_BAD_SECRENEG fail then + 2 addr-reneg set8 + else + \ "reneg" is non-zero, and we sent an extension, so it must + \ be 2 and this is a renegotiation. We must verify that + \ the extension contents have length exactly 24 bytes and + \ match the saved client and server "Finished". + 25 = ifnot ERR_BAD_SECRENEG fail then + read8 24 = ifnot ERR_BAD_SECRENEG fail then + addr-pad 24 read-blob + addr-saved_finished addr-pad 24 memcmp ifnot + ERR_BAD_SECRENEG fail + then + then ; + +\ Read the ALPN extension from the server. It must contain a single name, +\ and that name must match one of our names. +: read-ALPN-from-server ( lim -- lim ) + \ Extension contents length. + read16 open-elt + \ Length of list of names. + read16 open-elt + \ There should be a single name. + read8 addr-pad swap dup { len } read-blob + close-elt + close-elt + len test-protocol-name dup 0< if + 3 flag? if ERR_UNEXPECTED fail then + drop + else + 1+ addr-selected_protocol set16 + then ; + +\ Save a value in a 16-bit field, or check it in case of session resumption. +: check-resume ( val addr resume -- ) + if get16 = ifnot ERR_RESUME_MISMATCH fail then else set16 then ; + +cc: DEBUG-BLOB ( addr len -- ) { + extern int printf(const char *fmt, ...); + + size_t len = T0_POP(); + unsigned char *buf = (unsigned char *)CTX + T0_POP(); + size_t u; + + printf("BLOB:"); + for (u = 0; u < len; u ++) { + if (u % 16 == 0) { + printf("\n "); + } + printf(" %02x", buf[u]); + } + printf("\n"); +} + +\ Parse incoming ServerHello. Returned value is true (-1) on session +\ resumption. +: read-ServerHello ( -- bool ) + \ Get header, and check message type. + read-handshake-header 2 = ifnot ERR_UNEXPECTED fail then + + \ Get protocol version. + read16 { version } + version addr-version_min get16 < version addr-version_max get16 > or if + ERR_UNSUPPORTED_VERSION fail + then + + \ Enforce chosen version for subsequent records in both directions. + version addr-version_in get16 <> if ERR_BAD_VERSION fail then + version addr-version_out set16 + + \ Server random. + addr-server_random 32 read-blob + + \ The "session resumption" flag. + 0 { resume } + + \ Session ID. + read8 { idlen } + idlen 32 > if ERR_OVERSIZED_ID fail then + addr-pad idlen read-blob + idlen addr-session_id_len get8 = idlen 0 > and if + addr-session_id addr-pad idlen memcmp if + \ Server session ID is non-empty and matches what + \ we sent, so this is a session resumption. + -1 >resume + then + then + addr-session_id addr-pad idlen memcpy + idlen addr-session_id_len set8 + + \ Record version. + version addr-version resume check-resume + + \ Cipher suite. We check that it is part of the list of cipher + \ suites that we advertised. + read16 + dup scan-suite 0< if ERR_BAD_CIPHER_SUITE fail then + \ Also check that the cipher suite is compatible with the + \ announced version: suites that don't use HMAC/SHA-1 are + \ for TLS-1.2 only, not older versions. + dup use-tls12? version 0x0303 < and if ERR_BAD_CIPHER_SUITE fail then + addr-cipher_suite resume check-resume + + \ Compression method. Should be 0 (no compression). + read8 if ERR_BAD_COMPRESSION fail then + + \ Parse extensions (if any). If there is no extension, then the + \ read limit (on the TOS) should be 0 at that point. + dup if + \ Length of extension list. + \ message size. + read16 open-elt + + \ Enumerate extensions. For each of them, check that we + \ sent an extension of that type, and did not see it + \ yet; and then process it. + ext-sni-length { ok-sni } + ext-reneg-length { ok-reneg } + ext-frag-length { ok-frag } + ext-signatures-length { ok-signatures } + ext-supported-curves-length { ok-curves } + ext-point-format-length { ok-points } + ext-session-ticket-length { ok-session-ticket } + ext-ALPN-length { ok-ALPN } + begin dup while + read16 + case + \ Server Name Indication. The server may + \ send such an extension if it uses the SNI + \ from the client, but that "response + \ extension" is supposed to be empty. + 0x0000 of + ok-sni ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-sni + read-server-sni + endof + + \ Max Frag Length. The contents shall be + \ a single byte whose value matches the one + \ sent by the client. + 0x0001 of + ok-frag ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-frag + read-server-frag + endof + + \ Secure Renegotiation. + 0xFF01 of + ok-reneg ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-reneg + read-server-reneg + endof + + \ Signature Algorithms. + \ Normally, the server should never send this + \ extension (so says RFC 5246 #7.4.1.4.1), + \ but some existing servers do. + 0x000D of + ok-signatures ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-signatures + read-ignore-16 + endof + + \ Supported Curves. + 0x000A of + ok-curves ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-curves + read-ignore-16 + endof + + \ Supported Point Formats. + 0x000B of + ok-points ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-points + read-ignore-16 + endof + + \ ALPN. + 0x0010 of + ok-ALPN ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-ALPN + read-ALPN-from-server + endof + + \ Session Ticket (RFC 5077). + 0x0023 of + ok-session-ticket ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-session-ticket + read-ignore-16 + 1 addr-session_ticket_ok set8 + endof + + ERR_EXTRA_EXTENSION fail + endcase + repeat + + \ If we sent a secure renegotiation extension but did not + \ receive a response, then the server does not support + \ secure renegotiation. This is a hard failure if this + \ is a renegotiation. + ok-reneg if + ok-reneg 5 > if ERR_BAD_SECRENEG fail then + 1 addr-reneg set8 + then + close-elt + else + \ No extension received at all, so the server does not + \ support secure renegotiation. This is a hard failure + \ if the server was previously known to support it (i.e. + \ this is a renegotiation). + ext-reneg-length 5 > if ERR_BAD_SECRENEG fail then + 1 addr-reneg set8 + then + close-elt + resume + ; + +cc: set-server-curve ( -- ) { + const br_x509_class *xc; + const br_x509_pkey *pk; + + xc = *(ENG->x509ctx); + pk = xc->get_pkey(ENG->x509ctx, NULL); + CTX->server_curve = + (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0; +} + +\ Read Certificate message from server. +: read-Certificate-from-server ( -- ) + addr-cipher_suite get16 expected-key-type + -1 read-Certificate + dup 0< if neg fail then + dup ifnot ERR_UNEXPECTED fail then + over and <> if ERR_WRONG_KEY_USAGE fail then + + \ 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) +\ 'use-rsa' is 0 for ECDSA, -1 for for RSA +\ 'sig-len' is the signature length (in bytes) +\ The signature itself is in the pad. +cc: verify-SKE-sig ( hash use-rsa sig-len -- err ) { + size_t sig_len = T0_POP(); + int use_rsa = T0_POPi(); + int hash = T0_POPi(); + + T0_PUSH(verify_SKE_sig(CTX, hash, use_rsa, sig_len)); +} + +\ Parse ServerKeyExchange +: read-ServerKeyExchange ( -- ) + \ Get header, and check message type. + read-handshake-header 12 = ifnot ERR_UNEXPECTED fail then + + \ We expect a named curve, and we must support it. + read8 3 = ifnot ERR_INVALID_ALGORITHM fail then + read16 dup addr-ecdhe_curve set8 + dup 32 >= if ERR_INVALID_ALGORITHM fail then + supported-curves swap >> 1 and ifnot ERR_INVALID_ALGORITHM fail then + + \ Read the server point. + read8 + dup 133 > if ERR_INVALID_ALGORITHM fail then + dup addr-ecdhe_point_len set8 + addr-ecdhe_point swap read-blob + + \ If using TLS-1.2+, then the hash function and signature algorithm + \ are explicitly provided; the signature algorithm must match what + \ the cipher suite specifies. With TLS-1.0 and 1.1, the signature + \ algorithm is inferred from the cipher suite, and the hash is + \ either MD5+SHA-1 (for RSA signatures) or SHA-1 (for ECDSA). + addr-version get16 0x0303 >= { tls1.2+ } + addr-cipher_suite get16 use-rsa-ecdhe? { use-rsa } + 2 { hash } + tls1.2+ if + \ Read hash function; accept only the SHA-* identifiers + \ (from SHA-1 to SHA-512, no MD5 here). + read8 + dup dup 2 < swap 6 > or if ERR_INVALID_ALGORITHM fail then + >hash + read8 + \ Get expected signature algorithm and compare with what + \ the server just sent. Expected value is 1 for RSA, 3 + \ for ECDSA. Note that 'use-rsa' evaluates to -1 for RSA, + \ 0 for ECDSA. + use-rsa 1 << 3 + = ifnot ERR_INVALID_ALGORITHM fail then + else + \ For MD5+SHA-1, we set 'hash' to 0. + use-rsa if 0 >hash then + then + + \ Read signature into the pad. + read16 dup { sig-len } + + dup 512 > if ERR_LIMIT_EXCEEDED fail then + addr-pad swap read-blob + + \ Verify signature. + hash use-rsa sig-len verify-SKE-sig + dup if fail then drop + + 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 -- ) + \ Read supported client authentication 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 set32 + + \ 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 ; + +cc: do-rsa-encrypt ( prf_id -- nlen ) { + int x; + + x = make_pms_rsa(CTX, T0_POP()); + if (x < 0) { + br_ssl_engine_fail(ENG, -x); + T0_CO(); + } else { + T0_PUSH(x); + } +} + +cc: do-ecdh ( echde prf_id -- ulen ) { + unsigned prf_id = T0_POP(); + unsigned ecdhe = T0_POP(); + int x; + + x = make_pms_ecdh(CTX, ecdhe, prf_id); + if (x < 0) { + br_ssl_engine_fail(ENG, -x); + T0_CO(); + } else { + T0_PUSH(x); + } +} + +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 + dup use-rsa-keyx? if + prf-id do-rsa-encrypt + dup 2+ write24 + dup write16 + addr-pad swap write-blob + else + dup use-ecdhe? swap prf-id do-ecdh + dup 1+ write24 + dup write8 + 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 ; + +\ ======================================================================= + +\ Peek at the first byte of the handshake input buffer without consuming +\ it. Returns the byte value, or -1 if the buffer is empty. +cc: peek-hs-msg-type ( -- type ) { + if (ENG->hlen_in > 0) { + T0_PUSH(*ENG->hbuf_in); + } else { + T0_PUSHi(-1); + } +} + +\ Read a NewSessionTicket message (handshake type 4, RFC 5077). +\ Format: uint32 lifetime_hint, opaque ticket<0..2^16-1> +cc: debug-session-ticket ( len -- ) { + extern void __stdcall OutputDebugStringA(const char *); + extern int sprintf(char *, const char *, ...); + char buf[80]; + size_t len = T0_POP(); + sprintf(buf, "BearSSL: NewSessionTicket received (%u bytes)\r\n", + (unsigned)len); + OutputDebugStringA(buf); +} + +: read-NewSessionTicket-message ( -- ) + read-handshake-header 4 = ifnot ERR_UNEXPECTED fail then + \ Skip the 4-byte lifetime_hint. + read16 drop read16 drop + \ Read ticket length, then ticket data. + read16 { tlen } + tlen 1024 > if + \ Ticket too large for our buffer; skip it. + tlen skip-blob + 0 addr-session_ticket_len set16 + else + addr-session_ticket tlen read-blob + tlen addr-session_ticket_len set16 + then + tlen debug-session-ticket + close-elt ; + +\ Read optional NewSessionTicket (RFC 5077) then CCS+Finished. +\ During abbreviated handshakes the server MAY send a renewed ticket +\ before CCS, but it is not guaranteed. We peek at the next record +\ type: if it is a handshake record we read the ticket; if it is CCS +\ we skip straight to read-CCS-Finished. +: read-CCS-Finished-with-ticket ( is-client -- ) + addr-session_ticket_ok get8 if + has-input? if + addr-record_type_in get8 22 = if + read-NewSessionTicket-message + then + else + begin + wait-co 0x07 and + dup 0x01 = if + drop read-NewSessionTicket-message 0 + then + dup 0x02 <> while + dup if ERR_UNEXPECTED fail then + drop + repeat + drop + then + then + read-CCS-Finished ; + +\ Perform a handshake. +: do-handshake ( -- ) + 0 addr-application_data set8 + 22 addr-record_type_out set8 + 0 addr-selected_protocol set16 + 0 addr-session_ticket_ok set8 + multihash-init + + write-ClientHello + flush-record + read-ServerHello + + \ Track whether this is a ticket-based resumption detected by + \ peeking at the next server message (RFC 5077). + 0 { ticket-resume } + + ifnot + \ Not a session ID resumption. Check for ticket-based + \ resumption: if we sent a ticket and the server confirmed + \ ticket support, peek at the next record to decide. + addr-session_ticket_ok get8 + addr-session_ticket_len get16 0 > and if + \ Wait for data from server. + has-input? not if + begin wait-co 0x07 and dup 0= while + drop repeat drop + then + addr-record_type_in get8 20 = if + \ CCS → ticket resumption, no renewed ticket. + -1 >ticket-resume + else + \ Handshake record. Peek at message type. + peek-hs-msg-type 4 = if + \ NewSessionTicket → ticket resumption + \ with a renewed ticket. + read-NewSessionTicket-message + -1 >ticket-resume + then + then + then + else + -1 >ticket-resume + then + + ticket-resume if + \ Session resumption (session-ID or ticket-based). + -1 read-CCS-Finished-with-ticket + -1 write-CCS-Finished + else + \ Full handshake. + + \ 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. + addr-cipher_suite get16 expected-key-type + CX 0 63 { BR_KEYTYPE_SIGN } and if + read-ServerKeyExchange + then + + \ Get next header. + read-handshake-header + + \ If this is a CertificateRequest, parse it, then read + \ next header. + dup 13 = if + drop read-contents-CertificateRequest + read-handshake-header + -1 + else + 0 + then + { seen-CR } + + \ At that point, we should have a ServerHelloDone, + \ whose length must be 0. + 14 = ifnot ERR_UNEXPECTED fail then + if ERR_BAD_HELLO_DONE fail then + + \ There should not be more bytes in the record at that point. + more-incoming-bytes? if ERR_UNEXPECTED fail then + + seen-CR if + \ If the server requested a client certificate, then + \ we must write a Certificate message (it may be + \ empty). + write-Certificate + + \ If using static ECDH, then the ClientKeyExchange + \ is empty, and there is no CertificateVerify. + \ Otherwise, there is a ClientKeyExchange; there + \ will then be a CertificateVerify if a client chain + \ was indeed sent. + addr-hash_id get8 0xFF = if + drop + 16 write8 0 write24 + addr-cipher_suite get16 prf-id do-static-ecdh + else + write-ClientKeyExchange + if write-CertificateVerify then + then + else + write-ClientKeyExchange + then + + -1 write-CCS-Finished + -1 read-CCS-Finished-with-ticket + then + + \ Now we should be invoked only in case of renegotiation. + 1 addr-application_data set8 + 23 addr-record_type_out set8 ; + +\ Read a HelloRequest message. +: read-HelloRequest ( -- ) + \ A HelloRequest has length 0 and type 0. + read-handshake-header-core + if ERR_UNEXPECTED fail then + if ERR_BAD_HANDSHAKE fail then ; + +\ Entry point. +: main ( -- ! ) + \ Perform initial handshake. + do-handshake + + begin + \ Wait for further invocation. At that point, we should + \ get either an explicit call for renegotiation, or + \ an incoming HelloRequest handshake message. + wait-co + dup 0x07 and case + 0x00 of + 0x10 and if + do-handshake + then + endof + 0x01 of + drop + 0 addr-application_data set8 + read-HelloRequest + \ Reject renegotiations if the peer does not + \ support secure renegotiation, or if the + \ "no renegotiation" flag is set. + addr-reneg get8 1 = 1 flag? or if + flush-record + begin can-output? not while + wait-co drop + repeat + 100 send-warning + \ We rejected the renegotiation, + \ but the connection is not dead. + \ We must set back things into + \ working "application data" state. + 1 addr-application_data set8 + 23 addr-record_type_out set8 + else + do-handshake + then + endof + ERR_UNEXPECTED fail + endcase + again + ; diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_hs_common.t0 b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_common.t0 new file mode 100644 index 0000000..06c3d15 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_common.t0 @@ -0,0 +1,1385 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +\ ---------------------------------------------------------------------- +\ This is the common T0 code for processing handshake messages (code that +\ is used by both client and server). + +preamble { + +#include +#include + +#include "inner.h" + +/* + * This macro evaluates to a pointer to the current engine context. + */ +#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu))) + +} + +\ IMPLEMENTATION NOTES +\ ==================== +\ +\ This code handles all records except application data records. +\ Application data is accepted (incoming records, outgoing payload data) +\ only when the application_data flag is set, which is done at the end +\ of the handshake; and it is cleared whenever a renegotiation or a +\ closure takes place. +\ +\ Incoming alerts are processed on the fly; fatal alerts terminate the +\ context, while warnings are ignored, except for close_notify, which +\ triggers the closure procedure. That procedure never returns (it ends +\ with an 'ERR_OK fail' call). We can thus make this processing right +\ into the read functions. +\ +\ Specific actions from the caller (closure or renegotiation) may happen +\ only when jumping back into the T0 code, i.e. just after a 'co' call. +\ Similarly, incoming record type may change only while the caller has +\ control, so we need to check that type only when returning from a 'co'. +\ +\ The handshake processor needs to defer back to the caller ('co') only +\ in one of the following situations: +\ +\ -- Some handshake data is expected. +\ +\ -- The handshake is finished, and application data may flow. There may +\ be some incoming handshake data (HelloRequest from the server). This +\ is the only situation where a renegotiation call won't be ignored. +\ +\ -- Some change-cipher-spec data is expected. +\ +\ -- An alert record is expected. Other types of incoming records will be +\ skipped. +\ +\ -- Waiting for the currently accumulated record to be sent and the +\ output buffer to become free again for another record. + +\ Placeholder for handling not yet implemented functionalities. +: NYI ( -- ! ) + "NOT YET IMPLEMENTED!" puts cr -1 fail ; + +\ Debug function that prints a string (and a newline) on stderr. +cc: DBG ( addr -- ) { + extern void *stderr; + extern int fprintf(void *, const char *, ...); + fprintf(stderr, "%s\n", &t0_datablock[T0_POPi()]); +} + +\ Debug function that prints a string and an integer value (followed +\ by a newline) on stderr. +cc: DBG2 ( addr x -- ) { + extern void *stderr; + extern int fprintf(void *, const char *, ...); + int32_t x = T0_POPi(); + fprintf(stderr, "%s: %ld (0x%08lX)\n", + &t0_datablock[T0_POPi()], (long)x, (unsigned long)(uint32_t)x); +} + +\ Mark the context as failed with a specific error code. This also +\ returns control to the caller. +cc: fail ( err -- ! ) { + br_ssl_engine_fail(ENG, (int)T0_POPi()); + T0_CO(); +} + +\ Read a byte from the context (address is offset in context). +cc: get8 ( addr -- val ) { + size_t addr = (size_t)T0_POP(); + T0_PUSH(*((unsigned char *)ENG + addr)); +} + +\ Read a 16-bit word from the context (address is offset in context). +cc: get16 ( addr -- val ) { + size_t addr = (size_t)T0_POP(); + T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr)); +} + +\ Read a 32-bit word from the context (address is offset in context). +cc: get32 ( addr -- val ) { + size_t addr = (size_t)T0_POP(); + T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr)); +} + +\ Set a byte in the context (address is offset in context). +cc: set8 ( val addr -- ) { + size_t addr = (size_t)T0_POP(); + *((unsigned char *)ENG + addr) = (unsigned char)T0_POP(); +} + +\ Set a 16-bit word in the context (address is offset in context). +cc: set16 ( val addr -- ) { + size_t addr = (size_t)T0_POP(); + *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP(); +} + +\ Set a 32-bit word in the context (address is offset in context). +cc: set32 ( val addr -- ) { + size_t addr = (size_t)T0_POP(); + *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP(); +} + +\ Define a word that evaluates as an address of a field within the +\ engine context. The field name (C identifier) must follow in the +\ source. For field 'foo', the defined word is 'addr-foo'. +: addr-eng: + next-word { field } + "addr-" field + 0 1 define-word + 0 8191 "offsetof(br_ssl_engine_context, " field + ")" + make-CX + postpone literal postpone ; ; + +addr-eng: max_frag_len +addr-eng: log_max_frag_len +addr-eng: peer_log_max_frag_len +addr-eng: shutdown_recv +addr-eng: record_type_in +addr-eng: record_type_out +addr-eng: version_in +addr-eng: version_out +addr-eng: application_data +addr-eng: version_min +addr-eng: version_max +addr-eng: suites_buf +addr-eng: suites_num +addr-eng: server_name +addr-eng: client_random +addr-eng: server_random +addr-eng: ecdhe_curve +addr-eng: ecdhe_point +addr-eng: ecdhe_point_len +addr-eng: reneg +addr-eng: saved_finished +addr-eng: flags +addr-eng: pad +addr-eng: action +addr-eng: alert +addr-eng: close_received +addr-eng: protocol_names_num +addr-eng: selected_protocol +addr-eng: session_ticket_ok + +\ Similar to 'addr-eng:', for fields in the 'session' substructure. +: addr-session-field: + next-word { field } + "addr-" field + 0 1 define-word + 0 8191 "offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, " field + ")" + make-CX + postpone literal postpone ; ; + +addr-session-field: session_id +addr-session-field: session_id_len +addr-session-field: version +addr-session-field: cipher_suite +addr-session-field: master_secret +addr-session-field: session_ticket +addr-session-field: session_ticket_len + +\ Check a server flag by index. +: flag? ( index -- bool ) + addr-flags get32 swap >> 1 and neg ; + +\ Define a word that evaluates to an error constant. This assumes that +\ all relevant error codes are in the 0..63 range. +: err: + next-word { name } + name 0 1 define-word + 0 63 "BR_" name + make-CX postpone literal postpone ; ; + +err: ERR_OK +err: ERR_BAD_PARAM +err: ERR_BAD_STATE +err: ERR_UNSUPPORTED_VERSION +err: ERR_BAD_VERSION +err: ERR_BAD_LENGTH +err: ERR_TOO_LARGE +err: ERR_BAD_MAC +err: ERR_NO_RANDOM +err: ERR_UNKNOWN_TYPE +err: ERR_UNEXPECTED +err: ERR_BAD_CCS +err: ERR_BAD_ALERT +err: ERR_BAD_HANDSHAKE +err: ERR_OVERSIZED_ID +err: ERR_BAD_CIPHER_SUITE +err: ERR_BAD_COMPRESSION +err: ERR_BAD_FRAGLEN +err: ERR_BAD_SECRENEG +err: ERR_EXTRA_EXTENSION +err: ERR_BAD_SNI +err: ERR_BAD_HELLO_DONE +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 ) { + uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves; + T0_PUSH(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; + + x = 0; + num = 0; + for (i = br_sha1_ID; i <= br_sha512_ID; i ++) { + if (br_multihash_getimpl(&ENG->mhash, i)) { + x |= 1U << i; + num ++; + } + } + T0_PUSH(x); + 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); +} + +\ Flush the current record: if some payload data has been accumulated, +\ close the record and schedule it for sending. If there is no such data, +\ this function does nothing. +cc: flush-record ( -- ) { + br_ssl_engine_flush_record(ENG); +} + +\ Yield control to the caller. +\ When the control is returned to us, react to the new context. Returned +\ value is a bitwise combination of the following: +\ 0x01 handshake data is available +\ 0x02 change-cipher-spec data is available +\ 0x04 some data other than handshake or change-cipher-spec is available +\ 0x08 output buffer is ready for a new outgoing record +\ 0x10 renegotiation is requested and not to be ignored +\ Flags 0x01, 0x02 and 0x04 are mutually exclusive. +: wait-co ( -- state ) + co + 0 + addr-action get8 dup if + case + 1 of 0 do-close endof + 2 of addr-application_data get8 1 = if + 0x10 or + then endof + endcase + else + drop + then + addr-close_received get8 ifnot + has-input? if + addr-record_type_in get8 case + + \ ChangeCipherSpec + 20 of 0x02 or endof + + \ Alert -- if close_notify received, trigger + \ the closure sequence. + 21 of process-alerts if -1 do-close then endof + + \ Handshake + 22 of 0x01 or endof + + \ Not CCS, Alert or Handshake. + drop 0x04 or 0 + endcase + then + then + can-output? if 0x08 or then ; + +\ Send an alert message. This shall be called only when there is room for +\ an outgoing record. +: send-alert ( level alert -- ) + 21 addr-record_type_out set8 + swap write8-native drop write8-native drop + flush-record ; + +\ Send an alert message of level "warning". This shall be called only when +\ there is room for an outgoing record. +: send-warning ( alert -- ) + 1 swap send-alert ; + +\ Fail by sending a fatal alert. +: fail-alert ( alert -- ! ) + { alert } + flush-record + begin can-output? not while wait-co drop repeat + 2 alert send-alert + begin can-output? not while wait-co drop repeat + alert 512 + fail ; + +\ Perform the close operation: +\ -- Prevent new application data from the caller. +\ -- Incoming data is discarded (except alerts). +\ -- Outgoing data is flushed. +\ -- A close_notify alert is sent. +\ -- If 'cnr' is zero, then incoming data is discarded until a close_notify +\ is received. +\ -- At the end, the context is terminated. +\ +\ cnr shall be either 0 or -1. +: do-close ( cnr -- ! ) + \ 'cnr' is set to non-zero when a close_notify is received from + \ the peer. + { cnr } + + \ Get out of application data state. If we were accepting + \ application data (flag is 1), and we still expect a close_notify + \ from the peer (cnr is 0), then we should set the flag to 2. + \ In all other cases, flag should be set to 0. + addr-application_data get8 cnr not and 1 << addr-application_data set8 + + \ Flush existing payload if any. + flush-record + + \ Wait for room to send the close_notify. Since individual records + \ can always hold at least 512 bytes, we know that when there is + \ room, then there is room for a complete close_notify (two bytes). + begin can-output? not while cnr wait-for-close >cnr repeat + + \ Write the close_notify and flush it. + \ 21 addr-record_type_out set8 + \ 1 write8-native 0 write8-native 2drop + \ flush-record + 0 send-warning + + \ Loop until our record has been sent (we know it's gone when + \ writing is again possible) and a close_notify has been received. + cnr + begin + dup can-output? and if ERR_OK fail then + wait-for-close + again ; + +\ Yield control to the engine, with a possible flush. If 'cnr' is 0, +\ then input is analysed: all input is discarded, until a close_notify +\ is received. +: wait-for-close ( cnr -- cnr ) + co + dup ifnot + has-input? if + addr-record_type_in get8 21 = if + drop process-alerts + \ If we received a close_notify then we + \ no longer accept incoming application + \ data records. + 0 addr-application_data set8 + else + discard-input + then + then + then ; + +\ Test whether there is some accumulated payload that still needs to be +\ sent. +cc: payload-to-send? ( -- bool ) { + T0_PUSHi(-br_ssl_engine_has_pld_to_send(ENG)); +} + +\ Test whether there is some available input data. +cc: has-input? ( -- bool ) { + T0_PUSHi(-(ENG->hlen_in != 0)); +} + +\ Test whether some payload bytes may be written. +cc: can-output? ( -- bool ) { + T0_PUSHi(-(ENG->hlen_out > 0)); +} + +\ Discard current input entirely. +cc: discard-input ( -- ) { + ENG->hlen_in = 0; +} + +\ Low-level read for one byte. If there is no available byte right +\ away, then -1 is returned. Otherwise, the byte value is returned. +\ If the current record type is "handshake" then the read byte is also +\ injected in the multi-hasher. +cc: read8-native ( -- x ) { + if (ENG->hlen_in > 0) { + unsigned char x; + + x = *ENG->hbuf_in ++; + if (ENG->record_type_in == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, &x, 1); + } + T0_PUSH(x); + ENG->hlen_in --; + } else { + T0_PUSHi(-1); + } +} + +\ Low-level read for several bytes. On entry, this expects an address +\ (offset in the engine context) and a length; these values designate +\ where the chunk should go. Upon exit, the new address and length +\ are pushed; that output length contains how many bytes could not be +\ read. If there is no available byte for reading, the address and +\ length are unchanged. +\ If the current record type is "handshake" then the read bytes are +\ injected in the multi-hasher. +cc: read-chunk-native ( addr len -- addr len ) { + size_t clen = ENG->hlen_in; + if (clen > 0) { + uint32_t addr, len; + + len = T0_POP(); + addr = T0_POP(); + if ((size_t)len < clen) { + clen = (size_t)len; + } + memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); + if (ENG->record_type_in == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen); + } + T0_PUSH(addr + (uint32_t)clen); + T0_PUSH(len - (uint32_t)clen); + ENG->hbuf_in += clen; + ENG->hlen_in -= clen; + } +} + +\ Process available alert bytes. If a fatal alert is received, then the +\ context is terminated; otherwise, this returns either true (-1) if a +\ close_notify was received, false (0) otherwise. +: process-alerts ( -- bool ) + 0 + begin has-input? while read8-native process-alert-byte or repeat + dup if 1 addr-shutdown_recv set8 then ; + +\ Process an alert byte. Returned value is non-zero if this is a close_notify, +\ zero otherwise. +: process-alert-byte ( x -- bool ) + addr-alert get8 case + 0 of + \ 'alert' field is 0, so this byte shall be a level. + \ Levels shall be 1 (warning) or 2 (fatal); we convert + \ all other values to "fatal". + dup 1 <> if drop 2 then + addr-alert set8 0 + endof + 1 of + 0 addr-alert set8 + \ close_notify has value 0. + \ no_renegotiation has value 100, and we treat it + \ as a fatal alert. + dup 100 = if 256 + fail then + 0= + endof + \ Fatal alert implies context termination. + drop 256 + fail + endcase ; + +\ In general we only deal with handshake data here. Alerts are processed +\ in specific code right when they are received, and ChangeCipherSpec has +\ its own handling code. So we need to check that the data is "handshake" +\ only when returning from a coroutine call. + +\ Yield control to the engine. Alerts are processed; if incoming data is +\ neither handshake or alert, then an error is triggered. +: wait-for-handshake ( -- ) + wait-co 0x07 and 0x01 > if ERR_UNEXPECTED fail then ; + +\ Flush outgoing data (if any), then wait for the output buffer to be +\ clear; when this is done, set the output record type to the specified +\ value. +: wait-rectype-out ( rectype -- ) + { rectype } + flush-record + begin + can-output? if rectype addr-record_type_out set8 ret then + wait-co drop + again ; + +\ Read one byte of handshake data. Block until that byte is available. +\ This does not check any length. +: read8-nc ( -- x ) + begin + read8-native dup 0< ifnot ret then + drop wait-for-handshake + again ; + +\ Test whether there are some more bytes in the current record. These +\ bytes have not necessarily been received yet (processing of unencrypted +\ records may begin before all bytes are received). +cc: more-incoming-bytes? ( -- bool ) { + T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG)); +} + +\ For reading functions, the TOS is supposed to contain the number of bytes +\ that can still be read (from encapsulating structure header), and it is +\ updated. + +: check-len ( lim len -- lim ) + - dup 0< if ERR_BAD_PARAM fail then ; + +\ Read one byte of handshake data. This pushes an integer in the 0..255 range. +: read8 ( lim -- lim x ) + 1 check-len read8-nc ; + +\ Read a 16-bit value (in the 0..65535 range) +: read16 ( lim -- lim n ) + 2 check-len read8-nc 8 << read8-nc + ; + +\ Read a 24-bit value (in the 0..16777215 range) +: read24 ( lim -- lim n ) + 3 check-len read8-nc 8 << read8-nc + 8 << read8-nc + ; + +\ Read some bytes. The "address" is an offset within the context +\ structure. +: read-blob ( lim addr len -- lim ) + { addr len } + len check-len + addr len + begin + read-chunk-native + dup 0 = if 2drop ret then + wait-for-handshake + again ; + +\ Read some bytes and drop them. +: skip-blob ( lim len -- lim ) + swap over check-len swap + begin dup while read8-nc drop 1- repeat + drop ; + +\ Read a 16-bit length, then skip exactly that many bytes. +: read-ignore-16 ( lim -- lim ) + read16 skip-blob ; + +\ Open a substructure: the inner structure length is checked against, +\ and subtracted, from the output structure current limit. +: open-elt ( lim len -- lim-outer lim-inner ) + dup { len } + - dup 0< if ERR_BAD_PARAM fail then + len ; + +\ Close the current structure. This checks that the limit is 0. +: close-elt ( lim -- ) + if ERR_BAD_PARAM fail then ; + +\ Write one byte of handshake data. +: write8 ( n -- ) + begin + dup write8-native if drop ret then + wait-co drop + again ; + +\ Low-level write for one byte. On exit, it pushes either -1 (byte was +\ written) or 0 (no room in output buffer). +cc: write8-native ( x -- bool ) { + unsigned char x; + + x = (unsigned char)T0_POP(); + if (ENG->hlen_out > 0) { + if (ENG->record_type_out == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, &x, 1); + } + *ENG->hbuf_out ++ = x; + ENG->hlen_out --; + T0_PUSHi(-1); + } else { + T0_PUSHi(0); + } +} + +\ Write a 16-bit value. +: write16 ( n -- ) + dup 8 u>> write8 write8 ; + +\ Write a 24-bit value. +: write24 ( n -- ) + dup 16 u>> write8 write16 ; + +\ Write some bytes. The "address" is an offset within the context +\ structure. +: write-blob ( addr len -- ) + begin + write-blob-chunk + dup 0 = if 2drop ret then + wait-co drop + again ; + +cc: write-blob-chunk ( addr len -- addr len ) { + size_t clen = ENG->hlen_out; + if (clen > 0) { + uint32_t addr, len; + + len = T0_POP(); + addr = T0_POP(); + if ((size_t)len < clen) { + clen = (size_t)len; + } + memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); + if (ENG->record_type_out == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen); + } + T0_PUSH(addr + (uint32_t)clen); + T0_PUSH(len - (uint32_t)clen); + ENG->hbuf_out += clen; + ENG->hlen_out -= clen; + } +} + +\ Write a blob with the length as header (over one byte) +: write-blob-head8 ( addr len -- ) + dup write8 write-blob ; + +\ Write a blob with the length as header (over two bytes) +: write-blob-head16 ( addr len -- ) + dup write16 write-blob ; + +\ Perform a byte-to-byte comparison between two blobs. Each blob is +\ provided as an "address" (offset in the context structure); the +\ length is common. Returned value is true (-1) if the two blobs are +\ equal, false (0) otherwise. +cc: memcmp ( addr1 addr2 len -- bool ) { + size_t len = (size_t)T0_POP(); + void *addr2 = (unsigned char *)ENG + (size_t)T0_POP(); + void *addr1 = (unsigned char *)ENG + (size_t)T0_POP(); + int x = memcmp(addr1, addr2, len); + T0_PUSH((uint32_t)-(x == 0)); +} + +\ Copy bytes between two areas, whose addresses are provided as +\ offsets in the context structure. +cc: memcpy ( dst src len -- ) { + size_t len = (size_t)T0_POP(); + void *src = (unsigned char *)ENG + (size_t)T0_POP(); + void *dst = (unsigned char *)ENG + (size_t)T0_POP(); + memcpy(dst, src, len); +} + +\ Get string length (zero-terminated). The string address is provided as +\ an offset relative to the context start. Returned length does not include +\ the terminated 0. +cc: strlen ( str -- len ) { + void *str = (unsigned char *)ENG + (size_t)T0_POP(); + T0_PUSH((uint32_t)strlen(str)); +} + +\ Fill a buffer with zeros. The buffer address is an offset in the context. +cc: bzero ( addr len -- ) { + size_t len = (size_t)T0_POP(); + void *addr = (unsigned char *)ENG + (size_t)T0_POP(); + memset(addr, 0, len); +} + +\ Scan the list of supported cipher suites for a given value. If found, +\ then the list index at which it was found is returned; otherwise, -1 +\ is returned. +: scan-suite ( suite -- index ) + { suite } + addr-suites_num get8 { num } + 0 + begin dup num < while + dup 1 << addr-suites_buf + get16 suite = if ret then + 1+ + repeat + drop -1 ; + +\ ======================================================================= + +\ Generate random bytes into buffer (address is offset in context). +cc: mkrand ( addr len -- ) { + size_t len = (size_t)T0_POP(); + void *addr = (unsigned char *)ENG + (size_t)T0_POP(); + br_hmac_drbg_generate(&ENG->rng, addr, len); +} + +\ Read a handshake message header: type and length. These are returned +\ in reverse order (type is TOS, length is below it). +: read-handshake-header-core ( -- lim type ) + read8-nc 3 read24 swap drop swap ; + +\ Read a handshake message header: type and length. If the header is for +\ a HelloRequest message, then it is discarded and a new header is read +\ (repeatedly if necessary). +: read-handshake-header ( -- lim type ) + begin + read-handshake-header-core dup 0= while + drop if ERR_BAD_HANDSHAKE fail then + repeat ; + +\ ======================================================================= + +\ Cipher suite processing. +\ +\ Unfortunately, cipher suite identifiers are attributed mostly arbitrary, +\ so we have to map the cipher suite numbers we support into aggregate +\ words that encode the information we need. Table below is organized +\ as a sequence of pairs of 16-bit words, the first being the cipher suite +\ identifier, the second encoding the algorithm elements. The suites are +\ ordered by increasing cipher suite ID, so that fast lookups may be +\ performed with a binary search (not implemented for the moment, since it +\ does not appear to matter much in practice). +\ +\ Algorithm elements are encoded over 4 bits each, in the following order +\ (most significant to least significant): +\ +\ -- Server key type: +\ 0 RSA (RSA key exchange) +\ 1 ECDHE-RSA (ECDHE key exchange, RSA signature) +\ 2 ECDHE-ECDSA (ECDHE key exchange, ECDSA signature) +\ 3 ECDH-RSA (ECDH key exchange, certificate is RSA-signed) +\ 4 ECDH-ECDSA (ECDH key exchange, certificate is ECDSA-signed) +\ -- Encryption algorithm: +\ 0 3DES/CBC +\ 1 AES-128/CBC +\ 2 AES-256/CBC +\ 3 AES-128/GCM +\ 4 AES-256/GCM +\ 5 ChaCha20/Poly1305 +\ 6 AES-128/CCM +\ 7 AES-256/CCM +\ 8 AES-128/CCM8 +\ 9 AES-256/CCM8 +\ -- MAC algorithm: +\ 0 none (for suites with AEAD encryption) +\ 2 HMAC/SHA-1 +\ 4 HMAC/SHA-256 +\ 5 HMAC/SHA-384 +\ -- PRF for TLS-1.2: +\ 4 with SHA-256 +\ 5 with SHA-384 +\ +\ WARNING: if adding a new cipher suite that does not use SHA-256 for the +\ PRF (with TLS 1.2), be sure to check the suites_sha384[] array defined +\ in ssl/ssl_keyexport.c + +data: cipher-suite-def + +hexb| 000A 0024 | \ TLS_RSA_WITH_3DES_EDE_CBC_SHA +hexb| 002F 0124 | \ TLS_RSA_WITH_AES_128_CBC_SHA +hexb| 0035 0224 | \ TLS_RSA_WITH_AES_256_CBC_SHA +hexb| 003C 0144 | \ TLS_RSA_WITH_AES_128_CBC_SHA256 +hexb| 003D 0244 | \ TLS_RSA_WITH_AES_256_CBC_SHA256 + +hexb| 009C 0304 | \ TLS_RSA_WITH_AES_128_GCM_SHA256 +hexb| 009D 0405 | \ TLS_RSA_WITH_AES_256_GCM_SHA384 + +hexb| C003 4024 | \ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA +hexb| C004 4124 | \ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA +hexb| C005 4224 | \ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +hexb| C008 2024 | \ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA +hexb| C009 2124 | \ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +hexb| C00A 2224 | \ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +hexb| C00D 3024 | \ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA +hexb| C00E 3124 | \ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +hexb| C00F 3224 | \ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +hexb| C012 1024 | \ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +hexb| C013 1124 | \ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +hexb| C014 1224 | \ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + +hexb| C023 2144 | \ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +hexb| C024 2255 | \ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 +hexb| C025 4144 | \ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 +hexb| C026 4255 | \ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 +hexb| C027 1144 | \ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +hexb| C028 1255 | \ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 +hexb| C029 3144 | \ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +hexb| C02A 3255 | \ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +hexb| C02B 2304 | \ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +hexb| C02C 2405 | \ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +hexb| C02D 4304 | \ TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +hexb| C02E 4405 | \ TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +hexb| C02F 1304 | \ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +hexb| C030 1405 | \ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +hexb| C031 3304 | \ TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +hexb| C032 3405 | \ TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + +hexb| C09C 0604 | \ TLS_RSA_WITH_AES_128_CCM +hexb| C09D 0704 | \ TLS_RSA_WITH_AES_256_CCM +hexb| C0A0 0804 | \ TLS_RSA_WITH_AES_128_CCM_8 +hexb| C0A1 0904 | \ TLS_RSA_WITH_AES_256_CCM_8 +hexb| C0AC 2604 | \ TLS_ECDHE_ECDSA_WITH_AES_128_CCM +hexb| C0AD 2704 | \ TLS_ECDHE_ECDSA_WITH_AES_256_CCM +hexb| C0AE 2804 | \ TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +hexb| C0AF 2904 | \ TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + +hexb| CCA8 1504 | \ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 +hexb| CCA9 2504 | \ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + +hexb| 0000 | \ List terminator. + +\ Convert cipher suite identifier to element words. This returns 0 if +\ the cipher suite is not known. +: cipher-suite-to-elements ( suite -- elts ) + { id } + cipher-suite-def + begin + dup 2+ swap data-get16 + dup ifnot 2drop 0 ret then + id = if data-get16 ret then + 2+ + again ; + +\ Check that a given cipher suite is supported. Note that this also +\ returns true (-1) for the TLS_FALLBACK_SCSV pseudo-ciphersuite. +: suite-supported? ( suite -- bool ) + dup 0x5600 = if drop -1 ret then + cipher-suite-to-elements 0<> ; + +\ Get expected key type for cipher suite. The key type is one of +\ BR_KEYTYPE_RSA or BR_KEYTYPE_EC, combined with either BR_KEYTYPE_KEYX +\ (RSA encryption or static ECDH) or BR_KEYTYPE_SIGN (RSA or ECDSA +\ signature, for ECDHE cipher suites). +: expected-key-type ( suite -- key-type ) + cipher-suite-to-elements 12 >> + case + 0 of CX 0 63 { BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX } endof + 1 of CX 0 63 { BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN } endof + 2 of CX 0 63 { BR_KEYTYPE_EC | BR_KEYTYPE_SIGN } endof + 3 of CX 0 63 { BR_KEYTYPE_EC | BR_KEYTYPE_KEYX } endof + 4 of CX 0 63 { BR_KEYTYPE_EC | BR_KEYTYPE_KEYX } endof + 0 swap + endcase ; + +\ Test whether the cipher suite uses RSA key exchange. +: use-rsa-keyx? ( suite -- bool ) + cipher-suite-to-elements 12 >> 0= ; + +\ Test whether the cipher suite uses ECDHE key exchange, signed with RSA. +: use-rsa-ecdhe? ( suite -- bool ) + cipher-suite-to-elements 12 >> 1 = ; + +\ Test whether the cipher suite uses ECDHE key exchange, signed with ECDSA. +: use-ecdsa-ecdhe? ( suite -- bool ) + cipher-suite-to-elements 12 >> 2 = ; + +\ Test whether the cipher suite uses ECDHE key exchange (with RSA or ECDSA). +: use-ecdhe? ( suite -- bool ) + cipher-suite-to-elements 12 >> dup 0> swap 3 < and ; + +\ Test whether the cipher suite uses ECDH (static) key exchange. +: use-ecdh? ( suite -- bool ) + cipher-suite-to-elements 12 >> 2 > ; + +\ Get identifier for the PRF (TLS 1.2). +: prf-id ( suite -- id ) + cipher-suite-to-elements 15 and ; + +\ Test whether a cipher suite is only for TLS-1.2. Cipher suites that +\ can be used with TLS-1.0 or 1.1 use HMAC/SHA-1. RFC do not formally +\ forbid using a CBC-based TLS-1.2 cipher suite, e.g. based on HMAC/SHA-256, +\ with older protocol versions; however, servers should not do that, since +\ it may confuse clients. Since the server code does not try such games, +\ for consistency, the client should reject it as well (normal servers +\ don't do that, so any attempt is a sign of foul play). +: use-tls12? ( suite -- bool ) + cipher-suite-to-elements 0xF0 and 0x20 <> ; + +\ Switch to negotiated security parameters for input or output. +: switch-encryption ( is-client for-input -- ) + { for-input } + addr-cipher_suite get16 cipher-suite-to-elements { elts } + + \ prf_id + elts 15 and + + \ mac_id + elts 4 >> 15 and + + \ cipher type and key length + elts 8 >> 15 and case + \ 3DES/CBC + 0 of 0 24 + for-input if + switch-cbc-in + else + switch-cbc-out + then + endof + + \ AES-128/CBC + 1 of 1 16 + for-input if + switch-cbc-in + else + switch-cbc-out + then + endof + + \ AES-256/CBC + 2 of 1 32 + for-input if + switch-cbc-in + else + switch-cbc-out + then + endof + + \ AES-128/GCM + 3 of drop 16 + for-input if + switch-aesgcm-in + else + switch-aesgcm-out + then + endof + + \ AES-256/GCM + 4 of drop 32 + for-input if + switch-aesgcm-in + else + switch-aesgcm-out + then + endof + + \ ChaCha20+Poly1305 + 5 of drop + for-input if + switch-chapol-in + else + switch-chapol-out + then + endof + + \ Now we only have AES/CCM suites (6 to 9). Since the + \ input is between 0 and 15, and we checked values 0 to 5, + \ we only need to reject values larger than 9. + dup 9 > if + ERR_BAD_PARAM fail + then + + \ Stack: is_client prf_id mac_id cipher_id + \ We want to remove the mac_id (it is zero for CCM suites) + \ and replace the cipher_id with the key and tag lengths. + \ The following table applies: + \ id key length tag length + \ 6 16 16 + \ 7 32 16 + \ 8 16 8 + \ 9 32 8 + swap drop + dup 1 and 4 << 16 + swap + 8 and 16 swap - + for-input if + switch-aesccm-in + else + switch-aesccm-out + then + ret + endcase + ; + +cc: switch-cbc-out ( is_client prf_id mac_id aes cipher_key_len -- ) { + int is_client, prf_id, mac_id, aes; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + aes = T0_POP(); + mac_id = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id, + aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len); +} + +cc: switch-cbc-in ( is_client prf_id mac_id aes cipher_key_len -- ) { + int is_client, prf_id, mac_id, aes; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + aes = T0_POP(); + mac_id = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id, + aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len); +} + +cc: switch-aesgcm-out ( is_client prf_id cipher_key_len -- ) { + int is_client, prf_id; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id, + ENG->iaes_ctr, cipher_key_len); +} + +cc: switch-aesgcm-in ( is_client prf_id cipher_key_len -- ) { + int is_client, prf_id; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id, + ENG->iaes_ctr, cipher_key_len); +} + +cc: switch-chapol-out ( is_client prf_id -- ) { + int is_client, prf_id; + + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id); +} + +cc: switch-chapol-in ( is_client prf_id -- ) { + int is_client, prf_id; + + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id); +} + +cc: switch-aesccm-out ( is_client prf_id cipher_key_len tag_len -- ) { + int is_client, prf_id; + unsigned cipher_key_len, tag_len; + + tag_len = T0_POP(); + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id, + ENG->iaes_ctrcbc, cipher_key_len, tag_len); +} + +cc: switch-aesccm-in ( is_client prf_id cipher_key_len tag_len -- ) { + int is_client, prf_id; + unsigned cipher_key_len, tag_len; + + tag_len = T0_POP(); + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id, + ENG->iaes_ctrcbc, cipher_key_len, tag_len); +} + +\ Write Finished message. +: write-Finished ( from_client -- ) + compute-Finished + 20 write8 12 write24 addr-pad 12 write-blob ; + +\ Read Finished message. +: read-Finished ( from_client -- ) + compute-Finished + read-handshake-header 20 <> if ERR_UNEXPECTED fail then + addr-pad 12 + 12 read-blob + close-elt + addr-pad dup 12 + 12 memcmp ifnot ERR_BAD_FINISHED fail then ; + +\ Compute the "Finished" contents (either the value to send, or the +\ expected value). The 12-byte string is written in the pad. The +\ "from_client" value is non-zero for the Finished sent by the client. +\ The computed value is also saved in the relevant buffer for handling +\ secure renegotiation. +: compute-Finished ( from_client -- ) + dup addr-saved_finished swap ifnot 12 + then swap + addr-cipher_suite get16 prf-id compute-Finished-inner + addr-pad 12 memcpy ; + +cc: compute-Finished-inner ( from_client prf_id -- ) { + int prf_id = T0_POP(); + int from_client = T0_POPi(); + unsigned char tmp[48]; + br_tls_prf_seed_chunk seed; + + br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id); + seed.data = tmp; + if (ENG->session.version >= BR_TLS12) { + seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp); + } else { + br_multihash_out(&ENG->mhash, br_md5_ID, tmp); + br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16); + seed.len = 36; + } + prf(ENG->pad, 12, ENG->session.master_secret, + sizeof ENG->session.master_secret, + from_client ? "client finished" : "server finished", + 1, &seed); +} + +\ Receive ChangeCipherSpec and Finished from the peer. +: read-CCS-Finished ( is-client -- ) + has-input? if + addr-record_type_in get8 20 <> if ERR_UNEXPECTED fail then + else + begin + wait-co 0x07 and dup 0x02 <> while + if ERR_UNEXPECTED fail then + repeat + drop + then + read8-nc 1 <> more-incoming-bytes? or if ERR_BAD_CCS fail then + dup 1 switch-encryption + + \ Read and verify Finished from peer. + not read-Finished ; + +\ Send ChangeCipherSpec and Finished to the peer. +: write-CCS-Finished ( is-client -- ) + \ Flush and wait for output buffer to be clear, so that we may + \ write our ChangeCipherSpec. We must switch immediately after + \ triggering the flush. + 20 wait-rectype-out + 1 write8 + flush-record + dup 0 switch-encryption + 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 } + + \ If hash is 0x08 then this is a "new algorithm" identifier, + \ and we set the corresponding bit if it is in the 0..15 + \ range. Otherwise, we keep the value only if the signature + \ is either 1 (RSA) or 3 (ECDSA), and the hash is one of the + \ SHA-* functions (2 to 6). Note that we reject MD5. + hash 8 = if + sign 15 <= if + 1 sign 16 + << hashes or >hashes + then + else + hash 2 >= hash 6 <= and + sign 1 = sign 3 = or + and if + hashes 1 sign 1- 2 << hash + << or >hashes + then + 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 ; + +\ ======================================================================= + +\ Copy a specific protocol name from the list to the pad. The byte +\ length is returned. +cc: copy-protocol-name ( idx -- len ) { + size_t idx = T0_POP(); + size_t len = strlen(ENG->protocol_names[idx]); + memcpy(ENG->pad, ENG->protocol_names[idx], len); + T0_PUSH(len); +} + +\ Compare name in pad with the configured list of protocol names. +\ If a match is found, then the index is returned; otherwise, -1 +\ is returned. +cc: test-protocol-name ( len -- n ) { + size_t len = T0_POP(); + size_t u; + + for (u = 0; u < ENG->protocol_names_num; u ++) { + const char *name; + + name = ENG->protocol_names[u]; + if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) { + T0_PUSH(u); + T0_RET(); + } + } + T0_PUSHi(-1); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.c b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.c new file mode 100644 index 0000000..5f8cae7 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.c @@ -0,0 +1,2009 @@ +/* Automatically generated code; do not modify directly. */ + +#include +#include + +typedef struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; +} t0_context; + +static uint32_t +t0_parse7E_unsigned(const unsigned char **p) +{ + uint32_t x; + + x = 0; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + return x; + } + } +} + +static int32_t +t0_parse7E_signed(const unsigned char **p) +{ + int neg; + uint32_t x; + + neg = ((**p) >> 6) & 1; + x = (uint32_t)-neg; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + if (neg) { + return -(int32_t)~x - 1; + } else { + return (int32_t)x; + } + } + } +} + +#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) +#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) +#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) +#define T0_INT1(x) T0_FBYTE(x, 0) +#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) + +/* static const unsigned char t0_datablock[]; */ + + +void br_ssl_hs_server_init_main(void *t0ctx); + +void br_ssl_hs_server_run(void *t0ctx); + + + +#include +#include + +#include "inner.h" + +/* + * This macro evaluates to a pointer to the current engine context. + */ +#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu))) + + + + + +/* + * This macro evaluates to a pointer to the server context, under that + * specific name. It must be noted that since the engine context is the + * first field of the br_ssl_server_context structure ('eng'), then + * pointers values of both types are interchangeable, modulo an + * appropriate cast. This also means that "addresses" computed as offsets + * within the structure work for both kinds of context. + */ +#define CTX ((br_ssl_server_context *)ENG) + +/* + * Decrypt the pre-master secret (RSA key exchange). + */ +static void +do_rsa_decrypt(br_ssl_server_context *ctx, int prf_id, + unsigned char *epms, size_t len) +{ + uint32_t x; + unsigned char rpms[48]; + + /* + * Decrypt the PMS. + */ + x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, epms, &len); + + /* + * Set the first two bytes to the maximum supported client + * protocol version. These bytes are used for version rollback + * detection; forceing the two bytes will make the master secret + * wrong if the bytes are not correct. This process is + * recommended by RFC 5246 (section 7.4.7.1). + */ + br_enc16be(epms, ctx->client_max_version); + + /* + * Make a random PMS and copy it above the decrypted value if the + * decryption failed. Note that we use a constant-time conditional + * copy. + */ + br_hmac_drbg_generate(&ctx->eng.rng, rpms, sizeof rpms); + br_ccopy(x ^ 1, epms, rpms, sizeof rpms); + + /* + * Compute master secret. + */ + br_ssl_engine_compute_master(&ctx->eng, prf_id, epms, 48); + + /* + * Clear the pre-master secret from RAM: it is normally a buffer + * in the context, hence potentially long-lived. + */ + memset(epms, 0, len); +} + +/* + * Common part for ECDH and ECDHE. + */ +static void +ecdh_common(br_ssl_server_context *ctx, int prf_id, + unsigned char *xcoor, size_t xcoor_len, uint32_t ctl) +{ + unsigned char rpms[80]; + + if (xcoor_len > sizeof rpms) { + xcoor_len = sizeof rpms; + ctl = 0; + } + + /* + * Make a random PMS and copy it above the decrypted value if the + * decryption failed. Note that we use a constant-time conditional + * copy. + */ + br_hmac_drbg_generate(&ctx->eng.rng, rpms, xcoor_len); + br_ccopy(ctl ^ 1, xcoor, rpms, xcoor_len); + + /* + * Compute master secret. + */ + br_ssl_engine_compute_master(&ctx->eng, prf_id, xcoor, xcoor_len); + + /* + * Clear the pre-master secret from RAM: it is normally a buffer + * in the context, hence potentially long-lived. + */ + memset(xcoor, 0, xcoor_len); +} + +/* + * Do the ECDH key exchange (not ECDHE). + */ +static void +do_ecdh(br_ssl_server_context *ctx, int prf_id, + unsigned char *cpoint, size_t cpoint_len) +{ + uint32_t x; + + /* + * Finalise the key exchange. + */ + x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, + cpoint, &cpoint_len); + 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); +} + +static size_t +hash_data(br_ssl_server_context *ctx, + void *dst, int hash_id, const void *src, size_t len) +{ + const br_hash_class *hf; + br_hash_compat_context hc; + + if (hash_id == 0) { + unsigned char tmp[36]; + + hf = br_multihash_getimpl(&ctx->eng.mhash, br_md5_ID); + if (hf == NULL) { + return 0; + } + hf->init(&hc.vtable); + hf->update(&hc.vtable, src, len); + hf->out(&hc.vtable, tmp); + hf = br_multihash_getimpl(&ctx->eng.mhash, br_sha1_ID); + if (hf == NULL) { + return 0; + } + hf->init(&hc.vtable); + hf->update(&hc.vtable, src, len); + hf->out(&hc.vtable, tmp + 16); + memcpy(dst, tmp, 36); + return 36; + } else { + hf = br_multihash_getimpl(&ctx->eng.mhash, hash_id); + if (hf == NULL) { + return 0; + } + hf->init(&hc.vtable); + hf->update(&hc.vtable, src, len); + hf->out(&hc.vtable, dst); + return (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; + } +} + +/* + * 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 + * signature length (in bytes), or -x on error (with x being an error + * code). The encoded point is written in the ecdhe_point[] context buffer + * (length in ecdhe_point_len). + */ +static int +do_ecdhe_part1(br_ssl_server_context *ctx, int curve) +{ + unsigned algo_id; + unsigned mask; + const unsigned char *order; + size_t olen, glen; + size_t hv_len, sig_len; + + if (!((ctx->eng.iec->supported_curves >> curve) & 1)) { + return -BR_ERR_INVALID_ALGORITHM; + } + ctx->eng.ecdhe_curve = curve; + + /* + * Generate our private key. We need a non-zero random value + * which is lower than the curve order, in a "large enough" + * range. We force the top bit to 0 and bottom bit to 1, which + * does the trick. Note that contrary to what happens in ECDSA, + * this is not a problem if we do not cover the full range of + * possible values. + */ + order = ctx->eng.iec->order(curve, &olen); + mask = 0xFF; + while (mask >= order[0]) { + mask >>= 1; + } + br_hmac_drbg_generate(&ctx->eng.rng, ctx->ecdhe_key, olen); + ctx->ecdhe_key[0] &= mask; + ctx->ecdhe_key[olen - 1] |= 0x01; + ctx->ecdhe_key_len = olen; + + /* + * Compute our ECDH point. + */ + glen = ctx->eng.iec->mulgen(ctx->eng.ecdhe_point, + ctx->ecdhe_key, olen, curve); + ctx->eng.ecdhe_point_len = glen; + + /* + * Assemble the message to be signed, and possibly hash it. + */ + memcpy(ctx->eng.pad, ctx->eng.client_random, 32); + memcpy(ctx->eng.pad + 32, ctx->eng.server_random, 32); + ctx->eng.pad[64 + 0] = 0x03; + ctx->eng.pad[64 + 1] = 0x00; + ctx->eng.pad[64 + 2] = curve; + ctx->eng.pad[64 + 3] = ctx->eng.ecdhe_point_len; + memcpy(ctx->eng.pad + 64 + 4, + ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len); + hv_len = 64 + 4 + ctx->eng.ecdhe_point_len; + algo_id = ctx->sign_hash_id; + if (algo_id >= (unsigned)0xFF00) { + hv_len = hash_data(ctx, ctx->eng.pad, algo_id & 0xFF, + ctx->eng.pad, hv_len); + if (hv_len == 0) { + return -BR_ERR_INVALID_ALGORITHM; + } + } + + sig_len = (*ctx->policy_vtable)->do_sign(ctx->policy_vtable, + algo_id, ctx->eng.pad, hv_len, sizeof ctx->eng.pad); + return sig_len ? (int)sig_len : -BR_ERR_INVALID_ALGORITHM; +} + +/* + * Do the ECDHE key exchange (part 2: computation of the shared secret + * from the point sent by the client). + */ +static void +do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id, + unsigned char *cpoint, size_t cpoint_len) +{ + int curve; + uint32_t ctl; + size_t xoff, xlen; + + curve = ctx->eng.ecdhe_curve; + + /* + * Finalise the key exchange. + */ + ctl = ctx->eng.iec->mul(cpoint, cpoint_len, + ctx->ecdhe_key, ctx->ecdhe_key_len, curve); + xoff = ctx->eng.iec->xoff(curve, &xlen); + ecdh_common(ctx, prf_id, cpoint + xoff, xlen, ctl); + + /* + * Clear the ECDHE private key. Forward Secrecy is achieved insofar + * as that key does not get stolen, so we'd better destroy it + * as soon as it ceases to be useful. + */ + memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len); +} + +/* + * Offset for hash value within the pad (when obtaining all hash values, + * in preparation for verification of the CertificateVerify message). + * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value + * is used to get the total length. + */ +static const unsigned char HASH_PAD_OFF[] = { 0, 16, 36, 64, 96, 144, 208 }; + +/* + * OID for hash functions in RSA signatures. + */ +static const unsigned char HASH_OID_SHA1[] = { + 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A +}; + +static const unsigned char HASH_OID_SHA224[] = { + 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04 +}; + +static const unsigned char HASH_OID_SHA256[] = { + 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 +}; + +static const unsigned char HASH_OID_SHA384[] = { + 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 +}; + +static const unsigned char HASH_OID_SHA512[] = { + 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 +}; + +static const unsigned char *HASH_OID[] = { + HASH_OID_SHA1, + HASH_OID_SHA224, + HASH_OID_SHA256, + HASH_OID_SHA384, + HASH_OID_SHA512 +}; + +/* + * Verify the signature in CertificateVerify. Returned value is 0 on + * success, or a non-zero error code. Lack of implementation of the + * designated signature algorithm is reported as a "bad signature" + * error (because it means that the peer did not honour our advertised + * set of supported signature algorithms). + */ +static int +verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + int id; + + id = ctx->hash_CV_id; + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + if (pk->key_type == BR_KEYTYPE_RSA) { + unsigned char tmp[64]; + const unsigned char *hash_oid; + + if (id == 0) { + hash_oid = NULL; + } else { + hash_oid = HASH_OID[id - 2]; + } + if (ctx->eng.irsavrfy == 0) { + return BR_ERR_BAD_SIGNATURE; + } + if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len, + hash_oid, ctx->hash_CV_len, &pk->key.rsa, tmp) + || memcmp(tmp, ctx->hash_CV, ctx->hash_CV_len) != 0) + { + return BR_ERR_BAD_SIGNATURE; + } + } else { + if (ctx->eng.iecdsa == 0) { + return BR_ERR_BAD_SIGNATURE; + } + if (!ctx->eng.iecdsa(ctx->eng.iec, + ctx->hash_CV, ctx->hash_CV_len, + &pk->key.ec, ctx->eng.pad, sig_len)) + { + return BR_ERR_BAD_SIGNATURE; + } + } + return 0; +} + + + +static const unsigned char t0_datablock[] = { + 0x00, 0x00, 0x0A, 0x00, 0x24, 0x00, 0x2F, 0x01, 0x24, 0x00, 0x35, 0x02, + 0x24, 0x00, 0x3C, 0x01, 0x44, 0x00, 0x3D, 0x02, 0x44, 0x00, 0x9C, 0x03, + 0x04, 0x00, 0x9D, 0x04, 0x05, 0xC0, 0x03, 0x40, 0x24, 0xC0, 0x04, 0x41, + 0x24, 0xC0, 0x05, 0x42, 0x24, 0xC0, 0x08, 0x20, 0x24, 0xC0, 0x09, 0x21, + 0x24, 0xC0, 0x0A, 0x22, 0x24, 0xC0, 0x0D, 0x30, 0x24, 0xC0, 0x0E, 0x31, + 0x24, 0xC0, 0x0F, 0x32, 0x24, 0xC0, 0x12, 0x10, 0x24, 0xC0, 0x13, 0x11, + 0x24, 0xC0, 0x14, 0x12, 0x24, 0xC0, 0x23, 0x21, 0x44, 0xC0, 0x24, 0x22, + 0x55, 0xC0, 0x25, 0x41, 0x44, 0xC0, 0x26, 0x42, 0x55, 0xC0, 0x27, 0x11, + 0x44, 0xC0, 0x28, 0x12, 0x55, 0xC0, 0x29, 0x31, 0x44, 0xC0, 0x2A, 0x32, + 0x55, 0xC0, 0x2B, 0x23, 0x04, 0xC0, 0x2C, 0x24, 0x05, 0xC0, 0x2D, 0x43, + 0x04, 0xC0, 0x2E, 0x44, 0x05, 0xC0, 0x2F, 0x13, 0x04, 0xC0, 0x30, 0x14, + 0x05, 0xC0, 0x31, 0x33, 0x04, 0xC0, 0x32, 0x34, 0x05, 0xC0, 0x9C, 0x06, + 0x04, 0xC0, 0x9D, 0x07, 0x04, 0xC0, 0xA0, 0x08, 0x04, 0xC0, 0xA1, 0x09, + 0x04, 0xC0, 0xAC, 0x26, 0x04, 0xC0, 0xAD, 0x27, 0x04, 0xC0, 0xAE, 0x28, + 0x04, 0xC0, 0xAF, 0x29, 0x04, 0xCC, 0xA8, 0x15, 0x04, 0xCC, 0xA9, 0x25, + 0x04, 0x00, 0x00 +}; + +static const unsigned char t0_codeblock[] = { + 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x01, + 0x00, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x08, + 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00, + 0x01, 0x02, 0x09, 0x00, 0x00, 0x29, 0x29, 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_SIGNATURE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_VERSION), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_NO_CLIENT_AUTH), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK), + 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00, + 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_server_context, client_max_version)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, client_random)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_server_context, client_suites)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_server_context, client_suites_num)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, close_received)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_server_context, curves)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_server_context, hashes)), + 0x00, 0x00, 0x7B, 0x01, + T0_INT2(BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00, + 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, peer_log_max_frag_len)), 0x00, + 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, protocol_names_num)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, record_type_in)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, record_type_out)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, reneg)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, saved_finished)), 0x00, + 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, selected_protocol)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, server_name)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, server_random)), 0x00, 0x00, + 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id_len)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, shutdown_recv)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_server_context, sign_hash_id)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_buf)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_num)), 0x00, + 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, version)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_in)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)), + 0x00, 0x00, 0x09, 0x2A, 0x5D, 0x06, 0x02, 0x6A, 0x2B, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x03, 0x00, 0x9B, 0x2A, 0x63, 0x47, 0x9F, 0x2A, 0x05, + 0x04, 0x65, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0F, 0x06, 0x02, 0x9F, 0x00, + 0x63, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x6A, 0x2B, 0x00, 0x00, 0x2A, 0x8B, + 0x47, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x47, 0x78, 0x2E, 0xA8, 0x1C, 0x85, + 0x01, 0x0C, 0x33, 0x00, 0x00, 0x2A, 0x22, 0x01, 0x08, 0x0C, 0x47, 0x61, + 0x22, 0x08, 0x00, 0x01, 0x03, 0x00, 0x77, 0x30, 0x02, 0x00, 0x38, 0x13, + 0x01, 0x01, 0x0C, 0x77, 0x42, 0x2C, 0x19, 0x38, 0x06, 0x07, 0x02, 0x00, + 0xD0, 0x03, 0x00, 0x04, 0x75, 0x01, 0x00, 0xC7, 0x02, 0x00, 0x2A, 0x19, + 0x13, 0x06, 0x02, 0x71, 0x2B, 0xD0, 0x04, 0x76, 0x00, 0x01, 0x00, 0x77, + 0x42, 0x01, 0x16, 0x89, 0x42, 0x01, 0x00, 0x8C, 0x40, 0x36, 0xB1, 0x35, + 0x06, 0x02, 0x73, 0x2B, 0x06, 0x0A, 0xD7, 0x01, 0x00, 0xD3, 0x01, 0x00, + 0xAD, 0x04, 0x80, 0x46, 0xD7, 0xD4, 0x29, 0xD9, 0x50, 0x06, 0x01, 0xD5, + 0xD8, 0x2C, 0x50, 0x06, 0x31, 0x01, 0x00, 0xAE, 0x2A, 0x5D, 0x06, 0x0F, + 0x01, 0x02, 0xA4, 0x05, 0x02, 0x37, 0x2B, 0x29, 0xB2, 0xB0, 0x2A, 0xC9, + 0x29, 0x04, 0x19, 0x2A, 0x5F, 0x06, 0x0B, 0x29, 0x01, 0x02, 0xA4, 0x05, + 0x02, 0x70, 0x2B, 0xB2, 0x04, 0x0A, 0xB4, 0x2A, 0x05, 0x04, 0x29, 0xAB, + 0x04, 0x02, 0xB3, 0xAF, 0x04, 0x01, 0xB2, 0x01, 0x00, 0xAD, 0x01, 0x00, + 0xD3, 0x3E, 0x01, 0x01, 0x77, 0x42, 0x01, 0x17, 0x89, 0x42, 0x00, 0x00, + 0x3A, 0x3A, 0x00, 0x01, 0x03, 0x00, 0x2C, 0x19, 0x38, 0x06, 0x04, 0xCF, + 0x29, 0x04, 0x78, 0x01, 0x02, 0x02, 0x00, 0xC6, 0x19, 0x38, 0x06, 0x04, + 0xCF, 0x29, 0x04, 0x78, 0x02, 0x00, 0x01, 0x84, 0x00, 0x08, 0x2B, 0x00, + 0x00, 0x81, 0x2F, 0x47, 0x12, 0x01, 0x01, 0x13, 0x37, 0x00, 0x00, 0x2A, + 0x05, 0x04, 0x29, 0x01, 0x7F, 0x00, 0x01, 0x00, 0xA2, 0x12, 0x01, 0x01, + 0x13, 0x5F, 0x06, 0x03, 0x61, 0x04, 0x75, 0x47, 0x29, 0x00, 0x00, 0x01, + 0x7F, 0xA1, 0xCF, 0x2A, 0x01, 0x07, 0x13, 0x01, 0x00, 0x3A, 0x0F, 0x06, + 0x0D, 0x29, 0x01, 0x10, 0x13, 0x06, 0x05, 0x01, 0x00, 0x77, 0x42, 0xC5, + 0x04, 0x33, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x2A, 0x29, 0x29, 0x8A, 0x30, + 0x01, 0x01, 0x0F, 0x01, 0x01, 0xA4, 0x39, 0x06, 0x18, 0xC8, 0x2C, 0x19, + 0x38, 0x06, 0x04, 0xCF, 0x29, 0x04, 0x78, 0x01, 0x80, 0x64, 0xC7, 0x01, + 0x01, 0x77, 0x42, 0x01, 0x17, 0x89, 0x42, 0x04, 0x03, 0x01, 0x00, 0xA1, + 0x04, 0x03, 0x73, 0x2B, 0x29, 0x04, 0xFF, 0x32, 0x01, 0x2A, 0x03, 0x00, + 0x09, 0x2A, 0x5D, 0x06, 0x02, 0x6A, 0x2B, 0x02, 0x00, 0x00, 0x00, 0x9C, + 0x01, 0x0F, 0x13, 0x00, 0x00, 0x76, 0x30, 0x01, 0x00, 0x3A, 0x0F, 0x06, + 0x10, 0x29, 0x2A, 0x01, 0x01, 0x0E, 0x06, 0x03, 0x29, 0x01, 0x02, 0x76, + 0x42, 0x01, 0x00, 0x04, 0x21, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x14, 0x29, + 0x01, 0x00, 0x76, 0x42, 0x2A, 0x01, 0x80, 0x64, 0x0F, 0x06, 0x05, 0x01, + 0x82, 0x00, 0x08, 0x2B, 0x5F, 0x04, 0x07, 0x29, 0x01, 0x82, 0x00, 0x08, + 0x2B, 0x29, 0x00, 0x00, 0x01, 0x00, 0x31, 0x06, 0x05, 0x3D, 0xA9, 0x39, + 0x04, 0x78, 0x2A, 0x06, 0x04, 0x01, 0x01, 0x91, 0x42, 0x00, 0x00, 0x01, + 0x1F, 0x13, 0x01, 0x12, 0x0F, 0x05, 0x02, 0x74, 0x2B, 0x78, 0x2E, 0x2A, + 0xCB, 0x05, 0x02, 0x73, 0x2B, 0xA8, 0x28, 0x00, 0x02, 0x87, 0x2E, 0x05, + 0x02, 0xBC, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x01, 0x7E, 0x03, 0x00, 0x2A, + 0x06, 0x17, 0xC2, 0x2A, 0x03, 0x01, 0x85, 0x47, 0xB6, 0x02, 0x01, 0x51, + 0x2A, 0x02, 0x00, 0x53, 0x06, 0x04, 0x03, 0x00, 0x04, 0x01, 0x29, 0x04, + 0x66, 0x9D, 0x9D, 0x02, 0x00, 0x61, 0x8C, 0x40, 0x00, 0x00, 0x31, 0x06, + 0x0B, 0x88, 0x30, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x73, 0x2B, 0x04, 0x11, + 0xCF, 0x01, 0x07, 0x13, 0x2A, 0x01, 0x02, 0x0E, 0x06, 0x06, 0x06, 0x02, + 0x73, 0x2B, 0x04, 0x70, 0x29, 0xC3, 0x01, 0x01, 0x0E, 0x35, 0x39, 0x06, + 0x02, 0x66, 0x2B, 0x2A, 0x01, 0x01, 0xCA, 0x38, 0xB5, 0x00, 0x01, 0xBA, + 0x01, 0x0B, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x2A, 0x01, 0x03, 0x0F, 0x06, + 0x08, 0xC1, 0x06, 0x02, 0x6A, 0x2B, 0x47, 0x29, 0x00, 0x47, 0x5C, 0xC1, + 0xA7, 0x2A, 0x06, 0x23, 0xC1, 0xA7, 0x2A, 0x5B, 0x2A, 0x06, 0x18, 0x2A, + 0x01, 0x82, 0x00, 0x10, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x2A, + 0x03, 0x00, 0x85, 0x02, 0x00, 0xB6, 0x02, 0x00, 0x58, 0x04, 0x65, 0x9D, + 0x59, 0x04, 0x5A, 0x9D, 0x9D, 0x5A, 0x2A, 0x06, 0x02, 0x37, 0x00, 0x29, + 0x2D, 0x00, 0x02, 0x2A, 0x01, 0x20, 0x13, 0x05, 0x02, 0x74, 0x2B, 0x01, + 0x0F, 0x13, 0x03, 0x00, 0xB0, 0x95, 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06, + 0x23, 0xC0, 0x2A, 0x01, 0x81, 0x7F, 0x13, 0x61, 0x01, 0x01, 0x12, 0x02, + 0x00, 0x0F, 0x05, 0x02, 0x6C, 0x2B, 0x01, 0x08, 0x12, 0x2A, 0x01, 0x02, + 0x0B, 0x3A, 0x01, 0x06, 0x10, 0x39, 0x06, 0x02, 0x6E, 0x2B, 0x04, 0x0D, + 0x02, 0x00, 0x01, 0x01, 0x0F, 0x06, 0x04, 0x01, 0x00, 0x04, 0x02, 0x01, + 0x02, 0x20, 0x05, 0x02, 0x6E, 0x2B, 0xC0, 0x2A, 0x03, 0x01, 0x2A, 0x01, + 0x84, 0x00, 0x10, 0x06, 0x02, 0x6F, 0x2B, 0x85, 0x47, 0xB6, 0x02, 0x01, + 0x55, 0x2A, 0x06, 0x01, 0x2B, 0x29, 0x9D, 0x00, 0x00, 0x1D, 0xBA, 0x01, + 0x0F, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x00, 0x0A, 0xBA, 0x01, 0x01, 0x0F, + 0x05, 0x02, 0x73, 0x2B, 0xC0, 0x2A, 0x03, 0x00, 0x79, 0x40, 0x7A, 0x01, + 0x20, 0xB6, 0xC2, 0x2A, 0x01, 0x20, 0x10, 0x06, 0x02, 0x72, 0x2B, 0x2A, + 0x90, 0x42, 0x8F, 0x47, 0xB6, 0x1A, 0x03, 0x01, 0xC0, 0xA7, 0x01, 0x00, + 0x03, 0x02, 0x01, 0x00, 0x03, 0x03, 0x83, 0xA2, 0x17, 0x3A, 0x08, 0x03, + 0x04, 0x03, 0x05, 0x2A, 0x06, 0x80, 0x6D, 0xC0, 0x2A, 0x03, 0x06, 0x02, + 0x01, 0x06, 0x0A, 0x2A, 0x78, 0x2E, 0x0F, 0x06, 0x04, 0x01, 0x7F, 0x03, + 0x03, 0x2A, 0x01, 0x81, 0x7F, 0x0F, 0x06, 0x0A, 0x8A, 0x30, 0x06, 0x02, + 0x6B, 0x2B, 0x01, 0x7F, 0x03, 0x02, 0x2A, 0x01, 0x81, 0xAC, 0x00, 0x0F, + 0x06, 0x11, 0x02, 0x00, 0x98, 0x2E, 0x11, 0x02, 0x00, 0x97, 0x2E, 0x0B, + 0x13, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0xC4, 0x2A, 0x5D, 0x06, 0x03, + 0x29, 0x04, 0x26, 0x01, 0x00, 0xA4, 0x06, 0x0B, 0x01, 0x02, 0x0C, 0x7B, + 0x08, 0x02, 0x06, 0x47, 0x40, 0x04, 0x16, 0x29, 0x02, 0x05, 0x02, 0x04, + 0x11, 0x06, 0x02, 0x69, 0x2B, 0x02, 0x06, 0x02, 0x05, 0x40, 0x02, 0x05, + 0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0xFF, 0x0F, 0x29, 0x01, 0x00, 0x03, + 0x07, 0xC2, 0xA7, 0x2A, 0x06, 0x09, 0xC2, 0x05, 0x04, 0x01, 0x7F, 0x03, + 0x07, 0x04, 0x74, 0x9D, 0x01, 0x00, 0x8D, 0x42, 0x01, 0x88, 0x04, 0x82, + 0x41, 0x01, 0x84, 0x80, 0x80, 0x00, 0x7E, 0x41, 0x2A, 0x06, 0x80, 0x4E, + 0xC0, 0xA7, 0x2A, 0x06, 0x80, 0x47, 0xC0, 0x01, 0x00, 0x3A, 0x0F, 0x06, + 0x04, 0x29, 0xB9, 0x04, 0x39, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x04, 0x29, + 0xB7, 0x04, 0x2F, 0x01, 0x83, 0xFE, 0x01, 0x3A, 0x0F, 0x06, 0x04, 0x29, + 0xB8, 0x04, 0x23, 0x01, 0x0D, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xBE, 0x04, + 0x19, 0x01, 0x0A, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xBF, 0x04, 0x0F, 0x01, + 0x10, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xAC, 0x04, 0x05, 0x29, 0xBC, 0x01, + 0x00, 0x29, 0x04, 0xFF, 0x35, 0x9D, 0x9D, 0x02, 0x01, 0x02, 0x03, 0x13, + 0x03, 0x01, 0x02, 0x00, 0x5D, 0x06, 0x08, 0x79, 0x2E, 0x99, 0x40, 0x01, + 0x80, 0x56, 0xA3, 0x97, 0x2E, 0x2A, 0x02, 0x00, 0x10, 0x06, 0x03, 0x29, + 0x02, 0x00, 0x2A, 0x01, 0x86, 0x00, 0x0B, 0x06, 0x02, 0x6D, 0x2B, 0x02, + 0x00, 0x98, 0x2E, 0x0B, 0x06, 0x04, 0x01, 0x80, 0x46, 0xA3, 0x02, 0x01, + 0x06, 0x10, 0x95, 0x2E, 0x02, 0x00, 0x0D, 0x06, 0x05, 0x29, 0x95, 0x2E, + 0x04, 0x04, 0x01, 0x00, 0x03, 0x01, 0x2A, 0x95, 0x40, 0x2A, 0x96, 0x40, + 0x2A, 0x99, 0x40, 0x01, 0x86, 0x03, 0x11, 0x03, 0x08, 0x02, 0x02, 0x06, + 0x04, 0x01, 0x02, 0x8A, 0x42, 0x8A, 0x30, 0x05, 0x04, 0x01, 0x01, 0x8A, + 0x42, 0x02, 0x07, 0x05, 0x03, 0x01, 0x28, 0xA3, 0x44, 0x29, 0x01, 0x82, + 0x01, 0x07, 0x01, 0xFC, 0x80, 0x00, 0x39, 0x82, 0x2F, 0x13, 0x2A, 0x82, + 0x41, 0x2A, 0x01, 0x81, 0x7F, 0x13, 0x5E, 0x37, 0x47, 0x01, 0x08, 0x12, + 0x5E, 0x01, 0x02, 0x13, 0x39, 0x01, 0x0C, 0x0C, 0x03, 0x09, 0x7E, 0x2F, + 0x43, 0x13, 0x2A, 0x7E, 0x41, 0x05, 0x04, 0x01, 0x00, 0x03, 0x09, 0x02, + 0x01, 0x06, 0x03, 0x01, 0x7F, 0x00, 0x8F, 0x01, 0x20, 0x34, 0x01, 0x20, + 0x90, 0x42, 0x7B, 0x2A, 0x03, 0x05, 0x2A, 0x02, 0x04, 0x0B, 0x06, 0x80, + 0x49, 0x2A, 0x2E, 0x2A, 0x9C, 0x2A, 0x01, 0x0C, 0x12, 0x2A, 0x01, 0x01, + 0x0F, 0x47, 0x01, 0x02, 0x0F, 0x39, 0x06, 0x0A, 0x2A, 0x02, 0x09, 0x13, + 0x05, 0x04, 0x65, 0x01, 0x00, 0x2A, 0x02, 0x08, 0x05, 0x0E, 0x2A, 0x01, + 0x81, 0x70, 0x13, 0x01, 0x20, 0x0E, 0x06, 0x04, 0x65, 0x01, 0x00, 0x2A, + 0x2A, 0x06, 0x10, 0x02, 0x05, 0x63, 0x40, 0x02, 0x05, 0x40, 0x02, 0x05, + 0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0x01, 0x65, 0x01, 0x04, 0x08, 0x04, + 0xFF, 0x30, 0x29, 0x02, 0x05, 0x7B, 0x09, 0x01, 0x02, 0x12, 0x2A, 0x05, + 0x03, 0x01, 0x28, 0xA3, 0x7C, 0x42, 0x8C, 0x2E, 0x01, 0x83, 0xFF, 0x7F, + 0x0F, 0x06, 0x0D, 0x01, 0x03, 0xA4, 0x06, 0x04, 0x01, 0x80, 0x78, 0xA3, + 0x01, 0x00, 0x8C, 0x40, 0x18, 0x05, 0x03, 0x01, 0x28, 0xA3, 0x01, 0x00, + 0x00, 0x00, 0xB4, 0xB3, 0x00, 0x04, 0x78, 0x2E, 0xCE, 0x06, 0x16, 0xC0, + 0x2A, 0x01, 0x84, 0x00, 0x10, 0x06, 0x02, 0x6F, 0x2B, 0x2A, 0x03, 0x00, + 0x85, 0x47, 0xB6, 0x02, 0x00, 0x78, 0x2E, 0xA8, 0x27, 0x78, 0x2E, 0x2A, + 0xCC, 0x47, 0xCB, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x39, + 0x06, 0x14, 0xC2, 0x2A, 0x03, 0x03, 0x85, 0x47, 0xB6, 0x02, 0x03, 0x78, + 0x2E, 0xA8, 0x02, 0x02, 0x06, 0x03, 0x26, 0x04, 0x01, 0x24, 0x9D, 0x00, + 0x00, 0xBA, 0x01, 0x10, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x00, 0x00, 0x9E, + 0xBA, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x73, 0x2B, 0x85, 0x01, 0x0C, 0x08, + 0x01, 0x0C, 0xB6, 0x9D, 0x85, 0x2A, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x32, + 0x05, 0x02, 0x67, 0x2B, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00, + 0x9A, 0x02, 0x01, 0x02, 0x00, 0x3C, 0x2A, 0x01, 0x00, 0x0F, 0x06, 0x02, + 0x65, 0x00, 0xD1, 0x04, 0x74, 0x00, 0xC0, 0x01, 0x01, 0x0E, 0x06, 0x02, + 0x68, 0x2B, 0xC2, 0x2A, 0x2A, 0x5F, 0x47, 0x01, 0x05, 0x11, 0x39, 0x06, + 0x02, 0x68, 0x2B, 0x01, 0x08, 0x08, 0x2A, 0x84, 0x30, 0x0B, 0x06, 0x0D, + 0x2A, 0x01, 0x01, 0x47, 0x0C, 0x3F, 0x2A, 0x84, 0x42, 0x86, 0x42, 0x04, + 0x01, 0x29, 0x00, 0x00, 0xC0, 0x8A, 0x30, 0x01, 0x00, 0x3A, 0x0F, 0x06, + 0x13, 0x29, 0x01, 0x01, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0xC2, 0x06, 0x02, + 0x6B, 0x2B, 0x01, 0x02, 0x8A, 0x42, 0x04, 0x28, 0x01, 0x02, 0x3A, 0x0F, + 0x06, 0x1F, 0x29, 0x01, 0x0D, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0xC2, 0x01, + 0x0C, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0x85, 0x01, 0x0C, 0xB6, 0x8B, 0x85, + 0x01, 0x0C, 0x32, 0x05, 0x02, 0x6B, 0x2B, 0x04, 0x03, 0x6B, 0x2B, 0x29, + 0x00, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x2A, 0x06, 0x1D, 0xC2, 0x06, 0x03, + 0xBC, 0x04, 0x15, 0xC0, 0x2A, 0x01, 0x81, 0x7F, 0x0D, 0x06, 0x0C, 0x2A, + 0x8D, 0x08, 0x01, 0x00, 0x47, 0x42, 0x8D, 0x47, 0xB6, 0x04, 0x01, 0xC9, + 0x04, 0x60, 0x9D, 0x9D, 0x00, 0x00, 0xBB, 0x2A, 0x5F, 0x06, 0x07, 0x29, + 0x06, 0x02, 0x69, 0x2B, 0x04, 0x74, 0x00, 0x00, 0xC3, 0x01, 0x03, 0xC1, + 0x47, 0x29, 0x47, 0x00, 0x00, 0xC0, 0xC9, 0x00, 0x03, 0x01, 0x00, 0x03, + 0x00, 0xC0, 0xA7, 0x2A, 0x06, 0x80, 0x50, 0xC2, 0x03, 0x01, 0xC2, 0x03, + 0x02, 0x02, 0x01, 0x01, 0x08, 0x0F, 0x06, 0x16, 0x02, 0x02, 0x01, 0x0F, + 0x0D, 0x06, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x01, 0x10, 0x08, 0x0C, 0x02, + 0x00, 0x39, 0x03, 0x00, 0x04, 0x2A, 0x02, 0x01, 0x01, 0x02, 0x11, 0x02, + 0x01, 0x01, 0x06, 0x0D, 0x13, 0x02, 0x02, 0x01, 0x01, 0x0F, 0x02, 0x02, + 0x01, 0x03, 0x0F, 0x39, 0x13, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x62, 0x01, 0x02, 0x0C, 0x02, 0x01, 0x08, 0x0C, 0x39, 0x03, 0x00, + 0x04, 0xFF, 0x2C, 0x9D, 0x02, 0x00, 0x00, 0x00, 0xC0, 0xA7, 0xBD, 0x82, + 0x41, 0x9D, 0x00, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x01, 0x00, 0x7E, 0x41, + 0x2A, 0x06, 0x15, 0xC0, 0x2A, 0x01, 0x20, 0x0B, 0x06, 0x0B, 0x01, 0x01, + 0x47, 0x0C, 0x7E, 0x2F, 0x39, 0x7E, 0x41, 0x04, 0x01, 0x29, 0x04, 0x68, + 0x9D, 0x9D, 0x00, 0x00, 0x01, 0x02, 0x9A, 0xC3, 0x01, 0x08, 0x0C, 0xC3, + 0x08, 0x00, 0x00, 0x01, 0x03, 0x9A, 0xC3, 0x01, 0x08, 0x0C, 0xC3, 0x08, + 0x01, 0x08, 0x0C, 0xC3, 0x08, 0x00, 0x00, 0x01, 0x01, 0x9A, 0xC3, 0x00, + 0x00, 0x3D, 0x2A, 0x5D, 0x05, 0x01, 0x00, 0x29, 0xD1, 0x04, 0x76, 0x02, + 0x03, 0x00, 0x94, 0x30, 0x03, 0x01, 0x01, 0x00, 0x2A, 0x02, 0x01, 0x0B, + 0x06, 0x10, 0x2A, 0x01, 0x01, 0x0C, 0x93, 0x08, 0x2E, 0x02, 0x00, 0x0F, + 0x06, 0x01, 0x00, 0x61, 0x04, 0x6A, 0x29, 0x01, 0x7F, 0x00, 0x00, 0x2C, + 0x19, 0x38, 0x06, 0x04, 0xCF, 0x29, 0x04, 0x78, 0x01, 0x16, 0x89, 0x42, + 0x01, 0x00, 0xE2, 0x01, 0x00, 0xE1, 0x2C, 0x01, 0x17, 0x89, 0x42, 0x00, + 0x00, 0x01, 0x15, 0x89, 0x42, 0x47, 0x57, 0x29, 0x57, 0x29, 0x2C, 0x00, + 0x00, 0x01, 0x01, 0x47, 0xC6, 0x00, 0x00, 0xBB, 0x01, 0x01, 0x0F, 0x05, + 0x02, 0x73, 0x2B, 0x2A, 0xC9, 0x29, 0x00, 0x00, 0x47, 0x3A, 0x9A, 0x47, + 0x2A, 0x06, 0x05, 0xC3, 0x29, 0x62, 0x04, 0x78, 0x29, 0x00, 0x02, 0x03, + 0x00, 0x78, 0x2E, 0x9C, 0x03, 0x01, 0x02, 0x01, 0x01, 0x0F, 0x13, 0x02, + 0x01, 0x01, 0x04, 0x12, 0x01, 0x0F, 0x13, 0x02, 0x01, 0x01, 0x08, 0x12, + 0x01, 0x0F, 0x13, 0x01, 0x00, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x00, + 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x81, + 0x0D, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x01, 0x01, 0x10, + 0x02, 0x00, 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x80, 0x77, 0x01, + 0x02, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x01, 0x01, 0x20, 0x02, 0x00, + 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x80, 0x61, 0x01, 0x03, 0x3A, + 0x0F, 0x06, 0x0F, 0x29, 0x29, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x4A, + 0x04, 0x01, 0x4B, 0x04, 0x80, 0x4C, 0x01, 0x04, 0x3A, 0x0F, 0x06, 0x0E, + 0x29, 0x29, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x4A, 0x04, 0x01, 0x4B, + 0x04, 0x38, 0x01, 0x05, 0x3A, 0x0F, 0x06, 0x0C, 0x29, 0x29, 0x02, 0x00, + 0x06, 0x03, 0x4E, 0x04, 0x01, 0x4F, 0x04, 0x26, 0x2A, 0x01, 0x09, 0x10, + 0x06, 0x02, 0x6A, 0x2B, 0x47, 0x29, 0x2A, 0x01, 0x01, 0x13, 0x01, 0x04, + 0x0C, 0x01, 0x10, 0x08, 0x47, 0x01, 0x08, 0x13, 0x01, 0x10, 0x47, 0x09, + 0x02, 0x00, 0x06, 0x03, 0x48, 0x04, 0x01, 0x49, 0x00, 0x29, 0x00, 0x00, + 0x9C, 0x01, 0x0C, 0x12, 0x01, 0x02, 0x10, 0x00, 0x00, 0x9C, 0x01, 0x0C, + 0x12, 0x2A, 0x60, 0x47, 0x01, 0x03, 0x0B, 0x13, 0x00, 0x00, 0x9C, 0x01, + 0x0C, 0x12, 0x01, 0x01, 0x0F, 0x00, 0x00, 0x9C, 0x01, 0x0C, 0x12, 0x5F, + 0x00, 0x00, 0x1B, 0x01, 0x00, 0x75, 0x30, 0x2A, 0x06, 0x22, 0x01, 0x01, + 0x3A, 0x0F, 0x06, 0x06, 0x29, 0x01, 0x00, 0xA0, 0x04, 0x14, 0x01, 0x02, + 0x3A, 0x0F, 0x06, 0x0D, 0x29, 0x77, 0x30, 0x01, 0x01, 0x0F, 0x06, 0x03, + 0x01, 0x10, 0x39, 0x04, 0x01, 0x29, 0x04, 0x01, 0x29, 0x7D, 0x30, 0x05, + 0x33, 0x31, 0x06, 0x30, 0x88, 0x30, 0x01, 0x14, 0x3A, 0x0F, 0x06, 0x06, + 0x29, 0x01, 0x02, 0x39, 0x04, 0x22, 0x01, 0x15, 0x3A, 0x0F, 0x06, 0x09, + 0x29, 0xAA, 0x06, 0x03, 0x01, 0x7F, 0xA0, 0x04, 0x13, 0x01, 0x16, 0x3A, + 0x0F, 0x06, 0x06, 0x29, 0x01, 0x01, 0x39, 0x04, 0x07, 0x29, 0x01, 0x04, + 0x39, 0x01, 0x00, 0x29, 0x19, 0x06, 0x03, 0x01, 0x08, 0x39, 0x00, 0x00, + 0x1B, 0x2A, 0x05, 0x13, 0x31, 0x06, 0x10, 0x88, 0x30, 0x01, 0x15, 0x0F, + 0x06, 0x08, 0x29, 0xAA, 0x01, 0x00, 0x77, 0x42, 0x04, 0x01, 0x23, 0x00, + 0x00, 0xCF, 0x01, 0x07, 0x13, 0x01, 0x01, 0x10, 0x06, 0x02, 0x73, 0x2B, + 0x00, 0x01, 0x03, 0x00, 0x2C, 0x19, 0x06, 0x05, 0x02, 0x00, 0x89, 0x42, + 0x00, 0xCF, 0x29, 0x04, 0x74, 0x00, 0x01, 0x14, 0xD2, 0x01, 0x01, 0xE2, + 0x2C, 0x2A, 0x01, 0x00, 0xCA, 0x01, 0x16, 0xD2, 0xD6, 0x2C, 0x00, 0x00, + 0x01, 0x0B, 0xE2, 0x52, 0x2A, 0x2A, 0x01, 0x03, 0x08, 0xE1, 0xE1, 0x14, + 0x2A, 0x5D, 0x06, 0x02, 0x29, 0x00, 0xE1, 0x1E, 0x2A, 0x06, 0x05, 0x85, + 0x47, 0xDA, 0x04, 0x77, 0x29, 0x04, 0x6C, 0x00, 0x01, 0x00, 0xDC, 0x95, + 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06, 0x05, 0x63, 0x01, 0x00, 0xDD, 0x08, + 0x50, 0x08, 0x01, 0x03, 0x08, 0x01, 0x0D, 0xE2, 0xE1, 0x01, 0x00, 0xDC, + 0xE2, 0x01, 0x01, 0xDC, 0x29, 0x95, 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06, + 0x08, 0x01, 0x00, 0xDD, 0xE0, 0x01, 0x01, 0xDD, 0x29, 0x50, 0xE0, 0x16, + 0x15, 0x2A, 0x5D, 0x06, 0x02, 0x29, 0x00, 0xE0, 0x1F, 0x2A, 0x06, 0x05, + 0x85, 0x47, 0xDA, 0x04, 0x77, 0x29, 0x04, 0x6C, 0x00, 0x9E, 0x01, 0x14, + 0xE2, 0x01, 0x0C, 0xE1, 0x85, 0x01, 0x0C, 0xDA, 0x00, 0x04, 0x03, 0x00, + 0x01, 0x02, 0xE2, 0x01, 0x80, 0x46, 0x8A, 0x30, 0x01, 0x02, 0x0F, 0x06, + 0x0C, 0x02, 0x00, 0x06, 0x04, 0x01, 0x05, 0x04, 0x02, 0x01, 0x1D, 0x04, + 0x02, 0x01, 0x00, 0x03, 0x01, 0x86, 0x30, 0x06, 0x04, 0x01, 0x05, 0x04, + 0x02, 0x01, 0x00, 0x03, 0x02, 0x8C, 0x2E, 0x2A, 0x06, 0x05, 0x62, 0x21, + 0x01, 0x07, 0x08, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x02, 0x03, + 0x08, 0x2A, 0x06, 0x03, 0x01, 0x02, 0x08, 0x08, 0xE1, 0x95, 0x2E, 0xE0, + 0x8E, 0x01, 0x04, 0x17, 0x8E, 0x01, 0x04, 0x08, 0x01, 0x1C, 0x34, 0x8E, + 0x01, 0x20, 0xDA, 0x01, 0x20, 0xE2, 0x8F, 0x01, 0x20, 0xDA, 0x78, 0x2E, + 0xE0, 0x01, 0x00, 0xE2, 0x02, 0x01, 0x02, 0x02, 0x08, 0x02, 0x03, 0x08, + 0x2A, 0x06, 0x80, 0x40, 0xE0, 0x02, 0x01, 0x2A, 0x06, 0x10, 0x01, 0x83, + 0xFE, 0x01, 0xE0, 0x01, 0x04, 0x09, 0x2A, 0xE0, 0x62, 0x8B, 0x47, 0xDB, + 0x04, 0x01, 0x29, 0x02, 0x02, 0x06, 0x0C, 0x01, 0x01, 0xE0, 0x01, 0x01, + 0xE0, 0x86, 0x30, 0x01, 0x08, 0x09, 0xE2, 0x02, 0x03, 0x2A, 0x06, 0x11, + 0x01, 0x10, 0xE0, 0x01, 0x04, 0x09, 0x2A, 0xE0, 0x64, 0x2A, 0xE0, 0x62, + 0x85, 0x47, 0xDB, 0x04, 0x01, 0x29, 0x04, 0x01, 0x29, 0x00, 0x00, 0x01, + 0x0E, 0xE2, 0x01, 0x00, 0xE1, 0x00, 0x03, 0x78, 0x2E, 0xCC, 0x05, 0x01, + 0x00, 0x7E, 0x2F, 0x2A, 0x01, 0x82, 0x80, 0x80, 0x80, 0x00, 0x13, 0x06, + 0x05, 0x29, 0x01, 0x1D, 0x04, 0x0E, 0x2A, 0x01, 0x83, 0xC0, 0x80, 0x80, + 0x00, 0x13, 0x2A, 0x06, 0x01, 0x47, 0x29, 0xA5, 0x03, 0x00, 0x02, 0x00, + 0x25, 0x2A, 0x5D, 0x06, 0x02, 0x37, 0x2B, 0x03, 0x01, 0x95, 0x2E, 0x01, + 0x86, 0x03, 0x11, 0x03, 0x02, 0x01, 0x0C, 0xE2, 0x02, 0x01, 0x80, 0x30, + 0x08, 0x02, 0x02, 0x01, 0x02, 0x13, 0x08, 0x01, 0x06, 0x08, 0xE1, 0x01, + 0x03, 0xE2, 0x02, 0x00, 0xE0, 0x7F, 0x80, 0x30, 0xDB, 0x02, 0x02, 0x06, + 0x1C, 0x92, 0x2E, 0x2A, 0x01, 0x83, 0xFE, 0x00, 0x0B, 0x06, 0x03, 0xE0, + 0x04, 0x0F, 0x01, 0x81, 0x7F, 0x13, 0xE2, 0x78, 0x2E, 0xCD, 0x01, 0x01, + 0x0C, 0x01, 0x03, 0x08, 0xE2, 0x02, 0x01, 0xE0, 0x85, 0x02, 0x01, 0xDA, + 0x00, 0x00, 0x56, 0x2A, 0x01, 0x00, 0x0F, 0x06, 0x02, 0x65, 0x00, 0xCF, + 0x29, 0x04, 0x73, 0x00, 0x2A, 0xE2, 0xDA, 0x00, 0x00, 0x01, 0x00, 0x78, + 0x2E, 0xCB, 0x06, 0x0C, 0x63, 0x3A, 0x06, 0x08, 0x01, 0x80, 0x41, 0xE2, + 0x01, 0x80, 0x42, 0xE2, 0x46, 0x06, 0x07, 0x61, 0x3A, 0x06, 0x03, 0x01, + 0x01, 0xE2, 0x45, 0x06, 0x08, 0x61, 0x3A, 0x06, 0x04, 0x01, 0x80, 0x40, + 0xE2, 0x47, 0x29, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x46, 0x45, 0x39, + 0x05, 0x14, 0x01, 0x01, 0x01, 0x80, 0x7C, 0xDE, 0x03, 0x00, 0x01, 0x03, + 0x01, 0x80, 0x7C, 0xDE, 0x02, 0x00, 0x08, 0x47, 0x29, 0x00, 0x46, 0x06, + 0x07, 0x01, 0x01, 0x44, 0x29, 0xDE, 0x03, 0x00, 0x45, 0x06, 0x0A, 0x01, + 0x03, 0x44, 0x29, 0xDE, 0x02, 0x00, 0x08, 0x03, 0x00, 0x29, 0x02, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x04, 0xDF, 0x01, 0x05, 0xDF, 0x01, 0x06, + 0xDF, 0x01, 0x03, 0xDF, 0x01, 0x02, 0xDF, 0x0A, 0x65, 0x00, 0x01, 0x03, + 0x00, 0x3A, 0x01, 0x01, 0x02, 0x00, 0x0C, 0x13, 0x05, 0x01, 0x00, 0x63, + 0x01, 0x03, 0x3B, 0x06, 0x07, 0x02, 0x00, 0xE2, 0x01, 0x02, 0x3B, 0xE2, + 0x00, 0x00, 0x2A, 0x01, 0x08, 0x54, 0xE2, 0xE2, 0x00, 0x00, 0x2A, 0x01, + 0x10, 0x54, 0xE2, 0xE0, 0x00, 0x00, 0x2A, 0x57, 0x06, 0x02, 0x29, 0x00, + 0xCF, 0x29, 0x04, 0x76 +}; + +static const uint16_t t0_caddr[] = { + 0, + 5, + 10, + 15, + 20, + 25, + 30, + 35, + 40, + 44, + 48, + 52, + 56, + 60, + 64, + 68, + 72, + 76, + 80, + 84, + 88, + 92, + 96, + 100, + 104, + 109, + 114, + 119, + 124, + 129, + 134, + 139, + 144, + 149, + 154, + 159, + 164, + 169, + 174, + 180, + 185, + 190, + 195, + 200, + 205, + 210, + 215, + 220, + 225, + 230, + 235, + 240, + 245, + 250, + 255, + 260, + 265, + 270, + 275, + 280, + 285, + 290, + 299, + 303, + 328, + 334, + 353, + 364, + 405, + 516, + 520, + 553, + 563, + 587, + 669, + 683, + 689, + 748, + 767, + 789, + 838, + 887, + 963, + 1065, + 1076, + 1670, + 1674, + 1741, + 1751, + 1782, + 1806, + 1852, + 1922, + 1962, + 1976, + 1985, + 1989, + 2084, + 2092, + 2128, + 2139, + 2155, + 2161, + 2172, + 2207, + 2233, + 2245, + 2251, + 2264, + 2279, + 2472, + 2481, + 2494, + 2503, + 2510, + 2616, + 2641, + 2654, + 2670, + 2688, + 2720, + 2793, + 2806, + 2987, + 2995, + 3122, + 3136, + 3141, + 3185, + 3242, + 3263, + 3290, + 3298, + 3306 +}; + +#define T0_INTERPRETED 93 + +#define T0_ENTER(ip, rp, slot) do { \ + const unsigned char *t0_newip; \ + uint32_t t0_lnum; \ + t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ + t0_lnum = t0_parse7E_unsigned(&t0_newip); \ + (rp) += t0_lnum; \ + *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ + (ip) = t0_newip; \ + } while (0) + +#define T0_DEFENTRY(name, slot) \ +void \ +name(void *ctx) \ +{ \ + t0_context *t0ctx = ctx; \ + t0ctx->ip = &t0_codeblock[0]; \ + T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ +} + +T0_DEFENTRY(br_ssl_hs_server_init_main, 166) + +#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) + +void +br_ssl_hs_server_run(void *t0ctx) +{ + uint32_t *dp, *rp; + const unsigned char *ip; + +#define T0_LOCAL(x) (*(rp - 2 - (x))) +#define T0_POP() (*-- dp) +#define T0_POPi() (*(int32_t *)(-- dp)) +#define T0_PEEK(x) (*(dp - 1 - (x))) +#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) +#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) +#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) +#define T0_RPOP() (*-- rp) +#define T0_RPOPi() (*(int32_t *)(-- rp)) +#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) +#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) +#define T0_ROLL(x) do { \ + size_t t0len = (size_t)(x); \ + uint32_t t0tmp = *(dp - 1 - t0len); \ + memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_SWAP() do { \ + uint32_t t0tmp = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_ROT() do { \ + uint32_t t0tmp = *(dp - 3); \ + *(dp - 3) = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_NROT() do { \ + uint32_t t0tmp = *(dp - 1); \ + *(dp - 1) = *(dp - 2); \ + *(dp - 2) = *(dp - 3); \ + *(dp - 3) = t0tmp; \ +} while (0) +#define T0_PICK(x) do { \ + uint32_t t0depth = (x); \ + T0_PUSH(T0_PEEK(t0depth)); \ +} while (0) +#define T0_CO() do { \ + goto t0_exit; \ +} while (0) +#define T0_RET() goto t0_next + + dp = ((t0_context *)t0ctx)->dp; + rp = ((t0_context *)t0ctx)->rp; + ip = ((t0_context *)t0ctx)->ip; + goto t0_next; + for (;;) { + uint32_t t0x; + + t0_next: + t0x = T0_NEXT(&ip); + if (t0x < T0_INTERPRETED) { + switch (t0x) { + int32_t t0off; + + case 0: /* ret */ + t0x = T0_RPOP(); + rp -= (t0x >> 16); + t0x &= 0xFFFF; + if (t0x == 0) { + ip = NULL; + goto t0_exit; + } + ip = &t0_codeblock[t0x]; + break; + case 1: /* literal constant */ + T0_PUSHi(t0_parse7E_signed(&ip)); + break; + case 2: /* read local */ + T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); + break; + case 3: /* write local */ + T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); + break; + case 4: /* jump */ + t0off = t0_parse7E_signed(&ip); + ip += t0off; + break; + case 5: /* jump if */ + t0off = t0_parse7E_signed(&ip); + if (T0_POP()) { + ip += t0off; + } + break; + case 6: /* jump if not */ + t0off = t0_parse7E_signed(&ip); + if (!T0_POP()) { + ip += t0off; + } + break; + case 7: { + /* * */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a * b); + + } + break; + case 8: { + /* + */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a + b); + + } + break; + case 9: { + /* - */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a - b); + + } + break; + case 10: { + /* -rot */ + T0_NROT(); + } + break; + case 11: { + /* < */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a < b)); + + } + break; + case 12: { + /* << */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x << c); + + } + break; + case 13: { + /* <= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a <= b)); + + } + break; + case 14: { + /* <> */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a != b)); + + } + break; + case 15: { + /* = */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a == b)); + + } + break; + case 16: { + /* > */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a > b)); + + } + break; + case 17: { + /* >= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a >= b)); + + } + break; + case 18: { + /* >> */ + + int c = (int)T0_POPi(); + int32_t x = T0_POPi(); + T0_PUSHi(x >> c); + + } + break; + case 19: { + /* and */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a & b); + + } + break; + case 20: { + /* begin-cert */ + + if (ENG->chain_len == 0) { + T0_PUSHi(-1); + } else { + ENG->cert_cur = ENG->chain->data; + ENG->cert_len = ENG->chain->data_len; + ENG->chain ++; + ENG->chain_len --; + T0_PUSH(ENG->cert_len); + } + + } + break; + case 21: { + /* begin-ta-name */ + + const br_x500_name *dn; + if (CTX->cur_dn_index >= CTX->num_tas) { + T0_PUSHi(-1); + } else { + if (CTX->ta_names == NULL) { + dn = &CTX->tas[CTX->cur_dn_index].dn; + } else { + dn = &CTX->ta_names[CTX->cur_dn_index]; + } + CTX->cur_dn_index ++; + CTX->cur_dn = dn->data; + CTX->cur_dn_len = dn->len; + T0_PUSH(CTX->cur_dn_len); + } + + } + break; + case 22: { + /* begin-ta-name-list */ + + CTX->cur_dn_index = 0; + + } + break; + case 23: { + /* bzero */ + + size_t len = (size_t)T0_POP(); + void *addr = (unsigned char *)ENG + (size_t)T0_POP(); + memset(addr, 0, len); + + } + break; + case 24: { + /* call-policy-handler */ + + int x; + br_ssl_server_choices choices; + + x = (*CTX->policy_vtable)->choose( + CTX->policy_vtable, CTX, &choices); + ENG->session.cipher_suite = choices.cipher_suite; + CTX->sign_hash_id = choices.algo_id; + ENG->chain = choices.chain; + ENG->chain_len = choices.chain_len; + T0_PUSHi(-(x != 0)); + + } + break; + case 25: { + /* can-output? */ + + T0_PUSHi(-(ENG->hlen_out > 0)); + + } + break; + case 26: { + /* check-resume */ + + if (ENG->session.session_id_len == 32 + && CTX->cache_vtable != NULL && (*CTX->cache_vtable)->load( + CTX->cache_vtable, CTX, &ENG->session)) + { + T0_PUSHi(-1); + } else { + T0_PUSH(0); + } + + } + break; + case 27: { + /* co */ + T0_CO(); + } + break; + case 28: { + /* compute-Finished-inner */ + + int prf_id = T0_POP(); + int from_client = T0_POPi(); + unsigned char tmp[48]; + br_tls_prf_seed_chunk seed; + + br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id); + seed.data = tmp; + if (ENG->session.version >= BR_TLS12) { + seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp); + } else { + br_multihash_out(&ENG->mhash, br_md5_ID, tmp); + br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16); + seed.len = 36; + } + prf(ENG->pad, 12, ENG->session.master_secret, + sizeof ENG->session.master_secret, + from_client ? "client finished" : "server finished", + 1, &seed); + + } + break; + case 29: { + /* compute-hash-CV */ + + int i; + + for (i = 1; i <= 6; i ++) { + br_multihash_out(&ENG->mhash, i, + ENG->pad + HASH_PAD_OFF[i - 1]); + } + + } + break; + case 30: { + /* copy-cert-chunk */ + + size_t clen; + + clen = ENG->cert_len; + if (clen > sizeof ENG->pad) { + clen = sizeof ENG->pad; + } + memcpy(ENG->pad, ENG->cert_cur, clen); + ENG->cert_cur += clen; + ENG->cert_len -= clen; + T0_PUSH(clen); + + } + break; + case 31: { + /* copy-dn-chunk */ + + size_t clen; + + clen = CTX->cur_dn_len; + if (clen > sizeof ENG->pad) { + clen = sizeof ENG->pad; + } + memcpy(ENG->pad, CTX->cur_dn, clen); + CTX->cur_dn += clen; + CTX->cur_dn_len -= clen; + T0_PUSH(clen); + + } + break; + case 32: { + /* copy-hash-CV */ + + int id = T0_POP(); + size_t off, len; + + if (id == 0) { + off = 0; + len = 36; + } else { + if (br_multihash_getimpl(&ENG->mhash, id) == 0) { + T0_PUSH(0); + T0_RET(); + } + off = HASH_PAD_OFF[id - 1]; + len = HASH_PAD_OFF[id] - off; + } + memcpy(CTX->hash_CV, ENG->pad + off, len); + CTX->hash_CV_len = len; + CTX->hash_CV_id = id; + T0_PUSHi(-1); + + } + break; + case 33: { + /* copy-protocol-name */ + + size_t idx = T0_POP(); + size_t len = strlen(ENG->protocol_names[idx]); + memcpy(ENG->pad, ENG->protocol_names[idx], len); + T0_PUSH(len); + + } + break; + case 34: { + /* data-get8 */ + + size_t addr = T0_POP(); + T0_PUSH(t0_datablock[addr]); + + } + break; + case 35: { + /* discard-input */ + + ENG->hlen_in = 0; + + } + break; + case 36: { + /* do-ecdh */ + + int prf_id = T0_POPi(); + size_t len = T0_POP(); + do_ecdh(CTX, prf_id, ENG->pad, len); + + } + break; + case 37: { + /* do-ecdhe-part1 */ + + int curve = T0_POPi(); + T0_PUSHi(do_ecdhe_part1(CTX, curve)); + + } + break; + case 38: { + /* do-ecdhe-part2 */ + + int prf_id = T0_POPi(); + size_t len = T0_POP(); + do_ecdhe_part2(CTX, prf_id, ENG->pad, len); + + } + break; + case 39: { + /* do-rsa-decrypt */ + + int prf_id = T0_POPi(); + size_t len = T0_POP(); + do_rsa_decrypt(CTX, prf_id, ENG->pad, len); + + } + break; + case 40: { + /* do-static-ecdh */ + + do_static_ecdh(CTX, T0_POP()); + + } + break; + case 41: { + /* drop */ + (void)T0_POP(); + } + break; + case 42: { + /* dup */ + T0_PUSH(T0_PEEK(0)); + } + break; + case 43: { + /* fail */ + + br_ssl_engine_fail(ENG, (int)T0_POPi()); + T0_CO(); + + } + break; + case 44: { + /* flush-record */ + + br_ssl_engine_flush_record(ENG); + + } + break; + case 45: { + /* get-key-type-usages */ + + const br_x509_class *xc; + const br_x509_pkey *pk; + unsigned usages; + + xc = *(ENG->x509ctx); + pk = xc->get_pkey(ENG->x509ctx, &usages); + if (pk == NULL) { + T0_PUSH(0); + } else { + T0_PUSH(pk->key_type | usages); + } + + } + break; + case 46: { + /* get16 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr)); + + } + break; + case 47: { + /* get32 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr)); + + } + break; + case 48: { + /* get8 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*((unsigned char *)ENG + addr)); + + } + break; + case 49: { + /* has-input? */ + + T0_PUSHi(-(ENG->hlen_in != 0)); + + } + break; + case 50: { + /* memcmp */ + + size_t len = (size_t)T0_POP(); + void *addr2 = (unsigned char *)ENG + (size_t)T0_POP(); + void *addr1 = (unsigned char *)ENG + (size_t)T0_POP(); + int x = memcmp(addr1, addr2, len); + T0_PUSH((uint32_t)-(x == 0)); + + } + break; + case 51: { + /* memcpy */ + + size_t len = (size_t)T0_POP(); + void *src = (unsigned char *)ENG + (size_t)T0_POP(); + void *dst = (unsigned char *)ENG + (size_t)T0_POP(); + memcpy(dst, src, len); + + } + break; + case 52: { + /* mkrand */ + + size_t len = (size_t)T0_POP(); + void *addr = (unsigned char *)ENG + (size_t)T0_POP(); + br_hmac_drbg_generate(&ENG->rng, addr, len); + + } + break; + case 53: { + /* more-incoming-bytes? */ + + T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG)); + + } + break; + case 54: { + /* multihash-init */ + + br_multihash_init(&ENG->mhash); + + } + break; + case 55: { + /* neg */ + + uint32_t a = T0_POP(); + T0_PUSH(-a); + + } + break; + case 56: { + /* not */ + + uint32_t a = T0_POP(); + T0_PUSH(~a); + + } + break; + case 57: { + /* or */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a | b); + + } + break; + case 58: { + /* over */ + T0_PUSH(T0_PEEK(1)); + } + break; + case 59: { + /* pick */ + T0_PICK(T0_POP()); + } + break; + case 60: { + /* read-chunk-native */ + + size_t clen = ENG->hlen_in; + if (clen > 0) { + uint32_t addr, len; + + len = T0_POP(); + addr = T0_POP(); + if ((size_t)len < clen) { + clen = (size_t)len; + } + memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); + if (ENG->record_type_in == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen); + } + T0_PUSH(addr + (uint32_t)clen); + T0_PUSH(len - (uint32_t)clen); + ENG->hbuf_in += clen; + ENG->hlen_in -= clen; + } + + } + break; + case 61: { + /* read8-native */ + + if (ENG->hlen_in > 0) { + unsigned char x; + + x = *ENG->hbuf_in ++; + if (ENG->record_type_in == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, &x, 1); + } + T0_PUSH(x); + ENG->hlen_in --; + } else { + T0_PUSHi(-1); + } + + } + break; + case 62: { + /* save-session */ + + if (CTX->cache_vtable != NULL) { + (*CTX->cache_vtable)->save( + CTX->cache_vtable, CTX, &ENG->session); + } + + } + break; + case 63: { + /* set-max-frag-len */ + + size_t max_frag_len = T0_POP(); + + br_ssl_engine_new_max_frag_len(ENG, max_frag_len); + + /* + * We must adjust our own output limit. Since we call this only + * after receiving a ClientHello and before beginning to send + * the ServerHello, the next output record should be empty at + * that point, so we can use max_frag_len as a limit. + */ + if (ENG->hlen_out > max_frag_len) { + ENG->hlen_out = max_frag_len; + } + + } + break; + case 64: { + /* set16 */ + + size_t addr = (size_t)T0_POP(); + *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP(); + + } + break; + case 65: { + /* set32 */ + + size_t addr = (size_t)T0_POP(); + *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP(); + + } + break; + case 66: { + /* set8 */ + + size_t addr = (size_t)T0_POP(); + *((unsigned char *)ENG + addr) = (unsigned char)T0_POP(); + + } + break; + case 67: { + /* supported-curves */ + + uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves; + T0_PUSH(x); + + } + break; + case 68: { + /* supported-hash-functions */ + + int i; + unsigned x, num; + + x = 0; + num = 0; + for (i = br_sha1_ID; i <= br_sha512_ID; i ++) { + if (br_multihash_getimpl(&ENG->mhash, i)) { + x |= 1U << i; + num ++; + } + } + T0_PUSH(x); + T0_PUSH(num); + + } + break; + case 69: { + /* supports-ecdsa? */ + + T0_PUSHi(-(ENG->iecdsa != 0)); + + } + break; + case 70: { + /* supports-rsa-sign? */ + + T0_PUSHi(-(ENG->irsavrfy != 0)); + + } + break; + case 71: { + /* swap */ + T0_SWAP(); + } + break; + case 72: { + /* switch-aesccm-in */ + + int is_client, prf_id; + unsigned cipher_key_len, tag_len; + + tag_len = T0_POP(); + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id, + ENG->iaes_ctrcbc, cipher_key_len, tag_len); + + } + break; + case 73: { + /* switch-aesccm-out */ + + int is_client, prf_id; + unsigned cipher_key_len, tag_len; + + tag_len = T0_POP(); + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id, + ENG->iaes_ctrcbc, cipher_key_len, tag_len); + + } + break; + case 74: { + /* switch-aesgcm-in */ + + int is_client, prf_id; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id, + ENG->iaes_ctr, cipher_key_len); + + } + break; + case 75: { + /* switch-aesgcm-out */ + + int is_client, prf_id; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id, + ENG->iaes_ctr, cipher_key_len); + + } + break; + case 76: { + /* switch-cbc-in */ + + int is_client, prf_id, mac_id, aes; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + aes = T0_POP(); + mac_id = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id, + aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len); + + } + break; + case 77: { + /* switch-cbc-out */ + + int is_client, prf_id, mac_id, aes; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + aes = T0_POP(); + mac_id = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id, + aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len); + + } + break; + case 78: { + /* switch-chapol-in */ + + int is_client, prf_id; + + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id); + + } + break; + case 79: { + /* switch-chapol-out */ + + int is_client, prf_id; + + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id); + + } + break; + case 80: { + /* ta-names-total-length */ + + size_t u, len; + + len = 0; + if (CTX->ta_names != NULL) { + for (u = 0; u < CTX->num_tas; u ++) { + len += CTX->ta_names[u].len + 2; + } + } else if (CTX->tas != NULL) { + for (u = 0; u < CTX->num_tas; u ++) { + len += CTX->tas[u].dn.len + 2; + } + } + T0_PUSH(len); + + } + break; + case 81: { + /* test-protocol-name */ + + size_t len = T0_POP(); + size_t u; + + for (u = 0; u < ENG->protocol_names_num; u ++) { + const char *name; + + name = ENG->protocol_names[u]; + if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) { + T0_PUSH(u); + T0_RET(); + } + } + T0_PUSHi(-1); + + } + break; + case 82: { + /* total-chain-length */ + + size_t u; + uint32_t total; + + total = 0; + for (u = 0; u < ENG->chain_len; u ++) { + total += 3 + (uint32_t)ENG->chain[u].data_len; + } + T0_PUSH(total); + + } + break; + case 83: { + /* u< */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a < b)); + + } + break; + case 84: { + /* u>> */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x >> c); + + } + break; + case 85: { + /* verify-CV-sig */ + + int err; + + err = verify_CV_sig(CTX, T0_POP()); + T0_PUSHi(err); + + } + break; + case 86: { + /* write-blob-chunk */ + + size_t clen = ENG->hlen_out; + if (clen > 0) { + uint32_t addr, len; + + len = T0_POP(); + addr = T0_POP(); + if ((size_t)len < clen) { + clen = (size_t)len; + } + memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); + if (ENG->record_type_out == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen); + } + T0_PUSH(addr + (uint32_t)clen); + T0_PUSH(len - (uint32_t)clen); + ENG->hbuf_out += clen; + ENG->hlen_out -= clen; + } + + } + break; + case 87: { + /* write8-native */ + + unsigned char x; + + x = (unsigned char)T0_POP(); + if (ENG->hlen_out > 0) { + if (ENG->record_type_out == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, &x, 1); + } + *ENG->hbuf_out ++ = x; + ENG->hlen_out --; + T0_PUSHi(-1); + } else { + T0_PUSHi(0); + } + + } + break; + case 88: { + /* x509-append */ + + const br_x509_class *xc; + size_t len; + + xc = *(ENG->x509ctx); + len = T0_POP(); + xc->append(ENG->x509ctx, ENG->pad, len); + + } + break; + case 89: { + /* x509-end-cert */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + xc->end_cert(ENG->x509ctx); + + } + break; + case 90: { + /* x509-end-chain */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + T0_PUSH(xc->end_chain(ENG->x509ctx)); + + } + break; + case 91: { + /* x509-start-cert */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + xc->start_cert(ENG->x509ctx, T0_POP()); + + } + break; + case 92: { + /* x509-start-chain */ + + const br_x509_class *xc; + uint32_t bc; + + bc = T0_POP(); + xc = *(ENG->x509ctx); + xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL); + + } + break; + } + + } else { + T0_ENTER(ip, rp, t0x); + } + } +t0_exit: + ((t0_context *)t0ctx)->dp = dp; + ((t0_context *)t0ctx)->rp = rp; + ((t0_context *)t0ctx)->ip = ip; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.t0 b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.t0 new file mode 100644 index 0000000..9f6e934 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_hs_server.t0 @@ -0,0 +1,1510 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +\ ---------------------------------------------------------------------- +\ Handshake processing code, for the server. +\ The common T0 code (ssl_hs_common.t0) shall be read first. + +preamble { + +/* + * This macro evaluates to a pointer to the server context, under that + * specific name. It must be noted that since the engine context is the + * first field of the br_ssl_server_context structure ('eng'), then + * pointers values of both types are interchangeable, modulo an + * appropriate cast. This also means that "addresses" computed as offsets + * within the structure work for both kinds of context. + */ +#define CTX ((br_ssl_server_context *)ENG) + +/* + * Decrypt the pre-master secret (RSA key exchange). + */ +static void +do_rsa_decrypt(br_ssl_server_context *ctx, int prf_id, + unsigned char *epms, size_t len) +{ + uint32_t x; + unsigned char rpms[48]; + + /* + * Decrypt the PMS. + */ + x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, epms, &len); + + /* + * Set the first two bytes to the maximum supported client + * protocol version. These bytes are used for version rollback + * detection; forceing the two bytes will make the master secret + * wrong if the bytes are not correct. This process is + * recommended by RFC 5246 (section 7.4.7.1). + */ + br_enc16be(epms, ctx->client_max_version); + + /* + * Make a random PMS and copy it above the decrypted value if the + * decryption failed. Note that we use a constant-time conditional + * copy. + */ + br_hmac_drbg_generate(&ctx->eng.rng, rpms, sizeof rpms); + br_ccopy(x ^ 1, epms, rpms, sizeof rpms); + + /* + * Compute master secret. + */ + br_ssl_engine_compute_master(&ctx->eng, prf_id, epms, 48); + + /* + * Clear the pre-master secret from RAM: it is normally a buffer + * in the context, hence potentially long-lived. + */ + memset(epms, 0, len); +} + +/* + * Common part for ECDH and ECDHE. + */ +static void +ecdh_common(br_ssl_server_context *ctx, int prf_id, + unsigned char *xcoor, size_t xcoor_len, uint32_t ctl) +{ + unsigned char rpms[80]; + + if (xcoor_len > sizeof rpms) { + xcoor_len = sizeof rpms; + ctl = 0; + } + + /* + * Make a random PMS and copy it above the decrypted value if the + * decryption failed. Note that we use a constant-time conditional + * copy. + */ + br_hmac_drbg_generate(&ctx->eng.rng, rpms, xcoor_len); + br_ccopy(ctl ^ 1, xcoor, rpms, xcoor_len); + + /* + * Compute master secret. + */ + br_ssl_engine_compute_master(&ctx->eng, prf_id, xcoor, xcoor_len); + + /* + * Clear the pre-master secret from RAM: it is normally a buffer + * in the context, hence potentially long-lived. + */ + memset(xcoor, 0, xcoor_len); +} + +/* + * Do the ECDH key exchange (not ECDHE). + */ +static void +do_ecdh(br_ssl_server_context *ctx, int prf_id, + unsigned char *cpoint, size_t cpoint_len) +{ + uint32_t x; + + /* + * Finalise the key exchange. + */ + x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, + cpoint, &cpoint_len); + 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); +} + +static size_t +hash_data(br_ssl_server_context *ctx, + void *dst, int hash_id, const void *src, size_t len) +{ + const br_hash_class *hf; + br_hash_compat_context hc; + + if (hash_id == 0) { + unsigned char tmp[36]; + + hf = br_multihash_getimpl(&ctx->eng.mhash, br_md5_ID); + if (hf == NULL) { + return 0; + } + hf->init(&hc.vtable); + hf->update(&hc.vtable, src, len); + hf->out(&hc.vtable, tmp); + hf = br_multihash_getimpl(&ctx->eng.mhash, br_sha1_ID); + if (hf == NULL) { + return 0; + } + hf->init(&hc.vtable); + hf->update(&hc.vtable, src, len); + hf->out(&hc.vtable, tmp + 16); + memcpy(dst, tmp, 36); + return 36; + } else { + hf = br_multihash_getimpl(&ctx->eng.mhash, hash_id); + if (hf == NULL) { + return 0; + } + hf->init(&hc.vtable); + hf->update(&hc.vtable, src, len); + hf->out(&hc.vtable, dst); + return (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; + } +} + +/* + * 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 + * signature length (in bytes), or -x on error (with x being an error + * code). The encoded point is written in the ecdhe_point[] context buffer + * (length in ecdhe_point_len). + */ +static int +do_ecdhe_part1(br_ssl_server_context *ctx, int curve) +{ + unsigned algo_id; + unsigned mask; + const unsigned char *order; + size_t olen, glen; + size_t hv_len, sig_len; + + if (!((ctx->eng.iec->supported_curves >> curve) & 1)) { + return -BR_ERR_INVALID_ALGORITHM; + } + ctx->eng.ecdhe_curve = curve; + + /* + * Generate our private key. We need a non-zero random value + * which is lower than the curve order, in a "large enough" + * range. We force the top bit to 0 and bottom bit to 1, which + * does the trick. Note that contrary to what happens in ECDSA, + * this is not a problem if we do not cover the full range of + * possible values. + */ + order = ctx->eng.iec->order(curve, &olen); + mask = 0xFF; + while (mask >= order[0]) { + mask >>= 1; + } + br_hmac_drbg_generate(&ctx->eng.rng, ctx->ecdhe_key, olen); + ctx->ecdhe_key[0] &= mask; + ctx->ecdhe_key[olen - 1] |= 0x01; + ctx->ecdhe_key_len = olen; + + /* + * Compute our ECDH point. + */ + glen = ctx->eng.iec->mulgen(ctx->eng.ecdhe_point, + ctx->ecdhe_key, olen, curve); + ctx->eng.ecdhe_point_len = glen; + + /* + * Assemble the message to be signed, and possibly hash it. + */ + memcpy(ctx->eng.pad, ctx->eng.client_random, 32); + memcpy(ctx->eng.pad + 32, ctx->eng.server_random, 32); + ctx->eng.pad[64 + 0] = 0x03; + ctx->eng.pad[64 + 1] = 0x00; + ctx->eng.pad[64 + 2] = curve; + ctx->eng.pad[64 + 3] = ctx->eng.ecdhe_point_len; + memcpy(ctx->eng.pad + 64 + 4, + ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len); + hv_len = 64 + 4 + ctx->eng.ecdhe_point_len; + algo_id = ctx->sign_hash_id; + if (algo_id >= (unsigned)0xFF00) { + hv_len = hash_data(ctx, ctx->eng.pad, algo_id & 0xFF, + ctx->eng.pad, hv_len); + if (hv_len == 0) { + return -BR_ERR_INVALID_ALGORITHM; + } + } + + sig_len = (*ctx->policy_vtable)->do_sign(ctx->policy_vtable, + algo_id, ctx->eng.pad, hv_len, sizeof ctx->eng.pad); + return sig_len ? (int)sig_len : -BR_ERR_INVALID_ALGORITHM; +} + +/* + * Do the ECDHE key exchange (part 2: computation of the shared secret + * from the point sent by the client). + */ +static void +do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id, + unsigned char *cpoint, size_t cpoint_len) +{ + int curve; + uint32_t ctl; + size_t xoff, xlen; + + curve = ctx->eng.ecdhe_curve; + + /* + * Finalise the key exchange. + */ + ctl = ctx->eng.iec->mul(cpoint, cpoint_len, + ctx->ecdhe_key, ctx->ecdhe_key_len, curve); + xoff = ctx->eng.iec->xoff(curve, &xlen); + ecdh_common(ctx, prf_id, cpoint + xoff, xlen, ctl); + + /* + * Clear the ECDHE private key. Forward Secrecy is achieved insofar + * as that key does not get stolen, so we'd better destroy it + * as soon as it ceases to be useful. + */ + 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; +} + +} + +\ ======================================================================= + +: addr-ctx: + next-word { field } + "addr-" field + 0 1 define-word + 0 8191 "offsetof(br_ssl_server_context, " field + ")" + make-CX + postpone literal postpone ; ; + +addr-ctx: client_max_version +addr-ctx: client_suites +addr-ctx: client_suites_num +addr-ctx: hashes +addr-ctx: curves +addr-ctx: sign_hash_id + +\ Get address and length of the client_suites[] buffer. Length is expressed +\ in bytes. +: addr-len-client_suites ( -- addr len ) + addr-client_suites + CX 0 1023 { BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated) } ; + +\ Read the client SNI extension. +: read-client-sni ( lim -- lim ) + \ Open extension value. + read16 open-elt + + \ Open ServerNameList. + read16 open-elt + + \ Find if there is a name of type 0 (host_name) with a length + \ that fits in our dedicated buffer. + begin dup while + read8 if + read-ignore-16 + else + read16 + dup 255 <= if + dup addr-server_name + 0 swap set8 + addr-server_name swap read-blob + else + skip-blob + then + then + repeat + + \ Close ServerNameList. + close-elt + + \ Close extension value. + close-elt ; + +\ Set the new maximum fragment length. BEWARE: this shall be called only +\ after reading the ClientHello and before writing the ServerHello. +cc: set-max-frag-len ( len -- ) { + size_t max_frag_len = T0_POP(); + + br_ssl_engine_new_max_frag_len(ENG, max_frag_len); + + /* + * We must adjust our own output limit. Since we call this only + * after receiving a ClientHello and before beginning to send + * the ServerHello, the next output record should be empty at + * that point, so we can use max_frag_len as a limit. + */ + if (ENG->hlen_out > max_frag_len) { + ENG->hlen_out = max_frag_len; + } +} + +\ Read the client Max Frag Length extension. +: read-client-frag ( lim -- lim ) + \ Extension value must have length exactly 1 byte. + read16 1 <> if ERR_BAD_FRAGLEN fail then + read8 + + \ The byte value must be 1, 2, 3 or 4. + dup dup 0= swap 5 >= or if ERR_BAD_FRAGLEN fail then + + \ If our own maximum fragment length is greater, then we reduce + \ our length. + 8 + dup addr-log_max_frag_len get8 < if + dup 1 swap << set-max-frag-len + dup addr-log_max_frag_len set8 + addr-peer_log_max_frag_len set8 + else + drop + then ; + +\ Read the Secure Renegotiation extension from the client. +: read-client-reneg ( lim -- lim ) + \ Get value length. + read16 + + \ The "reneg" value is one of: + \ 0 on first handshake, client support is unknown + \ 1 client does not support secure renegotiation + \ 2 client supports secure renegotiation + addr-reneg get8 case + 0 of + \ First handshake, value length shall be 1. + 1 = ifnot ERR_BAD_SECRENEG fail then + read8 if ERR_BAD_SECRENEG fail then + 2 addr-reneg set8 + endof + 2 of + \ Renegotiation, value shall consist of 13 bytes + \ (header + copy of the saved client "Finished"). + 13 = ifnot ERR_BAD_SECRENEG fail then + read8 12 = ifnot ERR_BAD_SECRENEG fail then + addr-pad 12 read-blob + addr-saved_finished addr-pad 12 memcmp ifnot + ERR_BAD_SECRENEG fail + then + endof + + \ If "reneg" is 1 then the client is not supposed to support + \ the extension, and it sends it nonetheless, which means + \ foul play. + ERR_BAD_SECRENEG fail + endcase ; + +\ Read the Signature Algorithms extension. +: read-signatures ( lim -- lim ) + \ Open extension value. + read16 open-elt + + read-list-sign-algos addr-hashes set32 + + \ Close extension value. + close-elt ; + +\ Read the Supported Curves extension. +: read-supported-curves ( lim -- lim ) + \ Open extension value. + read16 open-elt + + \ Open list of curve identifiers. + read16 open-elt + + \ Get all supported curves. + 0 addr-curves set32 + begin dup while + read16 dup 32 < if + 1 swap << addr-curves get32 or addr-curves set32 + else + drop + then + repeat + close-elt + close-elt ; + +\ Read the ALPN extension from client. +: read-ALPN-from-client ( lim -- lim ) + \ If we do not have configured names, then we just ignore the + \ extension. + addr-protocol_names_num get16 ifnot read-ignore-16 ret then + + \ Open extension value. + read16 open-elt + + \ Open list of protocol names. + read16 open-elt + + \ Get all names and test for their support. We keep the one with + \ the lowest index (because we apply server's preferences, as + \ recommended by RFC 7301, section 3.2. We set the 'found' variable + \ to -2 and use an unsigned comparison, making -2 a huge value. + -2 { found } + begin dup while + read8 dup { len } addr-pad swap read-blob + len test-protocol-name dup found u< if + >found + else + drop + then + repeat + + \ End of extension. + close-elt + close-elt + + \ Write back found name index (or not). If no match was found, + \ then we write -1 (0xFFFF) in the index value, not 0, so that + \ the caller knows that we tried to match, and failed. + found 1+ addr-selected_protocol set16 ; + +\ Call policy handler to get cipher suite, hash function identifier and +\ certificate chain. Returned value is 0 (false) on failure. +cc: call-policy-handler ( -- bool ) { + int x; + br_ssl_server_choices choices; + + x = (*CTX->policy_vtable)->choose( + CTX->policy_vtable, CTX, &choices); + ENG->session.cipher_suite = choices.cipher_suite; + CTX->sign_hash_id = choices.algo_id; + ENG->chain = choices.chain; + ENG->chain_len = choices.chain_len; + T0_PUSHi(-(x != 0)); +} + +\ Check for a remembered session. +cc: check-resume ( -- bool ) { + if (ENG->session.session_id_len == 32 + && CTX->cache_vtable != NULL && (*CTX->cache_vtable)->load( + CTX->cache_vtable, CTX, &ENG->session)) + { + T0_PUSHi(-1); + } else { + T0_PUSH(0); + } +} + +\ Save the current session. +cc: save-session ( -- ) { + if (CTX->cache_vtable != NULL) { + (*CTX->cache_vtable)->save( + CTX->cache_vtable, CTX, &ENG->session); + } +} + +\ Read and drop ClientHello. This is used when a client-triggered +\ renegotiation attempt is rejected. +: skip-ClientHello ( -- ) + read-handshake-header-core + 1 = ifnot ERR_UNEXPECTED fail then + dup skip-blob drop ; + +\ Read ClientHello. If the session is resumed, then -1 is returned. +: read-ClientHello ( -- resume ) + \ Get header, and check message type. + read-handshake-header 1 = ifnot ERR_UNEXPECTED fail then + + \ Get maximum protocol version from client. + read16 dup { client-version-max } addr-client_max_version set16 + + \ Client random. + addr-client_random 32 read-blob + + \ Client session ID. + read8 dup 32 > if ERR_OVERSIZED_ID fail then + dup addr-session_id_len set8 + addr-session_id swap read-blob + + \ Lookup session for resumption. We should do that here because + \ we need to verify that the remembered cipher suite is still + \ matched by this ClientHello. + check-resume { resume } + + \ Cipher suites. We read all cipher suites from client, each time + \ matching against our own list. We accumulate suites in the + \ client_suites[] context buffer: we keep suites that are + \ supported by both the client and the server (so the list size + \ cannot exceed that of the server list), and we keep them in + \ either client or server preference order (depending on the + \ relevant flag). + \ + \ We also need to identify the pseudo cipher suite for secure + \ renegotiation here. + read16 open-elt + 0 { reneg-scsv } + 0 { resume-suite } + addr-len-client_suites dup2 bzero + over + { css-off css-max } + begin + dup while + read16 dup { suite } + + \ Check that when resuming a session, the requested + \ suite is still valid. + resume if + dup addr-cipher_suite get16 = if + -1 >resume-suite + then + then + + \ Special handling for TLS_EMPTY_RENEGOTIATION_INFO_SCSV. + \ This fake cipher suite may occur only in the first + \ handshake. + dup 0x00FF = if + addr-reneg get8 if ERR_BAD_SECRENEG fail then + -1 >reneg-scsv + then + + \ Special handling for TLS_FALLBACK_SCSV. If the client + \ maximum version is less than our own maximum version, + \ then this is an undue downgrade. We mark it by setting + \ the client max version to 0x10000. + dup 0x5600 = if + client-version-max addr-version_min get16 >= + client-version-max addr-version_max get16 < and if + -1 >client-version-max + then + then + + \ Test whether the suite is supported by the server. + scan-suite dup 0< if + \ We do not support this cipher suite. Note + \ that this also covers the case of pseudo + \ cipher suites. + drop + else + \ If we use server order, then we place the + \ suite at the computed offset; otherwise, we + \ append it to the list at the current place. + 0 flag? if + 2 << addr-client_suites + suite swap set16 + else + drop + \ We need to test for list length because + \ the client list may have duplicates, + \ that we do not filter. Duplicates are + \ invalid so this is not a problem if we + \ reject such clients. + css-off css-max >= if + ERR_BAD_HANDSHAKE fail + then + suite css-off set16 + css-off 4 + >css-off + then + then + repeat + drop + + \ Compression methods. We need method 0 (no compression). + 0 { ok-compression } + read8 open-elt + begin dup while + read8 ifnot -1 >ok-compression then + repeat + close-elt + + \ Set default values for parameters that may be affected by + \ extensions: + \ -- server name is empty + \ -- client is reputed to know RSA and ECDSA, both with SHA-1 + \ -- the default elliptic curve is P-256 (secp256r1, id = 23) + 0 addr-server_name set8 + 0x0404 addr-hashes set32 + 0x800000 addr-curves set32 + + \ Process extensions, if any. + dup if + read16 open-elt + begin dup while + read16 case + \ Server Name Indication. + 0x0000 of + read-client-sni + endof + \ Max Frag Length. + 0x0001 of + read-client-frag + endof + \ Secure Renegotiation. + 0xFF01 of + read-client-reneg + endof + \ Signature Algorithms. + 0x000D of + read-signatures + endof + \ Supported Curves. + 0x000A of + read-supported-curves + endof + \ Supported Point Formats. + \ We only support "uncompressed", that all + \ implementations are supposed to support, + \ so we can simply ignore that extension. + \ 0x000B of + \ read-ignore-16 + \ endof + + \ ALPN + 0x0010 of + read-ALPN-from-client + endof + + \ Other extensions are ignored. + drop read-ignore-16 0 + endcase + repeat + close-elt + then + + \ Close message. + close-elt + + \ Cancel session resumption if the cipher suite was not found. + resume resume-suite and >resume + + \ Now check the received data. Since the client is expecting an + \ answer, we can send an appropriate fatal alert on any error. + + \ Compute protocol version as the minimum of our maximum version, + \ and the maximum version sent by the client. If that is less than + \ 0x0300 (SSL-3.0), then fail. Otherwise, we may at least send an + \ alert with that version. We still reject versions lower than our + \ configured minimum. + \ As a special case, in case of undue downgrade, we send a specific + \ alert (see RFC 7507). Note that this case may happen only if + \ we would otherwise accept the client's version. + client-version-max 0< if + addr-client_max_version get16 addr-version_out set16 + 86 fail-alert + then + addr-version_max get16 + dup client-version-max > if drop client-version-max then + dup 0x0300 < if ERR_BAD_VERSION fail then + client-version-max addr-version_min get16 < if + 70 fail-alert + then + \ If resuming the session, then enforce the previously negotiated + \ version (if still possible). + resume if + addr-version get16 client-version-max <= if + drop addr-version get16 + else + 0 >resume + then + then + dup addr-version set16 + dup addr-version_in set16 + dup addr-version_out set16 + 0x0303 >= { can-tls12 } + + \ If the client sent TLS_EMPTY_RENEGOTIATION_INFO_SCSV, then + \ we should mark the client as "supporting secure renegotiation". + reneg-scsv if 2 addr-reneg set8 then + + \ If, at that point, the 'reneg' value is still 0, then the client + \ did not send the extension or the SCSV, so we have to assume + \ that secure renegotiation is not supported by that client. + addr-reneg get8 ifnot 1 addr-reneg set8 then + + \ Check compression. + ok-compression ifnot 40 fail-alert then + + \ Filter hash function support by what the server also supports. + \ If no common hash function remains with RSA and/or ECDSA, then + \ the corresponding ECDHE suites are not possible. + supported-hash-functions drop 257 * 0xFFFF0000 or + addr-hashes get32 and dup addr-hashes set32 + \ 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 12 << { can-ecdhe } + + \ Filter supported curves. If there is no common curve between + \ client and us, then ECDHE suites cannot be used. Note that we + \ may still allow ECDH, depending on the EC key handler. + addr-curves get32 supported-curves and dup addr-curves set32 + ifnot 0 >can-ecdhe then + + \ If resuming a session, then the next steps are not necessary; + \ we won't invoke the policy handler. + 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 + + \ Translate common cipher suites, then squeeze out holes: there + \ may be holes because of the way we fill the list when the + \ 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 the relevant signature algorithm) or no common curve. + \ -- TLS-1.2-only suites are removed if the negotiated 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 + dup 12 >> dup 1 = swap 2 = or if + dup can-ecdhe and ifnot + 2drop 0 dup + then + then + can-tls12 ifnot + \ Suites compatible with TLS-1.0 and TLS-1.1 are + \ exactly the ones that use HMAC/SHA-1. + dup 0xF0 and 0x20 <> if + 2drop 0 dup + then + then + dup if + css-off 2+ set16 css-off set16 + css-off 4 + >css-off + else + 2drop + then + 4 + + repeat + drop + css-off addr-client_suites - 2 >> + dup ifnot + \ No common cipher suite: handshake failure. + 40 fail-alert + then + addr-client_suites_num set8 + + \ Check ALPN. + addr-selected_protocol get16 0xFFFF = if + 3 flag? if 120 fail-alert then + 0 addr-selected_protocol set16 + then + + \ Call policy handler to obtain the cipher suite and other + \ parameters. + call-policy-handler ifnot 40 fail-alert then + + \ We are not resuming a session. + 0 ; + +\ Write ServerHello. +: write-ServerHello ( initial -- ) + { initial } + \ Compute ServerHello length. + 2 write8 70 + + \ Compute length of Secure Renegotiation extension. + addr-reneg get8 2 = if + initial if 5 else 29 then + else + 0 + then + { ext-reneg-len } + + \ Compute length of Max Fragment Length extension. + addr-peer_log_max_frag_len get8 if 5 else 0 then + { ext-max-frag-len } + + \ Compute length of ALPN extension. This also copy the + \ selected protocol name into the pad. + addr-selected_protocol get16 dup if 1- copy-protocol-name 7 + then + { ext-ALPN-len } + + \ Adjust ServerHello length to account for the extensions. + ext-reneg-len ext-max-frag-len + ext-ALPN-len + dup if 2 + then + + write24 + + \ Protocol version + addr-version get16 write16 + + \ Server random + addr-server_random 4 bzero + addr-server_random 4 + 28 mkrand + addr-server_random 32 write-blob + + \ Session ID + \ TODO: if we have no session cache at all, we might send here + \ an empty session ID. This would save a bit of network + \ bandwidth. + 32 write8 + addr-session_id 32 write-blob + + \ Cipher suite + addr-cipher_suite get16 write16 + + \ Compression method + 0 write8 + + \ Extensions + ext-reneg-len ext-max-frag-len + ext-ALPN-len + dup if + write16 + ext-reneg-len dup if + 0xFF01 write16 + 4 - dup write16 + 1- addr-saved_finished swap write-blob-head8 + else + drop + then + ext-max-frag-len if + 0x0001 write16 + 1 write16 addr-peer_log_max_frag_len get8 8 - write8 + then + ext-ALPN-len dup if + \ Note: the selected protocol name was previously + \ copied into the pad. + 0x0010 write16 + 4 - dup write16 + 2- dup write16 + 1- addr-pad swap write-blob-head8 + else + drop + then + else + drop + then ; + +\ 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 ) { + int curve = T0_POPi(); + T0_PUSHi(do_ecdhe_part1(CTX, curve)); +} + +\ Get index of first bit set to 1 (in low to high order). +: lowest-1 ( bits -- n ) + dup ifnot drop -1 ret then + 0 begin dup2 >> 1 and 0= while 1+ repeat + swap drop ; + +\ Write the Server Key Exchange message (if applicable). +: write-ServerKeyExchange ( -- ) + addr-cipher_suite get16 use-ecdhe? ifnot ret then + + \ We must select an appropriate curve among the curves that + \ are supported both by us and the peer. Right now, we apply + \ a fixed preference order: Curve25519, P-256, P-384, P-521, + \ then the common curve with the lowest ID. + \ (TODO: add some option to make that behaviour configurable.) + \ + \ This loop always terminates because previous processing made + \ sure that ECDHE suites are not selectable if there is no common + \ curve. + addr-curves get32 + dup 0x20000000 and if + drop 29 + else + dup 0x38000000 and dup if swap then + drop lowest-1 + then + { curve-id } + + \ Compute the signed curve point to send. + curve-id do-ecdhe-part1 dup 0< if neg fail then { sig-len } + + \ If using TLS-1.2+, then the hash function and signature + \ algorithm are explicitly encoded in the message. + addr-version get16 0x0303 >= { tls1.2+ } + + 12 write8 + sig-len addr-ecdhe_point_len get8 + tls1.2+ 2 and + 6 + write24 + + \ Curve parameters: named curve with 16-bit ID. + 3 write8 curve-id write16 + + \ Public point. + addr-ecdhe_point addr-ecdhe_point_len get8 write-blob-head8 + + \ If TLS-1.2+, write hash and signature identifiers. + tls1.2+ if + \ sign_hash_id contains either a hash identifier, + \ or the complete 16-bit value to write. + addr-sign_hash_id get16 + dup 0xFF00 < if + write16 + else + 0xFF and write8 + \ 'use-rsa-ecdhe?' returns -1 for RSA, 0 for + \ ECDSA. The byte on the wire shall be 1 for RSA, + \ 3 for ECDSA. + addr-cipher_suite get16 use-rsa-ecdhe? 1 << 3 + write8 + then + then + + \ Signature. + 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 ; + +\ Perform RSA decryption of the client-sent pre-master secret. The value +\ is in the pad, and its length is provided as parameter. +cc: do-rsa-decrypt ( len prf_id -- ) { + int prf_id = T0_POPi(); + size_t len = T0_POP(); + do_rsa_decrypt(CTX, prf_id, ENG->pad, len); +} + +\ Perform ECDH (not ECDHE). The point from the client is in the pad, and +\ its length is provided as parameter. +cc: do-ecdh ( len prf_id -- ) { + int prf_id = T0_POPi(); + size_t len = T0_POP(); + do_ecdh(CTX, prf_id, ENG->pad, len); +} + +\ Do the second part of ECDHE. +cc: do-ecdhe-part2 ( len prf_id -- ) { + int prf_id = T0_POPi(); + size_t len = T0_POP(); + do_ecdhe_part2(CTX, prf_id, ENG->pad, len); +} + +\ 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. + read16 + dup 512 > if ERR_LIMIT_EXCEEDED fail then + dup { enc-rsa-len } + addr-pad swap read-blob + enc-rsa-len addr-cipher_suite get16 prf-id do-rsa-decrypt + then + addr-cipher_suite get16 dup use-ecdhe? swap use-ecdh? { ecdhe ecdh } + ecdh ecdhe or if + \ ECDH or ECDHE key exchange: we expect an EC point. + read8 dup { ec-point-len } + addr-pad swap read-blob + ec-point-len addr-cipher_suite get16 prf-id + ecdhe if do-ecdhe-part2 else do-ecdh then + 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 + begin can-output? not while wait-co drop repeat + 22 addr-record_type_out set8 + 0 write8 0 write24 flush-record + 23 addr-record_type_out set8 ; + +\ Make a handshake. +: do-handshake ( initial -- ) + 0 addr-application_data set8 + 22 addr-record_type_out set8 + 0 addr-selected_protocol set16 + multihash-init + read-ClientHello + more-incoming-bytes? if ERR_UNEXPECTED fail then + if + \ Session resumption + write-ServerHello + 0 write-CCS-Finished + 0 read-CCS-Finished + else + \ Not a session resumption + write-ServerHello + write-Certificate drop + write-ServerKeyExchange + ta-names-total-length if + write-CertificateRequest + then + write-ServerHelloDone + flush-record + + \ 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 + then + 1 addr-application_data set8 + 23 addr-record_type_out set8 ; + +\ Entry point. +: main ( -- ! ) + \ Perform initial handshake. + -1 do-handshake + + begin + \ Wait for further invocation. At that point, we should + \ get either an explicit call for renegotiation, or + \ an incoming ClientHello handshake message. + wait-co + dup 0x07 and case + 0x00 of + 0x10 and if + \ The best we can do is ask for a + \ renegotiation, then wait for it + \ to happen. + 0 addr-application_data set8 + send-HelloRequest + then + endof + 0x01 of + \ Reject renegotiations if the peer does not + \ support secure renegotiation, or if the + \ "no renegotiation" flag is set. + drop + addr-reneg get8 1 = 1 flag? or if + skip-ClientHello + flush-record + begin can-output? not while + wait-co drop + repeat + 100 send-warning + \ Put back connection in "application + \ data" state: it's not dead yet. + 1 addr-application_data set8 + 23 addr-record_type_out set8 + else + 0 do-handshake + then + endof + ERR_UNEXPECTED fail + endcase + again + ; diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_io.c b/BearSSL-OG/libbearssl/src/ssl/ssl_io.c new file mode 100644 index 0000000..1952615 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_io.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_sslio_init(br_sslio_context *ctx, + br_ssl_engine_context *engine, + int (*low_read)(void *read_context, + unsigned char *data, size_t len), + void *read_context, + int (*low_write)(void *write_context, + const unsigned char *data, size_t len), + void *write_context) +{ + ctx->engine = engine; + ctx->low_read = low_read; + ctx->read_context = read_context; + ctx->low_write = low_write; + ctx->write_context = write_context; +} + +/* + * Run the engine, until the specified target state is achieved, or + * an error occurs. The target state is SENDAPP, RECVAPP, or the + * combination of both (the combination matches either). When a match is + * achieved, this function returns 0. On error, it returns -1. + */ +static int +run_until(br_sslio_context *ctx, unsigned target) +{ + for (;;) { + unsigned state; + + state = br_ssl_engine_current_state(ctx->engine); + if (state & BR_SSL_CLOSED) { + return -1; + } + + /* + * If there is some record data to send, do it. This takes + * precedence over everything else. + */ + if (state & BR_SSL_SENDREC) { + unsigned char *buf; + size_t len; + int wlen; + + buf = br_ssl_engine_sendrec_buf(ctx->engine, &len); + wlen = ctx->low_write(ctx->write_context, buf, len); + if (wlen < 0) { + /* + * If we received a close_notify and we + * still send something, then we have our + * own response close_notify to send, and + * the peer is allowed by RFC 5246 not to + * wait for it. + */ + if (!ctx->engine->shutdown_recv) { + br_ssl_engine_fail( + ctx->engine, BR_ERR_IO); + } + return -1; + } + if (wlen > 0) { + br_ssl_engine_sendrec_ack(ctx->engine, wlen); + } + continue; + } + + /* + * If we reached our target, then we are finished. + */ + if (state & target) { + return 0; + } + + /* + * If some application data must be read, and we did not + * exit, then this means that we are trying to write data, + * and that's not possible until the application data is + * read. This may happen if using a shared in/out buffer, + * and the underlying protocol is not strictly half-duplex. + * This is unrecoverable here, so we report an error. + */ + if (state & BR_SSL_RECVAPP) { + return -1; + } + + /* + * If we reached that point, then either we are trying + * to read data and there is some, or the engine is stuck + * until a new record is obtained. + */ + if (state & BR_SSL_RECVREC) { + unsigned char *buf; + size_t len; + int rlen; + + buf = br_ssl_engine_recvrec_buf(ctx->engine, &len); + rlen = ctx->low_read(ctx->read_context, buf, len); + if (rlen < 0) { + br_ssl_engine_fail(ctx->engine, BR_ERR_IO); + return -1; + } + if (rlen > 0) { + br_ssl_engine_recvrec_ack(ctx->engine, rlen); + } + continue; + } + + /* + * We can reach that point if the target RECVAPP, and + * the state contains SENDAPP only. This may happen with + * a shared in/out buffer. In that case, we must flush + * the buffered data to "make room" for a new incoming + * record. + */ + br_ssl_engine_flush(ctx->engine, 0); + } +} + +/* see bearssl_ssl.h */ +int +br_sslio_read(br_sslio_context *ctx, void *dst, size_t len) +{ + unsigned char *buf; + size_t alen; + + if (len == 0) { + return 0; + } + if (run_until(ctx, BR_SSL_RECVAPP) < 0) { + return -1; + } + buf = br_ssl_engine_recvapp_buf(ctx->engine, &alen); + if (alen > len) { + alen = len; + } + memcpy(dst, buf, alen); + br_ssl_engine_recvapp_ack(ctx->engine, alen); + return (int)alen; +} + +/* see bearssl_ssl.h */ +int +br_sslio_read_all(br_sslio_context *ctx, void *dst, size_t len) +{ + unsigned char *buf; + + buf = dst; + while (len > 0) { + int rlen; + + rlen = br_sslio_read(ctx, buf, len); + if (rlen < 0) { + return -1; + } + buf += rlen; + len -= (size_t)rlen; + } + return 0; +} + +/* see bearssl_ssl.h */ +int +br_sslio_write(br_sslio_context *ctx, const void *src, size_t len) +{ + unsigned char *buf; + size_t alen; + + if (len == 0) { + return 0; + } + if (run_until(ctx, BR_SSL_SENDAPP) < 0) { + return -1; + } + buf = br_ssl_engine_sendapp_buf(ctx->engine, &alen); + if (alen > len) { + alen = len; + } + memcpy(buf, src, alen); + br_ssl_engine_sendapp_ack(ctx->engine, alen); + return (int)alen; +} + +/* see bearssl_ssl.h */ +int +br_sslio_write_all(br_sslio_context *ctx, const void *src, size_t len) +{ + const unsigned char *buf; + + buf = src; + while (len > 0) { + int wlen; + + wlen = br_sslio_write(ctx, buf, len); + if (wlen < 0) { + return -1; + } + buf += wlen; + len -= (size_t)wlen; + } + return 0; +} + +/* see bearssl_ssl.h */ +int +br_sslio_flush(br_sslio_context *ctx) +{ + /* + * We trigger a flush. We know the data is gone when there is + * no longer any record data to send, and we can either read + * or write application data. The call to run_until() does the + * job because it ensures that any assembled record data is + * first sent down the wire before considering anything else. + */ + br_ssl_engine_flush(ctx->engine, 0); + return run_until(ctx, BR_SSL_SENDAPP | BR_SSL_RECVAPP); +} + +/* see bearssl_ssl.h */ +int +br_sslio_close(br_sslio_context *ctx) +{ + br_ssl_engine_close(ctx->engine); + while (br_ssl_engine_current_state(ctx->engine) != BR_SSL_CLOSED) { + /* + * Discard any incoming application data. + */ + size_t len; + + run_until(ctx, BR_SSL_RECVAPP); + if (br_ssl_engine_recvapp_buf(ctx->engine, &len) != NULL) { + br_ssl_engine_recvapp_ack(ctx->engine, len); + } + } + return br_ssl_engine_last_error(ctx->engine) == BR_ERR_OK; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_keyexport.c b/BearSSL-OG/libbearssl/src/ssl/ssl_keyexport.c new file mode 100644 index 0000000..58e6dc3 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_keyexport.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Supported cipher suites that use SHA-384 for the PRF when selected + * for TLS 1.2. All other cipher suites are deemed to use SHA-256. + */ +static const uint16_t suites_sha384[] = { + BR_TLS_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +}; + +/* see bearssl_ssl.h */ +int +br_ssl_key_export(br_ssl_engine_context *cc, + void *dst, size_t len, const char *label, + const void *context, size_t context_len) +{ + br_tls_prf_seed_chunk chunks[4]; + br_tls_prf_impl iprf; + size_t num_chunks, u; + unsigned char tmp[2]; + int prf_id; + + if (cc->application_data != 1) { + return 0; + } + chunks[0].data = cc->client_random; + chunks[0].len = sizeof cc->client_random; + chunks[1].data = cc->server_random; + chunks[1].len = sizeof cc->server_random; + if (context != NULL) { + br_enc16be(tmp, (unsigned)context_len); + chunks[2].data = tmp; + chunks[2].len = 2; + chunks[3].data = context; + chunks[3].len = context_len; + num_chunks = 4; + } else { + num_chunks = 2; + } + prf_id = BR_SSLPRF_SHA256; + for (u = 0; u < (sizeof suites_sha384) / sizeof(uint16_t); u ++) { + if (suites_sha384[u] == cc->session.cipher_suite) { + prf_id = BR_SSLPRF_SHA384; + } + } + iprf = br_ssl_engine_get_PRF(cc, prf_id); + iprf(dst, len, + cc->session.master_secret, sizeof cc->session.master_secret, + label, num_chunks, chunks); + return 1; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_lru.c b/BearSSL-OG/libbearssl/src/ssl/ssl_lru.c new file mode 100644 index 0000000..6577d5a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_lru.c @@ -0,0 +1,537 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * Each entry consists in a fixed number of bytes. Entries are concatenated + * in the store block. "Addresses" are really offsets in the block, + * expressed over 32 bits (so the cache may have size at most 4 GB, which + * "ought to be enough for everyone"). The "null address" is 0xFFFFFFFF. + * Note that since the storage block alignment is in no way guaranteed, we + * perform only accesses that can handle unaligned data. + * + * Two concurrent data structures are maintained: + * + * -- Entries are organised in a doubly-linked list; saved entries are added + * at the head, and loaded entries are moved to the head. Eviction uses + * the list tail (this is the LRU algorithm). + * + * -- Entries are indexed with a binary tree: all left descendants of a + * node have a lower session ID (in lexicographic order), while all + * right descendants have a higher session ID. The tree is heuristically + * balanced. + * + * Entry format: + * + * session ID 32 bytes + * master secret 48 bytes + * protocol version 2 bytes (big endian) + * cipher suite 2 bytes (big endian) + * list prev 4 bytes (big endian) + * list next 4 bytes (big endian) + * tree left child 4 bytes (big endian) + * tree right child 4 bytes (big endian) + * + * If an entry has a protocol version set to 0, then it is "disabled": + * it was a session pushed to the cache at some point, but it has + * been explicitly removed. + * + * We need to keep the tree balanced because an attacker could make + * handshakes, selecting some specific sessions (by reusing them) to + * try to make us make an imbalanced tree that makes lookups expensive + * (a denial-of-service attack that would persist as long as the cache + * remains, i.e. even after the attacker made all his connections). + * To do that, we replace the session ID (or the start of the session ID) + * with a HMAC value computed over the replaced part; the hash function + * implementation and the key are obtained from the server context upon + * first save() call. + * + * Theoretically, an attacker could use the exact timing of the lookup + * to infer the current tree topology, and try to revive entries to make + * it as unbalanced as possible. However, since the session ID are + * chosen randomly by the server, and the attacker cannot see the + * indexing values and must thus rely on blind selection, it should be + * exponentially difficult for the attacker to maintain a large + * imbalance. + */ +#define SESSION_ID_LEN 32 +#define MASTER_SECRET_LEN 48 + +#define SESSION_ID_OFF 0 +#define MASTER_SECRET_OFF 32 +#define VERSION_OFF 80 +#define CIPHER_SUITE_OFF 82 +#define LIST_PREV_OFF 84 +#define LIST_NEXT_OFF 88 +#define TREE_LEFT_OFF 92 +#define TREE_RIGHT_OFF 96 + +#define LRU_ENTRY_LEN 100 + +#define ADDR_NULL ((uint32_t)-1) + +#define GETSET(name, off) \ +static __inline uint32_t get_ ## name(br_ssl_session_cache_lru *cc, uint32_t x) \ +{ \ + return br_dec32be(cc->store + x + (off)); \ +} \ +static __inline void set_ ## name(br_ssl_session_cache_lru *cc, \ + uint32_t x, uint32_t val) \ +{ \ + br_enc32be(cc->store + x + (off), val); \ +} + +GETSET(prev, LIST_PREV_OFF) +GETSET(next, LIST_NEXT_OFF) +GETSET(left, TREE_LEFT_OFF) +GETSET(right, TREE_RIGHT_OFF) + +/* + * Transform the session ID by replacing the first N bytes with a HMAC + * value computed over these bytes, using the random key K (the HMAC + * value is truncated if needed). HMAC will use the same hash function + * as the DRBG in the SSL server context, so with SHA-256, SHA-384, + * or SHA-1, depending on what is available. + * + * The risk of collision is considered too small to be a concern; and + * the impact of a collision is low (the handshake won't succeed). This + * risk is much lower than any transmission error, which would lead to + * the same consequences. + * + * Source and destination arrays msut be disjoint. + */ +static void +mask_id(br_ssl_session_cache_lru *cc, + const unsigned char *src, unsigned char *dst) +{ + br_hmac_key_context hkc; + br_hmac_context hc; + + memcpy(dst, src, SESSION_ID_LEN); + br_hmac_key_init(&hkc, cc->hash, cc->index_key, sizeof cc->index_key); + br_hmac_init(&hc, &hkc, SESSION_ID_LEN); + br_hmac_update(&hc, src, SESSION_ID_LEN); + br_hmac_out(&hc, dst); +} + +/* + * Find a node by ID. Returned value is the node address, or ADDR_NULL if + * the node is not found. + * + * If addr_link is not NULL, then '*addr_link' is set to the address of the + * last followed link. If the found node is the root, or if the tree is + * empty, then '*addr_link' is set to ADDR_NULL. + */ +static uint32_t +find_node(br_ssl_session_cache_lru *cc, const unsigned char *id, + uint32_t *addr_link) +{ + uint32_t x, y; + + x = cc->root; + y = ADDR_NULL; + while (x != ADDR_NULL) { + int r; + + r = memcmp(id, cc->store + x + SESSION_ID_OFF, SESSION_ID_LEN); + if (r < 0) { + y = x + TREE_LEFT_OFF; + x = get_left(cc, x); + } else if (r == 0) { + if (addr_link != NULL) { + *addr_link = y; + } + return x; + } else { + y = x + TREE_RIGHT_OFF; + x = get_right(cc, x); + } + } + if (addr_link != NULL) { + *addr_link = y; + } + return ADDR_NULL; +} + +/* + * For node x, find its replacement upon removal. + * + * -- If node x has no child, then this returns ADDR_NULL. + * -- Otherwise, if node x has a left child, then the replacement is the + * rightmost left-descendent. + * -- Otherwise, the replacement is the leftmost right-descendent. + * + * If a node is returned, then '*al' is set to the address of the field + * that points to that node. Otherwise (node x has no child), '*al' is + * set to ADDR_NULL. + * + * Note that the replacement node, when found, is always a descendent + * of node 'x', so it cannot be the tree root. Thus, '*al' can be set + * to ADDR_NULL only when no node is found and ADDR_NULL is returned. + */ +static uint32_t +find_replacement_node(br_ssl_session_cache_lru *cc, uint32_t x, uint32_t *al) +{ + uint32_t y1, y2; + + y1 = get_left(cc, x); + if (y1 != ADDR_NULL) { + y2 = x + TREE_LEFT_OFF; + for (;;) { + uint32_t z; + + z = get_right(cc, y1); + if (z == ADDR_NULL) { + *al = y2; + return y1; + } + y2 = y1 + TREE_RIGHT_OFF; + y1 = z; + } + } + y1 = get_right(cc, x); + if (y1 != ADDR_NULL) { + y2 = x + TREE_RIGHT_OFF; + for (;;) { + uint32_t z; + + z = get_left(cc, y1); + if (z == ADDR_NULL) { + *al = y2; + return y1; + } + y2 = y1 + TREE_LEFT_OFF; + y1 = z; + } + } + *al = ADDR_NULL; + return ADDR_NULL; +} + +/* + * Set the link at address 'alx' to point to node 'x'. If 'alx' is + * ADDR_NULL, then this sets the tree root to 'x'. + */ +static __inline void +set_link(br_ssl_session_cache_lru *cc, uint32_t alx, uint32_t x) +{ + if (alx == ADDR_NULL) { + cc->root = x; + } else { + br_enc32be(cc->store + alx, x); + } +} + +/* + * Remove node 'x' from the tree. This function shall not be called if + * node 'x' is not part of the tree. + */ +static void +remove_node(br_ssl_session_cache_lru *cc, uint32_t x) +{ + uint32_t alx, y, aly; + + /* + * Removal algorithm: + * ------------------ + * + * - If we remove the root, then the tree becomes empty. + * + * - If the removed node has no child, then we can simply remove + * it, with nothing else to do. + * + * - Otherwise, the removed node must be replaced by either its + * rightmost left-descendent, or its leftmost right-descendent. + * The replacement node itself must be removed from its current + * place. By definition, that replacement node has either no + * child, or at most a single child that will replace it in the + * tree. + */ + + /* + * Find node back and its ancestor link. If the node was the + * root, then alx is set to ADDR_NULL. + */ + find_node(cc, cc->store + x + SESSION_ID_OFF, &alx); + + /* + * Find replacement node 'y', and 'aly' is set to the address of + * the link to that replacement node. If the removed node has no + * child, then both 'y' and 'aly' are set to ADDR_NULL. + */ + y = find_replacement_node(cc, x, &aly); + + if (y != ADDR_NULL) { + uint32_t z; + + /* + * The unlinked replacement node may have one child (but + * not two) that takes its place. + */ + z = get_left(cc, y); + if (z == ADDR_NULL) { + z = get_right(cc, y); + } + set_link(cc, aly, z); + + /* + * Link the replacement node in its new place, overwriting + * the current link to the node 'x' (which removes 'x'). + */ + set_link(cc, alx, y); + + /* + * The replacement node adopts the left and right children + * of the removed node. Note that this also works even if + * the replacement node was a direct descendent of the + * removed node, since we unlinked it previously. + */ + set_left(cc, y, get_left(cc, x)); + set_right(cc, y, get_right(cc, x)); + } else { + /* + * No replacement, we simply unlink the node 'x'. + */ + set_link(cc, alx, ADDR_NULL); + } +} + +static void +lru_save(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + const br_ssl_session_parameters *params) +{ + br_ssl_session_cache_lru *cc; + unsigned char id[SESSION_ID_LEN]; + uint32_t x, alx; + + cc = (br_ssl_session_cache_lru *)ctx; + + /* + * If the buffer is too small, we don't record anything. This + * test avoids problems in subsequent code. + */ + if (cc->store_len < LRU_ENTRY_LEN) { + return; + } + + /* + * Upon the first save in a session cache instance, we obtain + * a random key for our indexing. + */ + if (!cc->init_done) { + br_hmac_drbg_generate(&server_ctx->eng.rng, + cc->index_key, sizeof cc->index_key); + cc->hash = br_hmac_drbg_get_hash(&server_ctx->eng.rng); + cc->init_done = 1; + } + mask_id(cc, params->session_id, id); + + /* + * Look for the node in the tree. If the same ID is already used, + * then reject it. This is a collision event, which should be + * exceedingly rare. + * Note: we do NOT record the emplacement here, because the + * removal of an entry may change the tree topology. + */ + if (find_node(cc, id, NULL) != ADDR_NULL) { + return; + } + + /* + * Find some room for the new parameters. If the cache is not + * full yet, add it to the end of the area and bump the pointer up. + * Otherwise, evict the list tail entry. Note that we already + * filtered out the case of a ridiculously small buffer that + * cannot hold any entry at all; thus, if there is no room for an + * extra entry, then the cache cannot be empty. + */ + if (cc->store_ptr > (cc->store_len - LRU_ENTRY_LEN)) { + /* + * Evict tail. If the buffer has room for a single entry, + * then this may also be the head. + */ + x = cc->tail; + cc->tail = get_prev(cc, x); + if (cc->tail == ADDR_NULL) { + cc->head = ADDR_NULL; + } else { + set_next(cc, cc->tail, ADDR_NULL); + } + + /* + * Remove the node from the tree. + */ + remove_node(cc, x); + } else { + /* + * Allocate room for new node. + */ + x = cc->store_ptr; + cc->store_ptr += LRU_ENTRY_LEN; + } + + /* + * Find the emplacement for the new node, and link it. + */ + find_node(cc, id, &alx); + set_link(cc, alx, x); + set_left(cc, x, ADDR_NULL); + set_right(cc, x, ADDR_NULL); + + /* + * New entry becomes new list head. It may also become the list + * tail if the cache was empty at that point. + */ + if (cc->head == ADDR_NULL) { + cc->tail = x; + } else { + set_prev(cc, cc->head, x); + } + set_prev(cc, x, ADDR_NULL); + set_next(cc, x, cc->head); + cc->head = x; + + /* + * Fill data in the entry. + */ + memcpy(cc->store + x + SESSION_ID_OFF, id, SESSION_ID_LEN); + memcpy(cc->store + x + MASTER_SECRET_OFF, + params->master_secret, MASTER_SECRET_LEN); + br_enc16be(cc->store + x + VERSION_OFF, params->version); + br_enc16be(cc->store + x + CIPHER_SUITE_OFF, params->cipher_suite); +} + +static int +lru_load(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + br_ssl_session_parameters *params) +{ + br_ssl_session_cache_lru *cc; + unsigned char id[SESSION_ID_LEN]; + uint32_t x; + + (void)server_ctx; + cc = (br_ssl_session_cache_lru *)ctx; + if (!cc->init_done) { + return 0; + } + mask_id(cc, params->session_id, id); + x = find_node(cc, id, NULL); + if (x != ADDR_NULL) { + unsigned version; + + version = br_dec16be(cc->store + x + VERSION_OFF); + if (version == 0) { + /* + * Entry is disabled, we pretend we did not find it. + * Notably, we don't move it to the front of the + * LRU list. + */ + return 0; + } + params->version = version; + params->cipher_suite = br_dec16be( + cc->store + x + CIPHER_SUITE_OFF); + memcpy(params->master_secret, + cc->store + x + MASTER_SECRET_OFF, + MASTER_SECRET_LEN); + if (x != cc->head) { + /* + * Found node is not at list head, so move + * it to the head. + */ + uint32_t p, n; + + p = get_prev(cc, x); + n = get_next(cc, x); + set_next(cc, p, n); + if (n == ADDR_NULL) { + cc->tail = p; + } else { + set_prev(cc, n, p); + } + set_prev(cc, cc->head, x); + set_next(cc, x, cc->head); + set_prev(cc, x, ADDR_NULL); + cc->head = x; + } + return 1; + } + return 0; +} + +static const br_ssl_session_cache_class lru_class = { + sizeof(br_ssl_session_cache_lru), + &lru_save, + &lru_load +}; + +/* see inner.h */ +void +br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc, + unsigned char *store, size_t store_len) +{ + cc->vtable = &lru_class; + cc->store = store; + cc->store_len = store_len; + cc->store_ptr = 0; + cc->init_done = 0; + cc->head = ADDR_NULL; + cc->tail = ADDR_NULL; + cc->root = ADDR_NULL; +} + +/* see bearssl_ssl.h */ +void br_ssl_session_cache_lru_forget( + br_ssl_session_cache_lru *cc, const unsigned char *id) +{ + unsigned char mid[SESSION_ID_LEN]; + uint32_t addr; + + /* + * If the cache is not initialised yet, then it is empty, and + * there is nothing to forget. + */ + if (!cc->init_done) { + return; + } + + /* + * Look for the node in the tree. If found, the entry is marked + * as "disabled"; it will be reused in due course, as it ages + * through the list. + * + * We do not go through the complex moves of actually releasing + * the entry right away because explicitly forgetting sessions + * should be a rare event, meant mostly for testing purposes, + * so this is not worth the extra code size. + */ + mask_id(cc, id, mid); + addr = find_node(cc, mid, NULL); + if (addr != ADDR_NULL) { + br_enc16be(cc->store + addr + VERSION_OFF, 0); + } +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_rec_cbc.c b/BearSSL-OG/libbearssl/src/ssl/ssl_rec_cbc.c new file mode 100644 index 0000000..765efcc --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_rec_cbc.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 +in_cbc_init(br_sslrec_in_cbc_context *cc, + const br_block_cbcdec_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv) +{ + cc->vtable = &br_sslrec_in_cbc_vtable; + cc->seq = 0; + bc_impl->init(&cc->bc.vtable, bc_key, bc_key_len); + br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len); + cc->mac_len = mac_out_len; + if (iv == NULL) { + memset(cc->iv, 0, sizeof cc->iv); + cc->explicit_IV = 1; + } else { + memcpy(cc->iv, iv, bc_impl->block_size); + cc->explicit_IV = 0; + } +} + +static int +cbc_check_length(const br_sslrec_in_cbc_context *cc, size_t rlen) +{ + /* + * Plaintext size: at most 16384 bytes + * Padding: at most 256 bytes + * MAC: mac_len extra bytes + * TLS 1.1+: each record has an explicit IV + * + * Minimum length includes at least one byte of padding, and the + * MAC. + * + * Total length must be a multiple of the block size. + */ + size_t blen; + size_t min_len, max_len; + + blen = cc->bc.vtable->block_size; + min_len = (blen + cc->mac_len) & ~(blen - 1); + max_len = (16384 + 256 + cc->mac_len) & ~(blen - 1); + if (cc->explicit_IV) { + min_len += blen; + max_len += blen; + } + return min_len <= rlen && rlen <= max_len; +} + +/* + * Rotate array buf[] of length 'len' to the left (towards low indices) + * by 'num' bytes if ctl is 1; otherwise, leave it unchanged. This is + * constant-time. 'num' MUST be lower than 'len'. 'len' MUST be lower + * than or equal to 64. + */ +static void +cond_rotate(uint32_t ctl, unsigned char *buf, size_t len, size_t num) +{ + unsigned char tmp[64]; + size_t u, v; + + for (u = 0, v = num; u < len; u ++) { + tmp[u] = (unsigned char)MUX(ctl, buf[v], buf[u]); + if (++ v == len) { + v = 0; + } + } + memcpy(buf, tmp, len); +} + +static unsigned char * +cbc_decrypt(br_sslrec_in_cbc_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + /* + * We represent all lengths on 32-bit integers, because: + * -- SSL record lengths always fit in 32 bits; + * -- our constant-time primitives operate on 32-bit integers. + */ + unsigned char *buf; + uint32_t u, v, len, blen, min_len, max_len; + uint32_t good, pad_len, rot_count, len_withmac, len_nomac; + unsigned char tmp1[64], tmp2[64]; + int i; + br_hmac_context hc; + + buf = data; + len = *data_len; + blen = cc->bc.vtable->block_size; + + /* + * Decrypt data, and skip the explicit IV (if applicable). Note + * that the total length is supposed to have been verified by + * the caller. If there is an explicit IV, then we actually + * "decrypt" it using the implicit IV (from previous record), + * which is useless but harmless. + */ + cc->bc.vtable->run(&cc->bc.vtable, cc->iv, data, len); + if (cc->explicit_IV) { + buf += blen; + len -= blen; + } + + /* + * Compute minimum and maximum length of plaintext + MAC. These + * lengths can be inferred from the outside: they are not secret. + */ + min_len = (cc->mac_len + 256 < len) ? len - 256 : cc->mac_len; + max_len = len - 1; + + /* + * Use the last decrypted byte to compute the actual payload + * length. Take care not to overflow (we use unsigned types). + */ + pad_len = buf[max_len]; + good = LE(pad_len, (uint32_t)(max_len - min_len)); + len = MUX(good, (uint32_t)(max_len - pad_len), min_len); + + /* + * Check padding contents: all padding bytes must be equal to + * the value of pad_len. + */ + for (u = min_len; u < max_len; u ++) { + good &= LT(u, len) | EQ(buf[u], pad_len); + } + + /* + * Extract the MAC value. This is done in one pass, but results + * in a "rotated" MAC value depending on where it actually + * occurs. The 'rot_count' value is set to the offset of the + * first MAC byte within tmp1[]. + * + * min_len and max_len are also adjusted to the minimum and + * maximum lengths of the plaintext alone (without the MAC). + */ + len_withmac = (uint32_t)len; + len_nomac = len_withmac - cc->mac_len; + min_len -= cc->mac_len; + rot_count = 0; + memset(tmp1, 0, cc->mac_len); + v = 0; + for (u = min_len; u < max_len; u ++) { + tmp1[v] |= MUX(GE(u, len_nomac) & LT(u, len_withmac), + buf[u], 0x00); + rot_count = MUX(EQ(u, len_nomac), v, rot_count); + if (++ v == cc->mac_len) { + v = 0; + } + } + max_len -= cc->mac_len; + + /* + * Rotate back the MAC value. The loop below does the constant-time + * rotation in time n*log n for a MAC output of length n. We assume + * that the MAC output length is no more than 64 bytes, so the + * rotation count fits on 6 bits. + */ + for (i = 5; i >= 0; i --) { + uint32_t rc; + + rc = (uint32_t)1 << i; + cond_rotate(rot_count >> i, tmp1, cc->mac_len, rc); + rot_count &= ~rc; + } + + /* + * Recompute the HMAC value. The input is the concatenation of + * the sequence number (8 bytes), the record header (5 bytes), + * and the payload. + * + * At that point, min_len is the minimum plaintext length, but + * max_len still includes the MAC length. + */ + br_enc64be(tmp2, cc->seq ++); + tmp2[8] = (unsigned char)record_type; + br_enc16be(tmp2 + 9, version); + br_enc16be(tmp2 + 11, len_nomac); + br_hmac_init(&hc, &cc->mac, cc->mac_len); + br_hmac_update(&hc, tmp2, 13); + br_hmac_outCT(&hc, buf, len_nomac, min_len, max_len, tmp2); + + /* + * Compare the extracted and recomputed MAC values. + */ + for (u = 0; u < cc->mac_len; u ++) { + good &= EQ0(tmp1[u] ^ tmp2[u]); + } + + /* + * Check that the plaintext length is valid. The previous + * check was on the encrypted length, but the padding may have + * turned shorter than expected. + * + * Once this final test is done, the critical "constant-time" + * section ends and we can make conditional jumps again. + */ + good &= LE(len_nomac, 16384); + + if (!good) { + return 0; + } + *data_len = len_nomac; + return buf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable = { + { + sizeof(br_sslrec_in_cbc_context), + (int (*)(const br_sslrec_in_class *const *, size_t)) + &cbc_check_length, + (unsigned char *(*)(const br_sslrec_in_class **, + int, unsigned, void *, size_t *)) + &cbc_decrypt + }, + (void (*)(const br_sslrec_in_cbc_class **, + const br_block_cbcdec_class *, const void *, size_t, + const br_hash_class *, const void *, size_t, size_t, + const void *)) + &in_cbc_init +}; + +/* + * For CBC output: + * + * -- With TLS 1.1+, there is an explicit IV. Generation method uses + * HMAC, computed over the current sequence number, and the current MAC + * key. The resulting value is truncated to the size of a block, and + * added at the head of the plaintext; it will get encrypted along with + * the data. This custom generation mechanism is "safe" under the + * assumption that HMAC behaves like a random oracle; since the MAC for + * a record is computed over the concatenation of the sequence number, + * the record header and the plaintext, the HMAC-for-IV will not collide + * with the normal HMAC. + * + * -- With TLS 1.0, for application data, we want to enforce a 1/n-1 + * split, as a countermeasure against chosen-plaintext attacks. We thus + * need to leave some room in the buffer for that extra record. + */ + +static void +out_cbc_init(br_sslrec_out_cbc_context *cc, + const br_block_cbcenc_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv) +{ + cc->vtable = &br_sslrec_out_cbc_vtable; + cc->seq = 0; + bc_impl->init(&cc->bc.vtable, bc_key, bc_key_len); + br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len); + cc->mac_len = mac_out_len; + if (iv == NULL) { + memset(cc->iv, 0, sizeof cc->iv); + cc->explicit_IV = 1; + } else { + memcpy(cc->iv, iv, bc_impl->block_size); + cc->explicit_IV = 0; + } +} + +static void +cbc_max_plaintext(const br_sslrec_out_cbc_context *cc, + size_t *start, size_t *end) +{ + size_t blen, len; + + blen = cc->bc.vtable->block_size; + if (cc->explicit_IV) { + *start += blen; + } else { + *start += 4 + ((cc->mac_len + blen + 1) & ~(blen - 1)); + } + len = (*end - *start) & ~(blen - 1); + len -= 1 + cc->mac_len; + if (len > 16384) { + len = 16384; + } + *end = *start + len; +} + +static unsigned char * +cbc_encrypt(br_sslrec_out_cbc_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + unsigned char *buf, *rbuf; + size_t len, blen, plen; + unsigned char tmp[13]; + br_hmac_context hc; + + buf = data; + len = *data_len; + blen = cc->bc.vtable->block_size; + + /* + * If using TLS 1.0, with more than one byte of plaintext, and + * the record is application data, then we need to compute + * a "split". We do not perform the split on other record types + * because it turned out that some existing, deployed + * implementations of SSL/TLS do not tolerate the splitting of + * some message types (in particular the Finished message). + * + * If using TLS 1.1+, then there is an explicit IV. We produce + * that IV by adding an extra initial plaintext block, whose + * value is computed with HMAC over the record sequence number. + */ + if (cc->explicit_IV) { + /* + * We use here the fact that all the HMAC variants we + * support can produce at least 16 bytes, while all the + * block ciphers we support have blocks of no more than + * 16 bytes. Thus, we can always truncate the HMAC output + * down to the block size. + */ + br_enc64be(tmp, cc->seq); + br_hmac_init(&hc, &cc->mac, blen); + br_hmac_update(&hc, tmp, 8); + br_hmac_out(&hc, buf - blen); + rbuf = buf - blen - 5; + } else { + if (len > 1 && record_type == BR_SSL_APPLICATION_DATA) { + /* + * To do the split, we use a recursive invocation; + * since we only give one byte to the inner call, + * the recursion stops there. + * + * We need to compute the exact size of the extra + * record, so that the two resulting records end up + * being sequential in RAM. + * + * We use here the fact that cbc_max_plaintext() + * adjusted the start offset to leave room for the + * initial fragment. + */ + size_t xlen; + + rbuf = buf - 4 + - ((cc->mac_len + blen + 1) & ~(blen - 1)); + rbuf[0] = buf[0]; + xlen = 1; + rbuf = cbc_encrypt(cc, record_type, + version, rbuf, &xlen); + buf ++; + len --; + } else { + rbuf = buf - 5; + } + } + + /* + * Compute MAC. + */ + br_enc64be(tmp, cc->seq ++); + tmp[8] = record_type; + br_enc16be(tmp + 9, version); + br_enc16be(tmp + 11, len); + br_hmac_init(&hc, &cc->mac, cc->mac_len); + br_hmac_update(&hc, tmp, 13); + br_hmac_update(&hc, buf, len); + br_hmac_out(&hc, buf + len); + len += cc->mac_len; + + /* + * Add padding. + */ + plen = blen - (len & (blen - 1)); + memset(buf + len, (unsigned)plen - 1, plen); + len += plen; + + /* + * If an explicit IV is used, the corresponding extra block was + * already put in place earlier; we just have to account for it + * here. + */ + if (cc->explicit_IV) { + buf -= blen; + len += blen; + } + + /* + * Encrypt the whole thing. If there is an explicit IV, we also + * encrypt it, which is fine (encryption of a uniformly random + * block is still a uniformly random block). + */ + cc->bc.vtable->run(&cc->bc.vtable, cc->iv, buf, len); + + /* + * Add the header and return. + */ + buf[-5] = record_type; + br_enc16be(buf - 4, version); + br_enc16be(buf - 2, len); + *data_len = (size_t)((buf + len) - rbuf); + return rbuf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable = { + { + sizeof(br_sslrec_out_cbc_context), + (void (*)(const br_sslrec_out_class *const *, + size_t *, size_t *)) + &cbc_max_plaintext, + (unsigned char *(*)(const br_sslrec_out_class **, + int, unsigned, void *, size_t *)) + &cbc_encrypt + }, + (void (*)(const br_sslrec_out_cbc_class **, + const br_block_cbcenc_class *, const void *, size_t, + const br_hash_class *, const void *, size_t, size_t, + const void *)) + &out_cbc_init +}; diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_rec_ccm.c b/BearSSL-OG/libbearssl/src/ssl/ssl_rec_ccm.c new file mode 100644 index 0000000..92c3295 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_rec_ccm.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* + * CCM initialisation. This does everything except setting the vtable, + * which depends on whether this is a context for encrypting or for + * decrypting. + */ +static void +gen_ccm_init(br_sslrec_ccm_context *cc, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len) +{ + cc->seq = 0; + bc_impl->init(&cc->bc.vtable, key, key_len); + memcpy(cc->iv, iv, sizeof cc->iv); + cc->tag_len = tag_len; +} + +static void +in_ccm_init(br_sslrec_ccm_context *cc, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len) +{ + cc->vtable.in = &br_sslrec_in_ccm_vtable; + gen_ccm_init(cc, bc_impl, key, key_len, iv, tag_len); +} + +static int +ccm_check_length(const br_sslrec_ccm_context *cc, size_t rlen) +{ + /* + * CCM overhead is 8 bytes for nonce_explicit, and the tag + * (normally 8 or 16 bytes, depending on cipher suite). + */ + size_t over; + + over = 8 + cc->tag_len; + return rlen >= over && rlen <= (16384 + over); +} + +static unsigned char * +ccm_decrypt(br_sslrec_ccm_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + br_ccm_context zc; + unsigned char *buf; + unsigned char nonce[12], header[13]; + size_t len; + + buf = (unsigned char *)data + 8; + len = *data_len - (8 + cc->tag_len); + + /* + * Make nonce (implicit + explicit parts). + */ + memcpy(nonce, cc->iv, sizeof cc->iv); + memcpy(nonce + 4, data, 8); + + /* + * Assemble synthetic header for the AAD. + */ + br_enc64be(header, cc->seq ++); + header[8] = (unsigned char)record_type; + br_enc16be(header + 9, version); + br_enc16be(header + 11, len); + + /* + * Perform CCM decryption. + */ + br_ccm_init(&zc, &cc->bc.vtable); + br_ccm_reset(&zc, nonce, sizeof nonce, sizeof header, len, cc->tag_len); + br_ccm_aad_inject(&zc, header, sizeof header); + br_ccm_flip(&zc); + br_ccm_run(&zc, 0, buf, len); + if (!br_ccm_check_tag(&zc, buf + len)) { + return NULL; + } + *data_len = len; + return buf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable = { + { + sizeof(br_sslrec_ccm_context), + (int (*)(const br_sslrec_in_class *const *, size_t)) + &ccm_check_length, + (unsigned char *(*)(const br_sslrec_in_class **, + int, unsigned, void *, size_t *)) + &ccm_decrypt + }, + (void (*)(const br_sslrec_in_ccm_class **, + const br_block_ctrcbc_class *, const void *, size_t, + const void *, size_t)) + &in_ccm_init +}; + +static void +out_ccm_init(br_sslrec_ccm_context *cc, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len) +{ + cc->vtable.out = &br_sslrec_out_ccm_vtable; + gen_ccm_init(cc, bc_impl, key, key_len, iv, tag_len); +} + +static void +ccm_max_plaintext(const br_sslrec_ccm_context *cc, + size_t *start, size_t *end) +{ + size_t len; + + *start += 8; + len = *end - *start - cc->tag_len; + if (len > 16384) { + len = 16384; + } + *end = *start + len; +} + +static unsigned char * +ccm_encrypt(br_sslrec_ccm_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + br_ccm_context zc; + unsigned char *buf; + unsigned char nonce[12], header[13]; + size_t len; + + buf = (unsigned char *)data; + len = *data_len; + + /* + * Make nonce; the explicit part is an encoding of the sequence + * number. + */ + memcpy(nonce, cc->iv, sizeof cc->iv); + br_enc64be(nonce + 4, cc->seq); + + /* + * Assemble synthetic header for the AAD. + */ + br_enc64be(header, cc->seq ++); + header[8] = (unsigned char)record_type; + br_enc16be(header + 9, version); + br_enc16be(header + 11, len); + + /* + * Perform CCM encryption. + */ + br_ccm_init(&zc, &cc->bc.vtable); + br_ccm_reset(&zc, nonce, sizeof nonce, sizeof header, len, cc->tag_len); + br_ccm_aad_inject(&zc, header, sizeof header); + br_ccm_flip(&zc); + br_ccm_run(&zc, 1, buf, len); + br_ccm_get_tag(&zc, buf + len); + + /* + * Assemble header and adjust pointer/length. + */ + len += 8 + cc->tag_len; + buf -= 13; + memcpy(buf + 5, nonce + 4, 8); + buf[0] = (unsigned char)record_type; + br_enc16be(buf + 1, version); + br_enc16be(buf + 3, len); + *data_len = len + 5; + return buf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable = { + { + sizeof(br_sslrec_ccm_context), + (void (*)(const br_sslrec_out_class *const *, + size_t *, size_t *)) + &ccm_max_plaintext, + (unsigned char *(*)(const br_sslrec_out_class **, + int, unsigned, void *, size_t *)) + &ccm_encrypt + }, + (void (*)(const br_sslrec_out_ccm_class **, + const br_block_ctrcbc_class *, const void *, size_t, + const void *, size_t)) + &out_ccm_init +}; diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_rec_chapol.c b/BearSSL-OG/libbearssl/src/ssl/ssl_rec_chapol.c new file mode 100644 index 0000000..73b3c78 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_rec_chapol.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 +gen_chapol_init(br_sslrec_chapol_context *cc, + br_chacha20_run ichacha, br_poly1305_run ipoly, + const void *key, const void *iv) +{ + cc->seq = 0; + cc->ichacha = ichacha; + cc->ipoly = ipoly; + memcpy(cc->key, key, sizeof cc->key); + memcpy(cc->iv, iv, sizeof cc->iv); +} + +static void +gen_chapol_process(br_sslrec_chapol_context *cc, + int record_type, unsigned version, void *data, size_t len, + void *tag, int encrypt) +{ + unsigned char header[13]; + unsigned char nonce[12]; + uint64_t seq; + size_t u; + + seq = cc->seq ++; + br_enc64be(header, seq); + header[8] = (unsigned char)record_type; + br_enc16be(header + 9, version); + br_enc16be(header + 11, len); + memcpy(nonce, cc->iv, 12); + for (u = 0; u < 8; u ++) { + nonce[11 - u] ^= (unsigned char)seq; + seq >>= 8; + } + cc->ipoly(cc->key, nonce, data, len, header, sizeof header, + tag, cc->ichacha, encrypt); +} + +static void +in_chapol_init(br_sslrec_chapol_context *cc, + br_chacha20_run ichacha, br_poly1305_run ipoly, + const void *key, const void *iv) +{ + cc->vtable.in = &br_sslrec_in_chapol_vtable; + gen_chapol_init(cc, ichacha, ipoly, key, iv); +} + +static int +chapol_check_length(const br_sslrec_chapol_context *cc, size_t rlen) +{ + /* + * Overhead is just the authentication tag (16 bytes). + */ + (void)cc; + return rlen >= 16 && rlen <= (16384 + 16); +} + +static unsigned char * +chapol_decrypt(br_sslrec_chapol_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + unsigned char *buf; + size_t u, len; + unsigned char tag[16]; + unsigned bad; + + buf = data; + len = *data_len - 16; + gen_chapol_process(cc, record_type, version, buf, len, tag, 0); + bad = 0; + for (u = 0; u < 16; u ++) { + bad |= tag[u] ^ buf[len + u]; + } + if (bad) { + return NULL; + } + *data_len = len; + return buf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable = { + { + sizeof(br_sslrec_chapol_context), + (int (*)(const br_sslrec_in_class *const *, size_t)) + &chapol_check_length, + (unsigned char *(*)(const br_sslrec_in_class **, + int, unsigned, void *, size_t *)) + &chapol_decrypt + }, + (void (*)(const br_sslrec_in_chapol_class **, + br_chacha20_run, br_poly1305_run, + const void *, const void *)) + &in_chapol_init +}; + +static void +out_chapol_init(br_sslrec_chapol_context *cc, + br_chacha20_run ichacha, br_poly1305_run ipoly, + const void *key, const void *iv) +{ + cc->vtable.out = &br_sslrec_out_chapol_vtable; + gen_chapol_init(cc, ichacha, ipoly, key, iv); +} + +static void +chapol_max_plaintext(const br_sslrec_chapol_context *cc, + size_t *start, size_t *end) +{ + size_t len; + + (void)cc; + len = *end - *start - 16; + if (len > 16384) { + len = 16384; + } + *end = *start + len; +} + +static unsigned char * +chapol_encrypt(br_sslrec_chapol_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + unsigned char *buf; + size_t len; + + buf = data; + len = *data_len; + gen_chapol_process(cc, record_type, version, buf, len, buf + len, 1); + buf -= 5; + buf[0] = (unsigned char)record_type; + br_enc16be(buf + 1, version); + br_enc16be(buf + 3, len + 16); + *data_len = len + 21; + return buf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable = { + { + sizeof(br_sslrec_chapol_context), + (void (*)(const br_sslrec_out_class *const *, + size_t *, size_t *)) + &chapol_max_plaintext, + (unsigned char *(*)(const br_sslrec_out_class **, + int, unsigned, void *, size_t *)) + &chapol_encrypt + }, + (void (*)(const br_sslrec_out_chapol_class **, + br_chacha20_run, br_poly1305_run, + const void *, const void *)) + &out_chapol_init +}; diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_rec_gcm.c b/BearSSL-OG/libbearssl/src/ssl/ssl_rec_gcm.c new file mode 100644 index 0000000..70df277 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_rec_gcm.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * GCM initialisation. This does everything except setting the vtable, + * which depends on whether this is a context for encrypting or for + * decrypting. + */ +static void +gen_gcm_init(br_sslrec_gcm_context *cc, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv) +{ + unsigned char tmp[12]; + + cc->seq = 0; + bc_impl->init(&cc->bc.vtable, key, key_len); + cc->gh = gh_impl; + memcpy(cc->iv, iv, sizeof cc->iv); + memset(cc->h, 0, sizeof cc->h); + memset(tmp, 0, sizeof tmp); + bc_impl->run(&cc->bc.vtable, tmp, 0, cc->h, sizeof cc->h); +} + +static void +in_gcm_init(br_sslrec_gcm_context *cc, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv) +{ + cc->vtable.in = &br_sslrec_in_gcm_vtable; + gen_gcm_init(cc, bc_impl, key, key_len, gh_impl, iv); +} + +static int +gcm_check_length(const br_sslrec_gcm_context *cc, size_t rlen) +{ + /* + * GCM adds a fixed overhead: + * 8 bytes for the nonce_explicit (before the ciphertext) + * 16 bytes for the authentication tag (after the ciphertext) + */ + (void)cc; + return rlen >= 24 && rlen <= (16384 + 24); +} + +/* + * Compute the authentication tag. The value written in 'tag' must still + * be CTR-encrypted. + */ +static void +do_tag(br_sslrec_gcm_context *cc, + int record_type, unsigned version, + void *data, size_t len, void *tag) +{ + unsigned char header[13]; + unsigned char footer[16]; + + /* + * Compute authentication tag. Three elements must be injected in + * sequence, each possibly 0-padded to reach a length multiple + * of the block size: the 13-byte header (sequence number, record + * type, protocol version, record length), the cipher text, and + * the word containing the encodings of the bit lengths of the two + * other elements. + */ + br_enc64be(header, cc->seq ++); + header[8] = (unsigned char)record_type; + br_enc16be(header + 9, version); + br_enc16be(header + 11, len); + br_enc64be(footer, (uint64_t)(sizeof header) << 3); + br_enc64be(footer + 8, (uint64_t)len << 3); + memset(tag, 0, 16); + cc->gh(tag, cc->h, header, sizeof header); + cc->gh(tag, cc->h, data, len); + cc->gh(tag, cc->h, footer, sizeof footer); +} + +/* + * Do CTR encryption. This also does CTR encryption of a single block at + * address 'xortag' with the counter value appropriate for the final + * processing of the authentication tag. + */ +static void +do_ctr(br_sslrec_gcm_context *cc, const void *nonce, void *data, size_t len, + void *xortag) +{ + unsigned char iv[12]; + + memcpy(iv, cc->iv, 4); + memcpy(iv + 4, nonce, 8); + cc->bc.vtable->run(&cc->bc.vtable, iv, 2, data, len); + cc->bc.vtable->run(&cc->bc.vtable, iv, 1, xortag, 16); +} + +static unsigned char * +gcm_decrypt(br_sslrec_gcm_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + unsigned char *buf; + size_t len, u; + uint32_t bad; + unsigned char tag[16]; + + buf = (unsigned char *)data + 8; + len = *data_len - 24; + do_tag(cc, record_type, version, buf, len, tag); + do_ctr(cc, data, buf, len, tag); + + /* + * Compare the computed tag with the value from the record. It + * is possibly useless to do a constant-time comparison here, + * but it does not hurt. + */ + bad = 0; + for (u = 0; u < 16; u ++) { + bad |= tag[u] ^ buf[len + u]; + } + if (bad) { + return NULL; + } + *data_len = len; + return buf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable = { + { + sizeof(br_sslrec_gcm_context), + (int (*)(const br_sslrec_in_class *const *, size_t)) + &gcm_check_length, + (unsigned char *(*)(const br_sslrec_in_class **, + int, unsigned, void *, size_t *)) + &gcm_decrypt + }, + (void (*)(const br_sslrec_in_gcm_class **, + const br_block_ctr_class *, const void *, size_t, + br_ghash, const void *)) + &in_gcm_init +}; + +static void +out_gcm_init(br_sslrec_gcm_context *cc, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv) +{ + cc->vtable.out = &br_sslrec_out_gcm_vtable; + gen_gcm_init(cc, bc_impl, key, key_len, gh_impl, iv); +} + +static void +gcm_max_plaintext(const br_sslrec_gcm_context *cc, + size_t *start, size_t *end) +{ + size_t len; + + (void)cc; + *start += 8; + len = *end - *start - 16; + if (len > 16384) { + len = 16384; + } + *end = *start + len; +} + +static unsigned char * +gcm_encrypt(br_sslrec_gcm_context *cc, + int record_type, unsigned version, void *data, size_t *data_len) +{ + unsigned char *buf; + size_t u, len; + unsigned char tmp[16]; + + buf = (unsigned char *)data; + len = *data_len; + memset(tmp, 0, sizeof tmp); + br_enc64be(buf - 8, cc->seq); + do_ctr(cc, buf - 8, buf, len, tmp); + do_tag(cc, record_type, version, buf, len, buf + len); + for (u = 0; u < 16; u ++) { + buf[len + u] ^= tmp[u]; + } + len += 24; + buf -= 13; + buf[0] = (unsigned char)record_type; + br_enc16be(buf + 1, version); + br_enc16be(buf + 3, len); + *data_len = len + 5; + return buf; +} + +/* see bearssl_ssl.h */ +const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable = { + { + sizeof(br_sslrec_gcm_context), + (void (*)(const br_sslrec_out_class *const *, + size_t *, size_t *)) + &gcm_max_plaintext, + (unsigned char *(*)(const br_sslrec_out_class **, + int, unsigned, void *, size_t *)) + &gcm_encrypt + }, + (void (*)(const br_sslrec_out_gcm_class **, + const br_block_ctr_class *, const void *, size_t, + br_ghash, const void *)) + &out_gcm_init +}; diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_scert_single_ec.c b/BearSSL-OG/libbearssl/src/ssl/ssl_scert_single_ec.c new file mode 100644 index 0000000..ce8d753 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_scert_single_ec.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 int +se_choose(const br_ssl_server_policy_class **pctx, + const br_ssl_server_context *cc, + br_ssl_server_choices *choices) +{ + br_ssl_server_policy_ec_context *pc; + const br_suite_translated *st; + size_t u, st_num; + unsigned hash_id; + + 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) >> 8); + if (cc->eng.session.version < BR_TLS12) { + hash_id = br_sha1_ID; + } + choices->chain = pc->chain; + choices->chain_len = pc->chain_len; + for (u = 0; u < st_num; u ++) { + unsigned tt; + + tt = st[u][1]; + switch (tt >> 12) { + case BR_SSLKEYX_ECDH_RSA: + if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0 + && pc->cert_issuer_key_type == BR_KEYTYPE_RSA) + { + choices->cipher_suite = st[u][0]; + return 1; + } + break; + case BR_SSLKEYX_ECDH_ECDSA: + if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0 + && pc->cert_issuer_key_type == BR_KEYTYPE_EC) + { + choices->cipher_suite = st[u][0]; + return 1; + } + break; + case BR_SSLKEYX_ECDHE_ECDSA: + if ((pc->allowed_usages & BR_KEYTYPE_SIGN) != 0 + && hash_id != 0) + { + choices->cipher_suite = st[u][0]; + choices->algo_id = hash_id + 0xFF00; + return 1; + } + break; + } + } + return 0; +} + +static uint32_t +se_do_keyx(const br_ssl_server_policy_class **pctx, + unsigned char *data, size_t *len) +{ + br_ssl_server_policy_ec_context *pc; + uint32_t r; + size_t xoff, xlen; + + pc = (br_ssl_server_policy_ec_context *)pctx; + r = pc->iec->mul(data, *len, pc->sk->x, pc->sk->xlen, pc->sk->curve); + xoff = pc->iec->xoff(pc->sk->curve, &xlen); + memmove(data, data + xoff, xlen); + *len = xlen; + return r; +} + +static size_t +se_do_sign(const br_ssl_server_policy_class **pctx, + unsigned algo_id, unsigned char *data, size_t hv_len, size_t len) +{ + br_ssl_server_policy_ec_context *pc; + unsigned char hv[64]; + const br_hash_class *hc; + + algo_id &= 0xFF; + pc = (br_ssl_server_policy_ec_context *)pctx; + hc = br_multihash_getimpl(pc->mhash, algo_id); + if (hc == NULL) { + return 0; + } + memcpy(hv, data, hv_len); + if (len < 139) { + return 0; + } + return pc->iecdsa(pc->iec, hc, hv, pc->sk, data); +} + +static const br_ssl_server_policy_class se_policy_vtable = { + sizeof(br_ssl_server_policy_ec_context), + se_choose, + se_do_keyx, + se_do_sign +}; + +/* see bearssl_ssl.h */ +void +br_ssl_server_set_single_ec(br_ssl_server_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->chain_handler.single_ec.vtable = &se_policy_vtable; + cc->chain_handler.single_ec.chain = chain; + cc->chain_handler.single_ec.chain_len = chain_len; + cc->chain_handler.single_ec.sk = sk; + cc->chain_handler.single_ec.allowed_usages = allowed_usages; + cc->chain_handler.single_ec.cert_issuer_key_type = cert_issuer_key_type; + cc->chain_handler.single_ec.mhash = &cc->eng.mhash; + cc->chain_handler.single_ec.iec = iec; + cc->chain_handler.single_ec.iecdsa = iecdsa; + cc->policy_vtable = &cc->chain_handler.single_ec.vtable; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_scert_single_rsa.c b/BearSSL-OG/libbearssl/src/ssl/ssl_scert_single_rsa.c new file mode 100644 index 0000000..b2c7767 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_scert_single_rsa.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 int +sr_choose(const br_ssl_server_policy_class **pctx, + const br_ssl_server_context *cc, + br_ssl_server_choices *choices) +{ + br_ssl_server_policy_rsa_context *pc; + const br_suite_translated *st; + size_t u, st_num; + unsigned hash_id; + int fh; + + pc = (br_ssl_server_policy_rsa_context *)pctx; + st = br_ssl_server_get_client_suites(cc, &st_num); + if (cc->eng.session.version < BR_TLS12) { + hash_id = 0; + fh = 1; + } else { + hash_id = br_ssl_choose_hash( + br_ssl_server_get_client_hashes(cc)); + fh = (hash_id != 0); + } + choices->chain = pc->chain; + choices->chain_len = pc->chain_len; + for (u = 0; u < st_num; u ++) { + unsigned tt; + + tt = st[u][1]; + switch (tt >> 12) { + case BR_SSLKEYX_RSA: + if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0) { + choices->cipher_suite = st[u][0]; + return 1; + } + break; + case BR_SSLKEYX_ECDHE_RSA: + if ((pc->allowed_usages & BR_KEYTYPE_SIGN) != 0 && fh) { + choices->cipher_suite = st[u][0]; + choices->algo_id = hash_id + 0xFF00; + return 1; + } + break; + } + } + return 0; +} + +static uint32_t +sr_do_keyx(const br_ssl_server_policy_class **pctx, + unsigned char *data, size_t *len) +{ + br_ssl_server_policy_rsa_context *pc; + + pc = (br_ssl_server_policy_rsa_context *)pctx; + return br_rsa_ssl_decrypt(pc->irsacore, pc->sk, data, *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 +sr_do_sign(const br_ssl_server_policy_class **pctx, + unsigned algo_id, unsigned char *data, size_t hv_len, size_t len) +{ + br_ssl_server_policy_rsa_context *pc; + unsigned char hv[64]; + size_t sig_len; + const unsigned char *hash_oid; + + pc = (br_ssl_server_policy_rsa_context *)pctx; + memcpy(hv, data, hv_len); + algo_id &= 0xFF; + if (algo_id == 0) { + hash_oid = NULL; + } else if (algo_id >= 2 && algo_id <= 6) { + hash_oid = HASH_OID[algo_id - 2]; + } else { + return 0; + } + sig_len = (pc->sk->n_bitlen + 7) >> 3; + if (len < sig_len) { + return 0; + } + return pc->irsasign(hash_oid, hv, hv_len, pc->sk, data) ? sig_len : 0; +} + +static const br_ssl_server_policy_class sr_policy_vtable = { + sizeof(br_ssl_server_policy_rsa_context), + sr_choose, + sr_do_keyx, + sr_do_sign +}; + +/* see bearssl_ssl.h */ +void +br_ssl_server_set_single_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, unsigned allowed_usages, + br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign) +{ + cc->chain_handler.single_rsa.vtable = &sr_policy_vtable; + cc->chain_handler.single_rsa.chain = chain; + cc->chain_handler.single_rsa.chain_len = chain_len; + cc->chain_handler.single_rsa.sk = sk; + cc->chain_handler.single_rsa.allowed_usages = allowed_usages; + cc->chain_handler.single_rsa.irsacore = irsacore; + cc->chain_handler.single_rsa.irsasign = irsasign; + cc->policy_vtable = &cc->chain_handler.single_rsa.vtable; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server.c new file mode 100644 index 0000000..5578b63 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_zero(br_ssl_server_context *cc) +{ + /* + * For really standard C, we should explicitly set to NULL all + * pointers, and 0 all other fields. However, on all our target + * architectures, a direct memset() will work, be faster, and + * use a lot less code. + */ + memset(cc, 0, sizeof *cc); +} + +/* see bearssl_ssl.h */ +int +br_ssl_server_reset(br_ssl_server_context *cc) +{ + br_ssl_engine_set_buffer(&cc->eng, NULL, 0, 0); + if (!br_ssl_engine_init_rand(&cc->eng)) { + return 0; + } + cc->eng.reneg = 0; + br_ssl_engine_hs_reset(&cc->eng, + br_ssl_hs_server_init_main, br_ssl_hs_server_run); + return br_ssl_engine_last_error(&cc->eng) == BR_ERR_OK; +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_full_ec.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_full_ec.c new file mode 100644 index 0000000..bccc093 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_full_ec.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_full_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + unsigned cert_issuer_key_type, const br_ec_private_key *sk) +{ + /* + * The "full" profile supports all implemented cipher suites. + * + * Rationale for suite order, from most important to least + * important rule: + * + * -- Don't use 3DES if AES is available. + * -- Try to have Forward Secrecy (ECDHE suite) if possible. + * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller). + * -- GCM is better than CCM and CBC. CCM is better than CBC. + * -- CCM is better than CCM_8. + * -- AES-128 is preferred over AES-256 (AES-128 is already + * strong enough, and AES-256 is 40% more expensive). + * + * Note that for ECDH suites, the list will be automatically + * filtered based on the issuing CA key type. + */ + static const uint16_t suites[] = { + BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + }; + + /* + * All hash functions are activated. + * Note: the X.509 validation engine will nonetheless refuse to + * validate signatures that use MD5 as hash function. + */ + static const br_hash_class *hashes[] = { + &br_md5_vtable, + &br_sha1_vtable, + &br_sha224_vtable, + &br_sha256_vtable, + &br_sha384_vtable, + &br_sha512_vtable + }; + + int id; + + /* + * Reset server context and set supported versions from TLS-1.0 + * to TLS-1.2 (inclusive). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12); + + /* + * Set suites and elliptic curve implementation (for ECDHE). + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + br_ssl_engine_set_default_ec(&cc->eng); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_ec(cc, chain, chain_len, sk, + BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, + cert_issuer_key_type, + br_ssl_engine_get_ec(&cc->eng), +#if BR_LOMUL + br_ecdsa_i15_sign_asn1 +#else + br_ecdsa_i31_sign_asn1 +#endif + ); + + /* + * Set supported hash functions. + */ + for (id = br_md5_ID; id <= br_sha512_ID; id ++) { + const br_hash_class *hc; + + hc = hashes[id - 1]; + br_ssl_engine_set_hash(&cc->eng, id, hc); + } + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf); + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_aes_cbc(&cc->eng); + br_ssl_engine_set_default_aes_ccm(&cc->eng); + br_ssl_engine_set_default_aes_gcm(&cc->eng); + br_ssl_engine_set_default_des_cbc(&cc->eng); + br_ssl_engine_set_default_chapol(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_full_rsa.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_full_rsa.c new file mode 100644 index 0000000..d67c076 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_full_rsa.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_full_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk) +{ + /* + * The "full" profile supports all implemented cipher suites. + * + * Rationale for suite order, from most important to least + * important rule: + * + * -- Don't use 3DES if AES is available. + * -- Try to have Forward Secrecy (ECDHE suite) if possible. + * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller). + * -- GCM is better than CBC. + * -- AES-128 is preferred over AES-256 (AES-128 is already + * strong enough, and AES-256 is 40% more expensive). + */ + static const uint16_t suites[] = { + BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + BR_TLS_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_RSA_WITH_AES_128_CCM, + BR_TLS_RSA_WITH_AES_256_CCM, + BR_TLS_RSA_WITH_AES_128_CCM_8, + BR_TLS_RSA_WITH_AES_256_CCM_8, + BR_TLS_RSA_WITH_AES_128_CBC_SHA256, + BR_TLS_RSA_WITH_AES_256_CBC_SHA256, + BR_TLS_RSA_WITH_AES_128_CBC_SHA, + BR_TLS_RSA_WITH_AES_256_CBC_SHA, + BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA + }; + + /* + * All hash functions are activated. + * Note: the X.509 validation engine will nonetheless refuse to + * validate signatures that use MD5 as hash function. + */ + static const br_hash_class *hashes[] = { + &br_md5_vtable, + &br_sha1_vtable, + &br_sha224_vtable, + &br_sha256_vtable, + &br_sha384_vtable, + &br_sha512_vtable + }; + + int id; + + /* + * Reset server context and set supported versions from TLS-1.0 + * to TLS-1.2 (inclusive). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12); + + /* + * Set suites and elliptic curve implementation (for ECDHE). + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + br_ssl_engine_set_default_ec(&cc->eng); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, + BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, + br_rsa_private_get_default(), + br_rsa_pkcs1_sign_get_default()); + + /* + * Set supported hash functions. + */ + for (id = br_md5_ID; id <= br_sha512_ID; id ++) { + const br_hash_class *hc; + + hc = hashes[id - 1]; + br_ssl_engine_set_hash(&cc->eng, id, hc); + } + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf); + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_aes_cbc(&cc->eng); + br_ssl_engine_set_default_aes_ccm(&cc->eng); + br_ssl_engine_set_default_aes_gcm(&cc->eng); + br_ssl_engine_set_default_des_cbc(&cc->eng); + br_ssl_engine_set_default_chapol(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_mine2c.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_mine2c.c new file mode 100644 index 0000000..bf61b56 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_mine2c.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_mine2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk) +{ + static const uint16_t suites[] = { + BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + }; + + /* + * Reset server context and set supported versions to TLS-1.2 (only). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); + + /* + * Set suites and elliptic curve implementation (for ECDHE). + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, + BR_KEYTYPE_SIGN, 0, br_rsa_i31_pkcs1_sign); + + /* + * Set supported hash functions. + */ + br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_chapol(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_mine2g.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_mine2g.c new file mode 100644 index 0000000..80fa5b1 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_mine2g.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_mine2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk) +{ + static const uint16_t suites[] = { + BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + }; + + /* + * Reset server context and set supported versions to TLS-1.2 (only). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); + + /* + * Set suites and elliptic curve implementation (for ECDHE). + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, + BR_KEYTYPE_SIGN, 0, br_rsa_i31_pkcs1_sign); + + /* + * Set supported hash functions. + */ + br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_aes_gcm(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_minf2c.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minf2c.c new file mode 100644 index 0000000..3f44236 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minf2c.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_minf2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk) +{ + static const uint16_t suites[] = { + BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + }; + + /* + * Reset server context and set supported versions to TLS-1.2 (only). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); + + /* + * Set suites and elliptic curve implementation (for ECDHE). + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_ec(cc, chain, chain_len, sk, + BR_KEYTYPE_SIGN, 0, &br_ec_all_m15, br_ecdsa_i31_sign_asn1); + + /* + * Set supported hash functions. + */ + br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_chapol(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_minf2g.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minf2g.c new file mode 100644 index 0000000..8613de1 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minf2g.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_minf2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk) +{ + static const uint16_t suites[] = { + BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + }; + + /* + * Reset server context and set supported versions to TLS-1.2 (only). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); + + /* + * Set suites and elliptic curve implementation (for ECDHE). + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_ec(cc, chain, chain_len, sk, + BR_KEYTYPE_SIGN, 0, &br_ec_all_m15, br_ecdsa_i31_sign_asn1); + + /* + * Set supported hash functions. + */ + br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_aes_gcm(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_minr2g.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minr2g.c new file mode 100644 index 0000000..83c238b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minr2g.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_minr2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk) +{ + static const uint16_t suites[] = { + BR_TLS_RSA_WITH_AES_128_GCM_SHA256 + }; + + /* + * Reset server context and set supported versions to TLS-1.2 (only). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); + + /* + * Set suites. + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, + BR_KEYTYPE_KEYX, br_rsa_i31_private, 0); + + /* + * Set supported hash functions. + */ + br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_aes_gcm(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_minu2g.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minu2g.c new file mode 100644 index 0000000..6721384 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minu2g.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_minu2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk) +{ + static const uint16_t suites[] = { + BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + }; + + /* + * Reset server context and set supported versions to TLS-1.2 (only). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); + + /* + * Set suites. + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_ec(cc, chain, chain_len, sk, + BR_KEYTYPE_KEYX, BR_KEYTYPE_RSA, &br_ec_all_m15, 0); + + /* + * Set supported hash functions. + */ + br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_aes_gcm(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/ssl/ssl_server_minv2g.c b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minv2g.c new file mode 100644 index 0000000..194e654 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/ssl/ssl_server_minv2g.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_ssl.h */ +void +br_ssl_server_init_minv2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk) +{ + static const uint16_t suites[] = { + BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + }; + + /* + * Reset server context and set supported versions to TLS-1.2 (only). + */ + br_ssl_server_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); + + /* + * Set suites. + */ + br_ssl_engine_set_suites(&cc->eng, suites, + (sizeof suites) / (sizeof suites[0])); + + /* + * Set the "server policy": handler for the certificate chain + * and private key operations. + */ + br_ssl_server_set_single_ec(cc, chain, chain_len, sk, + BR_KEYTYPE_KEYX, BR_KEYTYPE_EC, &br_ec_all_m15, 0); + + /* + * Set supported hash functions. + */ + br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + + /* + * Symmetric encryption. + */ + br_ssl_engine_set_default_aes_gcm(&cc->eng); +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_big_cbcdec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_big_cbcdec.c new file mode 100644 index 0000000..d969a3b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_big_cbcdec.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_big_cbcdec_vtable; + ctx->num_rounds = br_aes_big_keysched_inv(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + + ivbuf = iv; + buf = data; + while (len > 0) { + unsigned char tmp[16]; + int i; + + memcpy(tmp, buf, 16); + br_aes_big_decrypt(ctx->num_rounds, ctx->skey, buf); + for (i = 0; i < 16; i ++) { + buf[i] ^= ivbuf[i]; + } + memcpy(ivbuf, tmp, 16); + buf += 16; + len -= 16; + } +} + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_aes_big_cbcdec_vtable = { + sizeof(br_aes_big_cbcdec_keys), + 16, + 4, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_aes_big_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_aes_big_cbcdec_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_big_cbcenc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_big_cbcenc.c new file mode 100644 index 0000000..265e53b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_big_cbcenc.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_big_cbcenc_vtable; + ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + + ivbuf = iv; + buf = data; + while (len > 0) { + int i; + + for (i = 0; i < 16; i ++) { + buf[i] ^= ivbuf[i]; + } + br_aes_big_encrypt(ctx->num_rounds, ctx->skey, buf); + memcpy(ivbuf, buf, 16); + buf += 16; + len -= 16; + } +} + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_aes_big_cbcenc_vtable = { + sizeof(br_aes_big_cbcenc_keys), + 16, + 4, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_aes_big_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_aes_big_cbcenc_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_big_ctr.c b/BearSSL-OG/libbearssl/src/symcipher/aes_big_ctr.c new file mode 100644 index 0000000..18fbb84 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_big_ctr.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_big_ctr_vtable; + ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); +} + +static void +xorbuf(void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + *d ++ ^= *s ++; + } +} + +/* see bearssl_block.h */ +uint32_t +br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + + buf = data; + while (len > 0) { + unsigned char tmp[16]; + + memcpy(tmp, iv, 12); + br_enc32be(tmp + 12, cc ++); + br_aes_big_encrypt(ctx->num_rounds, ctx->skey, tmp); + if (len <= 16) { + xorbuf(buf, tmp, len); + break; + } + xorbuf(buf, tmp, 16); + buf += 16; + len -= 16; + } + return cc; +} + +/* see bearssl_block.h */ +const br_block_ctr_class br_aes_big_ctr_vtable = { + sizeof(br_aes_big_ctr_keys), + 16, + 4, + (void (*)(const br_block_ctr_class **, const void *, size_t)) + &br_aes_big_ctr_init, + (uint32_t (*)(const br_block_ctr_class *const *, + const void *, uint32_t, void *, size_t)) + &br_aes_big_ctr_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_big_ctrcbc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_big_ctrcbc.c new file mode 100644 index 0000000..d45ca76 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_big_ctrcbc.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_big_ctrcbc_vtable; + ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); +} + +static void +xorbuf(void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + *d ++ ^= *s ++; + } +} + +/* see bearssl_block.h */ +void +br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len) +{ + unsigned char *buf, *bctr; + uint32_t cc0, cc1, cc2, cc3; + + buf = data; + bctr = ctr; + cc3 = br_dec32be(bctr + 0); + cc2 = br_dec32be(bctr + 4); + cc1 = br_dec32be(bctr + 8); + cc0 = br_dec32be(bctr + 12); + while (len > 0) { + unsigned char tmp[16]; + uint32_t carry; + + br_enc32be(tmp + 0, cc3); + br_enc32be(tmp + 4, cc2); + br_enc32be(tmp + 8, cc1); + br_enc32be(tmp + 12, cc0); + br_aes_big_encrypt(ctx->num_rounds, ctx->skey, tmp); + xorbuf(buf, tmp, 16); + buf += 16; + len -= 16; + cc0 ++; + carry = (~(cc0 | -cc0)) >> 31; + cc1 += carry; + carry &= (~(cc1 | -cc1)) >> 31; + cc2 += carry; + carry &= (~(cc2 | -cc2)) >> 31; + cc3 += carry; + } + br_enc32be(bctr + 0, cc3); + br_enc32be(bctr + 4, cc2); + br_enc32be(bctr + 8, cc1); + br_enc32be(bctr + 12, cc0); +} + +/* see bearssl_block.h */ +void +br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len) +{ + const unsigned char *buf; + + buf = data; + while (len > 0) { + xorbuf(cbcmac, buf, 16); + br_aes_big_encrypt(ctx->num_rounds, ctx->skey, cbcmac); + buf += 16; + len -= 16; + } +} + +/* see bearssl_block.h */ +void +br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + br_aes_big_ctrcbc_ctr(ctx, ctr, data, len); + br_aes_big_ctrcbc_mac(ctx, cbcmac, data, len); +} + +/* see bearssl_block.h */ +void +br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + br_aes_big_ctrcbc_mac(ctx, cbcmac, data, len); + br_aes_big_ctrcbc_ctr(ctx, ctr, data, len); +} + +/* see bearssl_block.h */ +const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable = { + sizeof(br_aes_big_ctrcbc_keys), + 16, + 4, + (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) + &br_aes_big_ctrcbc_init, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_big_ctrcbc_encrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_big_ctrcbc_decrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, size_t)) + &br_aes_big_ctrcbc_ctr, + (void (*)(const br_block_ctrcbc_class *const *, + void *, const void *, size_t)) + &br_aes_big_ctrcbc_mac +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_big_dec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_big_dec.c new file mode 100644 index 0000000..27a3a36 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_big_dec.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * Inverse S-box (used in key schedule for decryption). + */ +static const unsigned char iS[] = { + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, + 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, + 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, + 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, + 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, + 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, + 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, + 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, + 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, + 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0C, 0x7D +}; + +static const uint32_t iSsm0[] = { + 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1, + 0xACFA58AB, 0x4BE30393, 0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25, + 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F, 0xDEB15A49, 0x25BA1B67, + 0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6, + 0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3, + 0x49E06929, 0x8EC9C844, 0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD, + 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4, 0x63DF4A18, 0xE51A3182, + 0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94, + 0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2, + 0xE31F8F57, 0x6655AB2A, 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5, + 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C, 0x8ACF1C2B, 0xA779B492, + 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A, + 0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA, + 0x5E719F06, 0xBD6E1051, 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46, + 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF, 0x1998FB24, 0xD6BDE997, + 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB, + 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48, + 0x1E1170AC, 0x6C5A724E, 0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927, + 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A, 0x0C0A67B1, 0x9357E70F, + 0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16, + 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD, + 0x2DB6A8B9, 0x141EA9C8, 0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD, + 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34, 0x8B432976, 0xCB23C6DC, + 0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120, + 0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3, + 0x0D8652EC, 0x77C1E3D0, 0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422, + 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF, 0x87494EC7, 0xD938D1C1, + 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4, + 0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8, + 0x2E39F75E, 0x82C3AFF5, 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3, + 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B, 0xCD267809, 0x6E5918F4, + 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6, + 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331, + 0xC6A59430, 0x35A266C0, 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815, + 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F, 0x764DD68D, 0x43EFB04D, + 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F, + 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252, + 0xE9105633, 0x6DD64713, 0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89, + 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C, 0x9CD2DF59, 0x55F2733F, + 0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86, + 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C, + 0x283C498B, 0xFF0D9541, 0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190, + 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742 +}; + +static unsigned +mul2(unsigned x) +{ + x <<= 1; + return x ^ ((unsigned)(-(int)(x >> 8)) & 0x11B); +} + +static unsigned +mul9(unsigned x) +{ + return x ^ mul2(mul2(mul2(x))); +} + +static unsigned +mulb(unsigned x) +{ + unsigned x2; + + x2 = mul2(x); + return x ^ x2 ^ mul2(mul2(x2)); +} + +static unsigned +muld(unsigned x) +{ + unsigned x4; + + x4 = mul2(mul2(x)); + return x ^ x4 ^ mul2(x4); +} + +static unsigned +mule(unsigned x) +{ + unsigned x2, x4; + + x2 = mul2(x); + x4 = mul2(x2); + return x2 ^ x4 ^ mul2(x4); +} + +/* see inner.h */ +unsigned +br_aes_big_keysched_inv(uint32_t *skey, const void *key, size_t key_len) +{ + unsigned num_rounds; + int i, m; + + /* + * Sub-keys for decryption are distinct from encryption sub-keys + * in that InvMixColumns() is already applied for the inner + * rounds. + */ + num_rounds = br_aes_keysched(skey, key, key_len); + m = (int)(num_rounds << 2); + for (i = 4; i < m; i ++) { + uint32_t p; + unsigned p0, p1, p2, p3; + uint32_t q0, q1, q2, q3; + + p = skey[i]; + p0 = p >> 24; + p1 = (p >> 16) & 0xFF; + p2 = (p >> 8) & 0xFF; + p3 = p & 0xFF; + q0 = mule(p0) ^ mulb(p1) ^ muld(p2) ^ mul9(p3); + q1 = mul9(p0) ^ mule(p1) ^ mulb(p2) ^ muld(p3); + q2 = muld(p0) ^ mul9(p1) ^ mule(p2) ^ mulb(p3); + q3 = mulb(p0) ^ muld(p1) ^ mul9(p2) ^ mule(p3); + skey[i] = (q0 << 24) | (q1 << 16) | (q2 << 8) | q3; + } + return num_rounds; +} + +static __inline uint32_t +rotr(uint32_t x, int n) +{ + return (x << (32 - n)) | (x >> n); +} + +#define iSboxExt0(x) (iSsm0[x]) +#define iSboxExt1(x) (rotr(iSsm0[x], 8)) +#define iSboxExt2(x) (rotr(iSsm0[x], 16)) +#define iSboxExt3(x) (rotr(iSsm0[x], 24)) + +/* see bearssl.h */ +void +br_aes_big_decrypt(unsigned num_rounds, const uint32_t *skey, void *data) +{ + unsigned char *buf; + uint32_t s0, s1, s2, s3; + uint32_t t0, t1, t2, t3; + unsigned u; + + buf = data; + s0 = br_dec32be(buf); + s1 = br_dec32be(buf + 4); + s2 = br_dec32be(buf + 8); + s3 = br_dec32be(buf + 12); + s0 ^= skey[(num_rounds << 2) + 0]; + s1 ^= skey[(num_rounds << 2) + 1]; + s2 ^= skey[(num_rounds << 2) + 2]; + s3 ^= skey[(num_rounds << 2) + 3]; + for (u = num_rounds - 1; u > 0; u --) { + uint32_t v0 = iSboxExt0(s0 >> 24) + ^ iSboxExt1((s3 >> 16) & 0xFF) + ^ iSboxExt2((s2 >> 8) & 0xFF) + ^ iSboxExt3(s1 & 0xFF); + uint32_t v1 = iSboxExt0(s1 >> 24) + ^ iSboxExt1((s0 >> 16) & 0xFF) + ^ iSboxExt2((s3 >> 8) & 0xFF) + ^ iSboxExt3(s2 & 0xFF); + uint32_t v2 = iSboxExt0(s2 >> 24) + ^ iSboxExt1((s1 >> 16) & 0xFF) + ^ iSboxExt2((s0 >> 8) & 0xFF) + ^ iSboxExt3(s3 & 0xFF); + uint32_t v3 = iSboxExt0(s3 >> 24) + ^ iSboxExt1((s2 >> 16) & 0xFF) + ^ iSboxExt2((s1 >> 8) & 0xFF) + ^ iSboxExt3(s0 & 0xFF); + s0 = v0; + s1 = v1; + s2 = v2; + s3 = v3; + s0 ^= skey[u << 2]; + s1 ^= skey[(u << 2) + 1]; + s2 ^= skey[(u << 2) + 2]; + s3 ^= skey[(u << 2) + 3]; + } + t0 = ((uint32_t)iS[s0 >> 24] << 24) + | ((uint32_t)iS[(s3 >> 16) & 0xFF] << 16) + | ((uint32_t)iS[(s2 >> 8) & 0xFF] << 8) + | (uint32_t)iS[s1 & 0xFF]; + t1 = ((uint32_t)iS[s1 >> 24] << 24) + | ((uint32_t)iS[(s0 >> 16) & 0xFF] << 16) + | ((uint32_t)iS[(s3 >> 8) & 0xFF] << 8) + | (uint32_t)iS[s2 & 0xFF]; + t2 = ((uint32_t)iS[s2 >> 24] << 24) + | ((uint32_t)iS[(s1 >> 16) & 0xFF] << 16) + | ((uint32_t)iS[(s0 >> 8) & 0xFF] << 8) + | (uint32_t)iS[s3 & 0xFF]; + t3 = ((uint32_t)iS[s3 >> 24] << 24) + | ((uint32_t)iS[(s2 >> 16) & 0xFF] << 16) + | ((uint32_t)iS[(s1 >> 8) & 0xFF] << 8) + | (uint32_t)iS[s0 & 0xFF]; + s0 = t0 ^ skey[0]; + s1 = t1 ^ skey[1]; + s2 = t2 ^ skey[2]; + s3 = t3 ^ skey[3]; + br_enc32be(buf, s0); + br_enc32be(buf + 4, s1); + br_enc32be(buf + 8, s2); + br_enc32be(buf + 12, s3); +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_big_enc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_big_enc.c new file mode 100644 index 0000000..f506fa8 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_big_enc.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define S br_aes_S + +static const uint32_t Ssm0[] = { + 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, + 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, + 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D, + 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B, + 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, + 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, + 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C, 0x51A5A5F4, + 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F, + 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, + 0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, + 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E, + 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB, + 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, + 0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, + 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46, + 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A, + 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, + 0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, + 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE, + 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504, + 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A, + 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, + 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2, + 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395, + 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, + 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, + 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256, + 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4, + 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, + 0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, + 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA, + 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818, + 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, + 0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, + 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42, + 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12, + 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, + 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, + 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22, + 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A, + 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631, + 0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, + 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A +}; + +static __inline uint32_t +rotr(uint32_t x, int n) +{ + return (x << (32 - n)) | (x >> n); +} + +#define SboxExt0(x) (Ssm0[x]) +#define SboxExt1(x) (rotr(Ssm0[x], 8)) +#define SboxExt2(x) (rotr(Ssm0[x], 16)) +#define SboxExt3(x) (rotr(Ssm0[x], 24)) + + +/* see bearssl.h */ +void +br_aes_big_encrypt(unsigned num_rounds, const uint32_t *skey, void *data) +{ + unsigned char *buf; + uint32_t s0, s1, s2, s3; + uint32_t t0, t1, t2, t3; + unsigned u; + + buf = data; + s0 = br_dec32be(buf); + s1 = br_dec32be(buf + 4); + s2 = br_dec32be(buf + 8); + s3 = br_dec32be(buf + 12); + s0 ^= skey[0]; + s1 ^= skey[1]; + s2 ^= skey[2]; + s3 ^= skey[3]; + for (u = 1; u < num_rounds; u ++) { + uint32_t v0, v1, v2, v3; + + v0 = SboxExt0(s0 >> 24) + ^ SboxExt1((s1 >> 16) & 0xFF) + ^ SboxExt2((s2 >> 8) & 0xFF) + ^ SboxExt3(s3 & 0xFF); + v1 = SboxExt0(s1 >> 24) + ^ SboxExt1((s2 >> 16) & 0xFF) + ^ SboxExt2((s3 >> 8) & 0xFF) + ^ SboxExt3(s0 & 0xFF); + v2 = SboxExt0(s2 >> 24) + ^ SboxExt1((s3 >> 16) & 0xFF) + ^ SboxExt2((s0 >> 8) & 0xFF) + ^ SboxExt3(s1 & 0xFF); + v3 = SboxExt0(s3 >> 24) + ^ SboxExt1((s0 >> 16) & 0xFF) + ^ SboxExt2((s1 >> 8) & 0xFF) + ^ SboxExt3(s2 & 0xFF); + s0 = v0; + s1 = v1; + s2 = v2; + s3 = v3; + s0 ^= skey[u << 2]; + s1 ^= skey[(u << 2) + 1]; + s2 ^= skey[(u << 2) + 2]; + s3 ^= skey[(u << 2) + 3]; + } + t0 = ((uint32_t)S[s0 >> 24] << 24) + | ((uint32_t)S[(s1 >> 16) & 0xFF] << 16) + | ((uint32_t)S[(s2 >> 8) & 0xFF] << 8) + | (uint32_t)S[s3 & 0xFF]; + t1 = ((uint32_t)S[s1 >> 24] << 24) + | ((uint32_t)S[(s2 >> 16) & 0xFF] << 16) + | ((uint32_t)S[(s3 >> 8) & 0xFF] << 8) + | (uint32_t)S[s0 & 0xFF]; + t2 = ((uint32_t)S[s2 >> 24] << 24) + | ((uint32_t)S[(s3 >> 16) & 0xFF] << 16) + | ((uint32_t)S[(s0 >> 8) & 0xFF] << 8) + | (uint32_t)S[s1 & 0xFF]; + t3 = ((uint32_t)S[s3 >> 24] << 24) + | ((uint32_t)S[(s0 >> 16) & 0xFF] << 16) + | ((uint32_t)S[(s1 >> 8) & 0xFF] << 8) + | (uint32_t)S[s2 & 0xFF]; + s0 = t0 ^ skey[num_rounds << 2]; + s1 = t1 ^ skey[(num_rounds << 2) + 1]; + s2 = t2 ^ skey[(num_rounds << 2) + 2]; + s3 = t3 ^ skey[(num_rounds << 2) + 3]; + br_enc32be(buf, s0); + br_enc32be(buf + 4, s1); + br_enc32be(buf + 8, s2); + br_enc32be(buf + 12, s3); +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_common.c b/BearSSL-OG/libbearssl/src/symcipher/aes_common.c new file mode 100644 index 0000000..72c64fb --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_common.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 const uint32_t Rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, + 0x40000000, 0x80000000, 0x1B000000, 0x36000000 +}; + +#define S br_aes_S + +/* see inner.h */ +const unsigned char br_aes_S[] = { + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, + 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, + 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, + 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, + 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, + 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, + 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, + 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, + 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, + 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, + 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, + 0xB0, 0x54, 0xBB, 0x16 +}; + +static uint32_t +SubWord(uint32_t x) +{ + return ((uint32_t)S[x >> 24] << 24) + | ((uint32_t)S[(x >> 16) & 0xFF] << 16) + | ((uint32_t)S[(x >> 8) & 0xFF] << 8) + | (uint32_t)S[x & 0xFF]; +} + +/* see inner.h */ +unsigned +br_aes_keysched(uint32_t *skey, const void *key, size_t key_len) +{ + unsigned num_rounds; + int i, j, k, nk, nkf; + + switch (key_len) { + case 16: + num_rounds = 10; + break; + case 24: + num_rounds = 12; + break; + case 32: + num_rounds = 14; + break; + default: + /* abort(); */ + return 0; + } + nk = (int)(key_len >> 2); + nkf = (int)((num_rounds + 1) << 2); + for (i = 0; i < nk; i ++) { + skey[i] = br_dec32be((const unsigned char *)key + (i << 2)); + } + for (i = nk, j = 0, k = 0; i < nkf; i ++) { + uint32_t tmp; + + tmp = skey[i - 1]; + if (j == 0) { + tmp = (tmp << 8) | (tmp >> 24); + tmp = SubWord(tmp) ^ Rcon[k]; + } else if (nk > 6 && j == 4) { + tmp = SubWord(tmp); + } + skey[i] = skey[i - nk] ^ tmp; + if (++ j == nk) { + j = 0; + k ++; + } + } + return num_rounds; +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct.c new file mode 100644 index 0000000..66776d9 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_aes_ct_bitslice_Sbox(uint32_t *q) +{ + /* + * This S-box implementation is a straightforward translation of + * the circuit described by Boyar and Peralta in "A new + * combinational logic minimization technique with applications + * to cryptology" (https://eprint.iacr.org/2009/191.pdf). + * + * Note that variables x* (input) and s* (output) are numbered + * in "reverse" order (x0 is the high bit, x7 is the low bit). + */ + + uint32_t x0, x1, x2, x3, x4, x5, x6, x7; + uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; + uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + uint32_t y20, y21; + uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; + uint32_t z10, z11, z12, z13, z14, z15, z16, z17; + uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; + uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; + uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; + uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; + uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; + uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; + uint32_t t60, t61, t62, t63, t64, t65, t66, t67; + uint32_t s0, s1, s2, s3, s4, s5, s6, s7; + + x0 = q[7]; + x1 = q[6]; + x2 = q[5]; + x3 = q[4]; + x4 = q[3]; + x5 = q[2]; + x6 = q[1]; + x7 = q[0]; + + /* + * Top linear transformation. + */ + y14 = x3 ^ x5; + y13 = x0 ^ x6; + y9 = x0 ^ x3; + y8 = x0 ^ x5; + t0 = x1 ^ x2; + y1 = t0 ^ x7; + y4 = y1 ^ x3; + y12 = y13 ^ y14; + y2 = y1 ^ x0; + y5 = y1 ^ x6; + y3 = y5 ^ y8; + t1 = x4 ^ y12; + y15 = t1 ^ x5; + y20 = t1 ^ x1; + y6 = y15 ^ x7; + y10 = y15 ^ t0; + y11 = y20 ^ y9; + y7 = x7 ^ y11; + y17 = y10 ^ y11; + y19 = y10 ^ y8; + y16 = t0 ^ y11; + y21 = y13 ^ y16; + y18 = x0 ^ y16; + + /* + * Non-linear section. + */ + t2 = y12 & y15; + t3 = y3 & y6; + t4 = t3 ^ t2; + t5 = y4 & x7; + t6 = t5 ^ t2; + t7 = y13 & y16; + t8 = y5 & y1; + t9 = t8 ^ t7; + t10 = y2 & y7; + t11 = t10 ^ t7; + t12 = y9 & y11; + t13 = y14 & y17; + t14 = t13 ^ t12; + t15 = y8 & y10; + t16 = t15 ^ t12; + t17 = t4 ^ t14; + t18 = t6 ^ t16; + t19 = t9 ^ t14; + t20 = t11 ^ t16; + t21 = t17 ^ y20; + t22 = t18 ^ y19; + t23 = t19 ^ y21; + t24 = t20 ^ y18; + + t25 = t21 ^ t22; + t26 = t21 & t23; + t27 = t24 ^ t26; + t28 = t25 & t27; + t29 = t28 ^ t22; + t30 = t23 ^ t24; + t31 = t22 ^ t26; + t32 = t31 & t30; + t33 = t32 ^ t24; + t34 = t23 ^ t33; + t35 = t27 ^ t33; + t36 = t24 & t35; + t37 = t36 ^ t34; + t38 = t27 ^ t36; + t39 = t29 & t38; + t40 = t25 ^ t39; + + t41 = t40 ^ t37; + t42 = t29 ^ t33; + t43 = t29 ^ t40; + t44 = t33 ^ t37; + t45 = t42 ^ t41; + z0 = t44 & y15; + z1 = t37 & y6; + z2 = t33 & x7; + z3 = t43 & y16; + z4 = t40 & y1; + z5 = t29 & y7; + z6 = t42 & y11; + z7 = t45 & y17; + z8 = t41 & y10; + z9 = t44 & y12; + z10 = t37 & y3; + z11 = t33 & y4; + z12 = t43 & y13; + z13 = t40 & y5; + z14 = t29 & y2; + z15 = t42 & y9; + z16 = t45 & y14; + z17 = t41 & y8; + + /* + * Bottom linear transformation. + */ + t46 = z15 ^ z16; + t47 = z10 ^ z11; + t48 = z5 ^ z13; + t49 = z9 ^ z10; + t50 = z2 ^ z12; + t51 = z2 ^ z5; + t52 = z7 ^ z8; + t53 = z0 ^ z3; + t54 = z6 ^ z7; + t55 = z16 ^ z17; + t56 = z12 ^ t48; + t57 = t50 ^ t53; + t58 = z4 ^ t46; + t59 = z3 ^ t54; + t60 = t46 ^ t57; + t61 = z14 ^ t57; + t62 = t52 ^ t58; + t63 = t49 ^ t58; + t64 = z4 ^ t59; + t65 = t61 ^ t62; + t66 = z1 ^ t63; + s0 = t59 ^ t63; + s6 = t56 ^ ~t62; + s7 = t48 ^ ~t60; + t67 = t64 ^ t65; + s3 = t53 ^ t66; + s4 = t51 ^ t66; + s5 = t47 ^ t65; + s1 = t64 ^ ~s3; + s2 = t55 ^ ~t67; + + q[7] = s0; + q[6] = s1; + q[5] = s2; + q[4] = s3; + q[3] = s4; + q[2] = s5; + q[1] = s6; + q[0] = s7; +} + +/* see inner.h */ +void +br_aes_ct_ortho(uint32_t *q) +{ +#define SWAPN(cl, ch, s, x, y) do { \ + uint32_t a, b; \ + a = (x); \ + b = (y); \ + (x) = (a & (uint32_t)cl) | ((b & (uint32_t)cl) << (s)); \ + (y) = ((a & (uint32_t)ch) >> (s)) | (b & (uint32_t)ch); \ + } while (0) + +#define SWAP2(x, y) SWAPN(0x55555555, 0xAAAAAAAA, 1, x, y) +#define SWAP4(x, y) SWAPN(0x33333333, 0xCCCCCCCC, 2, x, y) +#define SWAP8(x, y) SWAPN(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) + + SWAP2(q[0], q[1]); + SWAP2(q[2], q[3]); + SWAP2(q[4], q[5]); + SWAP2(q[6], q[7]); + + SWAP4(q[0], q[2]); + SWAP4(q[1], q[3]); + SWAP4(q[4], q[6]); + SWAP4(q[5], q[7]); + + SWAP8(q[0], q[4]); + SWAP8(q[1], q[5]); + SWAP8(q[2], q[6]); + SWAP8(q[3], q[7]); +} + +static const unsigned char Rcon[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 +}; + +static uint32_t +sub_word(uint32_t x) +{ + uint32_t q[8]; + int i; + + for (i = 0; i < 8; i ++) { + q[i] = x; + } + br_aes_ct_ortho(q); + br_aes_ct_bitslice_Sbox(q); + br_aes_ct_ortho(q); + return q[0]; +} + +/* see inner.h */ +unsigned +br_aes_ct_keysched(uint32_t *comp_skey, const void *key, size_t key_len) +{ + unsigned num_rounds; + int i, j, k, nk, nkf; + uint32_t tmp; + uint32_t skey[120]; + + switch (key_len) { + case 16: + num_rounds = 10; + break; + case 24: + num_rounds = 12; + break; + case 32: + num_rounds = 14; + break; + default: + /* abort(); */ + return 0; + } + nk = (int)(key_len >> 2); + nkf = (int)((num_rounds + 1) << 2); + tmp = 0; + for (i = 0; i < nk; i ++) { + tmp = br_dec32le((const unsigned char *)key + (i << 2)); + skey[(i << 1) + 0] = tmp; + skey[(i << 1) + 1] = tmp; + } + for (i = nk, j = 0, k = 0; i < nkf; i ++) { + if (j == 0) { + tmp = (tmp << 24) | (tmp >> 8); + tmp = sub_word(tmp) ^ Rcon[k]; + } else if (nk > 6 && j == 4) { + tmp = sub_word(tmp); + } + tmp ^= skey[(i - nk) << 1]; + skey[(i << 1) + 0] = tmp; + skey[(i << 1) + 1] = tmp; + if (++ j == nk) { + j = 0; + k ++; + } + } + for (i = 0; i < nkf; i += 4) { + br_aes_ct_ortho(skey + (i << 1)); + } + for (i = 0, j = 0; i < nkf; i ++, j += 2) { + comp_skey[i] = (skey[j + 0] & 0x55555555) + | (skey[j + 1] & 0xAAAAAAAA); + } + return num_rounds; +} + +/* see inner.h */ +void +br_aes_ct_skey_expand(uint32_t *skey, + unsigned num_rounds, const uint32_t *comp_skey) +{ + unsigned u, v, n; + + n = (num_rounds + 1) << 2; + for (u = 0, v = 0; u < n; u ++, v += 2) { + uint32_t x, y; + + x = y = comp_skey[u]; + x &= 0x55555555; + skey[v + 0] = x | (x << 1); + y &= 0xAAAAAAAA; + skey[v + 1] = y | (y >> 1); + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct64.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64.c new file mode 100644 index 0000000..1523811 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_aes_ct64_bitslice_Sbox(uint64_t *q) +{ + /* + * This S-box implementation is a straightforward translation of + * the circuit described by Boyar and Peralta in "A new + * combinational logic minimization technique with applications + * to cryptology" (https://eprint.iacr.org/2009/191.pdf). + * + * Note that variables x* (input) and s* (output) are numbered + * in "reverse" order (x0 is the high bit, x7 is the low bit). + */ + + uint64_t x0, x1, x2, x3, x4, x5, x6, x7; + uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; + uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + uint64_t y20, y21; + uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; + uint64_t z10, z11, z12, z13, z14, z15, z16, z17; + uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; + uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; + uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; + uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; + uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; + uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; + uint64_t t60, t61, t62, t63, t64, t65, t66, t67; + uint64_t s0, s1, s2, s3, s4, s5, s6, s7; + + x0 = q[7]; + x1 = q[6]; + x2 = q[5]; + x3 = q[4]; + x4 = q[3]; + x5 = q[2]; + x6 = q[1]; + x7 = q[0]; + + /* + * Top linear transformation. + */ + y14 = x3 ^ x5; + y13 = x0 ^ x6; + y9 = x0 ^ x3; + y8 = x0 ^ x5; + t0 = x1 ^ x2; + y1 = t0 ^ x7; + y4 = y1 ^ x3; + y12 = y13 ^ y14; + y2 = y1 ^ x0; + y5 = y1 ^ x6; + y3 = y5 ^ y8; + t1 = x4 ^ y12; + y15 = t1 ^ x5; + y20 = t1 ^ x1; + y6 = y15 ^ x7; + y10 = y15 ^ t0; + y11 = y20 ^ y9; + y7 = x7 ^ y11; + y17 = y10 ^ y11; + y19 = y10 ^ y8; + y16 = t0 ^ y11; + y21 = y13 ^ y16; + y18 = x0 ^ y16; + + /* + * Non-linear section. + */ + t2 = y12 & y15; + t3 = y3 & y6; + t4 = t3 ^ t2; + t5 = y4 & x7; + t6 = t5 ^ t2; + t7 = y13 & y16; + t8 = y5 & y1; + t9 = t8 ^ t7; + t10 = y2 & y7; + t11 = t10 ^ t7; + t12 = y9 & y11; + t13 = y14 & y17; + t14 = t13 ^ t12; + t15 = y8 & y10; + t16 = t15 ^ t12; + t17 = t4 ^ t14; + t18 = t6 ^ t16; + t19 = t9 ^ t14; + t20 = t11 ^ t16; + t21 = t17 ^ y20; + t22 = t18 ^ y19; + t23 = t19 ^ y21; + t24 = t20 ^ y18; + + t25 = t21 ^ t22; + t26 = t21 & t23; + t27 = t24 ^ t26; + t28 = t25 & t27; + t29 = t28 ^ t22; + t30 = t23 ^ t24; + t31 = t22 ^ t26; + t32 = t31 & t30; + t33 = t32 ^ t24; + t34 = t23 ^ t33; + t35 = t27 ^ t33; + t36 = t24 & t35; + t37 = t36 ^ t34; + t38 = t27 ^ t36; + t39 = t29 & t38; + t40 = t25 ^ t39; + + t41 = t40 ^ t37; + t42 = t29 ^ t33; + t43 = t29 ^ t40; + t44 = t33 ^ t37; + t45 = t42 ^ t41; + z0 = t44 & y15; + z1 = t37 & y6; + z2 = t33 & x7; + z3 = t43 & y16; + z4 = t40 & y1; + z5 = t29 & y7; + z6 = t42 & y11; + z7 = t45 & y17; + z8 = t41 & y10; + z9 = t44 & y12; + z10 = t37 & y3; + z11 = t33 & y4; + z12 = t43 & y13; + z13 = t40 & y5; + z14 = t29 & y2; + z15 = t42 & y9; + z16 = t45 & y14; + z17 = t41 & y8; + + /* + * Bottom linear transformation. + */ + t46 = z15 ^ z16; + t47 = z10 ^ z11; + t48 = z5 ^ z13; + t49 = z9 ^ z10; + t50 = z2 ^ z12; + t51 = z2 ^ z5; + t52 = z7 ^ z8; + t53 = z0 ^ z3; + t54 = z6 ^ z7; + t55 = z16 ^ z17; + t56 = z12 ^ t48; + t57 = t50 ^ t53; + t58 = z4 ^ t46; + t59 = z3 ^ t54; + t60 = t46 ^ t57; + t61 = z14 ^ t57; + t62 = t52 ^ t58; + t63 = t49 ^ t58; + t64 = z4 ^ t59; + t65 = t61 ^ t62; + t66 = z1 ^ t63; + s0 = t59 ^ t63; + s6 = t56 ^ ~t62; + s7 = t48 ^ ~t60; + t67 = t64 ^ t65; + s3 = t53 ^ t66; + s4 = t51 ^ t66; + s5 = t47 ^ t65; + s1 = t64 ^ ~s3; + s2 = t55 ^ ~t67; + + q[7] = s0; + q[6] = s1; + q[5] = s2; + q[4] = s3; + q[3] = s4; + q[2] = s5; + q[1] = s6; + q[0] = s7; +} + +/* see inner.h */ +void +br_aes_ct64_ortho(uint64_t *q) +{ +#define SWAPN(cl, ch, s, x, y) do { \ + uint64_t a, b; \ + a = (x); \ + b = (y); \ + (x) = (a & (uint64_t)cl) | ((b & (uint64_t)cl) << (s)); \ + (y) = ((a & (uint64_t)ch) >> (s)) | (b & (uint64_t)ch); \ + } while (0) + +#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) +#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) +#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) + + SWAP2(q[0], q[1]); + SWAP2(q[2], q[3]); + SWAP2(q[4], q[5]); + SWAP2(q[6], q[7]); + + SWAP4(q[0], q[2]); + SWAP4(q[1], q[3]); + SWAP4(q[4], q[6]); + SWAP4(q[5], q[7]); + + SWAP8(q[0], q[4]); + SWAP8(q[1], q[5]); + SWAP8(q[2], q[6]); + SWAP8(q[3], q[7]); +} + +/* see inner.h */ +void +br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) +{ + uint64_t x0, x1, x2, x3; + + x0 = w[0]; + x1 = w[1]; + x2 = w[2]; + x3 = w[3]; + x0 |= (x0 << 16); + x1 |= (x1 << 16); + x2 |= (x2 << 16); + x3 |= (x3 << 16); + x0 &= (uint64_t)0x0000FFFF0000FFFF; + x1 &= (uint64_t)0x0000FFFF0000FFFF; + x2 &= (uint64_t)0x0000FFFF0000FFFF; + x3 &= (uint64_t)0x0000FFFF0000FFFF; + x0 |= (x0 << 8); + x1 |= (x1 << 8); + x2 |= (x2 << 8); + x3 |= (x3 << 8); + x0 &= (uint64_t)0x00FF00FF00FF00FF; + x1 &= (uint64_t)0x00FF00FF00FF00FF; + x2 &= (uint64_t)0x00FF00FF00FF00FF; + x3 &= (uint64_t)0x00FF00FF00FF00FF; + *q0 = x0 | (x2 << 8); + *q1 = x1 | (x3 << 8); +} + +/* see inner.h */ +void +br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) +{ + uint64_t x0, x1, x2, x3; + + x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; + x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; + x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; + x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; + x0 |= (x0 >> 8); + x1 |= (x1 >> 8); + x2 |= (x2 >> 8); + x3 |= (x3 >> 8); + x0 &= (uint64_t)0x0000FFFF0000FFFF; + x1 &= (uint64_t)0x0000FFFF0000FFFF; + x2 &= (uint64_t)0x0000FFFF0000FFFF; + x3 &= (uint64_t)0x0000FFFF0000FFFF; + w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); + w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); + w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); + w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); +} + +static const unsigned char Rcon[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 +}; + +static uint32_t +sub_word(uint32_t x) +{ + uint64_t q[8]; + + memset(q, 0, sizeof q); + q[0] = x; + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_Sbox(q); + br_aes_ct64_ortho(q); + return (uint32_t)q[0]; +} + +/* see inner.h */ +unsigned +br_aes_ct64_keysched(uint64_t *comp_skey, const void *key, size_t key_len) +{ + unsigned num_rounds; + int i, j, k, nk, nkf; + uint32_t tmp; + uint32_t skey[60]; + + switch (key_len) { + case 16: + num_rounds = 10; + break; + case 24: + num_rounds = 12; + break; + case 32: + num_rounds = 14; + break; + default: + /* abort(); */ + return 0; + } + nk = (int)(key_len >> 2); + nkf = (int)((num_rounds + 1) << 2); + br_range_dec32le(skey, (key_len >> 2), key); + tmp = skey[(key_len >> 2) - 1]; + for (i = nk, j = 0, k = 0; i < nkf; i ++) { + if (j == 0) { + tmp = (tmp << 24) | (tmp >> 8); + tmp = sub_word(tmp) ^ Rcon[k]; + } else if (nk > 6 && j == 4) { + tmp = sub_word(tmp); + } + tmp ^= skey[i - nk]; + skey[i] = tmp; + if (++ j == nk) { + j = 0; + k ++; + } + } + + for (i = 0, j = 0; i < nkf; i += 4, j += 2) { + uint64_t q[8]; + + br_aes_ct64_interleave_in(&q[0], &q[4], skey + i); + q[1] = q[0]; + q[2] = q[0]; + q[3] = q[0]; + q[5] = q[4]; + q[6] = q[4]; + q[7] = q[4]; + br_aes_ct64_ortho(q); + comp_skey[j + 0] = + (q[0] & (uint64_t)0x1111111111111111) + | (q[1] & (uint64_t)0x2222222222222222) + | (q[2] & (uint64_t)0x4444444444444444) + | (q[3] & (uint64_t)0x8888888888888888); + comp_skey[j + 1] = + (q[4] & (uint64_t)0x1111111111111111) + | (q[5] & (uint64_t)0x2222222222222222) + | (q[6] & (uint64_t)0x4444444444444444) + | (q[7] & (uint64_t)0x8888888888888888); + } + return num_rounds; +} + +/* see inner.h */ +void +br_aes_ct64_skey_expand(uint64_t *skey, + unsigned num_rounds, const uint64_t *comp_skey) +{ + unsigned u, v, n; + + n = (num_rounds + 1) << 1; + for (u = 0, v = 0; u < n; u ++, v += 4) { + uint64_t x0, x1, x2, x3; + + x0 = x1 = x2 = x3 = comp_skey[u]; + x0 &= (uint64_t)0x1111111111111111; + x1 &= (uint64_t)0x2222222222222222; + x2 &= (uint64_t)0x4444444444444444; + x3 &= (uint64_t)0x8888888888888888; + x1 >>= 1; + x2 >>= 2; + x3 >>= 3; + skey[v + 0] = (x0 << 4) - x0; + skey[v + 1] = (x1 << 4) - x1; + skey[v + 2] = (x2 << 4) - x2; + skey[v + 3] = (x3 << 4) - x3; + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_cbcdec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_cbcdec.c new file mode 100644 index 0000000..5a7360b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_cbcdec.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_ct64_cbcdec_vtable; + ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf; + uint64_t sk_exp[120]; + uint32_t ivw[4]; + + br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + br_range_dec32le(ivw, 4, iv); + buf = data; + while (len > 0) { + uint64_t q[8]; + uint32_t w1[16], w2[16]; + int i; + + if (len >= 64) { + br_range_dec32le(w1, 16, buf); + } else { + br_range_dec32le(w1, len >> 2, buf); + } + for (i = 0; i < 4; i ++) { + br_aes_ct64_interleave_in( + &q[i], &q[i + 4], w1 + (i << 2)); + } + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_decrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct64_ortho(q); + for (i = 0; i < 4; i ++) { + br_aes_ct64_interleave_out( + w2 + (i << 2), q[i], q[i + 4]); + } + for (i = 0; i < 4; i ++) { + w2[i] ^= ivw[i]; + } + if (len >= 64) { + for (i = 4; i < 16; i ++) { + w2[i] ^= w1[i - 4]; + } + memcpy(ivw, w1 + 12, sizeof ivw); + br_range_enc32le(buf, w2, 16); + } else { + int j; + + j = (int)(len >> 2); + for (i = 4; i < j; i ++) { + w2[i] ^= w1[i - 4]; + } + memcpy(ivw, w1 + j - 4, sizeof ivw); + br_range_enc32le(buf, w2, j); + break; + } + buf += 64; + len -= 64; + } + br_range_enc32le(iv, ivw, 4); +} + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable = { + sizeof(br_aes_ct64_cbcdec_keys), + 16, + 4, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_aes_ct64_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_aes_ct64_cbcdec_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_cbcenc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_cbcenc.c new file mode 100644 index 0000000..6cb9dec --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_cbcenc.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_ct64_cbcenc_vtable; + ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf; + uint64_t sk_exp[120]; + uint32_t ivw[4]; + + br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + br_range_dec32le(ivw, 4, iv); + buf = data; + while (len > 0) { + uint32_t w[4]; + uint64_t q[8]; + + w[0] = ivw[0] ^ br_dec32le(buf); + w[1] = ivw[1] ^ br_dec32le(buf + 4); + w[2] = ivw[2] ^ br_dec32le(buf + 8); + w[3] = ivw[3] ^ br_dec32le(buf + 12); + br_aes_ct64_interleave_in(&q[0], &q[4], w); + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct64_ortho(q); + br_aes_ct64_interleave_out(w, q[0], q[4]); + memcpy(ivw, w, sizeof w); + br_enc32le(buf, w[0]); + br_enc32le(buf + 4, w[1]); + br_enc32le(buf + 8, w[2]); + br_enc32le(buf + 12, w[3]); + buf += 16; + len -= 16; + } + br_range_enc32le(iv, ivw, 4); +} + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable = { + sizeof(br_aes_ct64_cbcenc_keys), + 16, + 4, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_aes_ct64_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_aes_ct64_cbcenc_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_ctr.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_ctr.c new file mode 100644 index 0000000..1275873 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_ctr.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_ct64_ctr_vtable; + ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); +} + +static void +xorbuf(void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + *d ++ ^= *s ++; + } +} + +/* see bearssl_block.h */ +uint32_t +br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + uint32_t ivw[16]; + uint64_t sk_exp[120]; + + br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + br_range_dec32le(ivw, 3, iv); + memcpy(ivw + 4, ivw, 3 * sizeof(uint32_t)); + memcpy(ivw + 8, ivw, 3 * sizeof(uint32_t)); + memcpy(ivw + 12, ivw, 3 * sizeof(uint32_t)); + buf = data; + while (len > 0) { + uint64_t q[8]; + uint32_t w[16]; + unsigned char tmp[64]; + int i; + + /* + * TODO: see if we can save on the first br_aes_ct64_ortho() + * call, since iv0/iv1/iv2 are constant for the whole run. + */ + memcpy(w, ivw, sizeof ivw); + w[3] = br_swap32(cc); + w[7] = br_swap32(cc + 1); + w[11] = br_swap32(cc + 2); + w[15] = br_swap32(cc + 3); + for (i = 0; i < 4; i ++) { + br_aes_ct64_interleave_in( + &q[i], &q[i + 4], w + (i << 2)); + } + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct64_ortho(q); + for (i = 0; i < 4; i ++) { + br_aes_ct64_interleave_out( + w + (i << 2), q[i], q[i + 4]); + } + br_range_enc32le(tmp, w, 16); + if (len <= 64) { + xorbuf(buf, tmp, len); + cc += (uint32_t)len >> 4; + break; + } + xorbuf(buf, tmp, 64); + buf += 64; + len -= 64; + cc += 4; + } + return cc; +} + +/* see bearssl_block.h */ +const br_block_ctr_class br_aes_ct64_ctr_vtable = { + sizeof(br_aes_ct64_ctr_keys), + 16, + 4, + (void (*)(const br_block_ctr_class **, const void *, size_t)) + &br_aes_ct64_ctr_init, + (uint32_t (*)(const br_block_ctr_class *const *, + const void *, uint32_t, void *, size_t)) + &br_aes_ct64_ctr_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_ctrcbc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_ctrcbc.c new file mode 100644 index 0000000..21bb8ef --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_ctrcbc.c @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_ct64_ctrcbc_vtable; + ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); +} + +static void +xorbuf(void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + *d ++ ^= *s ++; + } +} + +/* see bearssl_block.h */ +void +br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len) +{ + unsigned char *buf; + unsigned char *ivbuf; + uint32_t iv0, iv1, iv2, iv3; + uint64_t sk_exp[120]; + + br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + + /* + * We keep the counter as four 32-bit values, with big-endian + * convention, because that's what is expected for purposes of + * incrementing the counter value. + */ + ivbuf = ctr; + iv0 = br_dec32be(ivbuf + 0); + iv1 = br_dec32be(ivbuf + 4); + iv2 = br_dec32be(ivbuf + 8); + iv3 = br_dec32be(ivbuf + 12); + + buf = data; + while (len > 0) { + uint64_t q[8]; + uint32_t w[16]; + unsigned char tmp[64]; + int i, j; + + /* + * The bitslice implementation expects values in + * little-endian convention, so we have to byteswap them. + */ + j = (len >= 64) ? 16 : (int)(len >> 2); + for (i = 0; i < j; i += 4) { + uint32_t carry; + + w[i + 0] = br_swap32(iv0); + w[i + 1] = br_swap32(iv1); + w[i + 2] = br_swap32(iv2); + w[i + 3] = br_swap32(iv3); + iv3 ++; + carry = ~(iv3 | -iv3) >> 31; + iv2 += carry; + carry &= -(~(iv2 | -iv2) >> 31); + iv1 += carry; + carry &= -(~(iv1 | -iv1) >> 31); + iv0 += carry; + } + memset(w + i, 0, (16 - i) * sizeof(uint32_t)); + + for (i = 0; i < 4; i ++) { + br_aes_ct64_interleave_in( + &q[i], &q[i + 4], w + (i << 2)); + } + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct64_ortho(q); + for (i = 0; i < 4; i ++) { + br_aes_ct64_interleave_out( + w + (i << 2), q[i], q[i + 4]); + } + + br_range_enc32le(tmp, w, 16); + if (len <= 64) { + xorbuf(buf, tmp, len); + break; + } + xorbuf(buf, tmp, 64); + buf += 64; + len -= 64; + } + br_enc32be(ivbuf + 0, iv0); + br_enc32be(ivbuf + 4, iv1); + br_enc32be(ivbuf + 8, iv2); + br_enc32be(ivbuf + 12, iv3); +} + +/* see bearssl_block.h */ +void +br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len) +{ + const unsigned char *buf; + uint32_t cm0, cm1, cm2, cm3; + uint64_t q[8]; + uint64_t sk_exp[120]; + + br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + + cm0 = br_dec32le((unsigned char *)cbcmac + 0); + cm1 = br_dec32le((unsigned char *)cbcmac + 4); + cm2 = br_dec32le((unsigned char *)cbcmac + 8); + cm3 = br_dec32le((unsigned char *)cbcmac + 12); + + buf = data; + memset(q, 0, sizeof q); + while (len > 0) { + uint32_t w[4]; + + w[0] = cm0 ^ br_dec32le(buf + 0); + w[1] = cm1 ^ br_dec32le(buf + 4); + w[2] = cm2 ^ br_dec32le(buf + 8); + w[3] = cm3 ^ br_dec32le(buf + 12); + + br_aes_ct64_interleave_in(&q[0], &q[4], w); + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct64_ortho(q); + br_aes_ct64_interleave_out(w, q[0], q[4]); + + cm0 = w[0]; + cm1 = w[1]; + cm2 = w[2]; + cm3 = w[3]; + buf += 16; + len -= 16; + } + + br_enc32le((unsigned char *)cbcmac + 0, cm0); + br_enc32le((unsigned char *)cbcmac + 4, cm1); + br_enc32le((unsigned char *)cbcmac + 8, cm2); + br_enc32le((unsigned char *)cbcmac + 12, cm3); +} + +/* see bearssl_block.h */ +void +br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + /* + * When encrypting, the CBC-MAC processing must be lagging by + * one block, since it operates on the encrypted values, so + * it must wait for that encryption to complete. + */ + + unsigned char *buf; + unsigned char *ivbuf; + uint32_t iv0, iv1, iv2, iv3; + uint32_t cm0, cm1, cm2, cm3; + uint64_t sk_exp[120]; + uint64_t q[8]; + int first_iter; + + br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + + /* + * We keep the counter as four 32-bit values, with big-endian + * convention, because that's what is expected for purposes of + * incrementing the counter value. + */ + ivbuf = ctr; + iv0 = br_dec32be(ivbuf + 0); + iv1 = br_dec32be(ivbuf + 4); + iv2 = br_dec32be(ivbuf + 8); + iv3 = br_dec32be(ivbuf + 12); + + /* + * The current CBC-MAC value is kept in little-endian convention. + */ + cm0 = br_dec32le((unsigned char *)cbcmac + 0); + cm1 = br_dec32le((unsigned char *)cbcmac + 4); + cm2 = br_dec32le((unsigned char *)cbcmac + 8); + cm3 = br_dec32le((unsigned char *)cbcmac + 12); + + buf = data; + first_iter = 1; + memset(q, 0, sizeof q); + while (len > 0) { + uint32_t w[8], carry; + + /* + * The bitslice implementation expects values in + * little-endian convention, so we have to byteswap them. + */ + w[0] = br_swap32(iv0); + w[1] = br_swap32(iv1); + w[2] = br_swap32(iv2); + w[3] = br_swap32(iv3); + iv3 ++; + carry = ~(iv3 | -iv3) >> 31; + iv2 += carry; + carry &= -(~(iv2 | -iv2) >> 31); + iv1 += carry; + carry &= -(~(iv1 | -iv1) >> 31); + iv0 += carry; + + /* + * The block for CBC-MAC. + */ + w[4] = cm0; + w[5] = cm1; + w[6] = cm2; + w[7] = cm3; + + br_aes_ct64_interleave_in(&q[0], &q[4], w); + br_aes_ct64_interleave_in(&q[1], &q[5], w + 4); + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct64_ortho(q); + br_aes_ct64_interleave_out(w, q[0], q[4]); + br_aes_ct64_interleave_out(w + 4, q[1], q[5]); + + /* + * We do the XOR with the plaintext in 32-bit registers, + * so that the value are available for CBC-MAC processing + * as well. + */ + w[0] ^= br_dec32le(buf + 0); + w[1] ^= br_dec32le(buf + 4); + w[2] ^= br_dec32le(buf + 8); + w[3] ^= br_dec32le(buf + 12); + br_enc32le(buf + 0, w[0]); + br_enc32le(buf + 4, w[1]); + br_enc32le(buf + 8, w[2]); + br_enc32le(buf + 12, w[3]); + + buf += 16; + len -= 16; + + /* + * We set the cm* values to the block to encrypt in the + * next iteration. + */ + if (first_iter) { + first_iter = 0; + cm0 ^= w[0]; + cm1 ^= w[1]; + cm2 ^= w[2]; + cm3 ^= w[3]; + } else { + cm0 = w[0] ^ w[4]; + cm1 = w[1] ^ w[5]; + cm2 = w[2] ^ w[6]; + cm3 = w[3] ^ w[7]; + } + + /* + * If this was the last iteration, then compute the + * extra block encryption to complete CBC-MAC. + */ + if (len == 0) { + w[0] = cm0; + w[1] = cm1; + w[2] = cm2; + w[3] = cm3; + br_aes_ct64_interleave_in(&q[0], &q[4], w); + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_encrypt( + ctx->num_rounds, sk_exp, q); + br_aes_ct64_ortho(q); + br_aes_ct64_interleave_out(w, q[0], q[4]); + cm0 = w[0]; + cm1 = w[1]; + cm2 = w[2]; + cm3 = w[3]; + break; + } + } + + br_enc32be(ivbuf + 0, iv0); + br_enc32be(ivbuf + 4, iv1); + br_enc32be(ivbuf + 8, iv2); + br_enc32be(ivbuf + 12, iv3); + br_enc32le((unsigned char *)cbcmac + 0, cm0); + br_enc32le((unsigned char *)cbcmac + 4, cm1); + br_enc32le((unsigned char *)cbcmac + 8, cm2); + br_enc32le((unsigned char *)cbcmac + 12, cm3); +} + +/* see bearssl_block.h */ +void +br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + unsigned char *buf; + unsigned char *ivbuf; + uint32_t iv0, iv1, iv2, iv3; + uint32_t cm0, cm1, cm2, cm3; + uint64_t sk_exp[120]; + uint64_t q[8]; + + br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + + /* + * We keep the counter as four 32-bit values, with big-endian + * convention, because that's what is expected for purposes of + * incrementing the counter value. + */ + ivbuf = ctr; + iv0 = br_dec32be(ivbuf + 0); + iv1 = br_dec32be(ivbuf + 4); + iv2 = br_dec32be(ivbuf + 8); + iv3 = br_dec32be(ivbuf + 12); + + /* + * The current CBC-MAC value is kept in little-endian convention. + */ + cm0 = br_dec32le((unsigned char *)cbcmac + 0); + cm1 = br_dec32le((unsigned char *)cbcmac + 4); + cm2 = br_dec32le((unsigned char *)cbcmac + 8); + cm3 = br_dec32le((unsigned char *)cbcmac + 12); + + buf = data; + memset(q, 0, sizeof q); + while (len > 0) { + uint32_t w[8], carry; + unsigned char tmp[16]; + + /* + * The bitslice implementation expects values in + * little-endian convention, so we have to byteswap them. + */ + w[0] = br_swap32(iv0); + w[1] = br_swap32(iv1); + w[2] = br_swap32(iv2); + w[3] = br_swap32(iv3); + iv3 ++; + carry = ~(iv3 | -iv3) >> 31; + iv2 += carry; + carry &= -(~(iv2 | -iv2) >> 31); + iv1 += carry; + carry &= -(~(iv1 | -iv1) >> 31); + iv0 += carry; + + /* + * The block for CBC-MAC. + */ + w[4] = cm0 ^ br_dec32le(buf + 0); + w[5] = cm1 ^ br_dec32le(buf + 4); + w[6] = cm2 ^ br_dec32le(buf + 8); + w[7] = cm3 ^ br_dec32le(buf + 12); + + br_aes_ct64_interleave_in(&q[0], &q[4], w); + br_aes_ct64_interleave_in(&q[1], &q[5], w + 4); + br_aes_ct64_ortho(q); + br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct64_ortho(q); + br_aes_ct64_interleave_out(w, q[0], q[4]); + br_aes_ct64_interleave_out(w + 4, q[1], q[5]); + + br_enc32le(tmp + 0, w[0]); + br_enc32le(tmp + 4, w[1]); + br_enc32le(tmp + 8, w[2]); + br_enc32le(tmp + 12, w[3]); + xorbuf(buf, tmp, 16); + cm0 = w[4]; + cm1 = w[5]; + cm2 = w[6]; + cm3 = w[7]; + buf += 16; + len -= 16; + } + + br_enc32be(ivbuf + 0, iv0); + br_enc32be(ivbuf + 4, iv1); + br_enc32be(ivbuf + 8, iv2); + br_enc32be(ivbuf + 12, iv3); + br_enc32le((unsigned char *)cbcmac + 0, cm0); + br_enc32le((unsigned char *)cbcmac + 4, cm1); + br_enc32le((unsigned char *)cbcmac + 8, cm2); + br_enc32le((unsigned char *)cbcmac + 12, cm3); +} + +/* see bearssl_block.h */ +const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable = { + sizeof(br_aes_ct64_ctrcbc_keys), + 16, + 4, + (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) + &br_aes_ct64_ctrcbc_init, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_ct64_ctrcbc_encrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_ct64_ctrcbc_decrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, size_t)) + &br_aes_ct64_ctrcbc_ctr, + (void (*)(const br_block_ctrcbc_class *const *, + void *, const void *, size_t)) + &br_aes_ct64_ctrcbc_mac +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_dec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_dec.c new file mode 100644 index 0000000..2c3abee --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_dec.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_aes_ct64_bitslice_invSbox(uint64_t *q) +{ + /* + * See br_aes_ct_bitslice_invSbox(). This is the natural extension + * to 64-bit registers. + */ + uint64_t q0, q1, q2, q3, q4, q5, q6, q7; + + q0 = ~q[0]; + q1 = ~q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = ~q[5]; + q6 = ~q[6]; + q7 = q[7]; + q[7] = q1 ^ q4 ^ q6; + q[6] = q0 ^ q3 ^ q5; + q[5] = q7 ^ q2 ^ q4; + q[4] = q6 ^ q1 ^ q3; + q[3] = q5 ^ q0 ^ q2; + q[2] = q4 ^ q7 ^ q1; + q[1] = q3 ^ q6 ^ q0; + q[0] = q2 ^ q5 ^ q7; + + br_aes_ct64_bitslice_Sbox(q); + + q0 = ~q[0]; + q1 = ~q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = ~q[5]; + q6 = ~q[6]; + q7 = q[7]; + q[7] = q1 ^ q4 ^ q6; + q[6] = q0 ^ q3 ^ q5; + q[5] = q7 ^ q2 ^ q4; + q[4] = q6 ^ q1 ^ q3; + q[3] = q5 ^ q0 ^ q2; + q[2] = q4 ^ q7 ^ q1; + q[1] = q3 ^ q6 ^ q0; + q[0] = q2 ^ q5 ^ q7; +} + +static void +add_round_key(uint64_t *q, const uint64_t *sk) +{ + int i; + + for (i = 0; i < 8; i ++) { + q[i] ^= sk[i]; + } +} + +static void +inv_shift_rows(uint64_t *q) +{ + int i; + + for (i = 0; i < 8; i ++) { + uint64_t x; + + x = q[i]; + q[i] = (x & (uint64_t)0x000000000000FFFF) + | ((x & (uint64_t)0x000000000FFF0000) << 4) + | ((x & (uint64_t)0x00000000F0000000) >> 12) + | ((x & (uint64_t)0x000000FF00000000) << 8) + | ((x & (uint64_t)0x0000FF0000000000) >> 8) + | ((x & (uint64_t)0x000F000000000000) << 12) + | ((x & (uint64_t)0xFFF0000000000000) >> 4); + } +} + +static __inline uint64_t +rotr32(uint64_t x) +{ + return (x << 32) | (x >> 32); +} + +static void +inv_mix_columns(uint64_t *q) +{ + uint64_t q0, q1, q2, q3, q4, q5, q6, q7; + uint64_t r0, r1, r2, r3, r4, r5, r6, r7; + + q0 = q[0]; + q1 = q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = q[5]; + q6 = q[6]; + q7 = q[7]; + r0 = (q0 >> 16) | (q0 << 48); + r1 = (q1 >> 16) | (q1 << 48); + r2 = (q2 >> 16) | (q2 << 48); + r3 = (q3 >> 16) | (q3 << 48); + r4 = (q4 >> 16) | (q4 << 48); + r5 = (q5 >> 16) | (q5 << 48); + r6 = (q6 >> 16) | (q6 << 48); + r7 = (q7 >> 16) | (q7 << 48); + + q[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr32(q0 ^ q5 ^ q6 ^ r0 ^ r5); + q[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr32(q1 ^ q5 ^ q7 ^ r1 ^ r5 ^ r6); + q[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr32(q0 ^ q2 ^ q6 ^ r2 ^ r6 ^ r7); + q[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr32(q0 ^ q1 ^ q3 ^ q5 ^ q6 ^ q7 ^ r0 ^ r3 ^ r5 ^ r7); + q[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr32(q1 ^ q2 ^ q4 ^ q5 ^ q7 ^ r1 ^ r4 ^ r5 ^ r6); + q[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr32(q2 ^ q3 ^ q5 ^ q6 ^ r2 ^ r5 ^ r6 ^ r7); + q[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr32(q3 ^ q4 ^ q6 ^ q7 ^ r3 ^ r6 ^ r7); + q[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr32(q4 ^ q5 ^ q7 ^ r4 ^ r7); +} + +/* see inner.h */ +void +br_aes_ct64_bitslice_decrypt(unsigned num_rounds, + const uint64_t *skey, uint64_t *q) +{ + unsigned u; + + add_round_key(q, skey + (num_rounds << 3)); + for (u = num_rounds - 1; u > 0; u --) { + inv_shift_rows(q); + br_aes_ct64_bitslice_invSbox(q); + add_round_key(q, skey + (u << 3)); + inv_mix_columns(q); + } + inv_shift_rows(q); + br_aes_ct64_bitslice_invSbox(q); + add_round_key(q, skey); +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_enc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_enc.c new file mode 100644 index 0000000..0f08eeb --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct64_enc.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 __inline void +add_round_key(uint64_t *q, const uint64_t *sk) +{ + q[0] ^= sk[0]; + q[1] ^= sk[1]; + q[2] ^= sk[2]; + q[3] ^= sk[3]; + q[4] ^= sk[4]; + q[5] ^= sk[5]; + q[6] ^= sk[6]; + q[7] ^= sk[7]; +} + +static __inline void +shift_rows(uint64_t *q) +{ + int i; + + for (i = 0; i < 8; i ++) { + uint64_t x; + + x = q[i]; + q[i] = (x & (uint64_t)0x000000000000FFFF) + | ((x & (uint64_t)0x00000000FFF00000) >> 4) + | ((x & (uint64_t)0x00000000000F0000) << 12) + | ((x & (uint64_t)0x0000FF0000000000) >> 8) + | ((x & (uint64_t)0x000000FF00000000) << 8) + | ((x & (uint64_t)0xF000000000000000) >> 12) + | ((x & (uint64_t)0x0FFF000000000000) << 4); + } +} + +static __inline uint64_t +rotr32(uint64_t x) +{ + return (x << 32) | (x >> 32); +} + +static __inline void +mix_columns(uint64_t *q) +{ + uint64_t q0, q1, q2, q3, q4, q5, q6, q7; + uint64_t r0, r1, r2, r3, r4, r5, r6, r7; + + q0 = q[0]; + q1 = q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = q[5]; + q6 = q[6]; + q7 = q[7]; + r0 = (q0 >> 16) | (q0 << 48); + r1 = (q1 >> 16) | (q1 << 48); + r2 = (q2 >> 16) | (q2 << 48); + r3 = (q3 >> 16) | (q3 << 48); + r4 = (q4 >> 16) | (q4 << 48); + r5 = (q5 >> 16) | (q5 << 48); + r6 = (q6 >> 16) | (q6 << 48); + r7 = (q7 >> 16) | (q7 << 48); + + q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); + q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); + q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); + q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); + q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); + q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); + q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); + q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); +} + +/* see inner.h */ +void +br_aes_ct64_bitslice_encrypt(unsigned num_rounds, + const uint64_t *skey, uint64_t *q) +{ + unsigned u; + + add_round_key(q, skey); + for (u = 1; u < num_rounds; u ++) { + br_aes_ct64_bitslice_Sbox(q); + shift_rows(q); + mix_columns(q); + add_round_key(q, skey + (u << 3)); + } + br_aes_ct64_bitslice_Sbox(q); + shift_rows(q); + add_round_key(q, skey + (num_rounds << 3)); +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct_cbcdec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_cbcdec.c new file mode 100644 index 0000000..522645a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_cbcdec.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_ct_cbcdec_vtable; + ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + uint32_t iv0, iv1, iv2, iv3; + uint32_t sk_exp[120]; + + br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + ivbuf = iv; + iv0 = br_dec32le(ivbuf); + iv1 = br_dec32le(ivbuf + 4); + iv2 = br_dec32le(ivbuf + 8); + iv3 = br_dec32le(ivbuf + 12); + buf = data; + while (len > 0) { + uint32_t q[8], sq[8]; + + q[0] = br_dec32le(buf); + q[2] = br_dec32le(buf + 4); + q[4] = br_dec32le(buf + 8); + q[6] = br_dec32le(buf + 12); + if (len >= 32) { + q[1] = br_dec32le(buf + 16); + q[3] = br_dec32le(buf + 20); + q[5] = br_dec32le(buf + 24); + q[7] = br_dec32le(buf + 28); + } else { + q[1] = 0; + q[3] = 0; + q[5] = 0; + q[7] = 0; + } + memcpy(sq, q, sizeof q); + br_aes_ct_ortho(q); + br_aes_ct_bitslice_decrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct_ortho(q); + br_enc32le(buf, q[0] ^ iv0); + br_enc32le(buf + 4, q[2] ^ iv1); + br_enc32le(buf + 8, q[4] ^ iv2); + br_enc32le(buf + 12, q[6] ^ iv3); + if (len < 32) { + iv0 = sq[0]; + iv1 = sq[2]; + iv2 = sq[4]; + iv3 = sq[6]; + break; + } + br_enc32le(buf + 16, q[1] ^ sq[0]); + br_enc32le(buf + 20, q[3] ^ sq[2]); + br_enc32le(buf + 24, q[5] ^ sq[4]); + br_enc32le(buf + 28, q[7] ^ sq[6]); + iv0 = sq[1]; + iv1 = sq[3]; + iv2 = sq[5]; + iv3 = sq[7]; + buf += 32; + len -= 32; + } + br_enc32le(ivbuf, iv0); + br_enc32le(ivbuf + 4, iv1); + br_enc32le(ivbuf + 8, iv2); + br_enc32le(ivbuf + 12, iv3); +} + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_aes_ct_cbcdec_vtable = { + sizeof(br_aes_ct_cbcdec_keys), + 16, + 4, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_aes_ct_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_aes_ct_cbcdec_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct_cbcenc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_cbcenc.c new file mode 100644 index 0000000..cb85977 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_cbcenc.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_ct_cbcenc_vtable; + ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + uint32_t q[8]; + uint32_t iv0, iv1, iv2, iv3; + uint32_t sk_exp[120]; + + q[1] = 0; + q[3] = 0; + q[5] = 0; + q[7] = 0; + br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + ivbuf = iv; + iv0 = br_dec32le(ivbuf); + iv1 = br_dec32le(ivbuf + 4); + iv2 = br_dec32le(ivbuf + 8); + iv3 = br_dec32le(ivbuf + 12); + buf = data; + while (len > 0) { + q[0] = iv0 ^ br_dec32le(buf); + q[2] = iv1 ^ br_dec32le(buf + 4); + q[4] = iv2 ^ br_dec32le(buf + 8); + q[6] = iv3 ^ br_dec32le(buf + 12); + br_aes_ct_ortho(q); + br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct_ortho(q); + iv0 = q[0]; + iv1 = q[2]; + iv2 = q[4]; + iv3 = q[6]; + br_enc32le(buf, iv0); + br_enc32le(buf + 4, iv1); + br_enc32le(buf + 8, iv2); + br_enc32le(buf + 12, iv3); + buf += 16; + len -= 16; + } + br_enc32le(ivbuf, iv0); + br_enc32le(ivbuf + 4, iv1); + br_enc32le(ivbuf + 8, iv2); + br_enc32le(ivbuf + 12, iv3); +} + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_aes_ct_cbcenc_vtable = { + sizeof(br_aes_ct_cbcenc_keys), + 16, + 4, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_aes_ct_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_aes_ct_cbcenc_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct_ctr.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_ctr.c new file mode 100644 index 0000000..f407689 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_ctr.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_ct_ctr_vtable; + ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len); +} + +static void +xorbuf(void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + *d ++ ^= *s ++; + } +} + +/* see bearssl_block.h */ +uint32_t +br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + const unsigned char *ivbuf; + uint32_t iv0, iv1, iv2; + uint32_t sk_exp[120]; + + br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + ivbuf = iv; + iv0 = br_dec32le(ivbuf); + iv1 = br_dec32le(ivbuf + 4); + iv2 = br_dec32le(ivbuf + 8); + buf = data; + while (len > 0) { + uint32_t q[8]; + unsigned char tmp[32]; + + /* + * TODO: see if we can save on the first br_aes_ct_ortho() + * call, since iv0/iv1/iv2 are constant for the whole run. + */ + q[0] = q[1] = iv0; + q[2] = q[3] = iv1; + q[4] = q[5] = iv2; + q[6] = br_swap32(cc); + q[7] = br_swap32(cc + 1); + br_aes_ct_ortho(q); + br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct_ortho(q); + br_enc32le(tmp, q[0]); + br_enc32le(tmp + 4, q[2]); + br_enc32le(tmp + 8, q[4]); + br_enc32le(tmp + 12, q[6]); + br_enc32le(tmp + 16, q[1]); + br_enc32le(tmp + 20, q[3]); + br_enc32le(tmp + 24, q[5]); + br_enc32le(tmp + 28, q[7]); + + if (len <= 32) { + xorbuf(buf, tmp, len); + cc ++; + if (len > 16) { + cc ++; + } + break; + } + xorbuf(buf, tmp, 32); + buf += 32; + len -= 32; + cc += 2; + } + return cc; +} + +/* see bearssl_block.h */ +const br_block_ctr_class br_aes_ct_ctr_vtable = { + sizeof(br_aes_ct_ctr_keys), + 16, + 4, + (void (*)(const br_block_ctr_class **, const void *, size_t)) + &br_aes_ct_ctr_init, + (uint32_t (*)(const br_block_ctr_class *const *, + const void *, uint32_t, void *, size_t)) + &br_aes_ct_ctr_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct_ctrcbc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_ctrcbc.c new file mode 100644 index 0000000..8ae9fc7 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_ctrcbc.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_ct_ctrcbc_vtable; + ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len); +} + +static void +xorbuf(void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + *d ++ ^= *s ++; + } +} + +/* see bearssl_block.h */ +void +br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len) +{ + unsigned char *buf; + unsigned char *ivbuf; + uint32_t iv0, iv1, iv2, iv3; + uint32_t sk_exp[120]; + + br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + + /* + * We keep the counter as four 32-bit values, with big-endian + * convention, because that's what is expected for purposes of + * incrementing the counter value. + */ + ivbuf = ctr; + iv0 = br_dec32be(ivbuf + 0); + iv1 = br_dec32be(ivbuf + 4); + iv2 = br_dec32be(ivbuf + 8); + iv3 = br_dec32be(ivbuf + 12); + + buf = data; + while (len > 0) { + uint32_t q[8], carry; + unsigned char tmp[32]; + + /* + * The bitslice implementation expects values in + * little-endian convention, so we have to byteswap them. + */ + q[0] = br_swap32(iv0); + q[2] = br_swap32(iv1); + q[4] = br_swap32(iv2); + q[6] = br_swap32(iv3); + iv3 ++; + carry = ~(iv3 | -iv3) >> 31; + iv2 += carry; + carry &= -(~(iv2 | -iv2) >> 31); + iv1 += carry; + carry &= -(~(iv1 | -iv1) >> 31); + iv0 += carry; + q[1] = br_swap32(iv0); + q[3] = br_swap32(iv1); + q[5] = br_swap32(iv2); + q[7] = br_swap32(iv3); + if (len > 16) { + iv3 ++; + carry = ~(iv3 | -iv3) >> 31; + iv2 += carry; + carry &= -(~(iv2 | -iv2) >> 31); + iv1 += carry; + carry &= -(~(iv1 | -iv1) >> 31); + iv0 += carry; + } + + br_aes_ct_ortho(q); + br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct_ortho(q); + + br_enc32le(tmp, q[0]); + br_enc32le(tmp + 4, q[2]); + br_enc32le(tmp + 8, q[4]); + br_enc32le(tmp + 12, q[6]); + br_enc32le(tmp + 16, q[1]); + br_enc32le(tmp + 20, q[3]); + br_enc32le(tmp + 24, q[5]); + br_enc32le(tmp + 28, q[7]); + + if (len <= 32) { + xorbuf(buf, tmp, len); + break; + } + xorbuf(buf, tmp, 32); + buf += 32; + len -= 32; + } + br_enc32be(ivbuf + 0, iv0); + br_enc32be(ivbuf + 4, iv1); + br_enc32be(ivbuf + 8, iv2); + br_enc32be(ivbuf + 12, iv3); +} + +/* see bearssl_block.h */ +void +br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len) +{ + const unsigned char *buf; + uint32_t cm0, cm1, cm2, cm3; + uint32_t q[8]; + uint32_t sk_exp[120]; + + br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + + buf = data; + cm0 = br_dec32le((unsigned char *)cbcmac + 0); + cm1 = br_dec32le((unsigned char *)cbcmac + 4); + cm2 = br_dec32le((unsigned char *)cbcmac + 8); + cm3 = br_dec32le((unsigned char *)cbcmac + 12); + q[1] = 0; + q[3] = 0; + q[5] = 0; + q[7] = 0; + + while (len > 0) { + q[0] = cm0 ^ br_dec32le(buf + 0); + q[2] = cm1 ^ br_dec32le(buf + 4); + q[4] = cm2 ^ br_dec32le(buf + 8); + q[6] = cm3 ^ br_dec32le(buf + 12); + + br_aes_ct_ortho(q); + br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct_ortho(q); + + cm0 = q[0]; + cm1 = q[2]; + cm2 = q[4]; + cm3 = q[6]; + buf += 16; + len -= 16; + } + + br_enc32le((unsigned char *)cbcmac + 0, cm0); + br_enc32le((unsigned char *)cbcmac + 4, cm1); + br_enc32le((unsigned char *)cbcmac + 8, cm2); + br_enc32le((unsigned char *)cbcmac + 12, cm3); +} + +/* see bearssl_block.h */ +void +br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + /* + * When encrypting, the CBC-MAC processing must be lagging by + * one block, since it operates on the encrypted values, so + * it must wait for that encryption to complete. + */ + + unsigned char *buf; + unsigned char *ivbuf; + uint32_t iv0, iv1, iv2, iv3; + uint32_t cm0, cm1, cm2, cm3; + uint32_t sk_exp[120]; + int first_iter; + + br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + + /* + * We keep the counter as four 32-bit values, with big-endian + * convention, because that's what is expected for purposes of + * incrementing the counter value. + */ + ivbuf = ctr; + iv0 = br_dec32be(ivbuf + 0); + iv1 = br_dec32be(ivbuf + 4); + iv2 = br_dec32be(ivbuf + 8); + iv3 = br_dec32be(ivbuf + 12); + + /* + * The current CBC-MAC value is kept in little-endian convention. + */ + cm0 = br_dec32le((unsigned char *)cbcmac + 0); + cm1 = br_dec32le((unsigned char *)cbcmac + 4); + cm2 = br_dec32le((unsigned char *)cbcmac + 8); + cm3 = br_dec32le((unsigned char *)cbcmac + 12); + + buf = data; + first_iter = 1; + while (len > 0) { + uint32_t q[8], carry; + + /* + * The bitslice implementation expects values in + * little-endian convention, so we have to byteswap them. + */ + q[0] = br_swap32(iv0); + q[2] = br_swap32(iv1); + q[4] = br_swap32(iv2); + q[6] = br_swap32(iv3); + iv3 ++; + carry = ~(iv3 | -iv3) >> 31; + iv2 += carry; + carry &= -(~(iv2 | -iv2) >> 31); + iv1 += carry; + carry &= -(~(iv1 | -iv1) >> 31); + iv0 += carry; + + /* + * The odd values are used for CBC-MAC. + */ + q[1] = cm0; + q[3] = cm1; + q[5] = cm2; + q[7] = cm3; + + br_aes_ct_ortho(q); + br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct_ortho(q); + + /* + * We do the XOR with the plaintext in 32-bit registers, + * so that the value are available for CBC-MAC processing + * as well. + */ + q[0] ^= br_dec32le(buf + 0); + q[2] ^= br_dec32le(buf + 4); + q[4] ^= br_dec32le(buf + 8); + q[6] ^= br_dec32le(buf + 12); + br_enc32le(buf + 0, q[0]); + br_enc32le(buf + 4, q[2]); + br_enc32le(buf + 8, q[4]); + br_enc32le(buf + 12, q[6]); + + buf += 16; + len -= 16; + + /* + * We set the cm* values to the block to encrypt in the + * next iteration. + */ + if (first_iter) { + first_iter = 0; + cm0 ^= q[0]; + cm1 ^= q[2]; + cm2 ^= q[4]; + cm3 ^= q[6]; + } else { + cm0 = q[0] ^ q[1]; + cm1 = q[2] ^ q[3]; + cm2 = q[4] ^ q[5]; + cm3 = q[6] ^ q[7]; + } + + /* + * If this was the last iteration, then compute the + * extra block encryption to complete CBC-MAC. + */ + if (len == 0) { + q[0] = cm0; + q[2] = cm1; + q[4] = cm2; + q[6] = cm3; + br_aes_ct_ortho(q); + br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct_ortho(q); + cm0 = q[0]; + cm1 = q[2]; + cm2 = q[4]; + cm3 = q[6]; + break; + } + } + + br_enc32be(ivbuf + 0, iv0); + br_enc32be(ivbuf + 4, iv1); + br_enc32be(ivbuf + 8, iv2); + br_enc32be(ivbuf + 12, iv3); + br_enc32le((unsigned char *)cbcmac + 0, cm0); + br_enc32le((unsigned char *)cbcmac + 4, cm1); + br_enc32le((unsigned char *)cbcmac + 8, cm2); + br_enc32le((unsigned char *)cbcmac + 12, cm3); +} + +/* see bearssl_block.h */ +void +br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + unsigned char *buf; + unsigned char *ivbuf; + uint32_t iv0, iv1, iv2, iv3; + uint32_t cm0, cm1, cm2, cm3; + uint32_t sk_exp[120]; + + br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + + /* + * We keep the counter as four 32-bit values, with big-endian + * convention, because that's what is expected for purposes of + * incrementing the counter value. + */ + ivbuf = ctr; + iv0 = br_dec32be(ivbuf + 0); + iv1 = br_dec32be(ivbuf + 4); + iv2 = br_dec32be(ivbuf + 8); + iv3 = br_dec32be(ivbuf + 12); + + /* + * The current CBC-MAC value is kept in little-endian convention. + */ + cm0 = br_dec32le((unsigned char *)cbcmac + 0); + cm1 = br_dec32le((unsigned char *)cbcmac + 4); + cm2 = br_dec32le((unsigned char *)cbcmac + 8); + cm3 = br_dec32le((unsigned char *)cbcmac + 12); + + buf = data; + while (len > 0) { + uint32_t q[8], carry; + unsigned char tmp[16]; + + /* + * The bitslice implementation expects values in + * little-endian convention, so we have to byteswap them. + */ + q[0] = br_swap32(iv0); + q[2] = br_swap32(iv1); + q[4] = br_swap32(iv2); + q[6] = br_swap32(iv3); + iv3 ++; + carry = ~(iv3 | -iv3) >> 31; + iv2 += carry; + carry &= -(~(iv2 | -iv2) >> 31); + iv1 += carry; + carry &= -(~(iv1 | -iv1) >> 31); + iv0 += carry; + + /* + * The odd values are used for CBC-MAC. + */ + q[1] = cm0 ^ br_dec32le(buf + 0); + q[3] = cm1 ^ br_dec32le(buf + 4); + q[5] = cm2 ^ br_dec32le(buf + 8); + q[7] = cm3 ^ br_dec32le(buf + 12); + + br_aes_ct_ortho(q); + br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); + br_aes_ct_ortho(q); + + br_enc32le(tmp + 0, q[0]); + br_enc32le(tmp + 4, q[2]); + br_enc32le(tmp + 8, q[4]); + br_enc32le(tmp + 12, q[6]); + xorbuf(buf, tmp, 16); + cm0 = q[1]; + cm1 = q[3]; + cm2 = q[5]; + cm3 = q[7]; + buf += 16; + len -= 16; + } + + br_enc32be(ivbuf + 0, iv0); + br_enc32be(ivbuf + 4, iv1); + br_enc32be(ivbuf + 8, iv2); + br_enc32be(ivbuf + 12, iv3); + br_enc32le((unsigned char *)cbcmac + 0, cm0); + br_enc32le((unsigned char *)cbcmac + 4, cm1); + br_enc32le((unsigned char *)cbcmac + 8, cm2); + br_enc32le((unsigned char *)cbcmac + 12, cm3); +} + +/* see bearssl_block.h */ +const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable = { + sizeof(br_aes_ct_ctrcbc_keys), + 16, + 4, + (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) + &br_aes_ct_ctrcbc_init, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_ct_ctrcbc_encrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_ct_ctrcbc_decrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, size_t)) + &br_aes_ct_ctrcbc_ctr, + (void (*)(const br_block_ctrcbc_class *const *, + void *, const void *, size_t)) + &br_aes_ct_ctrcbc_mac +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct_dec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_dec.c new file mode 100644 index 0000000..d581b24 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_dec.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_aes_ct_bitslice_invSbox(uint32_t *q) +{ + /* + * AES S-box is: + * S(x) = A(I(x)) ^ 0x63 + * where I() is inversion in GF(256), and A() is a linear + * transform (0 is formally defined to be its own inverse). + * Since inversion is an involution, the inverse S-box can be + * computed from the S-box as: + * iS(x) = B(S(B(x ^ 0x63)) ^ 0x63) + * where B() is the inverse of A(). Indeed, for any y in GF(256): + * iS(S(y)) = B(A(I(B(A(I(y)) ^ 0x63 ^ 0x63))) ^ 0x63 ^ 0x63) = y + * + * Note: we reuse the implementation of the forward S-box, + * instead of duplicating it here, so that total code size is + * lower. By merging the B() transforms into the S-box circuit + * we could make faster CBC decryption, but CBC decryption is + * already quite faster than CBC encryption because we can + * process two blocks in parallel. + */ + uint32_t q0, q1, q2, q3, q4, q5, q6, q7; + + q0 = ~q[0]; + q1 = ~q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = ~q[5]; + q6 = ~q[6]; + q7 = q[7]; + q[7] = q1 ^ q4 ^ q6; + q[6] = q0 ^ q3 ^ q5; + q[5] = q7 ^ q2 ^ q4; + q[4] = q6 ^ q1 ^ q3; + q[3] = q5 ^ q0 ^ q2; + q[2] = q4 ^ q7 ^ q1; + q[1] = q3 ^ q6 ^ q0; + q[0] = q2 ^ q5 ^ q7; + + br_aes_ct_bitslice_Sbox(q); + + q0 = ~q[0]; + q1 = ~q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = ~q[5]; + q6 = ~q[6]; + q7 = q[7]; + q[7] = q1 ^ q4 ^ q6; + q[6] = q0 ^ q3 ^ q5; + q[5] = q7 ^ q2 ^ q4; + q[4] = q6 ^ q1 ^ q3; + q[3] = q5 ^ q0 ^ q2; + q[2] = q4 ^ q7 ^ q1; + q[1] = q3 ^ q6 ^ q0; + q[0] = q2 ^ q5 ^ q7; +} + +static void +add_round_key(uint32_t *q, const uint32_t *sk) +{ + int i; + + for (i = 0; i < 8; i ++) { + q[i] ^= sk[i]; + } +} + +static void +inv_shift_rows(uint32_t *q) +{ + int i; + + for (i = 0; i < 8; i ++) { + uint32_t x; + + x = q[i]; + q[i] = (x & 0x000000FF) + | ((x & 0x00003F00) << 2) | ((x & 0x0000C000) >> 6) + | ((x & 0x000F0000) << 4) | ((x & 0x00F00000) >> 4) + | ((x & 0x03000000) << 6) | ((x & 0xFC000000) >> 2); + } +} + +static __inline uint32_t +rotr16(uint32_t x) +{ + return (x << 16) | (x >> 16); +} + +static void +inv_mix_columns(uint32_t *q) +{ + uint32_t q0, q1, q2, q3, q4, q5, q6, q7; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + + q0 = q[0]; + q1 = q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = q[5]; + q6 = q[6]; + q7 = q[7]; + r0 = (q0 >> 8) | (q0 << 24); + r1 = (q1 >> 8) | (q1 << 24); + r2 = (q2 >> 8) | (q2 << 24); + r3 = (q3 >> 8) | (q3 << 24); + r4 = (q4 >> 8) | (q4 << 24); + r5 = (q5 >> 8) | (q5 << 24); + r6 = (q6 >> 8) | (q6 << 24); + r7 = (q7 >> 8) | (q7 << 24); + + q[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr16(q0 ^ q5 ^ q6 ^ r0 ^ r5); + q[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr16(q1 ^ q5 ^ q7 ^ r1 ^ r5 ^ r6); + q[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr16(q0 ^ q2 ^ q6 ^ r2 ^ r6 ^ r7); + q[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr16(q0 ^ q1 ^ q3 ^ q5 ^ q6 ^ q7 ^ r0 ^ r3 ^ r5 ^ r7); + q[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q1 ^ q2 ^ q4 ^ q5 ^ q7 ^ r1 ^ r4 ^ r5 ^ r6); + q[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q2 ^ q3 ^ q5 ^ q6 ^ r2 ^ r5 ^ r6 ^ r7); + q[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr16(q3 ^ q4 ^ q6 ^ q7 ^ r3 ^ r6 ^ r7); + q[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr16(q4 ^ q5 ^ q7 ^ r4 ^ r7); +} + +/* see inner.h */ +void +br_aes_ct_bitslice_decrypt(unsigned num_rounds, + const uint32_t *skey, uint32_t *q) +{ + unsigned u; + + add_round_key(q, skey + (num_rounds << 3)); + for (u = num_rounds - 1; u > 0; u --) { + inv_shift_rows(q); + br_aes_ct_bitslice_invSbox(q); + add_round_key(q, skey + (u << 3)); + inv_mix_columns(q); + } + inv_shift_rows(q); + br_aes_ct_bitslice_invSbox(q); + add_round_key(q, skey); +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_ct_enc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_enc.c new file mode 100644 index 0000000..b0b8cc7 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_ct_enc.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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 __inline void +add_round_key(uint32_t *q, const uint32_t *sk) +{ + q[0] ^= sk[0]; + q[1] ^= sk[1]; + q[2] ^= sk[2]; + q[3] ^= sk[3]; + q[4] ^= sk[4]; + q[5] ^= sk[5]; + q[6] ^= sk[6]; + q[7] ^= sk[7]; +} + +static __inline void +shift_rows(uint32_t *q) +{ + int i; + + for (i = 0; i < 8; i ++) { + uint32_t x; + + x = q[i]; + q[i] = (x & 0x000000FF) + | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) + | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) + | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); + } +} + +static __inline uint32_t +rotr16(uint32_t x) +{ + return (x << 16) | (x >> 16); +} + +static __inline void +mix_columns(uint32_t *q) +{ + uint32_t q0, q1, q2, q3, q4, q5, q6, q7; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + + q0 = q[0]; + q1 = q[1]; + q2 = q[2]; + q3 = q[3]; + q4 = q[4]; + q5 = q[5]; + q6 = q[6]; + q7 = q[7]; + r0 = (q0 >> 8) | (q0 << 24); + r1 = (q1 >> 8) | (q1 << 24); + r2 = (q2 >> 8) | (q2 << 24); + r3 = (q3 >> 8) | (q3 << 24); + r4 = (q4 >> 8) | (q4 << 24); + r5 = (q5 >> 8) | (q5 << 24); + r6 = (q6 >> 8) | (q6 << 24); + r7 = (q7 >> 8) | (q7 << 24); + + q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); + q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); + q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); + q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); + q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); + q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); + q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); + q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); +} + +/* see inner.h */ +void +br_aes_ct_bitslice_encrypt(unsigned num_rounds, + const uint32_t *skey, uint32_t *q) +{ + unsigned u; + + add_round_key(q, skey); + for (u = 1; u < num_rounds; u ++) { + br_aes_ct_bitslice_Sbox(q); + shift_rows(q); + mix_columns(q); + add_round_key(q, skey + (u << 3)); + } + br_aes_ct_bitslice_Sbox(q); + shift_rows(q); + add_round_key(q, skey + (num_rounds << 3)); +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8.c b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8.c new file mode 100644 index 0000000..b2c63c3 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8.c @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_POWER_ASM_MACROS 1 +#include "inner.h" + +/* + * This code contains the AES key schedule implementation using the + * POWER8 opcodes. + */ + +#if BR_POWER8 + +static void +key_schedule_128(unsigned char *sk, const unsigned char *key) +{ + long cc; + + static const uint32_t fmod[] = { 0x11B, 0x11B, 0x11B, 0x11B }; +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc = 0; + + /* + * We use the VSX instructions for loading and storing the + * key/subkeys, since they support unaligned accesses. The rest + * of the computation is VMX only. VMX register 0 is VSX + * register 32. + */ + asm volatile ( + + /* + * v0 = all-zero word + * v1 = constant -8 / +8, copied into four words + * v2 = current subkey + * v3 = Rcon (x4 words) + * v6 = constant 8, copied into four words + * v7 = constant 0x11B, copied into four words + * v8 = constant for byteswapping words + */ + vspltisw(0, 0) +#if BR_POWER8_LE + vspltisw(1, -8) +#else + vspltisw(1, 8) +#endif + lxvw4x(34, 0, %[key]) + vspltisw(3, 1) + vspltisw(6, 8) + lxvw4x(39, 0, %[fmod]) +#if BR_POWER8_LE + lxvw4x(40, 0, %[idx2be]) +#endif + + /* + * First subkey is a copy of the key itself. + */ +#if BR_POWER8_LE + vperm(4, 2, 2, 8) + stxvw4x(36, 0, %[sk]) +#else + stxvw4x(34, 0, %[sk]) +#endif + + /* + * Loop must run 10 times. + */ + li(%[cc], 10) + mtctr(%[cc]) + label(loop) + /* Increment subkey address */ + addi(%[sk], %[sk], 16) + + /* Compute SubWord(RotWord(temp)) xor Rcon (into v4, splat) */ + vrlw(4, 2, 1) + vsbox(4, 4) +#if BR_POWER8_LE + vxor(4, 4, 3) +#else + vsldoi(5, 3, 0, 3) + vxor(4, 4, 5) +#endif + vspltw(4, 4, 3) + + /* XOR words for next subkey */ + vsldoi(5, 0, 2, 12) + vxor(2, 2, 5) + vsldoi(5, 0, 2, 12) + vxor(2, 2, 5) + vsldoi(5, 0, 2, 12) + vxor(2, 2, 5) + vxor(2, 2, 4) + + /* Store next subkey */ +#if BR_POWER8_LE + vperm(4, 2, 2, 8) + stxvw4x(36, 0, %[sk]) +#else + stxvw4x(34, 0, %[sk]) +#endif + + /* Update Rcon */ + vadduwm(3, 3, 3) + vsrw(4, 3, 6) + vsubuwm(4, 0, 4) + vand(4, 4, 7) + vxor(3, 3, 4) + + bdnz(loop) + +: [sk] "+b" (sk), [cc] "+b" (cc) +: [key] "b" (key), [fmod] "b" (fmod) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "ctr", "memory" + ); +} + +static void +key_schedule_192(unsigned char *sk, const unsigned char *key) +{ + long cc; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc = 0; + + /* + * We use the VSX instructions for loading and storing the + * key/subkeys, since they support unaligned accesses. The rest + * of the computation is VMX only. VMX register 0 is VSX + * register 32. + */ + asm volatile ( + + /* + * v0 = all-zero word + * v1 = constant -8 / +8, copied into four words + * v2, v3 = current subkey + * v5 = Rcon (x4 words) (already shifted on big-endian) + * v6 = constant 8, copied into four words + * v8 = constant for byteswapping words + * + * The left two words of v3 are ignored. + */ + vspltisw(0, 0) +#if BR_POWER8_LE + vspltisw(1, -8) +#else + vspltisw(1, 8) +#endif + li(%[cc], 8) + lxvw4x(34, 0, %[key]) + lxvw4x(35, %[cc], %[key]) + vsldoi(3, 3, 0, 8) + vspltisw(5, 1) +#if !BR_POWER8_LE + vsldoi(5, 5, 0, 3) +#endif + vspltisw(6, 8) +#if BR_POWER8_LE + lxvw4x(40, 0, %[idx2be]) +#endif + + /* + * Loop must run 8 times. Each iteration produces 256 + * bits of subkeys, with a 64-bit overlap. + */ + li(%[cc], 8) + mtctr(%[cc]) + li(%[cc], 16) + label(loop) + + /* + * Last 6 words in v2:v3l. Compute next 6 words into + * v3r:v4. + */ + vrlw(10, 3, 1) + vsbox(10, 10) + vxor(10, 10, 5) + vspltw(10, 10, 1) + vsldoi(11, 0, 10, 8) + + vsldoi(12, 0, 2, 12) + vxor(12, 2, 12) + vsldoi(13, 0, 12, 12) + vxor(12, 12, 13) + vsldoi(13, 0, 12, 12) + vxor(12, 12, 13) + + vspltw(13, 12, 3) + vxor(13, 13, 3) + vsldoi(14, 0, 3, 12) + vxor(13, 13, 14) + + vsldoi(4, 12, 13, 8) + vsldoi(14, 0, 3, 8) + vsldoi(3, 14, 12, 8) + + vxor(3, 3, 11) + vxor(4, 4, 10) + + /* + * Update Rcon. Since for a 192-bit key, we use only 8 + * such constants, we will not hit the field modulus, + * so a simple shift (addition) works well. + */ + vadduwm(5, 5, 5) + + /* + * Write out the two left 128-bit words + */ +#if BR_POWER8_LE + vperm(10, 2, 2, 8) + vperm(11, 3, 3, 8) + stxvw4x(42, 0, %[sk]) + stxvw4x(43, %[cc], %[sk]) +#else + stxvw4x(34, 0, %[sk]) + stxvw4x(35, %[cc], %[sk]) +#endif + addi(%[sk], %[sk], 24) + + /* + * Shift words for next iteration. + */ + vsldoi(2, 3, 4, 8) + vsldoi(3, 4, 0, 8) + + bdnz(loop) + + /* + * The loop wrote the first 50 subkey words, but we need + * to produce 52, so we must do one last write. + */ +#if BR_POWER8_LE + vperm(10, 2, 2, 8) + stxvw4x(42, 0, %[sk]) +#else + stxvw4x(34, 0, %[sk]) +#endif + +: [sk] "+b" (sk), [cc] "+b" (cc) +: [key] "b" (key) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "ctr", "memory" + ); +} + +static void +key_schedule_256(unsigned char *sk, const unsigned char *key) +{ + long cc; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc = 0; + + /* + * We use the VSX instructions for loading and storing the + * key/subkeys, since they support unaligned accesses. The rest + * of the computation is VMX only. VMX register 0 is VSX + * register 32. + */ + asm volatile ( + + /* + * v0 = all-zero word + * v1 = constant -8 / +8, copied into four words + * v2, v3 = current subkey + * v6 = Rcon (x4 words) (already shifted on big-endian) + * v7 = constant 8, copied into four words + * v8 = constant for byteswapping words + * + * The left two words of v3 are ignored. + */ + vspltisw(0, 0) +#if BR_POWER8_LE + vspltisw(1, -8) +#else + vspltisw(1, 8) +#endif + li(%[cc], 16) + lxvw4x(34, 0, %[key]) + lxvw4x(35, %[cc], %[key]) + vspltisw(6, 1) +#if !BR_POWER8_LE + vsldoi(6, 6, 0, 3) +#endif + vspltisw(7, 8) +#if BR_POWER8_LE + lxvw4x(40, 0, %[idx2be]) +#endif + + /* + * Loop must run 7 times. Each iteration produces two + * subkeys. + */ + li(%[cc], 7) + mtctr(%[cc]) + li(%[cc], 16) + label(loop) + + /* + * Current words are in v2:v3. Compute next word in v4. + */ + vrlw(10, 3, 1) + vsbox(10, 10) + vxor(10, 10, 6) + vspltw(10, 10, 3) + + vsldoi(4, 0, 2, 12) + vxor(4, 2, 4) + vsldoi(5, 0, 4, 12) + vxor(4, 4, 5) + vsldoi(5, 0, 4, 12) + vxor(4, 4, 5) + vxor(4, 4, 10) + + /* + * Then other word in v5. + */ + vsbox(10, 4) + vspltw(10, 10, 3) + + vsldoi(5, 0, 3, 12) + vxor(5, 3, 5) + vsldoi(11, 0, 5, 12) + vxor(5, 5, 11) + vsldoi(11, 0, 5, 12) + vxor(5, 5, 11) + vxor(5, 5, 10) + + /* + * Update Rcon. Since for a 256-bit key, we use only 7 + * such constants, we will not hit the field modulus, + * so a simple shift (addition) works well. + */ + vadduwm(6, 6, 6) + + /* + * Write out the two left 128-bit words + */ +#if BR_POWER8_LE + vperm(10, 2, 2, 8) + vperm(11, 3, 3, 8) + stxvw4x(42, 0, %[sk]) + stxvw4x(43, %[cc], %[sk]) +#else + stxvw4x(34, 0, %[sk]) + stxvw4x(35, %[cc], %[sk]) +#endif + addi(%[sk], %[sk], 32) + + /* + * Replace v2:v3 with v4:v5. + */ + vxor(2, 0, 4) + vxor(3, 0, 5) + + bdnz(loop) + + /* + * The loop wrote the first 14 subkeys, but we need 15, + * so we must do an extra write. + */ +#if BR_POWER8_LE + vperm(10, 2, 2, 8) + stxvw4x(42, 0, %[sk]) +#else + stxvw4x(34, 0, %[sk]) +#endif + +: [sk] "+b" (sk), [cc] "+b" (cc) +: [key] "b" (key) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "ctr", "memory" + ); +} + +/* see inner.h */ +int +br_aes_pwr8_supported(void) +{ + return 1; +} + +/* see inner.h */ +unsigned +br_aes_pwr8_keysched(unsigned char *sk, const void *key, size_t len) +{ + switch (len) { + case 16: + key_schedule_128(sk, key); + return 10; + case 24: + key_schedule_192(sk, key); + return 12; + default: + key_schedule_256(sk, key); + return 14; + } +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_cbcdec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_cbcdec.c new file mode 100644 index 0000000..e535ba6 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_cbcdec.c @@ -0,0 +1,670 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_POWER_ASM_MACROS 1 +#include "inner.h" + +#if BR_POWER8 + +/* see bearssl_block.h */ +void +br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_pwr8_cbcdec_vtable; + ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len); +} + +static void +cbcdec_128(const unsigned char *sk, + const unsigned char *iv, unsigned char *buf, size_t num_blocks) +{ + long cc0, cc1, cc2, cc3; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc0 = 0; + cc1 = 16; + cc2 = 32; + cc3 = 48; + asm volatile ( + + /* + * Load subkeys into v0..v10 + */ + lxvw4x(32, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(33, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(34, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(35, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(36, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(37, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(38, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(39, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(40, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(41, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(42, %[cc0], %[sk]) + li(%[cc0], 0) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * Load IV into v24. + */ + lxvw4x(56, 0, %[iv]) +#if BR_POWER8_LE + vperm(24, 24, 24, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Load next ciphertext words in v16..v19. Also save them + * in v20..v23. + */ + lxvw4x(48, %[cc0], %[buf]) + lxvw4x(49, %[cc1], %[buf]) + lxvw4x(50, %[cc2], %[buf]) + lxvw4x(51, %[cc3], %[buf]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + vand(20, 16, 16) + vand(21, 17, 17) + vand(22, 18, 18) + vand(23, 19, 19) + + /* + * Decrypt the blocks. + */ + vxor(16, 16, 10) + vxor(17, 17, 10) + vxor(18, 18, 10) + vxor(19, 19, 10) + vncipher(16, 16, 9) + vncipher(17, 17, 9) + vncipher(18, 18, 9) + vncipher(19, 19, 9) + vncipher(16, 16, 8) + vncipher(17, 17, 8) + vncipher(18, 18, 8) + vncipher(19, 19, 8) + vncipher(16, 16, 7) + vncipher(17, 17, 7) + vncipher(18, 18, 7) + vncipher(19, 19, 7) + vncipher(16, 16, 6) + vncipher(17, 17, 6) + vncipher(18, 18, 6) + vncipher(19, 19, 6) + vncipher(16, 16, 5) + vncipher(17, 17, 5) + vncipher(18, 18, 5) + vncipher(19, 19, 5) + vncipher(16, 16, 4) + vncipher(17, 17, 4) + vncipher(18, 18, 4) + vncipher(19, 19, 4) + vncipher(16, 16, 3) + vncipher(17, 17, 3) + vncipher(18, 18, 3) + vncipher(19, 19, 3) + vncipher(16, 16, 2) + vncipher(17, 17, 2) + vncipher(18, 18, 2) + vncipher(19, 19, 2) + vncipher(16, 16, 1) + vncipher(17, 17, 1) + vncipher(18, 18, 1) + vncipher(19, 19, 1) + vncipherlast(16, 16, 0) + vncipherlast(17, 17, 0) + vncipherlast(18, 18, 0) + vncipherlast(19, 19, 0) + + /* + * XOR decrypted blocks with IV / previous block. + */ + vxor(16, 16, 24) + vxor(17, 17, 20) + vxor(18, 18, 21) + vxor(19, 19, 22) + + /* + * Store back result (with byteswap) + */ +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + stxvw4x(48, %[cc0], %[buf]) + stxvw4x(49, %[cc1], %[buf]) + stxvw4x(50, %[cc2], %[buf]) + stxvw4x(51, %[cc3], %[buf]) + + /* + * Fourth encrypted block is IV for next run. + */ + vand(24, 23, 23) + + addi(%[buf], %[buf], 64) + + bdnz(loop) + +: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), + [buf] "+b" (buf) +: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", + "ctr", "memory" + ); +} + +static void +cbcdec_192(const unsigned char *sk, + const unsigned char *iv, unsigned char *buf, size_t num_blocks) +{ + long cc0, cc1, cc2, cc3; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc0 = 0; + cc1 = 16; + cc2 = 32; + cc3 = 48; + asm volatile ( + + /* + * Load subkeys into v0..v12 + */ + lxvw4x(32, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(33, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(34, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(35, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(36, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(37, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(38, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(39, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(40, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(41, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(42, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(43, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(44, %[cc0], %[sk]) + li(%[cc0], 0) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * Load IV into v24. + */ + lxvw4x(56, 0, %[iv]) +#if BR_POWER8_LE + vperm(24, 24, 24, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Load next ciphertext words in v16..v19. Also save them + * in v20..v23. + */ + lxvw4x(48, %[cc0], %[buf]) + lxvw4x(49, %[cc1], %[buf]) + lxvw4x(50, %[cc2], %[buf]) + lxvw4x(51, %[cc3], %[buf]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + vand(20, 16, 16) + vand(21, 17, 17) + vand(22, 18, 18) + vand(23, 19, 19) + + /* + * Decrypt the blocks. + */ + vxor(16, 16, 12) + vxor(17, 17, 12) + vxor(18, 18, 12) + vxor(19, 19, 12) + vncipher(16, 16, 11) + vncipher(17, 17, 11) + vncipher(18, 18, 11) + vncipher(19, 19, 11) + vncipher(16, 16, 10) + vncipher(17, 17, 10) + vncipher(18, 18, 10) + vncipher(19, 19, 10) + vncipher(16, 16, 9) + vncipher(17, 17, 9) + vncipher(18, 18, 9) + vncipher(19, 19, 9) + vncipher(16, 16, 8) + vncipher(17, 17, 8) + vncipher(18, 18, 8) + vncipher(19, 19, 8) + vncipher(16, 16, 7) + vncipher(17, 17, 7) + vncipher(18, 18, 7) + vncipher(19, 19, 7) + vncipher(16, 16, 6) + vncipher(17, 17, 6) + vncipher(18, 18, 6) + vncipher(19, 19, 6) + vncipher(16, 16, 5) + vncipher(17, 17, 5) + vncipher(18, 18, 5) + vncipher(19, 19, 5) + vncipher(16, 16, 4) + vncipher(17, 17, 4) + vncipher(18, 18, 4) + vncipher(19, 19, 4) + vncipher(16, 16, 3) + vncipher(17, 17, 3) + vncipher(18, 18, 3) + vncipher(19, 19, 3) + vncipher(16, 16, 2) + vncipher(17, 17, 2) + vncipher(18, 18, 2) + vncipher(19, 19, 2) + vncipher(16, 16, 1) + vncipher(17, 17, 1) + vncipher(18, 18, 1) + vncipher(19, 19, 1) + vncipherlast(16, 16, 0) + vncipherlast(17, 17, 0) + vncipherlast(18, 18, 0) + vncipherlast(19, 19, 0) + + /* + * XOR decrypted blocks with IV / previous block. + */ + vxor(16, 16, 24) + vxor(17, 17, 20) + vxor(18, 18, 21) + vxor(19, 19, 22) + + /* + * Store back result (with byteswap) + */ +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + stxvw4x(48, %[cc0], %[buf]) + stxvw4x(49, %[cc1], %[buf]) + stxvw4x(50, %[cc2], %[buf]) + stxvw4x(51, %[cc3], %[buf]) + + /* + * Fourth encrypted block is IV for next run. + */ + vand(24, 23, 23) + + addi(%[buf], %[buf], 64) + + bdnz(loop) + +: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), + [buf] "+b" (buf) +: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", + "ctr", "memory" + ); +} + +static void +cbcdec_256(const unsigned char *sk, + const unsigned char *iv, unsigned char *buf, size_t num_blocks) +{ + long cc0, cc1, cc2, cc3; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc0 = 0; + cc1 = 16; + cc2 = 32; + cc3 = 48; + asm volatile ( + + /* + * Load subkeys into v0..v14 + */ + lxvw4x(32, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(33, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(34, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(35, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(36, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(37, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(38, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(39, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(40, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(41, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(42, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(43, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(44, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(45, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(46, %[cc0], %[sk]) + li(%[cc0], 0) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * Load IV into v24. + */ + lxvw4x(56, 0, %[iv]) +#if BR_POWER8_LE + vperm(24, 24, 24, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Load next ciphertext words in v16..v19. Also save them + * in v20..v23. + */ + lxvw4x(48, %[cc0], %[buf]) + lxvw4x(49, %[cc1], %[buf]) + lxvw4x(50, %[cc2], %[buf]) + lxvw4x(51, %[cc3], %[buf]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + vand(20, 16, 16) + vand(21, 17, 17) + vand(22, 18, 18) + vand(23, 19, 19) + + /* + * Decrypt the blocks. + */ + vxor(16, 16, 14) + vxor(17, 17, 14) + vxor(18, 18, 14) + vxor(19, 19, 14) + vncipher(16, 16, 13) + vncipher(17, 17, 13) + vncipher(18, 18, 13) + vncipher(19, 19, 13) + vncipher(16, 16, 12) + vncipher(17, 17, 12) + vncipher(18, 18, 12) + vncipher(19, 19, 12) + vncipher(16, 16, 11) + vncipher(17, 17, 11) + vncipher(18, 18, 11) + vncipher(19, 19, 11) + vncipher(16, 16, 10) + vncipher(17, 17, 10) + vncipher(18, 18, 10) + vncipher(19, 19, 10) + vncipher(16, 16, 9) + vncipher(17, 17, 9) + vncipher(18, 18, 9) + vncipher(19, 19, 9) + vncipher(16, 16, 8) + vncipher(17, 17, 8) + vncipher(18, 18, 8) + vncipher(19, 19, 8) + vncipher(16, 16, 7) + vncipher(17, 17, 7) + vncipher(18, 18, 7) + vncipher(19, 19, 7) + vncipher(16, 16, 6) + vncipher(17, 17, 6) + vncipher(18, 18, 6) + vncipher(19, 19, 6) + vncipher(16, 16, 5) + vncipher(17, 17, 5) + vncipher(18, 18, 5) + vncipher(19, 19, 5) + vncipher(16, 16, 4) + vncipher(17, 17, 4) + vncipher(18, 18, 4) + vncipher(19, 19, 4) + vncipher(16, 16, 3) + vncipher(17, 17, 3) + vncipher(18, 18, 3) + vncipher(19, 19, 3) + vncipher(16, 16, 2) + vncipher(17, 17, 2) + vncipher(18, 18, 2) + vncipher(19, 19, 2) + vncipher(16, 16, 1) + vncipher(17, 17, 1) + vncipher(18, 18, 1) + vncipher(19, 19, 1) + vncipherlast(16, 16, 0) + vncipherlast(17, 17, 0) + vncipherlast(18, 18, 0) + vncipherlast(19, 19, 0) + + /* + * XOR decrypted blocks with IV / previous block. + */ + vxor(16, 16, 24) + vxor(17, 17, 20) + vxor(18, 18, 21) + vxor(19, 19, 22) + + /* + * Store back result (with byteswap) + */ +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + stxvw4x(48, %[cc0], %[buf]) + stxvw4x(49, %[cc1], %[buf]) + stxvw4x(50, %[cc2], %[buf]) + stxvw4x(51, %[cc3], %[buf]) + + /* + * Fourth encrypted block is IV for next run. + */ + vand(24, 23, 23) + + addi(%[buf], %[buf], 64) + + bdnz(loop) + +: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), + [buf] "+b" (buf) +: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", + "ctr", "memory" + ); +} + +/* see bearssl_block.h */ +void +br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char nextiv[16]; + unsigned char *buf; + + if (len == 0) { + return; + } + buf = data; + memcpy(nextiv, buf + len - 16, 16); + if (len >= 64) { + size_t num_blocks; + unsigned char tmp[16]; + + num_blocks = (len >> 4) & ~(size_t)3; + memcpy(tmp, buf + (num_blocks << 4) - 16, 16); + switch (ctx->num_rounds) { + case 10: + cbcdec_128(ctx->skey.skni, iv, buf, num_blocks); + break; + case 12: + cbcdec_192(ctx->skey.skni, iv, buf, num_blocks); + break; + default: + cbcdec_256(ctx->skey.skni, iv, buf, num_blocks); + break; + } + buf += num_blocks << 4; + len &= 63; + memcpy(iv, tmp, 16); + } + if (len > 0) { + unsigned char tmp[64]; + + memcpy(tmp, buf, len); + memset(tmp + len, 0, (sizeof tmp) - len); + switch (ctx->num_rounds) { + case 10: + cbcdec_128(ctx->skey.skni, iv, tmp, 4); + break; + case 12: + cbcdec_192(ctx->skey.skni, iv, tmp, 4); + break; + default: + cbcdec_256(ctx->skey.skni, iv, tmp, 4); + break; + } + memcpy(buf, tmp, len); + } + memcpy(iv, nextiv, 16); +} + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable = { + sizeof(br_aes_pwr8_cbcdec_keys), + 16, + 4, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_aes_pwr8_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_aes_pwr8_cbcdec_run +}; + +/* see bearssl_block.h */ +const br_block_cbcdec_class * +br_aes_pwr8_cbcdec_get_vtable(void) +{ + return br_aes_pwr8_supported() ? &br_aes_pwr8_cbcdec_vtable : NULL; +} + +#else + +/* see bearssl_block.h */ +const br_block_cbcdec_class * +br_aes_pwr8_cbcdec_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_cbcenc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_cbcenc.c new file mode 100644 index 0000000..00f8eca --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_cbcenc.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_POWER_ASM_MACROS 1 +#include "inner.h" + +#if BR_POWER8 + +/* see bearssl_block.h */ +void +br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_pwr8_cbcenc_vtable; + ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len); +} + +static void +cbcenc_128(const unsigned char *sk, + const unsigned char *iv, unsigned char *buf, size_t len) +{ + long cc; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc = 0; + asm volatile ( + + /* + * Load subkeys into v0..v10 + */ + lxvw4x(32, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(33, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(34, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(35, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(36, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(37, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(38, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(39, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(40, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(41, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(42, %[cc], %[sk]) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * Load IV into v16. + */ + lxvw4x(48, 0, %[iv]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Load next plaintext word and XOR with current IV. + */ + lxvw4x(49, 0, %[buf]) +#if BR_POWER8_LE + vperm(17, 17, 17, 15) +#endif + vxor(16, 16, 17) + + /* + * Encrypt the block. + */ + vxor(16, 16, 0) + vcipher(16, 16, 1) + vcipher(16, 16, 2) + vcipher(16, 16, 3) + vcipher(16, 16, 4) + vcipher(16, 16, 5) + vcipher(16, 16, 6) + vcipher(16, 16, 7) + vcipher(16, 16, 8) + vcipher(16, 16, 9) + vcipherlast(16, 16, 10) + + /* + * Store back result (with byteswap) + */ +#if BR_POWER8_LE + vperm(17, 16, 16, 15) + stxvw4x(49, 0, %[buf]) +#else + stxvw4x(48, 0, %[buf]) +#endif + addi(%[buf], %[buf], 16) + + bdnz(loop) + +: [cc] "+b" (cc), [buf] "+b" (buf) +: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "ctr", "memory" + ); +} + +static void +cbcenc_192(const unsigned char *sk, + const unsigned char *iv, unsigned char *buf, size_t len) +{ + long cc; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc = 0; + asm volatile ( + + /* + * Load subkeys into v0..v12 + */ + lxvw4x(32, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(33, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(34, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(35, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(36, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(37, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(38, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(39, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(40, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(41, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(42, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(43, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(44, %[cc], %[sk]) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * Load IV into v16. + */ + lxvw4x(48, 0, %[iv]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Load next plaintext word and XOR with current IV. + */ + lxvw4x(49, 0, %[buf]) +#if BR_POWER8_LE + vperm(17, 17, 17, 15) +#endif + vxor(16, 16, 17) + + /* + * Encrypt the block. + */ + vxor(16, 16, 0) + vcipher(16, 16, 1) + vcipher(16, 16, 2) + vcipher(16, 16, 3) + vcipher(16, 16, 4) + vcipher(16, 16, 5) + vcipher(16, 16, 6) + vcipher(16, 16, 7) + vcipher(16, 16, 8) + vcipher(16, 16, 9) + vcipher(16, 16, 10) + vcipher(16, 16, 11) + vcipherlast(16, 16, 12) + + /* + * Store back result (with byteswap) + */ +#if BR_POWER8_LE + vperm(17, 16, 16, 15) + stxvw4x(49, 0, %[buf]) +#else + stxvw4x(48, 0, %[buf]) +#endif + addi(%[buf], %[buf], 16) + + bdnz(loop) + +: [cc] "+b" (cc), [buf] "+b" (buf) +: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "ctr", "memory" + ); +} + +static void +cbcenc_256(const unsigned char *sk, + const unsigned char *iv, unsigned char *buf, size_t len) +{ + long cc; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + + cc = 0; + asm volatile ( + + /* + * Load subkeys into v0..v14 + */ + lxvw4x(32, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(33, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(34, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(35, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(36, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(37, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(38, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(39, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(40, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(41, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(42, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(43, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(44, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(45, %[cc], %[sk]) + addi(%[cc], %[cc], 16) + lxvw4x(46, %[cc], %[sk]) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * Load IV into v16. + */ + lxvw4x(48, 0, %[iv]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Load next plaintext word and XOR with current IV. + */ + lxvw4x(49, 0, %[buf]) +#if BR_POWER8_LE + vperm(17, 17, 17, 15) +#endif + vxor(16, 16, 17) + + /* + * Encrypt the block. + */ + vxor(16, 16, 0) + vcipher(16, 16, 1) + vcipher(16, 16, 2) + vcipher(16, 16, 3) + vcipher(16, 16, 4) + vcipher(16, 16, 5) + vcipher(16, 16, 6) + vcipher(16, 16, 7) + vcipher(16, 16, 8) + vcipher(16, 16, 9) + vcipher(16, 16, 10) + vcipher(16, 16, 11) + vcipher(16, 16, 12) + vcipher(16, 16, 13) + vcipherlast(16, 16, 14) + + /* + * Store back result (with byteswap) + */ +#if BR_POWER8_LE + vperm(17, 16, 16, 15) + stxvw4x(49, 0, %[buf]) +#else + stxvw4x(48, 0, %[buf]) +#endif + addi(%[buf], %[buf], 16) + + bdnz(loop) + +: [cc] "+b" (cc), [buf] "+b" (buf) +: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "ctr", "memory" + ); +} + +/* see bearssl_block.h */ +void +br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + if (len > 0) { + switch (ctx->num_rounds) { + case 10: + cbcenc_128(ctx->skey.skni, iv, data, len); + break; + case 12: + cbcenc_192(ctx->skey.skni, iv, data, len); + break; + default: + cbcenc_256(ctx->skey.skni, iv, data, len); + break; + } + memcpy(iv, (unsigned char *)data + (len - 16), 16); + } +} + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable = { + sizeof(br_aes_pwr8_cbcenc_keys), + 16, + 4, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_aes_pwr8_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_aes_pwr8_cbcenc_run +}; + +/* see bearssl_block.h */ +const br_block_cbcenc_class * +br_aes_pwr8_cbcenc_get_vtable(void) +{ + return br_aes_pwr8_supported() ? &br_aes_pwr8_cbcenc_vtable : NULL; +} + +#else + +/* see bearssl_block.h */ +const br_block_cbcenc_class * +br_aes_pwr8_cbcenc_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_ctr.c b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_ctr.c new file mode 100644 index 0000000..f5d20c0 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_ctr.c @@ -0,0 +1,717 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_POWER_ASM_MACROS 1 +#include "inner.h" + +#if BR_POWER8 + +/* see bearssl_block.h */ +void +br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_pwr8_ctr_vtable; + ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len); +} + +static void +ctr_128(const unsigned char *sk, const unsigned char *ivbuf, + unsigned char *buf, size_t num_blocks) +{ + long cc0, cc1, cc2, cc3; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + static const uint32_t ctrinc[] = { + 0, 0, 0, 4 + }; + + cc0 = 0; + cc1 = 16; + cc2 = 32; + cc3 = 48; + asm volatile ( + + /* + * Load subkeys into v0..v10 + */ + lxvw4x(32, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(33, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(34, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(35, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(36, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(37, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(38, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(39, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(40, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(41, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(42, %[cc0], %[sk]) + li(%[cc0], 0) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * v28 = increment for IV counter. + */ + lxvw4x(60, 0, %[ctrinc]) + + /* + * Load IV into v16..v19 + */ + lxvw4x(48, %[cc0], %[ivbuf]) + lxvw4x(49, %[cc1], %[ivbuf]) + lxvw4x(50, %[cc2], %[ivbuf]) + lxvw4x(51, %[cc3], %[ivbuf]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Compute next IV into v24..v27 + */ + vadduwm(24, 16, 28) + vadduwm(25, 17, 28) + vadduwm(26, 18, 28) + vadduwm(27, 19, 28) + + /* + * Load next data blocks. We do this early on but we + * won't need them until IV encryption is done. + */ + lxvw4x(52, %[cc0], %[buf]) + lxvw4x(53, %[cc1], %[buf]) + lxvw4x(54, %[cc2], %[buf]) + lxvw4x(55, %[cc3], %[buf]) + + /* + * Encrypt the current IV. + */ + vxor(16, 16, 0) + vxor(17, 17, 0) + vxor(18, 18, 0) + vxor(19, 19, 0) + vcipher(16, 16, 1) + vcipher(17, 17, 1) + vcipher(18, 18, 1) + vcipher(19, 19, 1) + vcipher(16, 16, 2) + vcipher(17, 17, 2) + vcipher(18, 18, 2) + vcipher(19, 19, 2) + vcipher(16, 16, 3) + vcipher(17, 17, 3) + vcipher(18, 18, 3) + vcipher(19, 19, 3) + vcipher(16, 16, 4) + vcipher(17, 17, 4) + vcipher(18, 18, 4) + vcipher(19, 19, 4) + vcipher(16, 16, 5) + vcipher(17, 17, 5) + vcipher(18, 18, 5) + vcipher(19, 19, 5) + vcipher(16, 16, 6) + vcipher(17, 17, 6) + vcipher(18, 18, 6) + vcipher(19, 19, 6) + vcipher(16, 16, 7) + vcipher(17, 17, 7) + vcipher(18, 18, 7) + vcipher(19, 19, 7) + vcipher(16, 16, 8) + vcipher(17, 17, 8) + vcipher(18, 18, 8) + vcipher(19, 19, 8) + vcipher(16, 16, 9) + vcipher(17, 17, 9) + vcipher(18, 18, 9) + vcipher(19, 19, 9) + vcipherlast(16, 16, 10) + vcipherlast(17, 17, 10) + vcipherlast(18, 18, 10) + vcipherlast(19, 19, 10) + +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + + /* + * Load next plaintext word and XOR with encrypted IV. + */ + vxor(16, 20, 16) + vxor(17, 21, 17) + vxor(18, 22, 18) + vxor(19, 23, 19) + stxvw4x(48, %[cc0], %[buf]) + stxvw4x(49, %[cc1], %[buf]) + stxvw4x(50, %[cc2], %[buf]) + stxvw4x(51, %[cc3], %[buf]) + + addi(%[buf], %[buf], 64) + + /* + * Update IV. + */ + vand(16, 24, 24) + vand(17, 25, 25) + vand(18, 26, 26) + vand(19, 27, 27) + + bdnz(loop) + +: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), + [buf] "+b" (buf) +: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2), + [ctrinc] "b" (ctrinc) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", + "ctr", "memory" + ); +} + +static void +ctr_192(const unsigned char *sk, const unsigned char *ivbuf, + unsigned char *buf, size_t num_blocks) +{ + long cc0, cc1, cc2, cc3; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + static const uint32_t ctrinc[] = { + 0, 0, 0, 4 + }; + + cc0 = 0; + cc1 = 16; + cc2 = 32; + cc3 = 48; + asm volatile ( + + /* + * Load subkeys into v0..v12 + */ + lxvw4x(32, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(33, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(34, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(35, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(36, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(37, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(38, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(39, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(40, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(41, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(42, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(43, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(44, %[cc0], %[sk]) + li(%[cc0], 0) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * v28 = increment for IV counter. + */ + lxvw4x(60, 0, %[ctrinc]) + + /* + * Load IV into v16..v19 + */ + lxvw4x(48, %[cc0], %[ivbuf]) + lxvw4x(49, %[cc1], %[ivbuf]) + lxvw4x(50, %[cc2], %[ivbuf]) + lxvw4x(51, %[cc3], %[ivbuf]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Compute next IV into v24..v27 + */ + vadduwm(24, 16, 28) + vadduwm(25, 17, 28) + vadduwm(26, 18, 28) + vadduwm(27, 19, 28) + + /* + * Load next data blocks. We do this early on but we + * won't need them until IV encryption is done. + */ + lxvw4x(52, %[cc0], %[buf]) + lxvw4x(53, %[cc1], %[buf]) + lxvw4x(54, %[cc2], %[buf]) + lxvw4x(55, %[cc3], %[buf]) + + /* + * Encrypt the current IV. + */ + vxor(16, 16, 0) + vxor(17, 17, 0) + vxor(18, 18, 0) + vxor(19, 19, 0) + vcipher(16, 16, 1) + vcipher(17, 17, 1) + vcipher(18, 18, 1) + vcipher(19, 19, 1) + vcipher(16, 16, 2) + vcipher(17, 17, 2) + vcipher(18, 18, 2) + vcipher(19, 19, 2) + vcipher(16, 16, 3) + vcipher(17, 17, 3) + vcipher(18, 18, 3) + vcipher(19, 19, 3) + vcipher(16, 16, 4) + vcipher(17, 17, 4) + vcipher(18, 18, 4) + vcipher(19, 19, 4) + vcipher(16, 16, 5) + vcipher(17, 17, 5) + vcipher(18, 18, 5) + vcipher(19, 19, 5) + vcipher(16, 16, 6) + vcipher(17, 17, 6) + vcipher(18, 18, 6) + vcipher(19, 19, 6) + vcipher(16, 16, 7) + vcipher(17, 17, 7) + vcipher(18, 18, 7) + vcipher(19, 19, 7) + vcipher(16, 16, 8) + vcipher(17, 17, 8) + vcipher(18, 18, 8) + vcipher(19, 19, 8) + vcipher(16, 16, 9) + vcipher(17, 17, 9) + vcipher(18, 18, 9) + vcipher(19, 19, 9) + vcipher(16, 16, 10) + vcipher(17, 17, 10) + vcipher(18, 18, 10) + vcipher(19, 19, 10) + vcipher(16, 16, 11) + vcipher(17, 17, 11) + vcipher(18, 18, 11) + vcipher(19, 19, 11) + vcipherlast(16, 16, 12) + vcipherlast(17, 17, 12) + vcipherlast(18, 18, 12) + vcipherlast(19, 19, 12) + +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + + /* + * Load next plaintext word and XOR with encrypted IV. + */ + vxor(16, 20, 16) + vxor(17, 21, 17) + vxor(18, 22, 18) + vxor(19, 23, 19) + stxvw4x(48, %[cc0], %[buf]) + stxvw4x(49, %[cc1], %[buf]) + stxvw4x(50, %[cc2], %[buf]) + stxvw4x(51, %[cc3], %[buf]) + + addi(%[buf], %[buf], 64) + + /* + * Update IV. + */ + vand(16, 24, 24) + vand(17, 25, 25) + vand(18, 26, 26) + vand(19, 27, 27) + + bdnz(loop) + +: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), + [buf] "+b" (buf) +: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2), + [ctrinc] "b" (ctrinc) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", + "ctr", "memory" + ); +} + +static void +ctr_256(const unsigned char *sk, const unsigned char *ivbuf, + unsigned char *buf, size_t num_blocks) +{ + long cc0, cc1, cc2, cc3; + +#if BR_POWER8_LE + static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C + }; +#endif + static const uint32_t ctrinc[] = { + 0, 0, 0, 4 + }; + + cc0 = 0; + cc1 = 16; + cc2 = 32; + cc3 = 48; + asm volatile ( + + /* + * Load subkeys into v0..v14 + */ + lxvw4x(32, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(33, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(34, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(35, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(36, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(37, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(38, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(39, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(40, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(41, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(42, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(43, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(44, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(45, %[cc0], %[sk]) + addi(%[cc0], %[cc0], 16) + lxvw4x(46, %[cc0], %[sk]) + li(%[cc0], 0) + +#if BR_POWER8_LE + /* + * v15 = constant for byteswapping words + */ + lxvw4x(47, 0, %[idx2be]) +#endif + /* + * v28 = increment for IV counter. + */ + lxvw4x(60, 0, %[ctrinc]) + + /* + * Load IV into v16..v19 + */ + lxvw4x(48, %[cc0], %[ivbuf]) + lxvw4x(49, %[cc1], %[ivbuf]) + lxvw4x(50, %[cc2], %[ivbuf]) + lxvw4x(51, %[cc3], %[ivbuf]) +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + + mtctr(%[num_blocks]) + label(loop) + /* + * Compute next IV into v24..v27 + */ + vadduwm(24, 16, 28) + vadduwm(25, 17, 28) + vadduwm(26, 18, 28) + vadduwm(27, 19, 28) + + /* + * Load next data blocks. We do this early on but we + * won't need them until IV encryption is done. + */ + lxvw4x(52, %[cc0], %[buf]) + lxvw4x(53, %[cc1], %[buf]) + lxvw4x(54, %[cc2], %[buf]) + lxvw4x(55, %[cc3], %[buf]) + + /* + * Encrypt the current IV. + */ + vxor(16, 16, 0) + vxor(17, 17, 0) + vxor(18, 18, 0) + vxor(19, 19, 0) + vcipher(16, 16, 1) + vcipher(17, 17, 1) + vcipher(18, 18, 1) + vcipher(19, 19, 1) + vcipher(16, 16, 2) + vcipher(17, 17, 2) + vcipher(18, 18, 2) + vcipher(19, 19, 2) + vcipher(16, 16, 3) + vcipher(17, 17, 3) + vcipher(18, 18, 3) + vcipher(19, 19, 3) + vcipher(16, 16, 4) + vcipher(17, 17, 4) + vcipher(18, 18, 4) + vcipher(19, 19, 4) + vcipher(16, 16, 5) + vcipher(17, 17, 5) + vcipher(18, 18, 5) + vcipher(19, 19, 5) + vcipher(16, 16, 6) + vcipher(17, 17, 6) + vcipher(18, 18, 6) + vcipher(19, 19, 6) + vcipher(16, 16, 7) + vcipher(17, 17, 7) + vcipher(18, 18, 7) + vcipher(19, 19, 7) + vcipher(16, 16, 8) + vcipher(17, 17, 8) + vcipher(18, 18, 8) + vcipher(19, 19, 8) + vcipher(16, 16, 9) + vcipher(17, 17, 9) + vcipher(18, 18, 9) + vcipher(19, 19, 9) + vcipher(16, 16, 10) + vcipher(17, 17, 10) + vcipher(18, 18, 10) + vcipher(19, 19, 10) + vcipher(16, 16, 11) + vcipher(17, 17, 11) + vcipher(18, 18, 11) + vcipher(19, 19, 11) + vcipher(16, 16, 12) + vcipher(17, 17, 12) + vcipher(18, 18, 12) + vcipher(19, 19, 12) + vcipher(16, 16, 13) + vcipher(17, 17, 13) + vcipher(18, 18, 13) + vcipher(19, 19, 13) + vcipherlast(16, 16, 14) + vcipherlast(17, 17, 14) + vcipherlast(18, 18, 14) + vcipherlast(19, 19, 14) + +#if BR_POWER8_LE + vperm(16, 16, 16, 15) + vperm(17, 17, 17, 15) + vperm(18, 18, 18, 15) + vperm(19, 19, 19, 15) +#endif + + /* + * Load next plaintext word and XOR with encrypted IV. + */ + vxor(16, 20, 16) + vxor(17, 21, 17) + vxor(18, 22, 18) + vxor(19, 23, 19) + stxvw4x(48, %[cc0], %[buf]) + stxvw4x(49, %[cc1], %[buf]) + stxvw4x(50, %[cc2], %[buf]) + stxvw4x(51, %[cc3], %[buf]) + + addi(%[buf], %[buf], 64) + + /* + * Update IV. + */ + vand(16, 24, 24) + vand(17, 25, 25) + vand(18, 26, 26) + vand(19, 27, 27) + + bdnz(loop) + +: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), + [buf] "+b" (buf) +: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2), + [ctrinc] "b" (ctrinc) +#if BR_POWER8_LE + , [idx2be] "b" (idx2be) +#endif +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", + "ctr", "memory" + ); +} + +/* see bearssl_block.h */ +uint32_t +br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + unsigned char ivbuf[64]; + + buf = data; + memcpy(ivbuf + 0, iv, 12); + memcpy(ivbuf + 16, iv, 12); + memcpy(ivbuf + 32, iv, 12); + memcpy(ivbuf + 48, iv, 12); + if (len >= 64) { + br_enc32be(ivbuf + 12, cc + 0); + br_enc32be(ivbuf + 28, cc + 1); + br_enc32be(ivbuf + 44, cc + 2); + br_enc32be(ivbuf + 60, cc + 3); + switch (ctx->num_rounds) { + case 10: + ctr_128(ctx->skey.skni, ivbuf, buf, + (len >> 4) & ~(size_t)3); + break; + case 12: + ctr_192(ctx->skey.skni, ivbuf, buf, + (len >> 4) & ~(size_t)3); + break; + default: + ctr_256(ctx->skey.skni, ivbuf, buf, + (len >> 4) & ~(size_t)3); + break; + } + cc += (len >> 4) & ~(size_t)3; + buf += len & ~(size_t)63; + len &= 63; + } + if (len > 0) { + unsigned char tmp[64]; + + memcpy(tmp, buf, len); + memset(tmp + len, 0, (sizeof tmp) - len); + br_enc32be(ivbuf + 12, cc + 0); + br_enc32be(ivbuf + 28, cc + 1); + br_enc32be(ivbuf + 44, cc + 2); + br_enc32be(ivbuf + 60, cc + 3); + switch (ctx->num_rounds) { + case 10: + ctr_128(ctx->skey.skni, ivbuf, tmp, 4); + break; + case 12: + ctr_192(ctx->skey.skni, ivbuf, tmp, 4); + break; + default: + ctr_256(ctx->skey.skni, ivbuf, tmp, 4); + break; + } + memcpy(buf, tmp, len); + cc += (len + 15) >> 4; + } + return cc; +} + +/* see bearssl_block.h */ +const br_block_ctr_class br_aes_pwr8_ctr_vtable = { + sizeof(br_aes_pwr8_ctr_keys), + 16, + 4, + (void (*)(const br_block_ctr_class **, const void *, size_t)) + &br_aes_pwr8_ctr_init, + (uint32_t (*)(const br_block_ctr_class *const *, + const void *, uint32_t, void *, size_t)) + &br_aes_pwr8_ctr_run +}; + +/* see bearssl_block.h */ +const br_block_ctr_class * +br_aes_pwr8_ctr_get_vtable(void) +{ + return br_aes_pwr8_supported() ? &br_aes_pwr8_ctr_vtable : NULL; +} + +#else + +/* see bearssl_block.h */ +const br_block_ctr_class * +br_aes_pwr8_ctr_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_ctrcbc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_ctrcbc.c new file mode 100644 index 0000000..a67d30b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_pwr8_ctrcbc.c @@ -0,0 +1,946 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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. + */ + +#define BR_POWER_ASM_MACROS 1 +#include "inner.h" + +#if BR_POWER8 + +/* see bearssl_block.h */ +const br_block_ctrcbc_class * +br_aes_pwr8_ctrcbc_get_vtable(void) +{ + return br_aes_pwr8_supported() ? &br_aes_pwr8_ctrcbc_vtable : NULL; +} + +/* see bearssl_block.h */ +void +br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_pwr8_ctrcbc_vtable; + ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len); +} + +/* + * Register conventions for CTR + CBC-MAC: + * + * AES subkeys are in registers 0 to 10/12/14 (depending on keys size) + * Register v15 contains the byteswap index register (little-endian only) + * Register v16 contains the CTR counter value + * Register v17 contains the CBC-MAC current value + * Registers v18 to v27 are scratch + * Counter increment uses v28, v29 and v30 + * + * For CTR alone: + * + * AES subkeys are in registers 0 to 10/12/14 (depending on keys size) + * Register v15 contains the byteswap index register (little-endian only) + * Registers v16 to v19 contain the CTR counter values (four blocks) + * Registers v20 to v27 are scratch + * Counter increment uses v28, v29 and v30 + */ + +#define LOAD_SUBKEYS_128 \ + lxvw4x(32, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(33, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(34, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(35, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(36, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(37, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(38, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(39, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(40, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(41, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(42, %[cc], %[sk]) + +#define LOAD_SUBKEYS_192 \ + LOAD_SUBKEYS_128 \ + addi(%[cc], %[cc], 16) \ + lxvw4x(43, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(44, %[cc], %[sk]) + +#define LOAD_SUBKEYS_256 \ + LOAD_SUBKEYS_192 \ + addi(%[cc], %[cc], 16) \ + lxvw4x(45, %[cc], %[sk]) \ + addi(%[cc], %[cc], 16) \ + lxvw4x(46, %[cc], %[sk]) + +#define BLOCK_ENCRYPT_128(x) \ + vxor(x, x, 0) \ + vcipher(x, x, 1) \ + vcipher(x, x, 2) \ + vcipher(x, x, 3) \ + vcipher(x, x, 4) \ + vcipher(x, x, 5) \ + vcipher(x, x, 6) \ + vcipher(x, x, 7) \ + vcipher(x, x, 8) \ + vcipher(x, x, 9) \ + vcipherlast(x, x, 10) + +#define BLOCK_ENCRYPT_192(x) \ + vxor(x, x, 0) \ + vcipher(x, x, 1) \ + vcipher(x, x, 2) \ + vcipher(x, x, 3) \ + vcipher(x, x, 4) \ + vcipher(x, x, 5) \ + vcipher(x, x, 6) \ + vcipher(x, x, 7) \ + vcipher(x, x, 8) \ + vcipher(x, x, 9) \ + vcipher(x, x, 10) \ + vcipher(x, x, 11) \ + vcipherlast(x, x, 12) + +#define BLOCK_ENCRYPT_256(x) \ + vxor(x, x, 0) \ + vcipher(x, x, 1) \ + vcipher(x, x, 2) \ + vcipher(x, x, 3) \ + vcipher(x, x, 4) \ + vcipher(x, x, 5) \ + vcipher(x, x, 6) \ + vcipher(x, x, 7) \ + vcipher(x, x, 8) \ + vcipher(x, x, 9) \ + vcipher(x, x, 10) \ + vcipher(x, x, 11) \ + vcipher(x, x, 12) \ + vcipher(x, x, 13) \ + vcipherlast(x, x, 14) + +#define BLOCK_ENCRYPT_X2_128(x, y) \ + vxor(x, x, 0) \ + vxor(y, y, 0) \ + vcipher(x, x, 1) \ + vcipher(y, y, 1) \ + vcipher(x, x, 2) \ + vcipher(y, y, 2) \ + vcipher(x, x, 3) \ + vcipher(y, y, 3) \ + vcipher(x, x, 4) \ + vcipher(y, y, 4) \ + vcipher(x, x, 5) \ + vcipher(y, y, 5) \ + vcipher(x, x, 6) \ + vcipher(y, y, 6) \ + vcipher(x, x, 7) \ + vcipher(y, y, 7) \ + vcipher(x, x, 8) \ + vcipher(y, y, 8) \ + vcipher(x, x, 9) \ + vcipher(y, y, 9) \ + vcipherlast(x, x, 10) \ + vcipherlast(y, y, 10) + +#define BLOCK_ENCRYPT_X2_192(x, y) \ + vxor(x, x, 0) \ + vxor(y, y, 0) \ + vcipher(x, x, 1) \ + vcipher(y, y, 1) \ + vcipher(x, x, 2) \ + vcipher(y, y, 2) \ + vcipher(x, x, 3) \ + vcipher(y, y, 3) \ + vcipher(x, x, 4) \ + vcipher(y, y, 4) \ + vcipher(x, x, 5) \ + vcipher(y, y, 5) \ + vcipher(x, x, 6) \ + vcipher(y, y, 6) \ + vcipher(x, x, 7) \ + vcipher(y, y, 7) \ + vcipher(x, x, 8) \ + vcipher(y, y, 8) \ + vcipher(x, x, 9) \ + vcipher(y, y, 9) \ + vcipher(x, x, 10) \ + vcipher(y, y, 10) \ + vcipher(x, x, 11) \ + vcipher(y, y, 11) \ + vcipherlast(x, x, 12) \ + vcipherlast(y, y, 12) + +#define BLOCK_ENCRYPT_X2_256(x, y) \ + vxor(x, x, 0) \ + vxor(y, y, 0) \ + vcipher(x, x, 1) \ + vcipher(y, y, 1) \ + vcipher(x, x, 2) \ + vcipher(y, y, 2) \ + vcipher(x, x, 3) \ + vcipher(y, y, 3) \ + vcipher(x, x, 4) \ + vcipher(y, y, 4) \ + vcipher(x, x, 5) \ + vcipher(y, y, 5) \ + vcipher(x, x, 6) \ + vcipher(y, y, 6) \ + vcipher(x, x, 7) \ + vcipher(y, y, 7) \ + vcipher(x, x, 8) \ + vcipher(y, y, 8) \ + vcipher(x, x, 9) \ + vcipher(y, y, 9) \ + vcipher(x, x, 10) \ + vcipher(y, y, 10) \ + vcipher(x, x, 11) \ + vcipher(y, y, 11) \ + vcipher(x, x, 12) \ + vcipher(y, y, 12) \ + vcipher(x, x, 13) \ + vcipher(y, y, 13) \ + vcipherlast(x, x, 14) \ + vcipherlast(y, y, 14) + +#define BLOCK_ENCRYPT_X4_128(x0, x1, x2, x3) \ + vxor(x0, x0, 0) \ + vxor(x1, x1, 0) \ + vxor(x2, x2, 0) \ + vxor(x3, x3, 0) \ + vcipher(x0, x0, 1) \ + vcipher(x1, x1, 1) \ + vcipher(x2, x2, 1) \ + vcipher(x3, x3, 1) \ + vcipher(x0, x0, 2) \ + vcipher(x1, x1, 2) \ + vcipher(x2, x2, 2) \ + vcipher(x3, x3, 2) \ + vcipher(x0, x0, 3) \ + vcipher(x1, x1, 3) \ + vcipher(x2, x2, 3) \ + vcipher(x3, x3, 3) \ + vcipher(x0, x0, 4) \ + vcipher(x1, x1, 4) \ + vcipher(x2, x2, 4) \ + vcipher(x3, x3, 4) \ + vcipher(x0, x0, 5) \ + vcipher(x1, x1, 5) \ + vcipher(x2, x2, 5) \ + vcipher(x3, x3, 5) \ + vcipher(x0, x0, 6) \ + vcipher(x1, x1, 6) \ + vcipher(x2, x2, 6) \ + vcipher(x3, x3, 6) \ + vcipher(x0, x0, 7) \ + vcipher(x1, x1, 7) \ + vcipher(x2, x2, 7) \ + vcipher(x3, x3, 7) \ + vcipher(x0, x0, 8) \ + vcipher(x1, x1, 8) \ + vcipher(x2, x2, 8) \ + vcipher(x3, x3, 8) \ + vcipher(x0, x0, 9) \ + vcipher(x1, x1, 9) \ + vcipher(x2, x2, 9) \ + vcipher(x3, x3, 9) \ + vcipherlast(x0, x0, 10) \ + vcipherlast(x1, x1, 10) \ + vcipherlast(x2, x2, 10) \ + vcipherlast(x3, x3, 10) + +#define BLOCK_ENCRYPT_X4_192(x0, x1, x2, x3) \ + vxor(x0, x0, 0) \ + vxor(x1, x1, 0) \ + vxor(x2, x2, 0) \ + vxor(x3, x3, 0) \ + vcipher(x0, x0, 1) \ + vcipher(x1, x1, 1) \ + vcipher(x2, x2, 1) \ + vcipher(x3, x3, 1) \ + vcipher(x0, x0, 2) \ + vcipher(x1, x1, 2) \ + vcipher(x2, x2, 2) \ + vcipher(x3, x3, 2) \ + vcipher(x0, x0, 3) \ + vcipher(x1, x1, 3) \ + vcipher(x2, x2, 3) \ + vcipher(x3, x3, 3) \ + vcipher(x0, x0, 4) \ + vcipher(x1, x1, 4) \ + vcipher(x2, x2, 4) \ + vcipher(x3, x3, 4) \ + vcipher(x0, x0, 5) \ + vcipher(x1, x1, 5) \ + vcipher(x2, x2, 5) \ + vcipher(x3, x3, 5) \ + vcipher(x0, x0, 6) \ + vcipher(x1, x1, 6) \ + vcipher(x2, x2, 6) \ + vcipher(x3, x3, 6) \ + vcipher(x0, x0, 7) \ + vcipher(x1, x1, 7) \ + vcipher(x2, x2, 7) \ + vcipher(x3, x3, 7) \ + vcipher(x0, x0, 8) \ + vcipher(x1, x1, 8) \ + vcipher(x2, x2, 8) \ + vcipher(x3, x3, 8) \ + vcipher(x0, x0, 9) \ + vcipher(x1, x1, 9) \ + vcipher(x2, x2, 9) \ + vcipher(x3, x3, 9) \ + vcipher(x0, x0, 10) \ + vcipher(x1, x1, 10) \ + vcipher(x2, x2, 10) \ + vcipher(x3, x3, 10) \ + vcipher(x0, x0, 11) \ + vcipher(x1, x1, 11) \ + vcipher(x2, x2, 11) \ + vcipher(x3, x3, 11) \ + vcipherlast(x0, x0, 12) \ + vcipherlast(x1, x1, 12) \ + vcipherlast(x2, x2, 12) \ + vcipherlast(x3, x3, 12) + +#define BLOCK_ENCRYPT_X4_256(x0, x1, x2, x3) \ + vxor(x0, x0, 0) \ + vxor(x1, x1, 0) \ + vxor(x2, x2, 0) \ + vxor(x3, x3, 0) \ + vcipher(x0, x0, 1) \ + vcipher(x1, x1, 1) \ + vcipher(x2, x2, 1) \ + vcipher(x3, x3, 1) \ + vcipher(x0, x0, 2) \ + vcipher(x1, x1, 2) \ + vcipher(x2, x2, 2) \ + vcipher(x3, x3, 2) \ + vcipher(x0, x0, 3) \ + vcipher(x1, x1, 3) \ + vcipher(x2, x2, 3) \ + vcipher(x3, x3, 3) \ + vcipher(x0, x0, 4) \ + vcipher(x1, x1, 4) \ + vcipher(x2, x2, 4) \ + vcipher(x3, x3, 4) \ + vcipher(x0, x0, 5) \ + vcipher(x1, x1, 5) \ + vcipher(x2, x2, 5) \ + vcipher(x3, x3, 5) \ + vcipher(x0, x0, 6) \ + vcipher(x1, x1, 6) \ + vcipher(x2, x2, 6) \ + vcipher(x3, x3, 6) \ + vcipher(x0, x0, 7) \ + vcipher(x1, x1, 7) \ + vcipher(x2, x2, 7) \ + vcipher(x3, x3, 7) \ + vcipher(x0, x0, 8) \ + vcipher(x1, x1, 8) \ + vcipher(x2, x2, 8) \ + vcipher(x3, x3, 8) \ + vcipher(x0, x0, 9) \ + vcipher(x1, x1, 9) \ + vcipher(x2, x2, 9) \ + vcipher(x3, x3, 9) \ + vcipher(x0, x0, 10) \ + vcipher(x1, x1, 10) \ + vcipher(x2, x2, 10) \ + vcipher(x3, x3, 10) \ + vcipher(x0, x0, 11) \ + vcipher(x1, x1, 11) \ + vcipher(x2, x2, 11) \ + vcipher(x3, x3, 11) \ + vcipher(x0, x0, 12) \ + vcipher(x1, x1, 12) \ + vcipher(x2, x2, 12) \ + vcipher(x3, x3, 12) \ + vcipher(x0, x0, 13) \ + vcipher(x1, x1, 13) \ + vcipher(x2, x2, 13) \ + vcipher(x3, x3, 13) \ + vcipherlast(x0, x0, 14) \ + vcipherlast(x1, x1, 14) \ + vcipherlast(x2, x2, 14) \ + vcipherlast(x3, x3, 14) + +#if BR_POWER8_LE +static const uint32_t idx2be[] = { + 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C +}; +#define BYTESWAP_INIT lxvw4x(47, 0, %[idx2be]) +#define BYTESWAP(x) vperm(x, x, x, 15) +#define BYTESWAPX(d, s) vperm(d, s, s, 15) +#define BYTESWAP_REG , [idx2be] "b" (idx2be) +#else +#define BYTESWAP_INIT +#define BYTESWAP(x) +#define BYTESWAPX(d, s) vand(d, s, s) +#define BYTESWAP_REG +#endif + +static const uint32_t ctrinc[] = { + 0, 0, 0, 1 +}; +static const uint32_t ctrinc_x4[] = { + 0, 0, 0, 4 +}; +#define INCR_128_INIT lxvw4x(60, 0, %[ctrinc]) +#define INCR_128_X4_INIT lxvw4x(60, 0, %[ctrinc_x4]) +#define INCR_128(d, s) \ + vaddcuw(29, s, 28) \ + vadduwm(d, s, 28) \ + vsldoi(30, 29, 29, 4) \ + vaddcuw(29, d, 30) \ + vadduwm(d, d, 30) \ + vsldoi(30, 29, 29, 4) \ + vaddcuw(29, d, 30) \ + vadduwm(d, d, 30) \ + vsldoi(30, 29, 29, 4) \ + vadduwm(d, d, 30) + +#define MKCTR(size) \ +static void \ +ctr_ ## size(const unsigned char *sk, \ + unsigned char *ctrbuf, unsigned char *buf, size_t num_blocks_x4) \ +{ \ + long cc, cc0, cc1, cc2, cc3; \ + \ + cc = 0; \ + cc0 = 0; \ + cc1 = 16; \ + cc2 = 32; \ + cc3 = 48; \ + asm volatile ( \ + \ + /* \ + * Load subkeys into v0..v10 \ + */ \ + LOAD_SUBKEYS_ ## size \ + li(%[cc], 0) \ + \ + BYTESWAP_INIT \ + INCR_128_X4_INIT \ + \ + /* \ + * Load current CTR counters into v16 to v19. \ + */ \ + lxvw4x(48, %[cc0], %[ctrbuf]) \ + lxvw4x(49, %[cc1], %[ctrbuf]) \ + lxvw4x(50, %[cc2], %[ctrbuf]) \ + lxvw4x(51, %[cc3], %[ctrbuf]) \ + BYTESWAP(16) \ + BYTESWAP(17) \ + BYTESWAP(18) \ + BYTESWAP(19) \ + \ + mtctr(%[num_blocks_x4]) \ + \ + label(loop) \ + /* \ + * Compute next counter values into v20..v23. \ + */ \ + INCR_128(20, 16) \ + INCR_128(21, 17) \ + INCR_128(22, 18) \ + INCR_128(23, 19) \ + \ + /* \ + * Encrypt counter values and XOR into next data blocks. \ + */ \ + lxvw4x(56, %[cc0], %[buf]) \ + lxvw4x(57, %[cc1], %[buf]) \ + lxvw4x(58, %[cc2], %[buf]) \ + lxvw4x(59, %[cc3], %[buf]) \ + BYTESWAP(24) \ + BYTESWAP(25) \ + BYTESWAP(26) \ + BYTESWAP(27) \ + BLOCK_ENCRYPT_X4_ ## size(16, 17, 18, 19) \ + vxor(16, 16, 24) \ + vxor(17, 17, 25) \ + vxor(18, 18, 26) \ + vxor(19, 19, 27) \ + BYTESWAP(16) \ + BYTESWAP(17) \ + BYTESWAP(18) \ + BYTESWAP(19) \ + stxvw4x(48, %[cc0], %[buf]) \ + stxvw4x(49, %[cc1], %[buf]) \ + stxvw4x(50, %[cc2], %[buf]) \ + stxvw4x(51, %[cc3], %[buf]) \ + \ + /* \ + * Update counters and data pointer. \ + */ \ + vand(16, 20, 20) \ + vand(17, 21, 21) \ + vand(18, 22, 22) \ + vand(19, 23, 23) \ + addi(%[buf], %[buf], 64) \ + \ + bdnz(loop) \ + \ + /* \ + * Write back new counter values. \ + */ \ + BYTESWAP(16) \ + BYTESWAP(17) \ + BYTESWAP(18) \ + BYTESWAP(19) \ + stxvw4x(48, %[cc0], %[ctrbuf]) \ + stxvw4x(49, %[cc1], %[ctrbuf]) \ + stxvw4x(50, %[cc2], %[ctrbuf]) \ + stxvw4x(51, %[cc3], %[ctrbuf]) \ + \ +: [cc] "+b" (cc), [buf] "+b" (buf), \ + [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3) \ +: [sk] "b" (sk), [ctrbuf] "b" (ctrbuf), \ + [num_blocks_x4] "b" (num_blocks_x4), [ctrinc_x4] "b" (ctrinc_x4) \ + BYTESWAP_REG \ +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \ + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \ + "v30", "ctr", "memory" \ + ); \ +} + +MKCTR(128) +MKCTR(192) +MKCTR(256) + +#define MKCBCMAC(size) \ +static void \ +cbcmac_ ## size(const unsigned char *sk, \ + unsigned char *cbcmac, const unsigned char *buf, size_t num_blocks) \ +{ \ + long cc; \ + \ + cc = 0; \ + asm volatile ( \ + \ + /* \ + * Load subkeys into v0..v10 \ + */ \ + LOAD_SUBKEYS_ ## size \ + li(%[cc], 0) \ + \ + BYTESWAP_INIT \ + \ + /* \ + * Load current CBC-MAC value into v16. \ + */ \ + lxvw4x(48, %[cc], %[cbcmac]) \ + BYTESWAP(16) \ + \ + mtctr(%[num_blocks]) \ + \ + label(loop) \ + /* \ + * Load next block, XOR into current CBC-MAC value, \ + * and then encrypt it. \ + */ \ + lxvw4x(49, %[cc], %[buf]) \ + BYTESWAP(17) \ + vxor(16, 16, 17) \ + BLOCK_ENCRYPT_ ## size(16) \ + addi(%[buf], %[buf], 16) \ + \ + bdnz(loop) \ + \ + /* \ + * Write back new CBC-MAC value. \ + */ \ + BYTESWAP(16) \ + stxvw4x(48, %[cc], %[cbcmac]) \ + \ +: [cc] "+b" (cc), [buf] "+b" (buf) \ +: [sk] "b" (sk), [cbcmac] "b" (cbcmac), [num_blocks] "b" (num_blocks) \ + BYTESWAP_REG \ +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \ + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \ + "v30", "ctr", "memory" \ + ); \ +} + +MKCBCMAC(128) +MKCBCMAC(192) +MKCBCMAC(256) + +#define MKENCRYPT(size) \ +static void \ +ctrcbc_ ## size ## _encrypt(const unsigned char *sk, \ + unsigned char *ctr, unsigned char *cbcmac, unsigned char *buf, \ + size_t num_blocks) \ +{ \ + long cc; \ + \ + cc = 0; \ + asm volatile ( \ + \ + /* \ + * Load subkeys into v0..v10 \ + */ \ + LOAD_SUBKEYS_ ## size \ + li(%[cc], 0) \ + \ + BYTESWAP_INIT \ + INCR_128_INIT \ + \ + /* \ + * Load current CTR counter into v16, and current \ + * CBC-MAC IV into v17. \ + */ \ + lxvw4x(48, %[cc], %[ctr]) \ + lxvw4x(49, %[cc], %[cbcmac]) \ + BYTESWAP(16) \ + BYTESWAP(17) \ + \ + /* \ + * At each iteration, we do two parallel encryption: \ + * - new counter value for encryption of the next block; \ + * - CBC-MAC over the previous encrypted block. \ + * Thus, each plaintext block implies two AES instances, \ + * over two successive iterations. This requires a single \ + * counter encryption before the loop, and a single \ + * CBC-MAC encryption after the loop. \ + */ \ + \ + /* \ + * Encrypt first block (into v20). \ + */ \ + lxvw4x(52, %[cc], %[buf]) \ + BYTESWAP(20) \ + INCR_128(22, 16) \ + BLOCK_ENCRYPT_ ## size(16) \ + vxor(20, 20, 16) \ + BYTESWAPX(21, 20) \ + stxvw4x(53, %[cc], %[buf]) \ + vand(16, 22, 22) \ + addi(%[buf], %[buf], 16) \ + \ + /* \ + * Load loop counter; skip the loop if there is only \ + * one block in total (already handled by the boundary \ + * conditions). \ + */ \ + mtctr(%[num_blocks]) \ + bdz(fastexit) \ + \ + label(loop) \ + /* \ + * Upon loop entry: \ + * v16 counter value for next block \ + * v17 current CBC-MAC value \ + * v20 encrypted previous block \ + */ \ + vxor(17, 17, 20) \ + INCR_128(22, 16) \ + lxvw4x(52, %[cc], %[buf]) \ + BYTESWAP(20) \ + BLOCK_ENCRYPT_X2_ ## size(16, 17) \ + vxor(20, 20, 16) \ + BYTESWAPX(21, 20) \ + stxvw4x(53, %[cc], %[buf]) \ + addi(%[buf], %[buf], 16) \ + vand(16, 22, 22) \ + \ + bdnz(loop) \ + \ + label(fastexit) \ + vxor(17, 17, 20) \ + BLOCK_ENCRYPT_ ## size(17) \ + BYTESWAP(16) \ + BYTESWAP(17) \ + stxvw4x(48, %[cc], %[ctr]) \ + stxvw4x(49, %[cc], %[cbcmac]) \ + \ +: [cc] "+b" (cc), [buf] "+b" (buf) \ +: [sk] "b" (sk), [ctr] "b" (ctr), [cbcmac] "b" (cbcmac), \ + [num_blocks] "b" (num_blocks), [ctrinc] "b" (ctrinc) \ + BYTESWAP_REG \ +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \ + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \ + "v30", "ctr", "memory" \ + ); \ +} + +MKENCRYPT(128) +MKENCRYPT(192) +MKENCRYPT(256) + +#define MKDECRYPT(size) \ +static void \ +ctrcbc_ ## size ## _decrypt(const unsigned char *sk, \ + unsigned char *ctr, unsigned char *cbcmac, unsigned char *buf, \ + size_t num_blocks) \ +{ \ + long cc; \ + \ + cc = 0; \ + asm volatile ( \ + \ + /* \ + * Load subkeys into v0..v10 \ + */ \ + LOAD_SUBKEYS_ ## size \ + li(%[cc], 0) \ + \ + BYTESWAP_INIT \ + INCR_128_INIT \ + \ + /* \ + * Load current CTR counter into v16, and current \ + * CBC-MAC IV into v17. \ + */ \ + lxvw4x(48, %[cc], %[ctr]) \ + lxvw4x(49, %[cc], %[cbcmac]) \ + BYTESWAP(16) \ + BYTESWAP(17) \ + \ + /* \ + * At each iteration, we do two parallel encryption: \ + * - new counter value for decryption of the next block; \ + * - CBC-MAC over the next encrypted block. \ + * Each iteration performs the two AES instances related \ + * to the current block; there is thus no need for some \ + * extra pre-loop and post-loop work as in encryption. \ + */ \ + \ + mtctr(%[num_blocks]) \ + \ + label(loop) \ + /* \ + * Upon loop entry: \ + * v16 counter value for next block \ + * v17 current CBC-MAC value \ + */ \ + lxvw4x(52, %[cc], %[buf]) \ + BYTESWAP(20) \ + vxor(17, 17, 20) \ + INCR_128(22, 16) \ + BLOCK_ENCRYPT_X2_ ## size(16, 17) \ + vxor(20, 20, 16) \ + BYTESWAPX(21, 20) \ + stxvw4x(53, %[cc], %[buf]) \ + addi(%[buf], %[buf], 16) \ + vand(16, 22, 22) \ + \ + bdnz(loop) \ + \ + /* \ + * Store back counter and CBC-MAC value. \ + */ \ + BYTESWAP(16) \ + BYTESWAP(17) \ + stxvw4x(48, %[cc], %[ctr]) \ + stxvw4x(49, %[cc], %[cbcmac]) \ + \ +: [cc] "+b" (cc), [buf] "+b" (buf) \ +: [sk] "b" (sk), [ctr] "b" (ctr), [cbcmac] "b" (cbcmac), \ + [num_blocks] "b" (num_blocks), [ctrinc] "b" (ctrinc) \ + BYTESWAP_REG \ +: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \ + "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \ + "v30", "ctr", "memory" \ + ); \ +} + +MKDECRYPT(128) +MKDECRYPT(192) +MKDECRYPT(256) + +/* see bearssl_block.h */ +void +br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + if (len == 0) { + return; + } + switch (ctx->num_rounds) { + case 10: + ctrcbc_128_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); + break; + case 12: + ctrcbc_192_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); + break; + default: + ctrcbc_256_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); + break; + } +} + +/* see bearssl_block.h */ +void +br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + if (len == 0) { + return; + } + switch (ctx->num_rounds) { + case 10: + ctrcbc_128_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); + break; + case 12: + ctrcbc_192_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); + break; + default: + ctrcbc_256_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); + break; + } +} + +static inline void +incr_ctr(void *dst, const void *src) +{ + uint64_t hi, lo; + + hi = br_dec64be(src); + lo = br_dec64be((const unsigned char *)src + 8); + lo ++; + hi += ((lo | -lo) >> 63) ^ (uint64_t)1; + br_enc64be(dst, hi); + br_enc64be((unsigned char *)dst + 8, lo); +} + +/* see bearssl_block.h */ +void +br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len) +{ + unsigned char ctrbuf[64]; + + memcpy(ctrbuf, ctr, 16); + incr_ctr(ctrbuf + 16, ctrbuf); + incr_ctr(ctrbuf + 32, ctrbuf + 16); + incr_ctr(ctrbuf + 48, ctrbuf + 32); + if (len >= 64) { + switch (ctx->num_rounds) { + case 10: + ctr_128(ctx->skey.skni, ctrbuf, data, len >> 6); + break; + case 12: + ctr_192(ctx->skey.skni, ctrbuf, data, len >> 6); + break; + default: + ctr_256(ctx->skey.skni, ctrbuf, data, len >> 6); + break; + } + data = (unsigned char *)data + (len & ~(size_t)63); + len &= 63; + } + if (len > 0) { + unsigned char tmp[64]; + + if (len >= 32) { + if (len >= 48) { + memcpy(ctr, ctrbuf + 48, 16); + } else { + memcpy(ctr, ctrbuf + 32, 16); + } + } else { + if (len >= 16) { + memcpy(ctr, ctrbuf + 16, 16); + } + } + memcpy(tmp, data, len); + memset(tmp + len, 0, (sizeof tmp) - len); + switch (ctx->num_rounds) { + case 10: + ctr_128(ctx->skey.skni, ctrbuf, tmp, 1); + break; + case 12: + ctr_192(ctx->skey.skni, ctrbuf, tmp, 1); + break; + default: + ctr_256(ctx->skey.skni, ctrbuf, tmp, 1); + break; + } + memcpy(data, tmp, len); + } else { + memcpy(ctr, ctrbuf, 16); + } +} + +/* see bearssl_block.h */ +void +br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len) +{ + if (len > 0) { + switch (ctx->num_rounds) { + case 10: + cbcmac_128(ctx->skey.skni, cbcmac, data, len >> 4); + break; + case 12: + cbcmac_192(ctx->skey.skni, cbcmac, data, len >> 4); + break; + default: + cbcmac_256(ctx->skey.skni, cbcmac, data, len >> 4); + break; + } + } +} + +/* see bearssl_block.h */ +const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable = { + sizeof(br_aes_pwr8_ctrcbc_keys), + 16, + 4, + (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) + &br_aes_pwr8_ctrcbc_init, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_pwr8_ctrcbc_encrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_pwr8_ctrcbc_decrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, size_t)) + &br_aes_pwr8_ctrcbc_ctr, + (void (*)(const br_block_ctrcbc_class *const *, + void *, const void *, size_t)) + &br_aes_pwr8_ctrcbc_mac +}; + +#else + +/* see bearssl_block.h */ +const br_block_ctrcbc_class * +br_aes_pwr8_ctrcbc_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_small_cbcdec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_small_cbcdec.c new file mode 100644 index 0000000..8567244 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_small_cbcdec.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_small_cbcdec_vtable; + ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + + ivbuf = iv; + buf = data; + while (len > 0) { + unsigned char tmp[16]; + int i; + + memcpy(tmp, buf, 16); + br_aes_small_decrypt(ctx->num_rounds, ctx->skey, buf); + for (i = 0; i < 16; i ++) { + buf[i] ^= ivbuf[i]; + } + memcpy(ivbuf, tmp, 16); + buf += 16; + len -= 16; + } +} + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_aes_small_cbcdec_vtable = { + sizeof(br_aes_small_cbcdec_keys), + 16, + 4, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_aes_small_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_aes_small_cbcdec_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_small_cbcenc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_small_cbcenc.c new file mode 100644 index 0000000..0dc2910 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_small_cbcenc.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_small_cbcenc_vtable; + ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + + ivbuf = iv; + buf = data; + while (len > 0) { + int i; + + for (i = 0; i < 16; i ++) { + buf[i] ^= ivbuf[i]; + } + br_aes_small_encrypt(ctx->num_rounds, ctx->skey, buf); + memcpy(ivbuf, buf, 16); + buf += 16; + len -= 16; + } +} + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_aes_small_cbcenc_vtable = { + sizeof(br_aes_small_cbcenc_keys), + 16, + 4, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_aes_small_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_aes_small_cbcenc_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_small_ctr.c b/BearSSL-OG/libbearssl/src/symcipher/aes_small_ctr.c new file mode 100644 index 0000000..d5d371c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_small_ctr.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_small_ctr_vtable; + ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); +} + +static void +xorbuf(void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + *d ++ ^= *s ++; + } +} + +/* see bearssl_block.h */ +uint32_t +br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + + buf = data; + while (len > 0) { + unsigned char tmp[16]; + + memcpy(tmp, iv, 12); + br_enc32be(tmp + 12, cc ++); + br_aes_small_encrypt(ctx->num_rounds, ctx->skey, tmp); + if (len <= 16) { + xorbuf(buf, tmp, len); + break; + } + xorbuf(buf, tmp, 16); + buf += 16; + len -= 16; + } + return cc; +} + +/* see bearssl_block.h */ +const br_block_ctr_class br_aes_small_ctr_vtable = { + sizeof(br_aes_small_ctr_keys), + 16, + 4, + (void (*)(const br_block_ctr_class **, const void *, size_t)) + &br_aes_small_ctr_init, + (uint32_t (*)(const br_block_ctr_class *const *, + const void *, uint32_t, void *, size_t)) + &br_aes_small_ctr_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_small_ctrcbc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_small_ctrcbc.c new file mode 100644 index 0000000..2d6ba32 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_small_ctrcbc.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_small_ctrcbc_vtable; + ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); +} + +static void +xorbuf(void *dst, const void *src, size_t len) +{ + unsigned char *d; + const unsigned char *s; + + d = dst; + s = src; + while (len -- > 0) { + *d ++ ^= *s ++; + } +} + +/* see bearssl_block.h */ +void +br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len) +{ + unsigned char *buf, *bctr; + uint32_t cc0, cc1, cc2, cc3; + + buf = data; + bctr = ctr; + cc3 = br_dec32be(bctr + 0); + cc2 = br_dec32be(bctr + 4); + cc1 = br_dec32be(bctr + 8); + cc0 = br_dec32be(bctr + 12); + while (len > 0) { + unsigned char tmp[16]; + uint32_t carry; + + br_enc32be(tmp + 0, cc3); + br_enc32be(tmp + 4, cc2); + br_enc32be(tmp + 8, cc1); + br_enc32be(tmp + 12, cc0); + br_aes_small_encrypt(ctx->num_rounds, ctx->skey, tmp); + xorbuf(buf, tmp, 16); + buf += 16; + len -= 16; + cc0 ++; + carry = (~(cc0 | -cc0)) >> 31; + cc1 += carry; + carry &= (~(cc1 | -cc1)) >> 31; + cc2 += carry; + carry &= (~(cc2 | -cc2)) >> 31; + cc3 += carry; + } + br_enc32be(bctr + 0, cc3); + br_enc32be(bctr + 4, cc2); + br_enc32be(bctr + 8, cc1); + br_enc32be(bctr + 12, cc0); +} + +/* see bearssl_block.h */ +void +br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len) +{ + const unsigned char *buf; + + buf = data; + while (len > 0) { + xorbuf(cbcmac, buf, 16); + br_aes_small_encrypt(ctx->num_rounds, ctx->skey, cbcmac); + buf += 16; + len -= 16; + } +} + +/* see bearssl_block.h */ +void +br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + br_aes_small_ctrcbc_ctr(ctx, ctr, data, len); + br_aes_small_ctrcbc_mac(ctx, cbcmac, data, len); +} + +/* see bearssl_block.h */ +void +br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + br_aes_small_ctrcbc_mac(ctx, cbcmac, data, len); + br_aes_small_ctrcbc_ctr(ctx, ctr, data, len); +} + +/* see bearssl_block.h */ +const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable = { + sizeof(br_aes_small_ctrcbc_keys), + 16, + 4, + (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) + &br_aes_small_ctrcbc_init, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_small_ctrcbc_encrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_small_ctrcbc_decrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, size_t)) + &br_aes_small_ctrcbc_ctr, + (void (*)(const br_block_ctrcbc_class *const *, + void *, const void *, size_t)) + &br_aes_small_ctrcbc_mac +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_small_dec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_small_dec.c new file mode 100644 index 0000000..610ff13 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_small_dec.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * Inverse S-box. + */ +static const unsigned char iS[] = { + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, + 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, + 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, + 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, + 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, + 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, + 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, + 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, + 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, + 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0C, 0x7D +}; + +static void +add_round_key(unsigned *state, const uint32_t *skeys) +{ + int i; + + for (i = 0; i < 16; i += 4) { + uint32_t k; + + k = *skeys ++; + state[i + 0] ^= (unsigned)(k >> 24); + state[i + 1] ^= (unsigned)(k >> 16) & 0xFF; + state[i + 2] ^= (unsigned)(k >> 8) & 0xFF; + state[i + 3] ^= (unsigned)k & 0xFF; + } +} + +static void +inv_sub_bytes(unsigned *state) +{ + int i; + + for (i = 0; i < 16; i ++) { + state[i] = iS[state[i]]; + } +} + +static void +inv_shift_rows(unsigned *state) +{ + unsigned tmp; + + tmp = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = tmp; + + tmp = state[2]; + state[2] = state[10]; + state[10] = tmp; + tmp = state[6]; + state[6] = state[14]; + state[14] = tmp; + + tmp = state[3]; + state[3] = state[7]; + state[7] = state[11]; + state[11] = state[15]; + state[15] = tmp; +} + +static __inline unsigned +gf256red(unsigned x) +{ + unsigned y; + + y = x >> 8; + return (x ^ y ^ (y << 1) ^ (y << 3) ^ (y << 4)) & 0xFF; +} + +static void +inv_mix_columns(unsigned *state) +{ + int i; + + for (i = 0; i < 16; i += 4) { + unsigned s0, s1, s2, s3; + unsigned t0, t1, t2, t3; + + s0 = state[i + 0]; + s1 = state[i + 1]; + s2 = state[i + 2]; + s3 = state[i + 3]; + t0 = (s0 << 1) ^ (s0 << 2) ^ (s0 << 3) + ^ s1 ^ (s1 << 1) ^ (s1 << 3) + ^ s2 ^ (s2 << 2) ^ (s2 << 3) + ^ s3 ^ (s3 << 3); + t1 = s0 ^ (s0 << 3) + ^ (s1 << 1) ^ (s1 << 2) ^ (s1 << 3) + ^ s2 ^ (s2 << 1) ^ (s2 << 3) + ^ s3 ^ (s3 << 2) ^ (s3 << 3); + t2 = s0 ^ (s0 << 2) ^ (s0 << 3) + ^ s1 ^ (s1 << 3) + ^ (s2 << 1) ^ (s2 << 2) ^ (s2 << 3) + ^ s3 ^ (s3 << 1) ^ (s3 << 3); + t3 = s0 ^ (s0 << 1) ^ (s0 << 3) + ^ s1 ^ (s1 << 2) ^ (s1 << 3) + ^ s2 ^ (s2 << 3) + ^ (s3 << 1) ^ (s3 << 2) ^ (s3 << 3); + state[i + 0] = gf256red(t0); + state[i + 1] = gf256red(t1); + state[i + 2] = gf256red(t2); + state[i + 3] = gf256red(t3); + } +} + +/* see inner.h */ +void +br_aes_small_decrypt(unsigned num_rounds, const uint32_t *skey, void *data) +{ + unsigned char *buf; + unsigned state[16]; + unsigned u; + + buf = data; + for (u = 0; u < 16; u ++) { + state[u] = buf[u]; + } + add_round_key(state, skey + (num_rounds << 2)); + for (u = num_rounds - 1; u > 0; u --) { + inv_shift_rows(state); + inv_sub_bytes(state); + add_round_key(state, skey + (u << 2)); + inv_mix_columns(state); + } + inv_shift_rows(state); + inv_sub_bytes(state); + add_round_key(state, skey); + for (u = 0; u < 16; u ++) { + buf[u] = state[u]; + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_small_enc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_small_enc.c new file mode 100644 index 0000000..29f48a8 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_small_enc.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +#define S br_aes_S + +static void +add_round_key(unsigned *state, const uint32_t *skeys) +{ + int i; + + for (i = 0; i < 16; i += 4) { + uint32_t k; + + k = *skeys ++; + state[i + 0] ^= (unsigned)(k >> 24); + state[i + 1] ^= (unsigned)(k >> 16) & 0xFF; + state[i + 2] ^= (unsigned)(k >> 8) & 0xFF; + state[i + 3] ^= (unsigned)k & 0xFF; + } +} + +static void +sub_bytes(unsigned *state) +{ + int i; + + for (i = 0; i < 16; i ++) { + state[i] = S[state[i]]; + } +} + +static void +shift_rows(unsigned *state) +{ + unsigned tmp; + + tmp = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = tmp; + + tmp = state[2]; + state[2] = state[10]; + state[10] = tmp; + tmp = state[6]; + state[6] = state[14]; + state[14] = tmp; + + tmp = state[15]; + state[15] = state[11]; + state[11] = state[7]; + state[7] = state[3]; + state[3] = tmp; +} + +static void +mix_columns(unsigned *state) +{ + int i; + + for (i = 0; i < 16; i += 4) { + unsigned s0, s1, s2, s3; + unsigned t0, t1, t2, t3; + + s0 = state[i + 0]; + s1 = state[i + 1]; + s2 = state[i + 2]; + s3 = state[i + 3]; + t0 = (s0 << 1) ^ s1 ^ (s1 << 1) ^ s2 ^ s3; + t1 = s0 ^ (s1 << 1) ^ s2 ^ (s2 << 1) ^ s3; + t2 = s0 ^ s1 ^ (s2 << 1) ^ s3 ^ (s3 << 1); + t3 = s0 ^ (s0 << 1) ^ s1 ^ s2 ^ (s3 << 1); + state[i + 0] = t0 ^ ((unsigned)(-(int)(t0 >> 8)) & 0x11B); + state[i + 1] = t1 ^ ((unsigned)(-(int)(t1 >> 8)) & 0x11B); + state[i + 2] = t2 ^ ((unsigned)(-(int)(t2 >> 8)) & 0x11B); + state[i + 3] = t3 ^ ((unsigned)(-(int)(t3 >> 8)) & 0x11B); + } +} + +/* see inner.h */ +void +br_aes_small_encrypt(unsigned num_rounds, const uint32_t *skey, void *data) +{ + unsigned char *buf; + unsigned state[16]; + unsigned u; + + buf = data; + for (u = 0; u < 16; u ++) { + state[u] = buf[u]; + } + add_round_key(state, skey); + for (u = 1; u < num_rounds; u ++) { + sub_bytes(state); + shift_rows(state); + mix_columns(state); + add_round_key(state, skey + (u << 2)); + } + sub_bytes(state); + shift_rows(state); + add_round_key(state, skey + (num_rounds << 2)); + for (u = 0; u < 16; u ++) { + buf[u] = state[u]; + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni.c b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni.c new file mode 100644 index 0000000..d5408f1 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_ENABLE_INTRINSICS 1 +#include "inner.h" + +/* + * This code contains the AES key schedule implementation using the + * AES-NI opcodes. + */ + +#if BR_AES_X86NI + +/* see inner.h */ +int +br_aes_x86ni_supported(void) +{ + /* + * Bit mask for features in ECX: + * 19 SSE4.1 (used for _mm_insert_epi32(), for AES-CTR) + * 25 AES-NI + */ + return br_cpuid(0, 0, 0x02080000, 0); +} + +BR_TARGETS_X86_UP + +BR_TARGET("sse2,aes") +static inline __m128i +expand_step128(__m128i k, __m128i k2) +{ + k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); + k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); + k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); + k2 = _mm_shuffle_epi32(k2, 0xFF); + return _mm_xor_si128(k, k2); +} + +BR_TARGET("sse2,aes") +static inline void +expand_step192(__m128i *t1, __m128i *t2, __m128i *t3) +{ + __m128i t4; + + *t2 = _mm_shuffle_epi32(*t2, 0x55); + t4 = _mm_slli_si128(*t1, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + *t1 = _mm_xor_si128(*t1, *t2); + *t2 = _mm_shuffle_epi32(*t1, 0xFF); + t4 = _mm_slli_si128(*t3, 0x4); + *t3 = _mm_xor_si128(*t3, t4); + *t3 = _mm_xor_si128(*t3, *t2); +} + +BR_TARGET("sse2,aes") +static inline void +expand_step256_1(__m128i *t1, __m128i *t2) +{ + __m128i t4; + + *t2 = _mm_shuffle_epi32(*t2, 0xFF); + t4 = _mm_slli_si128(*t1, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + *t1 = _mm_xor_si128(*t1, *t2); +} + +BR_TARGET("sse2,aes") +static inline void +expand_step256_2(__m128i *t1, __m128i *t3) +{ + __m128i t2, t4; + + t4 = _mm_aeskeygenassist_si128(*t1, 0x0); + t2 = _mm_shuffle_epi32(t4, 0xAA); + t4 = _mm_slli_si128(*t3, 0x4); + *t3 = _mm_xor_si128(*t3, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t3 = _mm_xor_si128(*t3, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t3 = _mm_xor_si128(*t3, t4); + *t3 = _mm_xor_si128(*t3, t2); +} + +/* + * Perform key schedule for AES, encryption direction. Subkeys are written + * in sk[], and the number of rounds is returned. Key length MUST be 16, + * 24 or 32 bytes. + */ +BR_TARGET("sse2,aes") +static unsigned +x86ni_keysched(__m128i *sk, const void *key, size_t len) +{ + const unsigned char *kb; + +#define KEXP128(k, i, rcon) do { \ + k = expand_step128(k, _mm_aeskeygenassist_si128(k, rcon)); \ + sk[i] = k; \ + } while (0) + +#define KEXP192(i, rcon1, rcon2) do { \ + sk[(i) + 0] = t1; \ + sk[(i) + 1] = t3; \ + t2 = _mm_aeskeygenassist_si128(t3, rcon1); \ + expand_step192(&t1, &t2, &t3); \ + sk[(i) + 1] = _mm_castpd_si128(_mm_shuffle_pd( \ + _mm_castsi128_pd(sk[(i) + 1]), \ + _mm_castsi128_pd(t1), 0)); \ + sk[(i) + 2] = _mm_castpd_si128(_mm_shuffle_pd( \ + _mm_castsi128_pd(t1), \ + _mm_castsi128_pd(t3), 1)); \ + t2 = _mm_aeskeygenassist_si128(t3, rcon2); \ + expand_step192(&t1, &t2, &t3); \ + } while (0) + +#define KEXP256(i, rcon) do { \ + sk[(i) + 0] = t3; \ + t2 = _mm_aeskeygenassist_si128(t3, rcon); \ + expand_step256_1(&t1, &t2); \ + sk[(i) + 1] = t1; \ + expand_step256_2(&t1, &t3); \ + } while (0) + + kb = key; + switch (len) { + __m128i t1, t2, t3; + + case 16: + t1 = _mm_loadu_si128((const void *)kb); + sk[0] = t1; + KEXP128(t1, 1, 0x01); + KEXP128(t1, 2, 0x02); + KEXP128(t1, 3, 0x04); + KEXP128(t1, 4, 0x08); + KEXP128(t1, 5, 0x10); + KEXP128(t1, 6, 0x20); + KEXP128(t1, 7, 0x40); + KEXP128(t1, 8, 0x80); + KEXP128(t1, 9, 0x1B); + KEXP128(t1, 10, 0x36); + return 10; + + case 24: + t1 = _mm_loadu_si128((const void *)kb); + t3 = _mm_loadu_si128((const void *)(kb + 8)); + t3 = _mm_shuffle_epi32(t3, 0x4E); + KEXP192(0, 0x01, 0x02); + KEXP192(3, 0x04, 0x08); + KEXP192(6, 0x10, 0x20); + KEXP192(9, 0x40, 0x80); + sk[12] = t1; + return 12; + + case 32: + t1 = _mm_loadu_si128((const void *)kb); + t3 = _mm_loadu_si128((const void *)(kb + 16)); + sk[0] = t1; + KEXP256( 1, 0x01); + KEXP256( 3, 0x02); + KEXP256( 5, 0x04); + KEXP256( 7, 0x08); + KEXP256( 9, 0x10); + KEXP256(11, 0x20); + sk[13] = t3; + t2 = _mm_aeskeygenassist_si128(t3, 0x40); + expand_step256_1(&t1, &t2); + sk[14] = t1; + return 14; + + default: + return 0; + } + +#undef KEXP128 +#undef KEXP192 +#undef KEXP256 +} + +/* see inner.h */ +BR_TARGET("sse2,aes") +unsigned +br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len) +{ + __m128i sk[15]; + unsigned num_rounds; + + num_rounds = x86ni_keysched(sk, key, len); + memcpy(skni, sk, (num_rounds + 1) << 4); + return num_rounds; +} + +/* see inner.h */ +BR_TARGET("sse2,aes") +unsigned +br_aes_x86ni_keysched_dec(unsigned char *skni, const void *key, size_t len) +{ + __m128i sk[15]; + unsigned u, num_rounds; + + num_rounds = x86ni_keysched(sk, key, len); + _mm_storeu_si128((void *)skni, sk[num_rounds]); + for (u = 1; u < num_rounds; u ++) { + _mm_storeu_si128((void *)(skni + (u << 4)), + _mm_aesimc_si128(sk[num_rounds - u])); + } + _mm_storeu_si128((void *)(skni + (num_rounds << 4)), sk[0]); + return num_rounds; +} + +BR_TARGETS_X86_DOWN + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_cbcdec.c b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_cbcdec.c new file mode 100644 index 0000000..862b1b5 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_cbcdec.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_ENABLE_INTRINSICS 1 +#include "inner.h" + +#if BR_AES_X86NI + +/* see bearssl_block.h */ +const br_block_cbcdec_class * +br_aes_x86ni_cbcdec_get_vtable(void) +{ + return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcdec_vtable : NULL; +} + +/* see bearssl_block.h */ +void +br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_x86ni_cbcdec_vtable; + ctx->num_rounds = br_aes_x86ni_keysched_dec(ctx->skey.skni, key, len); +} + +BR_TARGETS_X86_UP + +/* see bearssl_block.h */ +BR_TARGET("sse2,aes") +void +br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf; + unsigned num_rounds; + __m128i sk[15], ivx; + unsigned u; + + buf = data; + ivx = _mm_loadu_si128(iv); + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + while (len > 0) { + __m128i x0, x1, x2, x3, e0, e1, e2, e3; + + x0 = _mm_loadu_si128((void *)(buf + 0)); + if (len >= 64) { + x1 = _mm_loadu_si128((void *)(buf + 16)); + x2 = _mm_loadu_si128((void *)(buf + 32)); + x3 = _mm_loadu_si128((void *)(buf + 48)); + } else { + x0 = _mm_loadu_si128((void *)(buf + 0)); + if (len >= 32) { + x1 = _mm_loadu_si128((void *)(buf + 16)); + if (len >= 48) { + x2 = _mm_loadu_si128( + (void *)(buf + 32)); + x3 = x2; + } else { + x2 = x0; + x3 = x1; + } + } else { + x1 = x0; + x2 = x0; + x3 = x0; + } + } + e0 = x0; + e1 = x1; + e2 = x2; + e3 = x3; + x0 = _mm_xor_si128(x0, sk[0]); + x1 = _mm_xor_si128(x1, sk[0]); + x2 = _mm_xor_si128(x2, sk[0]); + x3 = _mm_xor_si128(x3, sk[0]); + x0 = _mm_aesdec_si128(x0, sk[1]); + x1 = _mm_aesdec_si128(x1, sk[1]); + x2 = _mm_aesdec_si128(x2, sk[1]); + x3 = _mm_aesdec_si128(x3, sk[1]); + x0 = _mm_aesdec_si128(x0, sk[2]); + x1 = _mm_aesdec_si128(x1, sk[2]); + x2 = _mm_aesdec_si128(x2, sk[2]); + x3 = _mm_aesdec_si128(x3, sk[2]); + x0 = _mm_aesdec_si128(x0, sk[3]); + x1 = _mm_aesdec_si128(x1, sk[3]); + x2 = _mm_aesdec_si128(x2, sk[3]); + x3 = _mm_aesdec_si128(x3, sk[3]); + x0 = _mm_aesdec_si128(x0, sk[4]); + x1 = _mm_aesdec_si128(x1, sk[4]); + x2 = _mm_aesdec_si128(x2, sk[4]); + x3 = _mm_aesdec_si128(x3, sk[4]); + x0 = _mm_aesdec_si128(x0, sk[5]); + x1 = _mm_aesdec_si128(x1, sk[5]); + x2 = _mm_aesdec_si128(x2, sk[5]); + x3 = _mm_aesdec_si128(x3, sk[5]); + x0 = _mm_aesdec_si128(x0, sk[6]); + x1 = _mm_aesdec_si128(x1, sk[6]); + x2 = _mm_aesdec_si128(x2, sk[6]); + x3 = _mm_aesdec_si128(x3, sk[6]); + x0 = _mm_aesdec_si128(x0, sk[7]); + x1 = _mm_aesdec_si128(x1, sk[7]); + x2 = _mm_aesdec_si128(x2, sk[7]); + x3 = _mm_aesdec_si128(x3, sk[7]); + x0 = _mm_aesdec_si128(x0, sk[8]); + x1 = _mm_aesdec_si128(x1, sk[8]); + x2 = _mm_aesdec_si128(x2, sk[8]); + x3 = _mm_aesdec_si128(x3, sk[8]); + x0 = _mm_aesdec_si128(x0, sk[9]); + x1 = _mm_aesdec_si128(x1, sk[9]); + x2 = _mm_aesdec_si128(x2, sk[9]); + x3 = _mm_aesdec_si128(x3, sk[9]); + if (num_rounds == 10) { + x0 = _mm_aesdeclast_si128(x0, sk[10]); + x1 = _mm_aesdeclast_si128(x1, sk[10]); + x2 = _mm_aesdeclast_si128(x2, sk[10]); + x3 = _mm_aesdeclast_si128(x3, sk[10]); + } else if (num_rounds == 12) { + x0 = _mm_aesdec_si128(x0, sk[10]); + x1 = _mm_aesdec_si128(x1, sk[10]); + x2 = _mm_aesdec_si128(x2, sk[10]); + x3 = _mm_aesdec_si128(x3, sk[10]); + x0 = _mm_aesdec_si128(x0, sk[11]); + x1 = _mm_aesdec_si128(x1, sk[11]); + x2 = _mm_aesdec_si128(x2, sk[11]); + x3 = _mm_aesdec_si128(x3, sk[11]); + x0 = _mm_aesdeclast_si128(x0, sk[12]); + x1 = _mm_aesdeclast_si128(x1, sk[12]); + x2 = _mm_aesdeclast_si128(x2, sk[12]); + x3 = _mm_aesdeclast_si128(x3, sk[12]); + } else { + x0 = _mm_aesdec_si128(x0, sk[10]); + x1 = _mm_aesdec_si128(x1, sk[10]); + x2 = _mm_aesdec_si128(x2, sk[10]); + x3 = _mm_aesdec_si128(x3, sk[10]); + x0 = _mm_aesdec_si128(x0, sk[11]); + x1 = _mm_aesdec_si128(x1, sk[11]); + x2 = _mm_aesdec_si128(x2, sk[11]); + x3 = _mm_aesdec_si128(x3, sk[11]); + x0 = _mm_aesdec_si128(x0, sk[12]); + x1 = _mm_aesdec_si128(x1, sk[12]); + x2 = _mm_aesdec_si128(x2, sk[12]); + x3 = _mm_aesdec_si128(x3, sk[12]); + x0 = _mm_aesdec_si128(x0, sk[13]); + x1 = _mm_aesdec_si128(x1, sk[13]); + x2 = _mm_aesdec_si128(x2, sk[13]); + x3 = _mm_aesdec_si128(x3, sk[13]); + x0 = _mm_aesdeclast_si128(x0, sk[14]); + x1 = _mm_aesdeclast_si128(x1, sk[14]); + x2 = _mm_aesdeclast_si128(x2, sk[14]); + x3 = _mm_aesdeclast_si128(x3, sk[14]); + } + x0 = _mm_xor_si128(x0, ivx); + x1 = _mm_xor_si128(x1, e0); + x2 = _mm_xor_si128(x2, e1); + x3 = _mm_xor_si128(x3, e2); + ivx = e3; + _mm_storeu_si128((void *)(buf + 0), x0); + if (len >= 64) { + _mm_storeu_si128((void *)(buf + 16), x1); + _mm_storeu_si128((void *)(buf + 32), x2); + _mm_storeu_si128((void *)(buf + 48), x3); + buf += 64; + len -= 64; + } else { + if (len >= 32) { + _mm_storeu_si128((void *)(buf + 16), x1); + if (len >= 48) { + _mm_storeu_si128( + (void *)(buf + 32), x2); + } + } + break; + } + } + _mm_storeu_si128(iv, ivx); +} + +BR_TARGETS_X86_DOWN + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable = { + sizeof(br_aes_x86ni_cbcdec_keys), + 16, + 4, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_aes_x86ni_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_aes_x86ni_cbcdec_run +}; + +#else + +/* see bearssl_block.h */ +const br_block_cbcdec_class * +br_aes_x86ni_cbcdec_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_cbcenc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_cbcenc.c new file mode 100644 index 0000000..85feecd --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_cbcenc.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_ENABLE_INTRINSICS 1 +#include "inner.h" + +#if BR_AES_X86NI + +/* see bearssl_block.h */ +const br_block_cbcenc_class * +br_aes_x86ni_cbcenc_get_vtable(void) +{ + return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcenc_vtable : NULL; +} + +/* see bearssl_block.h */ +void +br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_x86ni_cbcenc_vtable; + ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len); +} + +BR_TARGETS_X86_UP + +/* see bearssl_block.h */ +BR_TARGET("sse2,aes") +void +br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf; + unsigned num_rounds; + __m128i sk[15], ivx; + unsigned u; + + buf = data; + ivx = _mm_loadu_si128(iv); + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + while (len > 0) { + __m128i x; + + x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx); + x = _mm_xor_si128(x, sk[0]); + x = _mm_aesenc_si128(x, sk[1]); + x = _mm_aesenc_si128(x, sk[2]); + x = _mm_aesenc_si128(x, sk[3]); + x = _mm_aesenc_si128(x, sk[4]); + x = _mm_aesenc_si128(x, sk[5]); + x = _mm_aesenc_si128(x, sk[6]); + x = _mm_aesenc_si128(x, sk[7]); + x = _mm_aesenc_si128(x, sk[8]); + x = _mm_aesenc_si128(x, sk[9]); + if (num_rounds == 10) { + x = _mm_aesenclast_si128(x, sk[10]); + } else if (num_rounds == 12) { + x = _mm_aesenc_si128(x, sk[10]); + x = _mm_aesenc_si128(x, sk[11]); + x = _mm_aesenclast_si128(x, sk[12]); + } else { + x = _mm_aesenc_si128(x, sk[10]); + x = _mm_aesenc_si128(x, sk[11]); + x = _mm_aesenc_si128(x, sk[12]); + x = _mm_aesenc_si128(x, sk[13]); + x = _mm_aesenclast_si128(x, sk[14]); + } + ivx = x; + _mm_storeu_si128((void *)buf, x); + buf += 16; + len -= 16; + } + _mm_storeu_si128(iv, ivx); +} + +BR_TARGETS_X86_DOWN + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable = { + sizeof(br_aes_x86ni_cbcenc_keys), + 16, + 4, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_aes_x86ni_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_aes_x86ni_cbcenc_run +}; + +#else + +/* see bearssl_block.h */ +const br_block_cbcenc_class * +br_aes_x86ni_cbcenc_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_ctr.c b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_ctr.c new file mode 100644 index 0000000..1cddd60 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_ctr.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_ENABLE_INTRINSICS 1 +#include "inner.h" + +#if BR_AES_X86NI + +/* see bearssl_block.h */ +const br_block_ctr_class * +br_aes_x86ni_ctr_get_vtable(void) +{ + return br_aes_x86ni_supported() ? &br_aes_x86ni_ctr_vtable : NULL; +} + +/* see bearssl_block.h */ +void +br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_x86ni_ctr_vtable; + ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len); +} + +BR_TARGETS_X86_UP + +/* see bearssl_block.h */ +BR_TARGET("sse2,sse4.1,aes") +uint32_t +br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + unsigned char ivbuf[16]; + unsigned num_rounds; + __m128i sk[15]; + __m128i ivx; + unsigned u; + + buf = data; + memcpy(ivbuf, iv, 12); + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + ivx = _mm_loadu_si128((void *)ivbuf); + while (len > 0) { + __m128i x0, x1, x2, x3; + + x0 = _mm_insert_epi32(ivx, br_bswap32(cc + 0), 3); + x1 = _mm_insert_epi32(ivx, br_bswap32(cc + 1), 3); + x2 = _mm_insert_epi32(ivx, br_bswap32(cc + 2), 3); + x3 = _mm_insert_epi32(ivx, br_bswap32(cc + 3), 3); + x0 = _mm_xor_si128(x0, sk[0]); + x1 = _mm_xor_si128(x1, sk[0]); + x2 = _mm_xor_si128(x2, sk[0]); + x3 = _mm_xor_si128(x3, sk[0]); + x0 = _mm_aesenc_si128(x0, sk[1]); + x1 = _mm_aesenc_si128(x1, sk[1]); + x2 = _mm_aesenc_si128(x2, sk[1]); + x3 = _mm_aesenc_si128(x3, sk[1]); + x0 = _mm_aesenc_si128(x0, sk[2]); + x1 = _mm_aesenc_si128(x1, sk[2]); + x2 = _mm_aesenc_si128(x2, sk[2]); + x3 = _mm_aesenc_si128(x3, sk[2]); + x0 = _mm_aesenc_si128(x0, sk[3]); + x1 = _mm_aesenc_si128(x1, sk[3]); + x2 = _mm_aesenc_si128(x2, sk[3]); + x3 = _mm_aesenc_si128(x3, sk[3]); + x0 = _mm_aesenc_si128(x0, sk[4]); + x1 = _mm_aesenc_si128(x1, sk[4]); + x2 = _mm_aesenc_si128(x2, sk[4]); + x3 = _mm_aesenc_si128(x3, sk[4]); + x0 = _mm_aesenc_si128(x0, sk[5]); + x1 = _mm_aesenc_si128(x1, sk[5]); + x2 = _mm_aesenc_si128(x2, sk[5]); + x3 = _mm_aesenc_si128(x3, sk[5]); + x0 = _mm_aesenc_si128(x0, sk[6]); + x1 = _mm_aesenc_si128(x1, sk[6]); + x2 = _mm_aesenc_si128(x2, sk[6]); + x3 = _mm_aesenc_si128(x3, sk[6]); + x0 = _mm_aesenc_si128(x0, sk[7]); + x1 = _mm_aesenc_si128(x1, sk[7]); + x2 = _mm_aesenc_si128(x2, sk[7]); + x3 = _mm_aesenc_si128(x3, sk[7]); + x0 = _mm_aesenc_si128(x0, sk[8]); + x1 = _mm_aesenc_si128(x1, sk[8]); + x2 = _mm_aesenc_si128(x2, sk[8]); + x3 = _mm_aesenc_si128(x3, sk[8]); + x0 = _mm_aesenc_si128(x0, sk[9]); + x1 = _mm_aesenc_si128(x1, sk[9]); + x2 = _mm_aesenc_si128(x2, sk[9]); + x3 = _mm_aesenc_si128(x3, sk[9]); + if (num_rounds == 10) { + x0 = _mm_aesenclast_si128(x0, sk[10]); + x1 = _mm_aesenclast_si128(x1, sk[10]); + x2 = _mm_aesenclast_si128(x2, sk[10]); + x3 = _mm_aesenclast_si128(x3, sk[10]); + } else if (num_rounds == 12) { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x2 = _mm_aesenc_si128(x2, sk[10]); + x3 = _mm_aesenc_si128(x3, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x2 = _mm_aesenc_si128(x2, sk[11]); + x3 = _mm_aesenc_si128(x3, sk[11]); + x0 = _mm_aesenclast_si128(x0, sk[12]); + x1 = _mm_aesenclast_si128(x1, sk[12]); + x2 = _mm_aesenclast_si128(x2, sk[12]); + x3 = _mm_aesenclast_si128(x3, sk[12]); + } else { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x2 = _mm_aesenc_si128(x2, sk[10]); + x3 = _mm_aesenc_si128(x3, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x2 = _mm_aesenc_si128(x2, sk[11]); + x3 = _mm_aesenc_si128(x3, sk[11]); + x0 = _mm_aesenc_si128(x0, sk[12]); + x1 = _mm_aesenc_si128(x1, sk[12]); + x2 = _mm_aesenc_si128(x2, sk[12]); + x3 = _mm_aesenc_si128(x3, sk[12]); + x0 = _mm_aesenc_si128(x0, sk[13]); + x1 = _mm_aesenc_si128(x1, sk[13]); + x2 = _mm_aesenc_si128(x2, sk[13]); + x3 = _mm_aesenc_si128(x3, sk[13]); + x0 = _mm_aesenclast_si128(x0, sk[14]); + x1 = _mm_aesenclast_si128(x1, sk[14]); + x2 = _mm_aesenclast_si128(x2, sk[14]); + x3 = _mm_aesenclast_si128(x3, sk[14]); + } + if (len >= 64) { + x0 = _mm_xor_si128(x0, + _mm_loadu_si128((void *)(buf + 0))); + x1 = _mm_xor_si128(x1, + _mm_loadu_si128((void *)(buf + 16))); + x2 = _mm_xor_si128(x2, + _mm_loadu_si128((void *)(buf + 32))); + x3 = _mm_xor_si128(x3, + _mm_loadu_si128((void *)(buf + 48))); + _mm_storeu_si128((void *)(buf + 0), x0); + _mm_storeu_si128((void *)(buf + 16), x1); + _mm_storeu_si128((void *)(buf + 32), x2); + _mm_storeu_si128((void *)(buf + 48), x3); + buf += 64; + len -= 64; + cc += 4; + } else { + unsigned char tmp[64]; + + _mm_storeu_si128((void *)(tmp + 0), x0); + _mm_storeu_si128((void *)(tmp + 16), x1); + _mm_storeu_si128((void *)(tmp + 32), x2); + _mm_storeu_si128((void *)(tmp + 48), x3); + for (u = 0; u < len; u ++) { + buf[u] ^= tmp[u]; + } + cc += (uint32_t)len >> 4; + break; + } + } + return cc; +} + +BR_TARGETS_X86_DOWN + +/* see bearssl_block.h */ +const br_block_ctr_class br_aes_x86ni_ctr_vtable = { + sizeof(br_aes_x86ni_ctr_keys), + 16, + 4, + (void (*)(const br_block_ctr_class **, const void *, size_t)) + &br_aes_x86ni_ctr_init, + (uint32_t (*)(const br_block_ctr_class *const *, + const void *, uint32_t, void *, size_t)) + &br_aes_x86ni_ctr_run +}; + +#else + +/* see bearssl_block.h */ +const br_block_ctr_class * +br_aes_x86ni_ctr_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_ctrcbc.c b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_ctrcbc.c new file mode 100644 index 0000000..f57fead --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/aes_x86ni_ctrcbc.c @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_ENABLE_INTRINSICS 1 +#include "inner.h" + +#if BR_AES_X86NI + +/* see bearssl_block.h */ +const br_block_ctrcbc_class * +br_aes_x86ni_ctrcbc_get_vtable(void) +{ + return br_aes_x86ni_supported() ? &br_aes_x86ni_ctrcbc_vtable : NULL; +} + +/* see bearssl_block.h */ +void +br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_x86ni_ctrcbc_vtable; + ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len); +} + +BR_TARGETS_X86_UP + +/* see bearssl_block.h */ +BR_TARGET("sse2,sse4.1,aes") +void +br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len) +{ + unsigned char *buf; + unsigned num_rounds; + __m128i sk[15]; + __m128i ivx0, ivx1, ivx2, ivx3; + __m128i erev, zero, one, four, notthree; + unsigned u; + + buf = data; + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + + /* + * Some SSE2 constants. + */ + erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15); + zero = _mm_setzero_si128(); + one = _mm_set_epi64x(0, 1); + four = _mm_set_epi64x(0, 4); + notthree = _mm_sub_epi64(zero, four); + + /* + * Decode the counter in big-endian and pre-increment the other + * three counters. + */ + ivx0 = _mm_shuffle_epi8(_mm_loadu_si128((void *)ctr), erev); + ivx1 = _mm_add_epi64(ivx0, one); + ivx1 = _mm_sub_epi64(ivx1, + _mm_slli_si128(_mm_cmpeq_epi64(ivx1, zero), 8)); + ivx2 = _mm_add_epi64(ivx1, one); + ivx2 = _mm_sub_epi64(ivx2, + _mm_slli_si128(_mm_cmpeq_epi64(ivx2, zero), 8)); + ivx3 = _mm_add_epi64(ivx2, one); + ivx3 = _mm_sub_epi64(ivx3, + _mm_slli_si128(_mm_cmpeq_epi64(ivx3, zero), 8)); + while (len > 0) { + __m128i x0, x1, x2, x3; + + /* + * Load counter values; we need to byteswap them because + * the specification says that they use big-endian. + */ + x0 = _mm_shuffle_epi8(ivx0, erev); + x1 = _mm_shuffle_epi8(ivx1, erev); + x2 = _mm_shuffle_epi8(ivx2, erev); + x3 = _mm_shuffle_epi8(ivx3, erev); + + x0 = _mm_xor_si128(x0, sk[0]); + x1 = _mm_xor_si128(x1, sk[0]); + x2 = _mm_xor_si128(x2, sk[0]); + x3 = _mm_xor_si128(x3, sk[0]); + x0 = _mm_aesenc_si128(x0, sk[1]); + x1 = _mm_aesenc_si128(x1, sk[1]); + x2 = _mm_aesenc_si128(x2, sk[1]); + x3 = _mm_aesenc_si128(x3, sk[1]); + x0 = _mm_aesenc_si128(x0, sk[2]); + x1 = _mm_aesenc_si128(x1, sk[2]); + x2 = _mm_aesenc_si128(x2, sk[2]); + x3 = _mm_aesenc_si128(x3, sk[2]); + x0 = _mm_aesenc_si128(x0, sk[3]); + x1 = _mm_aesenc_si128(x1, sk[3]); + x2 = _mm_aesenc_si128(x2, sk[3]); + x3 = _mm_aesenc_si128(x3, sk[3]); + x0 = _mm_aesenc_si128(x0, sk[4]); + x1 = _mm_aesenc_si128(x1, sk[4]); + x2 = _mm_aesenc_si128(x2, sk[4]); + x3 = _mm_aesenc_si128(x3, sk[4]); + x0 = _mm_aesenc_si128(x0, sk[5]); + x1 = _mm_aesenc_si128(x1, sk[5]); + x2 = _mm_aesenc_si128(x2, sk[5]); + x3 = _mm_aesenc_si128(x3, sk[5]); + x0 = _mm_aesenc_si128(x0, sk[6]); + x1 = _mm_aesenc_si128(x1, sk[6]); + x2 = _mm_aesenc_si128(x2, sk[6]); + x3 = _mm_aesenc_si128(x3, sk[6]); + x0 = _mm_aesenc_si128(x0, sk[7]); + x1 = _mm_aesenc_si128(x1, sk[7]); + x2 = _mm_aesenc_si128(x2, sk[7]); + x3 = _mm_aesenc_si128(x3, sk[7]); + x0 = _mm_aesenc_si128(x0, sk[8]); + x1 = _mm_aesenc_si128(x1, sk[8]); + x2 = _mm_aesenc_si128(x2, sk[8]); + x3 = _mm_aesenc_si128(x3, sk[8]); + x0 = _mm_aesenc_si128(x0, sk[9]); + x1 = _mm_aesenc_si128(x1, sk[9]); + x2 = _mm_aesenc_si128(x2, sk[9]); + x3 = _mm_aesenc_si128(x3, sk[9]); + if (num_rounds == 10) { + x0 = _mm_aesenclast_si128(x0, sk[10]); + x1 = _mm_aesenclast_si128(x1, sk[10]); + x2 = _mm_aesenclast_si128(x2, sk[10]); + x3 = _mm_aesenclast_si128(x3, sk[10]); + } else if (num_rounds == 12) { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x2 = _mm_aesenc_si128(x2, sk[10]); + x3 = _mm_aesenc_si128(x3, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x2 = _mm_aesenc_si128(x2, sk[11]); + x3 = _mm_aesenc_si128(x3, sk[11]); + x0 = _mm_aesenclast_si128(x0, sk[12]); + x1 = _mm_aesenclast_si128(x1, sk[12]); + x2 = _mm_aesenclast_si128(x2, sk[12]); + x3 = _mm_aesenclast_si128(x3, sk[12]); + } else { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x2 = _mm_aesenc_si128(x2, sk[10]); + x3 = _mm_aesenc_si128(x3, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x2 = _mm_aesenc_si128(x2, sk[11]); + x3 = _mm_aesenc_si128(x3, sk[11]); + x0 = _mm_aesenc_si128(x0, sk[12]); + x1 = _mm_aesenc_si128(x1, sk[12]); + x2 = _mm_aesenc_si128(x2, sk[12]); + x3 = _mm_aesenc_si128(x3, sk[12]); + x0 = _mm_aesenc_si128(x0, sk[13]); + x1 = _mm_aesenc_si128(x1, sk[13]); + x2 = _mm_aesenc_si128(x2, sk[13]); + x3 = _mm_aesenc_si128(x3, sk[13]); + x0 = _mm_aesenclast_si128(x0, sk[14]); + x1 = _mm_aesenclast_si128(x1, sk[14]); + x2 = _mm_aesenclast_si128(x2, sk[14]); + x3 = _mm_aesenclast_si128(x3, sk[14]); + } + if (len >= 64) { + x0 = _mm_xor_si128(x0, + _mm_loadu_si128((void *)(buf + 0))); + x1 = _mm_xor_si128(x1, + _mm_loadu_si128((void *)(buf + 16))); + x2 = _mm_xor_si128(x2, + _mm_loadu_si128((void *)(buf + 32))); + x3 = _mm_xor_si128(x3, + _mm_loadu_si128((void *)(buf + 48))); + _mm_storeu_si128((void *)(buf + 0), x0); + _mm_storeu_si128((void *)(buf + 16), x1); + _mm_storeu_si128((void *)(buf + 32), x2); + _mm_storeu_si128((void *)(buf + 48), x3); + buf += 64; + len -= 64; + } else { + unsigned char tmp[64]; + + _mm_storeu_si128((void *)(tmp + 0), x0); + _mm_storeu_si128((void *)(tmp + 16), x1); + _mm_storeu_si128((void *)(tmp + 32), x2); + _mm_storeu_si128((void *)(tmp + 48), x3); + for (u = 0; u < len; u ++) { + buf[u] ^= tmp[u]; + } + switch (len) { + case 16: + ivx0 = ivx1; + break; + case 32: + ivx0 = ivx2; + break; + case 48: + ivx0 = ivx3; + break; + } + break; + } + + /* + * Add 4 to each counter value. For carry propagation + * into the upper 64-bit words, we would need to compare + * the results with 4, but SSE2+ has only _signed_ + * comparisons. Instead, we mask out the low two bits, + * and check whether the remaining bits are zero. + */ + ivx0 = _mm_add_epi64(ivx0, four); + ivx1 = _mm_add_epi64(ivx1, four); + ivx2 = _mm_add_epi64(ivx2, four); + ivx3 = _mm_add_epi64(ivx3, four); + ivx0 = _mm_sub_epi64(ivx0, + _mm_slli_si128(_mm_cmpeq_epi64( + _mm_and_si128(ivx0, notthree), zero), 8)); + ivx1 = _mm_sub_epi64(ivx1, + _mm_slli_si128(_mm_cmpeq_epi64( + _mm_and_si128(ivx1, notthree), zero), 8)); + ivx2 = _mm_sub_epi64(ivx2, + _mm_slli_si128(_mm_cmpeq_epi64( + _mm_and_si128(ivx2, notthree), zero), 8)); + ivx3 = _mm_sub_epi64(ivx3, + _mm_slli_si128(_mm_cmpeq_epi64( + _mm_and_si128(ivx3, notthree), zero), 8)); + } + + /* + * Write back new counter value. The loop took care to put the + * right counter value in ivx0. + */ + _mm_storeu_si128((void *)ctr, _mm_shuffle_epi8(ivx0, erev)); +} + +/* see bearssl_block.h */ +BR_TARGET("sse2,sse4.1,aes") +void +br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len) +{ + const unsigned char *buf; + unsigned num_rounds; + __m128i sk[15], ivx; + unsigned u; + + buf = data; + ivx = _mm_loadu_si128(cbcmac); + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + while (len > 0) { + __m128i x; + + x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx); + x = _mm_xor_si128(x, sk[0]); + x = _mm_aesenc_si128(x, sk[1]); + x = _mm_aesenc_si128(x, sk[2]); + x = _mm_aesenc_si128(x, sk[3]); + x = _mm_aesenc_si128(x, sk[4]); + x = _mm_aesenc_si128(x, sk[5]); + x = _mm_aesenc_si128(x, sk[6]); + x = _mm_aesenc_si128(x, sk[7]); + x = _mm_aesenc_si128(x, sk[8]); + x = _mm_aesenc_si128(x, sk[9]); + if (num_rounds == 10) { + x = _mm_aesenclast_si128(x, sk[10]); + } else if (num_rounds == 12) { + x = _mm_aesenc_si128(x, sk[10]); + x = _mm_aesenc_si128(x, sk[11]); + x = _mm_aesenclast_si128(x, sk[12]); + } else { + x = _mm_aesenc_si128(x, sk[10]); + x = _mm_aesenc_si128(x, sk[11]); + x = _mm_aesenc_si128(x, sk[12]); + x = _mm_aesenc_si128(x, sk[13]); + x = _mm_aesenclast_si128(x, sk[14]); + } + ivx = x; + buf += 16; + len -= 16; + } + _mm_storeu_si128(cbcmac, ivx); +} + +/* see bearssl_block.h */ +BR_TARGET("sse2,sse4.1,aes") +void +br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + unsigned char *buf; + unsigned num_rounds; + __m128i sk[15]; + __m128i ivx, cmx; + __m128i erev, zero, one; + unsigned u; + int first_iter; + + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + + /* + * Some SSE2 constants. + */ + erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15); + zero = _mm_setzero_si128(); + one = _mm_set_epi64x(0, 1); + + /* + * Decode the counter in big-endian. + */ + ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev); + cmx = _mm_loadu_si128(cbcmac); + + buf = data; + first_iter = 1; + while (len > 0) { + __m128i dx, x0, x1; + + /* + * Load initial values: + * dx encrypted block of data + * x0 counter (for CTR encryption) + * x1 input for CBC-MAC + */ + dx = _mm_loadu_si128((void *)buf); + x0 = _mm_shuffle_epi8(ivx, erev); + x1 = cmx; + + x0 = _mm_xor_si128(x0, sk[0]); + x1 = _mm_xor_si128(x1, sk[0]); + x0 = _mm_aesenc_si128(x0, sk[1]); + x1 = _mm_aesenc_si128(x1, sk[1]); + x0 = _mm_aesenc_si128(x0, sk[2]); + x1 = _mm_aesenc_si128(x1, sk[2]); + x0 = _mm_aesenc_si128(x0, sk[3]); + x1 = _mm_aesenc_si128(x1, sk[3]); + x0 = _mm_aesenc_si128(x0, sk[4]); + x1 = _mm_aesenc_si128(x1, sk[4]); + x0 = _mm_aesenc_si128(x0, sk[5]); + x1 = _mm_aesenc_si128(x1, sk[5]); + x0 = _mm_aesenc_si128(x0, sk[6]); + x1 = _mm_aesenc_si128(x1, sk[6]); + x0 = _mm_aesenc_si128(x0, sk[7]); + x1 = _mm_aesenc_si128(x1, sk[7]); + x0 = _mm_aesenc_si128(x0, sk[8]); + x1 = _mm_aesenc_si128(x1, sk[8]); + x0 = _mm_aesenc_si128(x0, sk[9]); + x1 = _mm_aesenc_si128(x1, sk[9]); + if (num_rounds == 10) { + x0 = _mm_aesenclast_si128(x0, sk[10]); + x1 = _mm_aesenclast_si128(x1, sk[10]); + } else if (num_rounds == 12) { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x0 = _mm_aesenclast_si128(x0, sk[12]); + x1 = _mm_aesenclast_si128(x1, sk[12]); + } else { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x0 = _mm_aesenc_si128(x0, sk[12]); + x1 = _mm_aesenc_si128(x1, sk[12]); + x0 = _mm_aesenc_si128(x0, sk[13]); + x1 = _mm_aesenc_si128(x1, sk[13]); + x0 = _mm_aesenclast_si128(x0, sk[14]); + x1 = _mm_aesenclast_si128(x1, sk[14]); + } + + x0 = _mm_xor_si128(x0, dx); + if (first_iter) { + cmx = _mm_xor_si128(cmx, x0); + first_iter = 0; + } else { + cmx = _mm_xor_si128(x1, x0); + } + _mm_storeu_si128((void *)buf, x0); + + buf += 16; + len -= 16; + + /* + * Increment the counter value. + */ + ivx = _mm_add_epi64(ivx, one); + ivx = _mm_sub_epi64(ivx, + _mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8)); + + /* + * If this was the last iteration, then compute the + * extra block encryption to complete CBC-MAC. + */ + if (len == 0) { + cmx = _mm_xor_si128(cmx, sk[0]); + cmx = _mm_aesenc_si128(cmx, sk[1]); + cmx = _mm_aesenc_si128(cmx, sk[2]); + cmx = _mm_aesenc_si128(cmx, sk[3]); + cmx = _mm_aesenc_si128(cmx, sk[4]); + cmx = _mm_aesenc_si128(cmx, sk[5]); + cmx = _mm_aesenc_si128(cmx, sk[6]); + cmx = _mm_aesenc_si128(cmx, sk[7]); + cmx = _mm_aesenc_si128(cmx, sk[8]); + cmx = _mm_aesenc_si128(cmx, sk[9]); + if (num_rounds == 10) { + cmx = _mm_aesenclast_si128(cmx, sk[10]); + } else if (num_rounds == 12) { + cmx = _mm_aesenc_si128(cmx, sk[10]); + cmx = _mm_aesenc_si128(cmx, sk[11]); + cmx = _mm_aesenclast_si128(cmx, sk[12]); + } else { + cmx = _mm_aesenc_si128(cmx, sk[10]); + cmx = _mm_aesenc_si128(cmx, sk[11]); + cmx = _mm_aesenc_si128(cmx, sk[12]); + cmx = _mm_aesenc_si128(cmx, sk[13]); + cmx = _mm_aesenclast_si128(cmx, sk[14]); + } + break; + } + } + + /* + * Write back new counter value and CBC-MAC value. + */ + _mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev)); + _mm_storeu_si128(cbcmac, cmx); +} + +/* see bearssl_block.h */ +BR_TARGET("sse2,sse4.1,aes") +void +br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len) +{ + unsigned char *buf; + unsigned num_rounds; + __m128i sk[15]; + __m128i ivx, cmx; + __m128i erev, zero, one; + unsigned u; + + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + + /* + * Some SSE2 constants. + */ + erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15); + zero = _mm_setzero_si128(); + one = _mm_set_epi64x(0, 1); + + /* + * Decode the counter in big-endian. + */ + ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev); + cmx = _mm_loadu_si128(cbcmac); + + buf = data; + while (len > 0) { + __m128i dx, x0, x1; + + /* + * Load initial values: + * dx encrypted block of data + * x0 counter (for CTR encryption) + * x1 input for CBC-MAC + */ + dx = _mm_loadu_si128((void *)buf); + x0 = _mm_shuffle_epi8(ivx, erev); + x1 = _mm_xor_si128(cmx, dx); + + x0 = _mm_xor_si128(x0, sk[0]); + x1 = _mm_xor_si128(x1, sk[0]); + x0 = _mm_aesenc_si128(x0, sk[1]); + x1 = _mm_aesenc_si128(x1, sk[1]); + x0 = _mm_aesenc_si128(x0, sk[2]); + x1 = _mm_aesenc_si128(x1, sk[2]); + x0 = _mm_aesenc_si128(x0, sk[3]); + x1 = _mm_aesenc_si128(x1, sk[3]); + x0 = _mm_aesenc_si128(x0, sk[4]); + x1 = _mm_aesenc_si128(x1, sk[4]); + x0 = _mm_aesenc_si128(x0, sk[5]); + x1 = _mm_aesenc_si128(x1, sk[5]); + x0 = _mm_aesenc_si128(x0, sk[6]); + x1 = _mm_aesenc_si128(x1, sk[6]); + x0 = _mm_aesenc_si128(x0, sk[7]); + x1 = _mm_aesenc_si128(x1, sk[7]); + x0 = _mm_aesenc_si128(x0, sk[8]); + x1 = _mm_aesenc_si128(x1, sk[8]); + x0 = _mm_aesenc_si128(x0, sk[9]); + x1 = _mm_aesenc_si128(x1, sk[9]); + if (num_rounds == 10) { + x0 = _mm_aesenclast_si128(x0, sk[10]); + x1 = _mm_aesenclast_si128(x1, sk[10]); + } else if (num_rounds == 12) { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x0 = _mm_aesenclast_si128(x0, sk[12]); + x1 = _mm_aesenclast_si128(x1, sk[12]); + } else { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x0 = _mm_aesenc_si128(x0, sk[12]); + x1 = _mm_aesenc_si128(x1, sk[12]); + x0 = _mm_aesenc_si128(x0, sk[13]); + x1 = _mm_aesenc_si128(x1, sk[13]); + x0 = _mm_aesenclast_si128(x0, sk[14]); + x1 = _mm_aesenclast_si128(x1, sk[14]); + } + x0 = _mm_xor_si128(x0, dx); + cmx = x1; + _mm_storeu_si128((void *)buf, x0); + + buf += 16; + len -= 16; + + /* + * Increment the counter value. + */ + ivx = _mm_add_epi64(ivx, one); + ivx = _mm_sub_epi64(ivx, + _mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8)); + } + + /* + * Write back new counter value and CBC-MAC value. + */ + _mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev)); + _mm_storeu_si128(cbcmac, cmx); +} + +BR_TARGETS_X86_DOWN + +/* see bearssl_block.h */ +const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable = { + sizeof(br_aes_x86ni_ctrcbc_keys), + 16, + 4, + (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) + &br_aes_x86ni_ctrcbc_init, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_x86ni_ctrcbc_encrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, void *, size_t)) + &br_aes_x86ni_ctrcbc_decrypt, + (void (*)(const br_block_ctrcbc_class *const *, + void *, void *, size_t)) + &br_aes_x86ni_ctrcbc_ctr, + (void (*)(const br_block_ctrcbc_class *const *, + void *, const void *, size_t)) + &br_aes_x86ni_ctrcbc_mac +}; + +#else + +/* see bearssl_block.h */ +const br_block_ctrcbc_class * +br_aes_x86ni_ctrcbc_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/chacha20_ct.c b/BearSSL-OG/libbearssl/src/symcipher/chacha20_ct.c new file mode 100644 index 0000000..9961eb1 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/chacha20_ct.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +uint32_t +br_chacha20_ct_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + uint32_t kw[8], ivw[3]; + size_t u; + + static const uint32_t CW[] = { + 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 + }; + + buf = data; + for (u = 0; u < 8; u ++) { + kw[u] = br_dec32le((const unsigned char *)key + (u << 2)); + } + for (u = 0; u < 3; u ++) { + ivw[u] = br_dec32le((const unsigned char *)iv + (u << 2)); + } + while (len > 0) { + uint32_t state[16]; + int i; + size_t clen; + unsigned char tmp[64]; + + memcpy(&state[0], CW, sizeof CW); + memcpy(&state[4], kw, sizeof kw); + state[12] = cc; + memcpy(&state[13], ivw, sizeof ivw); + for (i = 0; i < 10; i ++) { + +#define QROUND(a, b, c, d) do { \ + state[a] += state[b]; \ + state[d] ^= state[a]; \ + state[d] = (state[d] << 16) | (state[d] >> 16); \ + state[c] += state[d]; \ + state[b] ^= state[c]; \ + state[b] = (state[b] << 12) | (state[b] >> 20); \ + state[a] += state[b]; \ + state[d] ^= state[a]; \ + state[d] = (state[d] << 8) | (state[d] >> 24); \ + state[c] += state[d]; \ + state[b] ^= state[c]; \ + state[b] = (state[b] << 7) | (state[b] >> 25); \ + } while (0) + + QROUND( 0, 4, 8, 12); + QROUND( 1, 5, 9, 13); + QROUND( 2, 6, 10, 14); + QROUND( 3, 7, 11, 15); + QROUND( 0, 5, 10, 15); + QROUND( 1, 6, 11, 12); + QROUND( 2, 7, 8, 13); + QROUND( 3, 4, 9, 14); + +#undef QROUND + + } + for (u = 0; u < 4; u ++) { + br_enc32le(&tmp[u << 2], state[u] + CW[u]); + } + for (u = 4; u < 12; u ++) { + br_enc32le(&tmp[u << 2], state[u] + kw[u - 4]); + } + br_enc32le(&tmp[48], state[12] + cc); + for (u = 13; u < 16; u ++) { + br_enc32le(&tmp[u << 2], state[u] + ivw[u - 13]); + } + + clen = len < 64 ? len : 64; + for (u = 0; u < clen; u ++) { + buf[u] ^= tmp[u]; + } + buf += clen; + len -= clen; + cc ++; + } + return cc; +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/chacha20_sse2.c b/BearSSL-OG/libbearssl/src/symcipher/chacha20_sse2.c new file mode 100644 index 0000000..92b4a4a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/chacha20_sse2.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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. + */ + +#define BR_ENABLE_INTRINSICS 1 +#include "inner.h" + +#if BR_SSE2 + +/* + * This file contains a ChaCha20 implementation that leverages SSE2 + * opcodes for better performance. + */ + +/* see bearssl_block.h */ +br_chacha20_run +br_chacha20_sse2_get(void) +{ + /* + * If using 64-bit mode, then SSE2 opcodes should be automatically + * available, since they are part of the ABI. + * + * In 32-bit mode, we use CPUID to detect the SSE2 feature. + */ + +#if BR_amd64 + return &br_chacha20_sse2_run; +#else + + /* + * SSE2 support is indicated by bit 26 in EDX. + */ + if (br_cpuid(0, 0, 0, 0x04000000)) { + return &br_chacha20_sse2_run; + } else { + return 0; + } +#endif +} + +BR_TARGETS_X86_UP + +/* see bearssl_block.h */ +BR_TARGET("sse2") +uint32_t +br_chacha20_sse2_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + uint32_t ivtmp[4]; + __m128i kw0, kw1; + __m128i iw, cw; + __m128i one; + + static const uint32_t CW[] = { + 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 + }; + + buf = data; + kw0 = _mm_loadu_si128(key); + kw1 = _mm_loadu_si128((const void *)((const unsigned char *)key + 16)); + ivtmp[0] = cc; + memcpy(ivtmp + 1, iv, 12); + iw = _mm_loadu_si128((const void *)ivtmp); + cw = _mm_loadu_si128((const void *)CW); + one = _mm_set_epi32(0, 0, 0, 1); + + while (len > 0) { + /* + * sj contains state words 4*j to 4*j+3. + */ + __m128i s0, s1, s2, s3; + int i; + + s0 = cw; + s1 = kw0; + s2 = kw1; + s3 = iw; + for (i = 0; i < 10; i ++) { + /* + * Even round is straightforward application on + * the state words. + */ + s0 = _mm_add_epi32(s0, s1); + s3 = _mm_xor_si128(s3, s0); + s3 = _mm_or_si128( + _mm_slli_epi32(s3, 16), + _mm_srli_epi32(s3, 16)); + + s2 = _mm_add_epi32(s2, s3); + s1 = _mm_xor_si128(s1, s2); + s1 = _mm_or_si128( + _mm_slli_epi32(s1, 12), + _mm_srli_epi32(s1, 20)); + + s0 = _mm_add_epi32(s0, s1); + s3 = _mm_xor_si128(s3, s0); + s3 = _mm_or_si128( + _mm_slli_epi32(s3, 8), + _mm_srli_epi32(s3, 24)); + + s2 = _mm_add_epi32(s2, s3); + s1 = _mm_xor_si128(s1, s2); + s1 = _mm_or_si128( + _mm_slli_epi32(s1, 7), + _mm_srli_epi32(s1, 25)); + + /* + * For the odd round, we must rotate some state + * words so that the computations apply on the + * right combinations of words. + */ + s1 = _mm_shuffle_epi32(s1, 0x39); + s2 = _mm_shuffle_epi32(s2, 0x4E); + s3 = _mm_shuffle_epi32(s3, 0x93); + + s0 = _mm_add_epi32(s0, s1); + s3 = _mm_xor_si128(s3, s0); + s3 = _mm_or_si128( + _mm_slli_epi32(s3, 16), + _mm_srli_epi32(s3, 16)); + + s2 = _mm_add_epi32(s2, s3); + s1 = _mm_xor_si128(s1, s2); + s1 = _mm_or_si128( + _mm_slli_epi32(s1, 12), + _mm_srli_epi32(s1, 20)); + + s0 = _mm_add_epi32(s0, s1); + s3 = _mm_xor_si128(s3, s0); + s3 = _mm_or_si128( + _mm_slli_epi32(s3, 8), + _mm_srli_epi32(s3, 24)); + + s2 = _mm_add_epi32(s2, s3); + s1 = _mm_xor_si128(s1, s2); + s1 = _mm_or_si128( + _mm_slli_epi32(s1, 7), + _mm_srli_epi32(s1, 25)); + + /* + * After the odd round, we rotate back the values + * to undo the rotate at the start of the odd round. + */ + s1 = _mm_shuffle_epi32(s1, 0x93); + s2 = _mm_shuffle_epi32(s2, 0x4E); + s3 = _mm_shuffle_epi32(s3, 0x39); + } + + /* + * Addition with the initial state. + */ + s0 = _mm_add_epi32(s0, cw); + s1 = _mm_add_epi32(s1, kw0); + s2 = _mm_add_epi32(s2, kw1); + s3 = _mm_add_epi32(s3, iw); + + /* + * Increment block counter. + */ + iw = _mm_add_epi32(iw, one); + + /* + * XOR final state with the data. + */ + if (len < 64) { + unsigned char tmp[64]; + size_t u; + + _mm_storeu_si128((void *)(tmp + 0), s0); + _mm_storeu_si128((void *)(tmp + 16), s1); + _mm_storeu_si128((void *)(tmp + 32), s2); + _mm_storeu_si128((void *)(tmp + 48), s3); + for (u = 0; u < len; u ++) { + buf[u] ^= tmp[u]; + } + break; + } else { + __m128i b0, b1, b2, b3; + + b0 = _mm_loadu_si128((const void *)(buf + 0)); + b1 = _mm_loadu_si128((const void *)(buf + 16)); + b2 = _mm_loadu_si128((const void *)(buf + 32)); + b3 = _mm_loadu_si128((const void *)(buf + 48)); + b0 = _mm_xor_si128(b0, s0); + b1 = _mm_xor_si128(b1, s1); + b2 = _mm_xor_si128(b2, s2); + b3 = _mm_xor_si128(b3, s3); + _mm_storeu_si128((void *)(buf + 0), b0); + _mm_storeu_si128((void *)(buf + 16), b1); + _mm_storeu_si128((void *)(buf + 32), b2); + _mm_storeu_si128((void *)(buf + 48), b3); + buf += 64; + len -= 64; + } + } + + /* + * _mm_extract_epi32() requires SSE4.1. We prefer to stick to + * raw SSE2, thus we use _mm_extract_epi16(). + */ + return (uint32_t)_mm_extract_epi16(iw, 0) + | ((uint32_t)_mm_extract_epi16(iw, 1) << 16); +} + +BR_TARGETS_X86_DOWN + +#else + +/* see bearssl_block.h */ +br_chacha20_run +br_chacha20_sse2_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/des_ct.c b/BearSSL-OG/libbearssl/src/symcipher/des_ct.c new file mode 100644 index 0000000..c1e1704 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/des_ct.c @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * During key schedule, we need to apply bit extraction PC-2 then permute + * things into our bitslice representation. PC-2 extracts 48 bits out + * of two 28-bit words (kl and kr), and we store these bits into two + * 32-bit words sk0 and sk1. + * + * -- bit 16+x of sk0 comes from bit QL0[x] of kl + * -- bit x of sk0 comes from bit QR0[x] of kr + * -- bit 16+x of sk1 comes from bit QL1[x] of kl + * -- bit x of sk1 comes from bit QR1[x] of kr + */ + +static const unsigned char QL0[] = { + 17, 4, 27, 23, 13, 22, 7, 18, + 16, 24, 2, 20, 1, 8, 15, 26 +}; + +static const unsigned char QR0[] = { + 25, 19, 9, 1, 5, 11, 23, 8, + 17, 0, 22, 3, 6, 20, 27, 24 +}; + +static const unsigned char QL1[] = { + 28, 28, 14, 11, 28, 28, 25, 0, + 28, 28, 5, 9, 28, 28, 12, 21 +}; + +static const unsigned char QR1[] = { + 28, 28, 15, 4, 28, 28, 26, 16, + 28, 28, 12, 7, 28, 28, 10, 14 +}; + +/* + * 32-bit rotation. The C compiler is supposed to recognize it as a + * rotation and use the local architecture rotation opcode (if available). + */ +static __inline uint32_t +rotl(uint32_t x, int n) +{ + return (x << n) | (x >> (32 - n)); +} + +/* + * Compute key schedule for 8 key bytes (produces 32 subkey words). + */ +static void +keysched_unit(uint32_t *skey, const void *key) +{ + int i; + + br_des_keysched_unit(skey, key); + + /* + * Apply PC-2 + bitslicing. + */ + for (i = 0; i < 16; i ++) { + uint32_t kl, kr, sk0, sk1; + int j; + + kl = skey[(i << 1) + 0]; + kr = skey[(i << 1) + 1]; + sk0 = 0; + sk1 = 0; + for (j = 0; j < 16; j ++) { + sk0 <<= 1; + sk1 <<= 1; + sk0 |= ((kl >> QL0[j]) & (uint32_t)1) << 16; + sk0 |= (kr >> QR0[j]) & (uint32_t)1; + sk1 |= ((kl >> QL1[j]) & (uint32_t)1) << 16; + sk1 |= (kr >> QR1[j]) & (uint32_t)1; + } + + skey[(i << 1) + 0] = sk0; + skey[(i << 1) + 1] = sk1; + } + +#if 0 + /* + * Speed-optimized version for PC-2 + bitslicing. + * (Unused. Kept for reference only.) + */ + sk0 = kl & (uint32_t)0x00100000; + sk0 |= (kl & (uint32_t)0x08008000) << 2; + sk0 |= (kl & (uint32_t)0x00400000) << 4; + sk0 |= (kl & (uint32_t)0x00800000) << 5; + sk0 |= (kl & (uint32_t)0x00040000) << 6; + sk0 |= (kl & (uint32_t)0x00010000) << 7; + sk0 |= (kl & (uint32_t)0x00000100) << 10; + sk0 |= (kl & (uint32_t)0x00022000) << 14; + sk0 |= (kl & (uint32_t)0x00000082) << 18; + sk0 |= (kl & (uint32_t)0x00000004) << 19; + sk0 |= (kl & (uint32_t)0x04000000) >> 10; + sk0 |= (kl & (uint32_t)0x00000010) << 26; + sk0 |= (kl & (uint32_t)0x01000000) >> 2; + + sk0 |= kr & (uint32_t)0x00000100; + sk0 |= (kr & (uint32_t)0x00000008) << 1; + sk0 |= (kr & (uint32_t)0x00000200) << 4; + sk0 |= rotl(kr & (uint32_t)0x08000021, 6); + sk0 |= (kr & (uint32_t)0x01000000) >> 24; + sk0 |= (kr & (uint32_t)0x00000002) << 11; + sk0 |= (kr & (uint32_t)0x00100000) >> 18; + sk0 |= (kr & (uint32_t)0x00400000) >> 17; + sk0 |= (kr & (uint32_t)0x00800000) >> 14; + sk0 |= (kr & (uint32_t)0x02020000) >> 10; + sk0 |= (kr & (uint32_t)0x00080000) >> 5; + sk0 |= (kr & (uint32_t)0x00000040) >> 3; + sk0 |= (kr & (uint32_t)0x00000800) >> 1; + + sk1 = kl & (uint32_t)0x02000000; + sk1 |= (kl & (uint32_t)0x00001000) << 5; + sk1 |= (kl & (uint32_t)0x00000200) << 11; + sk1 |= (kl & (uint32_t)0x00004000) << 15; + sk1 |= (kl & (uint32_t)0x00000020) << 16; + sk1 |= (kl & (uint32_t)0x00000800) << 17; + sk1 |= (kl & (uint32_t)0x00000001) << 24; + sk1 |= (kl & (uint32_t)0x00200000) >> 5; + + sk1 |= (kr & (uint32_t)0x00000010) << 8; + sk1 |= (kr & (uint32_t)0x04000000) >> 17; + sk1 |= (kr & (uint32_t)0x00004000) >> 14; + sk1 |= (kr & (uint32_t)0x00000400) >> 9; + sk1 |= (kr & (uint32_t)0x00010000) >> 8; + sk1 |= (kr & (uint32_t)0x00001000) >> 7; + sk1 |= (kr & (uint32_t)0x00000080) >> 3; + sk1 |= (kr & (uint32_t)0x00008000) >> 2; +#endif +} + +/* see inner.h */ +unsigned +br_des_ct_keysched(uint32_t *skey, const void *key, size_t key_len) +{ + switch (key_len) { + case 8: + keysched_unit(skey, key); + return 1; + case 16: + keysched_unit(skey, key); + keysched_unit(skey + 32, (const unsigned char *)key + 8); + br_des_rev_skey(skey + 32); + memcpy(skey + 64, skey, 32 * sizeof *skey); + return 3; + default: + keysched_unit(skey, key); + keysched_unit(skey + 32, (const unsigned char *)key + 8); + br_des_rev_skey(skey + 32); + keysched_unit(skey + 64, (const unsigned char *)key + 16); + return 3; + } +} + +/* + * DES confusion function. This function performs expansion E (32 to + * 48 bits), XOR with subkey, S-boxes, and permutation P. + */ +static __inline uint32_t +Fconf(uint32_t r0, const uint32_t *sk) +{ + /* + * Each 6->4 S-box is virtually turned into four 6->1 boxes; we + * thus end up with 32 boxes that we call "T-boxes" here. We will + * evaluate them with bitslice code. + * + * Each T-box is a circuit of multiplexers (sort of) and thus + * takes 70 inputs: the 6 actual T-box inputs, and 64 constants + * that describe the T-box output for all combinations of the + * 6 inputs. With this model, all T-boxes are identical (with + * distinct inputs) and thus can be executed in parallel with + * bitslice code. + * + * T-boxes are numbered from 0 to 31, in least-to-most + * significant order. Thus, S-box S1 corresponds to T-boxes 31, + * 30, 29 and 28, in that order. T-box 'n' is computed with the + * bits at rank 'n' in the 32-bit words. + * + * Words x0 to x5 contain the T-box inputs 0 to 5. + */ + uint32_t x0, x1, x2, x3, x4, x5, z0; + uint32_t y0, y1, y2, y3, y4, y5, y6, y7, y8, y9; + uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + uint32_t y20, y21, y22, y23, y24, y25, y26, y27, y28, y29; + uint32_t y30; + + /* + * Spread input bits over the 6 input words x*. + */ + x1 = r0 & (uint32_t)0x11111111; + x2 = (r0 >> 1) & (uint32_t)0x11111111; + x3 = (r0 >> 2) & (uint32_t)0x11111111; + x4 = (r0 >> 3) & (uint32_t)0x11111111; + x1 = (x1 << 4) - x1; + x2 = (x2 << 4) - x2; + x3 = (x3 << 4) - x3; + x4 = (x4 << 4) - x4; + x0 = (x4 << 4) | (x4 >> 28); + x5 = (x1 >> 4) | (x1 << 28); + + /* + * XOR with the subkey for this round. + */ + x0 ^= sk[0]; + x1 ^= sk[1]; + x2 ^= sk[2]; + x3 ^= sk[3]; + x4 ^= sk[4]; + x5 ^= sk[5]; + + /* + * The T-boxes are done in parallel, since they all use a + * "tree of multiplexer". We use "fake multiplexers": + * + * y = a ^ (x & b) + * + * computes y as either 'a' (if x == 0) or 'a ^ b' (if x == 1). + */ + y0 = (uint32_t)0xEFA72C4D ^ (x0 & (uint32_t)0xEC7AC69C); + y1 = (uint32_t)0xAEAAEDFF ^ (x0 & (uint32_t)0x500FB821); + y2 = (uint32_t)0x37396665 ^ (x0 & (uint32_t)0x40EFA809); + y3 = (uint32_t)0x68D7B833 ^ (x0 & (uint32_t)0xA5EC0B28); + y4 = (uint32_t)0xC9C755BB ^ (x0 & (uint32_t)0x252CF820); + y5 = (uint32_t)0x73FC3606 ^ (x0 & (uint32_t)0x40205801); + y6 = (uint32_t)0xA2A0A918 ^ (x0 & (uint32_t)0xE220F929); + y7 = (uint32_t)0x8222BD90 ^ (x0 & (uint32_t)0x44A3F9E1); + y8 = (uint32_t)0xD6B6AC77 ^ (x0 & (uint32_t)0x794F104A); + y9 = (uint32_t)0x3069300C ^ (x0 & (uint32_t)0x026F320B); + y10 = (uint32_t)0x6CE0D5CC ^ (x0 & (uint32_t)0x7640B01A); + y11 = (uint32_t)0x59A9A22D ^ (x0 & (uint32_t)0x238F1572); + y12 = (uint32_t)0xAC6D0BD4 ^ (x0 & (uint32_t)0x7A63C083); + y13 = (uint32_t)0x21C83200 ^ (x0 & (uint32_t)0x11CCA000); + y14 = (uint32_t)0xA0E62188 ^ (x0 & (uint32_t)0x202F69AA); + /* y15 = (uint32_t)0x00000000 ^ (x0 & (uint32_t)0x00000000); */ + y16 = (uint32_t)0xAF7D655A ^ (x0 & (uint32_t)0x51B33BE9); + y17 = (uint32_t)0xF0168AA3 ^ (x0 & (uint32_t)0x3B0FE8AE); + y18 = (uint32_t)0x90AA30C6 ^ (x0 & (uint32_t)0x90BF8816); + y19 = (uint32_t)0x5AB2750A ^ (x0 & (uint32_t)0x09E34F9B); + y20 = (uint32_t)0x5391BE65 ^ (x0 & (uint32_t)0x0103BE88); + y21 = (uint32_t)0x93372BAF ^ (x0 & (uint32_t)0x49AC8E25); + y22 = (uint32_t)0xF288210C ^ (x0 & (uint32_t)0x922C313D); + y23 = (uint32_t)0x920AF5C0 ^ (x0 & (uint32_t)0x70EF31B0); + y24 = (uint32_t)0x63D312C0 ^ (x0 & (uint32_t)0x6A707100); + y25 = (uint32_t)0x537B3006 ^ (x0 & (uint32_t)0xB97C9011); + y26 = (uint32_t)0xA2EFB0A5 ^ (x0 & (uint32_t)0xA320C959); + y27 = (uint32_t)0xBC8F96A5 ^ (x0 & (uint32_t)0x6EA0AB4A); + y28 = (uint32_t)0xFAD176A5 ^ (x0 & (uint32_t)0x6953DDF8); + y29 = (uint32_t)0x665A14A3 ^ (x0 & (uint32_t)0xF74F3E2B); + y30 = (uint32_t)0xF2EFF0CC ^ (x0 & (uint32_t)0xF0306CAD); + /* y31 = (uint32_t)0x00000000 ^ (x0 & (uint32_t)0x00000000); */ + + y0 = y0 ^ (x1 & y1); + y1 = y2 ^ (x1 & y3); + y2 = y4 ^ (x1 & y5); + y3 = y6 ^ (x1 & y7); + y4 = y8 ^ (x1 & y9); + y5 = y10 ^ (x1 & y11); + y6 = y12 ^ (x1 & y13); + y7 = y14; /* was: y14 ^ (x1 & y15) */ + y8 = y16 ^ (x1 & y17); + y9 = y18 ^ (x1 & y19); + y10 = y20 ^ (x1 & y21); + y11 = y22 ^ (x1 & y23); + y12 = y24 ^ (x1 & y25); + y13 = y26 ^ (x1 & y27); + y14 = y28 ^ (x1 & y29); + y15 = y30; /* was: y30 ^ (x1 & y31) */ + + y0 = y0 ^ (x2 & y1); + y1 = y2 ^ (x2 & y3); + y2 = y4 ^ (x2 & y5); + y3 = y6 ^ (x2 & y7); + y4 = y8 ^ (x2 & y9); + y5 = y10 ^ (x2 & y11); + y6 = y12 ^ (x2 & y13); + y7 = y14 ^ (x2 & y15); + + y0 = y0 ^ (x3 & y1); + y1 = y2 ^ (x3 & y3); + y2 = y4 ^ (x3 & y5); + y3 = y6 ^ (x3 & y7); + + y0 = y0 ^ (x4 & y1); + y1 = y2 ^ (x4 & y3); + + y0 = y0 ^ (x5 & y1); + + /* + * The P permutation: + * -- Each bit move is converted into a mask + left rotation. + * -- Rotations that use the same movement are coalesced together. + * -- Left and right shifts are used as alternatives to a rotation + * where appropriate (this will help architectures that do not have + * a rotation opcode). + */ + z0 = (y0 & (uint32_t)0x00000004) << 3; + z0 |= (y0 & (uint32_t)0x00004000) << 4; + z0 |= rotl(y0 & 0x12020120, 5); + z0 |= (y0 & (uint32_t)0x00100000) << 6; + z0 |= (y0 & (uint32_t)0x00008000) << 9; + z0 |= (y0 & (uint32_t)0x04000000) >> 22; + z0 |= (y0 & (uint32_t)0x00000001) << 11; + z0 |= rotl(y0 & 0x20000200, 12); + z0 |= (y0 & (uint32_t)0x00200000) >> 19; + z0 |= (y0 & (uint32_t)0x00000040) << 14; + z0 |= (y0 & (uint32_t)0x00010000) << 15; + z0 |= (y0 & (uint32_t)0x00000002) << 16; + z0 |= rotl(y0 & 0x40801800, 17); + z0 |= (y0 & (uint32_t)0x00080000) >> 13; + z0 |= (y0 & (uint32_t)0x00000010) << 21; + z0 |= (y0 & (uint32_t)0x01000000) >> 10; + z0 |= rotl(y0 & 0x88000008, 24); + z0 |= (y0 & (uint32_t)0x00000480) >> 7; + z0 |= (y0 & (uint32_t)0x00442000) >> 6; + return z0; +} + +/* + * Process one block through 16 successive rounds, omitting the swap + * in the final round. + */ +static void +process_block_unit(uint32_t *pl, uint32_t *pr, const uint32_t *sk_exp) +{ + int i; + uint32_t l, r; + + l = *pl; + r = *pr; + for (i = 0; i < 16; i ++) { + uint32_t t; + + t = l ^ Fconf(r, sk_exp); + l = r; + r = t; + sk_exp += 6; + } + *pl = r; + *pr = l; +} + +/* see inner.h */ +void +br_des_ct_process_block(unsigned num_rounds, + const uint32_t *sk_exp, void *block) +{ + unsigned char *buf; + uint32_t l, r; + + buf = block; + l = br_dec32be(buf); + r = br_dec32be(buf + 4); + br_des_do_IP(&l, &r); + while (num_rounds -- > 0) { + process_block_unit(&l, &r, sk_exp); + sk_exp += 96; + } + br_des_do_invIP(&l, &r); + br_enc32be(buf, l); + br_enc32be(buf + 4, r); +} + +/* see inner.h */ +void +br_des_ct_skey_expand(uint32_t *sk_exp, + unsigned num_rounds, const uint32_t *skey) +{ + num_rounds <<= 4; + while (num_rounds -- > 0) { + uint32_t v, w0, w1, w2, w3; + + v = *skey ++; + w0 = v & 0x11111111; + w1 = (v >> 1) & 0x11111111; + w2 = (v >> 2) & 0x11111111; + w3 = (v >> 3) & 0x11111111; + *sk_exp ++ = (w0 << 4) - w0; + *sk_exp ++ = (w1 << 4) - w1; + *sk_exp ++ = (w2 << 4) - w2; + *sk_exp ++ = (w3 << 4) - w3; + v = *skey ++; + w0 = v & 0x11111111; + w1 = (v >> 1) & 0x11111111; + *sk_exp ++ = (w0 << 4) - w0; + *sk_exp ++ = (w1 << 4) - w1; + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/des_ct_cbcdec.c b/BearSSL-OG/libbearssl/src/symcipher/des_ct_cbcdec.c new file mode 100644 index 0000000..d208a3d --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/des_ct_cbcdec.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_des_ct_cbcdec_vtable; + ctx->num_rounds = br_des_ct_keysched(ctx->skey, key, len); + if (len == 8) { + br_des_rev_skey(ctx->skey); + } else { + int i; + + for (i = 0; i < 48; i += 2) { + uint32_t t; + + t = ctx->skey[i]; + ctx->skey[i] = ctx->skey[94 - i]; + ctx->skey[94 - i] = t; + t = ctx->skey[i + 1]; + ctx->skey[i + 1] = ctx->skey[95 - i]; + ctx->skey[95 - i] = t; + } + } +} + +/* see bearssl_block.h */ +void +br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + uint32_t sk_exp[288]; + + br_des_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + ivbuf = iv; + buf = data; + while (len > 0) { + unsigned char tmp[8]; + int i; + + memcpy(tmp, buf, 8); + br_des_ct_process_block(ctx->num_rounds, sk_exp, buf); + for (i = 0; i < 8; i ++) { + buf[i] ^= ivbuf[i]; + } + memcpy(ivbuf, tmp, 8); + buf += 8; + len -= 8; + } +} + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_des_ct_cbcdec_vtable = { + sizeof(br_des_ct_cbcdec_keys), + 8, + 3, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_des_ct_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_des_ct_cbcdec_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/des_ct_cbcenc.c b/BearSSL-OG/libbearssl/src/symcipher/des_ct_cbcenc.c new file mode 100644 index 0000000..4b3610e --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/des_ct_cbcenc.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_des_ct_cbcenc_vtable; + ctx->num_rounds = br_des_ct_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + uint32_t sk_exp[288]; + + br_des_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); + ivbuf = iv; + buf = data; + while (len > 0) { + int i; + + for (i = 0; i < 8; i ++) { + buf[i] ^= ivbuf[i]; + } + br_des_ct_process_block(ctx->num_rounds, sk_exp, buf); + memcpy(ivbuf, buf, 8); + buf += 8; + len -= 8; + } +} + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_des_ct_cbcenc_vtable = { + sizeof(br_des_ct_cbcenc_keys), + 8, + 3, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_des_ct_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_des_ct_cbcenc_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/des_support.c b/BearSSL-OG/libbearssl/src/symcipher/des_support.c new file mode 100644 index 0000000..37f6db3 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/des_support.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see inner.h */ +void +br_des_do_IP(uint32_t *xl, uint32_t *xr) +{ + /* + * Permutation algorithm is initially from Richard Outerbridge; + * implementation here is adapted from Crypto++ "des.cpp" file + * (which is in public domain). + */ + uint32_t l, r, t; + + l = *xl; + r = *xr; + t = ((l >> 4) ^ r) & (uint32_t)0x0F0F0F0F; + r ^= t; + l ^= t << 4; + t = ((l >> 16) ^ r) & (uint32_t)0x0000FFFF; + r ^= t; + l ^= t << 16; + t = ((r >> 2) ^ l) & (uint32_t)0x33333333; + l ^= t; + r ^= t << 2; + t = ((r >> 8) ^ l) & (uint32_t)0x00FF00FF; + l ^= t; + r ^= t << 8; + t = ((l >> 1) ^ r) & (uint32_t)0x55555555; + r ^= t; + l ^= t << 1; + *xl = l; + *xr = r; +} + +/* see inner.h */ +void +br_des_do_invIP(uint32_t *xl, uint32_t *xr) +{ + /* + * See br_des_do_IP(). + */ + uint32_t l, r, t; + + l = *xl; + r = *xr; + t = ((l >> 1) ^ r) & 0x55555555; + r ^= t; + l ^= t << 1; + t = ((r >> 8) ^ l) & 0x00FF00FF; + l ^= t; + r ^= t << 8; + t = ((r >> 2) ^ l) & 0x33333333; + l ^= t; + r ^= t << 2; + t = ((l >> 16) ^ r) & 0x0000FFFF; + r ^= t; + l ^= t << 16; + t = ((l >> 4) ^ r) & 0x0F0F0F0F; + r ^= t; + l ^= t << 4; + *xl = l; + *xr = r; +} + +/* see inner.h */ +void +br_des_keysched_unit(uint32_t *skey, const void *key) +{ + uint32_t xl, xr, kl, kr; + int i; + + xl = br_dec32be(key); + xr = br_dec32be((const unsigned char *)key + 4); + + /* + * Permutation PC-1 is quite similar to the IP permutation. + * Definition of IP (in FIPS 46-3 notations) is: + * 58 50 42 34 26 18 10 2 + * 60 52 44 36 28 20 12 4 + * 62 54 46 38 30 22 14 6 + * 64 56 48 40 32 24 16 8 + * 57 49 41 33 25 17 9 1 + * 59 51 43 35 27 19 11 3 + * 61 53 45 37 29 21 13 5 + * 63 55 47 39 31 23 15 7 + * + * Definition of PC-1 is: + * 57 49 41 33 25 17 9 1 + * 58 50 42 34 26 18 10 2 + * 59 51 43 35 27 19 11 3 + * 60 52 44 36 + * 63 55 47 39 31 23 15 7 + * 62 54 46 38 30 22 14 6 + * 61 53 45 37 29 21 13 5 + * 28 20 12 4 + */ + br_des_do_IP(&xl, &xr); + kl = ((xr & (uint32_t)0xFF000000) >> 4) + | ((xl & (uint32_t)0xFF000000) >> 12) + | ((xr & (uint32_t)0x00FF0000) >> 12) + | ((xl & (uint32_t)0x00FF0000) >> 20); + kr = ((xr & (uint32_t)0x000000FF) << 20) + | ((xl & (uint32_t)0x0000FF00) << 4) + | ((xr & (uint32_t)0x0000FF00) >> 4) + | ((xl & (uint32_t)0x000F0000) >> 16); + + /* + * For each round, rotate the two 28-bit words kl and kr. + * The extraction of the 48-bit subkey (PC-2) is not done yet. + */ + for (i = 0; i < 16; i ++) { + if ((1 << i) & 0x8103) { + kl = (kl << 1) | (kl >> 27); + kr = (kr << 1) | (kr >> 27); + } else { + kl = (kl << 2) | (kl >> 26); + kr = (kr << 2) | (kr >> 26); + } + kl &= (uint32_t)0x0FFFFFFF; + kr &= (uint32_t)0x0FFFFFFF; + skey[(i << 1) + 0] = kl; + skey[(i << 1) + 1] = kr; + } +} + +/* see inner.h */ +void +br_des_rev_skey(uint32_t *skey) +{ + int i; + + for (i = 0; i < 16; i += 2) { + uint32_t t; + + t = skey[i + 0]; + skey[i + 0] = skey[30 - i]; + skey[30 - i] = t; + t = skey[i + 1]; + skey[i + 1] = skey[31 - i]; + skey[31 - i] = t; + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/des_tab.c b/BearSSL-OG/libbearssl/src/symcipher/des_tab.c new file mode 100644 index 0000000..d7aba0c --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/des_tab.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * PC2left[x] tells where bit x goes when applying PC-2. 'x' is a bit + * position in the left rotated key word. Both position are in normal + * order (rightmost bit is 0). + */ +static const unsigned char PC2left[] = { + 16, 3, 7, 24, 20, 11, 24, + 13, 2, 10, 24, 22, 5, 15, + 23, 1, 9, 21, 12, 24, 6, + 4, 14, 18, 8, 17, 0, 19 +}; + +/* + * Similar to PC2left[x], for the right rotated key word. + */ +static const unsigned char PC2right[] = { + 8, 18, 24, 6, 22, 15, 3, + 10, 12, 19, 5, 14, 11, 24, + 4, 23, 16, 9, 24, 20, 2, + 24, 7, 13, 0, 21, 17, 1 +}; + +/* + * S-boxes and PC-1 merged. + */ +static const uint32_t S1[] = { + 0x00808200, 0x00000000, 0x00008000, 0x00808202, + 0x00808002, 0x00008202, 0x00000002, 0x00008000, + 0x00000200, 0x00808200, 0x00808202, 0x00000200, + 0x00800202, 0x00808002, 0x00800000, 0x00000002, + 0x00000202, 0x00800200, 0x00800200, 0x00008200, + 0x00008200, 0x00808000, 0x00808000, 0x00800202, + 0x00008002, 0x00800002, 0x00800002, 0x00008002, + 0x00000000, 0x00000202, 0x00008202, 0x00800000, + 0x00008000, 0x00808202, 0x00000002, 0x00808000, + 0x00808200, 0x00800000, 0x00800000, 0x00000200, + 0x00808002, 0x00008000, 0x00008200, 0x00800002, + 0x00000200, 0x00000002, 0x00800202, 0x00008202, + 0x00808202, 0x00008002, 0x00808000, 0x00800202, + 0x00800002, 0x00000202, 0x00008202, 0x00808200, + 0x00000202, 0x00800200, 0x00800200, 0x00000000, + 0x00008002, 0x00008200, 0x00000000, 0x00808002 +}; + +static const uint32_t S2[] = { + 0x40084010, 0x40004000, 0x00004000, 0x00084010, + 0x00080000, 0x00000010, 0x40080010, 0x40004010, + 0x40000010, 0x40084010, 0x40084000, 0x40000000, + 0x40004000, 0x00080000, 0x00000010, 0x40080010, + 0x00084000, 0x00080010, 0x40004010, 0x00000000, + 0x40000000, 0x00004000, 0x00084010, 0x40080000, + 0x00080010, 0x40000010, 0x00000000, 0x00084000, + 0x00004010, 0x40084000, 0x40080000, 0x00004010, + 0x00000000, 0x00084010, 0x40080010, 0x00080000, + 0x40004010, 0x40080000, 0x40084000, 0x00004000, + 0x40080000, 0x40004000, 0x00000010, 0x40084010, + 0x00084010, 0x00000010, 0x00004000, 0x40000000, + 0x00004010, 0x40084000, 0x00080000, 0x40000010, + 0x00080010, 0x40004010, 0x40000010, 0x00080010, + 0x00084000, 0x00000000, 0x40004000, 0x00004010, + 0x40000000, 0x40080010, 0x40084010, 0x00084000 +}; + +static const uint32_t S3[] = { + 0x00000104, 0x04010100, 0x00000000, 0x04010004, + 0x04000100, 0x00000000, 0x00010104, 0x04000100, + 0x00010004, 0x04000004, 0x04000004, 0x00010000, + 0x04010104, 0x00010004, 0x04010000, 0x00000104, + 0x04000000, 0x00000004, 0x04010100, 0x00000100, + 0x00010100, 0x04010000, 0x04010004, 0x00010104, + 0x04000104, 0x00010100, 0x00010000, 0x04000104, + 0x00000004, 0x04010104, 0x00000100, 0x04000000, + 0x04010100, 0x04000000, 0x00010004, 0x00000104, + 0x00010000, 0x04010100, 0x04000100, 0x00000000, + 0x00000100, 0x00010004, 0x04010104, 0x04000100, + 0x04000004, 0x00000100, 0x00000000, 0x04010004, + 0x04000104, 0x00010000, 0x04000000, 0x04010104, + 0x00000004, 0x00010104, 0x00010100, 0x04000004, + 0x04010000, 0x04000104, 0x00000104, 0x04010000, + 0x00010104, 0x00000004, 0x04010004, 0x00010100 +}; + +static const uint32_t S4[] = { + 0x80401000, 0x80001040, 0x80001040, 0x00000040, + 0x00401040, 0x80400040, 0x80400000, 0x80001000, + 0x00000000, 0x00401000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00400040, 0x80400000, + 0x80000000, 0x00001000, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x80001000, 0x00001040, + 0x80400040, 0x80000000, 0x00001040, 0x00400040, + 0x00001000, 0x00401040, 0x80401040, 0x80000040, + 0x00400040, 0x80400000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00000000, 0x00401000, + 0x00001040, 0x00400040, 0x80400040, 0x80000000, + 0x80401000, 0x80001040, 0x80001040, 0x00000040, + 0x80401040, 0x80000040, 0x80000000, 0x00001000, + 0x80400000, 0x80001000, 0x00401040, 0x80400040, + 0x80001000, 0x00001040, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x00001000, 0x00401040 +}; + +static const uint32_t S5[] = { + 0x00000080, 0x01040080, 0x01040000, 0x21000080, + 0x00040000, 0x00000080, 0x20000000, 0x01040000, + 0x20040080, 0x00040000, 0x01000080, 0x20040080, + 0x21000080, 0x21040000, 0x00040080, 0x20000000, + 0x01000000, 0x20040000, 0x20040000, 0x00000000, + 0x20000080, 0x21040080, 0x21040080, 0x01000080, + 0x21040000, 0x20000080, 0x00000000, 0x21000000, + 0x01040080, 0x01000000, 0x21000000, 0x00040080, + 0x00040000, 0x21000080, 0x00000080, 0x01000000, + 0x20000000, 0x01040000, 0x21000080, 0x20040080, + 0x01000080, 0x20000000, 0x21040000, 0x01040080, + 0x20040080, 0x00000080, 0x01000000, 0x21040000, + 0x21040080, 0x00040080, 0x21000000, 0x21040080, + 0x01040000, 0x00000000, 0x20040000, 0x21000000, + 0x00040080, 0x01000080, 0x20000080, 0x00040000, + 0x00000000, 0x20040000, 0x01040080, 0x20000080 +}; + +static const uint32_t S6[] = { + 0x10000008, 0x10200000, 0x00002000, 0x10202008, + 0x10200000, 0x00000008, 0x10202008, 0x00200000, + 0x10002000, 0x00202008, 0x00200000, 0x10000008, + 0x00200008, 0x10002000, 0x10000000, 0x00002008, + 0x00000000, 0x00200008, 0x10002008, 0x00002000, + 0x00202000, 0x10002008, 0x00000008, 0x10200008, + 0x10200008, 0x00000000, 0x00202008, 0x10202000, + 0x00002008, 0x00202000, 0x10202000, 0x10000000, + 0x10002000, 0x00000008, 0x10200008, 0x00202000, + 0x10202008, 0x00200000, 0x00002008, 0x10000008, + 0x00200000, 0x10002000, 0x10000000, 0x00002008, + 0x10000008, 0x10202008, 0x00202000, 0x10200000, + 0x00202008, 0x10202000, 0x00000000, 0x10200008, + 0x00000008, 0x00002000, 0x10200000, 0x00202008, + 0x00002000, 0x00200008, 0x10002008, 0x00000000, + 0x10202000, 0x10000000, 0x00200008, 0x10002008 +}; + +static const uint32_t S7[] = { + 0x00100000, 0x02100001, 0x02000401, 0x00000000, + 0x00000400, 0x02000401, 0x00100401, 0x02100400, + 0x02100401, 0x00100000, 0x00000000, 0x02000001, + 0x00000001, 0x02000000, 0x02100001, 0x00000401, + 0x02000400, 0x00100401, 0x00100001, 0x02000400, + 0x02000001, 0x02100000, 0x02100400, 0x00100001, + 0x02100000, 0x00000400, 0x00000401, 0x02100401, + 0x00100400, 0x00000001, 0x02000000, 0x00100400, + 0x02000000, 0x00100400, 0x00100000, 0x02000401, + 0x02000401, 0x02100001, 0x02100001, 0x00000001, + 0x00100001, 0x02000000, 0x02000400, 0x00100000, + 0x02100400, 0x00000401, 0x00100401, 0x02100400, + 0x00000401, 0x02000001, 0x02100401, 0x02100000, + 0x00100400, 0x00000000, 0x00000001, 0x02100401, + 0x00000000, 0x00100401, 0x02100000, 0x00000400, + 0x02000001, 0x02000400, 0x00000400, 0x00100001 +}; + +static const uint32_t S8[] = { + 0x08000820, 0x00000800, 0x00020000, 0x08020820, + 0x08000000, 0x08000820, 0x00000020, 0x08000000, + 0x00020020, 0x08020000, 0x08020820, 0x00020800, + 0x08020800, 0x00020820, 0x00000800, 0x00000020, + 0x08020000, 0x08000020, 0x08000800, 0x00000820, + 0x00020800, 0x00020020, 0x08020020, 0x08020800, + 0x00000820, 0x00000000, 0x00000000, 0x08020020, + 0x08000020, 0x08000800, 0x00020820, 0x00020000, + 0x00020820, 0x00020000, 0x08020800, 0x00000800, + 0x00000020, 0x08020020, 0x00000800, 0x00020820, + 0x08000800, 0x00000020, 0x08000020, 0x08020000, + 0x08020020, 0x08000000, 0x00020000, 0x08000820, + 0x00000000, 0x08020820, 0x00020020, 0x08000020, + 0x08020000, 0x08000800, 0x08000820, 0x00000000, + 0x08020820, 0x00020800, 0x00020800, 0x00000820, + 0x00000820, 0x00020020, 0x08000000, 0x08020800 +}; + +static __inline uint32_t +Fconf(uint32_t r0, uint32_t skl, uint32_t skr) +{ + uint32_t r1; + + r1 = (r0 << 16) | (r0 >> 16); + return + S1[((r1 >> 11) ^ (skl >> 18)) & 0x3F] + | S2[((r0 >> 23) ^ (skl >> 12)) & 0x3F] + | S3[((r0 >> 19) ^ (skl >> 6)) & 0x3F] + | S4[((r0 >> 15) ^ (skl )) & 0x3F] + | S5[((r0 >> 11) ^ (skr >> 18)) & 0x3F] + | S6[((r0 >> 7) ^ (skr >> 12)) & 0x3F] + | S7[((r0 >> 3) ^ (skr >> 6)) & 0x3F] + | S8[((r1 >> 15) ^ (skr )) & 0x3F]; +} + +static void +process_block_unit(uint32_t *pl, uint32_t *pr, const uint32_t *skey) +{ + int i; + uint32_t l, r; + + l = *pl; + r = *pr; + for (i = 0; i < 16; i ++) { + uint32_t t; + + t = l ^ Fconf(r, skey[(i << 1) + 0], skey[(i << 1) + 1]); + l = r; + r = t; + } + *pl = r; + *pr = l; +} + +/* see inner.h */ +void +br_des_tab_process_block(unsigned num_rounds, const uint32_t *skey, void *block) +{ + unsigned char *buf; + uint32_t l, r; + + buf = block; + l = br_dec32be(buf); + r = br_dec32be(buf + 4); + br_des_do_IP(&l, &r); + while (num_rounds -- > 0) { + process_block_unit(&l, &r, skey); + skey += 32; + } + br_des_do_invIP(&l, &r); + br_enc32be(buf, l); + br_enc32be(buf + 4, r); +} + +static void +keysched_unit(uint32_t *skey, const void *key) +{ + int i; + + br_des_keysched_unit(skey, key); + + /* + * Apply PC-2 to get the 48-bit subkeys. + */ + for (i = 0; i < 16; i ++) { + uint32_t xl, xr, ul, ur; + int j; + + xl = skey[(i << 1) + 0]; + xr = skey[(i << 1) + 1]; + ul = 0; + ur = 0; + for (j = 0; j < 28; j ++) { + ul |= (xl & 1) << PC2left[j]; + ur |= (xr & 1) << PC2right[j]; + xl >>= 1; + xr >>= 1; + } + skey[(i << 1) + 0] = ul; + skey[(i << 1) + 1] = ur; + } +} + +/* see inner.h */ +unsigned +br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len) +{ + switch (key_len) { + case 8: + keysched_unit(skey, key); + return 1; + case 16: + keysched_unit(skey, key); + keysched_unit(skey + 32, (const unsigned char *)key + 8); + br_des_rev_skey(skey + 32); + memcpy(skey + 64, skey, 32 * sizeof *skey); + return 3; + default: + keysched_unit(skey, key); + keysched_unit(skey + 32, (const unsigned char *)key + 8); + br_des_rev_skey(skey + 32); + keysched_unit(skey + 64, (const unsigned char *)key + 16); + return 3; + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/des_tab_cbcdec.c b/BearSSL-OG/libbearssl/src/symcipher/des_tab_cbcdec.c new file mode 100644 index 0000000..e7eabe9 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/des_tab_cbcdec.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_des_tab_cbcdec_vtable; + ctx->num_rounds = br_des_tab_keysched(ctx->skey, key, len); + if (len == 8) { + br_des_rev_skey(ctx->skey); + } else { + int i; + + for (i = 0; i < 48; i += 2) { + uint32_t t; + + t = ctx->skey[i]; + ctx->skey[i] = ctx->skey[94 - i]; + ctx->skey[94 - i] = t; + t = ctx->skey[i + 1]; + ctx->skey[i + 1] = ctx->skey[95 - i]; + ctx->skey[95 - i] = t; + } + } +} + +/* see bearssl_block.h */ +void +br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + + ivbuf = iv; + buf = data; + while (len > 0) { + unsigned char tmp[8]; + int i; + + memcpy(tmp, buf, 8); + br_des_tab_process_block(ctx->num_rounds, ctx->skey, buf); + for (i = 0; i < 8; i ++) { + buf[i] ^= ivbuf[i]; + } + memcpy(ivbuf, tmp, 8); + buf += 8; + len -= 8; + } +} + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_des_tab_cbcdec_vtable = { + sizeof(br_des_tab_cbcdec_keys), + 8, + 3, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_des_tab_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_des_tab_cbcdec_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/des_tab_cbcenc.c b/BearSSL-OG/libbearssl/src/symcipher/des_tab_cbcenc.c new file mode 100644 index 0000000..3a45ba3 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/des_tab_cbcenc.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_block.h */ +void +br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_des_tab_cbcenc_vtable; + ctx->num_rounds = br_des_tab_keysched(ctx->skey, key, len); +} + +/* see bearssl_block.h */ +void +br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf, *ivbuf; + + ivbuf = iv; + buf = data; + while (len > 0) { + int i; + + for (i = 0; i < 8; i ++) { + buf[i] ^= ivbuf[i]; + } + br_des_tab_process_block(ctx->num_rounds, ctx->skey, buf); + memcpy(ivbuf, buf, 8); + buf += 8; + len -= 8; + } +} + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_des_tab_cbcenc_vtable = { + sizeof(br_des_tab_cbcenc_keys), + 8, + 3, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_des_tab_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_des_tab_cbcenc_run +}; diff --git a/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmul.c b/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmul.c new file mode 100644 index 0000000..150e610 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmul.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* + * Perform the inner processing of blocks for Poly1305. The accumulator + * and the r key are provided as arrays of 26-bit words (these words + * are allowed to have an extra bit, i.e. use 27 bits). + * + * On output, all accumulator words fit on 26 bits, except acc[1], which + * may be slightly larger (but by a very small amount only). + */ +static void +poly1305_inner(uint32_t *acc, const uint32_t *r, const void *data, size_t len) +{ + /* + * Implementation notes: we split the 130-bit values into five + * 26-bit words. This gives us some space for carries. + * + * This code is inspired from the public-domain code available + * on: + * https://github.com/floodyberry/poly1305-donna + * + * Since we compute modulo 2^130-5, the "upper words" become + * low words with a factor of 5; that is, x*2^130 = x*5 mod p. + */ + const unsigned char *buf; + uint32_t a0, a1, a2, a3, a4; + uint32_t r0, r1, r2, r3, r4; + uint32_t u1, u2, u3, u4; + + r0 = r[0]; + r1 = r[1]; + r2 = r[2]; + r3 = r[3]; + r4 = r[4]; + + u1 = r1 * 5; + u2 = r2 * 5; + u3 = r3 * 5; + u4 = r4 * 5; + + a0 = acc[0]; + a1 = acc[1]; + a2 = acc[2]; + a3 = acc[3]; + a4 = acc[4]; + + buf = data; + while (len > 0) { + uint64_t w0, w1, w2, w3, w4; + uint64_t c; + unsigned char tmp[16]; + + /* + * If there is a partial block, right-pad it with zeros. + */ + if (len < 16) { + memset(tmp, 0, sizeof tmp); + memcpy(tmp, buf, len); + buf = tmp; + len = 16; + } + + /* + * Decode next block and apply the "high bit"; that value + * is added to the accumulator. + */ + a0 += br_dec32le(buf) & 0x03FFFFFF; + a1 += (br_dec32le(buf + 3) >> 2) & 0x03FFFFFF; + a2 += (br_dec32le(buf + 6) >> 4) & 0x03FFFFFF; + a3 += (br_dec32le(buf + 9) >> 6) & 0x03FFFFFF; + a4 += (br_dec32le(buf + 12) >> 8) | 0x01000000; + + /* + * Compute multiplication. + */ +#define M(x, y) ((uint64_t)(x) * (uint64_t)(y)) + + w0 = M(a0, r0) + M(a1, u4) + M(a2, u3) + M(a3, u2) + M(a4, u1); + w1 = M(a0, r1) + M(a1, r0) + M(a2, u4) + M(a3, u3) + M(a4, u2); + w2 = M(a0, r2) + M(a1, r1) + M(a2, r0) + M(a3, u4) + M(a4, u3); + w3 = M(a0, r3) + M(a1, r2) + M(a2, r1) + M(a3, r0) + M(a4, u4); + w4 = M(a0, r4) + M(a1, r3) + M(a2, r2) + M(a3, r1) + M(a4, r0); + +#undef M + /* + * Perform some (partial) modular reduction. This step is + * enough to keep values in ranges such that there won't + * be carry overflows. Most of the reduction was done in + * the multiplication step (by using the 'u*' values, and + * using the fact that 2^130 = -5 mod p); here we perform + * some carry propagation. + */ + c = w0 >> 26; + a0 = (uint32_t)w0 & 0x3FFFFFF; + w1 += c; + c = w1 >> 26; + a1 = (uint32_t)w1 & 0x3FFFFFF; + w2 += c; + c = w2 >> 26; + a2 = (uint32_t)w2 & 0x3FFFFFF; + w3 += c; + c = w3 >> 26; + a3 = (uint32_t)w3 & 0x3FFFFFF; + w4 += c; + c = w4 >> 26; + a4 = (uint32_t)w4 & 0x3FFFFFF; + a0 += (uint32_t)c * 5; + a1 += a0 >> 26; + a0 &= 0x3FFFFFF; + + buf += 16; + len -= 16; + } + + acc[0] = a0; + acc[1] = a1; + acc[2] = a2; + acc[3] = a3; + acc[4] = a4; +} + +/* see bearssl_block.h */ +void +br_poly1305_ctmul_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt) +{ + unsigned char pkey[32], foot[16]; + uint32_t r[5], acc[5], cc, ctl, hi; + uint64_t w; + int i; + + /* + * Compute the MAC key. The 'r' value is the first 16 bytes of + * pkey[]. + */ + memset(pkey, 0, sizeof pkey); + ichacha(key, iv, 0, pkey, sizeof pkey); + + /* + * If encrypting, ChaCha20 must run first, followed by Poly1305. + * When decrypting, the operations are reversed. + */ + if (encrypt) { + ichacha(key, iv, 1, data, len); + } + + /* + * Run Poly1305. We must process the AAD, then ciphertext, then + * the footer (with the lengths). Note that the AAD and ciphertext + * are meant to be padded with zeros up to the next multiple of 16, + * and the length of the footer is 16 bytes as well. + */ + + /* + * Decode the 'r' value into 26-bit words, with the "clamping" + * operation applied. + */ + r[0] = br_dec32le(pkey) & 0x03FFFFFF; + r[1] = (br_dec32le(pkey + 3) >> 2) & 0x03FFFF03; + r[2] = (br_dec32le(pkey + 6) >> 4) & 0x03FFC0FF; + r[3] = (br_dec32le(pkey + 9) >> 6) & 0x03F03FFF; + r[4] = (br_dec32le(pkey + 12) >> 8) & 0x000FFFFF; + + /* + * Accumulator is 0. + */ + memset(acc, 0, sizeof acc); + + /* + * Process the additional authenticated data, ciphertext, and + * footer in due order. + */ + br_enc64le(foot, (uint64_t)aad_len); + br_enc64le(foot + 8, (uint64_t)len); + poly1305_inner(acc, r, aad, aad_len); + poly1305_inner(acc, r, data, len); + poly1305_inner(acc, r, foot, sizeof foot); + + /* + * Finalise modular reduction. This is done with carry propagation + * and applying the '2^130 = -5 mod p' rule. Note that the output + * of poly1035_inner() is already mostly reduced, since only + * acc[1] may be (very slightly) above 2^26. A single loop back + * to acc[1] will be enough to make the value fit in 130 bits. + */ + cc = 0; + for (i = 1; i <= 6; i ++) { + int j; + + j = (i >= 5) ? i - 5 : i; + acc[j] += cc; + cc = acc[j] >> 26; + acc[j] &= 0x03FFFFFF; + } + + /* + * We may still have a value in the 2^130-5..2^130-1 range, in + * which case we must reduce it again. The code below selects, + * in constant-time, between 'acc' and 'acc-p', + */ + ctl = GT(acc[0], 0x03FFFFFA); + for (i = 1; i < 5; i ++) { + ctl &= EQ(acc[i], 0x03FFFFFF); + } + cc = 5; + for (i = 0; i < 5; i ++) { + uint32_t t; + + t = (acc[i] + cc); + cc = t >> 26; + t &= 0x03FFFFFF; + acc[i] = MUX(ctl, t, acc[i]); + } + + /* + * Convert back the accumulator to 32-bit words, and add the + * 's' value (second half of pkey[]). That addition is done + * modulo 2^128. + */ + w = (uint64_t)acc[0] + ((uint64_t)acc[1] << 26) + br_dec32le(pkey + 16); + br_enc32le((unsigned char *)tag, (uint32_t)w); + w = (w >> 32) + ((uint64_t)acc[2] << 20) + br_dec32le(pkey + 20); + br_enc32le((unsigned char *)tag + 4, (uint32_t)w); + w = (w >> 32) + ((uint64_t)acc[3] << 14) + br_dec32le(pkey + 24); + br_enc32le((unsigned char *)tag + 8, (uint32_t)w); + hi = (uint32_t)(w >> 32) + (acc[4] << 8) + br_dec32le(pkey + 28); + br_enc32le((unsigned char *)tag + 12, hi); + + /* + * If decrypting, then ChaCha20 runs _after_ Poly1305. + */ + if (!encrypt) { + ichacha(key, iv, 1, data, len); + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmul32.c b/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmul32.c new file mode 100644 index 0000000..15d9635 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmul32.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * Perform the inner processing of blocks for Poly1305. + */ +static void +poly1305_inner(uint32_t *a, const uint32_t *r, const void *data, size_t len) +{ + /* + * Implementation notes: we split the 130-bit values into ten + * 13-bit words. This gives us some space for carries and allows + * using only 32x32->32 multiplications, which are way faster than + * 32x32->64 multiplications on the ARM Cortex-M0/M0+, and also + * help in making constant-time code on the Cortex-M3. + * + * Since we compute modulo 2^130-5, the "upper words" become + * low words with a factor of 5; that is, x*2^130 = x*5 mod p. + * This has already been integrated in the r[] array, which + * is extended to the 0..18 range. + * + * In each loop iteration, a[] and r[] words are 13-bit each, + * except a[1] which may use 14 bits. + */ + const unsigned char *buf; + + buf = data; + while (len > 0) { + unsigned char tmp[16]; + uint32_t b[10]; + unsigned u, v; + uint32_t z, cc1, cc2; + + /* + * If there is a partial block, right-pad it with zeros. + */ + if (len < 16) { + memset(tmp, 0, sizeof tmp); + memcpy(tmp, buf, len); + buf = tmp; + len = 16; + } + + /* + * Decode next block and apply the "high bit"; that value + * is added to the accumulator. + */ + v = br_dec16le(buf); + a[0] += v & 0x01FFF; + v >>= 13; + v |= buf[2] << 3; + v |= buf[3] << 11; + a[1] += v & 0x01FFF; + v >>= 13; + v |= buf[4] << 6; + a[2] += v & 0x01FFF; + v >>= 13; + v |= buf[5] << 1; + v |= buf[6] << 9; + a[3] += v & 0x01FFF; + v >>= 13; + v |= buf[7] << 4; + v |= buf[8] << 12; + a[4] += v & 0x01FFF; + v >>= 13; + v |= buf[9] << 7; + a[5] += v & 0x01FFF; + v >>= 13; + v |= buf[10] << 2; + v |= buf[11] << 10; + a[6] += v & 0x01FFF; + v >>= 13; + v |= buf[12] << 5; + a[7] += v & 0x01FFF; + v = br_dec16le(buf + 13); + a[8] += v & 0x01FFF; + v >>= 13; + v |= buf[15] << 3; + a[9] += v | 0x00800; + + /* + * At that point, all a[] values fit on 14 bits, while + * all r[] values fit on 13 bits. Thus products fit on + * 27 bits, and we can accumulate up to 31 of them in + * a 32-bit word and still have some room for carries. + */ + + /* + * Now a[] contains words with values up to 14 bits each. + * We perform the multiplication with r[]. + * + * The extended words of r[] may be larger than 13 bits + * (they are 5 times a 13-bit word) so the full summation + * may yield values up to 46 times a 27-bit word, which + * does not fit on a 32-bit word. To avoid that issue, we + * must split the loop below in two, with a carry + * propagation operation in the middle. + */ + cc1 = 0; + for (u = 0; u < 10; u ++) { + uint32_t s; + + s = cc1 + + MUL15(a[0], r[u + 9 - 0]) + + MUL15(a[1], r[u + 9 - 1]) + + MUL15(a[2], r[u + 9 - 2]) + + MUL15(a[3], r[u + 9 - 3]) + + MUL15(a[4], r[u + 9 - 4]); + b[u] = s & 0x1FFF; + cc1 = s >> 13; + } + cc2 = 0; + for (u = 0; u < 10; u ++) { + uint32_t s; + + s = b[u] + cc2 + + MUL15(a[5], r[u + 9 - 5]) + + MUL15(a[6], r[u + 9 - 6]) + + MUL15(a[7], r[u + 9 - 7]) + + MUL15(a[8], r[u + 9 - 8]) + + MUL15(a[9], r[u + 9 - 9]); + b[u] = s & 0x1FFF; + cc2 = s >> 13; + } + memcpy(a, b, sizeof b); + + /* + * The two carries "loop back" with a factor of 5. We + * propagate them into a[0] and a[1]. + */ + z = cc1 + cc2; + z += (z << 2) + a[0]; + a[0] = z & 0x1FFF; + a[1] += z >> 13; + + buf += 16; + len -= 16; + } +} + +/* see bearssl_block.h */ +void +br_poly1305_ctmul32_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt) +{ + unsigned char pkey[32], foot[16]; + uint32_t z, r[19], acc[10], cc, ctl; + int i; + + /* + * Compute the MAC key. The 'r' value is the first 16 bytes of + * pkey[]. + */ + memset(pkey, 0, sizeof pkey); + ichacha(key, iv, 0, pkey, sizeof pkey); + + /* + * If encrypting, ChaCha20 must run first, followed by Poly1305. + * When decrypting, the operations are reversed. + */ + if (encrypt) { + ichacha(key, iv, 1, data, len); + } + + /* + * Run Poly1305. We must process the AAD, then ciphertext, then + * the footer (with the lengths). Note that the AAD and ciphertext + * are meant to be padded with zeros up to the next multiple of 16, + * and the length of the footer is 16 bytes as well. + */ + + /* + * Decode the 'r' value into 13-bit words, with the "clamping" + * operation applied. + */ + z = br_dec32le(pkey) & 0x03FFFFFF; + r[9] = z & 0x1FFF; + r[10] = z >> 13; + z = (br_dec32le(pkey + 3) >> 2) & 0x03FFFF03; + r[11] = z & 0x1FFF; + r[12] = z >> 13; + z = (br_dec32le(pkey + 6) >> 4) & 0x03FFC0FF; + r[13] = z & 0x1FFF; + r[14] = z >> 13; + z = (br_dec32le(pkey + 9) >> 6) & 0x03F03FFF; + r[15] = z & 0x1FFF; + r[16] = z >> 13; + z = (br_dec32le(pkey + 12) >> 8) & 0x000FFFFF; + r[17] = z & 0x1FFF; + r[18] = z >> 13; + + /* + * Extend r[] with the 5x factor pre-applied. + */ + for (i = 0; i < 9; i ++) { + r[i] = MUL15(5, r[i + 10]); + } + + /* + * Accumulator is 0. + */ + memset(acc, 0, sizeof acc); + + /* + * Process the additional authenticated data, ciphertext, and + * footer in due order. + */ + br_enc64le(foot, (uint64_t)aad_len); + br_enc64le(foot + 8, (uint64_t)len); + poly1305_inner(acc, r, aad, aad_len); + poly1305_inner(acc, r, data, len); + poly1305_inner(acc, r, foot, sizeof foot); + + /* + * Finalise modular reduction. This is done with carry propagation + * and applying the '2^130 = -5 mod p' rule. Note that the output + * of poly1035_inner() is already mostly reduced, since only + * acc[1] may be (very slightly) above 2^13. A single loop back + * to acc[1] will be enough to make the value fit in 130 bits. + */ + cc = 0; + for (i = 1; i < 10; i ++) { + z = acc[i] + cc; + acc[i] = z & 0x1FFF; + cc = z >> 13; + } + z = acc[0] + cc + (cc << 2); + acc[0] = z & 0x1FFF; + acc[1] += z >> 13; + + /* + * We may still have a value in the 2^130-5..2^130-1 range, in + * which case we must reduce it again. The code below selects, + * in constant-time, between 'acc' and 'acc-p', + */ + ctl = GT(acc[0], 0x1FFA); + for (i = 1; i < 10; i ++) { + ctl &= EQ(acc[i], 0x1FFF); + } + acc[0] = MUX(ctl, acc[0] - 0x1FFB, acc[0]); + for (i = 1; i < 10; i ++) { + acc[i] &= ~(-ctl); + } + + /* + * Convert back the accumulator to 32-bit words, and add the + * 's' value (second half of pkey[]). That addition is done + * modulo 2^128. + */ + z = acc[0] + (acc[1] << 13) + br_dec16le(pkey + 16); + br_enc16le((unsigned char *)tag, z & 0xFFFF); + z = (z >> 16) + (acc[2] << 10) + br_dec16le(pkey + 18); + br_enc16le((unsigned char *)tag + 2, z & 0xFFFF); + z = (z >> 16) + (acc[3] << 7) + br_dec16le(pkey + 20); + br_enc16le((unsigned char *)tag + 4, z & 0xFFFF); + z = (z >> 16) + (acc[4] << 4) + br_dec16le(pkey + 22); + br_enc16le((unsigned char *)tag + 6, z & 0xFFFF); + z = (z >> 16) + (acc[5] << 1) + (acc[6] << 14) + br_dec16le(pkey + 24); + br_enc16le((unsigned char *)tag + 8, z & 0xFFFF); + z = (z >> 16) + (acc[7] << 11) + br_dec16le(pkey + 26); + br_enc16le((unsigned char *)tag + 10, z & 0xFFFF); + z = (z >> 16) + (acc[8] << 8) + br_dec16le(pkey + 28); + br_enc16le((unsigned char *)tag + 12, z & 0xFFFF); + z = (z >> 16) + (acc[9] << 5) + br_dec16le(pkey + 30); + br_enc16le((unsigned char *)tag + 14, z & 0xFFFF); + + /* + * If decrypting, then ChaCha20 runs _after_ Poly1305. + */ + if (!encrypt) { + ichacha(key, iv, 1, data, len); + } +} diff --git a/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmulq.c b/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmulq.c new file mode 100644 index 0000000..b00683a --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/poly1305_ctmulq.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +#if BR_INT128 || BR_UMUL128 + +#if BR_INT128 + +#define MUL128(hi, lo, x, y) do { \ + unsigned __int128 mul128tmp; \ + mul128tmp = (unsigned __int128)(x) * (unsigned __int128)(y); \ + (hi) = (uint64_t)(mul128tmp >> 64); \ + (lo) = (uint64_t)mul128tmp; \ + } while (0) + +#elif BR_UMUL128 + +#include + +#define MUL128(hi, lo, x, y) do { \ + (lo) = _umul128((x), (y), &(hi)); \ + } while (0) + +#endif + +#define MASK42 ((uint64_t)0x000003FFFFFFFFFF) +#define MASK44 ((uint64_t)0x00000FFFFFFFFFFF) + +/* + * The "accumulator" word is nominally a 130-bit value. We split it into + * words of 44 bits, each held in a 64-bit variable. + * + * If the current accumulator is a = a0 + a1*W + a2*W^2 (where W = 2^44) + * and r = r0 + r1*W + r2*W^2, then: + * + * a*r = (a0*r0) + * + (a0*r1 + a1*r0) * W + * + (a0*r2 + a1*r1 + a2*r0) * W^2 + * + (a1*r2 + a2*r1) * W^3 + * + (a2*r2) * W^4 + * + * We want to reduce that value modulo p = 2^130-5, so W^3 = 20 mod p, + * and W^4 = 20*W mod p. Thus, if we define u1 = 20*r1 and u2 = 20*r2, + * then the equations above become: + * + * b0 = a0*r0 + a1*u2 + a2*u1 + * b1 = a0*r1 + a1*r0 + a2*u2 + * b2 = a0*r2 + a1*r1 + a2*r0 + * + * In order to make u1 fit in 44 bits, we can change these equations + * into: + * + * b0 = a0*r0 + a1*u2 + a2*t1 + * b1 = a0*r1 + a1*r0 + a2*t2 + * b2 = a0*r2 + a1*r1 + a2*r0 + * + * Where t1 is u1 truncated to 44 bits, and t2 is u2 added to the extra + * bits of u1. Note that since r is clamped down to a 124-bit value, the + * values u2 and t2 fit on 44 bits too. + * + * The bx values are larger than 44 bits, so we may split them into a + * lower half (cx, 44 bits) and an upper half (dx). The new values for + * the accumulator are then: + * + * e0 = c0 + 20*d2 + * e1 = c1 + d0 + * e2 = c2 + d1 + * + * The equations allow for some room, i.e. the ax values may be larger + * than 44 bits. Similarly, the ex values will usually be larger than + * the ax. Thus, some sort of carry propagation must be done regularly, + * though not necessarily at each iteration. In particular, we do not + * need to compute the additions (for the bx values) over 128-bit + * quantities; we can stick to 64-bit computations. + * + * + * Since the 128-bit result of a 64x64 multiplication is actually + * represented over two 64-bit registers, it is cheaper to arrange for + * any split that happens between the "high" and "low" halves to be on + * that 64-bit boundary. This is done by left shifting the rx, ux and tx + * by 20 bits (since they all fit on 44 bits each, this shift is + * always possible). + */ + +static void +poly1305_inner_big(uint64_t *acc, uint64_t *r, const void *data, size_t len) +{ + +#define MX(hi, lo, m0, m1, m2) do { \ + uint64_t mxhi, mxlo; \ + MUL128(mxhi, mxlo, a0, m0); \ + (hi) = mxhi; \ + (lo) = mxlo >> 20; \ + MUL128(mxhi, mxlo, a1, m1); \ + (hi) += mxhi; \ + (lo) += mxlo >> 20; \ + MUL128(mxhi, mxlo, a2, m2); \ + (hi) += mxhi; \ + (lo) += mxlo >> 20; \ + } while (0) + + const unsigned char *buf; + uint64_t a0, a1, a2; + uint64_t r0, r1, r2, t1, t2, u2; + + r0 = r[0]; + r1 = r[1]; + r2 = r[2]; + t1 = r[3]; + t2 = r[4]; + u2 = r[5]; + a0 = acc[0]; + a1 = acc[1]; + a2 = acc[2]; + buf = data; + + while (len > 0) { + uint64_t v0, v1, v2; + uint64_t c0, c1, c2, d0, d1, d2; + + v0 = br_dec64le(buf + 0); + v1 = br_dec64le(buf + 8); + v2 = v1 >> 24; + v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; + v0 &= MASK44; + a0 += v0; + a1 += v1; + a2 += v2 + ((uint64_t)1 << 40); + MX(d0, c0, r0, u2, t1); + MX(d1, c1, r1, r0, t2); + MX(d2, c2, r2, r1, r0); + a0 = c0 + 20 * d2; + a1 = c1 + d0; + a2 = c2 + d1; + + v0 = br_dec64le(buf + 16); + v1 = br_dec64le(buf + 24); + v2 = v1 >> 24; + v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; + v0 &= MASK44; + a0 += v0; + a1 += v1; + a2 += v2 + ((uint64_t)1 << 40); + MX(d0, c0, r0, u2, t1); + MX(d1, c1, r1, r0, t2); + MX(d2, c2, r2, r1, r0); + a0 = c0 + 20 * d2; + a1 = c1 + d0; + a2 = c2 + d1; + + v0 = br_dec64le(buf + 32); + v1 = br_dec64le(buf + 40); + v2 = v1 >> 24; + v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; + v0 &= MASK44; + a0 += v0; + a1 += v1; + a2 += v2 + ((uint64_t)1 << 40); + MX(d0, c0, r0, u2, t1); + MX(d1, c1, r1, r0, t2); + MX(d2, c2, r2, r1, r0); + a0 = c0 + 20 * d2; + a1 = c1 + d0; + a2 = c2 + d1; + + v0 = br_dec64le(buf + 48); + v1 = br_dec64le(buf + 56); + v2 = v1 >> 24; + v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; + v0 &= MASK44; + a0 += v0; + a1 += v1; + a2 += v2 + ((uint64_t)1 << 40); + MX(d0, c0, r0, u2, t1); + MX(d1, c1, r1, r0, t2); + MX(d2, c2, r2, r1, r0); + a0 = c0 + 20 * d2; + a1 = c1 + d0; + a2 = c2 + d1; + + a1 += a0 >> 44; + a0 &= MASK44; + a2 += a1 >> 44; + a1 &= MASK44; + a0 += 20 * (a2 >> 44); + a2 &= MASK44; + + buf += 64; + len -= 64; + } + acc[0] = a0; + acc[1] = a1; + acc[2] = a2; + +#undef MX +} + +static void +poly1305_inner_small(uint64_t *acc, uint64_t *r, const void *data, size_t len) +{ + const unsigned char *buf; + uint64_t a0, a1, a2; + uint64_t r0, r1, r2, t1, t2, u2; + + r0 = r[0]; + r1 = r[1]; + r2 = r[2]; + t1 = r[3]; + t2 = r[4]; + u2 = r[5]; + a0 = acc[0]; + a1 = acc[1]; + a2 = acc[2]; + buf = data; + + while (len > 0) { + uint64_t v0, v1, v2; + uint64_t c0, c1, c2, d0, d1, d2; + unsigned char tmp[16]; + + if (len < 16) { + memcpy(tmp, buf, len); + memset(tmp + len, 0, (sizeof tmp) - len); + buf = tmp; + len = 16; + } + v0 = br_dec64le(buf + 0); + v1 = br_dec64le(buf + 8); + + v2 = v1 >> 24; + v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; + v0 &= MASK44; + + a0 += v0; + a1 += v1; + a2 += v2 + ((uint64_t)1 << 40); + +#define MX(hi, lo, m0, m1, m2) do { \ + uint64_t mxhi, mxlo; \ + MUL128(mxhi, mxlo, a0, m0); \ + (hi) = mxhi; \ + (lo) = mxlo >> 20; \ + MUL128(mxhi, mxlo, a1, m1); \ + (hi) += mxhi; \ + (lo) += mxlo >> 20; \ + MUL128(mxhi, mxlo, a2, m2); \ + (hi) += mxhi; \ + (lo) += mxlo >> 20; \ + } while (0) + + MX(d0, c0, r0, u2, t1); + MX(d1, c1, r1, r0, t2); + MX(d2, c2, r2, r1, r0); + +#undef MX + + a0 = c0 + 20 * d2; + a1 = c1 + d0; + a2 = c2 + d1; + + a1 += a0 >> 44; + a0 &= MASK44; + a2 += a1 >> 44; + a1 &= MASK44; + a0 += 20 * (a2 >> 44); + a2 &= MASK44; + + buf += 16; + len -= 16; + } + acc[0] = a0; + acc[1] = a1; + acc[2] = a2; +} + +static inline void +poly1305_inner(uint64_t *acc, uint64_t *r, const void *data, size_t len) +{ + if (len >= 64) { + size_t len2; + + len2 = len & ~(size_t)63; + poly1305_inner_big(acc, r, data, len2); + data = (const unsigned char *)data + len2; + len -= len2; + } + if (len > 0) { + poly1305_inner_small(acc, r, data, len); + } +} + +/* see bearssl_block.h */ +void +br_poly1305_ctmulq_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt) +{ + unsigned char pkey[32], foot[16]; + uint64_t r[6], acc[3], r0, r1; + uint32_t v0, v1, v2, v3, v4; + uint64_t w0, w1, w2, w3; + uint32_t ctl; + + /* + * Compute the MAC key. The 'r' value is the first 16 bytes of + * pkey[]. + */ + memset(pkey, 0, sizeof pkey); + ichacha(key, iv, 0, pkey, sizeof pkey); + + /* + * If encrypting, ChaCha20 must run first, followed by Poly1305. + * When decrypting, the operations are reversed. + */ + if (encrypt) { + ichacha(key, iv, 1, data, len); + } + + /* + * Run Poly1305. We must process the AAD, then ciphertext, then + * the footer (with the lengths). Note that the AAD and ciphertext + * are meant to be padded with zeros up to the next multiple of 16, + * and the length of the footer is 16 bytes as well. + */ + + /* + * Apply the "clamping" on r. + */ + pkey[ 3] &= 0x0F; + pkey[ 4] &= 0xFC; + pkey[ 7] &= 0x0F; + pkey[ 8] &= 0xFC; + pkey[11] &= 0x0F; + pkey[12] &= 0xFC; + pkey[15] &= 0x0F; + + /* + * Decode the 'r' value into 44-bit words, left-shifted by 20 bits. + * Also compute the u1 and u2 values. + */ + r0 = br_dec64le(pkey + 0); + r1 = br_dec64le(pkey + 8); + r[0] = r0 << 20; + r[1] = ((r0 >> 24) | (r1 << 40)) & ~(uint64_t)0xFFFFF; + r[2] = (r1 >> 4) & ~(uint64_t)0xFFFFF; + r1 = 20 * (r[1] >> 20); + r[3] = r1 << 20; + r[5] = 20 * r[2]; + r[4] = (r[5] + (r1 >> 24)) & ~(uint64_t)0xFFFFF; + + /* + * Accumulator is 0. + */ + acc[0] = 0; + acc[1] = 0; + acc[2] = 0; + + /* + * Process the additional authenticated data, ciphertext, and + * footer in due order. + */ + br_enc64le(foot, (uint64_t)aad_len); + br_enc64le(foot + 8, (uint64_t)len); + poly1305_inner(acc, r, aad, aad_len); + poly1305_inner(acc, r, data, len); + poly1305_inner_small(acc, r, foot, sizeof foot); + + /* + * Finalise modular reduction. At that point, the value consists + * in three 44-bit values (the lowest one might be slightly above + * 2^44). Two loops shall be sufficient. + */ + acc[1] += (acc[0] >> 44); + acc[0] &= MASK44; + acc[2] += (acc[1] >> 44); + acc[1] &= MASK44; + acc[0] += 5 * (acc[2] >> 42); + acc[2] &= MASK42; + acc[1] += (acc[0] >> 44); + acc[0] &= MASK44; + acc[2] += (acc[1] >> 44); + acc[1] &= MASK44; + acc[0] += 5 * (acc[2] >> 42); + acc[2] &= MASK42; + + /* + * The value may still fall in the 2^130-5..2^130-1 range, in + * which case we must reduce it again. The code below selects, + * in constant-time, between 'acc' and 'acc-p'. We encode the + * value over four 32-bit integers to finish the operation. + */ + v0 = (uint32_t)acc[0]; + v1 = (uint32_t)(acc[0] >> 32) | ((uint32_t)acc[1] << 12); + v2 = (uint32_t)(acc[1] >> 20) | ((uint32_t)acc[2] << 24); + v3 = (uint32_t)(acc[2] >> 8); + v4 = (uint32_t)(acc[2] >> 40); + + ctl = GT(v0, 0xFFFFFFFA); + ctl &= EQ(v1, 0xFFFFFFFF); + ctl &= EQ(v2, 0xFFFFFFFF); + ctl &= EQ(v3, 0xFFFFFFFF); + ctl &= EQ(v4, 0x00000003); + v0 = MUX(ctl, v0 + 5, v0); + v1 = MUX(ctl, 0, v1); + v2 = MUX(ctl, 0, v2); + v3 = MUX(ctl, 0, v3); + + /* + * Add the "s" value. This is done modulo 2^128. Don't forget + * carry propagation... + */ + w0 = (uint64_t)v0 + (uint64_t)br_dec32le(pkey + 16); + w1 = (uint64_t)v1 + (uint64_t)br_dec32le(pkey + 20) + (w0 >> 32); + w2 = (uint64_t)v2 + (uint64_t)br_dec32le(pkey + 24) + (w1 >> 32); + w3 = (uint64_t)v3 + (uint64_t)br_dec32le(pkey + 28) + (w2 >> 32); + v0 = (uint32_t)w0; + v1 = (uint32_t)w1; + v2 = (uint32_t)w2; + v3 = (uint32_t)w3; + + /* + * Encode the tag. + */ + br_enc32le((unsigned char *)tag + 0, v0); + br_enc32le((unsigned char *)tag + 4, v1); + br_enc32le((unsigned char *)tag + 8, v2); + br_enc32le((unsigned char *)tag + 12, v3); + + /* + * If decrypting, then ChaCha20 runs _after_ Poly1305. + */ + if (!encrypt) { + ichacha(key, iv, 1, data, len); + } +} + +/* see bearssl_block.h */ +br_poly1305_run +br_poly1305_ctmulq_get(void) +{ + return &br_poly1305_ctmulq_run; +} + +#else + +/* see bearssl_block.h */ +br_poly1305_run +br_poly1305_ctmulq_get(void) +{ + return 0; +} + +#endif diff --git a/BearSSL-OG/libbearssl/src/symcipher/poly1305_i15.c b/BearSSL-OG/libbearssl/src/symcipher/poly1305_i15.c new file mode 100644 index 0000000..6f89212 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/symcipher/poly1305_i15.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * 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" + +/* + * This is a "reference" implementation of Poly1305 that uses the + * generic "i15" code for big integers. It is slow, but it handles all + * big-integer operations with generic code, thereby avoiding most + * tricky situations with carry propagation and modular reduction. + */ + +/* + * Modulus: 2^130-5. + */ +static const uint16_t P1305[] = { + 0x008A, + 0x7FFB, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x03FF +}; + +/* + * -p mod 2^15. + */ +#define P0I 0x4CCD + +/* + * R^2 mod p, for conversion to Montgomery representation (R = 2^135, + * since we use 9 words of 15 bits each, and 15*9 = 135). + */ +static const uint16_t R2[] = { + 0x008A, + 0x6400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +/* + * Perform the inner processing of blocks for Poly1305. The "r" array + * is in Montgomery representation, while the "a" array is not. + */ +static void +poly1305_inner(uint16_t *a, const uint16_t *r, const void *data, size_t len) +{ + const unsigned char *buf; + + buf = data; + while (len > 0) { + unsigned char tmp[16], rev[16]; + uint16_t b[10]; + uint32_t ctl; + int i; + + /* + * If there is a partial block, right-pad it with zeros. + */ + if (len < 16) { + memset(tmp, 0, sizeof tmp); + memcpy(tmp, buf, len); + buf = tmp; + len = 16; + } + + /* + * Decode next block and apply the "high bit". Since + * decoding is little-endian, we must byte-swap the buffer. + */ + for (i = 0; i < 16; i ++) { + rev[i] = buf[15 - i]; + } + br_i15_decode_mod(b, rev, sizeof rev, P1305); + b[9] |= 0x0100; + + /* + * Add the accumulator to the decoded block (modular + * addition). + */ + ctl = br_i15_add(b, a, 1); + ctl |= NOT(br_i15_sub(b, P1305, 0)); + br_i15_sub(b, P1305, ctl); + + /* + * Multiply by r, result is the new accumulator value. + */ + br_i15_montymul(a, b, r, P1305, P0I); + + buf += 16; + len -= 16; + } +} + +/* + * Byteswap a 16-byte value. + */ +static void +byteswap16(unsigned char *buf) +{ + int i; + + for (i = 0; i < 8; i ++) { + unsigned x; + + x = buf[i]; + buf[i] = buf[15 - i]; + buf[15 - i] = x; + } +} + +/* see bearssl_block.h */ +void +br_poly1305_i15_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt) +{ + unsigned char pkey[32], foot[16]; + uint16_t t[10], r[10], acc[10]; + + /* + * Compute the MAC key. The 'r' value is the first 16 bytes of + * pkey[]. + */ + memset(pkey, 0, sizeof pkey); + ichacha(key, iv, 0, pkey, sizeof pkey); + + /* + * If encrypting, ChaCha20 must run first, followed by Poly1305. + * When decrypting, the operations are reversed. + */ + if (encrypt) { + ichacha(key, iv, 1, data, len); + } + + /* + * Run Poly1305. We must process the AAD, then ciphertext, then + * the footer (with the lengths). Note that the AAD and ciphertext + * are meant to be padded with zeros up to the next multiple of 16, + * and the length of the footer is 16 bytes as well. + */ + + /* + * Apply the "clamping" operation on the encoded 'r' value. + */ + pkey[ 3] &= 0x0F; + pkey[ 7] &= 0x0F; + pkey[11] &= 0x0F; + pkey[15] &= 0x0F; + pkey[ 4] &= 0xFC; + pkey[ 8] &= 0xFC; + pkey[12] &= 0xFC; + + /* + * Decode the clamped 'r' value. Decoding should use little-endian + * so we must byteswap the value first. + */ + byteswap16(pkey); + br_i15_decode_mod(t, pkey, 16, P1305); + + /* + * Convert 'r' to Montgomery representation. + */ + br_i15_montymul(r, t, R2, P1305, P0I); + + /* + * Accumulator is 0. + */ + br_i15_zero(acc, 0x8A); + + /* + * Process the additional authenticated data, ciphertext, and + * footer in due order. + */ + br_enc64le(foot, (uint64_t)aad_len); + br_enc64le(foot + 8, (uint64_t)len); + poly1305_inner(acc, r, aad, aad_len); + poly1305_inner(acc, r, data, len); + poly1305_inner(acc, r, foot, sizeof foot); + + /* + * Decode the value 's'. Again, a byteswap is needed. + */ + byteswap16(pkey + 16); + br_i15_decode_mod(t, pkey + 16, 16, P1305); + + /* + * Add the value 's' to the accumulator. That addition is done + * modulo 2^128, so we just ignore the carry. + */ + br_i15_add(acc, t, 1); + + /* + * Encode the result (128 low bits) to the tag. Encoding should + * be little-endian. + */ + br_i15_encode(tag, 16, acc); + byteswap16(tag); + + /* + * If decrypting, then ChaCha20 runs _after_ Poly1305. + */ + if (!encrypt) { + ichacha(key, iv, 1, data, len); + } +} diff --git a/BearSSL-OG/libbearssl/src/x509/asn1.t0 b/BearSSL-OG/libbearssl/src/x509/asn1.t0 new file mode 100644 index 0000000..c329514 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/asn1.t0 @@ -0,0 +1,757 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +\ ======================================================================= + +\ This file contains code which is common to all engines that do some +\ ASN.1 decoding. It should not be compiled on its own, but only along +\ with another file (e.g. x509_minimal.t0) which uses it. +\ +\ Users must define several things: +\ +\ -- In the preamble, a macro called "CTX" that evaluates to the current +\ context structure. +\ +\ -- In the preamble, a macro called "CONTEXT_NAME" that evaluates to the +\ context structure type. This will be invoked during compilation. +\ +\ -- A word called "read8-low" ( -- x ) that reads the next byte, or -1 +\ if the input buffer is empty. That word is usually written in C. +\ +\ -- A word called "read-blob-inner" ( addr len -- addr len ) that is +\ the multi-byte version of read8-low. +\ +\ -- A word called "skip-remaining-inner" ( lim -- lim ) which reads but +\ drops some input bytes. + +preamble { + +#include "inner.h" + +} + +\ Read next source character, skipping blanks. +: skip-blanks begin char dup 32 > if ret then drop again ; + +: fail-oid + "Invalid OID" puts cr exitvm ; + +\ Read a decimal integer, followed by either a dot or whitespace. +\ Note: this does not check for overflows. +: parse-number ( -- val nextchar ) + char decval + begin + char + dup dup `. = swap 32 <= or if ret then + decval swap 10 * + + again ; + +\ Encode a number in unsigned 7E format. +: encode7E ( val -- ) + 0 encode7E-inner ; + +: encode7E-inner ( val eb -- ) + swap dup 0x7F > if + dup 7 u>> 0x80 encode7E-inner 0x7F and + then + or data-add8 ; + +\ Decode an OID from source, and encode it. First byte is length, +\ followed by encoded ASN.1 DER value. The OID is encoded in the +\ current data block. +: OID + \ Get current data address, and push a 0 for length. + current-data 0 data-add8 + \ Skip blanks and get first digit, which must be 0, 1 or 2. + skip-blanks decval dup 2 > if fail-oid then + 40 * + \ Next character must be a dot. + char `. <> if fail-oid then + \ Second group must be one or two digits. + parse-number { nextchar } + dup 40 >= if fail-oid then + + encode7E + \ While next character is a dot, keep encoding numbers. + begin nextchar `. = while + parse-number >nextchar + encode7E + repeat + \ Write back length in the first byte. + dup current-data swap - 1- swap data-set8 + ; immediate + +\ Define a new data word for an encoded OID. The OID is read from the +\ source. +: OID: + new-data-block next-word define-data-word postpone OID ; + +\ Define a word that evaluates to the address of a field within the +\ context. +: addr: + next-word { field } + "addr-" field + 0 1 define-word + 0 8191 "offsetof(CONTEXT_NAME, " field + ")" + make-CX + postpone literal postpone ; ; + +addr: pad + +\ Define a word that evaluates to an error code through a macro name. +: err: + next-word { name } + name 0 1 define-word + 0 63 "BR_" name + make-CX postpone literal postpone ; ; + +err: ERR_X509_INVALID_VALUE +err: ERR_X509_TRUNCATED +err: ERR_X509_EMPTY_CHAIN +err: ERR_X509_INNER_TRUNC +err: ERR_X509_BAD_TAG_CLASS +err: ERR_X509_BAD_TAG_VALUE +err: ERR_X509_INDEFINITE_LENGTH +err: ERR_X509_EXTRA_ELEMENT +err: ERR_X509_UNEXPECTED +err: ERR_X509_NOT_CONSTRUCTED +err: ERR_X509_NOT_PRIMITIVE +err: ERR_X509_PARTIAL_BYTE +err: ERR_X509_BAD_BOOLEAN +err: ERR_X509_OVERFLOW +err: ERR_X509_BAD_DN +err: ERR_X509_BAD_TIME +err: ERR_X509_UNSUPPORTED +err: ERR_X509_LIMIT_EXCEEDED +err: ERR_X509_WRONG_KEY_TYPE +err: ERR_X509_BAD_SIGNATURE +err: ERR_X509_EXPIRED +err: ERR_X509_DN_MISMATCH +err: ERR_X509_BAD_SERVER_NAME +err: ERR_X509_CRITICAL_EXTENSION +err: ERR_X509_NOT_CA +err: ERR_X509_FORBIDDEN_KEY_USAGE +err: ERR_X509_WEAK_PUBLIC_KEY + +: KEYTYPE_RSA CX 0 15 { BR_KEYTYPE_RSA } ; +: KEYTYPE_EC CX 0 15 { BR_KEYTYPE_EC } ; + +cc: fail ( err -- ! ) { + CTX->err = T0_POPi(); + T0_CO(); +} + +\ Read one byte from the stream. +: read8-nc ( -- x ) + begin + read8-low dup 0 >= if ret then + drop co + again ; + +\ Read one byte, enforcing current read limit. +: read8 ( lim -- lim x ) + dup ifnot ERR_X509_INNER_TRUNC fail then + 1- read8-nc ; + +\ Read a 16-bit value, big-endian encoding. +: read16be ( lim -- lim x ) + read8 8 << swap read8 rot + ; + +\ Read a 16-bit value, little-endian encoding. +: read16le ( lim -- lim x ) + read8 swap read8 8 << rot + ; + +\ Read all bytes from the current element, then close it (i.e. drop the +\ limit). Destination address is an offset within the context. +: read-blob ( lim addr -- ) + swap + begin dup while read-blob-inner dup if co then repeat + 2drop ; + +\ Skip remaining bytes in the current structure, but do not close it +\ (thus, this leaves the value 0 on the stack). +: skip-remaining ( lim -- lim ) + begin dup while skip-remaining-inner dup if co then repeat ; + +: skip-remaining-inner ( lim -- lim ) + 0 over read-blob-inner -rot 2drop ; + +cc: set8 ( val addr -- ) { + uint32_t addr = T0_POP(); + *((unsigned char *)CTX + addr) = (unsigned char)T0_POP(); +} + +cc: set16 ( val addr -- ) { + uint32_t addr = T0_POP(); + *(uint16_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); +} + +cc: set32 ( val addr -- ) { + uint32_t addr = T0_POP(); + *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); +} + +cc: get8 ( addr -- val ) { + uint32_t addr = T0_POP(); + T0_PUSH(*((unsigned char *)CTX + addr)); +} + +cc: get16 ( addr -- val ) { + uint32_t addr = T0_POP(); + T0_PUSH(*(uint16_t *)(void *)((unsigned char *)CTX + addr)); +} + +cc: get32 ( addr -- val ) { + uint32_t addr = T0_POP(); + T0_PUSH(*(uint32_t *)(void *)((unsigned char *)CTX + addr)); +} + +\ Read an ASN.1 tag. This function returns the "constructed" status +\ and the tag value. The constructed status is a boolean (-1 for +\ constructed, 0 for primitive). The tag value is either 0 to 31 for +\ a universal tag, or 32+x for a contextual tag of value x. Tag classes +\ "application" and "private" are rejected. Universal tags beyond 30 +\ are rejected. Contextual tags beyond 30 are rejected. Thus, accepted +\ tags will necessarily fit on exactly one byte. This does not support +\ the whole of ASN.1/BER, but is sufficient for certificate parsing. +: read-tag ( lim -- lim constructed value ) + read8 { fb } + + \ Constructed flag is bit 5. + fb 5 >> 0x01 and neg + + \ Class is in bits 6 and 7. Accepted classes are 00 (universal) + \ and 10 (context). We check that bit 6 is 0, and shift back + \ bit 7 so that we get 0 (universal) or 32 (context). + fb 6 >> dup 0x01 and if ERR_X509_BAD_TAG_CLASS fail then + 4 << + + \ Tag value is in bits 0..4. If the value is 31, then this is + \ an extended tag, encoded over subsequent bytes, and we do + \ not support that. + fb 0x1F and dup 0x1F = if ERR_X509_BAD_TAG_VALUE fail then + + ; + +\ Read a tag, but only if not at the end of the current object. If there +\ is no room for another element (limit is zero), then this will push a +\ synthetic "no tag" value (primitive, with value -1). +: read-tag-or-end ( lim -- lim constructed value ) + dup ifnot 0 -1 ret then + read-tag ; + +\ Compare the read tag with the provided value. If equal, then the +\ element is skipped, and a new tag is read (or end of object). +: iftag-skip ( lim constructed value ref -- lim constructed value ) + over = if + 2drop + read-length-open-elt skip-close-elt + read-tag-or-end + then ; + +\ Read an ASN.1 length. This supports only definite lengths (theoretically, +\ certificates may use an indefinite length for the outer structure, using +\ DER only in the TBS, but this never happens in practice, except in a +\ single example certificate from 15 years ago that also fails to decode +\ properly for other reasons). +: read-length ( lim -- lim length ) + read8 + \ Lengths in 0x00..0x7F get encoded as a single byte. + dup 0x80 < if ret then + + \ If the byte is 0x80 then this is an indefinite length, and we + \ do not support that. + 0x80 - dup ifnot ERR_X509_INDEFINITE_LENGTH fail then + + \ Masking out bit 7, this yields the number of bytes over which + \ the value is encoded. Since the total certificate length must + \ fit over 3 bytes (this is a consequence of SSL/TLS message + \ format), we can reject big lengths and keep the length in a + \ single integer. + { n } 0 + begin n 0 > while n 1- >n + dup 0x7FFFFF > if ERR_X509_INNER_TRUNC fail then + 8 << swap read8 rot + + repeat ; + +\ Open a sub-structure. This subtracts the length from the limit, and +\ pushes the length back as new limit. +: open-elt ( lim length -- lim_outer lim_inner ) + dup2 < if ERR_X509_INNER_TRUNC fail then + dup { len } - len ; + +\ Read a length and open the value as a sub-structure. +: read-length-open-elt ( lim -- lim_outer lim_inner ) + read-length open-elt ; + +\ Close a sub-structure. This verifies that there is no remaining +\ element to read. +: close-elt ( lim -- ) + if ERR_X509_EXTRA_ELEMENT fail then ; + +\ Skip remaining bytes in the current structure, then close it. +: skip-close-elt ( lim -- ) + skip-remaining drop ; + +\ Read a length and then skip the value. +: read-length-skip ( lim -- lim ) + read-length-open-elt skip-close-elt ; + +\ Check that a given tag is constructed and has the expected value. +: check-tag-constructed ( constructed value refvalue -- ) + = ifnot ERR_X509_UNEXPECTED fail then + check-constructed ; + +\ Check that the top value is true; report a "not constructed" +\ error otherwise. +: check-constructed ( constructed -- ) + ifnot ERR_X509_NOT_CONSTRUCTED fail then ; + +\ Check that a given tag is primitive and has the expected value. +: check-tag-primitive ( constructed value refvalue -- ) + = ifnot ERR_X509_UNEXPECTED fail then + check-primitive ; + +\ Check that the top value is true; report a "not primitive" +\ error otherwise. +: check-primitive ( constructed -- ) + if ERR_X509_NOT_PRIMITIVE fail then ; + +\ Check that the tag is for a constructed SEQUENCE. +: check-sequence ( constructed value -- ) + 0x10 check-tag-constructed ; + +\ Read a tag, check that it is for a constructed SEQUENCE, and open +\ it as a sub-element. +: read-sequence-open ( lim -- lim_outer lim_inner ) + read-tag check-sequence read-length-open-elt ; + +\ Read the next element as a BIT STRING with no ignore bits, and open +\ it as a sub-element. +: read-bits-open ( lim -- lim_outer lim_inner ) + read-tag 0x03 check-tag-primitive + read-length-open-elt + read8 if ERR_X509_PARTIAL_BYTE fail then ; + +OID: rsaEncryption 1.2.840.113549.1.1.1 + +OID: sha1WithRSAEncryption 1.2.840.113549.1.1.5 +OID: sha224WithRSAEncryption 1.2.840.113549.1.1.14 +OID: sha256WithRSAEncryption 1.2.840.113549.1.1.11 +OID: sha384WithRSAEncryption 1.2.840.113549.1.1.12 +OID: sha512WithRSAEncryption 1.2.840.113549.1.1.13 + +OID: id-sha1 1.3.14.3.2.26 +OID: id-sha224 2.16.840.1.101.3.4.2.4 +OID: id-sha256 2.16.840.1.101.3.4.2.1 +OID: id-sha384 2.16.840.1.101.3.4.2.2 +OID: id-sha512 2.16.840.1.101.3.4.2.3 + +OID: id-ecPublicKey 1.2.840.10045.2.1 + +OID: ansix9p256r1 1.2.840.10045.3.1.7 +OID: ansix9p384r1 1.3.132.0.34 +OID: ansix9p521r1 1.3.132.0.35 + +OID: ecdsa-with-SHA1 1.2.840.10045.4.1 +OID: ecdsa-with-SHA224 1.2.840.10045.4.3.1 +OID: ecdsa-with-SHA256 1.2.840.10045.4.3.2 +OID: ecdsa-with-SHA384 1.2.840.10045.4.3.3 +OID: ecdsa-with-SHA512 1.2.840.10045.4.3.4 + +OID: id-at-commonName 2.5.4.3 + +\ Read a "small value". This assumes that the tag has just been read +\ and processed, but not the length. The first pad byte is set to the +\ value length; the encoded value itself follows. If the value length +\ exceeds 255 bytes, then a single 0 is written in the pad, and this +\ method returns false (0). Otherwise, it returns true (-1). +\ Either way, the element is fully read. +: read-small-value ( lim -- lim bool ) + read-length-open-elt + dup 255 > if skip-close-elt 0 addr-pad set8 0 ret then + dup addr-pad set8 + addr-pad 1+ read-blob + -1 ; + +\ Read an OID as a "small value" (tag, length and value). A boolean +\ value is returned, which is true (-1) if the OID value fits on the pad, +\ false (0) otherwise. +: read-OID ( lim -- lim bool ) + read-tag 0x06 check-tag-primitive read-small-value ; + +\ Read a UTF-8 code point. On error, return 0. Reading a code point of +\ value 0 is considered to be an error. +: read-UTF8 ( lim -- lim val ) + read8 + choice + dup 0x80 < uf ret enduf + dup 0xC0 < uf drop 0 ret enduf + dup 0xE0 < uf 0x1F and 1 read-UTF8-next 0x80 0x7FF enduf + dup 0xF0 < uf 0x0F and 2 read-UTF8-next 0x800 0xFFFF enduf + dup 0xF8 < uf 0x07 and 3 read-UTF8-next 0x10000 0x10FFFF enduf + drop 0 ret + endchoice + between? ifnot drop 0 then + ; + +\ Read n subsequent bytes to complete the provided first byte. The final +\ value is -1 on error, or the code point numerical value. The final +\ value is duplicated. +: read-UTF8-next ( lim val n -- lim val val ) + begin dup while + -rot + read-UTF8-chunk + rot 1- + repeat + drop dup ; + +\ Read one byte, that should be a trailing UTF-8 byte, and complement the +\ current value. On error, value is set to -1. +: read-UTF8-chunk ( lim val -- lim val ) + swap + \ If we are at the end of the value, report an error but don't fail. + dup ifnot 2drop 0 -1 ret then + read8 rot + dup 0< if swap drop ret then 6 << + swap dup 6 >> 2 <> if 2drop -1 ret then + 0x3F and + ; + +: high-surrogate? ( x -- x bool ) + dup 0xD800 0xDBFF between? ; + +: low-surrogate? ( x -- x bool ) + dup 0xDC00 0xDFFF between? ; + +: assemble-surrogate-pair ( hi lim lo -- lim val ) + low-surrogate? ifnot rot 2drop 0 ret then + rot 10 << + 0x35FDC00 - ; + +\ Read a UTF-16 code point (big-endian). Returned value is 0 on error. +: read-UTF16BE ( lim -- lim val ) + read16be + choice + high-surrogate? uf + swap dup ifnot 2drop 0 0 ret then + read16be assemble-surrogate-pair + enduf + low-surrogate? uf + drop 0 + enduf + endchoice ; + +\ Read a UTF-16 code point (little-endian). Returned value is 0 on error. +: read-UTF16LE ( lim -- lim val ) + read16le + choice + high-surrogate? uf + swap dup ifnot 2drop 0 0 ret then + read16le assemble-surrogate-pair + enduf + low-surrogate? uf + drop 0 + enduf + endchoice ; + +\ Add byte to current pad value. Offset is updated, or set to 0 on error. +: pad-append ( off val -- off ) + over dup 0= swap 256 >= or if 2drop 0 ret then + over addr-pad + set8 1+ ; + +\ Add UTF-8 chunk byte to the pad. The 'nn' parameter is the shift count. +: pad-append-UTF8-chunk ( off val nn -- off ) + >> 0x3F and 0x80 or pad-append ; + +\ Test whether a code point is invalid when encoding. This rejects the +\ 66 noncharacters, and also the surrogate range; this function does NOT +\ check that the value is in the 0..10FFFF range. +: valid-unicode? ( val -- bool ) + dup 0xFDD0 0xFDEF between? if drop 0 ret then + dup 0xD800 0xDFFF between? if drop 0 ret then + 0xFFFF and 0xFFFE < ; + +\ Encode a code point in UTF-8. Offset is in the pad; it is updated, or +\ set to 0 on error. Leading BOM are ignored. +: encode-UTF8 ( val off -- off ) + \ Skip leading BOM (U+FEFF when off is 1). + dup2 1 = swap 0xFEFF = and if swap drop ret then + + swap dup { val } + dup valid-unicode? ifnot 2drop 0 ret then + choice + dup 0x80 < uf pad-append enduf + dup 0x800 < uf + 6 >> 0xC0 or pad-append + val 0 pad-append-UTF8-chunk + enduf + dup 0xFFFF < uf + 12 >> 0xE0 or pad-append + val 6 pad-append-UTF8-chunk + val 0 pad-append-UTF8-chunk + enduf + 18 >> 0xF0 or pad-append + val 12 pad-append-UTF8-chunk + val 6 pad-append-UTF8-chunk + val 0 pad-append-UTF8-chunk + endchoice ; + +\ Read a string value into the pad; this function checks that the source +\ characters are UTF-8 and non-zero. The string length (in bytes) is +\ written in the first pad byte. Returned value is true (-1) on success, +\ false (0) on error. +: read-value-UTF8 ( lim -- lim bool ) + read-length-open-elt + 1 { off } + begin dup while + read-UTF8 dup ifnot drop skip-close-elt 0 ret then + off encode-UTF8 >off + repeat + drop off dup ifnot ret then 1- addr-pad set8 -1 ; + +\ Decode a UTF-16 string into the pad. The string is converted to UTF-8, +\ and the length is written in the first pad byte. A leading BOM is +\ honoured (big-endian is assumed if there is no BOM). A code point of +\ value 0 is an error. Returned value is true (-1) on success, false (0) +\ on error. +: read-value-UTF16 ( lim -- lim bool ) + read-length-open-elt + dup ifnot addr-pad set8 -1 ret then + 1 { off } + read-UTF16BE dup 0xFFFE = if + \ Leading BOM, and indicates little-endian. + drop + begin dup while + read-UTF16LE dup ifnot drop skip-close-elt 0 ret then + off encode-UTF8 >off + repeat + else + dup ifnot drop skip-close-elt 0 ret then + \ Big-endian BOM, or no BOM. + begin + off encode-UTF8 >off + dup while + read-UTF16BE dup ifnot drop skip-close-elt 0 ret then + repeat + then + drop off dup ifnot ret then 1- addr-pad set8 -1 ; + +\ Decode a latin-1 string into the pad. The string is converted to UTF-8, +\ and the length is written in the first pad byte. A source byte of +\ value 0 is an error. Returned value is true (-1) on success, false (0) +\ on error. +: read-value-latin1 ( lim -- lim bool ) + read-length-open-elt + 1 { off } + begin dup while + read8 dup ifnot drop skip-close-elt 0 ret then + off encode-UTF8 >off + repeat + drop off dup ifnot ret then 1- addr-pad set8 -1 ; + +\ Read a value and interpret it as an INTEGER or ENUMERATED value. If +\ the integer value does not fit on an unsigned 32-bit value, an error +\ is reported. This function assumes that the tag has just been read +\ and processed, but not the length. +: read-small-int-value ( lim -- lim x ) + read-length-open-elt + dup ifnot ERR_X509_OVERFLOW fail then + read8 dup 0x80 >= if ERR_X509_OVERFLOW fail then + { x } + begin dup while + read8 x dup 0xFFFFFF >= if ERR_X509_OVERFLOW fail then + 8 << + >x + repeat + drop x ; + +\ Compare the OID in the pad with an OID in the constant data block. +\ Returned value is -1 on equality, 0 otherwise. +cc: eqOID ( addrConst -- bool ) { + const unsigned char *a2 = &t0_datablock[T0_POP()]; + const unsigned char *a1 = &CTX->pad[0]; + size_t len = a1[0]; + int x; + if (len == a2[0]) { + x = -(memcmp(a1 + 1, a2 + 1, len) == 0); + } else { + x = 0; + } + T0_PUSH((uint32_t)x); +} + +\ Compare two blobs in the context. Returned value is -1 on equality, 0 +\ otherwise. +cc: eqblob ( addr1 addr2 len -- bool ) { + size_t len = T0_POP(); + const unsigned char *a2 = (const unsigned char *)CTX + T0_POP(); + const unsigned char *a1 = (const unsigned char *)CTX + T0_POP(); + T0_PUSHi(-(memcmp(a1, a2, len) == 0)); +} + +\ Check that a value is in a given range (inclusive). +: between? ( x min max -- bool ) + { min max } dup min >= swap max <= and ; + +\ Convert the provided byte value into a number in the 0..9 range, +\ assuming that it is an ASCII digit. A non-digit triggers an error +\ (a "bad time" error since this is used in date/time decoding). +: digit-dec ( char -- value ) + `0 - dup 0 9 between? ifnot ERR_X509_BAD_TIME fail then ; + +\ Read two ASCII digits and return the value in the 0..99 range. An +\ error is reported if the characters are not ASCII digits. +: read-dec2 ( lim -- lim x ) + read8 digit-dec 10 * { x } read8 digit-dec x + ; + +\ Read two ASCII digits and check that the value is in the provided +\ range (inclusive). +: read-dec2-range ( lim min max -- lim x ) + { min max } + read-dec2 dup min max between? ifnot ERR_X509_BAD_TIME fail then ; + +\ Maximum days in a month and accumulated day count. Each +\ 16-bit value contains the month day count in its lower 5 bits. The first +\ 12 values are for a normal year, the other 12 for a leap year. +data: month-to-days +hexb| 001F 03FC 077F 0B5E 0F1F 12FE 16BF 1A9F 1E7E 223F 261E 29DF | +hexb| 001F 03FD 079F 0B7E 0F3F 131E 16DF 1ABF 1E9E 225F 263E 29FF | + +\ Read a date (UTCTime or GeneralizedTime). The date value is converted +\ to a day count and a second count. The day count starts at 0 for +\ January 1st, 0 AD (that's they year before 1 AD, also known as 1 BC) +\ in a proleptic Gregorian calendar (i.e. Gregorian rules are assumed to +\ extend indefinitely in the past). The second count is between 0 and +\ 86400 (inclusive, in case of a leap second). +: read-date ( lim -- lim days seconds ) + \ Read tag; must be UTCTime or GeneralizedTime. Year count is + \ 4 digits with GeneralizedTime, 2 digits with UTCTime. + read-tag + dup 0x17 0x18 between? ifnot ERR_X509_BAD_TIME fail then + 0x18 = { y4d } + check-primitive + read-length-open-elt + + \ We compute the days and seconds counts during decoding, in + \ order to minimize the number of needed temporary variables. + { ; days seconds x } + + \ Year is 4-digit with GeneralizedTime. With UTCTime, the year + \ is in the 1950..2049 range, and only the last two digits are + \ present in the encoding. + read-dec2 + y4d if + 100 * >x read-dec2 x + + else + dup 50 < if 100 + then 1900 + + then + >x + x 365 * x 3 + 4 / + x 99 + 100 / - x 399 + 400 / + >days + + \ Month is 1..12. Number of days in a months depend on the + \ month and on the year (year count is in x at that point). + 1 12 read-dec2-range + 1- 1 << + x 4 % 0= x 100 % 0<> x 400 % 0= or and if 24 + then + month-to-days + data-get16 + dup 5 >> days + >days + 0x1F and + + \ Day. At this point, the TOS contains the maximum day count for + \ the current month. + 1 swap read-dec2-range + days + 1- >days + + \ Hour, minute and seconds. Count of seconds is allowed to go to + \ 60 in case of leap seconds (in practice, leap seconds really + \ occur only at the very end of the day, so this computation is + \ exact for a real leap second, and a spurious leap second only + \ implies a one-second shift that we can ignore). + 0 23 read-dec2-range 3600 * >seconds + 0 59 read-dec2-range 60 * seconds + >seconds + 0 60 read-dec2-range seconds + >seconds + + \ At this point, we may have fractional seconds. This should + \ happen only with GeneralizedTime, but we accept it for UTCTime + \ too (and, anyway, we ignore these fractional seconds). + read8 dup `. = if + drop + begin read8 dup `0 `9 between? while drop repeat + then + + \ The time zone should be 'Z', not followed by anything. Other + \ time zone indications are not DER and thus not supposed to + \ appear in certificates. + `Z <> if ERR_X509_BAD_TIME fail then + close-elt + days seconds ; + +\ Read an INTEGER (tag, length and value). The INTEGER is supposed to be +\ positive; its unsigned big-endian encoding is stored in the provided +\ in-context buffer. Returned value is the decoded length. If the integer +\ did not fit, or the value is negative, then an error is reported. +: read-integer ( lim addr len -- lim dlen ) + rot read-tag 0x02 check-tag-primitive -rot + read-integer-next ; + +\ Identical to read-integer, but the tag has already been read and checked. +: read-integer-next ( lim addr len -- lim dlen ) + dup { addr len origlen } + read-length-open-elt + \ Read first byte; sign bit must be 0. + read8 dup 0x80 >= if ERR_X509_OVERFLOW fail then + \ Skip leading bytes of value 0. If there are only bytes of + \ value 0, then return. + begin dup 0 = while + drop dup ifnot drop 0 ret then + read8 + repeat + \ At that point, we have the first non-zero byte on the stack. + begin + len dup ifnot ERR_X509_LIMIT_EXCEEDED fail then 1- >len + addr set8 addr 1+ >addr + dup while read8 + repeat + drop origlen len - ; + +\ Read a BOOLEAN value. This should be called immediately after reading +\ the tag. +: read-boolean ( lim constructed value -- lim bool ) + 0x01 check-tag-primitive + read-length 1 <> if ERR_X509_BAD_BOOLEAN fail then + read8 0<> ; + +\ Identify an elliptic curve: read the OID, then check it against the +\ known curve OID. +: read-curve-ID ( lim -- lim curve ) + read-OID ifnot ERR_X509_UNSUPPORTED fail then + choice + ansix9p256r1 eqOID uf 23 enduf + ansix9p384r1 eqOID uf 24 enduf + ansix9p521r1 eqOID uf 25 enduf + ERR_X509_UNSUPPORTED fail + endchoice ; + +\ A convenient debug word: print the current data stack contents. +cc: DEBUG ( -- ) { + extern int printf(const char *fmt, ...); + uint32_t *p; + + printf("dp_stack[0]; p != dp; p ++) { + printf(" %lu", (unsigned long)*p); + } + printf(" >\n"); +} diff --git a/BearSSL-OG/libbearssl/src/x509/asn1enc.c b/BearSSL-OG/libbearssl/src/x509/asn1enc.c new file mode 100644 index 0000000..7a74963 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/asn1enc.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see inner.h */ +br_asn1_uint +br_asn1_uint_prepare(const void *xdata, size_t xlen) +{ + const unsigned char *x; + br_asn1_uint t; + + x = xdata; + while (xlen > 0 && *x == 0) { + x ++; + xlen --; + } + t.data = x; + t.len = xlen; + t.asn1len = xlen; + if (xlen == 0 || x[0] >= 0x80) { + t.asn1len ++; + } + return t; +} + +/* see inner.h */ +size_t +br_asn1_encode_length(void *dest, size_t len) +{ + unsigned char *buf; + size_t z; + int i, j; + + buf = dest; + if (len < 0x80) { + if (buf != NULL) { + *buf = len; + } + return 1; + } + i = 0; + for (z = len; z != 0; z >>= 8) { + i ++; + } + if (buf != NULL) { + *buf ++ = 0x80 + i; + for (j = i - 1; j >= 0; j --) { + *buf ++ = len >> (j << 3); + } + } + return i + 1; +} + +/* see inner.h */ +size_t +br_asn1_encode_uint(void *dest, br_asn1_uint pp) +{ + unsigned char *buf; + size_t lenlen; + + if (dest == NULL) { + return 1 + br_asn1_encode_length(NULL, pp.asn1len) + pp.asn1len; + } + buf = dest; + *buf ++ = 0x02; + lenlen = br_asn1_encode_length(buf, pp.asn1len); + buf += lenlen; + *buf = 0x00; + memcpy(buf + pp.asn1len - pp.len, pp.data, pp.len); + return 1 + lenlen + pp.asn1len; +} diff --git a/BearSSL-OG/libbearssl/src/x509/encode_ec_pk8der.c b/BearSSL-OG/libbearssl/src/x509/encode_ec_pk8der.c new file mode 100644 index 0000000..53717ce --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/encode_ec_pk8der.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_x509.h */ +size_t +br_encode_ec_pkcs8_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk) +{ + /* + * ASN.1 format: + * + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] PublicKey OPTIONAL ]], + * ... + * } + * + * We don't include attributes or public key (the public key + * is included in the private key value instead). The + * 'version' field is an INTEGER that we will set to 0 + * (meaning 'v1', compatible with previous versions of PKCS#8). + * The 'privateKeyAlgorithm' structure is an AlgorithmIdentifier + * whose OID should be id-ecPublicKey, with, as parameters, the + * curve OID. The 'privateKey' is an OCTET STRING, whose value + * is the "raw DER" encoding of the key pair. + */ + + /* + * OID id-ecPublicKey (1.2.840.10045.2.1), DER-encoded (with + * the tag). + */ + static const unsigned char OID_ECPUBKEY[] = { + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 + }; + + size_t len_version, len_privateKeyAlgorithm, len_privateKeyValue; + size_t len_privateKey, len_seq; + const unsigned char *oid; + + oid = br_get_curve_OID(sk->curve); + if (oid == NULL) { + return 0; + } + len_version = 3; + len_privateKeyAlgorithm = 2 + sizeof OID_ECPUBKEY + 2 + oid[0]; + len_privateKeyValue = br_encode_ec_raw_der_inner(NULL, sk, pk, 0); + len_privateKey = 1 + len_of_len(len_privateKeyValue) + + len_privateKeyValue; + len_seq = len_version + len_privateKeyAlgorithm + len_privateKey; + + if (dest == NULL) { + return 1 + len_of_len(len_seq) + len_seq; + } else { + unsigned char *buf; + size_t lenlen; + + buf = dest; + *buf ++ = 0x30; /* SEQUENCE tag */ + lenlen = br_asn1_encode_length(buf, len_seq); + buf += lenlen; + + /* version */ + *buf ++ = 0x02; + *buf ++ = 0x01; + *buf ++ = 0x00; + + /* privateKeyAlgorithm */ + *buf ++ = 0x30; + *buf ++ = (sizeof OID_ECPUBKEY) + 2 + oid[0]; + memcpy(buf, OID_ECPUBKEY, sizeof OID_ECPUBKEY); + buf += sizeof OID_ECPUBKEY; + *buf ++ = 0x06; + memcpy(buf, oid, 1 + oid[0]); + buf += 1 + oid[0]; + + /* privateKey */ + *buf ++ = 0x04; + buf += br_asn1_encode_length(buf, len_privateKeyValue); + br_encode_ec_raw_der_inner(buf, sk, pk, 0); + + return 1 + lenlen + len_seq; + } +} diff --git a/BearSSL-OG/libbearssl/src/x509/encode_ec_rawder.c b/BearSSL-OG/libbearssl/src/x509/encode_ec_rawder.c new file mode 100644 index 0000000..5985909 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/encode_ec_rawder.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see inner.h */ +const unsigned char * +br_get_curve_OID(int curve) +{ + static const unsigned char OID_secp256r1[] = { + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 + }; + static const unsigned char OID_secp384r1[] = { + 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 + }; + static const unsigned char OID_secp521r1[] = { + 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23 + }; + + switch (curve) { + case BR_EC_secp256r1: return OID_secp256r1; + case BR_EC_secp384r1: return OID_secp384r1; + case BR_EC_secp521r1: return OID_secp521r1; + default: + return NULL; + } +} + +/* see inner.h */ +size_t +br_encode_ec_raw_der_inner(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk, + int include_curve_oid) +{ + /* + * ASN.1 format: + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + * + * The tages '[0]' and '[1]' are explicit. The 'ECParameters' + * is a CHOICE; in our case, it will always be an OBJECT IDENTIFIER + * that identifies the curve. + * + * The value of the 'privateKey' field is the raw unsigned big-endian + * encoding of the private key (integer modulo the curve subgroup + * order); there is no INTEGER tag, and the leading bit may be 1. + * Also, leading bytes of value 0x00 are _not_ removed. + * + * The 'publicKey' contents are the raw encoded public key point, + * normally uncompressed (leading byte of value 0x04, followed + * by the unsigned big-endian encodings of the X and Y coordinates, + * padded to the full field length if necessary). + */ + + size_t len_version, len_privateKey, len_parameters, len_publicKey; + size_t len_publicKey_bits, len_seq; + const unsigned char *oid; + + if (include_curve_oid) { + oid = br_get_curve_OID(sk->curve); + if (oid == NULL) { + return 0; + } + } else { + oid = NULL; + } + len_version = 3; + len_privateKey = 1 + len_of_len(sk->xlen) + sk->xlen; + if (include_curve_oid) { + len_parameters = 4 + oid[0]; + } else { + len_parameters = 0; + } + if (pk == NULL) { + len_publicKey = 0; + len_publicKey_bits = 0; + } else { + len_publicKey_bits = 2 + len_of_len(pk->qlen) + pk->qlen; + len_publicKey = 1 + len_of_len(len_publicKey_bits) + + len_publicKey_bits; + } + len_seq = len_version + len_privateKey + len_parameters + len_publicKey; + if (dest == NULL) { + return 1 + len_of_len(len_seq) + len_seq; + } else { + unsigned char *buf; + size_t lenlen; + + buf = dest; + *buf ++ = 0x30; /* SEQUENCE tag */ + lenlen = br_asn1_encode_length(buf, len_seq); + buf += lenlen; + + /* version */ + *buf ++ = 0x02; + *buf ++ = 0x01; + *buf ++ = 0x01; + + /* privateKey */ + *buf ++ = 0x04; + buf += br_asn1_encode_length(buf, sk->xlen); + memcpy(buf, sk->x, sk->xlen); + buf += sk->xlen; + + /* parameters */ + if (include_curve_oid) { + *buf ++ = 0xA0; + *buf ++ = oid[0] + 2; + *buf ++ = 0x06; + memcpy(buf, oid, oid[0] + 1); + buf += oid[0] + 1; + } + + /* publicKey */ + if (pk != NULL) { + *buf ++ = 0xA1; + buf += br_asn1_encode_length(buf, len_publicKey_bits); + *buf ++ = 0x03; + buf += br_asn1_encode_length(buf, pk->qlen + 1); + *buf ++ = 0x00; + memcpy(buf, pk->q, pk->qlen); + /* buf += pk->qlen; */ + } + + return 1 + lenlen + len_seq; + } +} + +/* see bearssl_x509.h */ +size_t +br_encode_ec_raw_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk) +{ + return br_encode_ec_raw_der_inner(dest, sk, pk, 1); +} diff --git a/BearSSL-OG/libbearssl/src/x509/encode_rsa_pk8der.c b/BearSSL-OG/libbearssl/src/x509/encode_rsa_pk8der.c new file mode 100644 index 0000000..c053503 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/encode_rsa_pk8der.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_x509.h */ +size_t +br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen) +{ + /* + * ASN.1 format: + * + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] PublicKey OPTIONAL ]], + * ... + * } + * + * We don't include attributes or public key. The 'version' field + * is an INTEGER that we will set to 0 (meaning 'v1', compatible + * with previous versions of PKCS#8). The 'privateKeyAlgorithm' + * structure is an AlgorithmIdentifier whose OID should be + * rsaEncryption, with NULL parameters. The 'privateKey' is an + * OCTET STRING, whose value is the "raw DER" encoding of the + * key pair. + * + * Since the private key value comes last, this function really + * adds a header, which is mostly fixed (only some lengths have + * to be modified. + */ + + /* + * Concatenation of: + * - DER encoding of an INTEGER of value 0 (the 'version' field) + * - DER encoding of a PrivateKeyAlgorithmIdentifier that uses + * the rsaEncryption OID, and NULL parameters + * - An OCTET STRING tag + */ + static const unsigned char PK8_HEAD[] = { + 0x02, 0x01, 0x00, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x04 + }; + + size_t len_raw, len_seq; + + len_raw = br_encode_rsa_raw_der(NULL, sk, pk, d, dlen); + len_seq = (sizeof PK8_HEAD) + len_of_len(len_raw) + len_raw; + if (dest == NULL) { + return 1 + len_of_len(len_seq) + len_seq; + } else { + unsigned char *buf; + size_t lenlen; + + buf = dest; + *buf ++ = 0x30; /* SEQUENCE tag */ + lenlen = br_asn1_encode_length(buf, len_seq); + buf += lenlen; + + /* version, privateKeyAlgorithm, privateKey tag */ + memcpy(buf, PK8_HEAD, sizeof PK8_HEAD); + buf += sizeof PK8_HEAD; + + /* privateKey */ + buf += br_asn1_encode_length(buf, len_raw); + br_encode_rsa_raw_der(buf, sk, pk, d, dlen); + + return 1 + lenlen + len_seq; + } +} diff --git a/BearSSL-OG/libbearssl/src/x509/encode_rsa_rawder.c b/BearSSL-OG/libbearssl/src/x509/encode_rsa_rawder.c new file mode 100644 index 0000000..1a8052b --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/encode_rsa_rawder.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * 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" + +/* see bearssl_x509.h */ +size_t +br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen) +{ + /* + * ASN.1 format: + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + * + * The 'version' field is an INTEGER of value 0 (meaning: there + * are exactly two prime factors), and 'otherPrimeInfos' will + * be absent (because there are exactly two prime factors). + */ + + br_asn1_uint num[9]; + size_t u, slen; + + /* + * For all INTEGER values, get the pointer and length for the + * data bytes. + */ + num[0] = br_asn1_uint_prepare(NULL, 0); + num[1] = br_asn1_uint_prepare(pk->n, pk->nlen); + num[2] = br_asn1_uint_prepare(pk->e, pk->elen); + num[3] = br_asn1_uint_prepare(d, dlen); + num[4] = br_asn1_uint_prepare(sk->p, sk->plen); + num[5] = br_asn1_uint_prepare(sk->q, sk->qlen); + num[6] = br_asn1_uint_prepare(sk->dp, sk->dplen); + num[7] = br_asn1_uint_prepare(sk->dq, sk->dqlen); + num[8] = br_asn1_uint_prepare(sk->iq, sk->iqlen); + + /* + * Get the length of the SEQUENCE contents. + */ + slen = 0; + for (u = 0; u < 9; u ++) { + uint32_t ilen; + + ilen = num[u].asn1len; + slen += 1 + len_of_len(ilen) + ilen; + } + + if (dest == NULL) { + return 1 + len_of_len(slen) + slen; + } else { + unsigned char *buf; + size_t lenlen; + + buf = dest; + *buf ++ = 0x30; /* SEQUENCE tag */ + lenlen = br_asn1_encode_length(buf, slen); + buf += lenlen; + for (u = 0; u < 9; u ++) { + buf += br_asn1_encode_uint(buf, num[u]); + } + return 1 + lenlen + slen; + } +} diff --git a/BearSSL-OG/libbearssl/src/x509/skey_decoder.c b/BearSSL-OG/libbearssl/src/x509/skey_decoder.c new file mode 100644 index 0000000..9e285d7 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/skey_decoder.c @@ -0,0 +1,650 @@ +/* Automatically generated code; do not modify directly. */ + +#include +#include + +typedef struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; +} t0_context; + +static uint32_t +t0_parse7E_unsigned(const unsigned char **p) +{ + uint32_t x; + + x = 0; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + return x; + } + } +} + +static int32_t +t0_parse7E_signed(const unsigned char **p) +{ + int neg; + uint32_t x; + + neg = ((**p) >> 6) & 1; + x = (uint32_t)-neg; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + if (neg) { + return -(int32_t)~x - 1; + } else { + return (int32_t)x; + } + } + } +} + +#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) +#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) +#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) +#define T0_INT1(x) T0_FBYTE(x, 0) +#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) + +/* static const unsigned char t0_datablock[]; */ + + +void br_skey_decoder_init_main(void *t0ctx); + +void br_skey_decoder_run(void *t0ctx); + + + +#include "inner.h" + + + + + +#include "inner.h" + +#define CTX ((br_skey_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_skey_decoder_context, cpu))) +#define CONTEXT_NAME br_skey_decoder_context + +/* see bearssl_x509.h */ +void +br_skey_decoder_init(br_skey_decoder_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->cpu.dp = &ctx->dp_stack[0]; + ctx->cpu.rp = &ctx->rp_stack[0]; + br_skey_decoder_init_main(&ctx->cpu); + br_skey_decoder_run(&ctx->cpu); +} + +/* see bearssl_x509.h */ +void +br_skey_decoder_push(br_skey_decoder_context *ctx, + const void *data, size_t len) +{ + ctx->hbuf = data; + ctx->hlen = len; + br_skey_decoder_run(&ctx->cpu); +} + + + +static const unsigned char t0_datablock[] = { + 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x07, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x05, 0x2B, + 0x81, 0x04, 0x00, 0x23 +}; + +static const unsigned char t0_codeblock[] = { + 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x13, + 0x13, 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, + 0x01, T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_INVALID_VALUE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01, + T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA), + 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_data)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_type)), 0x00, 0x00, + 0x33, 0x48, 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, pad)), + 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x01, 0x1C, 0x00, 0x00, 0x01, 0x22, + 0x00, 0x00, 0x05, 0x02, 0x2C, 0x16, 0x00, 0x00, 0x06, 0x02, 0x2D, 0x16, + 0x00, 0x00, 0x01, 0x10, 0x3D, 0x00, 0x00, 0x0D, 0x05, 0x02, 0x2F, 0x16, + 0x3A, 0x00, 0x00, 0x0D, 0x05, 0x02, 0x2F, 0x16, 0x3B, 0x00, 0x00, 0x06, + 0x02, 0x27, 0x16, 0x00, 0x01, 0x03, 0x00, 0x54, 0x57, 0x01, 0x02, 0x3E, + 0x55, 0x23, 0x06, 0x02, 0x30, 0x16, 0x57, 0x01, 0x04, 0x3E, 0x02, 0x00, + 0x41, 0x3F, 0x00, 0x02, 0x03, 0x00, 0x53, 0x14, 0x14, 0x03, 0x01, 0x48, + 0x0E, 0x06, 0x02, 0x30, 0x16, 0x33, 0x4C, 0x58, 0x01, 0x7F, 0x19, 0x0D, + 0x06, 0x04, 0x13, 0x13, 0x04, 0x29, 0x01, 0x20, 0x19, 0x0D, 0x06, 0x16, + 0x13, 0x3A, 0x53, 0x4D, 0x02, 0x00, 0x06, 0x09, 0x02, 0x00, 0x0C, 0x06, + 0x02, 0x2A, 0x16, 0x04, 0x02, 0x03, 0x00, 0x3F, 0x04, 0x0D, 0x01, 0x21, + 0x19, 0x0D, 0x06, 0x04, 0x13, 0x3A, 0x04, 0x03, 0x30, 0x16, 0x13, 0x5D, + 0x02, 0x00, 0x05, 0x02, 0x30, 0x16, 0x02, 0x00, 0x02, 0x01, 0x1D, 0x00, + 0x02, 0x53, 0x4B, 0x05, 0x02, 0x30, 0x16, 0x5B, 0x15, 0x06, 0x07, 0x5D, + 0x01, 0x7F, 0x03, 0x01, 0x04, 0x16, 0x46, 0x15, 0x06, 0x10, 0x01, 0x00, + 0x03, 0x01, 0x14, 0x06, 0x03, 0x4D, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, + 0x04, 0x02, 0x30, 0x16, 0x3F, 0x57, 0x01, 0x04, 0x3E, 0x53, 0x02, 0x01, + 0x06, 0x03, 0x43, 0x04, 0x03, 0x02, 0x00, 0x40, 0x3F, 0x5D, 0x02, 0x01, + 0x06, 0x03, 0x32, 0x04, 0x01, 0x31, 0x00, 0x00, 0x54, 0x57, 0x01, 0x02, + 0x3E, 0x55, 0x06, 0x02, 0x30, 0x16, 0x57, 0x01, 0x02, 0x3E, 0x44, 0x3F, + 0x00, 0x07, 0x35, 0x50, 0x14, 0x05, 0x02, 0x2F, 0x16, 0x23, 0x01, 0x03, + 0x0B, 0x33, 0x17, 0x47, 0x07, 0x03, 0x00, 0x4F, 0x4F, 0x35, 0x4E, 0x14, + 0x14, 0x03, 0x01, 0x03, 0x02, 0x51, 0x14, 0x03, 0x03, 0x02, 0x02, 0x07, + 0x14, 0x03, 0x02, 0x51, 0x14, 0x03, 0x04, 0x02, 0x02, 0x07, 0x14, 0x03, + 0x02, 0x51, 0x14, 0x03, 0x05, 0x02, 0x02, 0x07, 0x14, 0x03, 0x02, 0x51, + 0x03, 0x06, 0x02, 0x00, 0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x02, 0x05, + 0x02, 0x06, 0x1E, 0x00, 0x00, 0x19, 0x19, 0x00, 0x00, 0x01, 0x0B, 0x00, + 0x00, 0x01, 0x00, 0x20, 0x14, 0x06, 0x08, 0x01, 0x01, 0x21, 0x20, 0x22, + 0x20, 0x04, 0x75, 0x13, 0x00, 0x00, 0x01, + T0_INT2(3 * BR_X509_BUFSIZE_SIG), 0x00, 0x01, 0x01, 0x87, 0xFF, 0xFF, + 0x7F, 0x54, 0x57, 0x01, 0x02, 0x3E, 0x55, 0x01, 0x01, 0x0E, 0x06, 0x02, + 0x30, 0x16, 0x57, 0x01, 0x02, 0x19, 0x0D, 0x06, 0x06, 0x13, 0x3B, 0x44, + 0x32, 0x04, 0x1C, 0x01, 0x04, 0x19, 0x0D, 0x06, 0x08, 0x13, 0x3B, 0x01, + 0x00, 0x41, 0x31, 0x04, 0x0E, 0x01, 0x10, 0x19, 0x0D, 0x06, 0x05, 0x13, + 0x3A, 0x42, 0x04, 0x03, 0x30, 0x16, 0x13, 0x03, 0x00, 0x3F, 0x02, 0x00, + 0x34, 0x1F, 0x5A, 0x27, 0x16, 0x00, 0x01, 0x45, 0x0A, 0x06, 0x02, 0x29, + 0x16, 0x14, 0x03, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x57, 0x01, 0x06, + 0x3E, 0x56, 0x00, 0x00, 0x20, 0x14, 0x06, 0x07, 0x1A, 0x14, 0x06, 0x01, + 0x12, 0x04, 0x76, 0x24, 0x00, 0x00, 0x4B, 0x05, 0x02, 0x30, 0x16, 0x37, + 0x15, 0x06, 0x04, 0x01, 0x17, 0x04, 0x12, 0x38, 0x15, 0x06, 0x04, 0x01, + 0x18, 0x04, 0x0A, 0x39, 0x15, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x30, + 0x16, 0x00, 0x00, 0x1C, 0x57, 0x01, 0x02, 0x3E, 0x09, 0x50, 0x00, 0x00, + 0x35, 0x4E, 0x13, 0x00, 0x03, 0x14, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, + 0x53, 0x59, 0x14, 0x01, 0x81, 0x00, 0x0F, 0x06, 0x02, 0x2E, 0x16, 0x14, + 0x01, 0x00, 0x0D, 0x06, 0x0B, 0x13, 0x14, 0x05, 0x04, 0x13, 0x01, 0x00, + 0x00, 0x59, 0x04, 0x6F, 0x02, 0x01, 0x14, 0x05, 0x02, 0x2B, 0x16, 0x23, + 0x03, 0x01, 0x02, 0x02, 0x1F, 0x02, 0x02, 0x22, 0x03, 0x02, 0x14, 0x06, + 0x03, 0x59, 0x04, 0x68, 0x13, 0x02, 0x00, 0x02, 0x01, 0x08, 0x00, 0x00, + 0x14, 0x35, 0x1C, 0x08, 0x20, 0x1C, 0x07, 0x20, 0x4E, 0x00, 0x01, 0x59, + 0x14, 0x01, 0x81, 0x00, 0x0A, 0x06, 0x01, 0x00, 0x01, 0x81, 0x00, 0x08, + 0x14, 0x05, 0x02, 0x28, 0x16, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, + 0x00, 0x0E, 0x06, 0x19, 0x02, 0x00, 0x23, 0x03, 0x00, 0x14, 0x01, 0x83, + 0xFF, 0xFF, 0x7F, 0x0E, 0x06, 0x02, 0x29, 0x16, 0x01, 0x08, 0x0B, 0x20, + 0x59, 0x1C, 0x07, 0x04, 0x60, 0x00, 0x00, 0x52, 0x4A, 0x00, 0x00, 0x57, + 0x3C, 0x53, 0x00, 0x01, 0x53, 0x14, 0x05, 0x02, 0x2E, 0x16, 0x59, 0x14, + 0x01, 0x81, 0x00, 0x0F, 0x06, 0x02, 0x2E, 0x16, 0x03, 0x00, 0x14, 0x06, + 0x16, 0x59, 0x02, 0x00, 0x14, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x0F, 0x06, + 0x02, 0x2E, 0x16, 0x01, 0x08, 0x0B, 0x07, 0x03, 0x00, 0x04, 0x67, 0x13, + 0x02, 0x00, 0x00, 0x00, 0x53, 0x14, 0x01, 0x81, 0x7F, 0x0E, 0x06, 0x08, + 0x5C, 0x01, 0x00, 0x36, 0x1F, 0x01, 0x00, 0x00, 0x14, 0x36, 0x1F, 0x36, + 0x22, 0x4C, 0x01, 0x7F, 0x00, 0x01, 0x59, 0x03, 0x00, 0x02, 0x00, 0x01, + 0x05, 0x10, 0x01, 0x01, 0x11, 0x18, 0x02, 0x00, 0x01, 0x06, 0x10, 0x14, + 0x01, 0x01, 0x11, 0x06, 0x02, 0x25, 0x16, 0x01, 0x04, 0x0B, 0x02, 0x00, + 0x01, 0x1F, 0x11, 0x14, 0x01, 0x1F, 0x0D, 0x06, 0x02, 0x26, 0x16, 0x07, + 0x00, 0x00, 0x14, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x57, 0x00, + 0x00, 0x14, 0x05, 0x02, 0x29, 0x16, 0x23, 0x5A, 0x00, 0x00, 0x1B, 0x14, + 0x01, 0x00, 0x0F, 0x06, 0x01, 0x00, 0x13, 0x12, 0x04, 0x74, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, 0x14, 0x06, 0x07, 0x5E, 0x14, + 0x06, 0x01, 0x12, 0x04, 0x76, 0x00, 0x00, 0x01, 0x00, 0x19, 0x1A, 0x09, + 0x24, 0x00 +}; + +static const uint16_t t0_caddr[] = { + 0, + 5, + 10, + 14, + 18, + 22, + 26, + 30, + 34, + 38, + 42, + 46, + 50, + 54, + 58, + 62, + 66, + 70, + 75, + 80, + 84, + 89, + 93, + 97, + 101, + 107, + 113, + 118, + 126, + 134, + 140, + 163, + 244, + 311, + 329, + 404, + 408, + 412, + 429, + 434, + 505, + 519, + 526, + 540, + 573, + 582, + 587, + 654, + 665, + 721, + 725, + 730, + 778, + 804, + 848, + 859, + 868, + 881, + 885, + 889, + 901 +}; + +#define T0_INTERPRETED 34 + +#define T0_ENTER(ip, rp, slot) do { \ + const unsigned char *t0_newip; \ + uint32_t t0_lnum; \ + t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ + t0_lnum = t0_parse7E_unsigned(&t0_newip); \ + (rp) += t0_lnum; \ + *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ + (ip) = t0_newip; \ + } while (0) + +#define T0_DEFENTRY(name, slot) \ +void \ +name(void *ctx) \ +{ \ + t0_context *t0ctx = ctx; \ + t0ctx->ip = &t0_codeblock[0]; \ + T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ +} + +T0_DEFENTRY(br_skey_decoder_init_main, 73) + +#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) + +void +br_skey_decoder_run(void *t0ctx) +{ + uint32_t *dp, *rp; + const unsigned char *ip; + +#define T0_LOCAL(x) (*(rp - 2 - (x))) +#define T0_POP() (*-- dp) +#define T0_POPi() (*(int32_t *)(-- dp)) +#define T0_PEEK(x) (*(dp - 1 - (x))) +#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) +#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) +#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) +#define T0_RPOP() (*-- rp) +#define T0_RPOPi() (*(int32_t *)(-- rp)) +#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) +#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) +#define T0_ROLL(x) do { \ + size_t t0len = (size_t)(x); \ + uint32_t t0tmp = *(dp - 1 - t0len); \ + memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_SWAP() do { \ + uint32_t t0tmp = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_ROT() do { \ + uint32_t t0tmp = *(dp - 3); \ + *(dp - 3) = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_NROT() do { \ + uint32_t t0tmp = *(dp - 1); \ + *(dp - 1) = *(dp - 2); \ + *(dp - 2) = *(dp - 3); \ + *(dp - 3) = t0tmp; \ +} while (0) +#define T0_PICK(x) do { \ + uint32_t t0depth = (x); \ + T0_PUSH(T0_PEEK(t0depth)); \ +} while (0) +#define T0_CO() do { \ + goto t0_exit; \ +} while (0) +#define T0_RET() goto t0_next + + dp = ((t0_context *)t0ctx)->dp; + rp = ((t0_context *)t0ctx)->rp; + ip = ((t0_context *)t0ctx)->ip; + goto t0_next; + for (;;) { + uint32_t t0x; + + t0_next: + t0x = T0_NEXT(&ip); + if (t0x < T0_INTERPRETED) { + switch (t0x) { + int32_t t0off; + + case 0: /* ret */ + t0x = T0_RPOP(); + rp -= (t0x >> 16); + t0x &= 0xFFFF; + if (t0x == 0) { + ip = NULL; + goto t0_exit; + } + ip = &t0_codeblock[t0x]; + break; + case 1: /* literal constant */ + T0_PUSHi(t0_parse7E_signed(&ip)); + break; + case 2: /* read local */ + T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); + break; + case 3: /* write local */ + T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); + break; + case 4: /* jump */ + t0off = t0_parse7E_signed(&ip); + ip += t0off; + break; + case 5: /* jump if */ + t0off = t0_parse7E_signed(&ip); + if (T0_POP()) { + ip += t0off; + } + break; + case 6: /* jump if not */ + t0off = t0_parse7E_signed(&ip); + if (!T0_POP()) { + ip += t0off; + } + break; + case 7: { + /* + */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a + b); + + } + break; + case 8: { + /* - */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a - b); + + } + break; + case 9: { + /* -rot */ + T0_NROT(); + } + break; + case 10: { + /* < */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a < b)); + + } + break; + case 11: { + /* << */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x << c); + + } + break; + case 12: { + /* <> */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a != b)); + + } + break; + case 13: { + /* = */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a == b)); + + } + break; + case 14: { + /* > */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a > b)); + + } + break; + case 15: { + /* >= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a >= b)); + + } + break; + case 16: { + /* >> */ + + int c = (int)T0_POPi(); + int32_t x = T0_POPi(); + T0_PUSHi(x >> c); + + } + break; + case 17: { + /* and */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a & b); + + } + break; + case 18: { + /* co */ + T0_CO(); + } + break; + case 19: { + /* drop */ + (void)T0_POP(); + } + break; + case 20: { + /* dup */ + T0_PUSH(T0_PEEK(0)); + } + break; + case 21: { + /* eqOID */ + + const unsigned char *a2 = &t0_datablock[T0_POP()]; + const unsigned char *a1 = &CTX->pad[0]; + size_t len = a1[0]; + int x; + if (len == a2[0]) { + x = -(memcmp(a1 + 1, a2 + 1, len) == 0); + } else { + x = 0; + } + T0_PUSH((uint32_t)x); + + } + break; + case 22: { + /* fail */ + + CTX->err = T0_POPi(); + T0_CO(); + + } + break; + case 23: { + /* get8 */ + + uint32_t addr = T0_POP(); + T0_PUSH(*((unsigned char *)CTX + addr)); + + } + break; + case 24: { + /* neg */ + + uint32_t a = T0_POP(); + T0_PUSH(-a); + + } + break; + case 25: { + /* over */ + T0_PUSH(T0_PEEK(1)); + } + break; + case 26: { + /* read-blob-inner */ + + uint32_t len = T0_POP(); + uint32_t addr = T0_POP(); + size_t clen = CTX->hlen; + if (clen > len) { + clen = (size_t)len; + } + if (addr != 0) { + memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); + } + CTX->hbuf += clen; + CTX->hlen -= clen; + T0_PUSH(addr + clen); + T0_PUSH(len - clen); + + } + break; + case 27: { + /* read8-low */ + + if (CTX->hlen == 0) { + T0_PUSHi(-1); + } else { + CTX->hlen --; + T0_PUSH(*CTX->hbuf ++); + } + + } + break; + case 28: { + /* rot */ + T0_ROT(); + } + break; + case 29: { + /* set-ec-key */ + + size_t xlen = T0_POP(); + uint32_t curve = T0_POP(); + CTX->key.ec.curve = curve; + CTX->key.ec.x = CTX->key_data; + CTX->key.ec.xlen = xlen; + + } + break; + case 30: { + /* set-rsa-key */ + + size_t iqlen = T0_POP(); + size_t dqlen = T0_POP(); + size_t dplen = T0_POP(); + size_t qlen = T0_POP(); + size_t plen = T0_POP(); + uint32_t n_bitlen = T0_POP(); + size_t off; + + CTX->key.rsa.n_bitlen = n_bitlen; + CTX->key.rsa.p = CTX->key_data; + CTX->key.rsa.plen = plen; + off = plen; + CTX->key.rsa.q = CTX->key_data + off; + CTX->key.rsa.qlen = qlen; + off += qlen; + CTX->key.rsa.dp = CTX->key_data + off; + CTX->key.rsa.dplen = dplen; + off += dplen; + CTX->key.rsa.dq = CTX->key_data + off; + CTX->key.rsa.dqlen = dqlen; + off += dqlen; + CTX->key.rsa.iq = CTX->key_data + off; + CTX->key.rsa.iqlen = iqlen; + + } + break; + case 31: { + /* set8 */ + + uint32_t addr = T0_POP(); + *((unsigned char *)CTX + addr) = (unsigned char)T0_POP(); + + } + break; + case 32: { + /* swap */ + T0_SWAP(); + } + break; + case 33: { + /* u>> */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x >> c); + + } + break; + } + + } else { + T0_ENTER(ip, rp, t0x); + } + } +t0_exit: + ((t0_context *)t0ctx)->dp = dp; + ((t0_context *)t0ctx)->rp = rp; + ((t0_context *)t0ctx)->ip = ip; +} diff --git a/BearSSL-OG/libbearssl/src/x509/skey_decoder.t0 b/BearSSL-OG/libbearssl/src/x509/skey_decoder.t0 new file mode 100644 index 0000000..f00e614 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/skey_decoder.t0 @@ -0,0 +1,373 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +preamble { + +#include "inner.h" + +#define CTX ((br_skey_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_skey_decoder_context, cpu))) +#define CONTEXT_NAME br_skey_decoder_context + +/* see bearssl_x509.h */ +void +br_skey_decoder_init(br_skey_decoder_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->cpu.dp = &ctx->dp_stack[0]; + ctx->cpu.rp = &ctx->rp_stack[0]; + br_skey_decoder_init_main(&ctx->cpu); + br_skey_decoder_run(&ctx->cpu); +} + +/* see bearssl_x509.h */ +void +br_skey_decoder_push(br_skey_decoder_context *ctx, + const void *data, size_t len) +{ + ctx->hbuf = data; + ctx->hlen = len; + br_skey_decoder_run(&ctx->cpu); +} + +} + +addr: key_type +addr: key_data + +cc: read8-low ( -- x ) { + if (CTX->hlen == 0) { + T0_PUSHi(-1); + } else { + CTX->hlen --; + T0_PUSH(*CTX->hbuf ++); + } +} + +cc: read-blob-inner ( addr len -- addr len ) { + uint32_t len = T0_POP(); + uint32_t addr = T0_POP(); + size_t clen = CTX->hlen; + if (clen > len) { + clen = (size_t)len; + } + if (addr != 0) { + memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); + } + CTX->hbuf += clen; + CTX->hlen -= clen; + T0_PUSH(addr + clen); + T0_PUSH(len - clen); +} + +\ Get the length of the key_data buffer. +: len-key_data + CX 0 8191 { 3 * BR_X509_BUFSIZE_SIG } ; + +\ Get the address and length for the key_data buffer. +: addr-len-key_data ( -- addr len ) + addr-key_data len-key_data ; + +\ Set the private key (RSA). +cc: set-rsa-key ( n_bitlen plen qlen dplen dqlen iqlen -- ) { + size_t iqlen = T0_POP(); + size_t dqlen = T0_POP(); + size_t dplen = T0_POP(); + size_t qlen = T0_POP(); + size_t plen = T0_POP(); + uint32_t n_bitlen = T0_POP(); + size_t off; + + CTX->key.rsa.n_bitlen = n_bitlen; + CTX->key.rsa.p = CTX->key_data; + CTX->key.rsa.plen = plen; + off = plen; + CTX->key.rsa.q = CTX->key_data + off; + CTX->key.rsa.qlen = qlen; + off += qlen; + CTX->key.rsa.dp = CTX->key_data + off; + CTX->key.rsa.dplen = dplen; + off += dplen; + CTX->key.rsa.dq = CTX->key_data + off; + CTX->key.rsa.dqlen = dqlen; + off += dqlen; + CTX->key.rsa.iq = CTX->key_data + off; + CTX->key.rsa.iqlen = iqlen; +} + +\ Set the private key (EC). +cc: set-ec-key ( curve xlen -- ) { + size_t xlen = T0_POP(); + uint32_t curve = T0_POP(); + CTX->key.ec.curve = curve; + CTX->key.ec.x = CTX->key_data; + CTX->key.ec.xlen = xlen; +} + +\ Get the bit length for an integer (unsigned). +: int-bit-length ( x -- bitlen ) + 0 swap + begin dup while 1 u>> swap 1+ swap repeat + drop ; + +\ Read an INTEGER into the key_data buffer, but then ignore it. +: read-integer-ignore ( lim -- lim ) + addr-len-key_data read-integer drop ; + +\ Read an INTEGER into the key_data buffer, at the provided offset. +\ Returned value is the integer length (in bytes). +: read-integer-off ( lim off -- lim dlen ) + dup addr-len-key_data rot - swap rot + swap read-integer ; + +\ Decode RSA key, starting with the SEQUENCE tag. +: decode-RSA ( lim -- lim ) + read-sequence-open + + \ Version should be 0. + read-tag 0x02 check-tag-primitive read-small-int-value if + ERR_X509_UNSUPPORTED fail + then + + \ Read tag for the modulus; should be INTEGER. Then use the + \ decode-RSA-next function for the remainder of the key. + read-tag 0x02 check-tag-primitive + decode-RSA-next + + \ Close the SEQUENCE. + close-elt ; + +\ Decode RSA key; the version, and the tag for the modulus, have been +\ read. +: decode-RSA-next ( lim -- lim ) + \ Modulus: we read it but we do not keep it; we merely gather + \ the modulus bit length. + addr-len-key_data read-integer-next + dup ifnot ERR_X509_UNEXPECTED fail then + 1- 3 << addr-key_data get8 int-bit-length + { n_bitlen } + + \ Public exponent: read but skip. + read-integer-ignore + + \ Private exponent: read but skip. + read-integer-ignore + + \ First prime factor. + addr-len-key_data read-integer dup dup { off plen } + + \ Second prime factor. + read-integer-off dup { qlen } off + dup >off + + \ First reduced private exponent. + read-integer-off dup { dplen } off + dup >off + + \ Second reduced private exponent. + read-integer-off dup { dqlen } off + dup >off + + \ CRT coefficient. + read-integer-off { iqlen } + + \ Set RSA key. + n_bitlen plen qlen dplen dqlen iqlen set-rsa-key + + \ The caller will close the sequence, thereby validating that there + \ is no extra field. + ; + +\ Decode an EC key, starting with the SEQUENCE tag. +: decode-EC ( lim curve -- lim ) + { curve } + read-sequence-open + + \ Version should be 1. + read-tag 0x02 check-tag-primitive read-small-int-value 1- if + ERR_X509_UNSUPPORTED fail + then + + \ Read tag for the private key; should be OCTET STRING. Then use the + \ decode-EC-next function for the remainder of the key. + read-tag 0x04 check-tag-primitive + curve decode-EC-next + + \ Close the SEQUENCE. + close-elt ; + +\ Decode an EC key; the version, and the tag for the OCTET STRING, have +\ already been read. The curve ID is provided (0 if unknown). +: decode-EC-next ( lim curve -- lim ) + { curve } + + \ Read the private key proper. + read-length-open-elt + dup dup { xlen } len-key_data > if ERR_X509_UNSUPPORTED fail then + addr-key_data read-blob + + \ Next element might be the curve identifier. + read-tag-or-end + case + + \ End of structure. + -1 of drop endof + + \ Curve parameters; we support only named curves. + 0x20 of + check-constructed read-length-open-elt + read-curve-ID + curve if + curve <> if ERR_X509_INVALID_VALUE fail then + else + >curve + then + close-elt + endof + + \ Public key. We ignore it. + 0x21 of check-constructed endof + + ERR_X509_UNSUPPORTED fail + endcase + skip-remaining + + \ The curve must have been defined one way or another. + curve ifnot ERR_X509_UNSUPPORTED fail then + + \ Set the EC key. + curve xlen set-ec-key + + \ The caller will close the sequence. + ; + +\ Decode a PKCS#8 object. The version and the tag for the AlgorithmIdentifier +\ structure have already been read. This function returns the key type. +: decode-PKCS8-next ( lim -- lim keytype ) + \ Decode the AlgorithmIdentifier. + read-length-open-elt + read-OID ifnot ERR_X509_UNSUPPORTED fail then + { ; is-rsa curve } + choice + rsaEncryption eqOID uf + \ RSA private key. We ignore the parameters. + skip-remaining -1 >is-rsa + enduf + id-ecPublicKey eqOID uf + \ EC private key. Parameters, if present, shall + \ identify the curve. + 0 >is-rsa + dup if read-curve-ID else 0 then >curve + enduf + + ERR_X509_UNSUPPORTED fail + endchoice + close-elt + + \ Open private key value and decode it. + read-tag 0x04 check-tag-primitive + read-length-open-elt + is-rsa if + decode-RSA + else + curve decode-EC + then + close-elt + + \ We ignore any extra field, i.e. attributes or public key. + skip-remaining + + \ Return the key type. + is-rsa if KEYTYPE_RSA else KEYTYPE_EC then + ; + +\ Decode a private key. +: main ( -- ! ) + \ RSA private key format is defined in PKCS#1 (RFC 3447): + \ RSAPrivateKey ::= SEQUENCE { + \ version INTEGER, -- 0 or 1 + \ n INTEGER, + \ e INTEGER, + \ d INTEGER, + \ p INTEGER, + \ q INTEGER, + \ dp INTEGER, + \ dq INTEGER, + \ iq INTEGER, + \ other OtherPrimeInfos OPTIONAL + \ } + \ We do not support keys with more than two primes (these have + \ version 1); thus, we expect the version field to be 0, and + \ the 'other' field to be absent. + \ + \ EC private key format is defined in RFC 5915: + \ ECPrivateKey ::= SEQUENCE { + \ version INTEGER, -- always 1 + \ privateKey OCTET STRING, + \ parameters [0] EXPLICIT OBJECT IDENTIFIER OPTIONAL, + \ publicKey [1] EXPLICIT BIT STRING OPTIONAL + \ } + \ The "parameters" might conceptually be a complex curve description + \ structure but we support only named curves. The private key + \ contents are the unsigned big-endian encoding of the key value, + \ which is exactly what we want. + \ + \ PKCS#8 (unencrypted) is: + \ OneAsymmetricKey ::= SEQUENCE { + \ version INTEGER, -- 0 or 1 + \ algorithm AlgorithmIdentifier, + \ privateKey OCTET STRING, + \ attributes [0] IMPLICIT Attributes OPTIONAL, + \ publicKey [1] IMPLICIT BIT STRING OPTIONAL + \ } + \ The 'publicKey' field is an add-on from RFC 5958 and may be + \ present only if the 'version' is v2 (i.e. has value 1). We + \ ignore it anyway. + + \ An arbitrary upper limit on the private key size. + 0xFFFFFF + + \ Open the outer SEQUENCE. + read-sequence-open + + \ All our schemas begin with a small INTEGER which is either 0 or + \ 1. We don't care which it is. + read-tag 0x02 check-tag-primitive read-small-int-value 1 > if + ERR_X509_UNSUPPORTED fail + then + + \ Get next tag: it should be either an INTEGER (RSA private key), + \ an OCTET STRING (EC private key), or a SEQUENCE (for an + \ AlgorithmIdentifier, in a PKCS#8 object). + read-tag + case + 0x02 of check-primitive decode-RSA-next KEYTYPE_RSA endof + 0x04 of check-primitive 0 decode-EC-next KEYTYPE_EC endof + 0x10 of check-constructed decode-PKCS8-next endof + ERR_X509_UNSUPPORTED fail + endcase + { key-type } + + \ Close the SEQUENCE. + close-elt + + \ Set the key type, which marks the decoding as a success. + key-type addr-key_type set8 + + \ Read one byte, then fail: if the read succeeds, then there is + \ some trailing byte. + read8-nc ERR_X509_EXTRA_ELEMENT fail + ; diff --git a/BearSSL-OG/libbearssl/src/x509/x509_decoder.c b/BearSSL-OG/libbearssl/src/x509/x509_decoder.c new file mode 100644 index 0000000..8dd970f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/x509_decoder.c @@ -0,0 +1,773 @@ +/* Automatically generated code; do not modify directly. */ + +#include +#include + +typedef struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; +} t0_context; + +static uint32_t +t0_parse7E_unsigned(const unsigned char **p) +{ + uint32_t x; + + x = 0; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + return x; + } + } +} + +static int32_t +t0_parse7E_signed(const unsigned char **p) +{ + int neg; + uint32_t x; + + neg = ((**p) >> 6) & 1; + x = (uint32_t)-neg; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + if (neg) { + return -(int32_t)~x - 1; + } else { + return (int32_t)x; + } + } + } +} + +#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) +#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) +#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) +#define T0_INT1(x) T0_FBYTE(x, 0) +#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) + +/* static const unsigned char t0_datablock[]; */ + + +void br_x509_decoder_init_main(void *t0ctx); + +void br_x509_decoder_run(void *t0ctx); + + + +#include "inner.h" + + + + + +#include "inner.h" + +#define CTX ((br_x509_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_decoder_context, cpu))) +#define CONTEXT_NAME br_x509_decoder_context + +/* see bearssl_x509.h */ +void +br_x509_decoder_init(br_x509_decoder_context *ctx, + void (*append_dn)(void *ctx, const void *buf, size_t len), + void *append_dn_ctx) +{ + memset(ctx, 0, sizeof *ctx); + /* obsolete + ctx->err = 0; + ctx->hbuf = NULL; + ctx->hlen = 0; + */ + ctx->append_dn = append_dn; + ctx->append_dn_ctx = append_dn_ctx; + ctx->cpu.dp = &ctx->dp_stack[0]; + ctx->cpu.rp = &ctx->rp_stack[0]; + br_x509_decoder_init_main(&ctx->cpu); + br_x509_decoder_run(&ctx->cpu); +} + +/* see bearssl_x509.h */ +void +br_x509_decoder_push(br_x509_decoder_context *ctx, + const void *data, size_t len) +{ + ctx->hbuf = data; + ctx->hlen = len; + br_x509_decoder_run(&ctx->cpu); +} + + + +static const unsigned char t0_datablock[] = { + 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0E, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x0C, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, + 0x0D, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, + 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x04, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01, 0x08, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x08, 0x2A, 0x86, 0x48, + 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, + 0x03, 0x04, 0x00, 0x1F, 0x03, 0xFC, 0x07, 0x7F, 0x0B, 0x5E, 0x0F, 0x1F, + 0x12, 0xFE, 0x16, 0xBF, 0x1A, 0x9F, 0x1E, 0x7E, 0x22, 0x3F, 0x26, 0x1E, + 0x29, 0xDF, 0x00, 0x1F, 0x03, 0xFD, 0x07, 0x9F, 0x0B, 0x7E, 0x0F, 0x3F, + 0x13, 0x1E, 0x16, 0xDF, 0x1A, 0xBF, 0x1E, 0x9E, 0x22, 0x5F, 0x26, 0x3E, + 0x29, 0xFF, 0x03, 0x55, 0x1D, 0x13 +}; + +static const unsigned char t0_codeblock[] = { + 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x01, 0x09, 0x00, 0x00, 0x01, 0x01, 0x0A, 0x00, 0x00, 0x1A, 0x1A, 0x00, + 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_BOOLEAN), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_TIME), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_PARTIAL_BYTE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01, + T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA), + 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, copy_dn)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(CONTEXT_NAME, decoded)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, isCA)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_x509_decoder_context, pkey_data)), 0x01, + T0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, notafter_days)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, notafter_seconds)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, notbefore_days)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, notbefore_seconds)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, signer_hash_id)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, signer_key_type)), 0x00, 0x00, 0x01, + 0x80, 0x45, 0x00, 0x00, 0x01, 0x80, 0x4E, 0x00, 0x00, 0x01, 0x80, 0x54, + 0x00, 0x00, 0x01, 0x81, 0x36, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x1B, + 0x02, 0x01, 0x13, 0x26, 0x02, 0x00, 0x0F, 0x15, 0x00, 0x00, 0x05, 0x02, + 0x34, 0x1D, 0x00, 0x00, 0x06, 0x02, 0x35, 0x1D, 0x00, 0x00, 0x01, 0x10, + 0x4F, 0x00, 0x00, 0x11, 0x05, 0x02, 0x38, 0x1D, 0x4C, 0x00, 0x00, 0x11, + 0x05, 0x02, 0x38, 0x1D, 0x4D, 0x00, 0x00, 0x06, 0x02, 0x30, 0x1D, 0x00, + 0x00, 0x1B, 0x19, 0x01, 0x08, 0x0E, 0x26, 0x29, 0x19, 0x09, 0x00, 0x00, + 0x01, 0x30, 0x0A, 0x1B, 0x01, 0x00, 0x01, 0x09, 0x4B, 0x05, 0x02, 0x2F, + 0x1D, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x01, 0x80, 0x5A, 0x00, 0x00, + 0x01, 0x80, 0x62, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01, 0x80, + 0x74, 0x00, 0x00, 0x01, 0x80, 0x7D, 0x00, 0x00, 0x01, 0x3D, 0x00, 0x00, + 0x20, 0x11, 0x06, 0x04, 0x2B, 0x6B, 0x7A, 0x71, 0x00, 0x04, 0x01, 0x00, + 0x3D, 0x25, 0x01, 0x00, 0x3C, 0x25, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x6D, + 0x6D, 0x70, 0x1B, 0x01, 0x20, 0x11, 0x06, 0x11, 0x1A, 0x4C, 0x6B, 0x70, + 0x01, 0x02, 0x50, 0x6E, 0x01, 0x02, 0x12, 0x06, 0x02, 0x39, 0x1D, 0x51, + 0x70, 0x01, 0x02, 0x50, 0x6C, 0x6D, 0x7A, 0x6D, 0x7A, 0x6D, 0x65, 0x43, + 0x24, 0x42, 0x24, 0x65, 0x41, 0x24, 0x40, 0x24, 0x51, 0x01, 0x01, 0x3C, + 0x25, 0x6D, 0x7A, 0x01, 0x00, 0x3C, 0x25, 0x6D, 0x6D, 0x60, 0x05, 0x02, + 0x39, 0x1D, 0x74, 0x1C, 0x06, 0x1C, 0x7A, 0x61, 0x6D, 0x3F, 0x68, 0x03, + 0x00, 0x3F, 0x26, 0x02, 0x00, 0x09, 0x26, 0x02, 0x00, 0x0A, 0x68, 0x03, + 0x01, 0x51, 0x51, 0x02, 0x00, 0x02, 0x01, 0x18, 0x04, 0x1E, 0x5A, 0x1C, + 0x06, 0x18, 0x64, 0x03, 0x02, 0x51, 0x61, 0x1B, 0x03, 0x03, 0x1B, 0x3F, + 0x23, 0x0D, 0x06, 0x02, 0x33, 0x1D, 0x62, 0x02, 0x02, 0x02, 0x03, 0x17, + 0x04, 0x02, 0x39, 0x1D, 0x51, 0x01, 0x00, 0x3E, 0x25, 0x71, 0x01, 0x21, + 0x5B, 0x01, 0x22, 0x5B, 0x1B, 0x01, 0x23, 0x11, 0x06, 0x28, 0x1A, 0x4C, + 0x6B, 0x6D, 0x1B, 0x06, 0x1D, 0x6D, 0x60, 0x1A, 0x70, 0x1B, 0x01, 0x01, + 0x11, 0x06, 0x03, 0x63, 0x1A, 0x70, 0x01, 0x04, 0x50, 0x6B, 0x4A, 0x1C, + 0x06, 0x03, 0x5F, 0x04, 0x01, 0x7B, 0x51, 0x51, 0x04, 0x60, 0x51, 0x51, + 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02, 0x38, 0x1D, 0x1A, 0x51, 0x6D, + 0x60, 0x06, 0x80, 0x63, 0x75, 0x1C, 0x06, 0x06, 0x01, 0x02, 0x3B, 0x04, + 0x80, 0x57, 0x76, 0x1C, 0x06, 0x06, 0x01, 0x03, 0x3B, 0x04, 0x80, 0x4D, + 0x77, 0x1C, 0x06, 0x06, 0x01, 0x04, 0x3B, 0x04, 0x80, 0x43, 0x78, 0x1C, + 0x06, 0x05, 0x01, 0x05, 0x3B, 0x04, 0x3A, 0x79, 0x1C, 0x06, 0x05, 0x01, + 0x06, 0x3B, 0x04, 0x31, 0x55, 0x1C, 0x06, 0x05, 0x01, 0x02, 0x3A, 0x04, + 0x28, 0x56, 0x1C, 0x06, 0x05, 0x01, 0x03, 0x3A, 0x04, 0x1F, 0x57, 0x1C, + 0x06, 0x05, 0x01, 0x04, 0x3A, 0x04, 0x16, 0x58, 0x1C, 0x06, 0x05, 0x01, + 0x05, 0x3A, 0x04, 0x0D, 0x59, 0x1C, 0x06, 0x05, 0x01, 0x06, 0x3A, 0x04, + 0x04, 0x01, 0x00, 0x01, 0x00, 0x04, 0x04, 0x01, 0x00, 0x01, 0x00, 0x46, + 0x25, 0x45, 0x25, 0x7A, 0x61, 0x7A, 0x51, 0x1A, 0x01, 0x01, 0x3D, 0x25, + 0x73, 0x30, 0x1D, 0x00, 0x00, 0x01, 0x81, 0x06, 0x00, 0x01, 0x54, 0x0D, + 0x06, 0x02, 0x32, 0x1D, 0x1B, 0x03, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, + 0x6D, 0x71, 0x1B, 0x01, 0x01, 0x11, 0x06, 0x08, 0x63, 0x01, 0x01, 0x15, + 0x3E, 0x25, 0x04, 0x01, 0x2B, 0x7A, 0x00, 0x00, 0x70, 0x01, 0x06, 0x50, + 0x6F, 0x00, 0x00, 0x70, 0x01, 0x03, 0x50, 0x6B, 0x72, 0x06, 0x02, 0x37, + 0x1D, 0x00, 0x00, 0x26, 0x1B, 0x06, 0x07, 0x21, 0x1B, 0x06, 0x01, 0x16, + 0x04, 0x76, 0x2B, 0x00, 0x00, 0x01, 0x01, 0x50, 0x6A, 0x01, 0x01, 0x10, + 0x06, 0x02, 0x2C, 0x1D, 0x72, 0x27, 0x00, 0x00, 0x60, 0x05, 0x02, 0x39, + 0x1D, 0x47, 0x1C, 0x06, 0x04, 0x01, 0x17, 0x04, 0x12, 0x48, 0x1C, 0x06, + 0x04, 0x01, 0x18, 0x04, 0x0A, 0x49, 0x1C, 0x06, 0x04, 0x01, 0x19, 0x04, + 0x02, 0x39, 0x1D, 0x00, 0x04, 0x70, 0x1B, 0x01, 0x17, 0x01, 0x18, 0x4B, + 0x05, 0x02, 0x2F, 0x1D, 0x01, 0x18, 0x11, 0x03, 0x00, 0x4D, 0x6B, 0x66, + 0x02, 0x00, 0x06, 0x0C, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01, 0x66, 0x02, + 0x01, 0x09, 0x04, 0x0E, 0x1B, 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, 0x67, 0x2A, 0x01, 0x01, 0x0E, 0x02, 0x01, 0x01, 0x04, + 0x07, 0x28, 0x02, 0x01, 0x01, 0x80, 0x64, 0x07, 0x27, 0x02, 0x01, 0x01, + 0x83, 0x10, 0x07, 0x28, 0x1F, 0x15, 0x06, 0x03, 0x01, 0x18, 0x09, 0x5D, + 0x09, 0x52, 0x1B, 0x01, 0x05, 0x14, 0x02, 0x03, 0x09, 0x03, 0x03, 0x01, + 0x1F, 0x15, 0x01, 0x01, 0x26, 0x67, 0x02, 0x03, 0x09, 0x2A, 0x03, 0x03, + 0x01, 0x00, 0x01, 0x17, 0x67, 0x01, 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, + 0x00, 0x01, 0x3B, 0x67, 0x01, 0x3C, 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, + 0x01, 0x00, 0x01, 0x3C, 0x67, 0x02, 0x02, 0x09, 0x03, 0x02, 0x72, 0x1B, + 0x01, 0x2E, 0x11, 0x06, 0x0D, 0x1A, 0x72, 0x1B, 0x01, 0x30, 0x01, 0x39, + 0x4B, 0x06, 0x03, 0x1A, 0x04, 0x74, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, + 0x2F, 0x1D, 0x51, 0x02, 0x03, 0x02, 0x02, 0x00, 0x01, 0x72, 0x53, 0x01, + 0x0A, 0x08, 0x03, 0x00, 0x72, 0x53, 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, + 0x00, 0x03, 0x01, 0x66, 0x1B, 0x02, 0x01, 0x02, 0x00, 0x4B, 0x05, 0x02, + 0x2F, 0x1D, 0x00, 0x00, 0x23, 0x70, 0x01, 0x02, 0x50, 0x0B, 0x69, 0x00, + 0x03, 0x1B, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x6B, 0x72, 0x1B, 0x01, + 0x81, 0x00, 0x13, 0x06, 0x02, 0x36, 0x1D, 0x1B, 0x01, 0x00, 0x11, 0x06, + 0x0B, 0x1A, 0x1B, 0x05, 0x04, 0x1A, 0x01, 0x00, 0x00, 0x72, 0x04, 0x6F, + 0x02, 0x01, 0x1B, 0x05, 0x02, 0x33, 0x1D, 0x2A, 0x03, 0x01, 0x02, 0x02, + 0x25, 0x02, 0x02, 0x29, 0x03, 0x02, 0x1B, 0x06, 0x03, 0x72, 0x04, 0x68, + 0x1A, 0x02, 0x00, 0x02, 0x01, 0x0A, 0x00, 0x01, 0x72, 0x1B, 0x01, 0x81, + 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01, 0x81, 0x00, 0x0A, 0x1B, 0x05, 0x02, + 0x31, 0x1D, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, + 0x19, 0x02, 0x00, 0x2A, 0x03, 0x00, 0x1B, 0x01, 0x83, 0xFF, 0xFF, 0x7F, + 0x12, 0x06, 0x02, 0x32, 0x1D, 0x01, 0x08, 0x0E, 0x26, 0x72, 0x23, 0x09, + 0x04, 0x60, 0x00, 0x00, 0x6A, 0x5E, 0x00, 0x00, 0x6B, 0x7A, 0x00, 0x00, + 0x70, 0x4E, 0x6B, 0x00, 0x01, 0x6B, 0x1B, 0x05, 0x02, 0x36, 0x1D, 0x72, + 0x1B, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x36, 0x1D, 0x03, 0x00, 0x1B, + 0x06, 0x16, 0x72, 0x02, 0x00, 0x1B, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, + 0x06, 0x02, 0x36, 0x1D, 0x01, 0x08, 0x0E, 0x09, 0x03, 0x00, 0x04, 0x67, + 0x1A, 0x02, 0x00, 0x00, 0x00, 0x6B, 0x1B, 0x01, 0x81, 0x7F, 0x12, 0x06, + 0x08, 0x7A, 0x01, 0x00, 0x44, 0x25, 0x01, 0x00, 0x00, 0x1B, 0x44, 0x25, + 0x44, 0x29, 0x62, 0x01, 0x7F, 0x00, 0x01, 0x72, 0x03, 0x00, 0x02, 0x00, + 0x01, 0x05, 0x14, 0x01, 0x01, 0x15, 0x1E, 0x02, 0x00, 0x01, 0x06, 0x14, + 0x1B, 0x01, 0x01, 0x15, 0x06, 0x02, 0x2D, 0x1D, 0x01, 0x04, 0x0E, 0x02, + 0x00, 0x01, 0x1F, 0x15, 0x1B, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x2E, 0x1D, + 0x09, 0x00, 0x00, 0x1B, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x70, + 0x00, 0x00, 0x1B, 0x05, 0x02, 0x32, 0x1D, 0x2A, 0x73, 0x00, 0x00, 0x22, + 0x1B, 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x1A, 0x16, 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, + 0x7B, 0x1A, 0x00, 0x00, 0x1B, 0x06, 0x07, 0x7C, 0x1B, 0x06, 0x01, 0x16, + 0x04, 0x76, 0x00, 0x00, 0x01, 0x00, 0x20, 0x21, 0x0B, 0x2B, 0x00 +}; + +static const uint16_t t0_caddr[] = { + 0, + 5, + 10, + 15, + 20, + 24, + 28, + 32, + 36, + 40, + 44, + 48, + 52, + 56, + 60, + 64, + 68, + 72, + 76, + 80, + 84, + 88, + 93, + 98, + 103, + 111, + 116, + 121, + 126, + 131, + 136, + 141, + 146, + 151, + 156, + 161, + 166, + 181, + 187, + 193, + 198, + 206, + 214, + 220, + 231, + 246, + 250, + 255, + 260, + 265, + 270, + 275, + 279, + 289, + 620, + 625, + 639, + 659, + 666, + 678, + 692, + 707, + 740, + 960, + 974, + 991, + 1000, + 1067, + 1123, + 1127, + 1131, + 1136, + 1184, + 1210, + 1254, + 1265, + 1274, + 1287, + 1291, + 1295, + 1299, + 1303, + 1307, + 1311, + 1315, + 1327 +}; + +#define T0_INTERPRETED 39 + +#define T0_ENTER(ip, rp, slot) do { \ + const unsigned char *t0_newip; \ + uint32_t t0_lnum; \ + t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ + t0_lnum = t0_parse7E_unsigned(&t0_newip); \ + (rp) += t0_lnum; \ + *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ + (ip) = t0_newip; \ + } while (0) + +#define T0_DEFENTRY(name, slot) \ +void \ +name(void *ctx) \ +{ \ + t0_context *t0ctx = ctx; \ + t0ctx->ip = &t0_codeblock[0]; \ + T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ +} + +T0_DEFENTRY(br_x509_decoder_init_main, 92) + +#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) + +void +br_x509_decoder_run(void *t0ctx) +{ + uint32_t *dp, *rp; + const unsigned char *ip; + +#define T0_LOCAL(x) (*(rp - 2 - (x))) +#define T0_POP() (*-- dp) +#define T0_POPi() (*(int32_t *)(-- dp)) +#define T0_PEEK(x) (*(dp - 1 - (x))) +#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) +#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) +#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) +#define T0_RPOP() (*-- rp) +#define T0_RPOPi() (*(int32_t *)(-- rp)) +#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) +#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) +#define T0_ROLL(x) do { \ + size_t t0len = (size_t)(x); \ + uint32_t t0tmp = *(dp - 1 - t0len); \ + memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_SWAP() do { \ + uint32_t t0tmp = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_ROT() do { \ + uint32_t t0tmp = *(dp - 3); \ + *(dp - 3) = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_NROT() do { \ + uint32_t t0tmp = *(dp - 1); \ + *(dp - 1) = *(dp - 2); \ + *(dp - 2) = *(dp - 3); \ + *(dp - 3) = t0tmp; \ +} while (0) +#define T0_PICK(x) do { \ + uint32_t t0depth = (x); \ + T0_PUSH(T0_PEEK(t0depth)); \ +} while (0) +#define T0_CO() do { \ + goto t0_exit; \ +} while (0) +#define T0_RET() goto t0_next + + dp = ((t0_context *)t0ctx)->dp; + rp = ((t0_context *)t0ctx)->rp; + ip = ((t0_context *)t0ctx)->ip; + goto t0_next; + for (;;) { + uint32_t t0x; + + t0_next: + t0x = T0_NEXT(&ip); + if (t0x < T0_INTERPRETED) { + switch (t0x) { + int32_t t0off; + + case 0: /* ret */ + t0x = T0_RPOP(); + rp -= (t0x >> 16); + t0x &= 0xFFFF; + if (t0x == 0) { + ip = NULL; + goto t0_exit; + } + ip = &t0_codeblock[t0x]; + break; + case 1: /* literal constant */ + T0_PUSHi(t0_parse7E_signed(&ip)); + break; + case 2: /* read local */ + T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); + break; + case 3: /* write local */ + T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); + break; + case 4: /* jump */ + t0off = t0_parse7E_signed(&ip); + ip += t0off; + break; + case 5: /* jump if */ + t0off = t0_parse7E_signed(&ip); + if (T0_POP()) { + ip += t0off; + } + break; + case 6: /* jump if not */ + t0off = t0_parse7E_signed(&ip); + if (!T0_POP()) { + ip += t0off; + } + break; + case 7: { + /* %25 */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSHi(a % b); + + } + break; + case 8: { + /* * */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a * b); + + } + break; + case 9: { + /* + */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a + b); + + } + break; + case 10: { + /* - */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a - b); + + } + break; + case 11: { + /* -rot */ + T0_NROT(); + } + break; + case 12: { + /* / */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSHi(a / b); + + } + break; + case 13: { + /* < */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a < b)); + + } + break; + case 14: { + /* << */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x << c); + + } + break; + case 15: { + /* <= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a <= b)); + + } + break; + case 16: { + /* <> */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a != b)); + + } + break; + case 17: { + /* = */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a == b)); + + } + break; + case 18: { + /* > */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a > b)); + + } + break; + case 19: { + /* >= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a >= b)); + + } + break; + case 20: { + /* >> */ + + int c = (int)T0_POPi(); + int32_t x = T0_POPi(); + T0_PUSHi(x >> c); + + } + break; + case 21: { + /* and */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a & b); + + } + break; + case 22: { + /* co */ + T0_CO(); + } + break; + case 23: { + /* copy-ec-pkey */ + + size_t qlen = T0_POP(); + uint32_t curve = T0_POP(); + CTX->pkey.key_type = BR_KEYTYPE_EC; + CTX->pkey.key.ec.curve = curve; + CTX->pkey.key.ec.q = CTX->pkey_data; + CTX->pkey.key.ec.qlen = qlen; + + } + break; + case 24: { + /* copy-rsa-pkey */ + + size_t elen = T0_POP(); + size_t nlen = T0_POP(); + CTX->pkey.key_type = BR_KEYTYPE_RSA; + CTX->pkey.key.rsa.n = CTX->pkey_data; + CTX->pkey.key.rsa.nlen = nlen; + CTX->pkey.key.rsa.e = CTX->pkey_data + nlen; + CTX->pkey.key.rsa.elen = elen; + + } + break; + case 25: { + /* data-get8 */ + + size_t addr = T0_POP(); + T0_PUSH(t0_datablock[addr]); + + } + break; + case 26: { + /* drop */ + (void)T0_POP(); + } + break; + case 27: { + /* dup */ + T0_PUSH(T0_PEEK(0)); + } + break; + case 28: { + /* eqOID */ + + const unsigned char *a2 = &t0_datablock[T0_POP()]; + const unsigned char *a1 = &CTX->pad[0]; + size_t len = a1[0]; + int x; + if (len == a2[0]) { + x = -(memcmp(a1 + 1, a2 + 1, len) == 0); + } else { + x = 0; + } + T0_PUSH((uint32_t)x); + + } + break; + case 29: { + /* fail */ + + CTX->err = T0_POPi(); + T0_CO(); + + } + break; + case 30: { + /* neg */ + + uint32_t a = T0_POP(); + T0_PUSH(-a); + + } + break; + case 31: { + /* or */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a | b); + + } + break; + case 32: { + /* over */ + T0_PUSH(T0_PEEK(1)); + } + break; + case 33: { + /* read-blob-inner */ + + uint32_t len = T0_POP(); + uint32_t addr = T0_POP(); + size_t clen = CTX->hlen; + if (clen > len) { + clen = (size_t)len; + } + if (addr != 0) { + memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); + } + if (CTX->copy_dn && CTX->append_dn) { + CTX->append_dn(CTX->append_dn_ctx, CTX->hbuf, clen); + } + CTX->hbuf += clen; + CTX->hlen -= clen; + T0_PUSH(addr + clen); + T0_PUSH(len - clen); + + } + break; + case 34: { + /* read8-low */ + + if (CTX->hlen == 0) { + T0_PUSHi(-1); + } else { + unsigned char x = *CTX->hbuf ++; + if (CTX->copy_dn && CTX->append_dn) { + CTX->append_dn(CTX->append_dn_ctx, &x, 1); + } + CTX->hlen --; + T0_PUSH(x); + } + + } + break; + case 35: { + /* rot */ + T0_ROT(); + } + break; + case 36: { + /* set32 */ + + uint32_t addr = T0_POP(); + *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); + + } + break; + case 37: { + /* set8 */ + + uint32_t addr = T0_POP(); + *((unsigned char *)CTX + addr) = (unsigned char)T0_POP(); + + } + break; + case 38: { + /* swap */ + T0_SWAP(); + } + break; + } + + } else { + T0_ENTER(ip, rp, t0x); + } + } +t0_exit: + ((t0_context *)t0ctx)->dp = dp; + ((t0_context *)t0ctx)->rp = rp; + ((t0_context *)t0ctx)->ip = ip; +} diff --git a/BearSSL-OG/libbearssl/src/x509/x509_decoder.t0 b/BearSSL-OG/libbearssl/src/x509/x509_decoder.t0 new file mode 100644 index 0000000..0bf276f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/x509_decoder.t0 @@ -0,0 +1,321 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +preamble { + +#include "inner.h" + +#define CTX ((br_x509_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_decoder_context, cpu))) +#define CONTEXT_NAME br_x509_decoder_context + +/* see bearssl_x509.h */ +void +br_x509_decoder_init(br_x509_decoder_context *ctx, + void (*append_dn)(void *ctx, const void *buf, size_t len), + void *append_dn_ctx) +{ + memset(ctx, 0, sizeof *ctx); + /* obsolete + ctx->err = 0; + ctx->hbuf = NULL; + ctx->hlen = 0; + */ + ctx->append_dn = append_dn; + ctx->append_dn_ctx = append_dn_ctx; + ctx->cpu.dp = &ctx->dp_stack[0]; + ctx->cpu.rp = &ctx->rp_stack[0]; + br_x509_decoder_init_main(&ctx->cpu); + br_x509_decoder_run(&ctx->cpu); +} + +/* see bearssl_x509.h */ +void +br_x509_decoder_push(br_x509_decoder_context *ctx, + const void *data, size_t len) +{ + ctx->hbuf = data; + ctx->hlen = len; + br_x509_decoder_run(&ctx->cpu); +} + +} + +addr: decoded +addr: notbefore_days +addr: notbefore_seconds +addr: notafter_days +addr: notafter_seconds +addr: isCA +addr: copy_dn +addr: signer_key_type +addr: signer_hash_id + +cc: read8-low ( -- x ) { + if (CTX->hlen == 0) { + T0_PUSHi(-1); + } else { + unsigned char x = *CTX->hbuf ++; + if (CTX->copy_dn && CTX->append_dn) { + CTX->append_dn(CTX->append_dn_ctx, &x, 1); + } + CTX->hlen --; + T0_PUSH(x); + } +} + +cc: read-blob-inner ( addr len -- addr len ) { + uint32_t len = T0_POP(); + uint32_t addr = T0_POP(); + size_t clen = CTX->hlen; + if (clen > len) { + clen = (size_t)len; + } + if (addr != 0) { + memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); + } + if (CTX->copy_dn && CTX->append_dn) { + CTX->append_dn(CTX->append_dn_ctx, CTX->hbuf, clen); + } + CTX->hbuf += clen; + CTX->hlen -= clen; + T0_PUSH(addr + clen); + T0_PUSH(len - clen); +} + +\ Get the address and length for the pkey_data buffer. +: addr-len-pkey_data ( -- addr len ) + CX 0 8191 { offsetof(br_x509_decoder_context, pkey_data) } + CX 0 8191 { BR_X509_BUFSIZE_KEY } ; + +\ Copy the public key (RSA) to the permanent buffer. +cc: copy-rsa-pkey ( nlen elen -- ) { + size_t elen = T0_POP(); + size_t nlen = T0_POP(); + CTX->pkey.key_type = BR_KEYTYPE_RSA; + CTX->pkey.key.rsa.n = CTX->pkey_data; + CTX->pkey.key.rsa.nlen = nlen; + CTX->pkey.key.rsa.e = CTX->pkey_data + nlen; + CTX->pkey.key.rsa.elen = elen; +} + +\ Copy the public key (EC) to the permanent buffer. +cc: copy-ec-pkey ( curve qlen -- ) { + size_t qlen = T0_POP(); + uint32_t curve = T0_POP(); + CTX->pkey.key_type = BR_KEYTYPE_EC; + CTX->pkey.key.ec.curve = curve; + CTX->pkey.key.ec.q = CTX->pkey_data; + CTX->pkey.key.ec.qlen = qlen; +} + +\ Extensions with specific processing. +OID: basicConstraints 2.5.29.19 + +\ Process a Basic Constraints extension. We want the "CA" flag only. +: process-basicConstraints ( lim -- lim ) + read-sequence-open + read-tag-or-end dup 0x01 = if + read-boolean 1 and addr-isCA set8 + else + 2drop + then + skip-close-elt + ; + +\ Decode a certificate. +: main ( -- ! ) + + \ Initialise state flags. + 0 addr-decoded set8 + 0 addr-copy_dn set8 + + \ An arbitrary limit for the total certificate size. + 0xFFFFFF + + \ Open the outer SEQUENCE. + read-sequence-open + + \ TBS + read-sequence-open + + \ First element may be an explicit version. We accept only + \ versions 0 to 2 (certificates v1 to v3). + read-tag dup 0x20 = if + drop check-constructed read-length-open-elt + read-tag + 0x02 check-tag-primitive + read-small-int-value + 2 > if ERR_X509_UNSUPPORTED fail then + close-elt + read-tag + then + + \ Serial number. We just check that the tag is correct. + 0x02 check-tag-primitive read-length-skip + + \ Signature algorithm. + read-sequence-open skip-close-elt + + \ Issuer name. + read-sequence-open skip-close-elt + + \ Validity dates. + read-sequence-open + read-date addr-notbefore_seconds set32 addr-notbefore_days set32 + read-date addr-notafter_seconds set32 addr-notafter_days set32 + close-elt + + \ Subject name. + 1 addr-copy_dn set8 + read-sequence-open skip-close-elt + 0 addr-copy_dn set8 + + \ Public Key. + read-sequence-open + \ Algorithm Identifier. Right now we are only interested in the + \ OID, since we only support RSA keys. + \ TODO: support EC keys + read-sequence-open + read-OID ifnot ERR_X509_UNSUPPORTED fail then + choice + \ RSA public key. + rsaEncryption eqOID uf + skip-close-elt + \ Public key itself: the BIT STRING contains bytes + \ (no partial byte) and these bytes encode the + \ actual value. + read-bits-open + \ RSA public key is a SEQUENCE of two + \ INTEGER. We get both INTEGER values into + \ the pkey_data[] buffer, if they fit. + read-sequence-open + addr-len-pkey_data + read-integer { nlen } + addr-len-pkey_data swap nlen + swap nlen - + read-integer { elen } + close-elt + close-elt + nlen elen copy-rsa-pkey + enduf + + \ EC public key. + id-ecPublicKey eqOID uf + \ We support only named curves, for which the + \ "parameters" field in the AlgorithmIdentifier + \ field should be an OID. + read-curve-ID { curve } + close-elt + read-bits-open + dup { qlen } + dup addr-len-pkey_data rot < if + ERR_X509_LIMIT_EXCEEDED fail + then + read-blob + curve qlen copy-ec-pkey + enduf + ERR_X509_UNSUPPORTED fail + endchoice + close-elt + + \ This flag will be set to true if the Basic Constraints extension + \ is encountered. + 0 addr-isCA set8 + + \ Skip issuerUniqueID and subjectUniqueID, and process extensions + \ if present. Extensions are an explicit context tag of value 3 + \ around a SEQUENCE OF extensions. Each extension is a SEQUENCE + \ with an OID, an optional boolean, and a value; the value is + \ an OCTET STRING. + read-tag-or-end + 0x21 iftag-skip + 0x22 iftag-skip + dup 0x23 = if + drop + check-constructed read-length-open-elt + read-sequence-open + begin dup while + read-sequence-open + read-OID drop + read-tag dup 0x01 = if + read-boolean drop + read-tag + then + 0x04 check-tag-primitive read-length-open-elt + choice + \ Extensions with specific processing. + basicConstraints eqOID uf + process-basicConstraints + enduf + skip-remaining + endchoice + close-elt + close-elt + repeat + close-elt + close-elt + else + -1 = ifnot ERR_X509_UNEXPECTED fail then + drop + then + + close-elt + + \ signature algorithm + read-sequence-open + read-OID if + choice + sha1WithRSAEncryption eqOID uf 2 KEYTYPE_RSA enduf + sha224WithRSAEncryption eqOID uf 3 KEYTYPE_RSA enduf + sha256WithRSAEncryption eqOID uf 4 KEYTYPE_RSA enduf + sha384WithRSAEncryption eqOID uf 5 KEYTYPE_RSA enduf + sha512WithRSAEncryption eqOID uf 6 KEYTYPE_RSA enduf + + ecdsa-with-SHA1 eqOID uf 2 KEYTYPE_EC enduf + ecdsa-with-SHA224 eqOID uf 3 KEYTYPE_EC enduf + ecdsa-with-SHA256 eqOID uf 4 KEYTYPE_EC enduf + ecdsa-with-SHA384 eqOID uf 5 KEYTYPE_EC enduf + ecdsa-with-SHA512 eqOID uf 6 KEYTYPE_EC enduf + + 0 0 + endchoice + else + 0 0 + then + addr-signer_key_type set8 + addr-signer_hash_id set8 + skip-close-elt + \ read-sequence-open skip-close-elt + + \ signature value + read-bits-open skip-close-elt + + \ Close the outer SEQUENCE. + close-elt + drop + + \ Mark the decoding as successful. + 1 addr-decoded set8 + + \ Read one byte, then fail: if the read succeeds, then there is + \ some trailing byte. + read8-nc ERR_X509_EXTRA_ELEMENT fail + ; diff --git a/BearSSL-OG/libbearssl/src/x509/x509_knownkey.c b/BearSSL-OG/libbearssl/src/x509/x509_knownkey.c new file mode 100644 index 0000000..7674f3f --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/x509_knownkey.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_x509.h */ +void +br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx, + 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, 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, const char *server_name) +{ + (void)ctx; + (void)server_name; +} + +static void +kk_start_cert(const br_x509_class **ctx, uint32_t length) +{ + (void)ctx; + (void)length; +} + +static void +kk_append(const br_x509_class **ctx, const unsigned char *buf, size_t len) +{ + (void)ctx; + (void)buf; + (void)len; +} + +static void +kk_end_cert(const br_x509_class **ctx) +{ + (void)ctx; +} + +static unsigned +kk_end_chain(const br_x509_class **ctx) +{ + (void)ctx; + return 0; +} + +static const br_x509_pkey * +kk_get_pkey(const br_x509_class *const *ctx, unsigned *usages) +{ + 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 */ +const br_x509_class br_x509_knownkey_vtable = { + sizeof(br_x509_knownkey_context), + kk_start_chain, + kk_start_cert, + kk_append, + kk_end_cert, + kk_end_chain, + kk_get_pkey +}; diff --git a/BearSSL-OG/libbearssl/src/x509/x509_minimal.c b/BearSSL-OG/libbearssl/src/x509/x509_minimal.c new file mode 100644 index 0000000..83d8af9 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/x509_minimal.c @@ -0,0 +1,1745 @@ +/* Automatically generated code; do not modify directly. */ + +#include +#include + +typedef struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; +} t0_context; + +static uint32_t +t0_parse7E_unsigned(const unsigned char **p) +{ + uint32_t x; + + x = 0; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + return x; + } + } +} + +static int32_t +t0_parse7E_signed(const unsigned char **p) +{ + int neg; + uint32_t x; + + neg = ((**p) >> 6) & 1; + x = (uint32_t)-neg; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + if (neg) { + return -(int32_t)~x - 1; + } else { + return (int32_t)x; + } + } + } +} + +#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) +#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) +#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) +#define T0_INT1(x) T0_FBYTE(x, 0) +#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) + +/* static const unsigned char t0_datablock[]; */ + + +void br_x509_minimal_init_main(void *t0ctx); + +void br_x509_minimal_run(void *t0ctx); + + + +#include "inner.h" + + + + + +#include "inner.h" + +/* + * Implementation Notes + * -------------------- + * + * The C code pushes the data by chunks; all decoding is done in the + * T0 code. The cert_length value is set to the certificate length when + * a new certificate is started; the T0 code picks it up as outer limit, + * and decoding functions use it to ensure that no attempt is made at + * reading past it. The T0 code also checks that once the certificate is + * decoded, there are no trailing bytes. + * + * The T0 code sets cert_length to 0 when the certificate is fully + * decoded. + * + * The C code must still perform two checks: + * + * -- If the certificate length is 0, then the T0 code will not be + * invoked at all. This invalid condition must thus be reported by the + * C code. + * + * -- When reaching the end of certificate, the C code must verify that + * the certificate length has been set to 0, thereby signaling that + * the T0 code properly decoded a certificate. + * + * Processing of a chain works in the following way: + * + * -- The error flag is set to a non-zero value when validation is + * finished. The value is either BR_ERR_X509_OK (validation is + * successful) or another non-zero error code. When a non-zero error + * code is obtained, the remaining bytes in the current certificate and + * the subsequent certificates (if any) are completely ignored. + * + * -- Each certificate is decoded in due course, with the following + * "interesting points": + * + * -- Start of the TBS: the multihash engine is reset and activated. + * + * -- Start of the issuer DN: the secondary hash engine is started, + * to process the encoded issuer DN. + * + * -- End of the issuer DN: the secondary hash engine is stopped. The + * resulting hash value is computed and then copied into the + * next_dn_hash[] buffer. + * + * -- Start of the subject DN: the secondary hash engine is started, + * to process the encoded subject DN. + * + * -- For the EE certificate only: the Common Name, if any, is matched + * against the expected server name. + * + * -- End of the subject DN: the secondary hash engine is stopped. The + * resulting hash value is computed into the pad. It is then processed: + * + * -- If this is the EE certificate, then the hash is ignored + * (except for direct trust processing, see later; the hash is + * simply left in current_dn_hash[]). + * + * -- Otherwise, the hashed subject DN is compared with the saved + * hash value (in saved_dn_hash[]). They must match. + * + * Either way, the next_dn_hash[] value is then copied into the + * saved_dn_hash[] value. Thus, at that point, saved_dn_hash[] + * contains the hash of the issuer DN for the current certificate, + * and current_dn_hash[] contains the hash of the subject DN for the + * current certificate. + * + * -- Public key: it is decoded into the cert_pkey[] buffer. Unknown + * key types are reported at that point. + * + * -- If this is the EE certificate, then the key type is compared + * with the expected key type (initialization parameter). The public + * key data is copied to ee_pkey_data[]. The key and hashed subject + * DN are also compared with the "direct trust" keys; if the key + * and DN are matched, then validation ends with a success. + * + * -- Otherwise, the saved signature (cert_sig[]) is verified + * against the saved TBS hash (tbs_hash[]) and that freshly + * decoded public key. Failure here ends validation with an error. + * + * -- Extensions: extension values are processed in due order. + * + * -- Basic Constraints: for all certificates except EE, must be + * present, indicate a CA, and have a path length compatible with + * the chain length so far. + * + * -- Key Usage: for the EE, if present, must allow signatures + * or encryption/key exchange, as required for the cipher suite. + * For non-EE, if present, must have the "certificate sign" bit. + * + * -- Subject Alt Name: for the EE, dNSName names are matched + * against the server name. Ignored for non-EE. + * + * -- Authority Key Identifier, Subject Key Identifier, Issuer + * Alt Name, Subject Directory Attributes, CRL Distribution Points + * Freshest CRL, Authority Info Access and Subject Info Access + * extensions are always ignored: they either contain only + * informative data, or they relate to revocation processing, which + * we explicitly do not support. + * + * -- All other extensions are ignored if non-critical. If a + * critical extension other than the ones above is encountered, + * then a failure is reported. + * + * -- End of the TBS: the multihash engine is stopped. + * + * -- Signature algorithm: the signature algorithm on the + * certificate is decoded. A failure is reported if that algorithm + * is unknown. The hashed TBS corresponding to the signature hash + * function is computed and stored in tbs_hash[] (if not supported, + * then a failure is reported). The hash OID and length are stored + * in cert_sig_hash_oid and cert_sig_hash_len. + * + * -- Signature value: the signature value is copied into the + * cert_sig[] array. + * + * -- Certificate end: the hashed issuer DN (saved_dn_hash[]) is + * looked up in the trust store (CA trust anchors only); for all + * that match, the signature (cert_sig[]) is verified against the + * anchor public key (hashed TBS is in tbs_hash[]). If one of these + * signatures is valid, then validation ends with a success. + * + * -- If the chain end is reached without obtaining a validation success, + * then validation is reported as failed. + */ + +#if BR_USE_UNIX_TIME +#include +#endif + +#if BR_USE_WIN32_TIME +#ifdef _XBOX +#include +/* + * KeQuerySystemTime is exported by the Xbox kernel (xboxkrnl.lib). + * It returns the current system time in 100-nanosecond intervals + * since January 1, 1601 (same format as FILETIME). + */ +#ifdef __cplusplus +extern "C" +#endif +void WINAPI KeQuerySystemTime(PLARGE_INTEGER CurrentTime); +#else +#include +#endif +#endif + +/* + * The T0 compiler will produce these prototypes declarations in the + * header. + * +void br_x509_minimal_init_main(void *ctx); +void br_x509_minimal_run(void *ctx); + */ + +/* see bearssl_x509.h */ +void +br_x509_minimal_init(br_x509_minimal_context *ctx, + const br_hash_class *dn_hash_impl, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) +{ + memset(ctx, 0, sizeof *ctx); + ctx->vtable = &br_x509_minimal_vtable; + ctx->dn_hash_impl = dn_hash_impl; + ctx->trust_anchors = trust_anchors; + ctx->trust_anchors_num = trust_anchors_num; +} + +static void +xm_start_chain(const br_x509_class **ctx, const char *server_name) +{ + br_x509_minimal_context *cc; + size_t u; + + cc = (br_x509_minimal_context *)(void *)ctx; + for (u = 0; u < cc->num_name_elts; u ++) { + cc->name_elts[u].status = 0; + cc->name_elts[u].buf[0] = 0; + } + memset(&cc->pkey, 0, sizeof cc->pkey); + cc->num_certs = 0; + cc->err = 0; + cc->cpu.dp = cc->dp_stack; + cc->cpu.rp = cc->rp_stack; + br_x509_minimal_init_main(&cc->cpu); + if (server_name == NULL || *server_name == 0) { + cc->server_name = NULL; + } else { + cc->server_name = server_name; + } +} + +static void +xm_start_cert(const br_x509_class **ctx, uint32_t length) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)ctx; + if (cc->err != 0) { + return; + } + if (length == 0) { + cc->err = BR_ERR_X509_TRUNCATED; + return; + } + cc->cert_length = length; +} + +static void +xm_append(const br_x509_class **ctx, const unsigned char *buf, size_t len) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)ctx; + if (cc->err != 0) { + return; + } + cc->hbuf = buf; + cc->hlen = len; + br_x509_minimal_run(&cc->cpu); +} + +static void +xm_end_cert(const br_x509_class **ctx) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)ctx; + if (cc->err == 0 && cc->cert_length != 0) { + cc->err = BR_ERR_X509_TRUNCATED; + } + cc->num_certs ++; +} + +static unsigned +xm_end_chain(const br_x509_class **ctx) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)ctx; + if (cc->err == 0) { + if (cc->num_certs == 0) { + cc->err = BR_ERR_X509_EMPTY_CHAIN; + } else { + cc->err = BR_ERR_X509_NOT_TRUSTED; + } + } else if (cc->err == BR_ERR_X509_OK) { + return 0; + } + return (unsigned)cc->err; +} + +static const br_x509_pkey * +xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)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 *)(void *)ctx)->pkey; + } else { + return NULL; + } +} + +/* see bearssl_x509.h */ +const br_x509_class br_x509_minimal_vtable = { + sizeof(br_x509_minimal_context), + xm_start_chain, + xm_start_cert, + xm_append, + xm_end_cert, + xm_end_chain, + xm_get_pkey +}; + +#define CTX ((br_x509_minimal_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_minimal_context, cpu))) +#define CONTEXT_NAME br_x509_minimal_context + +#define DNHASH_LEN ((CTX->dn_hash_impl->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK) + +/* + * Hash a DN (from a trust anchor) into the provided buffer. This uses the + * DN hash implementation and context structure from the X.509 engine + * context. + */ +static void +hash_dn(br_x509_minimal_context *ctx, const void *dn, size_t len, + unsigned char *out) +{ + ctx->dn_hash_impl->init(&ctx->dn_hash.vtable); + ctx->dn_hash_impl->update(&ctx->dn_hash.vtable, dn, len); + ctx->dn_hash_impl->out(&ctx->dn_hash.vtable, out); +} + +/* + * Compare two big integers for equality. The integers use unsigned big-endian + * encoding; extra leading bytes (of value 0) are allowed. + */ +static int +eqbigint(const unsigned char *b1, size_t len1, + const unsigned char *b2, size_t len2) +{ + while (len1 > 0 && *b1 == 0) { + b1 ++; + len1 --; + } + while (len2 > 0 && *b2 == 0) { + b2 ++; + len2 --; + } + if (len1 != len2) { + return 0; + } + return memcmp(b1, b2, len1) == 0; +} + +/* + * Compare two strings for equality, in a case-insensitive way. This + * function handles casing only for ASCII letters. + */ +static int +eqnocase(const void *s1, const void *s2, size_t len) +{ + const unsigned char *buf1, *buf2; + + buf1 = s1; + buf2 = s2; + while (len -- > 0) { + int x1, x2; + + x1 = *buf1 ++; + x2 = *buf2 ++; + if (x1 >= 'A' && x1 <= 'Z') { + x1 += 'a' - 'A'; + } + if (x2 >= 'A' && x2 <= 'Z') { + x2 += 'a' - 'A'; + } + if (x1 != x2) { + return 0; + } + } + return 1; +} + +static int verify_signature(br_x509_minimal_context *ctx, + const br_x509_pkey *pk); + + + +static const unsigned char t0_datablock[] = { + 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0E, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x0C, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, + 0x0D, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x65, 0x03, 0x04, 0x02, 0x04, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x01, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x02, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x07, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x05, 0x2B, + 0x81, 0x04, 0x00, 0x23, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x04, 0x03, 0x03, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04, + 0x03, 0x55, 0x04, 0x03, 0x00, 0x1F, 0x03, 0xFC, 0x07, 0x7F, 0x0B, 0x5E, + 0x0F, 0x1F, 0x12, 0xFE, 0x16, 0xBF, 0x1A, 0x9F, 0x1E, 0x7E, 0x22, 0x3F, + 0x26, 0x1E, 0x29, 0xDF, 0x00, 0x1F, 0x03, 0xFD, 0x07, 0x9F, 0x0B, 0x7E, + 0x0F, 0x3F, 0x13, 0x1E, 0x16, 0xDF, 0x1A, 0xBF, 0x1E, 0x9E, 0x22, 0x5F, + 0x26, 0x3E, 0x29, 0xFF, 0x03, 0x55, 0x1D, 0x13, 0x03, 0x55, 0x1D, 0x0F, + 0x03, 0x55, 0x1D, 0x11, 0x03, 0x55, 0x1D, 0x20, 0x08, 0x2B, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x02, 0x01, 0x03, 0x55, 0x1D, 0x23, 0x03, 0x55, 0x1D, + 0x0E, 0x03, 0x55, 0x1D, 0x12, 0x03, 0x55, 0x1D, 0x09, 0x03, 0x55, 0x1D, + 0x1F, 0x03, 0x55, 0x1D, 0x2E, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x01, 0x01, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0B +}; + +static const unsigned char t0_codeblock[] = { + 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x01, 0x0A, + 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_BOOLEAN), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_DN), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_SERVER_NAME), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_BAD_TIME), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_CRITICAL_EXTENSION), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_DN_MISMATCH), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_EXPIRED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_FORBIDDEN_KEY_USAGE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_NOT_CA), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_PARTIAL_BYTE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_X509_WEAK_PUBLIC_KEY), 0x00, 0x00, 0x01, + T0_INT1(BR_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, + 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_hash_len)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_hash_oid)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_len)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(CONTEXT_NAME, cert_signer_key_type)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(CONTEXT_NAME, current_dn_hash)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(CONTEXT_NAME, 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, 0x01, 0x80, + 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00, 0x00, 0x01, 0x81, 0x02, 0x00, + 0x00, 0x8F, 0x05, 0x05, 0x33, 0x41, 0x01, 0x00, 0x00, 0x33, 0x01, 0x0A, + 0x0E, 0x09, 0x01, 0x9A, 0xFF, 0xB8, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x82, + 0x19, 0x00, 0x00, 0x01, 0x82, 0x01, 0x00, 0x00, 0x01, 0x81, 0x68, 0x00, + 0x02, 0x03, 0x00, 0x03, 0x01, 0x26, 0x02, 0x01, 0x13, 0x3A, 0x02, 0x00, + 0x0F, 0x15, 0x00, 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x05, 0x02, 0x51, + 0x29, 0x00, 0x00, 0x06, 0x02, 0x52, 0x29, 0x00, 0x00, 0x01, 0x10, 0x74, + 0x00, 0x00, 0x11, 0x05, 0x02, 0x55, 0x29, 0x71, 0x00, 0x00, 0x11, 0x05, + 0x02, 0x55, 0x29, 0x72, 0x00, 0x00, 0x06, 0x02, 0x4B, 0x29, 0x00, 0x00, + 0x01, 0x82, 0x11, 0x00, 0x00, 0x26, 0x21, 0x01, 0x08, 0x0E, 0x3A, 0x3F, + 0x21, 0x09, 0x00, 0x0B, 0x03, 0x00, 0x5A, 0x2B, 0xAC, 0x38, 0xAC, 0xB0, + 0x26, 0x01, 0x20, 0x11, 0x06, 0x11, 0x25, 0x71, 0xAA, 0xB0, 0x01, 0x02, + 0x75, 0xAD, 0x01, 0x02, 0x12, 0x06, 0x02, 0x56, 0x29, 0x76, 0xB0, 0x01, + 0x02, 0x75, 0xAB, 0xAC, 0xBF, 0x99, 0x64, 0x60, 0x22, 0x16, 0xAC, 0xA4, + 0x03, 0x01, 0x03, 0x02, 0xA4, 0x02, 0x02, 0x02, 0x01, 0x19, 0x06, 0x02, + 0x4A, 0x29, 0x76, 0x02, 0x00, 0x06, 0x05, 0x9A, 0x03, 0x03, 0x04, 0x09, + 0x99, 0x60, 0x67, 0x22, 0x28, 0x05, 0x02, 0x49, 0x29, 0x67, 0x64, 0x22, + 0x16, 0xAC, 0xAC, 0x9B, 0x05, 0x02, 0x56, 0x29, 0xB9, 0x27, 0x06, 0x27, + 0xBF, 0xA1, 0xAC, 0x62, 0xA7, 0x03, 0x05, 0x62, 0x3A, 0x02, 0x05, 0x09, + 0x3A, 0x02, 0x05, 0x0A, 0xA7, 0x03, 0x06, 0x76, 0x63, 0x2A, 0x01, 0x81, + 0x00, 0x09, 0x02, 0x05, 0x12, 0x06, 0x02, 0x57, 0x29, 0x76, 0x59, 0x03, + 0x04, 0x04, 0x3A, 0x85, 0x27, 0x06, 0x34, 0x9B, 0x05, 0x02, 0x56, 0x29, + 0x68, 0x27, 0x06, 0x04, 0x01, 0x17, 0x04, 0x12, 0x69, 0x27, 0x06, 0x04, + 0x01, 0x18, 0x04, 0x0A, 0x6A, 0x27, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, + 0x56, 0x29, 0x03, 0x07, 0x76, 0xA1, 0x26, 0x03, 0x08, 0x26, 0x62, 0x33, + 0x0D, 0x06, 0x02, 0x4F, 0x29, 0xA2, 0x58, 0x03, 0x04, 0x04, 0x02, 0x56, + 0x29, 0x76, 0x02, 0x00, 0x06, 0x21, 0x02, 0x04, 0x59, 0x30, 0x11, 0x06, + 0x08, 0x25, 0x02, 0x05, 0x02, 0x06, 0x1E, 0x04, 0x10, 0x58, 0x30, 0x11, + 0x06, 0x08, 0x25, 0x02, 0x07, 0x02, 0x08, 0x1D, 0x04, 0x03, 0x56, 0x29, + 0x25, 0x04, 0x24, 0x02, 0x04, 0x59, 0x30, 0x11, 0x06, 0x08, 0x25, 0x02, + 0x05, 0x02, 0x06, 0x24, 0x04, 0x10, 0x58, 0x30, 0x11, 0x06, 0x08, 0x25, + 0x02, 0x07, 0x02, 0x08, 0x23, 0x04, 0x03, 0x56, 0x29, 0x25, 0x26, 0x06, + 0x01, 0x29, 0x25, 0x01, 0x00, 0x03, 0x09, 0xB1, 0x01, 0x21, 0x8C, 0x01, + 0x22, 0x8C, 0x26, 0x01, 0x23, 0x11, 0x06, 0x81, 0x26, 0x25, 0x71, 0xAA, + 0xAC, 0x26, 0x06, 0x81, 0x1A, 0x01, 0x00, 0x03, 0x0A, 0xAC, 0x9B, 0x25, + 0xB0, 0x26, 0x01, 0x01, 0x11, 0x06, 0x04, 0xA3, 0x03, 0x0A, 0xB0, 0x01, + 0x04, 0x75, 0xAA, 0x6E, 0x27, 0x06, 0x0F, 0x02, 0x00, 0x06, 0x03, 0xC0, + 0x04, 0x05, 0x96, 0x01, 0x7F, 0x03, 0x09, 0x04, 0x80, 0x6C, 0x8E, 0x27, + 0x06, 0x06, 0x02, 0x00, 0x98, 0x04, 0x80, 0x62, 0xC2, 0x27, 0x06, 0x11, + 0x02, 0x00, 0x06, 0x09, 0x01, 0x00, 0x03, 0x03, 0x95, 0x03, 0x03, 0x04, + 0x01, 0xC0, 0x04, 0x80, 0x4D, 0x70, 0x27, 0x06, 0x0A, 0x02, 0x0A, 0x06, + 0x03, 0x97, 0x04, 0x01, 0xC0, 0x04, 0x3F, 0x6D, 0x27, 0x06, 0x03, 0xC0, + 0x04, 0x38, 0xC5, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x31, 0x8D, 0x27, 0x06, + 0x03, 0xC0, 0x04, 0x2A, 0xC3, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x23, 0x77, + 0x27, 0x06, 0x03, 0xC0, 0x04, 0x1C, 0x82, 0x27, 0x06, 0x03, 0xC0, 0x04, + 0x15, 0x6C, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x0E, 0xC4, 0x27, 0x06, 0x03, + 0xC0, 0x04, 0x07, 0x02, 0x0A, 0x06, 0x02, 0x48, 0x29, 0xC0, 0x76, 0x76, + 0x04, 0xFE, 0x62, 0x76, 0x76, 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02, + 0x55, 0x29, 0x25, 0x76, 0x39, 0x02, 0x00, 0x06, 0x08, 0x02, 0x03, 0x3B, + 0x2F, 0x05, 0x02, 0x44, 0x29, 0x02, 0x00, 0x06, 0x01, 0x17, 0x02, 0x00, + 0x02, 0x09, 0x2F, 0x05, 0x02, 0x50, 0x29, 0xB0, 0x73, 0xAA, 0x9B, 0x06, + 0x80, 0x77, 0xBA, 0x27, 0x06, 0x07, 0x01, 0x02, 0x59, 0x87, 0x04, 0x80, + 0x5E, 0xBB, 0x27, 0x06, 0x07, 0x01, 0x03, 0x59, 0x88, 0x04, 0x80, 0x53, + 0xBC, 0x27, 0x06, 0x07, 0x01, 0x04, 0x59, 0x89, 0x04, 0x80, 0x48, 0xBD, + 0x27, 0x06, 0x06, 0x01, 0x05, 0x59, 0x8A, 0x04, 0x3E, 0xBE, 0x27, 0x06, + 0x06, 0x01, 0x06, 0x59, 0x8B, 0x04, 0x34, 0x7C, 0x27, 0x06, 0x06, 0x01, + 0x02, 0x58, 0x87, 0x04, 0x2A, 0x7D, 0x27, 0x06, 0x06, 0x01, 0x03, 0x58, + 0x88, 0x04, 0x20, 0x7E, 0x27, 0x06, 0x06, 0x01, 0x04, 0x58, 0x89, 0x04, + 0x16, 0x7F, 0x27, 0x06, 0x06, 0x01, 0x05, 0x58, 0x8A, 0x04, 0x0C, 0x80, + 0x27, 0x06, 0x06, 0x01, 0x06, 0x58, 0x8B, 0x04, 0x02, 0x56, 0x29, 0x5D, + 0x34, 0x5F, 0x36, 0x1C, 0x26, 0x05, 0x02, 0x56, 0x29, 0x5C, 0x36, 0x04, + 0x02, 0x56, 0x29, 0xBF, 0xA1, 0x26, 0x01, T0_INT2(BR_X509_BUFSIZE_SIG), + 0x12, 0x06, 0x02, 0x4F, 0x29, 0x26, 0x5E, 0x34, 0x5B, 0xA2, 0x76, 0x76, + 0x01, 0x00, 0x5A, 0x35, 0x18, 0x00, 0x00, 0x01, 0x30, 0x0A, 0x26, 0x01, + 0x00, 0x01, 0x09, 0x6F, 0x05, 0x02, 0x47, 0x29, 0x00, 0x00, 0x30, 0x30, + 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, 0x01, 0x7B, 0x01, 0x01, 0x11, 0x3A, 0x01, 0x83, 0xFD, 0x7F, + 0x11, 0x15, 0x06, 0x03, 0x3A, 0x25, 0x00, 0x3A, 0x26, 0x03, 0x00, 0x26, + 0xC6, 0x05, 0x04, 0x41, 0x01, 0x00, 0x00, 0x26, 0x01, 0x81, 0x00, 0x0D, + 0x06, 0x04, 0x93, 0x04, 0x80, 0x49, 0x26, 0x01, 0x90, 0x00, 0x0D, 0x06, + 0x0F, 0x01, 0x06, 0x14, 0x01, 0x81, 0x40, 0x2F, 0x93, 0x02, 0x00, 0x01, + 0x00, 0x94, 0x04, 0x33, 0x26, 0x01, 0x83, 0xFF, 0x7F, 0x0D, 0x06, 0x14, + 0x01, 0x0C, 0x14, 0x01, 0x81, 0x60, 0x2F, 0x93, 0x02, 0x00, 0x01, 0x06, + 0x94, 0x02, 0x00, 0x01, 0x00, 0x94, 0x04, 0x17, 0x01, 0x12, 0x14, 0x01, + 0x81, 0x70, 0x2F, 0x93, 0x02, 0x00, 0x01, 0x0C, 0x94, 0x02, 0x00, 0x01, + 0x06, 0x94, 0x02, 0x00, 0x01, 0x00, 0x94, 0x00, 0x00, 0x01, 0x82, 0x15, + 0x00, 0x00, 0x26, 0x01, 0x83, 0xB0, 0x00, 0x01, 0x83, 0xB7, 0x7F, 0x6F, + 0x00, 0x00, 0x01, 0x81, 0x34, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, + 0x01, 0x81, 0x78, 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, 0x30, 0x11, 0x06, 0x04, 0x41, 0xAA, 0xBF, + 0xB1, 0x00, 0x00, 0x01, 0x82, 0x09, 0x00, 0x00, 0x01, 0x81, 0x6C, 0x00, + 0x00, 0x26, 0x01, 0x83, 0xB8, 0x00, 0x01, 0x83, 0xBF, 0x7F, 0x6F, 0x00, + 0x00, 0x01, 0x30, 0x61, 0x36, 0x01, 0x7F, 0x79, 0x1A, 0x01, 0x00, 0x79, + 0x1A, 0x04, 0x7A, 0x00, 0x01, 0x81, 0x38, 0x00, 0x01, 0x7B, 0x0D, 0x06, + 0x02, 0x4E, 0x29, 0x26, 0x03, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, 0x30, + 0x26, 0x3E, 0x3A, 0x01, 0x82, 0x00, 0x13, 0x2F, 0x06, 0x04, 0x41, 0x01, + 0x00, 0x00, 0x30, 0x66, 0x09, 0x36, 0x3F, 0x00, 0x00, 0x14, 0x01, 0x3F, + 0x15, 0x01, 0x81, 0x00, 0x2F, 0x93, 0x00, 0x02, 0x01, 0x00, 0x03, 0x00, + 0xAC, 0x26, 0x06, 0x80, 0x59, 0xB0, 0x01, 0x20, 0x30, 0x11, 0x06, 0x17, + 0x25, 0x71, 0xAA, 0x9B, 0x25, 0x01, 0x7F, 0x2E, 0x03, 0x01, 0xB0, 0x01, + 0x20, 0x74, 0xAA, 0xAF, 0x02, 0x01, 0x20, 0x76, 0x76, 0x04, 0x38, 0x01, + 0x21, 0x30, 0x11, 0x06, 0x08, 0x25, 0x72, 0xB3, 0x01, 0x01, 0x1F, 0x04, + 0x2A, 0x01, 0x22, 0x30, 0x11, 0x06, 0x11, 0x25, 0x72, 0xB3, 0x26, 0x06, + 0x06, 0x2C, 0x02, 0x00, 0x2F, 0x03, 0x00, 0x01, 0x02, 0x1F, 0x04, 0x13, + 0x01, 0x26, 0x30, 0x11, 0x06, 0x08, 0x25, 0x72, 0xB3, 0x01, 0x06, 0x1F, + 0x04, 0x05, 0x41, 0xAB, 0x01, 0x00, 0x25, 0x04, 0xFF, 0x23, 0x76, 0x02, + 0x00, 0x00, 0x00, 0xAC, 0xB1, 0x26, 0x01, 0x01, 0x11, 0x06, 0x08, 0xA3, + 0x05, 0x02, 0x50, 0x29, 0xB1, 0x04, 0x02, 0x50, 0x29, 0x26, 0x01, 0x02, + 0x11, 0x06, 0x0C, 0x25, 0x72, 0xAD, 0x65, 0x2B, 0x40, 0x0D, 0x06, 0x02, + 0x50, 0x29, 0xB1, 0x01, 0x7F, 0x10, 0x06, 0x02, 0x55, 0x29, 0x25, 0x76, + 0x00, 0x00, 0xAC, 0x26, 0x06, 0x1A, 0xAC, 0x9B, 0x25, 0x26, 0x06, 0x11, + 0xAC, 0x26, 0x06, 0x0C, 0xAC, 0x9B, 0x25, 0x86, 0x27, 0x05, 0x02, 0x48, + 0x29, 0xBF, 0x04, 0x71, 0x76, 0x76, 0x04, 0x63, 0x76, 0x00, 0x02, 0x03, + 0x00, 0xB0, 0x01, 0x03, 0x75, 0xAA, 0xB7, 0x03, 0x01, 0x02, 0x01, 0x01, + 0x07, 0x12, 0x06, 0x02, 0x55, 0x29, 0x26, 0x01, 0x00, 0x30, 0x11, 0x06, + 0x05, 0x25, 0x4C, 0x29, 0x04, 0x15, 0x01, 0x01, 0x30, 0x11, 0x06, 0x0A, + 0x25, 0xB7, 0x02, 0x01, 0x14, 0x02, 0x01, 0x0E, 0x04, 0x05, 0x25, 0xB7, + 0x01, 0x00, 0x25, 0x02, 0x00, 0x06, 0x19, 0x01, 0x00, 0x30, 0x01, 0x38, + 0x15, 0x06, 0x03, 0x01, 0x10, 0x2F, 0x3A, 0x01, 0x81, 0x40, 0x15, 0x06, + 0x03, 0x01, 0x20, 0x2F, 0x61, 0x36, 0x04, 0x07, 0x01, 0x04, 0x15, 0x05, + 0x02, 0x4C, 0x29, 0xBF, 0x00, 0x00, 0x37, 0xAC, 0xBF, 0x1B, 0x00, 0x03, + 0x01, 0x00, 0x03, 0x00, 0x37, 0xAC, 0x26, 0x06, 0x30, 0xB0, 0x01, 0x11, + 0x74, 0xAA, 0x26, 0x05, 0x02, 0x43, 0x29, 0x26, 0x06, 0x20, 0xAC, 0x9B, + 0x25, 0x84, 0x27, 0x03, 0x01, 0x01, 0x00, 0x2E, 0x03, 0x02, 0xAF, 0x26, + 0x02, 0x01, 0x15, 0x06, 0x07, 0x2C, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, + 0x02, 0x02, 0x20, 0x76, 0x04, 0x5D, 0x76, 0x04, 0x4D, 0x76, 0x1B, 0x02, + 0x00, 0x00, 0x00, 0xB0, 0x01, 0x06, 0x75, 0xAE, 0x00, 0x00, 0xB5, 0x83, + 0x06, 0x0E, 0x3A, 0x26, 0x05, 0x06, 0x41, 0x01, 0x00, 0x01, 0x00, 0x00, + 0xB5, 0x6B, 0x04, 0x08, 0x8F, 0x06, 0x05, 0x25, 0x01, 0x00, 0x04, 0x00, + 0x00, 0x00, 0xB6, 0x83, 0x06, 0x0E, 0x3A, 0x26, 0x05, 0x06, 0x41, 0x01, + 0x00, 0x01, 0x00, 0x00, 0xB6, 0x6B, 0x04, 0x08, 0x8F, 0x06, 0x05, 0x25, + 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB7, 0x26, 0x01, 0x81, 0x00, 0x0D, + 0x06, 0x04, 0x00, 0x04, 0x80, 0x55, 0x26, 0x01, 0x81, 0x40, 0x0D, 0x06, + 0x07, 0x25, 0x01, 0x00, 0x00, 0x04, 0x80, 0x47, 0x26, 0x01, 0x81, 0x60, + 0x0D, 0x06, 0x0E, 0x01, 0x1F, 0x15, 0x01, 0x01, 0xA0, 0x01, 0x81, 0x00, + 0x01, 0x8F, 0x7F, 0x04, 0x32, 0x26, 0x01, 0x81, 0x70, 0x0D, 0x06, 0x0F, + 0x01, 0x0F, 0x15, 0x01, 0x02, 0xA0, 0x01, 0x90, 0x00, 0x01, 0x83, 0xFF, + 0x7F, 0x04, 0x1C, 0x26, 0x01, 0x81, 0x78, 0x0D, 0x06, 0x11, 0x01, 0x07, + 0x15, 0x01, 0x03, 0xA0, 0x01, 0x84, 0x80, 0x00, 0x01, 0x80, 0xC3, 0xFF, + 0x7F, 0x04, 0x04, 0x25, 0x01, 0x00, 0x00, 0x6F, 0x05, 0x03, 0x25, 0x01, + 0x00, 0x00, 0x00, 0x3A, 0x26, 0x05, 0x06, 0x41, 0x01, 0x00, 0x01, 0x7F, + 0x00, 0xB7, 0x33, 0x26, 0x3C, 0x06, 0x03, 0x3A, 0x25, 0x00, 0x01, 0x06, + 0x0E, 0x3A, 0x26, 0x01, 0x06, 0x14, 0x01, 0x02, 0x10, 0x06, 0x04, 0x41, + 0x01, 0x7F, 0x00, 0x01, 0x3F, 0x15, 0x09, 0x00, 0x00, 0x26, 0x06, 0x06, + 0x0B, 0x9F, 0x33, 0x40, 0x04, 0x77, 0x25, 0x26, 0x00, 0x00, 0xB0, 0x01, + 0x03, 0x75, 0xAA, 0xB7, 0x06, 0x02, 0x54, 0x29, 0x00, 0x00, 0x3A, 0x26, + 0x06, 0x07, 0x31, 0x26, 0x06, 0x01, 0x1A, 0x04, 0x76, 0x41, 0x00, 0x00, + 0x01, 0x01, 0x75, 0xA9, 0x01, 0x01, 0x10, 0x06, 0x02, 0x42, 0x29, 0xB7, + 0x3D, 0x00, 0x04, 0xB0, 0x26, 0x01, 0x17, 0x01, 0x18, 0x6F, 0x05, 0x02, + 0x47, 0x29, 0x01, 0x18, 0x11, 0x03, 0x00, 0x72, 0xAA, 0xA5, 0x02, 0x00, + 0x06, 0x0C, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01, 0xA5, 0x02, 0x01, 0x09, + 0x04, 0x0E, 0x26, 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, 0xA6, 0x40, 0x01, 0x01, 0x0E, 0x02, 0x01, 0x01, 0x04, 0x07, 0x3E, + 0x02, 0x01, 0x01, 0x80, 0x64, 0x07, 0x3D, 0x02, 0x01, 0x01, 0x83, 0x10, + 0x07, 0x3E, 0x2F, 0x15, 0x06, 0x03, 0x01, 0x18, 0x09, 0x91, 0x09, 0x78, + 0x26, 0x01, 0x05, 0x14, 0x02, 0x03, 0x09, 0x03, 0x03, 0x01, 0x1F, 0x15, + 0x01, 0x01, 0x3A, 0xA6, 0x02, 0x03, 0x09, 0x40, 0x03, 0x03, 0x01, 0x00, + 0x01, 0x17, 0xA6, 0x01, 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, 0x00, 0x01, + 0x3B, 0xA6, 0x01, 0x3C, 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, + 0x01, 0x3C, 0xA6, 0x02, 0x02, 0x09, 0x03, 0x02, 0xB7, 0x26, 0x01, 0x2E, + 0x11, 0x06, 0x0D, 0x25, 0xB7, 0x26, 0x01, 0x30, 0x01, 0x39, 0x6F, 0x06, + 0x03, 0x25, 0x04, 0x74, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x47, 0x29, + 0x76, 0x02, 0x03, 0x02, 0x02, 0x00, 0x01, 0xB7, 0x7A, 0x01, 0x0A, 0x08, + 0x03, 0x00, 0xB7, 0x7A, 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, 0x00, 0x03, + 0x01, 0xA5, 0x26, 0x02, 0x01, 0x02, 0x00, 0x6F, 0x05, 0x02, 0x47, 0x29, + 0x00, 0x00, 0x33, 0xB0, 0x01, 0x02, 0x75, 0x0B, 0xA8, 0x00, 0x03, 0x26, + 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0xAA, 0xB7, 0x26, 0x01, 0x81, 0x00, + 0x13, 0x06, 0x02, 0x53, 0x29, 0x26, 0x01, 0x00, 0x11, 0x06, 0x0B, 0x25, + 0x26, 0x05, 0x04, 0x25, 0x01, 0x00, 0x00, 0xB7, 0x04, 0x6F, 0x02, 0x01, + 0x26, 0x05, 0x02, 0x4F, 0x29, 0x40, 0x03, 0x01, 0x02, 0x02, 0x36, 0x02, + 0x02, 0x3F, 0x03, 0x02, 0x26, 0x06, 0x03, 0xB7, 0x04, 0x68, 0x25, 0x02, + 0x00, 0x02, 0x01, 0x0A, 0x00, 0x01, 0xB7, 0x26, 0x01, 0x81, 0x00, 0x0D, + 0x06, 0x01, 0x00, 0x01, 0x81, 0x00, 0x0A, 0x26, 0x05, 0x02, 0x4D, 0x29, + 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x19, 0x02, + 0x00, 0x40, 0x03, 0x00, 0x26, 0x01, 0x83, 0xFF, 0xFF, 0x7F, 0x12, 0x06, + 0x02, 0x4E, 0x29, 0x01, 0x08, 0x0E, 0x3A, 0xB7, 0x33, 0x09, 0x04, 0x60, + 0x00, 0x00, 0xA9, 0x92, 0x00, 0x00, 0xAA, 0xBF, 0x00, 0x00, 0xB0, 0x73, + 0xAA, 0x00, 0x01, 0xAA, 0x26, 0x05, 0x02, 0x53, 0x29, 0xB7, 0x26, 0x01, + 0x81, 0x00, 0x13, 0x06, 0x02, 0x53, 0x29, 0x03, 0x00, 0x26, 0x06, 0x16, + 0xB7, 0x02, 0x00, 0x26, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, + 0x53, 0x29, 0x01, 0x08, 0x0E, 0x09, 0x03, 0x00, 0x04, 0x67, 0x25, 0x02, + 0x00, 0x00, 0x00, 0xAA, 0x26, 0x01, 0x81, 0x7F, 0x12, 0x06, 0x08, 0xBF, + 0x01, 0x00, 0x66, 0x36, 0x01, 0x00, 0x00, 0x26, 0x66, 0x36, 0x66, 0x3F, + 0xA2, 0x01, 0x7F, 0x00, 0x00, 0xB0, 0x01, 0x0C, 0x30, 0x11, 0x06, 0x05, + 0x25, 0x72, 0xB3, 0x04, 0x3E, 0x01, 0x12, 0x30, 0x11, 0x06, 0x05, 0x25, + 0x72, 0xB4, 0x04, 0x33, 0x01, 0x13, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, + 0xB4, 0x04, 0x28, 0x01, 0x14, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB4, + 0x04, 0x1D, 0x01, 0x16, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB4, 0x04, + 0x12, 0x01, 0x1E, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB2, 0x04, 0x07, + 0x41, 0xAB, 0x01, 0x00, 0x01, 0x00, 0x25, 0x00, 0x01, 0xB7, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x05, 0x14, 0x01, 0x01, 0x15, 0x2D, 0x02, 0x00, 0x01, + 0x06, 0x14, 0x26, 0x01, 0x01, 0x15, 0x06, 0x02, 0x45, 0x29, 0x01, 0x04, + 0x0E, 0x02, 0x00, 0x01, 0x1F, 0x15, 0x26, 0x01, 0x1F, 0x11, 0x06, 0x02, + 0x46, 0x29, 0x09, 0x00, 0x00, 0x26, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, + 0x00, 0xB0, 0x00, 0x01, 0xAA, 0x26, 0x05, 0x05, 0x66, 0x36, 0x01, 0x7F, + 0x00, 0x01, 0x01, 0x03, 0x00, 0x9C, 0x26, 0x01, 0x83, 0xFF, 0x7E, 0x11, + 0x06, 0x16, 0x25, 0x26, 0x06, 0x10, 0x9D, 0x26, 0x05, 0x05, 0x25, 0xBF, + 0x01, 0x00, 0x00, 0x02, 0x00, 0x81, 0x03, 0x00, 0x04, 0x6D, 0x04, 0x1B, + 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, 0x00, 0x02, 0x00, 0x81, 0x03, + 0x00, 0x26, 0x06, 0x0B, 0x9C, 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, + 0x00, 0x04, 0x6D, 0x25, 0x02, 0x00, 0x26, 0x05, 0x01, 0x00, 0x40, 0x66, + 0x36, 0x01, 0x7F, 0x00, 0x01, 0xAA, 0x01, 0x01, 0x03, 0x00, 0x26, 0x06, + 0x10, 0x9E, 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, 0x00, 0x02, 0x00, + 0x81, 0x03, 0x00, 0x04, 0x6D, 0x25, 0x02, 0x00, 0x26, 0x05, 0x01, 0x00, + 0x40, 0x66, 0x36, 0x01, 0x7F, 0x00, 0x01, 0xAA, 0x01, 0x01, 0x03, 0x00, + 0x26, 0x06, 0x10, 0xB7, 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, 0x00, + 0x02, 0x00, 0x81, 0x03, 0x00, 0x04, 0x6D, 0x25, 0x02, 0x00, 0x26, 0x05, + 0x01, 0x00, 0x40, 0x66, 0x36, 0x01, 0x7F, 0x00, 0x00, 0xB7, 0x01, 0x08, + 0x0E, 0x3A, 0xB7, 0x33, 0x09, 0x00, 0x00, 0xB7, 0x3A, 0xB7, 0x01, 0x08, + 0x0E, 0x33, 0x09, 0x00, 0x00, 0x26, 0x05, 0x02, 0x4E, 0x29, 0x40, 0xB8, + 0x00, 0x00, 0x32, 0x26, 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x25, 0x1A, + 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, 0xC0, 0x25, 0x00, 0x00, 0x26, 0x06, 0x07, 0xC1, 0x26, + 0x06, 0x01, 0x1A, 0x04, 0x76, 0x00, 0x00, 0x01, 0x00, 0x30, 0x31, 0x0B, + 0x41, 0x00, 0x00, 0x01, 0x81, 0x70, 0x00, 0x00, 0x01, 0x82, 0x0D, 0x00, + 0x00, 0x01, 0x82, 0x22, 0x00, 0x00, 0x01, 0x82, 0x05, 0x00, 0x00, 0x26, + 0x01, 0x83, 0xFB, 0x50, 0x01, 0x83, 0xFB, 0x6F, 0x6F, 0x06, 0x04, 0x25, + 0x01, 0x00, 0x00, 0x26, 0x01, 0x83, 0xB0, 0x00, 0x01, 0x83, 0xBF, 0x7F, + 0x6F, 0x06, 0x04, 0x25, 0x01, 0x00, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x15, + 0x01, 0x83, 0xFF, 0x7E, 0x0D, 0x00 +}; + +static const uint16_t t0_caddr[] = { + 0, + 5, + 10, + 15, + 20, + 25, + 29, + 33, + 37, + 41, + 45, + 49, + 53, + 57, + 61, + 65, + 69, + 73, + 77, + 81, + 85, + 89, + 93, + 97, + 101, + 105, + 109, + 113, + 117, + 121, + 125, + 130, + 135, + 140, + 145, + 150, + 155, + 160, + 165, + 173, + 178, + 183, + 188, + 193, + 198, + 203, + 208, + 213, + 234, + 239, + 244, + 249, + 264, + 269, + 275, + 281, + 286, + 294, + 302, + 308, + 313, + 324, + 960, + 975, + 979, + 984, + 989, + 994, + 999, + 1004, + 1118, + 1123, + 1135, + 1140, + 1145, + 1150, + 1154, + 1159, + 1164, + 1169, + 1174, + 1184, + 1189, + 1194, + 1206, + 1221, + 1226, + 1240, + 1262, + 1273, + 1376, + 1423, + 1456, + 1547, + 1553, + 1616, + 1623, + 1651, + 1679, + 1784, + 1826, + 1839, + 1851, + 1865, + 1880, + 2100, + 2114, + 2131, + 2140, + 2207, + 2263, + 2267, + 2271, + 2276, + 2324, + 2350, + 2426, + 2470, + 2481, + 2566, + 2604, + 2642, + 2652, + 2662, + 2671, + 2684, + 2688, + 2692, + 2696, + 2700, + 2704, + 2708, + 2712, + 2724, + 2732, + 2737, + 2742, + 2747, + 2752 +}; + +#define T0_INTERPRETED 60 + +#define T0_ENTER(ip, rp, slot) do { \ + const unsigned char *t0_newip; \ + uint32_t t0_lnum; \ + t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ + t0_lnum = t0_parse7E_unsigned(&t0_newip); \ + (rp) += t0_lnum; \ + *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ + (ip) = t0_newip; \ + } while (0) + +#define T0_DEFENTRY(name, slot) \ +void \ +name(void *ctx) \ +{ \ + t0_context *t0ctx = ctx; \ + t0ctx->ip = &t0_codeblock[0]; \ + T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ +} + +T0_DEFENTRY(br_x509_minimal_init_main, 144) + +#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) + +void +br_x509_minimal_run(void *t0ctx) +{ + uint32_t *dp, *rp; + const unsigned char *ip; + +#define T0_LOCAL(x) (*(rp - 2 - (x))) +#define T0_POP() (*-- dp) +#define T0_POPi() (*(int32_t *)(-- dp)) +#define T0_PEEK(x) (*(dp - 1 - (x))) +#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) +#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) +#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) +#define T0_RPOP() (*-- rp) +#define T0_RPOPi() (*(int32_t *)(-- rp)) +#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) +#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) +#define T0_ROLL(x) do { \ + size_t t0len = (size_t)(x); \ + uint32_t t0tmp = *(dp - 1 - t0len); \ + memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_SWAP() do { \ + uint32_t t0tmp = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_ROT() do { \ + uint32_t t0tmp = *(dp - 3); \ + *(dp - 3) = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_NROT() do { \ + uint32_t t0tmp = *(dp - 1); \ + *(dp - 1) = *(dp - 2); \ + *(dp - 2) = *(dp - 3); \ + *(dp - 3) = t0tmp; \ +} while (0) +#define T0_PICK(x) do { \ + uint32_t t0depth = (x); \ + T0_PUSH(T0_PEEK(t0depth)); \ +} while (0) +#define T0_CO() do { \ + goto t0_exit; \ +} while (0) +#define T0_RET() goto t0_next + + dp = ((t0_context *)t0ctx)->dp; + rp = ((t0_context *)t0ctx)->rp; + ip = ((t0_context *)t0ctx)->ip; + goto t0_next; + for (;;) { + uint32_t t0x; + + t0_next: + t0x = T0_NEXT(&ip); + if (t0x < T0_INTERPRETED) { + switch (t0x) { + int32_t t0off; + + case 0: /* ret */ + t0x = T0_RPOP(); + rp -= (t0x >> 16); + t0x &= 0xFFFF; + if (t0x == 0) { + ip = NULL; + goto t0_exit; + } + ip = &t0_codeblock[t0x]; + break; + case 1: /* literal constant */ + T0_PUSHi(t0_parse7E_signed(&ip)); + break; + case 2: /* read local */ + T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); + break; + case 3: /* write local */ + T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); + break; + case 4: /* jump */ + t0off = t0_parse7E_signed(&ip); + ip += t0off; + break; + case 5: /* jump if */ + t0off = t0_parse7E_signed(&ip); + if (T0_POP()) { + ip += t0off; + } + break; + case 6: /* jump if not */ + t0off = t0_parse7E_signed(&ip); + if (!T0_POP()) { + ip += t0off; + } + break; + case 7: { + /* %25 */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSHi(a % b); + + } + break; + case 8: { + /* * */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a * b); + + } + break; + case 9: { + /* + */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a + b); + + } + break; + case 10: { + /* - */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a - b); + + } + break; + case 11: { + /* -rot */ + T0_NROT(); + } + break; + case 12: { + /* / */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSHi(a / b); + + } + break; + case 13: { + /* < */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a < b)); + + } + break; + case 14: { + /* << */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x << c); + + } + break; + case 15: { + /* <= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a <= b)); + + } + break; + case 16: { + /* <> */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a != b)); + + } + break; + case 17: { + /* = */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a == b)); + + } + break; + case 18: { + /* > */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a > b)); + + } + break; + case 19: { + /* >= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a >= b)); + + } + break; + case 20: { + /* >> */ + + int c = (int)T0_POPi(); + int32_t x = T0_POPi(); + T0_PUSHi(x >> c); + + } + break; + case 21: { + /* and */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a & b); + + } + break; + case 22: { + /* blobcopy */ + + size_t len = T0_POP(); + unsigned char *src = (unsigned char *)CTX + T0_POP(); + unsigned char *dst = (unsigned char *)CTX + T0_POP(); + memcpy(dst, src, len); + + } + break; + case 23: { + /* check-direct-trust */ + + size_t u; + + for (u = 0; u < CTX->trust_anchors_num; u ++) { + const br_x509_trust_anchor *ta; + unsigned char hashed_DN[64]; + int kt; + + ta = &CTX->trust_anchors[u]; + if (ta->flags & BR_X509_TA_CA) { + continue; + } + hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); + if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) { + continue; + } + kt = CTX->pkey.key_type; + if ((ta->pkey.key_type & 0x0F) != kt) { + continue; + } + switch (kt) { + + case BR_KEYTYPE_RSA: + if (!eqbigint(CTX->pkey.key.rsa.n, + CTX->pkey.key.rsa.nlen, + ta->pkey.key.rsa.n, + ta->pkey.key.rsa.nlen) + || !eqbigint(CTX->pkey.key.rsa.e, + CTX->pkey.key.rsa.elen, + ta->pkey.key.rsa.e, + ta->pkey.key.rsa.elen)) + { + continue; + } + break; + + case BR_KEYTYPE_EC: + if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve + || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen + || memcmp(CTX->pkey.key.ec.q, + ta->pkey.key.ec.q, + ta->pkey.key.ec.qlen) != 0) + { + continue; + } + break; + + default: + continue; + } + + /* + * Direct trust match! + */ + CTX->err = BR_ERR_X509_OK; + T0_CO(); + } + + } + break; + case 24: { + /* check-trust-anchor-CA */ + + size_t u; + + for (u = 0; u < CTX->trust_anchors_num; u ++) { + const br_x509_trust_anchor *ta; + unsigned char hashed_DN[64]; + + ta = &CTX->trust_anchors[u]; + if (!(ta->flags & BR_X509_TA_CA)) { + continue; + } + hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); + if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) { + continue; + } + if (verify_signature(CTX, &ta->pkey) == 0) { + CTX->err = BR_ERR_X509_OK; + T0_CO(); + } + } + + } + break; + case 25: { + /* check-validity-range */ + + uint32_t nbs = T0_POP(); + uint32_t nbd = T0_POP(); + uint32_t nas = T0_POP(); + uint32_t nad = T0_POP(); + int r; + if (CTX->itime != 0) { + r = CTX->itime(CTX->itime_ctx, nbd, nbs, nad, nas); + if (r < -1 || r > 1) { + CTX->err = BR_ERR_X509_TIME_UNKNOWN; + T0_CO(); + } + } else { + uint32_t vd = CTX->days; + uint32_t vs = CTX->seconds; + if (vd == 0 && vs == 0) { +#if BR_USE_UNIX_TIME + time_t x = time(NULL); + + vd = (uint32_t)(x / 86400) + 719528; + vs = (uint32_t)(x % 86400); +#elif BR_USE_WIN32_TIME + uint64_t x; +#ifdef _XBOX + /* + * Xbox uses KeQuerySystemTime from the kernel. + * This returns time in 100-nanosecond intervals + * since January 1, 1601 (same as FILETIME). + */ + LARGE_INTEGER system_time; + KeQuerySystemTime(&system_time); + x = (uint64_t)system_time.QuadPart; +#else + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + x = ((uint64_t)ft.dwHighDateTime << 32) + + (uint64_t)ft.dwLowDateTime; +#endif + x = (x / 10000000); + vd = (uint32_t)(x / 86400) + 584754; + vs = (uint32_t)(x % 86400); +#else + CTX->err = BR_ERR_X509_TIME_UNKNOWN; + T0_CO(); +#endif + } + if (vd < nbd || (vd == nbd && vs < nbs)) { + r = -1; + } else if (vd > nad || (vd == nad && vs > nas)) { + r = 1; + } else { + r = 0; + } + } + T0_PUSHi(r); + + } + break; + case 26: { + /* co */ + T0_CO(); + } + break; + case 27: { + /* compute-dn-hash */ + + CTX->dn_hash_impl->out(&CTX->dn_hash.vtable, CTX->current_dn_hash); + CTX->do_dn_hash = 0; + + } + break; + case 28: { + /* compute-tbs-hash */ + + int id = T0_POPi(); + size_t len; + len = br_multihash_out(&CTX->mhash, id, CTX->tbs_hash); + T0_PUSH(len); + + } + break; + case 29: { + /* copy-ee-ec-pkey */ + + size_t qlen = T0_POP(); + uint32_t curve = T0_POP(); + memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen); + CTX->pkey.key_type = BR_KEYTYPE_EC; + CTX->pkey.key.ec.curve = curve; + CTX->pkey.key.ec.q = CTX->ee_pkey_data; + CTX->pkey.key.ec.qlen = qlen; + + } + break; + case 30: { + /* copy-ee-rsa-pkey */ + + size_t elen = T0_POP(); + size_t nlen = T0_POP(); + memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen); + CTX->pkey.key_type = BR_KEYTYPE_RSA; + CTX->pkey.key.rsa.n = CTX->ee_pkey_data; + CTX->pkey.key.rsa.nlen = nlen; + CTX->pkey.key.rsa.e = CTX->ee_pkey_data + nlen; + CTX->pkey.key.rsa.elen = elen; + + } + break; + case 31: { + /* copy-name-SAN */ + + unsigned tag = T0_POP(); + unsigned ok = T0_POP(); + size_t u, len; + + len = CTX->pad[0]; + for (u = 0; u < CTX->num_name_elts; u ++) { + br_name_element *ne; + + ne = &CTX->name_elts[u]; + if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) { + if (ok && ne->len > len) { + memcpy(ne->buf, CTX->pad + 1, len); + ne->buf[len] = 0; + ne->status = 1; + } else { + ne->status = -1; + } + break; + } + } + + } + break; + case 32: { + /* copy-name-element */ + + size_t len; + int32_t off = T0_POPi(); + int ok = T0_POPi(); + + if (off >= 0) { + br_name_element *ne = &CTX->name_elts[off]; + + if (ok) { + len = CTX->pad[0]; + if (len < ne->len) { + memcpy(ne->buf, CTX->pad + 1, len); + ne->buf[len] = 0; + ne->status = 1; + } else { + ne->status = -1; + } + } else { + ne->status = -1; + } + } + + } + break; + case 33: { + /* data-get8 */ + + size_t addr = T0_POP(); + T0_PUSH(t0_datablock[addr]); + + } + break; + case 34: { + /* dn-hash-length */ + + T0_PUSH(DNHASH_LEN); + + } + break; + case 35: { + /* do-ecdsa-vrfy */ + + size_t qlen = T0_POP(); + int curve = T0_POP(); + br_x509_pkey pk; + + pk.key_type = BR_KEYTYPE_EC; + pk.key.ec.curve = curve; + pk.key.ec.q = CTX->pkey_data; + pk.key.ec.qlen = qlen; + T0_PUSH(verify_signature(CTX, &pk)); + + } + break; + case 36: { + /* do-rsa-vrfy */ + + size_t elen = T0_POP(); + size_t nlen = T0_POP(); + br_x509_pkey pk; + + pk.key_type = BR_KEYTYPE_RSA; + pk.key.rsa.n = CTX->pkey_data; + pk.key.rsa.nlen = nlen; + pk.key.rsa.e = CTX->pkey_data + nlen; + pk.key.rsa.elen = elen; + T0_PUSH(verify_signature(CTX, &pk)); + + } + break; + case 37: { + /* drop */ + (void)T0_POP(); + } + break; + case 38: { + /* dup */ + T0_PUSH(T0_PEEK(0)); + } + break; + case 39: { + /* eqOID */ + + const unsigned char *a2 = &t0_datablock[T0_POP()]; + const unsigned char *a1 = &CTX->pad[0]; + size_t len = a1[0]; + int x; + if (len == a2[0]) { + x = -(memcmp(a1 + 1, a2 + 1, len) == 0); + } else { + x = 0; + } + T0_PUSH((uint32_t)x); + + } + break; + case 40: { + /* eqblob */ + + size_t len = T0_POP(); + const unsigned char *a2 = (const unsigned char *)CTX + T0_POP(); + const unsigned char *a1 = (const unsigned char *)CTX + T0_POP(); + T0_PUSHi(-(memcmp(a1, a2, len) == 0)); + + } + break; + case 41: { + /* fail */ + + CTX->err = T0_POPi(); + T0_CO(); + + } + break; + case 42: { + /* get16 */ + + uint32_t addr = T0_POP(); + T0_PUSH(*(uint16_t *)(void *)((unsigned char *)CTX + addr)); + + } + break; + case 43: { + /* get32 */ + + uint32_t addr = T0_POP(); + T0_PUSH(*(uint32_t *)(void *)((unsigned char *)CTX + addr)); + + } + break; + case 44: { + /* match-server-name */ + + size_t n1, n2; + + if (CTX->server_name == NULL) { + T0_PUSH(0); + T0_RET(); + } + n1 = strlen(CTX->server_name); + n2 = CTX->pad[0]; + if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) { + T0_PUSHi(-1); + T0_RET(); + } + if (n2 >= 2 && CTX->pad[1] == '*' && CTX->pad[2] == '.') { + size_t u; + + u = 0; + while (u < n1 && CTX->server_name[u] != '.') { + u ++; + } + u ++; + n1 -= u; + if ((n2 - 2) == n1 + && eqnocase(&CTX->pad[3], CTX->server_name + u, n1)) + { + T0_PUSHi(-1); + T0_RET(); + } + } + T0_PUSH(0); + + } + break; + case 45: { + /* neg */ + + uint32_t a = T0_POP(); + T0_PUSH(-a); + + } + break; + case 46: { + /* offset-name-element */ + + unsigned san = T0_POP(); + size_t u; + + for (u = 0; u < CTX->num_name_elts; u ++) { + if (CTX->name_elts[u].status == 0) { + const unsigned char *oid; + size_t len, off; + + oid = CTX->name_elts[u].oid; + if (san) { + if (oid[0] != 0 || oid[1] != 0) { + continue; + } + off = 2; + } else { + off = 0; + } + len = oid[off]; + if (len != 0 && len == CTX->pad[0] + && memcmp(oid + off + 1, + CTX->pad + 1, len) == 0) + { + T0_PUSH(u); + T0_RET(); + } + } + } + T0_PUSHi(-1); + + } + break; + case 47: { + /* or */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a | b); + + } + break; + case 48: { + /* over */ + T0_PUSH(T0_PEEK(1)); + } + break; + case 49: { + /* read-blob-inner */ + + uint32_t len = T0_POP(); + uint32_t addr = T0_POP(); + size_t clen = CTX->hlen; + if (clen > len) { + clen = (size_t)len; + } + if (addr != 0) { + memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); + } + if (CTX->do_mhash) { + br_multihash_update(&CTX->mhash, CTX->hbuf, clen); + } + if (CTX->do_dn_hash) { + CTX->dn_hash_impl->update( + &CTX->dn_hash.vtable, CTX->hbuf, clen); + } + CTX->hbuf += clen; + CTX->hlen -= clen; + T0_PUSH(addr + clen); + T0_PUSH(len - clen); + + } + break; + case 50: { + /* read8-low */ + + if (CTX->hlen == 0) { + T0_PUSHi(-1); + } else { + unsigned char x = *CTX->hbuf ++; + if (CTX->do_mhash) { + br_multihash_update(&CTX->mhash, &x, 1); + } + if (CTX->do_dn_hash) { + CTX->dn_hash_impl->update(&CTX->dn_hash.vtable, &x, 1); + } + CTX->hlen --; + T0_PUSH(x); + } + + } + break; + case 51: { + /* rot */ + T0_ROT(); + } + break; + case 52: { + /* set16 */ + + uint32_t addr = T0_POP(); + *(uint16_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); + + } + break; + case 53: { + /* set32 */ + + uint32_t addr = T0_POP(); + *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); + + } + break; + case 54: { + /* set8 */ + + uint32_t addr = T0_POP(); + *((unsigned char *)CTX + addr) = (unsigned char)T0_POP(); + + } + break; + case 55: { + /* start-dn-hash */ + + CTX->dn_hash_impl->init(&CTX->dn_hash.vtable); + CTX->do_dn_hash = 1; + + } + break; + case 56: { + /* start-tbs-hash */ + + br_multihash_init(&CTX->mhash); + CTX->do_mhash = 1; + + } + break; + case 57: { + /* stop-tbs-hash */ + + CTX->do_mhash = 0; + + } + break; + case 58: { + /* swap */ + T0_SWAP(); + } + break; + case 59: { + /* zero-server-name */ + + T0_PUSHi(-(CTX->server_name == NULL)); + + } + break; + } + + } else { + T0_ENTER(ip, rp, t0x); + } + } +t0_exit: + ((t0_context *)t0ctx)->dp = dp; + ((t0_context *)t0ctx)->rp = rp; + ((t0_context *)t0ctx)->ip = ip; +} + + + +/* + * Verify the signature on the certificate with the provided public key. + * This function checks the public key type with regards to the expected + * type. Returned value is either 0 on success, or a non-zero error code. + */ +static int +verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk) +{ + int kt; + + kt = ctx->cert_signer_key_type; + if ((pk->key_type & 0x0F) != kt) { + return BR_ERR_X509_WRONG_KEY_TYPE; + } + switch (kt) { + unsigned char tmp[64]; + + case BR_KEYTYPE_RSA: + if (ctx->irsa == 0) { + return BR_ERR_X509_UNSUPPORTED; + } + if (!ctx->irsa(ctx->cert_sig, ctx->cert_sig_len, + &t0_datablock[ctx->cert_sig_hash_oid], + ctx->cert_sig_hash_len, &pk->key.rsa, tmp)) + { + return BR_ERR_X509_BAD_SIGNATURE; + } + if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) { + return BR_ERR_X509_BAD_SIGNATURE; + } + return 0; + + case BR_KEYTYPE_EC: + if (ctx->iecdsa == 0) { + return BR_ERR_X509_UNSUPPORTED; + } + if (!ctx->iecdsa(ctx->iec, ctx->tbs_hash, + ctx->cert_sig_hash_len, &pk->key.ec, + ctx->cert_sig, ctx->cert_sig_len)) + { + return BR_ERR_X509_BAD_SIGNATURE; + } + return 0; + + default: + return BR_ERR_X509_UNSUPPORTED; + } +} + + diff --git a/BearSSL-OG/libbearssl/src/x509/x509_minimal.t0 b/BearSSL-OG/libbearssl/src/x509/x509_minimal.t0 new file mode 100644 index 0000000..80a3701 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/x509_minimal.t0 @@ -0,0 +1,1526 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +preamble { + +#include "inner.h" + +/* + * Implementation Notes + * -------------------- + * + * The C code pushes the data by chunks; all decoding is done in the + * T0 code. The cert_length value is set to the certificate length when + * a new certificate is started; the T0 code picks it up as outer limit, + * and decoding functions use it to ensure that no attempt is made at + * reading past it. The T0 code also checks that once the certificate is + * decoded, there are no trailing bytes. + * + * The T0 code sets cert_length to 0 when the certificate is fully + * decoded. + * + * The C code must still perform two checks: + * + * -- If the certificate length is 0, then the T0 code will not be + * invoked at all. This invalid condition must thus be reported by the + * C code. + * + * -- When reaching the end of certificate, the C code must verify that + * the certificate length has been set to 0, thereby signaling that + * the T0 code properly decoded a certificate. + * + * Processing of a chain works in the following way: + * + * -- The error flag is set to a non-zero value when validation is + * finished. The value is either BR_ERR_X509_OK (validation is + * successful) or another non-zero error code. When a non-zero error + * code is obtained, the remaining bytes in the current certificate and + * the subsequent certificates (if any) are completely ignored. + * + * -- Each certificate is decoded in due course, with the following + * "interesting points": + * + * -- Start of the TBS: the multihash engine is reset and activated. + * + * -- Start of the issuer DN: the secondary hash engine is started, + * to process the encoded issuer DN. + * + * -- End of the issuer DN: the secondary hash engine is stopped. The + * resulting hash value is computed and then copied into the + * next_dn_hash[] buffer. + * + * -- Start of the subject DN: the secondary hash engine is started, + * to process the encoded subject DN. + * + * -- For the EE certificate only: the Common Name, if any, is matched + * against the expected server name. + * + * -- End of the subject DN: the secondary hash engine is stopped. The + * resulting hash value is computed into the pad. It is then processed: + * + * -- If this is the EE certificate, then the hash is ignored + * (except for direct trust processing, see later; the hash is + * simply left in current_dn_hash[]). + * + * -- Otherwise, the hashed subject DN is compared with the saved + * hash value (in saved_dn_hash[]). They must match. + * + * Either way, the next_dn_hash[] value is then copied into the + * saved_dn_hash[] value. Thus, at that point, saved_dn_hash[] + * contains the hash of the issuer DN for the current certificate, + * and current_dn_hash[] contains the hash of the subject DN for the + * current certificate. + * + * -- Public key: it is decoded into the cert_pkey[] buffer. Unknown + * key types are reported at that point. + * + * -- If this is the EE certificate, then the key type is compared + * with the expected key type (initialization parameter). The public + * key data is copied to ee_pkey_data[]. The key and hashed subject + * DN are also compared with the "direct trust" keys; if the key + * and DN are matched, then validation ends with a success. + * + * -- Otherwise, the saved signature (cert_sig[]) is verified + * against the saved TBS hash (tbs_hash[]) and that freshly + * decoded public key. Failure here ends validation with an error. + * + * -- Extensions: extension values are processed in due order. + * + * -- Basic Constraints: for all certificates except EE, must be + * present, indicate a CA, and have a path length compatible with + * the chain length so far. + * + * -- Key Usage: for the EE, if present, must allow signatures + * or encryption/key exchange, as required for the cipher suite. + * For non-EE, if present, must have the "certificate sign" bit. + * + * -- Subject Alt Name: for the EE, dNSName names are matched + * against the server name. Ignored for non-EE. + * + * -- Authority Key Identifier, Subject Key Identifier, Issuer + * Alt Name, Subject Directory Attributes, CRL Distribution Points + * Freshest CRL, Authority Info Access and Subject Info Access + * extensions are always ignored: they either contain only + * informative data, or they relate to revocation processing, which + * we explicitly do not support. + * + * -- All other extensions are ignored if non-critical. If a + * critical extension other than the ones above is encountered, + * then a failure is reported. + * + * -- End of the TBS: the multihash engine is stopped. + * + * -- Signature algorithm: the signature algorithm on the + * certificate is decoded. A failure is reported if that algorithm + * is unknown. The hashed TBS corresponding to the signature hash + * function is computed and stored in tbs_hash[] (if not supported, + * then a failure is reported). The hash OID and length are stored + * in cert_sig_hash_oid and cert_sig_hash_len. + * + * -- Signature value: the signature value is copied into the + * cert_sig[] array. + * + * -- Certificate end: the hashed issuer DN (saved_dn_hash[]) is + * looked up in the trust store (CA trust anchors only); for all + * that match, the signature (cert_sig[]) is verified against the + * anchor public key (hashed TBS is in tbs_hash[]). If one of these + * signatures is valid, then validation ends with a success. + * + * -- If the chain end is reached without obtaining a validation success, + * then validation is reported as failed. + */ + +#if BR_USE_UNIX_TIME +#include +#endif + +#if BR_USE_WIN32_TIME +#include +#endif + +/* + * The T0 compiler will produce these prototypes declarations in the + * header. + * +void br_x509_minimal_init_main(void *ctx); +void br_x509_minimal_run(void *ctx); + */ + +/* see bearssl_x509.h */ +void +br_x509_minimal_init(br_x509_minimal_context *ctx, + const br_hash_class *dn_hash_impl, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) +{ + memset(ctx, 0, sizeof *ctx); + ctx->vtable = &br_x509_minimal_vtable; + ctx->dn_hash_impl = dn_hash_impl; + ctx->trust_anchors = trust_anchors; + ctx->trust_anchors_num = trust_anchors_num; +} + +static void +xm_start_chain(const br_x509_class **ctx, const char *server_name) +{ + br_x509_minimal_context *cc; + size_t u; + + cc = (br_x509_minimal_context *)(void *)ctx; + for (u = 0; u < cc->num_name_elts; u ++) { + cc->name_elts[u].status = 0; + cc->name_elts[u].buf[0] = 0; + } + memset(&cc->pkey, 0, sizeof cc->pkey); + cc->num_certs = 0; + cc->err = 0; + cc->cpu.dp = cc->dp_stack; + cc->cpu.rp = cc->rp_stack; + br_x509_minimal_init_main(&cc->cpu); + if (server_name == NULL || *server_name == 0) { + cc->server_name = NULL; + } else { + cc->server_name = server_name; + } +} + +static void +xm_start_cert(const br_x509_class **ctx, uint32_t length) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)ctx; + if (cc->err != 0) { + return; + } + if (length == 0) { + cc->err = BR_ERR_X509_TRUNCATED; + return; + } + cc->cert_length = length; +} + +static void +xm_append(const br_x509_class **ctx, const unsigned char *buf, size_t len) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)ctx; + if (cc->err != 0) { + return; + } + cc->hbuf = buf; + cc->hlen = len; + br_x509_minimal_run(&cc->cpu); +} + +static void +xm_end_cert(const br_x509_class **ctx) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)ctx; + if (cc->err == 0 && cc->cert_length != 0) { + cc->err = BR_ERR_X509_TRUNCATED; + } + cc->num_certs ++; +} + +static unsigned +xm_end_chain(const br_x509_class **ctx) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)ctx; + if (cc->err == 0) { + if (cc->num_certs == 0) { + cc->err = BR_ERR_X509_EMPTY_CHAIN; + } else { + cc->err = BR_ERR_X509_NOT_TRUSTED; + } + } else if (cc->err == BR_ERR_X509_OK) { + return 0; + } + return (unsigned)cc->err; +} + +static const br_x509_pkey * +xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages) +{ + br_x509_minimal_context *cc; + + cc = (br_x509_minimal_context *)(void *)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 *)(void *)ctx)->pkey; + } else { + return NULL; + } +} + +/* see bearssl_x509.h */ +const br_x509_class br_x509_minimal_vtable = { + sizeof(br_x509_minimal_context), + xm_start_chain, + xm_start_cert, + xm_append, + xm_end_cert, + xm_end_chain, + xm_get_pkey +}; + +#define CTX ((br_x509_minimal_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_minimal_context, cpu))) +#define CONTEXT_NAME br_x509_minimal_context + +#define DNHASH_LEN ((CTX->dn_hash_impl->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK) + +/* + * Hash a DN (from a trust anchor) into the provided buffer. This uses the + * DN hash implementation and context structure from the X.509 engine + * context. + */ +static void +hash_dn(br_x509_minimal_context *ctx, const void *dn, size_t len, + unsigned char *out) +{ + ctx->dn_hash_impl->init(&ctx->dn_hash.vtable); + ctx->dn_hash_impl->update(&ctx->dn_hash.vtable, dn, len); + ctx->dn_hash_impl->out(&ctx->dn_hash.vtable, out); +} + +/* + * Compare two big integers for equality. The integers use unsigned big-endian + * encoding; extra leading bytes (of value 0) are allowed. + */ +static int +eqbigint(const unsigned char *b1, size_t len1, + const unsigned char *b2, size_t len2) +{ + while (len1 > 0 && *b1 == 0) { + b1 ++; + len1 --; + } + while (len2 > 0 && *b2 == 0) { + b2 ++; + len2 --; + } + if (len1 != len2) { + return 0; + } + return memcmp(b1, b2, len1) == 0; +} + +/* + * Compare two strings for equality, in a case-insensitive way. This + * function handles casing only for ASCII letters. + */ +static int +eqnocase(const void *s1, const void *s2, size_t len) +{ + const unsigned char *buf1, *buf2; + + buf1 = s1; + buf2 = s2; + while (len -- > 0) { + int x1, x2; + + x1 = *buf1 ++; + x2 = *buf2 ++; + if (x1 >= 'A' && x1 <= 'Z') { + x1 += 'a' - 'A'; + } + if (x2 >= 'A' && x2 <= 'Z') { + x2 += 'a' - 'A'; + } + if (x1 != x2) { + return 0; + } + } + return 1; +} + +static int verify_signature(br_x509_minimal_context *ctx, + const br_x509_pkey *pk); + +} + +postamble { + +/* + * Verify the signature on the certificate with the provided public key. + * This function checks the public key type with regards to the expected + * type. Returned value is either 0 on success, or a non-zero error code. + */ +static int +verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk) +{ + int kt; + + kt = ctx->cert_signer_key_type; + if ((pk->key_type & 0x0F) != kt) { + return BR_ERR_X509_WRONG_KEY_TYPE; + } + switch (kt) { + unsigned char tmp[64]; + + case BR_KEYTYPE_RSA: + if (ctx->irsa == 0) { + return BR_ERR_X509_UNSUPPORTED; + } + if (!ctx->irsa(ctx->cert_sig, ctx->cert_sig_len, + &t0_datablock[ctx->cert_sig_hash_oid], + ctx->cert_sig_hash_len, &pk->key.rsa, tmp)) + { + return BR_ERR_X509_BAD_SIGNATURE; + } + if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) { + return BR_ERR_X509_BAD_SIGNATURE; + } + return 0; + + case BR_KEYTYPE_EC: + if (ctx->iecdsa == 0) { + return BR_ERR_X509_UNSUPPORTED; + } + if (!ctx->iecdsa(ctx->iec, ctx->tbs_hash, + ctx->cert_sig_hash_len, &pk->key.ec, + ctx->cert_sig, ctx->cert_sig_len)) + { + return BR_ERR_X509_BAD_SIGNATURE; + } + return 0; + + default: + return BR_ERR_X509_UNSUPPORTED; + } +} + +} + +cc: read8-low ( -- x ) { + if (CTX->hlen == 0) { + T0_PUSHi(-1); + } else { + unsigned char x = *CTX->hbuf ++; + if (CTX->do_mhash) { + br_multihash_update(&CTX->mhash, &x, 1); + } + if (CTX->do_dn_hash) { + CTX->dn_hash_impl->update(&CTX->dn_hash.vtable, &x, 1); + } + CTX->hlen --; + T0_PUSH(x); + } +} + +addr: cert_length +addr: num_certs + +cc: read-blob-inner ( addr len -- addr len ) { + uint32_t len = T0_POP(); + uint32_t addr = T0_POP(); + size_t clen = CTX->hlen; + if (clen > len) { + clen = (size_t)len; + } + if (addr != 0) { + memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); + } + if (CTX->do_mhash) { + br_multihash_update(&CTX->mhash, CTX->hbuf, clen); + } + if (CTX->do_dn_hash) { + CTX->dn_hash_impl->update( + &CTX->dn_hash.vtable, CTX->hbuf, clen); + } + CTX->hbuf += clen; + CTX->hlen -= clen; + T0_PUSH(addr + clen); + T0_PUSH(len - clen); +} + +\ Compute the TBS hash, using the provided hash ID. The hash value is +\ written in the tbs_hash[] array, and the hash length is returned. If +\ the requested hash function is not supported, then 0 is returned. +cc: compute-tbs-hash ( id -- hashlen ) { + int id = T0_POPi(); + size_t len; + len = br_multihash_out(&CTX->mhash, id, CTX->tbs_hash); + T0_PUSH(len); +} + +\ Push true (-1) if no server name is expected in the EE certificate. +cc: zero-server-name ( -- bool ) { + T0_PUSHi(-(CTX->server_name == NULL)); +} + +addr: key_usages +addr: cert_sig +addr: cert_sig_len +addr: cert_signer_key_type +addr: cert_sig_hash_oid +addr: cert_sig_hash_len +addr: tbs_hash +addr: min_rsa_size + +\ Start TBS hash computation. The hash functions are reinitialised. +cc: start-tbs-hash ( -- ) { + br_multihash_init(&CTX->mhash); + CTX->do_mhash = 1; +} + +\ Stop TBS hash computation. +cc: stop-tbs-hash ( -- ) { + CTX->do_mhash = 0; +} + +\ Start DN hash computation. +cc: start-dn-hash ( -- ) { + CTX->dn_hash_impl->init(&CTX->dn_hash.vtable); + CTX->do_dn_hash = 1; +} + +\ Terminate DN hash computation and write the DN hash into the +\ current_dn_hash buffer. +cc: compute-dn-hash ( -- ) { + CTX->dn_hash_impl->out(&CTX->dn_hash.vtable, CTX->current_dn_hash); + CTX->do_dn_hash = 0; +} + +\ Get the length of hash values obtained with the DN hasher. +cc: dn-hash-length ( -- len ) { + T0_PUSH(DNHASH_LEN); +} + +\ Copy data between two areas in the context. +cc: blobcopy ( addr-dst addr-src len -- ) { + size_t len = T0_POP(); + unsigned char *src = (unsigned char *)CTX + T0_POP(); + unsigned char *dst = (unsigned char *)CTX + T0_POP(); + memcpy(dst, src, len); +} + +addr: current_dn_hash +addr: next_dn_hash +addr: saved_dn_hash + +\ Read a DN, hashing it into current_dn_hash. The DN contents are not +\ inspected (only the outer tag, for SEQUENCE, is checked). +: read-DN ( lim -- lim ) + start-dn-hash + read-sequence-open skip-close-elt + compute-dn-hash ; + +cc: offset-name-element ( san -- n ) { + unsigned san = T0_POP(); + size_t u; + + for (u = 0; u < CTX->num_name_elts; u ++) { + if (CTX->name_elts[u].status == 0) { + const unsigned char *oid; + size_t len, off; + + oid = CTX->name_elts[u].oid; + if (san) { + if (oid[0] != 0 || oid[1] != 0) { + continue; + } + off = 2; + } else { + off = 0; + } + len = oid[off]; + if (len != 0 && len == CTX->pad[0] + && memcmp(oid + off + 1, + CTX->pad + 1, len) == 0) + { + T0_PUSH(u); + T0_RET(); + } + } + } + T0_PUSHi(-1); +} + +cc: copy-name-element ( bool offbuf -- ) { + size_t len; + int32_t off = T0_POPi(); + int ok = T0_POPi(); + + if (off >= 0) { + br_name_element *ne = &CTX->name_elts[off]; + + if (ok) { + len = CTX->pad[0]; + if (len < ne->len) { + memcpy(ne->buf, CTX->pad + 1, len); + ne->buf[len] = 0; + ne->status = 1; + } else { + ne->status = -1; + } + } else { + ne->status = -1; + } + } +} + +cc: copy-name-SAN ( bool tag -- ) { + unsigned tag = T0_POP(); + unsigned ok = T0_POP(); + size_t u, len; + + len = CTX->pad[0]; + for (u = 0; u < CTX->num_name_elts; u ++) { + br_name_element *ne; + + ne = &CTX->name_elts[u]; + if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) { + if (ok && ne->len > len) { + memcpy(ne->buf, CTX->pad + 1, len); + ne->buf[len] = 0; + ne->status = 1; + } else { + ne->status = -1; + } + break; + } + } +} + +\ Read a value, decoding string types. If the string type is recognised +\ and the value could be converted to UTF-8 into the pad, then true (-1) +\ is returned; in all other cases, false (0) is returned. Either way, the +\ object is consumed. +: read-string ( lim -- lim bool ) + read-tag case + \ UTF8String + 12 of check-primitive read-value-UTF8 endof + \ NumericString + 18 of check-primitive read-value-latin1 endof + \ PrintableString + 19 of check-primitive read-value-latin1 endof + \ TeletexString + 20 of check-primitive read-value-latin1 endof + \ IA5String + 22 of check-primitive read-value-latin1 endof + \ BMPString + 30 of check-primitive read-value-UTF16 endof + 2drop read-length-skip 0 0 + endcase ; + +\ Read a DN for the EE. The normalized DN hash is computed and stored in the +\ current_dn_hash. +\ Name elements are gathered. Also, the Common Name is matched against the +\ intended server name. +\ Returned value is true (-1) if the CN matches the intended server name, +\ false (0) otherwise. +: read-DN-EE ( lim -- lim bool ) + \ Flag will be set to true if there is a CN and it matches the + \ intended server name. + 0 { eename-matches } + + \ Activate DN hashing. + start-dn-hash + + \ Parse the DN structure: it is a SEQUENCE of SET of + \ AttributeTypeAndValue. Each AttributeTypeAndValue is a + \ SEQUENCE { OBJECT IDENTIFIER, ANY }. + read-sequence-open + begin + dup while + + read-tag 0x11 check-tag-constructed read-length-open-elt + dup ifnot ERR_X509_BAD_DN fail then + begin + dup while + + read-sequence-open + + \ Read the OID. If the OID could not be read (too + \ long) then the first pad byte will be 0. + read-OID drop + + \ If it is the Common Name then we'll need to + \ match it against the intended server name (if + \ applicable). + id-at-commonName eqOID { isCN } + + \ Get offset for reception buffer for that element + \ (or -1). + 0 offset-name-element { offbuf } + + \ Try to read the value as a string. + read-string + + \ If the value could be decoded as a string, + \ copy it and/or match it, as appropriate. + dup isCN and if + match-server-name if + -1 >eename-matches + then + then + offbuf copy-name-element + + \ Close the SEQUENCE + close-elt + + repeat + close-elt + repeat + close-elt + + \ Compute DN hash and deactivate DN hashing. + compute-dn-hash + + \ Return the CN match flag. + eename-matches ; + +\ Check the provided validity range against the current (or configured) +\ date and time ("na" = notAfter, "nb = notBefore). Returned value: +\ -1 current date/time is before the notBefore date +\ 0 current date/time is within the allowed range +\ +1 current date/time is after the notAfter range +\ If the current date/time is not available, then this function triggers a +\ failure and does not return. +cc: check-validity-range ( na-days na-seconds nb-days nb-seconds -- int ) { + uint32_t nbs = T0_POP(); + uint32_t nbd = T0_POP(); + uint32_t nas = T0_POP(); + uint32_t nad = T0_POP(); + int r; + if (CTX->itime != 0) { + r = CTX->itime(CTX->itime_ctx, nbd, nbs, nad, nas); + if (r < -1 || r > 1) { + CTX->err = BR_ERR_X509_TIME_UNKNOWN; + T0_CO(); + } + } else { + uint32_t vd = CTX->days; + uint32_t vs = CTX->seconds; + if (vd == 0 && vs == 0) { +#if BR_USE_UNIX_TIME + time_t x = time(NULL); + + vd = (uint32_t)(x / 86400) + 719528; + vs = (uint32_t)(x % 86400); +#elif BR_USE_WIN32_TIME + FILETIME ft; + uint64_t x; + + GetSystemTimeAsFileTime(&ft); + x = ((uint64_t)ft.dwHighDateTime << 32) + + (uint64_t)ft.dwLowDateTime; + x = (x / 10000000); + vd = (uint32_t)(x / 86400) + 584754; + vs = (uint32_t)(x % 86400); +#else + CTX->err = BR_ERR_X509_TIME_UNKNOWN; + T0_CO(); +#endif + } + if (vd < nbd || (vd == nbd && vs < nbs)) { + r = -1; + } else if (vd > nad || (vd == nad && vs > nas)) { + r = 1; + } else { + r = 0; + } + } + T0_PUSHi(r); +} + +\ Swap the top two elements with the two elements immediately below. +: swap2 ( a b c d -- c d a b ) + 3 roll 3 roll ; + +\ Match the name in the pad with the expected server name. Returned value +\ is true (-1) on match, false (0) otherwise. If there is no expected +\ server name, then 0 is returned. +\ Match conditions: either an exact match (case insensitive), or a +\ wildcard match, if the found name starts with "*.". We only match a +\ starting wildcard, and only against a complete DN name component. +cc: match-server-name ( -- bool ) { + size_t n1, n2; + + if (CTX->server_name == NULL) { + T0_PUSH(0); + T0_RET(); + } + n1 = strlen(CTX->server_name); + n2 = CTX->pad[0]; + if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) { + T0_PUSHi(-1); + T0_RET(); + } + if (n2 >= 2 && CTX->pad[1] == '*' && CTX->pad[2] == '.') { + size_t u; + + u = 0; + while (u < n1 && CTX->server_name[u] != '.') { + u ++; + } + u ++; + n1 -= u; + if ((n2 - 2) == n1 + && eqnocase(&CTX->pad[3], CTX->server_name + u, n1)) + { + T0_PUSHi(-1); + T0_RET(); + } + } + T0_PUSH(0); +} + +\ Get the address and length for the pkey_data buffer. +: addr-len-pkey_data ( -- addr len ) + CX 0 8191 { offsetof(br_x509_minimal_context, pkey_data) } + CX 0 8191 { BR_X509_BUFSIZE_KEY } ; + +\ Copy the EE public key to the permanent buffer (RSA). +cc: copy-ee-rsa-pkey ( nlen elen -- ) { + size_t elen = T0_POP(); + size_t nlen = T0_POP(); + memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen); + CTX->pkey.key_type = BR_KEYTYPE_RSA; + CTX->pkey.key.rsa.n = CTX->ee_pkey_data; + CTX->pkey.key.rsa.nlen = nlen; + CTX->pkey.key.rsa.e = CTX->ee_pkey_data + nlen; + CTX->pkey.key.rsa.elen = elen; +} + +\ Copy the EE public key to the permanent buffer (EC). +cc: copy-ee-ec-pkey ( curve qlen -- ) { + size_t qlen = T0_POP(); + uint32_t curve = T0_POP(); + memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen); + CTX->pkey.key_type = BR_KEYTYPE_EC; + CTX->pkey.key.ec.curve = curve; + CTX->pkey.key.ec.q = CTX->ee_pkey_data; + CTX->pkey.key.ec.qlen = qlen; +} + +\ Check whether the current certificate (EE) is directly trusted. +cc: check-direct-trust ( -- ) { + size_t u; + + for (u = 0; u < CTX->trust_anchors_num; u ++) { + const br_x509_trust_anchor *ta; + unsigned char hashed_DN[64]; + int kt; + + ta = &CTX->trust_anchors[u]; + if (ta->flags & BR_X509_TA_CA) { + continue; + } + hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); + if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) { + continue; + } + kt = CTX->pkey.key_type; + if ((ta->pkey.key_type & 0x0F) != kt) { + continue; + } + switch (kt) { + + case BR_KEYTYPE_RSA: + if (!eqbigint(CTX->pkey.key.rsa.n, + CTX->pkey.key.rsa.nlen, + ta->pkey.key.rsa.n, + ta->pkey.key.rsa.nlen) + || !eqbigint(CTX->pkey.key.rsa.e, + CTX->pkey.key.rsa.elen, + ta->pkey.key.rsa.e, + ta->pkey.key.rsa.elen)) + { + continue; + } + break; + + case BR_KEYTYPE_EC: + if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve + || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen + || memcmp(CTX->pkey.key.ec.q, + ta->pkey.key.ec.q, + ta->pkey.key.ec.qlen) != 0) + { + continue; + } + break; + + default: + continue; + } + + /* + * Direct trust match! + */ + CTX->err = BR_ERR_X509_OK; + T0_CO(); + } +} + +\ Check the signature on the certificate with regards to all trusted CA. +\ We use the issuer hash (in saved_dn_hash[]) as CA identifier. +cc: check-trust-anchor-CA ( -- ) { + size_t u; + + for (u = 0; u < CTX->trust_anchors_num; u ++) { + const br_x509_trust_anchor *ta; + unsigned char hashed_DN[64]; + + ta = &CTX->trust_anchors[u]; + if (!(ta->flags & BR_X509_TA_CA)) { + continue; + } + hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); + if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) { + continue; + } + if (verify_signature(CTX, &ta->pkey) == 0) { + CTX->err = BR_ERR_X509_OK; + T0_CO(); + } + } +} + +\ Verify RSA signature. This uses the public key that was just decoded +\ into CTX->pkey_data; the modulus and exponent length are provided as +\ parameters. The resulting hash value is compared with the one in +\ tbs_hash. Returned value is 0 on success, or a non-zero error code. +cc: do-rsa-vrfy ( nlen elen -- err ) { + size_t elen = T0_POP(); + size_t nlen = T0_POP(); + br_x509_pkey pk; + + pk.key_type = BR_KEYTYPE_RSA; + pk.key.rsa.n = CTX->pkey_data; + pk.key.rsa.nlen = nlen; + pk.key.rsa.e = CTX->pkey_data + nlen; + pk.key.rsa.elen = elen; + T0_PUSH(verify_signature(CTX, &pk)); +} + +\ Verify ECDSA signature. This uses the public key that was just decoded +\ into CTX->pkey_dayta; the curve ID and public point length are provided +\ as parameters. The hash value in tbs_hash is used. Returned value is 0 +\ on success, or non-zero error code. +cc: do-ecdsa-vrfy ( curve qlen -- err ) { + size_t qlen = T0_POP(); + int curve = T0_POP(); + br_x509_pkey pk; + + pk.key_type = BR_KEYTYPE_EC; + pk.key.ec.curve = curve; + pk.key.ec.q = CTX->pkey_data; + pk.key.ec.qlen = qlen; + T0_PUSH(verify_signature(CTX, &pk)); +} + +cc: print-bytes ( addr len -- ) { + extern int printf(const char *fmt, ...); + size_t len = T0_POP(); + unsigned char *buf = (unsigned char *)CTX + T0_POP(); + size_t u; + + for (u = 0; u < len; u ++) { + printf("%02X", buf[u]); + } +} + +cc: printOID ( -- ) { + extern int printf(const char *fmt, ...); + size_t u, len; + + len = CTX->pad[0]; + if (len == 0) { + printf("*"); + T0_RET(); + } + printf("%u.%u", CTX->pad[1] / 40, CTX->pad[1] % 40); + u = 2; + while (u <= len) { + unsigned long ul; + + ul = 0; + for (;;) { + int x; + + if (u > len) { + printf("BAD"); + T0_RET(); + } + x = CTX->pad[u ++]; + ul = (ul << 7) + (x & 0x7F); + if (!(x & 0x80)) { + break; + } + } + printf(".%lu", ul); + } +} + +\ Extensions with specific processing. +OID: basicConstraints 2.5.29.19 +OID: keyUsage 2.5.29.15 +OID: subjectAltName 2.5.29.17 +OID: certificatePolicies 2.5.29.32 + +\ Policy qualifier "pointer to CPS" +OID: id-qt-cps 1.3.6.1.5.5.7.2.1 + +\ Extensions which are ignored when encountered, even if critical. +OID: authorityKeyIdentifier 2.5.29.35 +OID: subjectKeyIdentifier 2.5.29.14 +OID: issuerAltName 2.5.29.18 +OID: subjectDirectoryAttributes 2.5.29.9 +OID: crlDistributionPoints 2.5.29.31 +OID: freshestCRL 2.5.29.46 +OID: authorityInfoAccess 1.3.6.1.5.5.7.1.1 +OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11 + +\ Process a Basic Constraints extension. This should be called only if +\ the certificate is not the EE. We check that the extension contains +\ the "CA" flag, and that the path length, if specified, is compatible +\ with the current chain length. +: process-basicConstraints ( lim -- lim ) + read-sequence-open + read-tag-or-end + dup 0x01 = if + read-boolean ifnot ERR_X509_NOT_CA fail then + read-tag-or-end + else + ERR_X509_NOT_CA fail + then + dup 0x02 = if + drop check-primitive read-small-int-value + addr-num_certs get32 1- < if ERR_X509_NOT_CA fail then + read-tag-or-end + then + -1 <> if ERR_X509_UNEXPECTED fail then + drop + close-elt + ; + +\ Process a Key Usage extension. +\ For the EE certificate: +\ -- 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 ) + { ee } + + \ Read tag for the BIT STRING and open it. + read-tag 0x03 check-tag-primitive + read-length-open-elt + \ First byte indicates number of ignored bits in the last byte. It + \ must be between 0 and 7. + read8 { ign } + ign 7 > if ERR_X509_UNEXPECTED fail then + \ Depending on length, we have either 0, 1 or more bytes to read. + dup case + 0 of ERR_X509_FORBIDDEN_KEY_USAGE fail endof + 1 of read8 ign >> ign << endof + drop read8 0 + endcase + + \ 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 Certificate Policies extension. +\ +\ Since we don't actually support full policies processing, this function +\ only checks that the extension contents can be safely ignored. Indeed, +\ we don't validate against a specific set of policies (in RFC 5280 +\ terminology, user-initial-policy-set only contains the special value +\ any-policy). Moreover, we don't support policy constraints (if a +\ critical Policy Constraints extension is encountered, the validation +\ will fail). Therefore, we can safely ignore the contents of this +\ extension, except if it is critical AND one of the policy OID has a +\ qualifier which is distinct from id-qt-cps (because id-qt-cps is +\ specially designated by RFC 5280 has having no mandated action). +\ +\ This function is called only if the extension is critical. +: process-certPolicies ( lim -- lim ) + \ Extension value is a SEQUENCE OF PolicyInformation. + read-sequence-open + begin dup while + \ PolicyInformation ::= SEQUENCE { + \ policyIdentifier OBJECT IDENTIFIER, + \ policyQualifiers SEQUENCE OF PolicyQualifierInfo OPTIONAL + \ } + read-sequence-open + read-OID drop + dup if + read-sequence-open + begin dup while + \ PolicyQualifierInfo ::= SEQUENCE { + \ policyQualifierId OBJECT IDENTIFIER, + \ qualifier ANY + \ } + read-sequence-open + read-OID drop id-qt-cps eqOID ifnot + ERR_X509_CRITICAL_EXTENSION fail + then + skip-close-elt + repeat + close-elt + then + close-elt + repeat + close-elt ; + +\ Process a Subject Alt Name extension. Returned value is a boolean set +\ to true if the expected server name was matched against a dNSName in +\ the extension. +: process-SAN ( lim -- lim bool ) + 0 { m } + read-sequence-open + begin dup while + \ Read the tag. If the tag is context-0, then parse an + \ 'otherName'. If the tag is context-2, then parse a + \ dNSName. If the tag is context-1 or context-6, + \ parse + read-tag case + \ OtherName + 0x20 of + \ OtherName ::= SEQUENCE { + \ type-id OBJECT IDENTIFIER, + \ value [0] EXPLICIT ANY + \ } + check-constructed read-length-open-elt + read-OID drop + -1 offset-name-element { offbuf } + read-tag 0x20 check-tag-constructed + read-length-open-elt + read-string offbuf copy-name-element + close-elt + close-elt + endof + \ rfc822Name (IA5String) + 0x21 of + check-primitive + read-value-UTF8 1 copy-name-SAN + endof + \ dNSName (IA5String) + 0x22 of + check-primitive + read-value-UTF8 + dup if match-server-name m or >m then + 2 copy-name-SAN + endof + \ uniformResourceIdentifier (IA5String) + 0x26 of + check-primitive + read-value-UTF8 6 copy-name-SAN + endof + 2drop read-length-skip 0 + endcase + + \ We check only names of type dNSName; they use IA5String, + \ which is basically ASCII. + \ read-tag 0x22 = if + \ check-primitive + \ read-small-value drop + \ match-server-name m or >m + \ else + \ drop read-length-skip + \ then + repeat + close-elt + m ; + +\ Decode a certificate. The "ee" boolean must be true for the EE. +: decode-certificate ( ee -- ) + { ee } + + \ Obtain the total certificate length. + addr-cert_length get32 + + \ Open the outer SEQUENCE. + read-sequence-open + + \ TBS + \ Activate hashing. + start-tbs-hash + read-sequence-open + + \ First element may be an explicit version. We accept only + \ versions 0 to 2 (certificates v1 to v3). + read-tag dup 0x20 = if + drop check-constructed read-length-open-elt + read-tag + 0x02 check-tag-primitive + read-small-int-value + 2 > if ERR_X509_UNSUPPORTED fail then + close-elt + read-tag + then + + \ Serial number. We just check that the tag is correct. + 0x02 check-tag-primitive + read-length-skip + + \ Signature algorithm. This structure is redundant with the one + \ on the outside; we just skip it. + read-sequence-open skip-close-elt + + \ Issuer name: hashed, then copied into next_dn_hash[]. + read-DN + addr-next_dn_hash addr-current_dn_hash dn-hash-length blobcopy + + \ Validity dates. + read-sequence-open + read-date { nbd nbs } read-date nbd nbs check-validity-range + if ERR_X509_EXPIRED fail then + close-elt + + \ Subject name. + ee if + \ For the EE, we must check whether the Common Name, if + \ any, matches the expected server name. + read-DN-EE { eename } + else + \ For a non-EE certificate, the hashed subject DN must match + \ the saved hashed issuer DN from the previous certificate. + read-DN + addr-current_dn_hash addr-saved_dn_hash dn-hash-length eqblob + ifnot ERR_X509_DN_MISMATCH fail then + then + \ Move the hashed issuer DN for this certificate into the + \ saved_dn_hash[] array. + addr-saved_dn_hash addr-next_dn_hash dn-hash-length blobcopy + + \ Public Key. + read-sequence-open + \ Algorithm Identifier. Right now we are only interested in the + \ OID, since we only support RSA keys. + read-sequence-open + read-OID ifnot ERR_X509_UNSUPPORTED fail then + { ; pkey-type } + choice + \ RSA public key. + rsaEncryption eqOID uf + skip-close-elt + \ Public key itself: the BIT STRING contains bytes + \ (no partial byte) and these bytes encode the + \ actual value. + read-bits-open + \ RSA public key is a SEQUENCE of two + \ INTEGER. We get both INTEGER values into + \ the pkey_data[] buffer, if they fit. + read-sequence-open + addr-len-pkey_data + read-integer { nlen } + addr-len-pkey_data swap nlen + swap nlen - + read-integer { elen } + close-elt + + \ Check that the public key fits our minimal + \ size requirements. Note that the integer + \ decoder already skipped the leading bytes + \ of value 0, so we are working on the true + \ modulus length here. + addr-min_rsa_size get16 128 + nlen > if + ERR_X509_WEAK_PUBLIC_KEY fail + then + close-elt + KEYTYPE_RSA >pkey-type + enduf + + \ EC public key. + id-ecPublicKey eqOID uf + \ We support only named curves, for which the + \ "parameters" field in the AlgorithmIdentifier + \ field should be an OID. + read-OID ifnot ERR_X509_UNSUPPORTED fail then + choice + ansix9p256r1 eqOID uf 23 enduf + ansix9p384r1 eqOID uf 24 enduf + ansix9p521r1 eqOID uf 25 enduf + ERR_X509_UNSUPPORTED fail + endchoice + { curve } + close-elt + read-bits-open + dup { qlen } + dup addr-len-pkey_data rot < if + ERR_X509_LIMIT_EXCEEDED fail + then + read-blob + KEYTYPE_EC >pkey-type + enduf + + \ Not a recognised public key type. + ERR_X509_UNSUPPORTED fail + endchoice + close-elt + + \ Process public key. + ee if + \ 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 + ERR_X509_UNSUPPORTED fail + endcase + else + \ Verify signature on previous certificate. We invoke + \ the RSA implementation. + pkey-type case + KEYTYPE_RSA of nlen elen do-rsa-vrfy endof + KEYTYPE_EC of curve qlen do-ecdsa-vrfy endof + ERR_X509_UNSUPPORTED fail + endcase + dup if fail then + drop + then + + \ This flag will be set to true if the Basic Constraints extension + \ is encountered. + 0 { seenBC } + + \ Skip issuerUniqueID and subjectUniqueID, and process extensions + \ if present. Extensions are an explicit context tag of value 3 + \ around a SEQUENCE OF extensions. Each extension is a SEQUENCE + \ with an OID, an optional boolean, and a value; the value is + \ an OCTET STRING. + read-tag-or-end + 0x21 iftag-skip + 0x22 iftag-skip + dup 0x23 = if + drop + check-constructed read-length-open-elt + read-sequence-open + begin dup while + 0 { critical } + read-sequence-open + read-OID drop + read-tag dup 0x01 = if + read-boolean >critical + read-tag + then + 0x04 check-tag-primitive read-length-open-elt + choice + \ Extensions with specific processing. + basicConstraints eqOID uf + ee if + skip-remaining + else + process-basicConstraints + -1 >seenBC + then + enduf + keyUsage eqOID uf + ee process-keyUsage + enduf + subjectAltName eqOID uf + ee if + 0 >eename + process-SAN >eename + else + skip-remaining + then + enduf + + \ We don't implement full processing of + \ policies. The call below mostly checks + \ that the contents of the Certificate + \ Policies extension can be safely ignored. + certificatePolicies eqOID uf + critical if + process-certPolicies + else + skip-remaining + then + enduf + + \ Extensions which are always ignored, + \ even if critical. + authorityKeyIdentifier eqOID uf + skip-remaining + enduf + subjectKeyIdentifier eqOID uf + skip-remaining + enduf + issuerAltName eqOID uf + skip-remaining + enduf + subjectDirectoryAttributes eqOID uf + skip-remaining + enduf + crlDistributionPoints eqOID uf + skip-remaining + enduf + freshestCRL eqOID uf + skip-remaining + enduf + authorityInfoAccess eqOID uf + skip-remaining + enduf + subjectInfoAccess eqOID uf + skip-remaining + enduf + + \ Unrecognized extensions trigger a failure + \ if critical; otherwise, they are just + \ ignored. + critical if + ERR_X509_CRITICAL_EXTENSION fail + then + skip-remaining + endchoice + close-elt + close-elt + repeat + close-elt + close-elt + else + -1 = ifnot ERR_X509_UNEXPECTED fail then + drop + then + + close-elt + \ Terminate hashing. + stop-tbs-hash + + \ For the EE certificate, verify that the intended server name + \ was matched. + ee if + eename zero-server-name or ifnot + ERR_X509_BAD_SERVER_NAME fail + then + then + + \ If this is the EE certificate, then direct trust may apply. + \ Note: we do this at this point, not immediately after decoding + \ the public key, because even in case of direct trust we still + \ want to check the server name with regards to the SAN extension. + \ However, we want to check direct trust before trying to decode + \ the signature algorithm, because it should work even if that + \ algorithm is not supported. + ee if check-direct-trust then + + \ Non-EE certificates MUST have a Basic Constraints extension + \ (that marks them as being CA). + ee seenBC or ifnot ERR_X509_NOT_CA fail then + + \ signature algorithm + read-tag check-sequence read-length-open-elt + \ Read and understand the OID. Right now, we support only + \ RSA with PKCS#1 v1.5 padding, and hash functions SHA-1, + \ SHA-224, SHA-256, SHA-384 and SHA-512. We purposely do NOT + \ support MD5 here. + \ TODO: add support for RSA/PSS + read-OID if + \ Based on the signature OID, we get: + \ -- the signing key type + \ -- the hash function numeric identifier + \ -- the hash function OID + choice + sha1WithRSAEncryption eqOID + uf 2 KEYTYPE_RSA id-sha1 enduf + sha224WithRSAEncryption eqOID + uf 3 KEYTYPE_RSA id-sha224 enduf + sha256WithRSAEncryption eqOID + uf 4 KEYTYPE_RSA id-sha256 enduf + sha384WithRSAEncryption eqOID + uf 5 KEYTYPE_RSA id-sha384 enduf + sha512WithRSAEncryption eqOID + uf 6 KEYTYPE_RSA id-sha512 enduf + + ecdsa-with-SHA1 eqOID + uf 2 KEYTYPE_EC id-sha1 enduf + ecdsa-with-SHA224 eqOID + uf 3 KEYTYPE_EC id-sha224 enduf + ecdsa-with-SHA256 eqOID + uf 4 KEYTYPE_EC id-sha256 enduf + ecdsa-with-SHA384 eqOID + uf 5 KEYTYPE_EC id-sha384 enduf + ecdsa-with-SHA512 eqOID + uf 6 KEYTYPE_EC id-sha512 enduf + ERR_X509_UNSUPPORTED fail + endchoice + addr-cert_sig_hash_oid set16 + addr-cert_signer_key_type set8 + + \ Compute the TBS hash into tbs_hash. + compute-tbs-hash + dup ifnot ERR_X509_UNSUPPORTED fail then + addr-cert_sig_hash_len set8 + else + ERR_X509_UNSUPPORTED fail + then + \ We ignore the parameters, whether they are present or not, + \ because we got all the information from the OID. + skip-close-elt + + \ signature value + read-bits-open + dup CX 0 8191 { BR_X509_BUFSIZE_SIG } > if + ERR_X509_LIMIT_EXCEEDED fail + then + dup addr-cert_sig_len set16 + addr-cert_sig read-blob + + \ Close the outer SEQUENCE. + close-elt + + \ Close the advertised total certificate length. This checks that + \ there is no trailing garbage after the certificate. + close-elt + + \ Flag the certificate as fully processed. + 0 addr-cert_length set32 + + \ Check whether the issuer for the current certificate is known + \ as a trusted CA; in which case, verify the signature. + 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 + 0 decode-certificate co + again + ; diff --git a/BearSSL-OG/libbearssl/src/x509/x509_minimal_full.c b/BearSSL-OG/libbearssl/src/x509/x509_minimal_full.c new file mode 100644 index 0000000..2b54426 --- /dev/null +++ b/BearSSL-OG/libbearssl/src/x509/x509_minimal_full.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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" + +/* see bearssl_x509.h */ +void +br_x509_minimal_init_full(br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) +{ + /* + * All hash functions are activated. + * Note: the X.509 validation engine will nonetheless refuse to + * validate signatures that use MD5 as hash function. + */ + static const br_hash_class *hashes[] = { + &br_md5_vtable, + &br_sha1_vtable, + &br_sha224_vtable, + &br_sha256_vtable, + &br_sha384_vtable, + &br_sha512_vtable + }; + + int id; + + br_x509_minimal_init(xc, &br_sha256_vtable, + trust_anchors, trust_anchors_num); + 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); + for (id = br_md5_ID; id <= br_sha512_ID; id ++) { + const br_hash_class *hc; + + hc = hashes[id - 1]; + br_x509_minimal_set_hash(xc, id, hc); + } +} diff --git a/BearSSL-OG/main.cpp b/BearSSL-OG/main.cpp new file mode 100644 index 0000000..4a51d8e --- /dev/null +++ b/BearSSL-OG/main.cpp @@ -0,0 +1,63 @@ +#include "stdafx.h" + +#include "network_utility.h" +#include "client.h" +#include "server.h" +#include "debug_utility.h" +#include "data_store.h" + +bool mount_e_drive() +{ + char* mountPoint = "\\??\\E:"; + char* systemPath = "\\Device\\Harddisk0\\Partition1"; + STRING sMountPoint = {(USHORT)strlen(mountPoint), (USHORT)strlen(mountPoint) + 1, mountPoint}; + STRING sSystemPath = {(USHORT)strlen(systemPath), (USHORT)strlen(systemPath) + 1, systemPath}; + int result = IoCreateSymbolicLink(&sMountPoint, &sSystemPath); + return result == 0; +} + +void __cdecl main() +{ + if (network_utility::init() == false) + { + return; + } + + if (network_utility::wait_ready() == false) + { + return; + } + + mount_e_drive(); + + uint16_t port = 443; + + //const char* url = "https://codeload.github.com/Team-Resurgent/PrometheOS-Firmware/archive/refs/tags/V1.5.0.zip"; + const char* url = "https://codeload.github.com/Team-Resurgent/PrometheOS-Firmware/zip/refs/tags/V1.5.0"; + const char* file_path = "E:\\testfile.bin"; + + //With Redirect + //const char* url = "https://github.com/Team-Resurgent/Modxo/releases/download/V1.0.8/modxo_official_pico.bin"; + //const char* file_path = "E:\\modxo_official_pico.bin"; + + //Chunked (saves as webp) + //const char* url = "https://www.etechnophiles.com/wp-content/uploads/2021/02/pinout_923x768.jpg"; + //const char* file_path = "E:\\pinout_923x768.webp"; + + //Non Chunked + //const char* url = "https://download.winamp.com/winamp/winamp_latest_full.exe"; + //const char* file_path = "E:\\winamp_latest_full.exe"; + + client* client_instance = new client(); + //client_instance->download_file(url, port, file_path); + + server* server_instance = new server(); + server_instance->start(443); + + while (true) + { + Sleep(100); + } +} + + diff --git a/BearSSL-OG/main_test.cpp b/BearSSL-OG/main_test.cpp new file mode 100644 index 0000000..85add61 --- /dev/null +++ b/BearSSL-OG/main_test.cpp @@ -0,0 +1,132 @@ +// main_test.cpp - Test runner for SSL enhancements +// +// This is an alternative main() that runs the SSL test suite instead of +// the normal server/client operations. To use: +// +// Option 1: Rename this to main.cpp (backup original first) +// Option 2: Add a #define RUN_SSL_TESTS before including this +// Option 3: Copy the test call into your existing main.cpp +// +// Example usage in existing main.cpp: +// +// #include "ssl_test.h" +// +// void __cdecl main() +// { +// // ... network init code ... +// +// // Run SSL tests +// int failures = ssl_test::run_all_tests(); +// +// if (failures > 0) { +// debug_utility::debug_print("SSL tests had %d failures\n", failures); +// } +// +// // ... rest of your code ... +// } + +#include "stdafx.h" + +#include "network_utility.h" +#include "client.h" +#include "server.h" +#include "debug_utility.h" +#include "ssl_test.h" +#include "ssl_debug.h" + +bool mount_e_drive() +{ + char* mountPoint = "\\??\\E:"; + char* systemPath = "\\Device\\Harddisk0\\Partition1"; + STRING sMountPoint = {(USHORT)strlen(mountPoint), (USHORT)strlen(mountPoint) + 1, mountPoint}; + STRING sSystemPath = {(USHORT)strlen(systemPath), (USHORT)strlen(systemPath) + 1, systemPath}; + int result = IoCreateSymbolicLink(&sMountPoint, &sSystemPath); + return result == 0; +} + +void __cdecl main() +{ + debug_utility::debug_print("BearSSL-OG Test Runner\n"); + debug_utility::debug_print("======================\n\n"); + + // Initialize network + debug_utility::debug_print("Initializing network...\n"); + if (network_utility::init() == false) + { + debug_utility::debug_print("ERROR: Network init failed\n"); + return; + } + + debug_utility::debug_print("Waiting for network ready...\n"); + if (network_utility::wait_ready() == false) + { + debug_utility::debug_print("ERROR: Network not ready\n"); + return; + } + + debug_utility::debug_print("Network ready!\n"); + + // Mount E: drive for test files + if (mount_e_drive()) + { + debug_utility::debug_print("E: drive mounted\n"); + } + else + { + debug_utility::debug_print("WARNING: E: drive mount failed\n"); + } + + // Set default debug level + ssl_debug::set_level(SSL_DEBUG_INFO); + + // ========================================================================= + // RUN SSL TEST SUITE + // ========================================================================= + int failures = ssl_test::run_all_tests(); + + // ========================================================================= + // OPTIONAL: Run individual tests + // ========================================================================= + // Uncomment any of these to run specific tests: + // + // ssl_test_result r1 = ssl_test::test_basic_https_connection(); + // ssl_test::print_result(r1); + // + // ssl_test_result r2 = ssl_test::test_large_file_download(); + // ssl_test::print_result(r2); + // + // ssl_test_result r3 = ssl_test::test_session_resumption(); + // ssl_test::print_result(r3); + + // ========================================================================= + // OPTIONAL: Quick single download test + // ========================================================================= + // If you just want to test a single download: + // + // client* c = new client(); + // int result = c->download_file( + // "https://raw.githubusercontent.com/AbanteAI/rawdog/main/README.md", + // 443, + // "E:\\test_download.txt" + // ); + // debug_utility::debug_print("Download result: %d\n", result); + // delete c; + + // Report final status + debug_utility::debug_print("\n\n"); + if (failures == 0) + { + debug_utility::debug_print("*** ALL SSL TESTS PASSED ***\n"); + } + else + { + debug_utility::debug_print("*** %d SSL TEST(S) FAILED ***\n", failures); + } + + // Keep alive so output can be read + debug_utility::debug_print("\nTest complete. System will idle.\n"); + while (true) + { + Sleep(1000); + } +} diff --git a/BearSSL-OG/missing/stdint.h b/BearSSL-OG/missing/stdint.h new file mode 100644 index 0000000..04c3d22 --- /dev/null +++ b/BearSSL-OG/missing/stdint.h @@ -0,0 +1,213 @@ +#pragma once + +/* + * C99 stdint.h implementation for Xbox XDK (Visual Studio 2003) + * The Xbox XDK doesn't include this standard header. + * Some types may already be defined by XDK headers, so we guard against redefinition. + */ + +/* Exact-width integer types */ +#ifndef _INT8_T_DEFINED +typedef signed char int8_t; +#define _INT8_T_DEFINED +#endif + +#ifndef _INT16_T_DEFINED +typedef short int16_t; +#define _INT16_T_DEFINED +#endif + +#ifndef _INT32_T_DEFINED +typedef long int32_t; +#define _INT32_T_DEFINED +#endif + +#ifndef _INT64_T_DEFINED +typedef long long int64_t; +#define _INT64_T_DEFINED +#endif + +#ifndef _UINT8_T_DEFINED +typedef unsigned char uint8_t; +#define _UINT8_T_DEFINED +#endif + +#ifndef _UINT16_T_DEFINED +typedef unsigned short uint16_t; +#define _UINT16_T_DEFINED +#endif + +#ifndef _UINT32_T_DEFINED +typedef unsigned long uint32_t; +#define _UINT32_T_DEFINED +#endif + +#ifndef _UINT64_T_DEFINED +typedef unsigned long long uint64_t; +#define _UINT64_T_DEFINED +#endif + +/* Minimum-width integer types */ +#ifndef _INT_LEAST8_T_DEFINED +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; +#define _INT_LEAST8_T_DEFINED +#endif + +/* Fastest minimum-width integer types */ +#ifndef _INT_FAST8_T_DEFINED +typedef int32_t int_fast8_t; +typedef int32_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint32_t uint_fast8_t; +typedef uint32_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; +#define _INT_FAST8_T_DEFINED +#endif + +/* Integer types capable of holding object pointers */ +#ifndef _INTPTR_T_DEFINED +typedef long intptr_t; +#define _INTPTR_T_DEFINED +#endif + +#ifndef _UINTPTR_T_DEFINED +typedef unsigned long uintptr_t; +#define _UINTPTR_T_DEFINED +#endif + +/* Greatest-width integer types */ +#ifndef _INTMAX_T_DEFINED +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; +#define _INTMAX_T_DEFINED +#endif + +/* Signed integer type for size differences */ +#ifndef _SSIZE_T_DEFINED +typedef long ssize_t; +#define _SSIZE_T_DEFINED +#endif + +/* Limits of exact-width integer types */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT8_MAX +#define INT8_MAX 127 +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32768) +#endif +#ifndef INT16_MAX +#define INT16_MAX 32767 +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647L - 1) +#endif +#ifndef INT32_MAX +#define INT32_MAX 2147483647L +#endif +#ifndef INT64_MIN +#define INT64_MIN (-9223372036854775807LL - 1) +#endif +#ifndef INT64_MAX +#define INT64_MAX 9223372036854775807LL +#endif + +#ifndef UINT8_MAX +#define UINT8_MAX 255 +#endif +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif +#ifndef UINT32_MAX +#define UINT32_MAX 4294967295UL +#endif +#ifndef UINT64_MAX +#define UINT64_MAX 18446744073709551615ULL +#endif + +/* Limits of minimum-width integer types */ +#ifndef INT_LEAST8_MIN +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX +#endif + +/* Limits of fastest minimum-width integer types */ +#ifndef INT_FAST8_MIN +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST8_MAX INT32_MAX +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX +#endif + +/* Limits of integer types capable of holding object pointers */ +#ifndef INTPTR_MIN +#define INTPTR_MIN INT32_MIN +#endif +#ifndef INTPTR_MAX +#define INTPTR_MAX INT32_MAX +#endif +#ifndef UINTPTR_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* Limits of greatest-width integer types */ +#ifndef INTMAX_MIN +#define INTMAX_MIN INT64_MIN +#endif +#ifndef INTMAX_MAX +#define INTMAX_MAX INT64_MAX +#endif +#ifndef UINTMAX_MAX +#define UINTMAX_MAX UINT64_MAX +#endif + +/* Limits of other integer types */ +#ifndef SIZE_MAX +#define SIZE_MAX UINT32_MAX +#endif +#ifndef SSIZE_MAX +#define SSIZE_MAX INT32_MAX +#endif + +/* Macros for integer constant expressions */ +#ifndef INT8_C +#define INT8_C(x) (x) +#define INT16_C(x) (x) +#define INT32_C(x) (x ## L) +#define INT64_C(x) (x ## LL) +#define UINT8_C(x) (x) +#define UINT16_C(x) (x) +#define UINT32_C(x) (x ## UL) +#define UINT64_C(x) (x ## ULL) +#define INTMAX_C(x) INT64_C(x) +#define UINTMAX_C(x) UINT64_C(x) +#endif \ No newline at end of file diff --git a/BearSSL-OG/network_utility.cpp b/BearSSL-OG/network_utility.cpp new file mode 100644 index 0000000..565e7e2 --- /dev/null +++ b/BearSSL-OG/network_utility.cpp @@ -0,0 +1,127 @@ +#include "network_utility.h" + +#include +#include +#include + +#define RECV_SOCKET_BUFFER_SIZE_IN_K 64 +#define RECV_SOCKET_BUFFER_SIZE RECV_SOCKET_BUFFER_SIZE_IN_K * 1024 +#define SEND_SOCKET_BUFFER_SIZE_IN_K 64 +#define SEND_SOCKET_BUFFER_SIZE SEND_SOCKET_BUFFER_SIZE_IN_K * 1024 + +static bool initialized = false; + +bool network_utility::init() +{ + if (initialized == true) + { + return false; + } + + XNetStartupParams xnsp; + memset(&xnsp, 0, sizeof(xnsp)); + xnsp.cfgSizeOfStruct = sizeof(XNetStartupParams); + xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY; + + xnsp.cfgPrivatePoolSizeInPages = 64; + xnsp.cfgEnetReceiveQueueLength = 16; + xnsp.cfgIpFragMaxSimultaneous = 16; + xnsp.cfgIpFragMaxPacketDiv256 = 32; + xnsp.cfgSockMaxSockets = 64; + + xnsp.cfgSockDefaultRecvBufsizeInK = RECV_SOCKET_BUFFER_SIZE_IN_K; + xnsp.cfgSockDefaultSendBufsizeInK = SEND_SOCKET_BUFFER_SIZE_IN_K; + + int xnet_result = XNetStartup(&xnsp); + if (xnet_result != 0) + { + return false; + } + + WSADATA wsaData; + int result = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (result != 0) + { + return false; + } + initialized = true; + return true; +} + +bool network_utility::is_ready() +{ + if (initialized == false) + { + return false; + } + XNADDR addr; + memset(&addr, 0, sizeof(addr)); + DWORD dwState = XNetGetTitleXnAddr(&addr); + return dwState != XNET_GET_XNADDR_PENDING; +} + +bool network_utility::wait_ready() +{ + if (initialized == false) + { + return false; + } + while (is_ready() == false) + { + Sleep(1000); + } + return true; +} + +uint32_t network_utility::resolve_host(const char* host) +{ + return resolve_host_with_timeout(host, DNS_TIMEOUT_MS); +} + +uint32_t network_utility::resolve_host_with_timeout(const char* host, uint32_t timeout_ms) +{ + uint32_t result = 0; /* Return 0 (INADDR_ANY/invalid) on failure */ + XNDNS* dns = NULL; + WSAEVENT event_handle = NULL; + + /* Validate input */ + if (host == NULL || host[0] == '\0') + { + return 0; + } + + /* Create event for async DNS notification */ + event_handle = WSACreateEvent(); + if (event_handle == NULL) + { + return 0; + } + + /* Initiate DNS lookup */ + int error = XNetDnsLookup(host, event_handle, &dns); + if (error != 0) + { + WSACloseEvent(event_handle); + return 0; + } + + /* Wait for DNS response with timeout */ + DWORD wait_result = WaitForSingleObject(event_handle, timeout_ms); + WSACloseEvent(event_handle); + + /* Check if we timed out */ + if (wait_result == WAIT_TIMEOUT) + { + XNetDnsRelease(dns); + return 0; + } + + /* Check result and extract address */ + if (dns->iStatus == 0 && dns->cina > 0) + { + result = dns->aina[0].S_un.S_addr; + } + + XNetDnsRelease(dns); + return result; +} \ No newline at end of file diff --git a/BearSSL-OG/network_utility.h b/BearSSL-OG/network_utility.h new file mode 100644 index 0000000..ab966d6 --- /dev/null +++ b/BearSSL-OG/network_utility.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +/* Default DNS timeout in milliseconds (30 seconds) */ +#define DNS_TIMEOUT_MS 30000 + +class network_utility +{ +public: + static bool init(); + static bool is_ready(); + static bool wait_ready(); + static uint32_t resolve_host(const char* host); + static uint32_t resolve_host_with_timeout(const char* host, uint32_t timeout_ms); +}; diff --git a/BearSSL-OG/pointer_vector.h b/BearSSL-OG/pointer_vector.h new file mode 100644 index 0000000..a8c5a5a --- /dev/null +++ b/BearSSL-OG/pointer_vector.h @@ -0,0 +1,132 @@ +#pragma once + +#include +#include + +#define VECTOR_SIZE_INCREMENT 1024 + +template +class pointer_vector +{ +public: + + pointer_vector(bool useDelete) + { + mUseDelete = useDelete; + mSize = 0; + mValueContainers = (valueContainer*)malloc(sizeof(valueContainer) * VECTOR_SIZE_INCREMENT); + if (mValueContainers == NULL) + { + mMaxSize = 0; + return; + } + mMaxSize = VECTOR_SIZE_INCREMENT; + } + + ~pointer_vector() + { + for (uint32_t i = 0; i < mSize; i++) + { + if (mUseDelete == true) + { + delete(mValueContainers[i].value); + } + else + { + free(mValueContainers[i].value); + } + } + free(mValueContainers); + } + + void add(T1 value) + { + if (mSize == mMaxSize) + { + valueContainer* reallocedValueContainers = (valueContainer*)realloc(mValueContainers, sizeof(valueContainer) * (mMaxSize + VECTOR_SIZE_INCREMENT)); + if (reallocedValueContainers == NULL) + { + return; + } + mMaxSize += VECTOR_SIZE_INCREMENT; + mValueContainers = reallocedValueContainers; + } + + mValueContainers[mSize].value = value; + mSize++; + } + + T1 get(uint32_t index) + { + if (index >= mSize) + { + return NULL; + } + return mValueContainers[index].value; + } + + void remove(uint32_t index) + { + if (index >= mSize) + { + return; + } + if (mUseDelete == true) + { + delete(mValueContainers[index].value); + } + else + { + free(mValueContainers[index].value); + } + for (uint32_t j = index; j < mSize - 1; j++) + { + mValueContainers[j].value = mValueContainers[j + 1].value; + } + mSize--; + } + + void swap(uint32_t index1, uint32_t index2) + { + if (index1 >= mSize || index2 >= mSize) + { + return; + } + T1 temp = mValueContainers[index1].value; + mValueContainers[index1].value = mValueContainers[index2].value; + mValueContainers[index2].value = temp; + } + + uint32_t count() + { + return mSize; + } + + void clear() + { + for (uint32_t i = 0; i < mSize; i++) + { + if (mUseDelete == true) + { + delete(mValueContainers[i].value); + } + else + { + free(mValueContainers[i].value); + } + } + mSize = 0; + } + +private: + + typedef struct valueContainer { + T1 value; + } valueContainer; + + valueContainer* mValueContainers; + bool mUseDelete; + uint32_t mSize; + uint32_t mMaxSize; +}; + diff --git a/BearSSL-OG/server.cpp b/BearSSL-OG/server.cpp new file mode 100644 index 0000000..16a80b5 --- /dev/null +++ b/BearSSL-OG/server.cpp @@ -0,0 +1,326 @@ +#include "server.h" +#include "debug_utility.h" +#include "socket_utility.h" + +#include +#include +#include +#include +#include +#include "ssl_config.h" +#include "ssl_debug.h" + +#if !(SERVER_RSA || SERVER_EC || SERVER_MIXED) +#define SERVER_RSA 1 +#define SERVER_EC 0 +#define SERVER_MIXED 0 +#endif + +#if SERVER_RSA +#include "chain-rsa.h" +#include "key-rsa.h" +#define SKEY RSA +#elif SERVER_EC +#include "chain-ec.h" +#include "key-ec.h" +#define SKEY EC +#elif SERVER_MIXED +#include "chain-ec+rsa.h" +#include "key-ec.h" +#define SKEY EC +#else +#error Must use one of RSA, EC or MIXED chains. +#endif + + +#define MAX_NUM_THREADS 5 + +typedef struct { + int client_socket; + int thread_complete; + uint16_t port; +} thread_info_t; + +typedef struct { + int active; + thread_info_t data; + HANDLE thread; +} pthread_info_t; + +static pthread_info_t threads[MAX_NUM_THREADS]; +static volatile bool server_running = false; +static int listen_socket_global = INVALID_SOCKET; + +// Server session cache +static br_ssl_session_cache_lru server_session_cache; +static unsigned char server_session_cache_store[4096]; +static bool server_cache_initialized = false; + +static const char *HTTP_RES = + "HTTP/1.1 200 OK\r\n" + "Cache-Control: no-store, no-cache, must-revalidate\r\n" + "Pragma: no-cache\r\n" + "Expires: 0\r\n" + //"Content-Length: 46\r\n" + "Connection: close\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "\r\n" + "" + "\r\n" + "\r\n" + "

BearSSL Test by EqUiNoX

Play Doom
\r\n" + "\r\n" + "\r\n"; + +static void init_server_session_cache() +{ + if (server_cache_initialized) return; + + br_ssl_session_cache_lru_init(&server_session_cache, + server_session_cache_store, + sizeof(server_session_cache_store)); + server_cache_initialized = true; + ssl_debug::log_verbose("Server session cache initialized\n"); +} + +static void client_process(void* data) +{ + thread_info_t *thread_info = (thread_info_t*)data; + + unsigned char io_buffer[BR_SSL_BUFSIZE_BIDI]; + + br_ssl_server_context server_context; + +#if SERVER_RSA /* RSA */ +#if SERVER_PROFILE_MIN_FS +#if SERVER_CHACHA20 + br_ssl_server_init_mine2c(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#else + br_ssl_server_init_mine2g(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#endif +#elif SERVER_PROFILE_MIN_NOFS + br_ssl_server_init_minr2g(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#else + br_ssl_server_init_full_rsa(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#endif +#elif SERVER_EC /* EC */ +#if SERVER_PROFILE_MIN_FS +#if SERVER_CHACHA20 + br_ssl_server_init_minf2c(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#else + br_ssl_server_init_minf2g(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#endif +#elif SERVER_PROFILE_MIN_NOFS + br_ssl_server_init_minv2g(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#else + br_ssl_server_init_full_ec(&server_context, CHAIN, CHAIN_LEN, BR_KEYTYPE_EC, &SKEY); +#endif +#else /* SERVER_MIXED */ +#if SERVER_PROFILE_MIN_FS +#if SERVER_CHACHA20 + br_ssl_server_init_minf2c(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#else + br_ssl_server_init_minf2g(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#endif +#elif SERVER_PROFILE_MIN_NOFS + br_ssl_server_init_minu2g(&server_context, CHAIN, CHAIN_LEN, &SKEY); +#else + br_ssl_server_init_full_ec(&server_context, CHAIN, CHAIN_LEN, BR_KEYTYPE_RSA, &SKEY); +#endif +#endif + + // Enable session cache + init_server_session_cache(); + br_ssl_server_set_cache(&server_context, &server_session_cache.vtable); + + br_ssl_engine_set_buffer(&server_context.eng, io_buffer, BR_SSL_BUFSIZE_BIDI, 1); + br_ssl_server_reset(&server_context); + + // Enforce TLS 1.2 minimum +#if SSL_ENFORCE_TLS12 + br_ssl_engine_set_versions(&server_context.eng, SSL_MIN_VERSION, SSL_MAX_VERSION); +#endif + + br_sslio_context io_context; + br_sslio_init(&io_context, &server_context.eng, socket_utility::socket_read, &thread_info->client_socket, socket_utility::socket_write, &thread_info->client_socket); + + bool client_dropped = false; + + int feed_count = 0; + while (true) + { + unsigned char current_char; + if (br_sslio_read(&io_context, ¤t_char, 1) < 0) + { + client_dropped = true; + break; + } + if (current_char == 0x0D) + { + continue; + } + if (current_char == 0x0A) + { + if (feed_count == 1) + { + break; + } + feed_count = 1; + } + else + { + feed_count = 0; + } + } + + if (client_dropped == false) + { + br_sslio_write_all(&io_context, HTTP_RES, strlen(HTTP_RES)); + } + + int error = br_ssl_engine_last_error(&server_context.eng); + if (error == 0) + { + ssl_debug::log_info("Client connection closed cleanly\n"); + ssl_debug::log_handshake_result(&server_context.eng); + } + else + { + ssl_debug::log_ssl_error(error); + } + + br_sslio_close(&io_context); + closesocket(thread_info->client_socket); + + thread_info->thread_complete = 1; +} + +static uint64_t WINAPI process(void* data) +{ + uint16_t port = (uint16_t)data; + + int listen_socket = socket_utility::host_bind(port); + if (listen_socket == INVALID_SOCKET) + { + server_running = false; + return EXIT_FAILURE; + } + + listen_socket_global = listen_socket; + + while (server_running) + { + int read_status = socket_utility::get_read_status(listen_socket); + if (read_status == SOCKET_ERROR) + { + break; + } + + int client_socket = INVALID_SOCKET; + if (read_status == 1) + { + client_socket = socket_utility::accept_client(listen_socket); + } + else + { + Sleep(50); + continue; + } + + if (client_socket == INVALID_SOCKET) + { + continue; + } + + int i; + for (i = 0; i < MAX_NUM_THREADS; i++) + { + if (threads[i].active == 0) + { + break; + } + if (threads[i].data.thread_complete == 1) + { + CloseHandle(threads[i].thread); + memset(&threads[i], 0, sizeof(pthread_info_t)); + break; + } + } + + if (i == MAX_NUM_THREADS) + { + closesocket(client_socket); + continue; + } + + threads[i].active = 1; + threads[i].data.client_socket = client_socket; + threads[i].data.port = port; + threads[i].thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)client_process, (void*)&threads[i].data, 0, NULL); + } + + closesocket(listen_socket); + listen_socket_global = INVALID_SOCKET; + + return 0; +} + + +server::server() + : thread(NULL), running(false) +{ +} + +void server::start(uint16_t port) +{ + memset(threads, 0, sizeof(threads)); + running = true; + server_running = true; + thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)port, 0, NULL); +} + +void server::stop() +{ + if (!running) + { + return; + } + + running = false; + server_running = false; + + // Close the listening socket to unblock accept + if (listen_socket_global != INVALID_SOCKET) + { + closesocket(listen_socket_global); + } + + // Wait for the main server thread to finish + if (thread != NULL) + { + WaitForSingleObject(thread, 5000); + CloseHandle(thread); + thread = NULL; + } + + // Wait for all client threads to complete + for (int i = 0; i < MAX_NUM_THREADS; i++) + { + if (threads[i].active && threads[i].thread != NULL) + { + WaitForSingleObject(threads[i].thread, 2000); + CloseHandle(threads[i].thread); + } + } + + memset(threads, 0, sizeof(threads)); +} + +bool server::is_running() +{ + return running; +} + + + + diff --git a/BearSSL-OG/server.h b/BearSSL-OG/server.h new file mode 100644 index 0000000..c90a3ba --- /dev/null +++ b/BearSSL-OG/server.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +class server +{ +public: + server(); + void start(uint16_t port); + void stop(); + bool is_running(); +private: + HANDLE thread; + volatile bool running; +}; diff --git a/BearSSL-OG/session_cache.cpp b/BearSSL-OG/session_cache.cpp new file mode 100644 index 0000000..2322495 --- /dev/null +++ b/BearSSL-OG/session_cache.cpp @@ -0,0 +1,153 @@ +#include "session_cache.h" +#include "ssl_debug.h" + +#include +#include + +// KeQuerySystemTime is exported by the Xbox kernel (xboxkrnl.lib) +#ifdef __cplusplus +extern "C" +#endif +void WINAPI KeQuerySystemTime(PLARGE_INTEGER CurrentTime); + +session_cache::session_entry session_cache::entries[SESSION_CACHE_SIZE]; +bool session_cache::initialized = false; + +void session_cache::initialize() +{ + if (initialized) return; + + memset(entries, 0, sizeof(entries)); + initialized = true; + ssl_debug::log_verbose("Session cache initialized (%d slots)\n", SESSION_CACHE_SIZE); +} + +void session_cache::shutdown() +{ + clear(); + initialized = false; +} + +uint32_t session_cache::get_current_time() +{ + LARGE_INTEGER system_time; + KeQuerySystemTime(&system_time); + // Convert 100-nanosecond intervals to seconds + return (uint32_t)(system_time.QuadPart / 10000000ULL); +} + +int session_cache::find_entry(const char* hostname) +{ + for (int i = 0; i < SESSION_CACHE_SIZE; i++) { + if (entries[i].valid && strcmp(entries[i].hostname, hostname) == 0) { + return i; + } + } + return -1; +} + +int session_cache::find_free_slot() +{ + uint32_t current_time = get_current_time(); + int oldest_idx = -1; + uint32_t oldest_time = 0xFFFFFFFF; + + for (int i = 0; i < SESSION_CACHE_SIZE; i++) { + // Free slot + if (!entries[i].valid) { + return i; + } + + // Expired entry - reuse it + if (current_time - entries[i].timestamp > SESSION_MAX_AGE_SECONDS) { + entries[i].valid = false; + return i; + } + + // Track oldest for LRU eviction + if (entries[i].timestamp < oldest_time) { + oldest_time = entries[i].timestamp; + oldest_idx = i; + } + } + + // Evict oldest entry + if (oldest_idx >= 0) { + ssl_debug::log_verbose("Session cache: evicting entry for %s\n", entries[oldest_idx].hostname); + entries[oldest_idx].valid = false; + return oldest_idx; + } + + return 0; // Fallback to first slot +} + +bool session_cache::get(const char* hostname, br_ssl_session_parameters* params) +{ + if (!initialized) initialize(); + + int idx = find_entry(hostname); + if (idx < 0) { + ssl_debug::log_verbose("Session cache: miss for %s\n", hostname); + return false; + } + + uint32_t current_time = get_current_time(); + if (current_time - entries[idx].timestamp > SESSION_MAX_AGE_SECONDS) { + ssl_debug::log_verbose("Session cache: expired entry for %s\n", hostname); + entries[idx].valid = false; + return false; + } + + /* Update timestamp on access for proper LRU eviction */ + entries[idx].timestamp = current_time; + memcpy(params, &entries[idx].params, sizeof(br_ssl_session_parameters)); + ssl_debug::log_info("Session cache: hit for %s\n", hostname); + return true; +} + +void session_cache::store(const char* hostname, const br_ssl_session_parameters* params) +{ + if (!initialized) initialize(); + + // Don't cache if no session ID and no session ticket + if (params->session_id_len == 0 && params->session_ticket_len == 0) { + return; + } + + int idx = find_entry(hostname); + if (idx < 0) { + idx = find_free_slot(); + } + + strncpy(entries[idx].hostname, hostname, 255); + entries[idx].hostname[255] = '\0'; + memcpy(&entries[idx].params, params, sizeof(br_ssl_session_parameters)); + entries[idx].timestamp = get_current_time(); + entries[idx].valid = true; + + ssl_debug::log_info("Session cache: stored session for %s\n", hostname); +} + +void session_cache::remove(const char* hostname) +{ + int idx = find_entry(hostname); + if (idx >= 0) { + entries[idx].valid = false; + ssl_debug::log_verbose("Session cache: removed entry for %s\n", hostname); + } +} + +void session_cache::clear() +{ + memset(entries, 0, sizeof(entries)); + ssl_debug::log_verbose("Session cache: cleared\n"); +} + +int session_cache::get_count() +{ + int count = 0; + for (int i = 0; i < SESSION_CACHE_SIZE; i++) { + if (entries[i].valid) count++; + } + return count; +} diff --git a/BearSSL-OG/session_cache.h b/BearSSL-OG/session_cache.h new file mode 100644 index 0000000..3411892 --- /dev/null +++ b/BearSSL-OG/session_cache.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#define SESSION_CACHE_SIZE 8 +#define SESSION_MAX_AGE_SECONDS 3600 + +class session_cache +{ +public: + static void initialize(); + static void shutdown(); + + static bool get(const char* hostname, br_ssl_session_parameters* params); + static void store(const char* hostname, const br_ssl_session_parameters* params); + static void remove(const char* hostname); + static void clear(); + + static int get_count(); + +private: + struct session_entry { + char hostname[256]; + br_ssl_session_parameters params; + uint32_t timestamp; + bool valid; + }; + + static session_entry entries[SESSION_CACHE_SIZE]; + static bool initialized; + + static int find_entry(const char* hostname); + static int find_free_slot(); + static uint32_t get_current_time(); +}; diff --git a/BearSSL-OG/socket_utility.cpp b/BearSSL-OG/socket_utility.cpp new file mode 100644 index 0000000..1a4120f --- /dev/null +++ b/BearSSL-OG/socket_utility.cpp @@ -0,0 +1,160 @@ +#include "socket_utility.h" + +#include +#include +#include + +int socket_utility::connect_to_host(uint32_t host_ip, uint16_t port) +{ + sockaddr_in server_addr; + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + server_addr.sin_addr.S_un.S_addr = host_ip; + + int32_t connect_socket = socket(AF_INET, SOCK_STREAM, 0); + if (connect_socket == INVALID_SOCKET) + { + return -1; + } + + if (connect(connect_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) + { + closesocket(connect_socket); + return -1; + } + + return connect_socket; +} + +int socket_utility::host_bind(uint16_t port) +{ + int32_t bind_socket = socket(AF_INET, SOCK_STREAM, 0); + if (bind_socket == INVALID_SOCKET) + { + return -1; + } + + uint32_t reuse = 1; + if (setsockopt(bind_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0) + { + closesocket(bind_socket); + return -1; + } + + uint32_t non_blocking = 1; + if (ioctlsocket((SOCKET)bind_socket, FIONBIO, &non_blocking) == SOCKET_ERROR) + { + closesocket(bind_socket); + return -1; + } + + SOCKADDR_IN address_in; + memset(&address_in, 0, sizeof(SOCKADDR_IN)); + address_in.sin_addr.s_addr = INADDR_ANY; + address_in.sin_family = AF_INET; + address_in.sin_port = htons(port); + + if (bind(bind_socket, (struct sockaddr *)&address_in, sizeof(address_in)) == SOCKET_ERROR) + { + closesocket(bind_socket); + return -1; + } + + if (listen(bind_socket, 5) < 0) + { + closesocket(bind_socket); + return -1; + } + + return bind_socket; +} + +int socket_utility::get_read_status(int socket) +{ + static const timeval instantSpeedPlease = { 0,0 }; + fd_set a = { 1, {(SOCKET)socket} }; + + int result = select(0, &a, 0, 0, &instantSpeedPlease); + if (result == SOCKET_ERROR) + { + result = WSAGetLastError(); + } + + if (result != 0 && result != 1) + { + return SOCKET_ERROR; + } + return result; +} + +int socket_utility::accept_client(int server_socket) +{ + sockaddr sock_addr; + int sock_addr_length = sizeof(sock_addr); + int32_t socket = accept(server_socket, &sock_addr, &sock_addr_length); + if (socket == INVALID_SOCKET) + { + return -1; + } + return socket; +} + +int socket_utility::socket_read(void *context, unsigned char *buffer, size_t length) +{ + int socket = *(int *)context; + + struct timeval tv; + fd_set read_fds; + + + while (true) + { + FD_ZERO(&read_fds ); + FD_SET(socket, &read_fds ); + + tv.tv_sec = 2; + tv.tv_usec = 0; + + int ret = select(socket, &read_fds, NULL, NULL, &tv ); + if( ret == 0 ) + { + return -1; + } + + int recv_len = (length > 0x7FFFFFFF) ? 0x7FFFFFFF : (int)length; + int bytes_read = recv(socket, (char *)buffer, recv_len, 0); + if (bytes_read == SOCKET_ERROR) + { + if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK) + { + continue; + } + return -1; + } + if (bytes_read == 0) + { + return 0; + } + return bytes_read; + } +} + +int socket_utility::socket_write(void *context, const unsigned char *buffer, size_t length) +{ + while (true) + { + int socket = *(int *)context; + int send_len = (length > 0x7FFFFFFF) ? 0x7FFFFFFF : (int)length; + int bytes_written = send(socket, (const char *)buffer, send_len, 0); + if (bytes_written == SOCKET_ERROR) + { + if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK) + { + continue; + } + return -1; + } + return bytes_written; + } +} \ No newline at end of file diff --git a/BearSSL-OG/socket_utility.h b/BearSSL-OG/socket_utility.h new file mode 100644 index 0000000..9f98652 --- /dev/null +++ b/BearSSL-OG/socket_utility.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +class socket_utility +{ +public: + static int connect_to_host(uint32_t host_ip, uint16_t port); + static int host_bind(uint16_t port); + static int get_read_status(int socket); + static int accept_client(int server_socket); + static int socket_read(void *context, unsigned char *buffer, size_t length); + static int socket_write(void *context, const unsigned char *buffer, size_t length); +}; diff --git a/BearSSL-OG/ssl_config.h b/BearSSL-OG/ssl_config.h new file mode 100644 index 0000000..8678c9b --- /dev/null +++ b/BearSSL-OG/ssl_config.h @@ -0,0 +1,30 @@ +#pragma once + +// TLS Version Configuration +#define SSL_MIN_VERSION BR_TLS12 +#define SSL_MAX_VERSION BR_TLS12 + +// Secure cipher suites (ECDHE + AEAD only) +static const uint16_t SSL_SECURE_SUITES[] = { + BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +}; + +#define SSL_SECURE_SUITES_COUNT 6 + +// Feature flags +#define SSL_ENFORCE_TLS12 1 +#define SSL_RESTRICT_CIPHERS 1 +#define SSL_ENABLE_SESSION_CACHE 1 + +// Set to 1 to enable certificate pinning verification +#define SSL_ENABLE_CERT_PINNING 0 + +// Default CA bundle file path on Xbox HDD +// T:\ maps to E:\TDATA\\ (title-persistent storage) +// Place cacert.pem at E:\TDATA\\cacert.pem on the Xbox HDD +#define SSL_DEFAULT_CA_FILE "T:\\cacert.pem" diff --git a/BearSSL-OG/ssl_debug.cpp b/BearSSL-OG/ssl_debug.cpp new file mode 100644 index 0000000..569437d --- /dev/null +++ b/BearSSL-OG/ssl_debug.cpp @@ -0,0 +1,147 @@ +#include "ssl_debug.h" +#include "ssl_errors.h" +#include "debug_utility.h" + +#include +#include +#include + +ssl_debug_level ssl_debug::current_level = SSL_DEBUG_ERROR; + +void ssl_debug::set_level(ssl_debug_level level) +{ + current_level = level; +} + +ssl_debug_level ssl_debug::get_level() +{ + return current_level; +} + +void ssl_debug::log_error(const char* format, ...) +{ + if (current_level < SSL_DEBUG_ERROR) return; + + debug_utility::debug_print("[SSL ERROR] "); + va_list args; + va_start(args, format); + char buffer[256]; + _vsnprintf(buffer, sizeof(buffer) - 1, format, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + debug_utility::debug_print("%s", buffer); +} + +void ssl_debug::log_info(const char* format, ...) +{ + if (current_level < SSL_DEBUG_INFO) return; + + debug_utility::debug_print("[SSL] "); + va_list args; + va_start(args, format); + char buffer[256]; + _vsnprintf(buffer, sizeof(buffer) - 1, format, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + debug_utility::debug_print("%s", buffer); +} + +void ssl_debug::log_verbose(const char* format, ...) +{ + if (current_level < SSL_DEBUG_VERBOSE) return; + + debug_utility::debug_print("[SSL DEBUG] "); + va_list args; + va_start(args, format); + char buffer[256]; + _vsnprintf(buffer, sizeof(buffer) - 1, format, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + debug_utility::debug_print("%s", buffer); +} + +const char* ssl_debug::version_to_string(unsigned version) +{ + switch (version) { + case BR_TLS10: return "TLS 1.0"; + case BR_TLS11: return "TLS 1.1"; + case BR_TLS12: return "TLS 1.2"; + default: return "Unknown"; + } +} + +const char* ssl_debug::cipher_suite_to_string(uint16_t suite) +{ + switch (suite) { + case BR_TLS_RSA_WITH_AES_128_CBC_SHA: + return "RSA-AES128-CBC-SHA"; + case BR_TLS_RSA_WITH_AES_256_CBC_SHA: + return "RSA-AES256-CBC-SHA"; + case BR_TLS_RSA_WITH_AES_128_CBC_SHA256: + return "RSA-AES128-CBC-SHA256"; + case BR_TLS_RSA_WITH_AES_256_CBC_SHA256: + return "RSA-AES256-CBC-SHA256"; + case BR_TLS_RSA_WITH_AES_128_GCM_SHA256: + return "RSA-AES128-GCM-SHA256"; + case BR_TLS_RSA_WITH_AES_256_GCM_SHA384: + return "RSA-AES256-GCM-SHA384"; + case BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "ECDHE-RSA-AES128-CBC-SHA"; + case BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "ECDHE-RSA-AES256-CBC-SHA"; + case BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return "ECDHE-RSA-AES128-CBC-SHA256"; + case BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return "ECDHE-RSA-AES256-CBC-SHA384"; + case BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + return "ECDHE-RSA-AES128-GCM-SHA256"; + case BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + return "ECDHE-RSA-AES256-GCM-SHA384"; + case BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return "ECDHE-RSA-CHACHA20-POLY1305"; + case BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + return "ECDHE-ECDSA-AES128-GCM-SHA256"; + case BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return "ECDHE-ECDSA-AES256-GCM-SHA384"; + case BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + return "ECDHE-ECDSA-CHACHA20-POLY1305"; + default: + return "Unknown"; + } +} + +void ssl_debug::log_handshake_result(br_ssl_engine_context* engine) +{ + if (current_level < SSL_DEBUG_INFO) return; + + unsigned version = br_ssl_engine_get_version(engine); + log_info("Handshake complete\n"); + log_info(" Version: %s\n", version_to_string(version)); + + br_ssl_session_parameters params; + br_ssl_engine_get_session_parameters(engine, ¶ms); + log_info(" Cipher: %s\n", cipher_suite_to_string(params.cipher_suite)); + log_info(" Session resumed: %s\n", params.session_id_len > 0 ? "yes" : "no"); +} + +void ssl_debug::log_ssl_error(int error) +{ + if (error == 0) return; + + log_error("SSL error %d: %s\n", error, ssl_errors::error_to_string(error)); + + if (error >= 256 && error < 512) { + int alert = error - 256; + log_error(" Alert: %s\n", ssl_errors::alert_to_string(alert)); + } +} + +void ssl_debug::log_peer_certificate(br_ssl_engine_context* engine) +{ + // Note: BearSSL does not provide a direct API to retrieve the peer certificate + // chain after handshake completion. Certificate inspection would require + // custom X.509 callbacks during validation. This function is a placeholder. + if (current_level < SSL_DEBUG_VERBOSE) return; + log_verbose("Certificate inspection not available (requires X.509 callback)\n"); + (void)engine; // Suppress unused parameter warning +} diff --git a/BearSSL-OG/ssl_debug.h b/BearSSL-OG/ssl_debug.h new file mode 100644 index 0000000..a3541ac --- /dev/null +++ b/BearSSL-OG/ssl_debug.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +enum ssl_debug_level { + SSL_DEBUG_NONE = 0, + SSL_DEBUG_ERROR = 1, + SSL_DEBUG_INFO = 2, + SSL_DEBUG_VERBOSE = 3 +}; + +class ssl_debug +{ +public: + static void set_level(ssl_debug_level level); + static ssl_debug_level get_level(); + + static void log_error(const char* format, ...); + static void log_info(const char* format, ...); + static void log_verbose(const char* format, ...); + + static void log_handshake_result(br_ssl_engine_context* engine); + static void log_ssl_error(int error); + static void log_peer_certificate(br_ssl_engine_context* engine); + + static const char* version_to_string(unsigned version); + static const char* cipher_suite_to_string(uint16_t suite); + +private: + static ssl_debug_level current_level; +}; diff --git a/BearSSL-OG/ssl_errors.cpp b/BearSSL-OG/ssl_errors.cpp new file mode 100644 index 0000000..a72a52c --- /dev/null +++ b/BearSSL-OG/ssl_errors.cpp @@ -0,0 +1,73 @@ +#include "ssl_errors.h" +#include + +const char* ssl_errors::error_to_string(int error) +{ + switch (error) { + case BR_ERR_OK: return "Success"; + case BR_ERR_BAD_PARAM: return "Bad parameter"; + case BR_ERR_BAD_STATE: return "Invalid state"; + case BR_ERR_UNSUPPORTED_VERSION: return "Unsupported TLS version"; + case BR_ERR_BAD_VERSION: return "Bad TLS version"; + case BR_ERR_TOO_LARGE: return "Record too large"; + case BR_ERR_BAD_MAC: return "MAC verification failed"; + case BR_ERR_NO_RANDOM: return "No random seed"; + case BR_ERR_UNKNOWN_TYPE: return "Unknown record type"; + case BR_ERR_UNEXPECTED: return "Unexpected message"; + case BR_ERR_BAD_CCS: return "Bad ChangeCipherSpec"; + case BR_ERR_BAD_ALERT: return "Bad alert"; + case BR_ERR_BAD_HANDSHAKE: return "Bad handshake message"; + case BR_ERR_OVERSIZED_ID: return "Oversized ID"; + case BR_ERR_BAD_CIPHER_SUITE: return "Bad cipher suite"; + case BR_ERR_BAD_COMPRESSION: return "Bad compression"; + case BR_ERR_BAD_FRAGLEN: return "Bad fragment length"; + case BR_ERR_BAD_SECRENEG: return "Bad secure renegotiation"; + case BR_ERR_EXTRA_EXTENSION: return "Extra extension"; + case BR_ERR_BAD_SNI: return "Bad SNI"; + case BR_ERR_BAD_HELLO_DONE: return "Bad HelloDone"; + case BR_ERR_LIMIT_EXCEEDED: return "Limit exceeded"; + case BR_ERR_BAD_FINISHED: return "Bad Finished message"; + case BR_ERR_RESUME_MISMATCH: return "Session resume mismatch"; + case BR_ERR_INVALID_ALGORITHM: return "Invalid algorithm"; + case BR_ERR_BAD_SIGNATURE: return "Bad signature"; + case BR_ERR_WRONG_KEY_USAGE: return "Wrong key usage"; + case BR_ERR_NO_CLIENT_AUTH: return "No client auth"; + case BR_ERR_IO: return "I/O error"; + default: + if (error >= 256 && error < 512) + return "Received fatal alert from server"; + if (error >= 512) + return "Sent fatal alert to server"; + return "Unknown SSL error"; + } +} + +const char* ssl_errors::alert_to_string(int alert_code) +{ + switch (alert_code) { + case 0: return "close_notify"; + case 10: return "unexpected_message"; + case 20: return "bad_record_mac"; + case 21: return "decryption_failed"; + case 22: return "record_overflow"; + case 30: return "decompression_failure"; + case 40: return "handshake_failure"; + case 42: return "bad_certificate"; + case 43: return "unsupported_certificate"; + case 44: return "certificate_revoked"; + case 45: return "certificate_expired"; + case 46: return "certificate_unknown"; + case 47: return "illegal_parameter"; + case 48: return "unknown_ca"; + case 49: return "access_denied"; + case 50: return "decode_error"; + case 51: return "decrypt_error"; + case 70: return "protocol_version"; + case 71: return "insufficient_security"; + case 80: return "internal_error"; + case 90: return "user_canceled"; + case 100: return "no_renegotiation"; + case 110: return "unsupported_extension"; + default: return "unknown_alert"; + } +} diff --git a/BearSSL-OG/ssl_errors.h b/BearSSL-OG/ssl_errors.h new file mode 100644 index 0000000..d764b85 --- /dev/null +++ b/BearSSL-OG/ssl_errors.h @@ -0,0 +1,8 @@ +#pragma once + +class ssl_errors +{ +public: + static const char* error_to_string(int error); + static const char* alert_to_string(int alert_code); +}; diff --git a/BearSSL-OG/ssl_test.cpp b/BearSSL-OG/ssl_test.cpp new file mode 100644 index 0000000..a56e708 --- /dev/null +++ b/BearSSL-OG/ssl_test.cpp @@ -0,0 +1,574 @@ +#include "ssl_test.h" +#include "client.h" +#include "ssl_debug.h" +#include "session_cache.h" +#include "debug_utility.h" + +#include +#include +#include + +// KeQuerySystemTime is exported by the Xbox kernel (xboxkrnl.lib) +#ifdef __cplusplus +extern "C" +#endif +void WINAPI KeQuerySystemTime(PLARGE_INTEGER CurrentTime); + +// Test file paths on Xbox E: drive +#define TEST_FILE_SMALL "E:\\ssl_test_small.bin" +#define TEST_FILE_LARGE "E:\\ssl_test_large.bin" +#define TEST_FILE_REDIRECT "E:\\ssl_test_redirect.bin" +#define TEST_FILE_CHUNKED "E:\\ssl_test_chunked.bin" +#define TEST_FILE_RESUME "E:\\ssl_test_resume.bin" + +// Test URLs - using reliable public HTTPS endpoints +// Small file test - GitHub raw file +#define URL_SMALL "https://raw.githubusercontent.com/AbanteAI/rawdog/main/README.md" + +// Larger file test - Known firmware download +#define URL_LARGE "https://codeload.github.com/Team-Resurgent/PrometheOS-Firmware/zip/refs/tags/V1.5.0" + +// Redirect test - GitHub releases redirect +#define URL_REDIRECT "https://github.com/Team-Resurgent/Modxo/releases/download/V1.0.8/modxo_official_pico.bin" + +// Chunked transfer test - use httpbin which returns chunked encoding +#define URL_CHUNKED "https://httpbin.org/stream/5" + +// Alternate host test - non-GitHub server +#define URL_ALTERNATE "https://httpbin.org/get" +#define TEST_FILE_ALTERNATE "E:\\ssl_test_alternate.bin" + +uint32_t ssl_test::get_time_ms() +{ + LARGE_INTEGER system_time; + KeQuerySystemTime(&system_time); + return (uint32_t)(system_time.QuadPart / 10000ULL); +} + +bool ssl_test::file_exists(const char* path) +{ + FILE* f = fopen(path, "rb"); + if (f != NULL) { + fclose(f); + return true; + } + return false; +} + +int64_t ssl_test::get_file_size(const char* path) +{ + FILE* f = fopen(path, "rb"); + if (f == NULL) return -1; + + fseek(f, 0, SEEK_END); + int64_t size = ftell(f); + fclose(f); + return size; +} + +void ssl_test::delete_file(const char* path) +{ + DeleteFile(path); +} + +void ssl_test::print_result(const ssl_test_result& result) +{ + const char* status; + switch (result.result) { + case SSL_TEST_PASS: status = "PASS"; break; + case SSL_TEST_FAIL: status = "FAIL"; break; + case SSL_TEST_SKIP: status = "SKIP"; break; + default: status = "????"; break; + } + + debug_utility::debug_print("\n[%s] %s\n", status, result.test_name); + + if (result.message != NULL && result.message[0] != '\0') { + debug_utility::debug_print(" %s\n", result.message); + } + + if (result.bytes_downloaded > 0) { + debug_utility::debug_print(" Downloaded: %lld bytes\n", result.bytes_downloaded); + } + + if (result.time_ms > 0) { + debug_utility::debug_print(" Time: %u ms\n", result.time_ms); + } +} + +void ssl_test::print_summary(int passed, int failed, int skipped) +{ + debug_utility::debug_print("\n"); + debug_utility::debug_print("==========================================\n"); + debug_utility::debug_print("SSL TEST SUMMARY\n"); + debug_utility::debug_print("==========================================\n"); + debug_utility::debug_print("Passed: %d\n", passed); + debug_utility::debug_print("Failed: %d\n", failed); + debug_utility::debug_print("Skipped: %d\n", skipped); + debug_utility::debug_print("Total: %d\n", passed + failed + skipped); + debug_utility::debug_print("==========================================\n"); + + if (failed == 0) { + debug_utility::debug_print("ALL TESTS PASSED!\n"); + } else { + debug_utility::debug_print("SOME TESTS FAILED - check results above\n"); + } + debug_utility::debug_print("==========================================\n"); +} + +// ============================================================================= +// TEST: Basic HTTPS Connection +// ============================================================================= +ssl_test_result ssl_test::test_basic_https_connection() +{ + ssl_test_result result; + result.test_name = "Basic HTTPS Connection"; + result.message = ""; + result.bytes_downloaded = 0; + result.time_ms = 0; + + debug_utility::debug_print("\n--- Running: %s ---\n", result.test_name); + + // Clean up any previous test file + delete_file(TEST_FILE_SMALL); + + // Set debug level to see handshake info + ssl_debug::set_level(SSL_DEBUG_INFO); + + uint32_t start_time = get_time_ms(); + + client* c = new client(); + int ret = c->download_file(URL_SMALL, 443, TEST_FILE_SMALL); + delete c; + + result.time_ms = get_time_ms() - start_time; + + if (ret == 0) { + if (file_exists(TEST_FILE_SMALL)) { + result.bytes_downloaded = get_file_size(TEST_FILE_SMALL); + if (result.bytes_downloaded > 0) { + result.result = SSL_TEST_PASS; + result.message = "Successfully connected and downloaded file"; + } else { + result.result = SSL_TEST_FAIL; + result.message = "File created but empty"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "Download returned success but file not found"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "Download failed - check SSL debug output above"; + } + + // Clean up + delete_file(TEST_FILE_SMALL); + + return result; +} + +// ============================================================================= +// TEST: Large File Download +// ============================================================================= +ssl_test_result ssl_test::test_large_file_download() +{ + ssl_test_result result; + result.test_name = "Large File Download (PrometheOS zip)"; + result.message = ""; + result.bytes_downloaded = 0; + result.time_ms = 0; + + debug_utility::debug_print("\n--- Running: %s ---\n", result.test_name); + + delete_file(TEST_FILE_LARGE); + + ssl_debug::set_level(SSL_DEBUG_INFO); + + uint32_t start_time = get_time_ms(); + + client* c = new client(); + int ret = c->download_file(URL_LARGE, 443, TEST_FILE_LARGE); + delete c; + + result.time_ms = get_time_ms() - start_time; + + if (ret == 0) { + if (file_exists(TEST_FILE_LARGE)) { + result.bytes_downloaded = get_file_size(TEST_FILE_LARGE); + // PrometheOS zip should be at least 100KB + if (result.bytes_downloaded > 100000) { + result.result = SSL_TEST_PASS; + result.message = "Large file downloaded successfully"; + } else { + result.result = SSL_TEST_FAIL; + result.message = "File too small - possible incomplete download"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "File not created"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "Download failed"; + } + + delete_file(TEST_FILE_LARGE); + + return result; +} + +// ============================================================================= +// TEST: Redirect Handling +// ============================================================================= +ssl_test_result ssl_test::test_redirect_handling() +{ + ssl_test_result result; + result.test_name = "HTTP Redirect Handling"; + result.message = ""; + result.bytes_downloaded = 0; + result.time_ms = 0; + + debug_utility::debug_print("\n--- Running: %s ---\n", result.test_name); + + delete_file(TEST_FILE_REDIRECT); + + ssl_debug::set_level(SSL_DEBUG_INFO); + + uint32_t start_time = get_time_ms(); + + client* c = new client(); + int ret = c->download_file(URL_REDIRECT, 443, TEST_FILE_REDIRECT); + delete c; + + result.time_ms = get_time_ms() - start_time; + + if (ret == 0) { + if (file_exists(TEST_FILE_REDIRECT)) { + result.bytes_downloaded = get_file_size(TEST_FILE_REDIRECT); + if (result.bytes_downloaded > 0) { + result.result = SSL_TEST_PASS; + result.message = "Redirect followed and file downloaded"; + } else { + result.result = SSL_TEST_FAIL; + result.message = "File empty after redirect"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "File not created after redirect"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "Download with redirect failed"; + } + + delete_file(TEST_FILE_REDIRECT); + + return result; +} + +// ============================================================================= +// TEST: Chunked Transfer Encoding +// ============================================================================= +ssl_test_result ssl_test::test_chunked_transfer() +{ + ssl_test_result result; + result.test_name = "Chunked Transfer Encoding"; + result.message = ""; + result.bytes_downloaded = 0; + result.time_ms = 0; + + debug_utility::debug_print("\n--- Running: %s ---\n", result.test_name); + + delete_file(TEST_FILE_CHUNKED); + + ssl_debug::set_level(SSL_DEBUG_INFO); + + uint32_t start_time = get_time_ms(); + + client* c = new client(); + int ret = c->download_file(URL_CHUNKED, 443, TEST_FILE_CHUNKED); + delete c; + + result.time_ms = get_time_ms() - start_time; + + if (ret == 0) { + if (file_exists(TEST_FILE_CHUNKED)) { + result.bytes_downloaded = get_file_size(TEST_FILE_CHUNKED); + if (result.bytes_downloaded > 0) { + result.result = SSL_TEST_PASS; + result.message = "Chunked transfer handled correctly"; + } else { + result.result = SSL_TEST_FAIL; + result.message = "File empty"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "File not created"; + } + } else { + // Chunked might fail gracefully with some servers + result.result = SSL_TEST_FAIL; + result.message = "Chunked download failed"; + } + + delete_file(TEST_FILE_CHUNKED); + + return result; +} + +// ============================================================================= +// TEST: Session Resumption +// ============================================================================= +ssl_test_result ssl_test::test_session_resumption() +{ + ssl_test_result result; + result.test_name = "TLS Session Resumption"; + result.message = ""; + result.bytes_downloaded = 0; + result.time_ms = 0; + + debug_utility::debug_print("\n--- Running: %s ---\n", result.test_name); + + // Clear session cache first + session_cache::clear(); + + ssl_debug::set_level(SSL_DEBUG_INFO); + + delete_file(TEST_FILE_RESUME); + + // First connection - should establish new session + debug_utility::debug_print("First connection (new session)...\n"); + uint32_t start1 = get_time_ms(); + + client* c1 = new client(); + int ret1 = c1->download_file(URL_SMALL, 443, TEST_FILE_RESUME); + delete c1; + + uint32_t time1 = get_time_ms() - start1; + + if (ret1 != 0) { + result.result = SSL_TEST_FAIL; + result.message = "First connection failed"; + return result; + } + + // Check if session was cached + int cache_count = session_cache::get_count(); + debug_utility::debug_print("Sessions in cache: %d\n", cache_count); + + delete_file(TEST_FILE_RESUME); + + // Second connection - should resume session + debug_utility::debug_print("Second connection (should resume)...\n"); + uint32_t start2 = get_time_ms(); + + client* c2 = new client(); + int ret2 = c2->download_file(URL_SMALL, 443, TEST_FILE_RESUME); + delete c2; + + uint32_t time2 = get_time_ms() - start2; + + result.time_ms = time1 + time2; + + if (ret2 == 0) { + result.bytes_downloaded = get_file_size(TEST_FILE_RESUME); + + // Session resumption should make second connection faster + // (though this is not guaranteed due to network variability) + debug_utility::debug_print("First connection: %u ms\n", time1); + debug_utility::debug_print("Second connection: %u ms\n", time2); + + if (cache_count > 0) { + result.result = SSL_TEST_PASS; + result.message = "Session cached and second connection succeeded"; + } else { + result.result = SSL_TEST_PASS; + result.message = "Connections succeeded (server may not support resumption)"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "Second connection failed"; + } + + delete_file(TEST_FILE_RESUME); + + return result; +} + +// ============================================================================= +// TEST: Invalid Host (Error Handling) +// ============================================================================= +ssl_test_result ssl_test::test_invalid_host() +{ + ssl_test_result result; + result.test_name = "Invalid Host Error Handling"; + result.message = ""; + result.bytes_downloaded = 0; + result.time_ms = 0; + + debug_utility::debug_print("\n--- Running: %s ---\n", result.test_name); + + ssl_debug::set_level(SSL_DEBUG_ERROR); + + uint32_t start_time = get_time_ms(); + + // Try to connect to a non-existent host + client* c = new client(); + int ret = c->download_file("https://this-host-does-not-exist-12345.invalid/test.bin", 443, "E:\\invalid.bin"); + delete c; + + result.time_ms = get_time_ms() - start_time; + + // This SHOULD fail - that's what we're testing + if (ret != 0) { + result.result = SSL_TEST_PASS; + result.message = "Correctly failed on invalid host"; + } else { + result.result = SSL_TEST_FAIL; + result.message = "Should have failed but returned success"; + } + + delete_file("E:\\invalid.bin"); + + return result; +} + +// ============================================================================= +// TEST: TLS Version Enforcement +// ============================================================================= +ssl_test_result ssl_test::test_tls_version_enforcement() +{ + ssl_test_result result; + result.test_name = "TLS 1.2 Enforcement"; + result.message = ""; + result.bytes_downloaded = 0; + result.time_ms = 0; + + debug_utility::debug_print("\n--- Running: %s ---\n", result.test_name); + + // This test verifies that connections work with TLS 1.2 + // Most modern servers support TLS 1.2, so if our enforcement is correct, + // connections should succeed. If we had wrongly configured TLS 1.0 only, + // modern servers might reject us. + + ssl_debug::set_level(SSL_DEBUG_INFO); + + delete_file(TEST_FILE_SMALL); + + uint32_t start_time = get_time_ms(); + + client* c = new client(); + int ret = c->download_file(URL_SMALL, 443, TEST_FILE_SMALL); + delete c; + + result.time_ms = get_time_ms() - start_time; + + if (ret == 0 && file_exists(TEST_FILE_SMALL)) { + result.bytes_downloaded = get_file_size(TEST_FILE_SMALL); + result.result = SSL_TEST_PASS; + result.message = "TLS 1.2 connection successful (check log for version)"; + } else { + result.result = SSL_TEST_FAIL; + result.message = "TLS 1.2 connection failed - check cipher/version compatibility"; + } + + delete_file(TEST_FILE_SMALL); + + return result; +} + +// ============================================================================= +// TEST: Alternate Host Connection +// ============================================================================= +ssl_test_result ssl_test::test_alternate_host() +{ + ssl_test_result result; + result.test_name = "Alternate Host (httpbin.org)"; + result.message = ""; + result.bytes_downloaded = 0; + result.time_ms = 0; + + debug_utility::debug_print("\n--- Running: %s ---\n", result.test_name); + + delete_file(TEST_FILE_ALTERNATE); + + ssl_debug::set_level(SSL_DEBUG_INFO); + + uint32_t start_time = get_time_ms(); + + client* c = new client(); + int ret = c->download_file(URL_ALTERNATE, 443, TEST_FILE_ALTERNATE); + delete c; + + result.time_ms = get_time_ms() - start_time; + + if (ret == 0) { + if (file_exists(TEST_FILE_ALTERNATE)) { + result.bytes_downloaded = get_file_size(TEST_FILE_ALTERNATE); + if (result.bytes_downloaded > 0) { + result.result = SSL_TEST_PASS; + result.message = "Non-GitHub host connection successful"; + } else { + result.result = SSL_TEST_FAIL; + result.message = "File created but empty"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "File not created"; + } + } else { + result.result = SSL_TEST_FAIL; + result.message = "Connection to alternate host failed"; + } + + delete_file(TEST_FILE_ALTERNATE); + + return result; +} + +// ============================================================================= +// RUN ALL TESTS +// ============================================================================= +int ssl_test::run_all_tests() +{ + debug_utility::debug_print("\n"); + debug_utility::debug_print("==========================================\n"); + debug_utility::debug_print("BearSSL-OG SSL/TLS TEST SUITE\n"); + debug_utility::debug_print("==========================================\n"); + debug_utility::debug_print("Testing HTTPS client functionality after\n"); + debug_utility::debug_print("SSL enhancements (TLS 1.2, ciphers, etc.)\n"); + debug_utility::debug_print("==========================================\n"); + + int passed = 0; + int failed = 0; + int skipped = 0; + + ssl_test_result results[8]; + + // Run all tests + results[0] = test_basic_https_connection(); + results[1] = test_tls_version_enforcement(); + results[2] = test_session_resumption(); + results[3] = test_redirect_handling(); + results[4] = test_chunked_transfer(); + results[5] = test_alternate_host(); + results[6] = test_invalid_host(); + results[7] = test_large_file_download(); + + // Print results and count + for (int i = 0; i < 8; i++) { + print_result(results[i]); + + switch (results[i].result) { + case SSL_TEST_PASS: passed++; break; + case SSL_TEST_FAIL: failed++; break; + case SSL_TEST_SKIP: skipped++; break; + } + } + + // Print summary + print_summary(passed, failed, skipped); + + return failed; +} diff --git a/BearSSL-OG/ssl_test.h b/BearSSL-OG/ssl_test.h new file mode 100644 index 0000000..4c22f3f --- /dev/null +++ b/BearSSL-OG/ssl_test.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +// Test result codes +#define SSL_TEST_PASS 0 +#define SSL_TEST_FAIL 1 +#define SSL_TEST_SKIP 2 + +// Test result structure +struct ssl_test_result { + const char* test_name; + int result; + const char* message; + int64_t bytes_downloaded; + uint32_t time_ms; +}; + +class ssl_test +{ +public: + // Run all tests and print summary + static int run_all_tests(); + + // Individual tests + static ssl_test_result test_basic_https_connection(); + static ssl_test_result test_large_file_download(); + static ssl_test_result test_redirect_handling(); + static ssl_test_result test_chunked_transfer(); + static ssl_test_result test_session_resumption(); + static ssl_test_result test_invalid_host(); + static ssl_test_result test_tls_version_enforcement(); + static ssl_test_result test_alternate_host(); + + // Utility + static void print_result(const ssl_test_result& result); + static void print_summary(int passed, int failed, int skipped); + +private: + static uint32_t get_time_ms(); + static bool file_exists(const char* path); + static int64_t get_file_size(const char* path); + static void delete_file(const char* path); +}; diff --git a/BearSSL-OG/stdafx.cpp b/BearSSL-OG/stdafx.cpp new file mode 100644 index 0000000..e73396f --- /dev/null +++ b/BearSSL-OG/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// XboxOGBearSSL.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/BearSSL-OG/stdafx.h b/BearSSL-OG/stdafx.h new file mode 100644 index 0000000..0454862 --- /dev/null +++ b/BearSSL-OG/stdafx.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +typedef struct STRING { + uint16_t Length; + uint16_t MaximumLength; + char* Buffer; +} STRING; + +extern "C" +{ + LONG WINAPI IoCreateSymbolicLink(STRING*, STRING*); +} diff --git a/BearSSL-OG/string_utility.cpp b/BearSSL-OG/string_utility.cpp new file mode 100644 index 0000000..842e356 --- /dev/null +++ b/BearSSL-OG/string_utility.cpp @@ -0,0 +1,239 @@ +#include "string_utility.h" +#include "pointer_vector.h" + +#include +#include +#include + +/* MSVC 7.1 lacks va_copy. On x86, va_list is a char* passed by value, + so a plain assignment creates an independent copy. */ +#ifndef va_copy +#define va_copy(dest, src) ((dest) = (src)) +#endif + +char* string_utility::format_string(const char* format, ...) +{ + va_list args, args_copy; + va_start(args, format); + va_copy(args_copy, args); + + uint32_t length = _vsnprintf(NULL, 0, format, args_copy); + va_end(args_copy); + + char* result = (char*)malloc(length + 1); + if (result == NULL) + { + va_end(args); + return NULL; + } + _vsnprintf(result, length + 1, format, args); + result[length] = 0; + + va_end(args); + return result; +} + +char* string_utility::strtok_r(char* str, const char* delimiters, char** save_ptr) +{ + char* token; + + if (str == NULL) + { + str = *save_ptr; + } + + if (*str == '\0') + { + *save_ptr = str; + return NULL; + } + + str += strspn(str, delimiters); + + if (*str == '\0') + { + *save_ptr = str; + return NULL; + } + + token = str + strcspn(str, delimiters); + if (*token == '\0') + { + *save_ptr = token; + return str; + } + + *token = '\0'; + *save_ptr = token + 1; + return str; +} + +char* string_utility::left_trim(const char* value, const char trim_char) +{ + uint32_t offset = 0; + while(value[offset] == trim_char && value[offset] != 0) + { + offset++; + } + + uint32_t length = strlen(value) - offset; + + char* result = (char*)malloc(length + 1); + if (result == NULL) + { + return NULL; + } + + strncpy(result, value + offset, length); + result[length] = 0; + return result; +} + +char* string_utility::right_trim(const char* value, const char trim_char) +{ + if (value == NULL) return NULL; + + int32_t length = strlen(value); + + while(length > 0 && value[length - 1] == trim_char) + { + length--; + } + + char* result = (char*)malloc(length + 1); + if (result == NULL) + { + return NULL; + } + + strncpy(result, value, length); + result[length] = 0; + return result; +} + +char* string_utility::trim(const char* value, const char trim_char) +{ + char* leftTrimmed = left_trim(value, trim_char); + char* trimmed = right_trim(leftTrimmed, trim_char); + free(leftTrimmed); + return trimmed; +} + +pointer_vector* string_utility::split(const char* value, const char* delimiter, bool trim_values) +{ + pointer_vector* result = new pointer_vector(false); + + char* value_copy = strdup(value); + char* position = value_copy; + char* token = strtok_r(value_copy, delimiter, &position); + while (token != NULL) + { + char* value_to_add = trim_values == true ? trim(token, ' ') : strdup(token); + result->add(value_to_add); + token = strtok_r(NULL, delimiter, &position); + } + + free(value_copy); + return result; +} + +pointer_vector* string_utility::split_first(const char* value, const char* delimiter, bool trim_values) +{ + pointer_vector* result = new pointer_vector(false); + + char* str = new char[strlen(value) + 1]; + strcpy(str, value); + + char* save_ptr = NULL; + char* first_part = string_utility::strtok_r(str, delimiter, &save_ptr); + char* second_part = string_utility::strtok_r(NULL, "", &save_ptr); + + if (first_part != NULL) + { + result->add(trim_values ? trim(first_part, ' ') : strdup(first_part)); + } + + if (second_part != NULL) + { + result->add(trim_values ? trim(second_part, ' ') : strdup(second_part)); + } + + delete[] str; + + return result; +} + +int64_t string_utility::string_to_int64(const char* string) +{ + int64_t result = 0; + if (string == NULL) + { + return result; + } + + bool is_negative = false; + if (*string == '-') + { + is_negative = true; + string++; + } + + while (*string != '\0') + { + if (*string < '0' || *string > '9') + { + break; + } + result = result * 10 + (*string - '0'); + string++; + } + + return is_negative ? -result : result; +} + +int64_t string_utility::hex_to_int64(const char* hex) +{ + int64_t result = 0; + + while (*hex != '\0') + { + char c = *hex; + result *= 16; + + if (c >= '0' && c <= '9') + { + result += c - '0'; + } + else if (c >= 'A' && c <= 'F') + { + result += c - 'A' + 10; + } + else if (c >= 'a' && c <= 'f') + { + result += c - 'a' + 10; + } + else + { + return -1; + } + + ++hex; + } + return result; +} + +int string_utility::find_crlf(unsigned char* buffer, uint32_t length) +{ + if (buffer == NULL || length < 2) + { + return -1; + } + for (uint32_t i = 0; i < length - 1; ++i) + { + if (buffer[i] == '\r' && buffer[i + 1] == '\n') + { + return i; + } + } + return -1; +} diff --git a/BearSSL-OG/string_utility.h b/BearSSL-OG/string_utility.h new file mode 100644 index 0000000..8bb4e82 --- /dev/null +++ b/BearSSL-OG/string_utility.h @@ -0,0 +1,18 @@ +#pragma once + +#include "pointer_vector.h" + +class string_utility +{ +public: + static char* format_string(const char* format, ...); + static char* strtok_r(char* str, const char* delimiters, char** save_ptr); + static char* left_trim(const char* value, const char trim_char); + static char* right_trim(const char* value, const char trim_char); + static char* trim(const char* value, const char trim_char); + static pointer_vector* split(const char* value, const char* delimiter, bool trim_values); + static pointer_vector* split_first(const char* value, const char* delimiter, bool trim_values); + static int64_t string_to_int64(const char* string); + static int64_t hex_to_int64(const char* hex); + static int find_crlf(unsigned char* buffer, uint32_t length); +}; diff --git a/BearSSL-OG/trust_anchors.h b/BearSSL-OG/trust_anchors.h new file mode 100644 index 0000000..9ee13fb --- /dev/null +++ b/BearSSL-OG/trust_anchors.h @@ -0,0 +1,33591 @@ +#pragma once + +static const unsigned char TA0_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA0_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA0_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA1_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA1_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA2_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA2_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA2_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA3_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA3_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA3_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA4_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA4_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA5_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA5_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA5_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA6_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA6_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA6_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA7_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA7_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA8_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA8_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA8_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA9_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA9_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA10_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA10_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA10_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA11_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA11_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA12_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA12_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA12_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA13_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA13_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA14_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA14_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA15_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA15_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA16_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA16_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA16_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA17_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA17_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA17_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA18_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA18_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA18_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA19_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA19_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA19_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA20_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA20_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA21_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA21_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA21_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA22_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA22_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA23_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA23_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA24_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA24_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA24_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA25_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA25_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA26_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA26_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA27_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA27_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA27_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA28_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA28_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA28_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA29_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA29_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA29_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA30_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA30_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA30_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA31_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA31_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA31_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA32_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA32_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA32_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA33_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA33_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA33_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA34_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA34_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA34_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA35_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA35_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA35_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA36_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA36_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA37_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA37_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA37_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA38_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA38_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA38_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA39_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA39_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA40_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA40_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA40_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA41_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA41_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA42_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA42_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA42_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA43_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA43_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA43_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA44_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA44_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA44_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA45_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA45_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA46_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA46_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA46_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA47_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA47_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA47_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA48_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA48_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA48_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA49_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA49_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA49_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA50_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA50_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA50_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA51_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA51_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA51_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA52_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA52_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA53_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA53_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA53_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA54_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA54_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA54_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA55_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA55_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA55_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA56_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA56_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA56_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA57_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA57_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA58_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA58_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA58_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA59_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA59_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA59_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA60_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA60_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA61_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA61_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA61_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA62_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA62_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA63_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA63_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA63_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA64_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA64_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA64_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA65_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA65_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA65_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA66_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA66_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA66_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA67_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA67_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA67_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA68_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA68_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA68_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA69_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA69_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA70_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA70_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA70_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA71_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA71_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA71_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA72_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA72_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA72_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA73_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA73_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA73_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA74_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA74_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA75_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA75_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA75_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA76_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA76_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA76_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA77_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA77_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA78_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA78_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA78_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA79_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA79_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA79_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA80_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA80_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA80_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA81_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA81_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA81_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA82_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA82_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA82_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA83_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA83_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA83_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA84_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA84_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA84_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA85_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA85_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA86_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA86_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA87_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA87_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA88_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA88_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA88_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA89_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA89_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA90_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA90_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA90_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA91_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA91_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA91_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA92_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA92_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA92_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA93_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA93_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA93_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA94_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA94_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA94_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA95_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA95_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA95_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA96_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA96_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA97_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA97_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA98_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA98_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA98_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA99_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA99_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA99_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA100_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA100_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA100_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA101_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA101_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA101_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA102_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA102_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA102_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA103_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA103_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA103_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA104_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA104_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA104_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA105_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA105_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA105_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA106_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA106_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA106_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA107_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA107_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA108_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA108_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA109_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA109_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA110_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA110_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA110_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA111_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA111_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA111_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA112_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA112_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA112_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA113_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA113_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA113_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA114_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA114_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA114_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA115_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA115_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA115_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA116_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA116_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA116_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA117_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA117_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA117_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA118_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA118_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA118_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA119_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA119_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA119_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA120_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA120_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA121_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA121_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA122_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA122_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA123_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA123_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA123_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA124_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA124_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA124_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA125_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA125_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA126_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA126_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA126_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA127_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA127_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA128_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA128_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA129_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA129_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA129_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA130_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA130_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA130_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA131_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA131_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA131_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA132_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA132_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA133_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA133_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA133_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA134_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA134_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA134_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA135_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA135_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA136_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA136_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA137_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA137_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA137_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA138_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA138_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA138_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA139_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA139_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA140_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA140_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA141_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA141_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA141_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA142_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA142_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA142_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA143_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA143_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA144_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA144_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA144_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA145_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA145_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA146_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA146_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA147_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA147_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA148_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA148_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA148_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA149_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA149_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA149_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA150_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA150_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA150_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA151_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA151_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA152_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA152_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA152_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA153_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA153_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA154_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA154_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA154_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA155_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA155_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA155_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA156_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA156_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA156_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA157_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA157_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA157_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA158_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA158_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA158_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA159_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA159_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA159_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA160_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA160_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA160_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA161_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA161_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA162_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA162_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA163_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA163_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA163_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA164_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA164_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA164_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA165_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA165_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA165_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA166_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA166_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA167_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA167_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA167_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA168_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA168_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA168_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA169_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA169_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA169_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA170_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA170_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA170_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA171_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA171_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA172_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA172_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA172_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA173_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA173_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA174_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA174_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA174_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA175_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA175_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA176_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA176_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA176_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA177_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA177_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA177_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA178_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA178_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA179_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA179_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA179_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA180_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA180_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA180_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA181_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA181_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA181_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA182_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA182_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA183_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA183_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA184_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA184_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA184_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA185_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA185_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA185_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA186_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA186_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA186_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA187_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA187_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA187_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA188_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA188_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA188_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA189_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA189_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA189_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA190_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA190_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA190_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA191_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA191_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA192_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA192_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA192_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA193_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA193_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA193_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA194_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA194_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA194_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA195_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA195_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA195_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA196_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA196_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA197_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA197_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA197_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA198_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA198_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA198_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA199_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA199_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA199_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA200_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA200_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA201_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA201_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA202_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA202_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA202_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA203_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA203_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA203_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA204_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA204_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA205_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA205_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA205_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA206_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA206_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA206_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA207_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA207_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA208_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA208_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA208_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA209_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA209_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA209_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA210_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA210_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA210_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA211_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA211_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA212_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA212_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA213_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA213_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA213_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA214_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA214_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA214_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA215_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA215_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA215_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA216_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA216_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA217_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA217_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA217_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA218_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA218_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA218_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA219_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA219_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA220_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA220_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA220_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA221_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA221_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA221_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA222_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA222_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA222_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA223_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA223_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA223_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA224_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA224_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA225_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA225_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA225_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA226_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA226_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA226_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA227_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA227_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA227_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA228_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA228_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA228_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA229_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA229_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA229_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA230_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA230_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA230_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA231_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA231_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA231_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA232_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA232_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA233_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA233_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA233_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA234_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA234_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA234_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA235_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA235_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA235_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA236_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA236_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA236_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA237_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA237_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA237_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA238_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA238_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA239_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA239_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA239_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA240_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA240_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA241_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA241_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA241_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA242_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA242_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA242_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA243_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA243_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA243_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA244_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA244_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA244_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA245_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA245_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA246_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA246_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA246_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA247_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA247_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA247_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA248_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA248_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA248_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA249_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA249_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA249_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA250_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA250_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA250_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA251_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA251_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA252_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA252_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA252_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA253_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA253_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA253_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA254_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA254_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA255_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA255_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA256_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA256_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA256_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA257_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA257_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA258_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA258_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA258_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA259_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA259_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA259_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA260_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA260_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA260_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA261_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA261_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA262_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA262_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA262_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA263_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA263_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA263_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA264_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA264_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA264_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA265_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA265_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA265_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA266_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA266_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA266_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA267_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA267_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA267_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA268_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA268_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA269_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA269_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA269_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA270_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA270_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA271_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA271_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA271_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA272_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA272_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA272_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA273_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA273_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA273_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA274_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA274_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA275_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA275_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA275_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA276_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA276_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA276_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA277_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA277_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA277_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA278_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA278_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA279_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA279_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA280_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA280_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA280_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA281_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA281_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA281_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA282_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA282_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA282_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA283_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA283_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA284_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA284_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA284_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA285_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA285_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA286_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA286_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA286_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA287_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA287_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA287_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA288_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA288_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA288_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA289_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA289_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA289_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA290_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA290_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA290_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA291_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA291_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA292_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA292_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA292_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA293_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA293_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA293_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA294_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA294_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA295_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA295_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA295_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA296_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA296_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA297_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA297_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA297_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA298_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA298_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA298_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA299_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA299_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA299_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA300_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA300_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA300_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA301_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA301_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA302_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA302_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA302_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA303_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA303_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA304_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA304_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA304_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA305_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA305_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA305_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA306_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA306_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA306_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA307_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA307_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA307_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA308_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA308_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA309_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA309_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA310_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA310_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA311_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA311_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA312_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA312_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA312_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA313_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA313_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA313_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA314_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA314_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA314_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA315_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA315_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA316_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA316_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA316_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA317_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA317_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA317_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA318_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA318_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA318_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA319_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA319_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA320_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA320_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA320_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA321_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA321_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA322_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA322_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA322_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA323_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA323_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA323_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA324_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA324_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA324_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA325_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA325_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA325_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA326_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA326_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA327_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA327_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA327_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA328_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA328_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA328_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA329_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA329_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA329_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA330_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA330_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA330_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA331_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA331_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA332_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA332_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA332_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA333_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA333_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA333_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA334_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA334_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA334_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA335_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA335_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA335_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA336_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA336_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA337_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA337_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA337_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA338_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA338_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA338_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA339_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA339_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA339_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA340_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA340_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA340_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA341_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA341_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA341_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA342_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA342_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA343_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA343_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA343_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA344_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA344_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA345_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA345_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA345_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA346_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA346_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA347_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA347_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA347_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA348_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA348_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA348_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA349_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA349_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA350_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA350_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA350_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA351_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA351_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA351_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA352_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA352_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA352_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA353_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA353_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA354_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA354_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA354_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA355_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA355_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA355_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA356_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA356_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA357_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA357_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA357_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA358_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA358_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA358_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA359_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA359_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA359_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA360_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA360_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA360_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA361_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA361_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA361_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA362_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA362_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA362_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA363_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA363_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA363_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA364_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA364_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA364_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA365_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA365_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA365_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA366_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA366_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA366_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA367_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA367_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA367_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA368_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA368_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA369_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA369_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA369_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA370_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA370_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA370_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA371_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA371_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA371_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA372_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA372_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA372_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA373_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA373_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA374_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA374_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA374_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA375_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA375_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA376_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA376_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA377_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA377_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA377_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA378_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA378_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA378_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA379_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA379_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA379_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA380_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA380_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA381_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA381_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA381_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA382_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA382_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA382_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA383_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA383_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA383_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA384_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA384_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA384_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA385_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA385_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA386_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA386_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA386_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA387_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA387_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA388_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA388_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA389_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA389_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA389_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA390_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA390_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA390_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA391_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA391_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA392_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA392_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA392_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA393_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA393_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA393_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA394_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA394_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA394_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA395_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA395_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA396_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA396_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA396_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA397_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA397_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA397_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA398_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA398_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA398_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA399_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA399_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA399_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA400_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA400_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA400_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA401_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA401_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA402_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA402_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA402_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA403_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA403_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA403_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA404_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA404_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA405_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA405_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA406_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA406_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA406_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA407_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA407_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA408_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA408_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA408_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA409_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA409_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA409_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA410_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA410_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA410_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA411_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA411_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA412_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA412_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA412_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA413_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA413_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA413_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA414_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA414_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA414_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA415_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA415_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA415_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA416_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA416_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA416_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA417_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA417_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA417_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA418_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA418_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA419_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA419_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA419_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA420_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA420_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA421_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA421_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA421_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA422_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA422_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA422_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA423_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA423_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA423_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA424_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA424_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA425_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA425_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA425_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA426_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA426_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA426_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA427_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA427_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA427_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA428_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA428_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA429_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA429_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA430_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA430_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA430_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA431_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA431_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA431_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA432_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA432_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA432_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA433_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA433_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA434_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA434_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA434_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA435_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA435_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA436_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA436_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA436_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA437_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA437_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA437_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA438_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA438_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA438_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA439_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA439_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA439_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA440_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA440_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA440_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA441_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA441_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA442_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA442_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA442_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA443_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA443_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA443_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA444_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA444_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA445_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA445_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA445_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA446_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA446_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA447_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA447_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA447_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA448_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA448_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA448_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA449_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA449_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA449_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA450_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA450_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA450_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA451_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA451_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA452_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA452_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA452_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA453_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA453_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA454_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA454_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA454_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA455_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA455_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA455_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA456_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA456_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA456_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA457_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA457_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA457_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA458_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA458_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA459_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA459_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA460_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA460_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA461_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA461_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA462_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA462_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA462_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA463_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA463_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA463_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA464_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA464_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA464_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA465_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA465_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA466_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA466_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA466_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA467_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA467_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA467_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA468_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA468_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA468_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA469_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA469_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA470_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA470_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA470_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA471_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA471_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA472_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA472_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA472_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA473_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA473_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA473_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA474_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA474_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA474_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA475_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA475_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA475_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA476_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA476_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA477_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA477_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA477_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA478_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA478_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA478_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA479_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA479_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA479_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA480_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA480_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA480_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA481_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA481_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA482_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA482_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA482_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA483_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA483_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA483_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA484_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA484_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA484_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA485_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA485_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA485_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA486_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA486_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA487_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA487_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA487_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA488_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA488_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA488_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA489_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA489_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA489_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA490_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA490_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA490_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA491_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA491_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA491_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA492_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA492_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA493_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA493_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA493_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA494_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA494_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA495_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA495_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA495_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA496_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA496_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA497_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA497_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA497_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA498_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA498_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA498_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA499_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA499_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA500_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA500_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA500_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA501_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA501_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA501_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA502_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA502_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA502_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA503_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA503_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA504_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA504_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA504_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA505_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA505_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA505_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA506_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA506_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA507_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA507_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA507_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA508_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA508_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA508_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA509_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA509_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA509_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA510_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA510_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA510_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA511_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA511_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA511_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA512_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA512_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA512_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA513_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA513_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA513_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA514_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA514_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA514_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA515_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA515_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA515_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA516_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA516_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA516_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA517_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA517_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA517_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA518_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA518_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA519_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA519_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA519_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA520_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA520_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA520_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA521_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA521_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA521_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA522_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA522_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA522_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA523_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA523_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA524_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA524_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA524_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA525_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA525_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA526_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA526_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA527_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA527_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA527_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA528_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA528_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA528_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA529_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA529_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA529_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA530_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA530_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA531_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA531_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA531_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA532_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA532_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA532_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA533_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA533_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA533_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA534_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA534_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA534_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA535_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA535_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA536_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA536_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA536_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA537_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA537_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA538_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA538_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA539_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA539_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA539_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA540_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA540_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA540_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA541_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA541_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA542_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA542_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA542_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA543_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA543_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA543_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA544_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA544_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA544_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA545_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA545_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA546_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA546_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA546_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA547_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA547_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA547_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA548_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA548_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA549_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA549_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA549_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA550_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA550_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA550_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA551_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA551_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA551_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA552_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA552_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA553_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA553_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA553_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA554_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA554_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA554_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA555_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA555_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA555_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA556_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA556_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA556_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA557_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA557_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA557_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA558_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA558_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA559_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA559_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA559_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA560_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA560_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA560_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA561_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA561_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA561_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA562_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA562_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA562_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA563_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA563_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA563_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA564_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA564_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA565_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA565_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA566_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA566_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA566_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA567_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA567_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA567_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA568_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA568_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA568_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA569_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA569_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA569_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA570_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA570_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA571_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA571_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA571_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA572_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA572_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA572_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA573_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA573_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA573_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA574_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA574_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA574_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA575_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA575_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA575_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA576_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA576_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA577_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA577_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA577_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA578_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA578_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA578_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA579_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA579_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA579_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA580_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA580_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA580_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA581_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA581_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA581_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA582_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA582_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA582_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA583_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA583_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA583_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA584_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA584_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA585_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA585_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA585_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA586_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA586_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA587_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA587_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA587_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA588_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA588_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA588_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA589_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA589_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA589_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA590_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA590_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA590_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA591_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA591_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA591_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA592_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA592_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA593_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA593_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA594_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA594_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA595_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA595_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA595_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA596_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA596_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA596_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA597_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA597_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA597_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA598_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA598_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA599_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA599_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA599_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA600_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA600_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA600_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA601_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA601_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA602_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA602_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA602_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA603_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA603_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA604_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA604_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA604_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA605_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA605_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA605_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA606_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA606_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA607_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA607_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA607_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA608_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA608_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA609_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA609_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA609_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA610_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA610_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA610_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA611_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA611_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA611_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA612_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA612_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA612_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA613_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA613_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA613_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA614_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA614_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA614_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA615_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA615_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA615_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA616_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA616_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA616_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA617_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA617_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA617_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA618_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA618_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA618_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA619_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA619_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA619_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA620_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA620_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA620_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA621_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA621_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA622_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA622_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA622_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA623_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA623_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA623_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA624_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA624_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA625_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA625_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA625_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA626_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA626_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA627_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA627_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA628_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA628_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA629_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA629_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA629_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA630_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA630_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA630_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA631_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA631_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA632_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA632_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA632_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA633_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA633_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA634_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA634_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA634_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA635_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA635_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA636_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA636_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA637_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA637_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA637_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA638_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA638_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA638_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA639_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA639_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA639_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA640_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA640_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA641_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA641_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA641_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA642_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA642_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA642_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA643_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA643_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA643_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA644_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA644_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA645_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA645_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA645_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA646_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA646_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA646_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA647_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA647_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA647_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA648_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA648_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA649_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA649_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA649_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA650_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA650_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA651_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA651_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA651_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA652_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA652_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA652_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA653_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA653_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA653_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA654_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA654_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA654_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA655_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA655_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA655_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA656_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA656_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA656_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA657_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA657_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA657_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA658_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA658_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA659_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA659_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA659_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA660_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA660_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA660_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA661_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA661_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA661_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA662_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA662_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA662_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA663_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA663_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA663_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA664_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA664_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA665_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA665_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA665_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA666_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA666_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA666_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA667_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA667_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA667_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA668_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA668_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA669_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA669_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA669_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA670_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA670_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA671_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA671_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA672_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA672_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA672_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA673_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA673_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA673_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA674_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA674_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA674_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA675_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA675_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA676_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA676_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA676_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA677_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA677_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA677_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA678_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA678_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA678_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA679_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA679_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA679_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA680_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA680_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA680_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA681_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA681_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA681_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA682_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA682_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA683_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA683_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA684_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA684_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA685_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA685_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA685_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA686_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA686_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA687_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA687_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA687_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA688_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA688_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA688_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA689_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA689_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA689_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA690_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA690_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA690_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA691_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA691_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA691_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA692_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA692_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA692_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA693_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA693_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA694_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA694_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA694_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA695_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA695_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA695_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA696_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA696_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA697_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA697_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA697_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA698_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA698_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA698_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA699_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA699_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA699_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA700_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA700_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA700_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA701_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA701_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA702_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA702_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA702_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA703_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA703_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA703_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA704_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA704_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA704_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA705_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA705_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA705_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA706_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA706_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA706_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA707_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA707_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA708_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA708_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA708_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA709_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA709_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA709_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA710_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA710_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA710_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA711_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA711_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA711_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA712_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA712_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA713_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA713_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA713_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA714_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA714_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA715_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA715_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA715_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA716_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA716_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA717_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA717_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA717_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA718_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA718_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA719_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA719_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA719_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA720_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA720_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA721_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA721_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA721_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA722_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA722_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA722_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA723_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA723_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA723_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA724_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA724_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA724_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA725_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA725_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA725_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA726_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA726_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA726_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA727_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA727_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA728_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA728_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA728_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA729_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA729_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA729_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA730_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA730_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA730_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA731_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA731_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA731_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA732_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA732_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA733_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA733_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA733_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA734_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA734_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA735_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA735_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA736_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA736_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA736_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA737_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA737_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA737_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA738_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA738_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA738_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA739_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA739_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA739_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA740_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA740_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA740_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA741_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA741_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA741_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA742_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA742_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA742_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA743_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA743_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA743_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA744_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA744_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA744_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA745_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA745_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA746_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA746_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA746_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA747_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA747_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA748_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA748_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA748_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA749_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA749_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA749_RSA_E[] = { + 0x01, 0x00, 0x01 +}; diff --git a/BearSSL-OG/url_utility.cpp b/BearSSL-OG/url_utility.cpp new file mode 100644 index 0000000..6f31b86 --- /dev/null +++ b/BearSSL-OG/url_utility.cpp @@ -0,0 +1,36 @@ +#include "url_utility.h" +#include "pointer_vector.h" +#include "string_utility.h" + +bool url_utility::parse_url(const char* url, char** host, char** path) +{ + bool result = false; + + pointer_vector* url_parts = string_utility::split_first(url, "://", true); + if (url_parts->count() == 2) + { + pointer_vector* domain_parts = string_utility::split_first(url_parts->get(1), "/", true); + if (domain_parts->count() == 2) + { + *host = strdup(domain_parts->get(0)); + *path = string_utility::format_string("/%s", domain_parts->get(1)); + if (*host != NULL && *path != NULL) + { + result = true; + } + else + { + /* Allocation failed — clean up partial results */ + free(*host); + free(*path); + *host = NULL; + *path = NULL; + } + } + delete(domain_parts); + } + delete(url_parts); + + return result; +} + diff --git a/BearSSL-OG/url_utility.h b/BearSSL-OG/url_utility.h new file mode 100644 index 0000000..53dcb55 --- /dev/null +++ b/BearSSL-OG/url_utility.h @@ -0,0 +1,7 @@ +#pragma once + +class url_utility +{ +public: + static bool parse_url(const char* url, char** host, char** path); +}; diff --git a/XboxCurl.sln b/XboxCurl.sln new file mode 100644 index 0000000..8a7095a --- /dev/null +++ b/XboxCurl.sln @@ -0,0 +1,47 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbearssl", "BearSSL-OG\libbearssl.vcproj", "{A1B2C3D4-1234-5678-9ABC-DEF012345678}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "libcurl\libcurl.vcproj", "{C3127A20-19DD-4483-AC21-D35386AC0E7C}" + ProjectSection(ProjectDependencies) = postProject + {A1B2C3D4-1234-5678-9ABC-DEF012345678} = {A1B2C3D4-1234-5678-9ABC-DEF012345678} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcproj", "{12345678-TEST-TEST-TEST-123456789ABC}" + ProjectSection(ProjectDependencies) = postProject + {A1B2C3D4-1234-5678-9ABC-DEF012345678} = {A1B2C3D4-1234-5678-9ABC-DEF012345678} + {C3127A20-19DD-4483-AC21-D35386AC0E7C} = {C3127A20-19DD-4483-AC21-D35386AC0E7C} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_minimal", "test\test_minimal.vcproj", "{12345678-TMIN-TMIN-TMIN-123456789ABC}" + ProjectSection(ProjectDependencies) = postProject + {C3127A20-19DD-4483-AC21-D35386AC0E7C} = {C3127A20-19DD-4483-AC21-D35386AC0E7C} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {A1B2C3D4-1234-5678-9ABC-DEF012345678}.Debug.ActiveCfg = Debug|Xbox + {A1B2C3D4-1234-5678-9ABC-DEF012345678}.Debug.Build.0 = Debug|Xbox + {A1B2C3D4-1234-5678-9ABC-DEF012345678}.Release.ActiveCfg = Release|Xbox + {A1B2C3D4-1234-5678-9ABC-DEF012345678}.Release.Build.0 = Release|Xbox + {C3127A20-19DD-4483-AC21-D35386AC0E7C}.Debug.ActiveCfg = Debug|Xbox + {C3127A20-19DD-4483-AC21-D35386AC0E7C}.Debug.Build.0 = Debug|Xbox + {C3127A20-19DD-4483-AC21-D35386AC0E7C}.Release.ActiveCfg = Release|Xbox + {C3127A20-19DD-4483-AC21-D35386AC0E7C}.Release.Build.0 = Release|Xbox + {12345678-TEST-TEST-TEST-123456789ABC}.Debug.ActiveCfg = Debug|Xbox + {12345678-TEST-TEST-TEST-123456789ABC}.Debug.Build.0 = Debug|Xbox + {12345678-TEST-TEST-TEST-123456789ABC}.Release.ActiveCfg = Release|Xbox + {12345678-TEST-TEST-TEST-123456789ABC}.Release.Build.0 = Release|Xbox + {12345678-TMIN-TMIN-TMIN-123456789ABC}.Debug.ActiveCfg = Debug|Xbox + {12345678-TMIN-TMIN-TMIN-123456789ABC}.Debug.Build.0 = Debug|Xbox + {12345678-TMIN-TMIN-TMIN-123456789ABC}.Release.ActiveCfg = Release|Xbox + {12345678-TMIN-TMIN-TMIN-123456789ABC}.Release.Build.0 = Release|Xbox + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/libcurl/include/Makefile.am b/libcurl/include/Makefile.am new file mode 100644 index 0000000..3b24860 --- /dev/null +++ b/libcurl/include/Makefile.am @@ -0,0 +1,5 @@ +SUBDIRS = curl + +EXTRA_DIST = README + +AUTOMAKE_OPTIONS = foreign no-dependencies diff --git a/libcurl/include/Makefile.in b/libcurl/include/Makefile.in new file mode 100644 index 0000000..d7a1094 --- /dev/null +++ b/libcurl/include/Makefile.in @@ -0,0 +1,720 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \ + $(top_srcdir)/m4/curl-compilers.m4 \ + $(top_srcdir)/m4/curl-confopts.m4 \ + $(top_srcdir)/m4/curl-functions.m4 \ + $(top_srcdir)/m4/curl-openssl.m4 \ + $(top_srcdir)/m4/curl-override.m4 \ + $(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/xc-am-iface.m4 \ + $(top_srcdir)/m4/xc-cc-check.m4 \ + $(top_srcdir)/m4/xc-lt-iface.m4 \ + $(top_srcdir)/m4/xc-translit.m4 \ + $(top_srcdir)/m4/xc-val-flgs.m4 \ + $(top_srcdir)/m4/zz40-xc-ovr.m4 \ + $(top_srcdir)/m4/zz50-xc-ovr.m4 \ + $(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/curl_config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +depcomp = +am__maybe_remake_depfiles = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AR_FLAGS = @AR_FLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@ +CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@ +CURLVERSION = @CURLVERSION@ +CURL_CA_BUNDLE = @CURL_CA_BUNDLE@ +CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@ +CURL_DISABLE_DICT = @CURL_DISABLE_DICT@ +CURL_DISABLE_FILE = @CURL_DISABLE_FILE@ +CURL_DISABLE_FTP = @CURL_DISABLE_FTP@ +CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@ +CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@ +CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@ +CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@ +CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@ +CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@ +CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@ +CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@ +CURL_DISABLE_SMB = @CURL_DISABLE_SMB@ +CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@ +CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@ +CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@ +CURL_LT_SHLIB_VERSIONED_FLAVOUR = @CURL_LT_SHLIB_VERSIONED_FLAVOUR@ +CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@ +CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@ +CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SHARED = @ENABLE_SHARED@ +ENABLE_STATIC = @ENABLE_STATIC@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ +GCOV = @GCOV@ +GREP = @GREP@ +HAVE_BROTLI = @HAVE_BROTLI@ +HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@ +HAVE_LDAP_SSL = @HAVE_LDAP_SSL@ +HAVE_LIBZ = @HAVE_LIBZ@ +HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@ +HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@ +IDN_ENABLED = @IDN_ENABLED@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPV6_ENABLED = @IPV6_ENABLED@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCURL_LIBS = @LIBCURL_LIBS@ +LIBMETALINK_CPPFLAGS = @LIBMETALINK_CPPFLAGS@ +LIBMETALINK_LDFLAGS = @LIBMETALINK_LDFLAGS@ +LIBMETALINK_LIBS = @LIBMETALINK_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANOPT = @MANOPT@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NROFF = @NROFF@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGADD_NAME = @PKGADD_NAME@ +PKGADD_PKG = @PKGADD_PKG@ +PKGADD_VENDOR = @PKGADD_VENDOR@ +PKGCONFIG = @PKGCONFIG@ +RANDOM_FILE = @RANDOM_FILE@ +RANLIB = @RANLIB@ +REQUIRE_LIB_DEPS = @REQUIRE_LIB_DEPS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_BACKENDS = @SSL_BACKENDS@ +SSL_ENABLED = @SSL_ENABLED@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +SUPPORT_FEATURES = @SUPPORT_FEATURES@ +SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@ +USE_ARES = @USE_ARES@ +USE_GNUTLS = @USE_GNUTLS@ +USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@ +USE_LIBRTMP = @USE_LIBRTMP@ +USE_LIBSSH = @USE_LIBSSH@ +USE_LIBSSH2 = @USE_LIBSSH2@ +USE_MBEDTLS = @USE_MBEDTLS@ +USE_MESALINK = @USE_MESALINK@ +USE_NGHTTP2 = @USE_NGHTTP2@ +USE_NSS = @USE_NSS@ +USE_OPENLDAP = @USE_OPENLDAP@ +USE_SCHANNEL = @USE_SCHANNEL@ +USE_SECTRANSP = @USE_SECTRANSP@ +USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ +USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ +USE_WOLFSSL = @USE_WOLFSSL@ +VERSION = @VERSION@ +VERSIONNUM = @VERSIONNUM@ +ZLIB_LIBS = @ZLIB_LIBS@ +ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libext = @libext@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = curl +EXTRA_DIST = README +AUTOMAKE_OPTIONS = foreign no-dependencies +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libcurl/include/README b/libcurl/include/README new file mode 100644 index 0000000..091ef76 --- /dev/null +++ b/libcurl/include/README @@ -0,0 +1,18 @@ + _ _ ____ _ + ___| | | | _ \| | + / __| | | | |_) | | + | (__| |_| | _ <| |___ + \___|\___/|_| \_\_____| + +Include files for libcurl, external users. + +They're all placed in the curl subdirectory here for better fit in any kind +of environment. You must include files from here using... + + #include + +... style and point the compiler's include path to the directory holding the +curl subdirectory. It makes it more likely to survive future modifications. + +The public curl include files can be shared freely between different platforms +and different architectures. diff --git a/libcurl/include/curl/Makefile.am b/libcurl/include/curl/Makefile.am new file mode 100644 index 0000000..a31f61b --- /dev/null +++ b/libcurl/include/curl/Makefile.am @@ -0,0 +1,39 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h + +pkgincludedir= $(includedir)/curl + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) + +checksrc: + $(CHECKSRC)@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +if CURLDEBUG +# for debug builds, we scan the sources on all regular make invokes +all-local: checksrc +endif diff --git a/libcurl/include/curl/Makefile.in b/libcurl/include/curl/Makefile.in new file mode 100644 index 0000000..220d294 --- /dev/null +++ b/libcurl/include/curl/Makefile.in @@ -0,0 +1,693 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include/curl +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \ + $(top_srcdir)/m4/curl-compilers.m4 \ + $(top_srcdir)/m4/curl-confopts.m4 \ + $(top_srcdir)/m4/curl-functions.m4 \ + $(top_srcdir)/m4/curl-openssl.m4 \ + $(top_srcdir)/m4/curl-override.m4 \ + $(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/xc-am-iface.m4 \ + $(top_srcdir)/m4/xc-cc-check.m4 \ + $(top_srcdir)/m4/xc-lt-iface.m4 \ + $(top_srcdir)/m4/xc-translit.m4 \ + $(top_srcdir)/m4/xc-val-flgs.m4 \ + $(top_srcdir)/m4/zz40-xc-ovr.m4 \ + $(top_srcdir)/m4/zz50-xc-ovr.m4 \ + $(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/curl_config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgincludedir)" +HEADERS = $(pkginclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +pkgincludedir = $(includedir)/curl +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AR_FLAGS = @AR_FLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@ +CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@ +CURLVERSION = @CURLVERSION@ +CURL_CA_BUNDLE = @CURL_CA_BUNDLE@ +CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@ +CURL_DISABLE_DICT = @CURL_DISABLE_DICT@ +CURL_DISABLE_FILE = @CURL_DISABLE_FILE@ +CURL_DISABLE_FTP = @CURL_DISABLE_FTP@ +CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@ +CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@ +CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@ +CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@ +CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@ +CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@ +CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@ +CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@ +CURL_DISABLE_SMB = @CURL_DISABLE_SMB@ +CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@ +CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@ +CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@ +CURL_LT_SHLIB_VERSIONED_FLAVOUR = @CURL_LT_SHLIB_VERSIONED_FLAVOUR@ +CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@ +CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@ +CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SHARED = @ENABLE_SHARED@ +ENABLE_STATIC = @ENABLE_STATIC@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ +GCOV = @GCOV@ +GREP = @GREP@ +HAVE_BROTLI = @HAVE_BROTLI@ +HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@ +HAVE_LDAP_SSL = @HAVE_LDAP_SSL@ +HAVE_LIBZ = @HAVE_LIBZ@ +HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@ +HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@ +IDN_ENABLED = @IDN_ENABLED@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPV6_ENABLED = @IPV6_ENABLED@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCURL_LIBS = @LIBCURL_LIBS@ +LIBMETALINK_CPPFLAGS = @LIBMETALINK_CPPFLAGS@ +LIBMETALINK_LDFLAGS = @LIBMETALINK_LDFLAGS@ +LIBMETALINK_LIBS = @LIBMETALINK_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANOPT = @MANOPT@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NROFF = @NROFF@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGADD_NAME = @PKGADD_NAME@ +PKGADD_PKG = @PKGADD_PKG@ +PKGADD_VENDOR = @PKGADD_VENDOR@ +PKGCONFIG = @PKGCONFIG@ +RANDOM_FILE = @RANDOM_FILE@ +RANLIB = @RANLIB@ +REQUIRE_LIB_DEPS = @REQUIRE_LIB_DEPS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_BACKENDS = @SSL_BACKENDS@ +SSL_ENABLED = @SSL_ENABLED@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +SUPPORT_FEATURES = @SUPPORT_FEATURES@ +SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@ +USE_ARES = @USE_ARES@ +USE_GNUTLS = @USE_GNUTLS@ +USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@ +USE_LIBRTMP = @USE_LIBRTMP@ +USE_LIBSSH = @USE_LIBSSH@ +USE_LIBSSH2 = @USE_LIBSSH2@ +USE_MBEDTLS = @USE_MBEDTLS@ +USE_MESALINK = @USE_MESALINK@ +USE_NGHTTP2 = @USE_NGHTTP2@ +USE_NSS = @USE_NSS@ +USE_OPENLDAP = @USE_OPENLDAP@ +USE_SCHANNEL = @USE_SCHANNEL@ +USE_SECTRANSP = @USE_SECTRANSP@ +USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ +USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ +USE_WOLFSSL = @USE_WOLFSSL@ +VERSION = @VERSION@ +VERSIONNUM = @VERSIONNUM@ +ZLIB_LIBS = @ZLIB_LIBS@ +ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libext = @libext@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/curl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/curl/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgincludeHEADERS: $(pkginclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +@CURLDEBUG_FALSE@all-local: +all-am: Makefile $(HEADERS) all-local +installdirs: + for dir in "$(DESTDIR)$(pkgincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkgincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkgincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ + clean-generic clean-libtool cscopelist-am ctags ctags-am \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgincludeHEADERS \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkgincludeHEADERS + +.PRECIOUS: Makefile + + +checksrc: + $(CHECKSRC)@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +# for debug builds, we scan the sources on all regular make invokes +@CURLDEBUG_TRUE@all-local: checksrc + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libcurl/include/curl/curl.h b/libcurl/include/curl/curl.h new file mode 100644 index 0000000..014fb56 --- /dev/null +++ b/libcurl/include/curl/curl.h @@ -0,0 +1,2873 @@ +#ifndef __CURL_CURL_H +#define __CURL_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.haxx.se/libcurl/ + * + * curl-library mailing list subscription and unsubscription web interface: + * https://cool.haxx.se/mailman/listinfo/curl-library/ + */ + +#include +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things run-time */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && \ + !defined(WIN32) && !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +//#include +//#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) +#include +#endif + +#if !defined(WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#ifdef __BEOS__ +#include +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_easy CURL; +typedef struct Curl_share CURLSH; +#else +typedef void CURL; +typedef void CURLSH; +#endif + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(WIN32) || defined(__SYMBIAN32__) || \ + (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */ + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK = 12, + CURLSSLBACKEND_BEARSSL = 13 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + +/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE 524288 +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Content of this structure depends on information which is known and is + achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man + page for callbacks returning this structure -- some fields are mandatory, + some others are optional. The FLAG field has special meaning. */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors*/ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an OpenSSL + or WolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a zero-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_IMMEDIATELY (1<<0) +#define CURLALTSVC_ALTUSED (1<<1) +#define CURLALTSVC_READONLYFILE (1<<2) +#define CURLALTSVC_H1 (1<<3) +#define CURLALTSVC_H2 (1<<4) +#define CURLALTSVC_H3 (1<<5) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + +/* name is uppercase CURLOPT_, + type is one of the defined CURLOPTTYPE_ + number is unique identifier */ +#ifdef CINIT +#undef CINIT +#endif + +#ifdef CURL_ISOCPP +#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLOPT_/**/name = type + number +#endif + +/* handy aliases that make no run-time difference */ +#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT +#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT + +/* + * This macro-mania below setups the CURLOPT_[what] enum, to be used with + * curl_easy_setopt(). The first argument in the CINIT() macro is the [what] + * word. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CINIT(WRITEDATA, OBJECTPOINT, 1), + + /* The full URL to get/put */ + CINIT(URL, STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CINIT(PORT, LONG, 3), + + /* Name of proxy to use. */ + CINIT(PROXY, STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CINIT(USERPWD, STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CINIT(PROXYUSERPWD, STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CINIT(RANGE, STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CINIT(READDATA, OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CINIT(ERRORBUFFER, OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CINIT(READFUNCTION, FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CINIT(TIMEOUT, LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CINIT(INFILESIZE, LONG, 14), + + /* POST static input fields. */ + CINIT(POSTFIELDS, OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CINIT(REFERER, STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CINIT(FTPPORT, STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CINIT(USERAGENT, STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CINIT(LOW_SPEED_LIMIT, LONG, 19), + + /* Set the "low speed time" */ + CINIT(LOW_SPEED_TIME, LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CINIT(RESUME_FROM, LONG, 21), + + /* Set cookie in request: */ + CINIT(COOKIE, STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CINIT(HTTPHEADER, SLISTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CINIT(HTTPPOST, OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CINIT(SSLCERT, STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CINIT(KEYPASSWD, STRINGPOINT, 26), + + /* send TYPE parameter? */ + CINIT(CRLF, LONG, 27), + + /* send linked-list of QUOTE commands */ + CINIT(QUOTE, SLISTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CINIT(HEADERDATA, OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CINIT(COOKIEFILE, STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CINIT(SSLVERSION, LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CINIT(TIMECONDITION, LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CINIT(TIMEVALUE, LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CINIT(CUSTOMREQUEST, STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CINIT(STDERR, OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CINIT(POSTQUOTE, SLISTPOINT, 39), + + CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */ + + CINIT(VERBOSE, LONG, 41), /* talk a lot */ + CINIT(HEADER, LONG, 42), /* throw the header out too */ + CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ + CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ + CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */ + CINIT(UPLOAD, LONG, 46), /* this is an upload */ + CINIT(POST, LONG, 47), /* HTTP POST method */ + CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */ + + CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ + + CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ + CINIT(PUT, LONG, 54), /* HTTP PUT */ + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CINIT(PROGRESSDATA, OBJECTPOINT, 57), +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA + + /* We want the referrer field set automatically when following locations */ + CINIT(AUTOREFERER, LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CINIT(PROXYPORT, LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CINIT(POSTFIELDSIZE, LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CINIT(HTTPPROXYTUNNEL, LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CINIT(INTERFACE, STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CINIT(KRBLEVEL, STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CINIT(SSL_VERIFYPEER, LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAINFO, STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CINIT(MAXREDIRS, LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CINIT(FILETIME, LONG, 69), + + /* This points to a linked list of telnet options */ + CINIT(TELNETOPTIONS, SLISTPOINT, 70), + + /* Max amount of cached alive connections */ + CINIT(MAXCONNECTS, LONG, 71), + + CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */ + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CINIT(FRESH_CONNECT, LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CINIT(FORBID_REUSE, LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CINIT(RANDOM_FILE, STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CINIT(EGDSOCKET, STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CINIT(CONNECTTIMEOUT, LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CINIT(HTTPGET, LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CINIT(SSL_VERIFYHOST, LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CINIT(COOKIEJAR, STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CINIT(HTTP_VERSION, LONG, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CINIT(FTP_USE_EPSV, LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CINIT(SSLCERTTYPE, STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CINIT(SSLKEY, STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CINIT(SSLKEYTYPE, STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CINIT(SSLENGINE, STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CINIT(SSLENGINE_DEFAULT, LONG, 90), + + /* Non-zero value means to use the global dns cache */ + CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */ + + /* DNS cache timeout */ + CINIT(DNS_CACHE_TIMEOUT, LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CINIT(PREQUOTE, SLISTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CINIT(ACCEPT_ENCODING, STRINGPOINT, 102), + + /* Set pointer to private data */ + CINIT(PRIVATE, OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CINIT(HTTP200ALIASES, SLISTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CINIT(UNRESTRICTED_AUTH, LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CINIT(FTP_USE_EPRT, LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(HTTPAUTH, LONG, 107), + + /* Set the ssl context callback function, currently only for OpenSSL or + WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(PROXYAUTH, LONG, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to resolve names to those IP versions only. This only has + affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CINIT(IPRESOLVE, LONG, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CINIT(MAXFILESIZE, LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CINIT(INFILESIZE_LARGE, OFF_T, 115), + + /* Sets the continuation offset. There is also a LONG version of this; + * look above for RESUME_FROM. + */ + CINIT(RESUME_FROM_LARGE, OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CINIT(MAXFILESIZE_LARGE, OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CINIT(NETRC_FILE, STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CINIT(USE_SSL, LONG, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CINIT(TCP_NODELAY, LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CINIT(FTPSSLAUTH, LONG, 129), + + CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), + CINIT(IOCTLDATA, OBJECTPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* zero terminated string for pass on to the FTP server when asked for + "account" info */ + CINIT(FTP_ACCOUNT, STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CINIT(COOKIELIST, STRINGPOINT, 135), + + /* ignore Content-Length */ + CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CINIT(FTP_SKIP_PASV_IP, LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CINIT(FTP_FILEMETHOD, LONG, 138), + + /* Local port number to bind the socket to */ + CINIT(LOCALPORT, LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CINIT(LOCALPORTRANGE, LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CINIT(CONNECT_ONLY, LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), + CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147), + + /* callback function for setting socket options */ + CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), + CINIT(SOCKOPTDATA, OBJECTPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CINIT(SSL_SESSIONID_CACHE, LONG, 150), + + /* allowed SSH authentication methods */ + CINIT(SSH_AUTH_TYPES, LONG, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152), + CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CINIT(FTP_SSL_CCC, LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CINIT(TIMEOUT_MS, LONG, 155), + CINIT(CONNECTTIMEOUT_MS, LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CINIT(HTTP_TRANSFER_DECODING, LONG, 157), + CINIT(HTTP_CONTENT_DECODING, LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CINIT(NEW_FILE_PERMS, LONG, 159), + CINIT(NEW_DIRECTORY_PERMS, LONG, 160), + + /* Set the behaviour of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CINIT(POSTREDIR, LONG, 161), + + /* used by scp/sftp to verify the host's public key */ + CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), + CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), + + /* POST volatile input fields. */ + CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CINIT(PROXY_TRANSFER_MODE, LONG, 166), + + /* Callback function for seeking in the input stream */ + CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), + CINIT(SEEKDATA, OBJECTPOINT, 168), + + /* CRL file */ + CINIT(CRLFILE, STRINGPOINT, 169), + + /* Issuer certificate */ + CINIT(ISSUERCERT, STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CINIT(ADDRESS_SCOPE, LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CINIT(CERTINFO, LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CINIT(USERNAME, STRINGPOINT, 173), + CINIT(PASSWORD, STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CINIT(PROXYUSERNAME, STRINGPOINT, 175), + CINIT(PROXYPASSWORD, STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CINIT(NOPROXY, STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CINIT(TFTP_BLKSIZE, LONG, 178), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */ + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CINIT(PROTOCOLS, LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + CINIT(REDIR_PROTOCOLS, LONG, 182), + + /* set the SSH knownhost file name to use */ + CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CINIT(SSH_KEYDATA, OBJECTPOINT, 185), + + /* set the SMTP mail originator */ + CINIT(MAIL_FROM, STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CINIT(MAIL_RCPT, SLISTPOINT, 187), + + /* FTP: send PRET before PASV */ + CINIT(FTP_USE_PRET, LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CINIT(RTSP_REQUEST, LONG, 189), + + /* The RTSP session identifier */ + CINIT(RTSP_SESSION_ID, STRINGPOINT, 190), + + /* The RTSP stream URI */ + CINIT(RTSP_STREAM_URI, STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CINIT(RTSP_TRANSPORT, STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CINIT(RTSP_CLIENT_CSEQ, LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CINIT(RTSP_SERVER_CSEQ, LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CINIT(INTERLEAVEDATA, OBJECTPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CINIT(WILDCARDMATCH, LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CINIT(CHUNK_DATA, OBJECTPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CINIT(FNMATCH_DATA, OBJECTPOINT, 202), + + /* send linked-list of name:port:address sets */ + CINIT(RESOLVE, SLISTPOINT, 203), + + /* Set a username for authenticated TLS */ + CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CINIT(TLSAUTH_TYPE, STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CINIT(TRANSFER_ENCODING, LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), + CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), + + /* allow GSSAPI credential delegation */ + CINIT(GSSAPI_DELEGATION, LONG, 210), + + /* Set the name servers to use for DNS resolution */ + CINIT(DNS_SERVERS, STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CINIT(ACCEPTTIMEOUT_MS, LONG, 212), + + /* Set TCP keepalive */ + CINIT(TCP_KEEPALIVE, LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CINIT(TCP_KEEPIDLE, LONG, 214), + CINIT(TCP_KEEPINTVL, LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CINIT(SSL_OPTIONS, LONG, 216), + + /* Set the SMTP auth originator */ + CINIT(MAIL_AUTH, STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CINIT(SASL_IR, LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CINIT(XOAUTH2_BEARER, STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_INTERFACE, STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223), + + /* Set authentication options directly */ + CINIT(LOGIN_OPTIONS, STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_NPN, LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_ALPN, LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CINIT(PROXYHEADER, SLISTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CINIT(HEADEROPT, LONG, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CINIT(SSL_VERIFYSTATUS, LONG, 232), + + /* Set if we should enable TLS false start. */ + CINIT(SSL_FALSESTART, LONG, 233), + + /* Do not squash dot-dot sequences */ + CINIT(PATH_AS_IS, LONG, 234), + + /* Proxy Service Name */ + CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235), + + /* Service Name */ + CINIT(SERVICE_NAME, STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CINIT(PIPEWAIT, LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CINIT(STREAM_WEIGHT, LONG, 239), + + /* Set stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS, OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CINIT(TFTP_NO_OPTIONS, LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CINIT(CONNECT_TO, SLISTPOINT, 243), + + /* Set TCP Fast Open */ + CINIT(TCP_FASTOPEN, LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CINIT(KEEP_SENDING_ON_ERROR, LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAINFO, STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAPATH, STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CINIT(PROXY_SSL_VERIFYPEER, LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CINIT(PROXY_SSL_VERIFYHOST, LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CINIT(PROXY_SSLVERSION, LONG, 250), + + /* Set a username for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CINIT(PROXY_SSLCERT, STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CINIT(PROXY_SSLKEY, STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259), + + /* CRL file for proxy */ + CINIT(PROXY_CRLFILE, STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CINIT(PROXY_SSL_OPTIONS, LONG, 261), + + /* Name of pre proxy to use. */ + CINIT(PRE_PROXY, STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265), + + /* The request target, instead of extracted from the URL */ + CINIT(REQUEST_TARGET, STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CINIT(SOCKS5_AUTH, LONG, 267), + + /* Enable/disable SSH compression */ + CINIT(SSH_COMPRESSION, LONG, 268), + + /* Post MIME data. */ + CINIT(MIMEPOST, OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CINIT(TIMEVALUE_LARGE, OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271), + + /* Function that will be called before a resolver request is made */ + CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CINIT(HAPROXYPROTOCOL, LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CINIT(TLS13_CIPHERS, STRINGPOINT, 276), + CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278), + + /* DNS-over-HTTPS URL */ + CINIT(DOH_URL, STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CINIT(UPLOAD_BUFFERSIZE, LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CINIT(UPKEEP_INTERVAL_MS, LONG, 281), + + /* Specify URL using CURL URL API. */ + CINIT(CURLU, OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CINIT(TRAILERDATA, OBJECTPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CINIT(HTTP09_ALLOWED, LONG, 285), + + /* alt-svc control bitmask */ + CINIT(ALTSVC_CTRL, LONG, 286), + + /* alt-svc cache file name to possibly read from/write to */ + CINIT(ALTSVC, STRINGPOINT, 287), + + /* maximum age of a connection to consider it for reuse (in seconds) */ + CINIT(MAXAGE_CONN, LONG, 288), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ +#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum { + CURL_SSLVERSION_MAX_NONE = 0, + CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16), + CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16), + CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16), + CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16), + CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16), + + /* never use, keep last */ + CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16) +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* Special size_t value signaling a zero-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime_s curl_mime; /* Mime context. */ +typedef struct curl_mimepart_s curl_mimepart; /* Mime part context. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote file name. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +/* Old form API. */ +/* name is uppercase CURLFORM_ */ +#ifdef CFINIT +#undef CFINIT +#endif + +#ifdef CURL_ISOCPP +#define CFINIT(name) CURLFORM_ ## name +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define CFINIT(name) CURLFORM_/**/name +#endif + +typedef enum { + CFINIT(NOTHING), /********* the first one is unused ************/ + + /* */ + CFINIT(COPYNAME), + CFINIT(PTRNAME), + CFINIT(NAMELENGTH), + CFINIT(COPYCONTENTS), + CFINIT(PTRCONTENTS), + CFINIT(CONTENTSLENGTH), + CFINIT(FILECONTENT), + CFINIT(ARRAY), + CFINIT(OBSOLETE), + CFINIT(FILE), + + CFINIT(BUFFER), + CFINIT(BUFFERPTR), + CFINIT(BUFFERLENGTH), + + CFINIT(CONTENTTYPE), + CFINIT(CONTENTHEADER), + CFINIT(FILENAME), + CFINIT(END), + CFINIT(OBSOLETE2), + + CFINIT(STREAM), + CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +#undef CFINIT /* done */ + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines with be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). + * If both id and name are specified, the name will be ignored. If neither id + * nor name are specified, the function will fail with + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the + * NULL-terminated list of available backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated + * list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +typedef struct { + curl_sslbackend id; + const char *name; +} curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS + and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + /* Fill in new entries below here! */ + + /* Preferably these would be defined conditionally based on the + sizeof curl_off_t being 64-bits */ + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + + CURLINFO_LASTONE = 56 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_FIFTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_FIFTH + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* __CURL_CURL_H */ diff --git a/libcurl/include/curl/curlver.h b/libcurl/include/curl/curlver.h new file mode 100644 index 0000000..3e8789e --- /dev/null +++ b/libcurl/include/curl/curlver.h @@ -0,0 +1,77 @@ +#ifndef __CURL_CURLVER_H +#define __CURL_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.65.3" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 65 +#define LIBCURL_VERSION_PATCH 3 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparions by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x074103 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +#define LIBCURL_TIMESTAMP "2019-07-19" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* __CURL_CURLVER_H */ diff --git a/libcurl/include/curl/easy.h b/libcurl/include/curl/easy.h new file mode 100644 index 0000000..f42a8a9 --- /dev/null +++ b/libcurl/include/curl/easy.h @@ -0,0 +1,112 @@ +#ifndef __CURL_EASY_H +#define __CURL_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + + +/* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ +CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libcurl/include/curl/mprintf.h b/libcurl/include/curl/mprintf.h new file mode 100644 index 0000000..e20f546 --- /dev/null +++ b/libcurl/include/curl/mprintf.h @@ -0,0 +1,50 @@ +#ifndef __CURL_MPRINTF_H +#define __CURL_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* __CURL_MPRINTF_H */ diff --git a/libcurl/include/curl/multi.h b/libcurl/include/curl/multi.h new file mode 100644 index 0000000..b19dbaf --- /dev/null +++ b/libcurl/include/curl/multi.h @@ -0,0 +1,441 @@ +#ifndef __CURL_MULTI_H +#define __CURL_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_multi CURLM; +#else +typedef void CURLM; +#endif + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic information. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a zero-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +#undef CINIT /* re-using the same name as in curl.h */ + +#ifdef CURL_ISOCPP +#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLMOPT_/**/name = type + number +#endif + +typedef enum { + /* This is the socket callback function pointer */ + CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CINIT(SOCKETDATA, OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CINIT(PIPELINING, LONG, 3), + + /* This is the timer callback function pointer */ + CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CINIT(TIMERDATA, OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CINIT(MAXCONNECTS, LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CINIT(MAX_HOST_CONNECTIONS, LONG, 7), + + /* maximum number of requests in a pipeline */ + CINIT(MAX_PIPELINE_LENGTH, LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10), + + /* a list of site names(+port) that are blacklisted from + pipelining */ + CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11), + + /* a list of server types that are blacklisted from + pipelining */ + CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13), + + /* This is the server push callback function pointer */ + CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CINIT(PUSHDATA, OBJECTPOINT, 15), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. + * + * Returns: CURL_PUSH_OK or CURL_PUSH_DENY. + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/libcurl/include/curl/stdcheaders.h b/libcurl/include/curl/stdcheaders.h new file mode 100644 index 0000000..027b6f4 --- /dev/null +++ b/libcurl/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef __STDC_HEADERS_H +#define __STDC_HEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* __STDC_HEADERS_H */ diff --git a/libcurl/include/curl/system.h b/libcurl/include/curl/system.h new file mode 100644 index 0000000..1e555ec --- /dev/null +++ b/libcurl/include/curl/system.h @@ -0,0 +1,493 @@ +#ifndef __CURL_SYSTEM_H +#define __CURL_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit + * wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SALFORDC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TURBOC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__LCC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__MWERKS__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(_WIN32_WCE) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__MINGW32__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_WS2TCPIP_H 1 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TINYC__) /* also known as tcc */ + +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */ +# if !defined(__LP64) && (defined(__ILP32) || \ + defined(__i386) || \ + defined(__sparcv8) || \ + defined(__sparcv8plus)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64) || \ + defined(__amd64) || defined(__sparcv9) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__xlc__) /* IBM xlc compiler */ +# if !defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) && !defined(_SCO_DS) +# if !defined(__LP64__) && \ + (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \ + defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__) || \ + defined(__XTENSA__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32 bit style */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +#endif + +#ifdef _AIX +/* AIX needs */ +#define CURL_PULL_SYS_POLL_H +#endif + + +/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */ +/* ws2tcpip.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_WS2TCPIP_H +# include +# include +# include +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */ +/* sys/poll.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define __CURL_OFF_T_C_HLPR2(x) x +# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ + __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ + __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +#endif /* __CURL_SYSTEM_H */ diff --git a/libcurl/include/curl/typecheck-gcc.h b/libcurl/include/curl/typecheck-gcc.h new file mode 100644 index 0000000..eeb36ab --- /dev/null +++ b/libcurl/include/curl/typecheck-gcc.h @@ -0,0 +1,698 @@ +#ifndef __CURL_TYPECHECK_GCC_H +#define __CURL_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(_curl_is_sometype_option(_curl_opt)) + * if(!_curl_is_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define _curl_is_sometype_option, _curl_is_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ +__extension__ ({ \ + __typeof__(option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(_curl_is_long_option(_curl_opt)) \ + if(!_curl_is_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(_curl_is_off_t_option(_curl_opt)) \ + if(!_curl_is_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(_curl_is_string_option(_curl_opt)) \ + if(!_curl_is_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(_curl_is_write_cb_option(_curl_opt)) \ + if(!_curl_is_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \ + if(!_curl_is_resolver_start_callback(value)) \ + _curl_easy_setopt_err_resolver_start_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!_curl_is_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!_curl_is_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!_curl_is_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!_curl_is_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!_curl_is_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!_curl_is_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!_curl_is_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(_curl_is_conv_cb_option(_curl_opt)) \ + if(!_curl_is_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!_curl_is_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(_curl_is_cb_data_option(_curl_opt)) \ + if(!_curl_is_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!_curl_is_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!_curl_is_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(_curl_is_postfields_option(_curl_opt)) \ + if(!_curl_is_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!_curl_is_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if((_curl_opt) == CURLOPT_MIMEPOST) \ + if(!_curl_is_ptr((value), curl_mime)) \ + _curl_easy_setopt_err_curl_mimepost(); \ + if(_curl_is_slist_option(_curl_opt)) \ + if(!_curl_is_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!_curl_is_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ +}) + +/* wraps curl_easy_getinfo() with typechecking */ +#define curl_easy_getinfo(handle, info, arg) \ +__extension__ ({ \ + __typeof__(info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(_curl_is_string_info(_curl_info)) \ + if(!_curl_is_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(_curl_is_long_info(_curl_info)) \ + if(!_curl_is_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(_curl_is_double_info(_curl_info)) \ + if(!_curl_is_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(_curl_is_slist_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + if(_curl_is_tlssessioninfo_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \ + _curl_easy_getinfo_err_curl_tlssesssioninfo(); \ + if(_curl_is_certinfo_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_certinfo *)) \ + _curl_easy_getinfo_err_curl_certinfo(); \ + if(_curl_is_socket_info(_curl_info)) \ + if(!_curl_is_arr((arg), curl_socket_t)) \ + _curl_easy_getinfo_err_curl_socket(); \ + if(_curl_is_off_t_info(_curl_info)) \ + if(!_curl_is_arr((arg), curl_off_t)) \ + _curl_easy_getinfo_err_curl_off_t(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ +}) + +/* + * For now, just make sure that the functions are called with three arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define _CURL_WARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +_CURL_WARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string ('char *' or char[]) argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback, + "curl_easy_setopt expects a " + "curl_resolver_start_callback argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +_CURL_WARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a 'FILE *' argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost, + "curl_easy_setopt expects a 'curl_mime *' " + "argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") +_CURL_WARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +_CURL_WARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to 'char *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +_CURL_WARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t, + "curl_easy_getinfo expects a pointer to curl_off_t for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define _curl_is_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define _curl_is_off_t_option(option) \ + ((option) > CURLOPTTYPE_OFF_T) + +/* evaluates to true if option takes a char* argument */ +#define _curl_is_string_option(option) \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_ALTSVC || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DOH_URL || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_TLS13_CIPHERS || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_REQUEST_TARGET || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_TLS13_CIPHERS || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define _curl_is_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define _curl_is_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define _curl_is_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PRIVATE || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_RESOLVER_START_DATA || \ + (option) == CURLOPT_TRAILERDATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define _curl_is_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define _curl_is_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + (option) == CURLOPT_CONNECT_TO || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define _curl_is_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) + +/* evaluates to true if info expects a pointer to long argument */ +#define _curl_is_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define _curl_is_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define _curl_is_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define _curl_is_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define _curl_is_socket_info(info) \ + (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T) + +/* true if info expects a pointer to curl_off_t argument */ +#define _curl_is_off_t_info(info) \ + (CURLINFO_OFF_T < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true if expr is a pointer */ +#define _curl_is_any_ptr(expr) \ + (sizeof(expr) == sizeof(void *)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define _curl_is_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define _curl_is_ptr(expr, type) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define _curl_is_arr(expr, type) \ + (_curl_is_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define _curl_is_string(expr) \ + (_curl_is_arr((expr), char) || \ + _curl_is_arr((expr), signed char) || \ + _curl_is_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define _curl_is_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define _curl_is_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define _curl_is_error_buffer(expr) \ + (_curl_is_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define _curl_is_cb_data(expr) \ + (_curl_is_ptr((expr), void) || \ + _curl_is_ptr((expr), FILE)) +#else /* be less strict */ +#define _curl_is_cb_data(expr) \ + _curl_is_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define _curl_is_FILE(expr) \ + (_curl_is_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define _curl_is_postfields(expr) \ + (_curl_is_ptr((expr), void) || \ + _curl_is_arr((expr), char) || \ + _curl_is_arr((expr), unsigned char)) + +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define _curl_callback_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func) *, type)) + +/* evaluates to true if expr is of type curl_resolver_start_callback */ +#define _curl_is_resolver_start_callback(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_resolver_start_callback)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define _curl_is_read_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), __typeof__(fread) *) || \ + _curl_callback_compatible((expr), curl_read_callback) || \ + _curl_callback_compatible((expr), _curl_read_callback1) || \ + _curl_callback_compatible((expr), _curl_read_callback2) || \ + _curl_callback_compatible((expr), _curl_read_callback3) || \ + _curl_callback_compatible((expr), _curl_read_callback4) || \ + _curl_callback_compatible((expr), _curl_read_callback5) || \ + _curl_callback_compatible((expr), _curl_read_callback6)) +typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define _curl_is_write_cb(expr) \ + (_curl_is_read_cb(expr) || \ + _curl_callback_compatible((expr), __typeof__(fwrite) *) || \ + _curl_callback_compatible((expr), curl_write_callback) || \ + _curl_callback_compatible((expr), _curl_write_callback1) || \ + _curl_callback_compatible((expr), _curl_write_callback2) || \ + _curl_callback_compatible((expr), _curl_write_callback3) || \ + _curl_callback_compatible((expr), _curl_write_callback4) || \ + _curl_callback_compatible((expr), _curl_write_callback5) || \ + _curl_callback_compatible((expr), _curl_write_callback6)) +typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define _curl_is_ioctl_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_ioctl_callback) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback1) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback2) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback3) || \ + _curl_callback_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define _curl_is_sockopt_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_sockopt_callback) || \ + _curl_callback_compatible((expr), _curl_sockopt_callback1) || \ + _curl_callback_compatible((expr), _curl_sockopt_callback2)) +typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define _curl_is_opensocket_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_opensocket_callback) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback1) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback2) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback3) || \ + _curl_callback_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (*_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define _curl_is_progress_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_progress_callback) || \ + _curl_callback_compatible((expr), _curl_progress_callback1) || \ + _curl_callback_compatible((expr), _curl_progress_callback2)) +typedef int (*_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (*_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define _curl_is_debug_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_debug_callback) || \ + _curl_callback_compatible((expr), _curl_debug_callback1) || \ + _curl_callback_compatible((expr), _curl_debug_callback2) || \ + _curl_callback_compatible((expr), _curl_debug_callback3) || \ + _curl_callback_compatible((expr), _curl_debug_callback4) || \ + _curl_callback_compatible((expr), _curl_debug_callback5) || \ + _curl_callback_compatible((expr), _curl_debug_callback6) || \ + _curl_callback_compatible((expr), _curl_debug_callback7) || \ + _curl_callback_compatible((expr), _curl_debug_callback8)) +typedef int (*_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (*_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (*_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (*_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (*_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (*_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define _curl_is_ssl_ctx_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_ssl_ctx_callback) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \ + _curl_callback_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, + const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define _curl_is_conv_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_conv_callback) || \ + _curl_callback_compatible((expr), _curl_conv_callback1) || \ + _curl_callback_compatible((expr), _curl_conv_callback2) || \ + _curl_callback_compatible((expr), _curl_conv_callback3) || \ + _curl_callback_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define _curl_is_seek_cb(expr) \ + (_curl_is_NULL(expr) || \ + _curl_callback_compatible((expr), curl_seek_callback) || \ + _curl_callback_compatible((expr), _curl_seek_callback1) || \ + _curl_callback_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* __CURL_TYPECHECK_GCC_H */ diff --git a/libcurl/include/curl/urlapi.h b/libcurl/include/curl/urlapi.h new file mode 100644 index 0000000..58e89d8 --- /dev/null +++ b/libcurl/include/curl/urlapi.h @@ -0,0 +1,123 @@ +#ifndef __CURL_URLAPI_H +#define __CURL_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* the error codes for the URL API */ +typedef enum { + CURLUE_OK, + CURLUE_BAD_HANDLE, /* 1 */ + CURLUE_BAD_PARTPOINTER, /* 2 */ + CURLUE_MALFORMED_INPUT, /* 3 */ + CURLUE_BAD_PORT_NUMBER, /* 4 */ + CURLUE_UNSUPPORTED_SCHEME, /* 5 */ + CURLUE_URLDECODE, /* 6 */ + CURLUE_OUT_OF_MEMORY, /* 7 */ + CURLUE_USER_NOT_ALLOWED, /* 8 */ + CURLUE_UNKNOWN_PART, /* 9 */ + CURLUE_NO_SCHEME, /* 10 */ + CURLUE_NO_USER, /* 11 */ + CURLUE_NO_PASSWORD, /* 12 */ + CURLUE_NO_OPTIONS, /* 13 */ + CURLUE_NO_HOST, /* 14 */ + CURLUE_NO_PORT, /* 15 */ + CURLUE_NO_QUERY, /* 16 */ + CURLUE_NO_FRAGMENT /* 17 */ +} CURLUcode; + +typedef enum { + CURLUPART_URL, + CURLUPART_SCHEME, + CURLUPART_USER, + CURLUPART_PASSWORD, + CURLUPART_OPTIONS, + CURLUPART_HOST, + CURLUPART_PORT, + CURLUPART_PATH, + CURLUPART_QUERY, + CURLUPART_FRAGMENT, + CURLUPART_ZONEID /* added in 7.65.0 */ +} CURLUPart; + +#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */ +#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set, + if the port number matches the + default for the scheme */ +#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if + missing */ +#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */ +#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */ +#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */ +#define CURLU_URLDECODE (1<<6) /* URL decode on get */ +#define CURLU_URLENCODE (1<<7) /* URL encode on set */ +#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ +#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ + +typedef struct Curl_URL CURLU; + +/* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url(void); + +/* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ +CURL_EXTERN void curl_url_cleanup(CURLU *handle); + +/* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url_dup(CURLU *in); + +/* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ +CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, + char **part, unsigned int flags); + +/* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ +CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, + const char *part, unsigned int flags); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/libcurl/lib/CMakeLists.txt b/libcurl/lib/CMakeLists.txt new file mode 100644 index 0000000..eca9a8a --- /dev/null +++ b/libcurl/lib/CMakeLists.txt @@ -0,0 +1,121 @@ +set(LIB_NAME libcurl) + +if(BUILD_SHARED_LIBS) + set(CURL_STATICLIB NO) +else() + set(CURL_STATICLIB YES) +endif() + +# Use: +# * CURL_STATICLIB +configure_file(curl_config.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h) + +transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") +include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake) + +list(APPEND HHEADERS + ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h + ) + +if(MSVC) + list(APPEND CSOURCES libcurl.rc) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4127") +endif() + +# SET(CSOURCES +# # memdebug.c -not used +# # nwlib.c - Not used +# # strtok.c - specify later +# # strtoofft.c - specify later +# ) + +# # if we have Kerberos 4, right now this is never on +# #OPTION(CURL_KRB4 "Use Kerberos 4" OFF) +# IF(CURL_KRB4) +# SET(CSOURCES ${CSOURCES} +# krb4.c +# security.c +# ) +# ENDIF(CURL_KRB4) + +# #OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF) +# MARK_AS_ADVANCED(CURL_MALLOC_DEBUG) +# IF(CURL_MALLOC_DEBUG) +# SET(CSOURCES ${CSOURCES} +# memdebug.c +# ) +# ENDIF(CURL_MALLOC_DEBUG) + +# # only build compat strtoofft if we need to +# IF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64) +# SET(CSOURCES ${CSOURCES} +# strtoofft.c +# ) +# ENDIF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64) + + +# The rest of the build + +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/..) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +if(USE_ARES) + include_directories(${CARES_INCLUDE_DIR}) +endif() + +add_library( + ${LIB_NAME} + ${HHEADERS} ${CSOURCES} + ) + +if(MSVC AND NOT BUILD_SHARED_LIBS) + set_target_properties(${LIB_NAME} PROPERTIES STATIC_LIBRARY_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) +endif() + +if(NOT BUILD_SHARED_LIBS) + set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB) +endif() + +target_link_libraries(${LIB_NAME} ${CURL_LIBS}) + +if(WIN32) + add_definitions(-D_USRDLL) +endif() + +set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL) + +if(HIDES_CURL_PRIVATE_SYMBOLS) + set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") + set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE}) +endif() + +# Remove the "lib" prefix since the library is already named "libcurl". +set_target_properties(${LIB_NAME} PROPERTIES PREFIX "") +set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "") + +if(WIN32) + if(BUILD_SHARED_LIBS) + # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib" + set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib") + endif() +endif() + +target_include_directories(${LIB_NAME} INTERFACE + $ + $) + +install(TARGETS ${LIB_NAME} + EXPORT ${TARGETS_EXPORT_NAME} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +export(TARGETS ${LIB_NAME} + APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake + NAMESPACE CURL:: +) diff --git a/libcurl/lib/Makefile.Watcom b/libcurl/lib/Makefile.Watcom new file mode 100644 index 0000000..942cd0c --- /dev/null +++ b/libcurl/lib/Makefile.Watcom @@ -0,0 +1,274 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 2005 - 2009, Gisle Vanem . +# Copyright (C) 2005 - 2017, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +#*************************************************************************** + +# +# Watcom / OpenWatcom / Win32 makefile for libcurl. +# + +.ERASE + +!if $(__VERSION__) < 1280 +!message !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!message ! This Open Watcom version is too old and is no longer supported ! +!message ! Please download latest version from www.openwatcom.org ! +!message !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!error Unsupported version of Open Watcom +!endif + +!ifndef %watcom +!error WATCOM environment variable not set! +!endif + +# In order to process Makefile.inc wmake must be called with -u switch! +!ifndef %MAKEFLAGS +!error You MUST call wmake with the -u switch! +!endif + +!ifdef %libname +LIBNAME = $(%libname) +!else +LIBNAME = libcurl +!endif +TARGETS = $(LIBNAME).dll $(LIBNAME).lib + +CC = wcc386 +LD = wlink +AR = wlib +RC = wrc + +!ifdef __LOADDLL__ +! loaddll wcc386 wccd386 +! loaddll wpp386 wppd386 +! loaddll wlib wlibd +! loaddll wlink wlinkd +!endif + +!ifdef __LINUX__ +CP = cp +MD = mkdir -p +!else +CP = copy 2>NUL +MD = mkdir +!endif +!if $(__VERSION__) > 1290 +RD = rm -rf +!else ifdef __UNIX__ +RD = rm -rf +!else +RD = rmdir /q /s 2>NUL +!endif + +SYS_INCL = -I"$(%watcom)/h/nt" -I"$(%watcom)/h" + +CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm & + -wcd=201 -bt=nt -d+ -dWIN32 & + -dBUILDING_LIBCURL -I. -I"../include" $(SYS_INCL) + +!ifdef %debug +DEBUG = -dDEBUG=1 -dDEBUGBUILD +CFLAGS += -d3 $(DEBUG) +!else +CFLAGS += -d0 +!endif + +!ifdef %use_ipv6 +CFLAGS += -d_WIN32_WINNT=0x0501 -dENABLE_IPV6 +!endif + +!ifdef %use_sspi +CFLAGS += -dUSE_WINDOWS_SSPI +!endif + +!ifdef %use_winssl +CFLAGS += -dUSE_WINDOWS_SSPI +CFLAGS += -DUSE_SCHANNEL +!endif + +!ifdef %use_winidn +CFLAGS += -dWINVER=0x0600 -dUSE_WIN32_IDN +! if $(__VERSION__) <= 1290 +CFLAGS += -dWANT_IDN_PROTOTYPES +! endif +!endif + +# +# Change to suite. +# +!ifdef %zlib_root +ZLIB_ROOT = $(%zlib_root) +!else +ZLIB_ROOT = ../../zlib-1.2.8 +!endif + +!ifdef %libssh2_root +LIBSSH2_ROOT = $(%libssh2_root) +!else +LIBSSH2_ROOT = ../../libssh2-1.5.0 +!endif + +!ifdef %librtmp_root +LIBRTMP_ROOT = $(%librtmp_root) +!else +LIBRTMP_ROOT = ../../rtmpdump-2.3 +!endif + +!ifdef %openssl_root +OPENSSL_ROOT = $(%openssl_root) +!else +OPENSSL_ROOT = ../../openssl-1.0.2a +!endif + +!ifdef %ares_root +ARES_ROOT = $(%ares_root) +!else +ARES_ROOT = ../ares +!endif + +!ifdef %use_zlib +CFLAGS += -dHAVE_ZLIB_H -dHAVE_LIBZ -I"$(ZLIB_ROOT)" +!endif + +!ifdef %use_rtmp +CFLAGS += -dUSE_LIBRTMP -I"$(LIBRTMP_ROOT)" +!endif + +!ifdef %use_ssh2 +CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H -I"$(LIBSSH2_ROOT)/include" -I"$(LIBSSH2_ROOT)/win32" +!endif + +!ifdef %use_ssl +CFLAGS += -wcd=138 -dUSE_OPENSSL -I"$(OPENSSL_ROOT)/inc32" +!endif + +!ifdef %use_ares +CFLAGS += -dUSE_ARES -I"$(ARES_ROOT)" +!endif + +!ifdef %use_watt32 +CFLAGS += -dUSE_WATT32 -I"$(%watt_root)/inc" +!endif + +OBJ_BASE = WC_Win32.obj +!if $(__VERSION__) > 1290 +OBJ_STAT = $(OBJ_BASE)/stat +OBJ_DYN = $(OBJ_BASE)/dyn +!else ifdef __UNIX__ +OBJ_STAT = $(OBJ_BASE)/stat +OBJ_DYN = $(OBJ_BASE)/dyn +!else +OBJ_STAT = $(OBJ_BASE)\stat +OBJ_DYN = $(OBJ_BASE)\dyn +!endif + +LINK_ARG = $(OBJ_DYN)/wlink.arg +LIB_ARG = $(OBJ_STAT)/wlib.arg + +!include Makefile.inc + +OBJS1 = ./$(CSOURCES:.c=.obj) +OBJS2 = $(OBJS1:vtls/=) +OBJS3 = $(OBJS2:vauth/=) +OBJS4 = $(OBJS3: = ./) +OBJS_STAT = $(OBJS4:./=$(OBJ_STAT)/) +OBJS_DYN = $(OBJS4:./=$(OBJ_DYN)/) + +RESOURCE = $(OBJ_DYN)/libcurl.res + +DIRS = $(OBJ_BASE) $(OBJ_BASE)/stat $(OBJ_BASE)/dyn + +.c : vauth vtls + +all: $(DIRS) $(TARGETS) .SYMBOLIC + @echo Welcome to libcurl + +clean: .SYMBOLIC + -rm -f $(OBJS_STAT) + -rm -f $(OBJS_DYN) + -rm -f $(RESOURCE) $(LINK_ARG) $(LIB_ARG) + +vclean distclean: clean .SYMBOLIC + -rm -f $(TARGETS) $(LIBNAME).map $(LIBNAME).sym + -$(RD) $(OBJ_STAT) + -$(RD) $(OBJ_DYN) + -$(RD) $(OBJ_BASE) + +$(DIRS): + -$(MD) $^@ + +$(LIBNAME).dll: $(OBJS_DYN) $(RESOURCE) $(__MAKEFILES__) + %create $(LINK_ARG) + @%append $(LINK_ARG) system nt dll +!ifdef %debug + @%append $(LINK_ARG) debug all + @%append $(LINK_ARG) option symfile +!endif + @%append $(LINK_ARG) option quiet, caseexact, eliminate + @%append $(LINK_ARG) option map=$(OBJ_DYN)/$(LIBNAME).map + @%append $(LINK_ARG) option implib=$(LIBNAME)_imp.lib + @%append $(LINK_ARG) option res=$(RESOURCE) + @for %f in ($(OBJS_DYN)) do @%append $(LINK_ARG) file %f + @%append $(LINK_ARG) library wldap32.lib +!ifdef %use_watt32 + @%append $(LINK_ARG) library '$(%watt_root)/lib/wattcpw_imp.lib' +!else + @%append $(LINK_ARG) library ws2_32.lib +!endif +!ifdef %use_zlib + @%append $(LINK_ARG) library '$(ZLIB_ROOT)/zlib.lib' +!endif +!ifdef %use_rtmp + @%append $(LINK_ARG) library '$(LIBRTMP_ROOT)/librtmp/librtmp.lib' +!endif +!ifdef %use_ssh2 + @%append $(LINK_ARG) library '$(LIBSSH2_ROOT)/win32/libssh2.lib' +!endif +!ifdef %use_ssl + @%append $(LINK_ARG) library '$(OPENSSL_ROOT)/out32/libeay32.lib' + @%append $(LINK_ARG) library '$(OPENSSL_ROOT)/out32/ssleay32.lib' +!endif +!ifdef %use_ares + @%append $(LINK_ARG) library '$(ARES_ROOT)/cares.lib' +!endif +!ifdef %use_winidn +! if $(__VERSION__) > 1290 + @%append $(LINK_ARG) library normaliz.lib +! else + @%append $(LINK_ARG) import '_IdnToAscii@20' 'NORMALIZ.DLL'.'IdnToAscii' + @%append $(LINK_ARG) import '_IdnToUnicode@20' 'NORMALIZ.DLL'.'IdnToUnicode' +! endif +!endif + $(LD) name $^@ @$(LINK_ARG) + +$(LIBNAME).lib: $(OBJS_STAT) + %create $(LIB_ARG) + @for %f in ($<) do @%append $(LIB_ARG) +- %f + $(AR) -q -b -c -pa $^@ @$(LIB_ARG) + +$(RESOURCE): libcurl.rc + $(RC) $(DEBUG) -q -r -zm -bt=nt -I"../include" $(SYS_INCL) $[@ -fo=$^@ + +.c{$(OBJ_DYN)}.obj: + $(CC) $(CFLAGS) -bd -br $[@ -fo=$^@ + +.c{$(OBJ_STAT)}.obj: + $(CC) $(CFLAGS) -DCURL_STATICLIB $[@ -fo=$^@ diff --git a/libcurl/lib/Makefile.am b/libcurl/lib/Makefile.am new file mode 100644 index 0000000..7c258b3 --- /dev/null +++ b/libcurl/lib/Makefile.am @@ -0,0 +1,154 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +AUTOMAKE_OPTIONS = foreign nostdinc + +CMAKE_DIST = CMakeLists.txt curl_config.h.cmake + +EXTRA_DIST = Makefile.m32 config-win32.h \ + config-win32ce.h config-riscos.h config-mac.h curl_config.h.in \ + makefile.dj config-dos.h libcurl.plist libcurl.rc config-amigaos.h \ + makefile.amiga Makefile.netware nwlib.c nwos.c config-win32ce.h \ + config-os400.h setup-os400.h config-symbian.h Makefile.Watcom \ + config-tpf.h mk-ca-bundle.pl mk-ca-bundle.vbs $(CMAKE_DIST) \ + firefox-db2pem.sh config-vxworks.h Makefile.vxworks checksrc.pl + +lib_LTLIBRARIES = libcurl.la + +if BUILD_UNITTESTS +noinst_LTLIBRARIES = libcurlu.la +else +noinst_LTLIBRARIES = +endif + +# This might hold -Werror +CFLAGS += @CURL_CFLAG_EXTRAS@ + +# Specify our include paths here, and do it relative to $(top_srcdir) and +# $(top_builddir), to ensure that these paths which belong to the library +# being currently built and tested are searched before the library which +# might possibly already be installed in the system. +# +# $(top_srcdir)/include is for libcurl's external include files +# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file +# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "private" files +# $(top_builddir)/ares is for in-tree c-ares's generated ares_build.h file +# $(top_srcdir)/ares is for in-tree c-ares's external include files + +AM_CPPFLAGS = -I$(top_srcdir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/lib + +if USE_EMBEDDED_ARES +AM_CPPFLAGS += -I$(top_builddir)/ares \ + -I$(top_srcdir)/ares +endif + +# Prevent LIBS from being used for all link targets +LIBS = $(BLANK_AT_MAKETIME) + +VERSIONINFO=-version-info 9:0:5 +# This flag accepts an argument of the form current[:revision[:age]]. So, +# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to +# 1. +# +# Here's the simplified rule guide on how to change -version-info: +# (current version is C:R:A) +# +# 1. if there are only source changes, use C:R+1:A +# 2. if interfaces were added use C+1:0:A+1 +# 3. if interfaces were removed, then use C+1:0:0 +# +# For the full guide on libcurl ABI rules, see docs/libcurl/ABI + +AM_CPPFLAGS += -DBUILDING_LIBCURL +AM_LDFLAGS = +AM_CFLAGS = + +libcurl_la_CPPFLAGS_EXTRA = +libcurl_la_LDFLAGS_EXTRA = +libcurl_la_CFLAGS_EXTRA = + +if CURL_LT_SHLIB_USE_VERSION_INFO +libcurl_la_LDFLAGS_EXTRA += $(VERSIONINFO) +endif + +if CURL_LT_SHLIB_USE_NO_UNDEFINED +libcurl_la_LDFLAGS_EXTRA += -no-undefined +endif + +if CURL_LT_SHLIB_USE_MIMPURE_TEXT +libcurl_la_LDFLAGS_EXTRA += -mimpure-text +endif + +if CURL_LT_SHLIB_USE_VERSIONED_SYMBOLS +libcurl_la_LDFLAGS_EXTRA += -Wl,--version-script=libcurl.vers +else +# if symbol-hiding is enabled, hide them! +if DOING_CURL_SYMBOL_HIDING +libcurl_la_LDFLAGS_EXTRA += -export-symbols-regex '^curl_.*' +endif +endif + +if USE_CPPFLAG_CURL_STATICLIB +libcurl_la_CPPFLAGS_EXTRA += -DCURL_STATICLIB +endif + +if DOING_CURL_SYMBOL_HIDING +libcurl_la_CPPFLAGS_EXTRA += -DCURL_HIDDEN_SYMBOLS +libcurl_la_CFLAGS_EXTRA += $(CFLAG_CURL_SYMBOL_HIDING) +endif + +libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA) +libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS) +libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) + +libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS +libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS) +libcurlu_la_CFLAGS = $(AM_CFLAGS) + +# Makefile.inc provides the CSOURCES and HHEADERS defines +include Makefile.inc + +libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS) +libcurlu_la_SOURCES = $(CSOURCES) $(HHEADERS) + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) + +checksrc: + $(CHECKSRC)(@PERL@ $(srcdir)/checksrc.pl -D$(srcdir) -W$(srcdir)/curl_config.h \ + $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch]) + +if CURLDEBUG +# for debug builds, we scan the sources on all regular make invokes +all-local: checksrc +endif + +# disable the tests that are mostly causing false positives +TIDYFLAGS=-checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-valist.Uninitialized,-clang-analyzer-core.NonNullParamChecker,-clang-analyzer-core.NullDereference -quiet + +TIDY:=clang-tidy + +tidy: + $(TIDY) $(CSOURCES) $(TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H diff --git a/libcurl/lib/Makefile.b32 b/libcurl/lib/Makefile.b32 new file mode 100644 index 0000000..5b5b5fa --- /dev/null +++ b/libcurl/lib/Makefile.b32 @@ -0,0 +1,185 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 2000, Jaepil Kim, . +# Copyright (C) 2001 - 2015, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +#*************************************************************************** + +############################################################ +# +# Makefile.b32 - Borland's C++ Compiler 5.X +# +# 'BCCDIR' has to be set up to point to the base directory +# of the compiler, i.e. SET BCCDIR = c:\Borland\BCC55 +# +############################################################ + +!if "$(__MAKE__)" == "" +!error __MAKE__ not defined. Use Borlands's MAKE to process this makefile. +!endif + +# Borland's $(MAKEDIR) expands to the path where make.exe is located, +# use this feature to define BCCDIR when user has not defined BCCDIR. +!ifndef BCCDIR +BCCDIR = $(MAKEDIR)\.. +!endif + +# Edit the path below to point to the base of your Zlib sources. +!ifndef ZLIB_PATH +ZLIB_PATH = ..\..\zlib-1.2.8 +!endif + +# Edit the path below to point to the base of your OpenSSL package. +!ifndef OPENSSL_PATH +OPENSSL_PATH = ..\..\openssl-1.0.2a +!endif + +# Set libcurl static lib, dll and import lib +LIBCURL_LIB = libcurl.lib +LIBCURL_DLL = libcurl.dll +LIBCURL_IMPLIB = libcurl_imp.lib + +# Setup environment +PP_CMD = cpp32 -q -P- +CC_CMD = bcc32 -q -c +LD = bcc32 +RM = del 2>NUL +MKDIR = md +RMDIR = rd /q +LIB = tlib +IMPLIB = implib + +CC_FLAGS = -5 -O2 -tWM -w -w-aus -w-ccc -w-dup -w-prc -w-pro -w-rch -w-sig -w-spa -w-inl -w-pia -w-pin -Dinline=__inline +LIBFLAGS = /C /P32 +LDFLAGS = -q -lq -laa -tWD + +SRCDIR = .;.\vauth;.\vtls +OBJDIR = .\BCC_objs +INCDIRS = -I.;.\lib;..\include +LINKLIB = $(BCCDIR)\lib\cw32mt.lib $(BCCDIR)\lib\ws2_32.lib +DEFINES = -DNDEBUG -DWIN32 -DBUILDING_LIBCURL + +# By default SSPI support is enabled for BCC +!ifndef DISABLE_SSPI +DEFINES = $(DEFINES) -DUSE_WINDOWS_SSPI +!endif + +# By default LDAP support is disabled for BCC +!ifndef WITH_LDAP +DEFINES = $(DEFINES) -DCURL_DISABLE_LDAP +!endif + +# ZLIB support is enabled setting WITH_ZLIB=1 +!ifdef WITH_ZLIB +DEFINES = $(DEFINES) -DHAVE_LIBZ -DHAVE_ZLIB_H +INCDIRS = $(INCDIRS);$(ZLIB_PATH) +LINKLIB = $(LINKLIB) $(ZLIB_PATH)\zlib.lib +!endif + +# SSL support is enabled setting WITH_SSL=1 +!ifdef WITH_SSL +DEFINES = $(DEFINES) -DUSE_OPENSSL +INCDIRS = $(INCDIRS);$(OPENSSL_PATH)\inc32;$(OPENSSL_PATH)\inc32\openssl +LINKLIB = $(LINKLIB) $(OPENSSL_PATH)\out32\ssleay32.lib $(OPENSSL_PATH)\out32\libeay32.lib +!endif + +.autodepend + +.path.c = $(SRCDIR) +.path.obj = $(OBJDIR) +.path.int = $(OBJDIR) + +# Makefile.inc provides the CSOURCES and HHEADERS defines +!include Makefile.inc + +# Borland's command line librarian program TLIB version 4.5 is not capable +# of building a library when any of its objects contains an hyphen in its +# name, due to a command line parsing bug. In order to workaround this, we +# build source files with hyphens in their name as objects with underscores +# using explicit compilation build rules instead of implicit ones. + +NOHYPHEN1 = $(CSOURCES:-=_) +NOHYPHEN2 = $(NOHYPHEN1:vauth/=) +NOHYPHEN3 = $(NOHYPHEN2:vtls/=) + +OBJECTS = $(NOHYPHEN3:.c=.obj) +PREPROCESSED = $(NOHYPHEN3:.c=.int) + +# Borland's command line compiler (BCC32) version 5.5.1 integrated +# preprocessor has a bug which results in silently generating wrong +# definitions for libcurl macros such as CURL_OFF_T_C, on the other +# hand Borland's command line preprocessor (CPP32) version 5.5.1 does +# not have the bug and achieves proper results. In order to avoid the +# silent bug we first preprocess source files and later compile the +# preprocessed result. + +.c.obj: + @-$(RM) $(@R).int + $(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(<) + $(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int + +all: $(OBJDIR) $(LIBCURL_LIB) $(LIBCURL_DLL) + +asyn_ares.obj: asyn-ares.c + @-$(RM) $(@R).int + $(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?) + $(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int + +asyn_thread.obj: asyn-thread.c + @-$(RM) $(@R).int + $(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?) + $(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int + +non_ascii.obj: non-ascii.c + @-$(RM) $(@R).int + $(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?) + $(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int + +clean: + cd $(OBJDIR) + @-$(RM) $(OBJECTS) + @-$(RM) $(PREPROCESSED) + cd .. + @-$(RMDIR) $(OBJDIR) + @-$(RM) $(LIBCURL_LIB) + @-$(RM) $(LIBCURL_IMPLIB) + @-$(RM) libcurl.tds + +$(OBJDIR): + @-$(RMDIR) $(OBJDIR) + @-$(MKDIR) $(OBJDIR) + +$(LIBCURL_LIB): $(OBJECTS) + @-$(RM) $(LIBCURL_LIB) + $(LIB) $(LIBFLAGS) $@ @&&! ++$(**: = &^ ++) +! + +$(LIBCURL_DLL) $(LIBCURL_IMPLIB): $(OBJECTS) $(LINKLIB) + @-$(RM) $(LIBCURL_DLL) + @-$(RM) $(LIBCURL_IMPLIB) + $(LD) $(LDFLAGS) -e$(LIBCURL_DLL) @&&! +$(**: = ^ +) +! + $(IMPLIB) $(LIBCURL_IMPLIB) $(LIBCURL_DLL) + + +# End of Makefile.b32 diff --git a/libcurl/lib/Makefile.in b/libcurl/lib/Makefile.in new file mode 100644 index 0000000..da01c26 --- /dev/null +++ b/libcurl/lib/Makefile.in @@ -0,0 +1,4257 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@USE_EMBEDDED_ARES_TRUE@am__append_1 = -I$(top_builddir)/ares \ +@USE_EMBEDDED_ARES_TRUE@ -I$(top_srcdir)/ares + +@CURL_LT_SHLIB_USE_VERSION_INFO_TRUE@am__append_2 = $(VERSIONINFO) +@CURL_LT_SHLIB_USE_NO_UNDEFINED_TRUE@am__append_3 = -no-undefined +@CURL_LT_SHLIB_USE_MIMPURE_TEXT_TRUE@am__append_4 = -mimpure-text +@CURL_LT_SHLIB_USE_VERSIONED_SYMBOLS_TRUE@am__append_5 = -Wl,--version-script=libcurl.vers +# if symbol-hiding is enabled, hide them! +@CURL_LT_SHLIB_USE_VERSIONED_SYMBOLS_FALSE@@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_6 = -export-symbols-regex '^curl_.*' +@USE_CPPFLAG_CURL_STATICLIB_TRUE@am__append_7 = -DCURL_STATICLIB +@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_8 = -DCURL_HIDDEN_SYMBOLS +@DOING_CURL_SYMBOL_HIDING_TRUE@am__append_9 = $(CFLAG_CURL_SYMBOL_HIDING) +subdir = lib +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \ + $(top_srcdir)/m4/curl-compilers.m4 \ + $(top_srcdir)/m4/curl-confopts.m4 \ + $(top_srcdir)/m4/curl-functions.m4 \ + $(top_srcdir)/m4/curl-openssl.m4 \ + $(top_srcdir)/m4/curl-override.m4 \ + $(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/xc-am-iface.m4 \ + $(top_srcdir)/m4/xc-cc-check.m4 \ + $(top_srcdir)/m4/xc-lt-iface.m4 \ + $(top_srcdir)/m4/xc-translit.m4 \ + $(top_srcdir)/m4/xc-val-flgs.m4 \ + $(top_srcdir)/m4/zz40-xc-ovr.m4 \ + $(top_srcdir)/m4/zz50-xc-ovr.m4 \ + $(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = curl_config.h +CONFIG_CLEAN_FILES = libcurl.vers +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +libcurl_la_LIBADD = +am__objects_1 = libcurl_la-file.lo libcurl_la-timeval.lo \ + libcurl_la-base64.lo libcurl_la-hostip.lo \ + libcurl_la-progress.lo libcurl_la-formdata.lo \ + libcurl_la-cookie.lo libcurl_la-http.lo libcurl_la-sendf.lo \ + libcurl_la-ftp.lo libcurl_la-url.lo libcurl_la-dict.lo \ + libcurl_la-if2ip.lo libcurl_la-speedcheck.lo \ + libcurl_la-ldap.lo libcurl_la-version.lo libcurl_la-getenv.lo \ + libcurl_la-escape.lo libcurl_la-mprintf.lo \ + libcurl_la-telnet.lo libcurl_la-netrc.lo libcurl_la-getinfo.lo \ + libcurl_la-transfer.lo libcurl_la-strcase.lo \ + libcurl_la-easy.lo libcurl_la-security.lo \ + libcurl_la-curl_fnmatch.lo libcurl_la-fileinfo.lo \ + libcurl_la-ftplistparser.lo libcurl_la-wildcard.lo \ + libcurl_la-krb5.lo libcurl_la-memdebug.lo \ + libcurl_la-http_chunks.lo libcurl_la-strtok.lo \ + libcurl_la-connect.lo libcurl_la-llist.lo libcurl_la-hash.lo \ + libcurl_la-multi.lo libcurl_la-content_encoding.lo \ + libcurl_la-share.lo libcurl_la-http_digest.lo \ + libcurl_la-md4.lo libcurl_la-md5.lo \ + libcurl_la-http_negotiate.lo libcurl_la-inet_pton.lo \ + libcurl_la-strtoofft.lo libcurl_la-strerror.lo \ + libcurl_la-amigaos.lo libcurl_la-hostasyn.lo \ + libcurl_la-hostip4.lo libcurl_la-hostip6.lo \ + libcurl_la-hostsyn.lo libcurl_la-inet_ntop.lo \ + libcurl_la-parsedate.lo libcurl_la-select.lo \ + libcurl_la-tftp.lo libcurl_la-splay.lo libcurl_la-strdup.lo \ + libcurl_la-socks.lo libcurl_la-ssh.lo libcurl_la-ssh-libssh.lo \ + libcurl_la-curl_addrinfo.lo libcurl_la-socks_gssapi.lo \ + libcurl_la-socks_sspi.lo libcurl_la-curl_sspi.lo \ + libcurl_la-slist.lo libcurl_la-nonblock.lo \ + libcurl_la-curl_memrchr.lo libcurl_la-imap.lo \ + libcurl_la-pop3.lo libcurl_la-smtp.lo libcurl_la-pingpong.lo \ + libcurl_la-rtsp.lo libcurl_la-curl_threads.lo \ + libcurl_la-warnless.lo libcurl_la-hmac.lo \ + libcurl_la-curl_rtmp.lo libcurl_la-openldap.lo \ + libcurl_la-curl_gethostname.lo libcurl_la-gopher.lo \ + libcurl_la-idn_win32.lo libcurl_la-http_proxy.lo \ + libcurl_la-non-ascii.lo libcurl_la-asyn-ares.lo \ + libcurl_la-asyn-thread.lo libcurl_la-curl_gssapi.lo \ + libcurl_la-http_ntlm.lo libcurl_la-curl_ntlm_wb.lo \ + libcurl_la-curl_ntlm_core.lo libcurl_la-curl_sasl.lo \ + libcurl_la-rand.lo libcurl_la-curl_multibyte.lo \ + libcurl_la-hostcheck.lo libcurl_la-conncache.lo \ + libcurl_la-dotdot.lo libcurl_la-x509asn1.lo \ + libcurl_la-http2.lo libcurl_la-smb.lo \ + libcurl_la-curl_endian.lo libcurl_la-curl_des.lo \ + libcurl_la-system_win32.lo libcurl_la-mime.lo \ + libcurl_la-sha256.lo libcurl_la-setopt.lo \ + libcurl_la-curl_path.lo libcurl_la-curl_ctype.lo \ + libcurl_la-curl_range.lo libcurl_la-psl.lo libcurl_la-doh.lo \ + libcurl_la-urlapi.lo libcurl_la-curl_get_line.lo \ + libcurl_la-altsvc.lo +am__dirstamp = $(am__leading_dot)dirstamp +am__objects_2 = vauth/libcurl_la-vauth.lo \ + vauth/libcurl_la-cleartext.lo vauth/libcurl_la-cram.lo \ + vauth/libcurl_la-digest.lo vauth/libcurl_la-digest_sspi.lo \ + vauth/libcurl_la-krb5_gssapi.lo vauth/libcurl_la-krb5_sspi.lo \ + vauth/libcurl_la-ntlm.lo vauth/libcurl_la-ntlm_sspi.lo \ + vauth/libcurl_la-oauth2.lo vauth/libcurl_la-spnego_gssapi.lo \ + vauth/libcurl_la-spnego_sspi.lo +am__objects_3 = vtls/libcurl_la-openssl.lo vtls/libcurl_la-gtls.lo \ + vtls/libcurl_la-vtls.lo vtls/libcurl_la-nss.lo \ + vtls/libcurl_la-polarssl.lo \ + vtls/libcurl_la-polarssl_threadlock.lo \ + vtls/libcurl_la-wolfssl.lo vtls/libcurl_la-schannel.lo \ + vtls/libcurl_la-schannel_verify.lo \ + vtls/libcurl_la-sectransp.lo vtls/libcurl_la-gskit.lo \ + vtls/libcurl_la-mbedtls.lo vtls/libcurl_la-mesalink.lo +am__objects_4 = $(am__objects_1) $(am__objects_2) $(am__objects_3) +am__objects_5 = +am__objects_6 = $(am__objects_5) $(am__objects_5) $(am__objects_5) +am_libcurl_la_OBJECTS = $(am__objects_4) $(am__objects_6) +libcurl_la_OBJECTS = $(am_libcurl_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libcurl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcurl_la_CFLAGS) \ + $(CFLAGS) $(libcurl_la_LDFLAGS) $(LDFLAGS) -o $@ +libcurlu_la_LIBADD = +am__objects_7 = libcurlu_la-file.lo libcurlu_la-timeval.lo \ + libcurlu_la-base64.lo libcurlu_la-hostip.lo \ + libcurlu_la-progress.lo libcurlu_la-formdata.lo \ + libcurlu_la-cookie.lo libcurlu_la-http.lo libcurlu_la-sendf.lo \ + libcurlu_la-ftp.lo libcurlu_la-url.lo libcurlu_la-dict.lo \ + libcurlu_la-if2ip.lo libcurlu_la-speedcheck.lo \ + libcurlu_la-ldap.lo libcurlu_la-version.lo \ + libcurlu_la-getenv.lo libcurlu_la-escape.lo \ + libcurlu_la-mprintf.lo libcurlu_la-telnet.lo \ + libcurlu_la-netrc.lo libcurlu_la-getinfo.lo \ + libcurlu_la-transfer.lo libcurlu_la-strcase.lo \ + libcurlu_la-easy.lo libcurlu_la-security.lo \ + libcurlu_la-curl_fnmatch.lo libcurlu_la-fileinfo.lo \ + libcurlu_la-ftplistparser.lo libcurlu_la-wildcard.lo \ + libcurlu_la-krb5.lo libcurlu_la-memdebug.lo \ + libcurlu_la-http_chunks.lo libcurlu_la-strtok.lo \ + libcurlu_la-connect.lo libcurlu_la-llist.lo \ + libcurlu_la-hash.lo libcurlu_la-multi.lo \ + libcurlu_la-content_encoding.lo libcurlu_la-share.lo \ + libcurlu_la-http_digest.lo libcurlu_la-md4.lo \ + libcurlu_la-md5.lo libcurlu_la-http_negotiate.lo \ + libcurlu_la-inet_pton.lo libcurlu_la-strtoofft.lo \ + libcurlu_la-strerror.lo libcurlu_la-amigaos.lo \ + libcurlu_la-hostasyn.lo libcurlu_la-hostip4.lo \ + libcurlu_la-hostip6.lo libcurlu_la-hostsyn.lo \ + libcurlu_la-inet_ntop.lo libcurlu_la-parsedate.lo \ + libcurlu_la-select.lo libcurlu_la-tftp.lo libcurlu_la-splay.lo \ + libcurlu_la-strdup.lo libcurlu_la-socks.lo libcurlu_la-ssh.lo \ + libcurlu_la-ssh-libssh.lo libcurlu_la-curl_addrinfo.lo \ + libcurlu_la-socks_gssapi.lo libcurlu_la-socks_sspi.lo \ + libcurlu_la-curl_sspi.lo libcurlu_la-slist.lo \ + libcurlu_la-nonblock.lo libcurlu_la-curl_memrchr.lo \ + libcurlu_la-imap.lo libcurlu_la-pop3.lo libcurlu_la-smtp.lo \ + libcurlu_la-pingpong.lo libcurlu_la-rtsp.lo \ + libcurlu_la-curl_threads.lo libcurlu_la-warnless.lo \ + libcurlu_la-hmac.lo libcurlu_la-curl_rtmp.lo \ + libcurlu_la-openldap.lo libcurlu_la-curl_gethostname.lo \ + libcurlu_la-gopher.lo libcurlu_la-idn_win32.lo \ + libcurlu_la-http_proxy.lo libcurlu_la-non-ascii.lo \ + libcurlu_la-asyn-ares.lo libcurlu_la-asyn-thread.lo \ + libcurlu_la-curl_gssapi.lo libcurlu_la-http_ntlm.lo \ + libcurlu_la-curl_ntlm_wb.lo libcurlu_la-curl_ntlm_core.lo \ + libcurlu_la-curl_sasl.lo libcurlu_la-rand.lo \ + libcurlu_la-curl_multibyte.lo libcurlu_la-hostcheck.lo \ + libcurlu_la-conncache.lo libcurlu_la-dotdot.lo \ + libcurlu_la-x509asn1.lo libcurlu_la-http2.lo \ + libcurlu_la-smb.lo libcurlu_la-curl_endian.lo \ + libcurlu_la-curl_des.lo libcurlu_la-system_win32.lo \ + libcurlu_la-mime.lo libcurlu_la-sha256.lo \ + libcurlu_la-setopt.lo libcurlu_la-curl_path.lo \ + libcurlu_la-curl_ctype.lo libcurlu_la-curl_range.lo \ + libcurlu_la-psl.lo libcurlu_la-doh.lo libcurlu_la-urlapi.lo \ + libcurlu_la-curl_get_line.lo libcurlu_la-altsvc.lo +am__objects_8 = vauth/libcurlu_la-vauth.lo \ + vauth/libcurlu_la-cleartext.lo vauth/libcurlu_la-cram.lo \ + vauth/libcurlu_la-digest.lo vauth/libcurlu_la-digest_sspi.lo \ + vauth/libcurlu_la-krb5_gssapi.lo \ + vauth/libcurlu_la-krb5_sspi.lo vauth/libcurlu_la-ntlm.lo \ + vauth/libcurlu_la-ntlm_sspi.lo vauth/libcurlu_la-oauth2.lo \ + vauth/libcurlu_la-spnego_gssapi.lo \ + vauth/libcurlu_la-spnego_sspi.lo +am__objects_9 = vtls/libcurlu_la-openssl.lo vtls/libcurlu_la-gtls.lo \ + vtls/libcurlu_la-vtls.lo vtls/libcurlu_la-nss.lo \ + vtls/libcurlu_la-polarssl.lo \ + vtls/libcurlu_la-polarssl_threadlock.lo \ + vtls/libcurlu_la-wolfssl.lo vtls/libcurlu_la-schannel.lo \ + vtls/libcurlu_la-schannel_verify.lo \ + vtls/libcurlu_la-sectransp.lo vtls/libcurlu_la-gskit.lo \ + vtls/libcurlu_la-mbedtls.lo vtls/libcurlu_la-mesalink.lo +am__objects_10 = $(am__objects_7) $(am__objects_8) $(am__objects_9) +am_libcurlu_la_OBJECTS = $(am__objects_10) $(am__objects_6) +libcurlu_la_OBJECTS = $(am_libcurlu_la_OBJECTS) +libcurlu_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcurlu_la_CFLAGS) \ + $(CFLAGS) $(libcurlu_la_LDFLAGS) $(LDFLAGS) -o $@ +@BUILD_UNITTESTS_TRUE@am_libcurlu_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \ + ./$(DEPDIR)/libcurl_la-amigaos.Plo \ + ./$(DEPDIR)/libcurl_la-asyn-ares.Plo \ + ./$(DEPDIR)/libcurl_la-asyn-thread.Plo \ + ./$(DEPDIR)/libcurl_la-base64.Plo \ + ./$(DEPDIR)/libcurl_la-conncache.Plo \ + ./$(DEPDIR)/libcurl_la-connect.Plo \ + ./$(DEPDIR)/libcurl_la-content_encoding.Plo \ + ./$(DEPDIR)/libcurl_la-cookie.Plo \ + ./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo \ + ./$(DEPDIR)/libcurl_la-curl_ctype.Plo \ + ./$(DEPDIR)/libcurl_la-curl_des.Plo \ + ./$(DEPDIR)/libcurl_la-curl_endian.Plo \ + ./$(DEPDIR)/libcurl_la-curl_fnmatch.Plo \ + ./$(DEPDIR)/libcurl_la-curl_get_line.Plo \ + ./$(DEPDIR)/libcurl_la-curl_gethostname.Plo \ + ./$(DEPDIR)/libcurl_la-curl_gssapi.Plo \ + ./$(DEPDIR)/libcurl_la-curl_memrchr.Plo \ + ./$(DEPDIR)/libcurl_la-curl_multibyte.Plo \ + ./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo \ + ./$(DEPDIR)/libcurl_la-curl_ntlm_wb.Plo \ + ./$(DEPDIR)/libcurl_la-curl_path.Plo \ + ./$(DEPDIR)/libcurl_la-curl_range.Plo \ + ./$(DEPDIR)/libcurl_la-curl_rtmp.Plo \ + ./$(DEPDIR)/libcurl_la-curl_sasl.Plo \ + ./$(DEPDIR)/libcurl_la-curl_sspi.Plo \ + ./$(DEPDIR)/libcurl_la-curl_threads.Plo \ + ./$(DEPDIR)/libcurl_la-dict.Plo ./$(DEPDIR)/libcurl_la-doh.Plo \ + ./$(DEPDIR)/libcurl_la-dotdot.Plo \ + ./$(DEPDIR)/libcurl_la-easy.Plo \ + ./$(DEPDIR)/libcurl_la-escape.Plo \ + ./$(DEPDIR)/libcurl_la-file.Plo \ + ./$(DEPDIR)/libcurl_la-fileinfo.Plo \ + ./$(DEPDIR)/libcurl_la-formdata.Plo \ + ./$(DEPDIR)/libcurl_la-ftp.Plo \ + ./$(DEPDIR)/libcurl_la-ftplistparser.Plo \ + ./$(DEPDIR)/libcurl_la-getenv.Plo \ + ./$(DEPDIR)/libcurl_la-getinfo.Plo \ + ./$(DEPDIR)/libcurl_la-gopher.Plo \ + ./$(DEPDIR)/libcurl_la-hash.Plo \ + ./$(DEPDIR)/libcurl_la-hmac.Plo \ + ./$(DEPDIR)/libcurl_la-hostasyn.Plo \ + ./$(DEPDIR)/libcurl_la-hostcheck.Plo \ + ./$(DEPDIR)/libcurl_la-hostip.Plo \ + ./$(DEPDIR)/libcurl_la-hostip4.Plo \ + ./$(DEPDIR)/libcurl_la-hostip6.Plo \ + ./$(DEPDIR)/libcurl_la-hostsyn.Plo \ + ./$(DEPDIR)/libcurl_la-http.Plo \ + ./$(DEPDIR)/libcurl_la-http2.Plo \ + ./$(DEPDIR)/libcurl_la-http_chunks.Plo \ + ./$(DEPDIR)/libcurl_la-http_digest.Plo \ + ./$(DEPDIR)/libcurl_la-http_negotiate.Plo \ + ./$(DEPDIR)/libcurl_la-http_ntlm.Plo \ + ./$(DEPDIR)/libcurl_la-http_proxy.Plo \ + ./$(DEPDIR)/libcurl_la-idn_win32.Plo \ + ./$(DEPDIR)/libcurl_la-if2ip.Plo \ + ./$(DEPDIR)/libcurl_la-imap.Plo \ + ./$(DEPDIR)/libcurl_la-inet_ntop.Plo \ + ./$(DEPDIR)/libcurl_la-inet_pton.Plo \ + ./$(DEPDIR)/libcurl_la-krb5.Plo \ + ./$(DEPDIR)/libcurl_la-ldap.Plo \ + ./$(DEPDIR)/libcurl_la-llist.Plo \ + ./$(DEPDIR)/libcurl_la-md4.Plo ./$(DEPDIR)/libcurl_la-md5.Plo \ + ./$(DEPDIR)/libcurl_la-memdebug.Plo \ + ./$(DEPDIR)/libcurl_la-mime.Plo \ + ./$(DEPDIR)/libcurl_la-mprintf.Plo \ + ./$(DEPDIR)/libcurl_la-multi.Plo \ + ./$(DEPDIR)/libcurl_la-netrc.Plo \ + ./$(DEPDIR)/libcurl_la-non-ascii.Plo \ + ./$(DEPDIR)/libcurl_la-nonblock.Plo \ + ./$(DEPDIR)/libcurl_la-openldap.Plo \ + ./$(DEPDIR)/libcurl_la-parsedate.Plo \ + ./$(DEPDIR)/libcurl_la-pingpong.Plo \ + ./$(DEPDIR)/libcurl_la-pop3.Plo \ + ./$(DEPDIR)/libcurl_la-progress.Plo \ + ./$(DEPDIR)/libcurl_la-psl.Plo ./$(DEPDIR)/libcurl_la-rand.Plo \ + ./$(DEPDIR)/libcurl_la-rtsp.Plo \ + ./$(DEPDIR)/libcurl_la-security.Plo \ + ./$(DEPDIR)/libcurl_la-select.Plo \ + ./$(DEPDIR)/libcurl_la-sendf.Plo \ + ./$(DEPDIR)/libcurl_la-setopt.Plo \ + ./$(DEPDIR)/libcurl_la-sha256.Plo \ + ./$(DEPDIR)/libcurl_la-share.Plo \ + ./$(DEPDIR)/libcurl_la-slist.Plo \ + ./$(DEPDIR)/libcurl_la-smb.Plo ./$(DEPDIR)/libcurl_la-smtp.Plo \ + ./$(DEPDIR)/libcurl_la-socks.Plo \ + ./$(DEPDIR)/libcurl_la-socks_gssapi.Plo \ + ./$(DEPDIR)/libcurl_la-socks_sspi.Plo \ + ./$(DEPDIR)/libcurl_la-speedcheck.Plo \ + ./$(DEPDIR)/libcurl_la-splay.Plo \ + ./$(DEPDIR)/libcurl_la-ssh-libssh.Plo \ + ./$(DEPDIR)/libcurl_la-ssh.Plo \ + ./$(DEPDIR)/libcurl_la-strcase.Plo \ + ./$(DEPDIR)/libcurl_la-strdup.Plo \ + ./$(DEPDIR)/libcurl_la-strerror.Plo \ + ./$(DEPDIR)/libcurl_la-strtok.Plo \ + ./$(DEPDIR)/libcurl_la-strtoofft.Plo \ + ./$(DEPDIR)/libcurl_la-system_win32.Plo \ + ./$(DEPDIR)/libcurl_la-telnet.Plo \ + ./$(DEPDIR)/libcurl_la-tftp.Plo \ + ./$(DEPDIR)/libcurl_la-timeval.Plo \ + ./$(DEPDIR)/libcurl_la-transfer.Plo \ + ./$(DEPDIR)/libcurl_la-url.Plo \ + ./$(DEPDIR)/libcurl_la-urlapi.Plo \ + ./$(DEPDIR)/libcurl_la-version.Plo \ + ./$(DEPDIR)/libcurl_la-warnless.Plo \ + ./$(DEPDIR)/libcurl_la-wildcard.Plo \ + ./$(DEPDIR)/libcurl_la-x509asn1.Plo \ + ./$(DEPDIR)/libcurlu_la-altsvc.Plo \ + ./$(DEPDIR)/libcurlu_la-amigaos.Plo \ + ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo \ + ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo \ + ./$(DEPDIR)/libcurlu_la-base64.Plo \ + ./$(DEPDIR)/libcurlu_la-conncache.Plo \ + ./$(DEPDIR)/libcurlu_la-connect.Plo \ + ./$(DEPDIR)/libcurlu_la-content_encoding.Plo \ + ./$(DEPDIR)/libcurlu_la-cookie.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_ctype.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_des.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_endian.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_fnmatch.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_get_line.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_ntlm_wb.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_path.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_range.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_rtmp.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_sasl.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_sspi.Plo \ + ./$(DEPDIR)/libcurlu_la-curl_threads.Plo \ + ./$(DEPDIR)/libcurlu_la-dict.Plo \ + ./$(DEPDIR)/libcurlu_la-doh.Plo \ + ./$(DEPDIR)/libcurlu_la-dotdot.Plo \ + ./$(DEPDIR)/libcurlu_la-easy.Plo \ + ./$(DEPDIR)/libcurlu_la-escape.Plo \ + ./$(DEPDIR)/libcurlu_la-file.Plo \ + ./$(DEPDIR)/libcurlu_la-fileinfo.Plo \ + ./$(DEPDIR)/libcurlu_la-formdata.Plo \ + ./$(DEPDIR)/libcurlu_la-ftp.Plo \ + ./$(DEPDIR)/libcurlu_la-ftplistparser.Plo \ + ./$(DEPDIR)/libcurlu_la-getenv.Plo \ + ./$(DEPDIR)/libcurlu_la-getinfo.Plo \ + ./$(DEPDIR)/libcurlu_la-gopher.Plo \ + ./$(DEPDIR)/libcurlu_la-hash.Plo \ + ./$(DEPDIR)/libcurlu_la-hmac.Plo \ + ./$(DEPDIR)/libcurlu_la-hostasyn.Plo \ + ./$(DEPDIR)/libcurlu_la-hostcheck.Plo \ + ./$(DEPDIR)/libcurlu_la-hostip.Plo \ + ./$(DEPDIR)/libcurlu_la-hostip4.Plo \ + ./$(DEPDIR)/libcurlu_la-hostip6.Plo \ + ./$(DEPDIR)/libcurlu_la-hostsyn.Plo \ + ./$(DEPDIR)/libcurlu_la-http.Plo \ + ./$(DEPDIR)/libcurlu_la-http2.Plo \ + ./$(DEPDIR)/libcurlu_la-http_chunks.Plo \ + ./$(DEPDIR)/libcurlu_la-http_digest.Plo \ + ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo \ + ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo \ + ./$(DEPDIR)/libcurlu_la-http_proxy.Plo \ + ./$(DEPDIR)/libcurlu_la-idn_win32.Plo \ + ./$(DEPDIR)/libcurlu_la-if2ip.Plo \ + ./$(DEPDIR)/libcurlu_la-imap.Plo \ + ./$(DEPDIR)/libcurlu_la-inet_ntop.Plo \ + ./$(DEPDIR)/libcurlu_la-inet_pton.Plo \ + ./$(DEPDIR)/libcurlu_la-krb5.Plo \ + ./$(DEPDIR)/libcurlu_la-ldap.Plo \ + ./$(DEPDIR)/libcurlu_la-llist.Plo \ + ./$(DEPDIR)/libcurlu_la-md4.Plo \ + ./$(DEPDIR)/libcurlu_la-md5.Plo \ + ./$(DEPDIR)/libcurlu_la-memdebug.Plo \ + ./$(DEPDIR)/libcurlu_la-mime.Plo \ + ./$(DEPDIR)/libcurlu_la-mprintf.Plo \ + ./$(DEPDIR)/libcurlu_la-multi.Plo \ + ./$(DEPDIR)/libcurlu_la-netrc.Plo \ + ./$(DEPDIR)/libcurlu_la-non-ascii.Plo \ + ./$(DEPDIR)/libcurlu_la-nonblock.Plo \ + ./$(DEPDIR)/libcurlu_la-openldap.Plo \ + ./$(DEPDIR)/libcurlu_la-parsedate.Plo \ + ./$(DEPDIR)/libcurlu_la-pingpong.Plo \ + ./$(DEPDIR)/libcurlu_la-pop3.Plo \ + ./$(DEPDIR)/libcurlu_la-progress.Plo \ + ./$(DEPDIR)/libcurlu_la-psl.Plo \ + ./$(DEPDIR)/libcurlu_la-rand.Plo \ + ./$(DEPDIR)/libcurlu_la-rtsp.Plo \ + ./$(DEPDIR)/libcurlu_la-security.Plo \ + ./$(DEPDIR)/libcurlu_la-select.Plo \ + ./$(DEPDIR)/libcurlu_la-sendf.Plo \ + ./$(DEPDIR)/libcurlu_la-setopt.Plo \ + ./$(DEPDIR)/libcurlu_la-sha256.Plo \ + ./$(DEPDIR)/libcurlu_la-share.Plo \ + ./$(DEPDIR)/libcurlu_la-slist.Plo \ + ./$(DEPDIR)/libcurlu_la-smb.Plo \ + ./$(DEPDIR)/libcurlu_la-smtp.Plo \ + ./$(DEPDIR)/libcurlu_la-socks.Plo \ + ./$(DEPDIR)/libcurlu_la-socks_gssapi.Plo \ + ./$(DEPDIR)/libcurlu_la-socks_sspi.Plo \ + ./$(DEPDIR)/libcurlu_la-speedcheck.Plo \ + ./$(DEPDIR)/libcurlu_la-splay.Plo \ + ./$(DEPDIR)/libcurlu_la-ssh-libssh.Plo \ + ./$(DEPDIR)/libcurlu_la-ssh.Plo \ + ./$(DEPDIR)/libcurlu_la-strcase.Plo \ + ./$(DEPDIR)/libcurlu_la-strdup.Plo \ + ./$(DEPDIR)/libcurlu_la-strerror.Plo \ + ./$(DEPDIR)/libcurlu_la-strtok.Plo \ + ./$(DEPDIR)/libcurlu_la-strtoofft.Plo \ + ./$(DEPDIR)/libcurlu_la-system_win32.Plo \ + ./$(DEPDIR)/libcurlu_la-telnet.Plo \ + ./$(DEPDIR)/libcurlu_la-tftp.Plo \ + ./$(DEPDIR)/libcurlu_la-timeval.Plo \ + ./$(DEPDIR)/libcurlu_la-transfer.Plo \ + ./$(DEPDIR)/libcurlu_la-url.Plo \ + ./$(DEPDIR)/libcurlu_la-urlapi.Plo \ + ./$(DEPDIR)/libcurlu_la-version.Plo \ + ./$(DEPDIR)/libcurlu_la-warnless.Plo \ + ./$(DEPDIR)/libcurlu_la-wildcard.Plo \ + ./$(DEPDIR)/libcurlu_la-x509asn1.Plo \ + vauth/$(DEPDIR)/libcurl_la-cleartext.Plo \ + vauth/$(DEPDIR)/libcurl_la-cram.Plo \ + vauth/$(DEPDIR)/libcurl_la-digest.Plo \ + vauth/$(DEPDIR)/libcurl_la-digest_sspi.Plo \ + vauth/$(DEPDIR)/libcurl_la-krb5_gssapi.Plo \ + vauth/$(DEPDIR)/libcurl_la-krb5_sspi.Plo \ + vauth/$(DEPDIR)/libcurl_la-ntlm.Plo \ + vauth/$(DEPDIR)/libcurl_la-ntlm_sspi.Plo \ + vauth/$(DEPDIR)/libcurl_la-oauth2.Plo \ + vauth/$(DEPDIR)/libcurl_la-spnego_gssapi.Plo \ + vauth/$(DEPDIR)/libcurl_la-spnego_sspi.Plo \ + vauth/$(DEPDIR)/libcurl_la-vauth.Plo \ + vauth/$(DEPDIR)/libcurlu_la-cleartext.Plo \ + vauth/$(DEPDIR)/libcurlu_la-cram.Plo \ + vauth/$(DEPDIR)/libcurlu_la-digest.Plo \ + vauth/$(DEPDIR)/libcurlu_la-digest_sspi.Plo \ + vauth/$(DEPDIR)/libcurlu_la-krb5_gssapi.Plo \ + vauth/$(DEPDIR)/libcurlu_la-krb5_sspi.Plo \ + vauth/$(DEPDIR)/libcurlu_la-ntlm.Plo \ + vauth/$(DEPDIR)/libcurlu_la-ntlm_sspi.Plo \ + vauth/$(DEPDIR)/libcurlu_la-oauth2.Plo \ + vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo \ + vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo \ + vauth/$(DEPDIR)/libcurlu_la-vauth.Plo \ + vtls/$(DEPDIR)/libcurl_la-gskit.Plo \ + vtls/$(DEPDIR)/libcurl_la-gtls.Plo \ + vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo \ + vtls/$(DEPDIR)/libcurl_la-mesalink.Plo \ + vtls/$(DEPDIR)/libcurl_la-nss.Plo \ + vtls/$(DEPDIR)/libcurl_la-openssl.Plo \ + vtls/$(DEPDIR)/libcurl_la-polarssl.Plo \ + vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo \ + vtls/$(DEPDIR)/libcurl_la-schannel.Plo \ + vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo \ + vtls/$(DEPDIR)/libcurl_la-sectransp.Plo \ + vtls/$(DEPDIR)/libcurl_la-vtls.Plo \ + vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo \ + vtls/$(DEPDIR)/libcurlu_la-gskit.Plo \ + vtls/$(DEPDIR)/libcurlu_la-gtls.Plo \ + vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo \ + vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo \ + vtls/$(DEPDIR)/libcurlu_la-nss.Plo \ + vtls/$(DEPDIR)/libcurlu_la-openssl.Plo \ + vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo \ + vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo \ + vtls/$(DEPDIR)/libcurlu_la-schannel.Plo \ + vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo \ + vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo \ + vtls/$(DEPDIR)/libcurlu_la-vtls.Plo \ + vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcurl_la_SOURCES) $(libcurlu_la_SOURCES) +DIST_SOURCES = $(libcurl_la_SOURCES) $(libcurlu_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)curl_config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.inc \ + $(srcdir)/curl_config.h.in $(srcdir)/libcurl.vers.in \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AR_FLAGS = @AR_FLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ + +# This might hold -Werror +CFLAGS = @CFLAGS@ @CURL_CFLAG_EXTRAS@ +CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@ +CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@ +CURLVERSION = @CURLVERSION@ +CURL_CA_BUNDLE = @CURL_CA_BUNDLE@ +CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@ +CURL_DISABLE_DICT = @CURL_DISABLE_DICT@ +CURL_DISABLE_FILE = @CURL_DISABLE_FILE@ +CURL_DISABLE_FTP = @CURL_DISABLE_FTP@ +CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@ +CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@ +CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@ +CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@ +CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@ +CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@ +CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@ +CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@ +CURL_DISABLE_SMB = @CURL_DISABLE_SMB@ +CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@ +CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@ +CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@ +CURL_LT_SHLIB_VERSIONED_FLAVOUR = @CURL_LT_SHLIB_VERSIONED_FLAVOUR@ +CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@ +CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@ +CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SHARED = @ENABLE_SHARED@ +ENABLE_STATIC = @ENABLE_STATIC@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ +GCOV = @GCOV@ +GREP = @GREP@ +HAVE_BROTLI = @HAVE_BROTLI@ +HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@ +HAVE_LDAP_SSL = @HAVE_LDAP_SSL@ +HAVE_LIBZ = @HAVE_LIBZ@ +HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@ +HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@ +IDN_ENABLED = @IDN_ENABLED@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPV6_ENABLED = @IPV6_ENABLED@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCURL_LIBS = @LIBCURL_LIBS@ +LIBMETALINK_CPPFLAGS = @LIBMETALINK_CPPFLAGS@ +LIBMETALINK_LDFLAGS = @LIBMETALINK_LDFLAGS@ +LIBMETALINK_LIBS = @LIBMETALINK_LIBS@ +LIBOBJS = @LIBOBJS@ + +# Prevent LIBS from being used for all link targets +LIBS = $(BLANK_AT_MAKETIME) +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANOPT = @MANOPT@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NROFF = @NROFF@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGADD_NAME = @PKGADD_NAME@ +PKGADD_PKG = @PKGADD_PKG@ +PKGADD_VENDOR = @PKGADD_VENDOR@ +PKGCONFIG = @PKGCONFIG@ +RANDOM_FILE = @RANDOM_FILE@ +RANLIB = @RANLIB@ +REQUIRE_LIB_DEPS = @REQUIRE_LIB_DEPS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_BACKENDS = @SSL_BACKENDS@ +SSL_ENABLED = @SSL_ENABLED@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +SUPPORT_FEATURES = @SUPPORT_FEATURES@ +SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@ +USE_ARES = @USE_ARES@ +USE_GNUTLS = @USE_GNUTLS@ +USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@ +USE_LIBRTMP = @USE_LIBRTMP@ +USE_LIBSSH = @USE_LIBSSH@ +USE_LIBSSH2 = @USE_LIBSSH2@ +USE_MBEDTLS = @USE_MBEDTLS@ +USE_MESALINK = @USE_MESALINK@ +USE_NGHTTP2 = @USE_NGHTTP2@ +USE_NSS = @USE_NSS@ +USE_OPENLDAP = @USE_OPENLDAP@ +USE_SCHANNEL = @USE_SCHANNEL@ +USE_SECTRANSP = @USE_SECTRANSP@ +USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ +USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ +USE_WOLFSSL = @USE_WOLFSSL@ +VERSION = @VERSION@ +VERSIONNUM = @VERSIONNUM@ +ZLIB_LIBS = @ZLIB_LIBS@ +ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libext = @libext@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +AUTOMAKE_OPTIONS = foreign nostdinc +CMAKE_DIST = CMakeLists.txt curl_config.h.cmake +EXTRA_DIST = Makefile.m32 config-win32.h \ + config-win32ce.h config-riscos.h config-mac.h curl_config.h.in \ + makefile.dj config-dos.h libcurl.plist libcurl.rc config-amigaos.h \ + makefile.amiga Makefile.netware nwlib.c nwos.c config-win32ce.h \ + config-os400.h setup-os400.h config-symbian.h Makefile.Watcom \ + config-tpf.h mk-ca-bundle.pl mk-ca-bundle.vbs $(CMAKE_DIST) \ + firefox-db2pem.sh config-vxworks.h Makefile.vxworks checksrc.pl + +lib_LTLIBRARIES = libcurl.la +@BUILD_UNITTESTS_FALSE@noinst_LTLIBRARIES = +@BUILD_UNITTESTS_TRUE@noinst_LTLIBRARIES = libcurlu.la + +# Specify our include paths here, and do it relative to $(top_srcdir) and +# $(top_builddir), to ensure that these paths which belong to the library +# being currently built and tested are searched before the library which +# might possibly already be installed in the system. +# +# $(top_srcdir)/include is for libcurl's external include files +# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file +# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "private" files +# $(top_builddir)/ares is for in-tree c-ares's generated ares_build.h file +# $(top_srcdir)/ares is for in-tree c-ares's external include files +# This flag accepts an argument of the form current[:revision[:age]]. So, +# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to +# 1. +# +# Here's the simplified rule guide on how to change -version-info: +# (current version is C:R:A) +# +# 1. if there are only source changes, use C:R+1:A +# 2. if interfaces were added use C+1:0:A+1 +# 3. if interfaces were removed, then use C+1:0:0 +# +# For the full guide on libcurl ABI rules, see docs/libcurl/ABI +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/lib \ + -I$(top_srcdir)/lib $(am__append_1) -DBUILDING_LIBCURL +VERSIONINFO = -version-info 9:0:5 +AM_LDFLAGS = +AM_CFLAGS = +libcurl_la_CPPFLAGS_EXTRA = $(am__append_7) $(am__append_8) +libcurl_la_LDFLAGS_EXTRA = $(am__append_2) $(am__append_3) \ + $(am__append_4) $(am__append_5) $(am__append_6) +libcurl_la_CFLAGS_EXTRA = $(am__append_9) +libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA) +libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS) +libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) +libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS +libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS) +libcurlu_la_CFLAGS = $(AM_CFLAGS) +LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \ + vauth/digest.c vauth/digest_sspi.c vauth/krb5_gssapi.c \ + vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c vauth/oauth2.c \ + vauth/spnego_gssapi.c vauth/spnego_sspi.c + +LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h +LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \ + vtls/polarssl.c vtls/polarssl_threadlock.c \ + vtls/wolfssl.c vtls/schannel.c vtls/schannel_verify.c \ + vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c + +LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ + vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ + vtls/wolfssl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ + vtls/mbedtls.h vtls/mesalink.h + +LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ + cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \ + ldap.c version.c getenv.c escape.c mprintf.c telnet.c netrc.c \ + getinfo.c transfer.c strcase.c easy.c security.c curl_fnmatch.c \ + fileinfo.c ftplistparser.c wildcard.c krb5.c memdebug.c http_chunks.c \ + strtok.c connect.c llist.c hash.c multi.c content_encoding.c share.c \ + http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \ + strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \ + inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \ + ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \ + curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \ + pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \ + openldap.c curl_gethostname.c gopher.c idn_win32.c \ + http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \ + http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \ + curl_multibyte.c hostcheck.c conncache.c dotdot.c \ + x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \ + mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \ + doh.c urlapi.c curl_get_line.c altsvc.c + +LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ + formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ + speedcheck.h urldata.h curl_ldap.h escape.h telnet.h getinfo.h \ + strcase.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \ + wildcard.h fileinfo.h ftplistparser.h strtok.h connect.h llist.h \ + hash.h content_encoding.h share.h curl_md4.h curl_md5.h http_digest.h \ + http_negotiate.h inet_pton.h amigaos.h strtoofft.h strerror.h \ + inet_ntop.h curlx.h curl_memory.h curl_setup.h transfer.h select.h \ + easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h \ + socks.h ssh.h curl_base64.h curl_addrinfo.h curl_sspi.h \ + slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \ + rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \ + curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \ + http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \ + curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \ + curl_setup_once.h multihandle.h setup-vms.h dotdot.h \ + x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ + curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \ + curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ + curl_get_line.h altsvc.h + +LIB_RCFILES = libcurl.rc +CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) +HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) + +# Makefile.inc provides the CSOURCES and HHEADERS defines +libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS) +libcurlu_la_SOURCES = $(CSOURCES) $(HHEADERS) +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) + +# disable the tests that are mostly causing false positives +TIDYFLAGS = -checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-valist.Uninitialized,-clang-analyzer-core.NonNullParamChecker,-clang-analyzer-core.NullDereference -quiet +TIDY := clang-tidy +all: curl_config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile.inc $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(srcdir)/Makefile.inc $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +curl_config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/curl_config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status lib/curl_config.h +$(srcdir)/curl_config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f curl_config.h stamp-h1 +libcurl.vers: $(top_builddir)/config.status $(srcdir)/libcurl.vers.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +vauth/$(am__dirstamp): + @$(MKDIR_P) vauth + @: > vauth/$(am__dirstamp) +vauth/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) vauth/$(DEPDIR) + @: > vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-vauth.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-cleartext.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-cram.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-digest.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-digest_sspi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-krb5_gssapi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-krb5_sspi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-ntlm.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-ntlm_sspi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-oauth2.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-spnego_gssapi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurl_la-spnego_sspi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vtls/$(am__dirstamp): + @$(MKDIR_P) vtls + @: > vtls/$(am__dirstamp) +vtls/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) vtls/$(DEPDIR) + @: > vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-openssl.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-gtls.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-vtls.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-nss.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-polarssl.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-polarssl_threadlock.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-wolfssl.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-schannel.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-schannel_verify.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-sectransp.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-gskit.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-mbedtls.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurl_la-mesalink.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) + +libcurl.la: $(libcurl_la_OBJECTS) $(libcurl_la_DEPENDENCIES) $(EXTRA_libcurl_la_DEPENDENCIES) + $(AM_V_CCLD)$(libcurl_la_LINK) -rpath $(libdir) $(libcurl_la_OBJECTS) $(libcurl_la_LIBADD) $(LIBS) +vauth/libcurlu_la-vauth.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-cleartext.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-cram.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-digest.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-digest_sspi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-krb5_gssapi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-krb5_sspi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-ntlm.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-ntlm_sspi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-oauth2.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-spnego_gssapi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vauth/libcurlu_la-spnego_sspi.lo: vauth/$(am__dirstamp) \ + vauth/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-openssl.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-gtls.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-vtls.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-nss.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-polarssl.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-polarssl_threadlock.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-wolfssl.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-schannel.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-schannel_verify.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-sectransp.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-gskit.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-mbedtls.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) +vtls/libcurlu_la-mesalink.lo: vtls/$(am__dirstamp) \ + vtls/$(DEPDIR)/$(am__dirstamp) + +libcurlu.la: $(libcurlu_la_OBJECTS) $(libcurlu_la_DEPENDENCIES) $(EXTRA_libcurlu_la_DEPENDENCIES) + $(AM_V_CCLD)$(libcurlu_la_LINK) $(am_libcurlu_la_rpath) $(libcurlu_la_OBJECTS) $(libcurlu_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f vauth/*.$(OBJEXT) + -rm -f vauth/*.lo + -rm -f vtls/*.$(OBJEXT) + -rm -f vtls/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-altsvc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-amigaos.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-ares.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-thread.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-base64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-conncache.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-connect.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-content_encoding.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-cookie.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_ctype.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_des.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_endian.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_fnmatch.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_get_line.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_gethostname.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_gssapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_memrchr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_multibyte.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_ntlm_wb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_path.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_range.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_rtmp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_sasl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_threads.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-dict.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-doh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-dotdot.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-easy.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-escape.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-file.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-fileinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-formdata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-ftp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-ftplistparser.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-getenv.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-getinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-gopher.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hash.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hmac.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostasyn.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostcheck.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip4.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip6.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostsyn.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_chunks.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_digest.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_negotiate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_ntlm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http_proxy.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-idn_win32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-if2ip.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-imap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-inet_ntop.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-inet_pton.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-krb5.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-ldap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-llist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-md4.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-md5.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-memdebug.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-mime.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-mprintf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-multi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-netrc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-non-ascii.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-nonblock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-openldap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-parsedate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-pingpong.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-pop3.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-progress.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-psl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-rand.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-rtsp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-security.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-select.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-sendf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-setopt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-sha256.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-share.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-slist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-smb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-smtp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-socks.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-socks_gssapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-socks_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-speedcheck.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-splay.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-ssh-libssh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-ssh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strcase.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strdup.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strerror.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strtok.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strtoofft.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-system_win32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-telnet.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-tftp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-timeval.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-transfer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-url.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-urlapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-version.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-warnless.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-wildcard.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-x509asn1.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-altsvc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-amigaos.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-ares.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-thread.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-base64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-conncache.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-connect.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-content_encoding.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-cookie.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_ctype.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_des.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_endian.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_fnmatch.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_get_line.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_ntlm_wb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_path.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_range.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_rtmp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_sasl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_threads.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-dict.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-doh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-dotdot.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-easy.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-escape.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-file.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-fileinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-formdata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-ftp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-ftplistparser.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-getenv.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-getinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-gopher.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hash.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hmac.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostasyn.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostcheck.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip4.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip6.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostsyn.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_chunks.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_digest.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_negotiate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_ntlm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http_proxy.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-idn_win32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-if2ip.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-imap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-inet_ntop.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-inet_pton.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-krb5.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-ldap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-llist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-md4.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-md5.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-memdebug.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-mime.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-mprintf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-multi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-netrc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-non-ascii.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-nonblock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-openldap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-parsedate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-pingpong.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-pop3.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-progress.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-psl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-rand.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-rtsp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-security.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-select.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-sendf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-setopt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-sha256.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-share.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-slist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-smb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-smtp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-socks.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-socks_gssapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-socks_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-speedcheck.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-splay.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-ssh-libssh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-ssh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strcase.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strdup.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strerror.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strtok.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strtoofft.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-system_win32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-telnet.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-tftp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-timeval.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-transfer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-url.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-urlapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-version.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-warnless.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-wildcard.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-x509asn1.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-cleartext.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-cram.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-digest.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-digest_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-krb5_gssapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-krb5_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-ntlm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-ntlm_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-oauth2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-spnego_gssapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-spnego_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-vauth.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-cleartext.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-cram.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-digest.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-digest_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-krb5_gssapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-krb5_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-ntlm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-ntlm_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-oauth2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurlu_la-vauth.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-gskit.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-gtls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-mesalink.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-nss.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-openssl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-polarssl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-schannel.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-sectransp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-vtls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-gskit.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-gtls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-nss.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-openssl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-schannel.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-vtls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libcurl_la-file.lo: file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-file.lo -MD -MP -MF $(DEPDIR)/libcurl_la-file.Tpo -c -o libcurl_la-file.lo `test -f 'file.c' || echo '$(srcdir)/'`file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-file.Tpo $(DEPDIR)/libcurl_la-file.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='file.c' object='libcurl_la-file.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-file.lo `test -f 'file.c' || echo '$(srcdir)/'`file.c + +libcurl_la-timeval.lo: timeval.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-timeval.lo -MD -MP -MF $(DEPDIR)/libcurl_la-timeval.Tpo -c -o libcurl_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-timeval.Tpo $(DEPDIR)/libcurl_la-timeval.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timeval.c' object='libcurl_la-timeval.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c + +libcurl_la-base64.lo: base64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-base64.lo -MD -MP -MF $(DEPDIR)/libcurl_la-base64.Tpo -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-base64.Tpo $(DEPDIR)/libcurl_la-base64.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='base64.c' object='libcurl_la-base64.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c + +libcurl_la-hostip.lo: hostip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostip.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostip.Tpo -c -o libcurl_la-hostip.lo `test -f 'hostip.c' || echo '$(srcdir)/'`hostip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostip.Tpo $(DEPDIR)/libcurl_la-hostip.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostip.c' object='libcurl_la-hostip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostip.lo `test -f 'hostip.c' || echo '$(srcdir)/'`hostip.c + +libcurl_la-progress.lo: progress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-progress.lo -MD -MP -MF $(DEPDIR)/libcurl_la-progress.Tpo -c -o libcurl_la-progress.lo `test -f 'progress.c' || echo '$(srcdir)/'`progress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-progress.Tpo $(DEPDIR)/libcurl_la-progress.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='progress.c' object='libcurl_la-progress.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-progress.lo `test -f 'progress.c' || echo '$(srcdir)/'`progress.c + +libcurl_la-formdata.lo: formdata.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-formdata.lo -MD -MP -MF $(DEPDIR)/libcurl_la-formdata.Tpo -c -o libcurl_la-formdata.lo `test -f 'formdata.c' || echo '$(srcdir)/'`formdata.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-formdata.Tpo $(DEPDIR)/libcurl_la-formdata.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='formdata.c' object='libcurl_la-formdata.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-formdata.lo `test -f 'formdata.c' || echo '$(srcdir)/'`formdata.c + +libcurl_la-cookie.lo: cookie.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-cookie.lo -MD -MP -MF $(DEPDIR)/libcurl_la-cookie.Tpo -c -o libcurl_la-cookie.lo `test -f 'cookie.c' || echo '$(srcdir)/'`cookie.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-cookie.Tpo $(DEPDIR)/libcurl_la-cookie.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cookie.c' object='libcurl_la-cookie.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-cookie.lo `test -f 'cookie.c' || echo '$(srcdir)/'`cookie.c + +libcurl_la-http.lo: http.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http.Tpo -c -o libcurl_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http.Tpo $(DEPDIR)/libcurl_la-http.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='libcurl_la-http.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c + +libcurl_la-sendf.lo: sendf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-sendf.lo -MD -MP -MF $(DEPDIR)/libcurl_la-sendf.Tpo -c -o libcurl_la-sendf.lo `test -f 'sendf.c' || echo '$(srcdir)/'`sendf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-sendf.Tpo $(DEPDIR)/libcurl_la-sendf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sendf.c' object='libcurl_la-sendf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-sendf.lo `test -f 'sendf.c' || echo '$(srcdir)/'`sendf.c + +libcurl_la-ftp.lo: ftp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ftp.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ftp.Tpo -c -o libcurl_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ftp.Tpo $(DEPDIR)/libcurl_la-ftp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ftp.c' object='libcurl_la-ftp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c + +libcurl_la-url.lo: url.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-url.lo -MD -MP -MF $(DEPDIR)/libcurl_la-url.Tpo -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-url.Tpo $(DEPDIR)/libcurl_la-url.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='url.c' object='libcurl_la-url.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c + +libcurl_la-dict.lo: dict.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dict.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dict.Tpo -c -o libcurl_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dict.Tpo $(DEPDIR)/libcurl_la-dict.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dict.c' object='libcurl_la-dict.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c + +libcurl_la-if2ip.lo: if2ip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-if2ip.lo -MD -MP -MF $(DEPDIR)/libcurl_la-if2ip.Tpo -c -o libcurl_la-if2ip.lo `test -f 'if2ip.c' || echo '$(srcdir)/'`if2ip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-if2ip.Tpo $(DEPDIR)/libcurl_la-if2ip.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='if2ip.c' object='libcurl_la-if2ip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-if2ip.lo `test -f 'if2ip.c' || echo '$(srcdir)/'`if2ip.c + +libcurl_la-speedcheck.lo: speedcheck.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-speedcheck.lo -MD -MP -MF $(DEPDIR)/libcurl_la-speedcheck.Tpo -c -o libcurl_la-speedcheck.lo `test -f 'speedcheck.c' || echo '$(srcdir)/'`speedcheck.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-speedcheck.Tpo $(DEPDIR)/libcurl_la-speedcheck.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='speedcheck.c' object='libcurl_la-speedcheck.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-speedcheck.lo `test -f 'speedcheck.c' || echo '$(srcdir)/'`speedcheck.c + +libcurl_la-ldap.lo: ldap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ldap.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ldap.Tpo -c -o libcurl_la-ldap.lo `test -f 'ldap.c' || echo '$(srcdir)/'`ldap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ldap.Tpo $(DEPDIR)/libcurl_la-ldap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ldap.c' object='libcurl_la-ldap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ldap.lo `test -f 'ldap.c' || echo '$(srcdir)/'`ldap.c + +libcurl_la-version.lo: version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-version.lo -MD -MP -MF $(DEPDIR)/libcurl_la-version.Tpo -c -o libcurl_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-version.Tpo $(DEPDIR)/libcurl_la-version.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version.c' object='libcurl_la-version.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c + +libcurl_la-getenv.lo: getenv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-getenv.lo -MD -MP -MF $(DEPDIR)/libcurl_la-getenv.Tpo -c -o libcurl_la-getenv.lo `test -f 'getenv.c' || echo '$(srcdir)/'`getenv.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-getenv.Tpo $(DEPDIR)/libcurl_la-getenv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='getenv.c' object='libcurl_la-getenv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-getenv.lo `test -f 'getenv.c' || echo '$(srcdir)/'`getenv.c + +libcurl_la-escape.lo: escape.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-escape.lo -MD -MP -MF $(DEPDIR)/libcurl_la-escape.Tpo -c -o libcurl_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-escape.Tpo $(DEPDIR)/libcurl_la-escape.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='escape.c' object='libcurl_la-escape.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c + +libcurl_la-mprintf.lo: mprintf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-mprintf.lo -MD -MP -MF $(DEPDIR)/libcurl_la-mprintf.Tpo -c -o libcurl_la-mprintf.lo `test -f 'mprintf.c' || echo '$(srcdir)/'`mprintf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-mprintf.Tpo $(DEPDIR)/libcurl_la-mprintf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mprintf.c' object='libcurl_la-mprintf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-mprintf.lo `test -f 'mprintf.c' || echo '$(srcdir)/'`mprintf.c + +libcurl_la-telnet.lo: telnet.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-telnet.lo -MD -MP -MF $(DEPDIR)/libcurl_la-telnet.Tpo -c -o libcurl_la-telnet.lo `test -f 'telnet.c' || echo '$(srcdir)/'`telnet.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-telnet.Tpo $(DEPDIR)/libcurl_la-telnet.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telnet.c' object='libcurl_la-telnet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-telnet.lo `test -f 'telnet.c' || echo '$(srcdir)/'`telnet.c + +libcurl_la-netrc.lo: netrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-netrc.lo -MD -MP -MF $(DEPDIR)/libcurl_la-netrc.Tpo -c -o libcurl_la-netrc.lo `test -f 'netrc.c' || echo '$(srcdir)/'`netrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-netrc.Tpo $(DEPDIR)/libcurl_la-netrc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netrc.c' object='libcurl_la-netrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-netrc.lo `test -f 'netrc.c' || echo '$(srcdir)/'`netrc.c + +libcurl_la-getinfo.lo: getinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-getinfo.lo -MD -MP -MF $(DEPDIR)/libcurl_la-getinfo.Tpo -c -o libcurl_la-getinfo.lo `test -f 'getinfo.c' || echo '$(srcdir)/'`getinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-getinfo.Tpo $(DEPDIR)/libcurl_la-getinfo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='getinfo.c' object='libcurl_la-getinfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-getinfo.lo `test -f 'getinfo.c' || echo '$(srcdir)/'`getinfo.c + +libcurl_la-transfer.lo: transfer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-transfer.lo -MD -MP -MF $(DEPDIR)/libcurl_la-transfer.Tpo -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-transfer.Tpo $(DEPDIR)/libcurl_la-transfer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='transfer.c' object='libcurl_la-transfer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c + +libcurl_la-strcase.lo: strcase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-strcase.lo -MD -MP -MF $(DEPDIR)/libcurl_la-strcase.Tpo -c -o libcurl_la-strcase.lo `test -f 'strcase.c' || echo '$(srcdir)/'`strcase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-strcase.Tpo $(DEPDIR)/libcurl_la-strcase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strcase.c' object='libcurl_la-strcase.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strcase.lo `test -f 'strcase.c' || echo '$(srcdir)/'`strcase.c + +libcurl_la-easy.lo: easy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-easy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-easy.Tpo -c -o libcurl_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-easy.Tpo $(DEPDIR)/libcurl_la-easy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easy.c' object='libcurl_la-easy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c + +libcurl_la-security.lo: security.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-security.lo -MD -MP -MF $(DEPDIR)/libcurl_la-security.Tpo -c -o libcurl_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-security.Tpo $(DEPDIR)/libcurl_la-security.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='security.c' object='libcurl_la-security.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c + +libcurl_la-curl_fnmatch.lo: curl_fnmatch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_fnmatch.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_fnmatch.Tpo -c -o libcurl_la-curl_fnmatch.lo `test -f 'curl_fnmatch.c' || echo '$(srcdir)/'`curl_fnmatch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_fnmatch.Tpo $(DEPDIR)/libcurl_la-curl_fnmatch.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_fnmatch.c' object='libcurl_la-curl_fnmatch.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_fnmatch.lo `test -f 'curl_fnmatch.c' || echo '$(srcdir)/'`curl_fnmatch.c + +libcurl_la-fileinfo.lo: fileinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-fileinfo.lo -MD -MP -MF $(DEPDIR)/libcurl_la-fileinfo.Tpo -c -o libcurl_la-fileinfo.lo `test -f 'fileinfo.c' || echo '$(srcdir)/'`fileinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-fileinfo.Tpo $(DEPDIR)/libcurl_la-fileinfo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fileinfo.c' object='libcurl_la-fileinfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-fileinfo.lo `test -f 'fileinfo.c' || echo '$(srcdir)/'`fileinfo.c + +libcurl_la-ftplistparser.lo: ftplistparser.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ftplistparser.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ftplistparser.Tpo -c -o libcurl_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ftplistparser.Tpo $(DEPDIR)/libcurl_la-ftplistparser.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ftplistparser.c' object='libcurl_la-ftplistparser.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c + +libcurl_la-wildcard.lo: wildcard.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-wildcard.lo -MD -MP -MF $(DEPDIR)/libcurl_la-wildcard.Tpo -c -o libcurl_la-wildcard.lo `test -f 'wildcard.c' || echo '$(srcdir)/'`wildcard.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-wildcard.Tpo $(DEPDIR)/libcurl_la-wildcard.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wildcard.c' object='libcurl_la-wildcard.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-wildcard.lo `test -f 'wildcard.c' || echo '$(srcdir)/'`wildcard.c + +libcurl_la-krb5.lo: krb5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-krb5.lo -MD -MP -MF $(DEPDIR)/libcurl_la-krb5.Tpo -c -o libcurl_la-krb5.lo `test -f 'krb5.c' || echo '$(srcdir)/'`krb5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-krb5.Tpo $(DEPDIR)/libcurl_la-krb5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='krb5.c' object='libcurl_la-krb5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-krb5.lo `test -f 'krb5.c' || echo '$(srcdir)/'`krb5.c + +libcurl_la-memdebug.lo: memdebug.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-memdebug.lo -MD -MP -MF $(DEPDIR)/libcurl_la-memdebug.Tpo -c -o libcurl_la-memdebug.lo `test -f 'memdebug.c' || echo '$(srcdir)/'`memdebug.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-memdebug.Tpo $(DEPDIR)/libcurl_la-memdebug.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='memdebug.c' object='libcurl_la-memdebug.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-memdebug.lo `test -f 'memdebug.c' || echo '$(srcdir)/'`memdebug.c + +libcurl_la-http_chunks.lo: http_chunks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_chunks.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_chunks.Tpo -c -o libcurl_la-http_chunks.lo `test -f 'http_chunks.c' || echo '$(srcdir)/'`http_chunks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_chunks.Tpo $(DEPDIR)/libcurl_la-http_chunks.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_chunks.c' object='libcurl_la-http_chunks.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_chunks.lo `test -f 'http_chunks.c' || echo '$(srcdir)/'`http_chunks.c + +libcurl_la-strtok.lo: strtok.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-strtok.lo -MD -MP -MF $(DEPDIR)/libcurl_la-strtok.Tpo -c -o libcurl_la-strtok.lo `test -f 'strtok.c' || echo '$(srcdir)/'`strtok.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-strtok.Tpo $(DEPDIR)/libcurl_la-strtok.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strtok.c' object='libcurl_la-strtok.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strtok.lo `test -f 'strtok.c' || echo '$(srcdir)/'`strtok.c + +libcurl_la-connect.lo: connect.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-connect.lo -MD -MP -MF $(DEPDIR)/libcurl_la-connect.Tpo -c -o libcurl_la-connect.lo `test -f 'connect.c' || echo '$(srcdir)/'`connect.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-connect.Tpo $(DEPDIR)/libcurl_la-connect.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='connect.c' object='libcurl_la-connect.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-connect.lo `test -f 'connect.c' || echo '$(srcdir)/'`connect.c + +libcurl_la-llist.lo: llist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-llist.lo -MD -MP -MF $(DEPDIR)/libcurl_la-llist.Tpo -c -o libcurl_la-llist.lo `test -f 'llist.c' || echo '$(srcdir)/'`llist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-llist.Tpo $(DEPDIR)/libcurl_la-llist.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='llist.c' object='libcurl_la-llist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-llist.lo `test -f 'llist.c' || echo '$(srcdir)/'`llist.c + +libcurl_la-hash.lo: hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hash.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hash.Tpo -c -o libcurl_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hash.Tpo $(DEPDIR)/libcurl_la-hash.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hash.c' object='libcurl_la-hash.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c + +libcurl_la-multi.lo: multi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-multi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-multi.Tpo -c -o libcurl_la-multi.lo `test -f 'multi.c' || echo '$(srcdir)/'`multi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-multi.Tpo $(DEPDIR)/libcurl_la-multi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='multi.c' object='libcurl_la-multi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-multi.lo `test -f 'multi.c' || echo '$(srcdir)/'`multi.c + +libcurl_la-content_encoding.lo: content_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-content_encoding.lo -MD -MP -MF $(DEPDIR)/libcurl_la-content_encoding.Tpo -c -o libcurl_la-content_encoding.lo `test -f 'content_encoding.c' || echo '$(srcdir)/'`content_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-content_encoding.Tpo $(DEPDIR)/libcurl_la-content_encoding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='content_encoding.c' object='libcurl_la-content_encoding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-content_encoding.lo `test -f 'content_encoding.c' || echo '$(srcdir)/'`content_encoding.c + +libcurl_la-share.lo: share.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-share.lo -MD -MP -MF $(DEPDIR)/libcurl_la-share.Tpo -c -o libcurl_la-share.lo `test -f 'share.c' || echo '$(srcdir)/'`share.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-share.Tpo $(DEPDIR)/libcurl_la-share.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='share.c' object='libcurl_la-share.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-share.lo `test -f 'share.c' || echo '$(srcdir)/'`share.c + +libcurl_la-http_digest.lo: http_digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_digest.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_digest.Tpo -c -o libcurl_la-http_digest.lo `test -f 'http_digest.c' || echo '$(srcdir)/'`http_digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_digest.Tpo $(DEPDIR)/libcurl_la-http_digest.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_digest.c' object='libcurl_la-http_digest.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_digest.lo `test -f 'http_digest.c' || echo '$(srcdir)/'`http_digest.c + +libcurl_la-md4.lo: md4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-md4.lo -MD -MP -MF $(DEPDIR)/libcurl_la-md4.Tpo -c -o libcurl_la-md4.lo `test -f 'md4.c' || echo '$(srcdir)/'`md4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-md4.Tpo $(DEPDIR)/libcurl_la-md4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md4.c' object='libcurl_la-md4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-md4.lo `test -f 'md4.c' || echo '$(srcdir)/'`md4.c + +libcurl_la-md5.lo: md5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-md5.lo -MD -MP -MF $(DEPDIR)/libcurl_la-md5.Tpo -c -o libcurl_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-md5.Tpo $(DEPDIR)/libcurl_la-md5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md5.c' object='libcurl_la-md5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c + +libcurl_la-http_negotiate.lo: http_negotiate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_negotiate.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_negotiate.Tpo -c -o libcurl_la-http_negotiate.lo `test -f 'http_negotiate.c' || echo '$(srcdir)/'`http_negotiate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_negotiate.Tpo $(DEPDIR)/libcurl_la-http_negotiate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_negotiate.c' object='libcurl_la-http_negotiate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_negotiate.lo `test -f 'http_negotiate.c' || echo '$(srcdir)/'`http_negotiate.c + +libcurl_la-inet_pton.lo: inet_pton.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-inet_pton.lo -MD -MP -MF $(DEPDIR)/libcurl_la-inet_pton.Tpo -c -o libcurl_la-inet_pton.lo `test -f 'inet_pton.c' || echo '$(srcdir)/'`inet_pton.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-inet_pton.Tpo $(DEPDIR)/libcurl_la-inet_pton.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inet_pton.c' object='libcurl_la-inet_pton.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-inet_pton.lo `test -f 'inet_pton.c' || echo '$(srcdir)/'`inet_pton.c + +libcurl_la-strtoofft.lo: strtoofft.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-strtoofft.lo -MD -MP -MF $(DEPDIR)/libcurl_la-strtoofft.Tpo -c -o libcurl_la-strtoofft.lo `test -f 'strtoofft.c' || echo '$(srcdir)/'`strtoofft.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-strtoofft.Tpo $(DEPDIR)/libcurl_la-strtoofft.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strtoofft.c' object='libcurl_la-strtoofft.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strtoofft.lo `test -f 'strtoofft.c' || echo '$(srcdir)/'`strtoofft.c + +libcurl_la-strerror.lo: strerror.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-strerror.lo -MD -MP -MF $(DEPDIR)/libcurl_la-strerror.Tpo -c -o libcurl_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-strerror.Tpo $(DEPDIR)/libcurl_la-strerror.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strerror.c' object='libcurl_la-strerror.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c + +libcurl_la-amigaos.lo: amigaos.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-amigaos.lo -MD -MP -MF $(DEPDIR)/libcurl_la-amigaos.Tpo -c -o libcurl_la-amigaos.lo `test -f 'amigaos.c' || echo '$(srcdir)/'`amigaos.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-amigaos.Tpo $(DEPDIR)/libcurl_la-amigaos.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='amigaos.c' object='libcurl_la-amigaos.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-amigaos.lo `test -f 'amigaos.c' || echo '$(srcdir)/'`amigaos.c + +libcurl_la-hostasyn.lo: hostasyn.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostasyn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostasyn.Tpo -c -o libcurl_la-hostasyn.lo `test -f 'hostasyn.c' || echo '$(srcdir)/'`hostasyn.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostasyn.Tpo $(DEPDIR)/libcurl_la-hostasyn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostasyn.c' object='libcurl_la-hostasyn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostasyn.lo `test -f 'hostasyn.c' || echo '$(srcdir)/'`hostasyn.c + +libcurl_la-hostip4.lo: hostip4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostip4.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostip4.Tpo -c -o libcurl_la-hostip4.lo `test -f 'hostip4.c' || echo '$(srcdir)/'`hostip4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostip4.Tpo $(DEPDIR)/libcurl_la-hostip4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostip4.c' object='libcurl_la-hostip4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostip4.lo `test -f 'hostip4.c' || echo '$(srcdir)/'`hostip4.c + +libcurl_la-hostip6.lo: hostip6.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostip6.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostip6.Tpo -c -o libcurl_la-hostip6.lo `test -f 'hostip6.c' || echo '$(srcdir)/'`hostip6.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostip6.Tpo $(DEPDIR)/libcurl_la-hostip6.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostip6.c' object='libcurl_la-hostip6.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostip6.lo `test -f 'hostip6.c' || echo '$(srcdir)/'`hostip6.c + +libcurl_la-hostsyn.lo: hostsyn.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostsyn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostsyn.Tpo -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostsyn.Tpo $(DEPDIR)/libcurl_la-hostsyn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostsyn.c' object='libcurl_la-hostsyn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c + +libcurl_la-inet_ntop.lo: inet_ntop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-inet_ntop.lo -MD -MP -MF $(DEPDIR)/libcurl_la-inet_ntop.Tpo -c -o libcurl_la-inet_ntop.lo `test -f 'inet_ntop.c' || echo '$(srcdir)/'`inet_ntop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-inet_ntop.Tpo $(DEPDIR)/libcurl_la-inet_ntop.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inet_ntop.c' object='libcurl_la-inet_ntop.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-inet_ntop.lo `test -f 'inet_ntop.c' || echo '$(srcdir)/'`inet_ntop.c + +libcurl_la-parsedate.lo: parsedate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-parsedate.lo -MD -MP -MF $(DEPDIR)/libcurl_la-parsedate.Tpo -c -o libcurl_la-parsedate.lo `test -f 'parsedate.c' || echo '$(srcdir)/'`parsedate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-parsedate.Tpo $(DEPDIR)/libcurl_la-parsedate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parsedate.c' object='libcurl_la-parsedate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-parsedate.lo `test -f 'parsedate.c' || echo '$(srcdir)/'`parsedate.c + +libcurl_la-select.lo: select.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-select.lo -MD -MP -MF $(DEPDIR)/libcurl_la-select.Tpo -c -o libcurl_la-select.lo `test -f 'select.c' || echo '$(srcdir)/'`select.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-select.Tpo $(DEPDIR)/libcurl_la-select.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='select.c' object='libcurl_la-select.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-select.lo `test -f 'select.c' || echo '$(srcdir)/'`select.c + +libcurl_la-tftp.lo: tftp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-tftp.lo -MD -MP -MF $(DEPDIR)/libcurl_la-tftp.Tpo -c -o libcurl_la-tftp.lo `test -f 'tftp.c' || echo '$(srcdir)/'`tftp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-tftp.Tpo $(DEPDIR)/libcurl_la-tftp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tftp.c' object='libcurl_la-tftp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-tftp.lo `test -f 'tftp.c' || echo '$(srcdir)/'`tftp.c + +libcurl_la-splay.lo: splay.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-splay.lo -MD -MP -MF $(DEPDIR)/libcurl_la-splay.Tpo -c -o libcurl_la-splay.lo `test -f 'splay.c' || echo '$(srcdir)/'`splay.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-splay.Tpo $(DEPDIR)/libcurl_la-splay.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='splay.c' object='libcurl_la-splay.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-splay.lo `test -f 'splay.c' || echo '$(srcdir)/'`splay.c + +libcurl_la-strdup.lo: strdup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-strdup.lo -MD -MP -MF $(DEPDIR)/libcurl_la-strdup.Tpo -c -o libcurl_la-strdup.lo `test -f 'strdup.c' || echo '$(srcdir)/'`strdup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-strdup.Tpo $(DEPDIR)/libcurl_la-strdup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strdup.c' object='libcurl_la-strdup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strdup.lo `test -f 'strdup.c' || echo '$(srcdir)/'`strdup.c + +libcurl_la-socks.lo: socks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-socks.lo -MD -MP -MF $(DEPDIR)/libcurl_la-socks.Tpo -c -o libcurl_la-socks.lo `test -f 'socks.c' || echo '$(srcdir)/'`socks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-socks.Tpo $(DEPDIR)/libcurl_la-socks.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socks.c' object='libcurl_la-socks.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-socks.lo `test -f 'socks.c' || echo '$(srcdir)/'`socks.c + +libcurl_la-ssh.lo: ssh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ssh.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ssh.Tpo -c -o libcurl_la-ssh.lo `test -f 'ssh.c' || echo '$(srcdir)/'`ssh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ssh.Tpo $(DEPDIR)/libcurl_la-ssh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ssh.c' object='libcurl_la-ssh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ssh.lo `test -f 'ssh.c' || echo '$(srcdir)/'`ssh.c + +libcurl_la-ssh-libssh.lo: ssh-libssh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ssh-libssh.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ssh-libssh.Tpo -c -o libcurl_la-ssh-libssh.lo `test -f 'ssh-libssh.c' || echo '$(srcdir)/'`ssh-libssh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ssh-libssh.Tpo $(DEPDIR)/libcurl_la-ssh-libssh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ssh-libssh.c' object='libcurl_la-ssh-libssh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-ssh-libssh.lo `test -f 'ssh-libssh.c' || echo '$(srcdir)/'`ssh-libssh.c + +libcurl_la-curl_addrinfo.lo: curl_addrinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_addrinfo.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_addrinfo.Tpo -c -o libcurl_la-curl_addrinfo.lo `test -f 'curl_addrinfo.c' || echo '$(srcdir)/'`curl_addrinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_addrinfo.Tpo $(DEPDIR)/libcurl_la-curl_addrinfo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_addrinfo.c' object='libcurl_la-curl_addrinfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_addrinfo.lo `test -f 'curl_addrinfo.c' || echo '$(srcdir)/'`curl_addrinfo.c + +libcurl_la-socks_gssapi.lo: socks_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-socks_gssapi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-socks_gssapi.Tpo -c -o libcurl_la-socks_gssapi.lo `test -f 'socks_gssapi.c' || echo '$(srcdir)/'`socks_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-socks_gssapi.Tpo $(DEPDIR)/libcurl_la-socks_gssapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socks_gssapi.c' object='libcurl_la-socks_gssapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-socks_gssapi.lo `test -f 'socks_gssapi.c' || echo '$(srcdir)/'`socks_gssapi.c + +libcurl_la-socks_sspi.lo: socks_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-socks_sspi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-socks_sspi.Tpo -c -o libcurl_la-socks_sspi.lo `test -f 'socks_sspi.c' || echo '$(srcdir)/'`socks_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-socks_sspi.Tpo $(DEPDIR)/libcurl_la-socks_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socks_sspi.c' object='libcurl_la-socks_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-socks_sspi.lo `test -f 'socks_sspi.c' || echo '$(srcdir)/'`socks_sspi.c + +libcurl_la-curl_sspi.lo: curl_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_sspi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_sspi.Tpo -c -o libcurl_la-curl_sspi.lo `test -f 'curl_sspi.c' || echo '$(srcdir)/'`curl_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_sspi.Tpo $(DEPDIR)/libcurl_la-curl_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_sspi.c' object='libcurl_la-curl_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_sspi.lo `test -f 'curl_sspi.c' || echo '$(srcdir)/'`curl_sspi.c + +libcurl_la-slist.lo: slist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-slist.lo -MD -MP -MF $(DEPDIR)/libcurl_la-slist.Tpo -c -o libcurl_la-slist.lo `test -f 'slist.c' || echo '$(srcdir)/'`slist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-slist.Tpo $(DEPDIR)/libcurl_la-slist.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slist.c' object='libcurl_la-slist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-slist.lo `test -f 'slist.c' || echo '$(srcdir)/'`slist.c + +libcurl_la-nonblock.lo: nonblock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-nonblock.lo -MD -MP -MF $(DEPDIR)/libcurl_la-nonblock.Tpo -c -o libcurl_la-nonblock.lo `test -f 'nonblock.c' || echo '$(srcdir)/'`nonblock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-nonblock.Tpo $(DEPDIR)/libcurl_la-nonblock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nonblock.c' object='libcurl_la-nonblock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-nonblock.lo `test -f 'nonblock.c' || echo '$(srcdir)/'`nonblock.c + +libcurl_la-curl_memrchr.lo: curl_memrchr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_memrchr.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_memrchr.Tpo -c -o libcurl_la-curl_memrchr.lo `test -f 'curl_memrchr.c' || echo '$(srcdir)/'`curl_memrchr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_memrchr.Tpo $(DEPDIR)/libcurl_la-curl_memrchr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_memrchr.c' object='libcurl_la-curl_memrchr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_memrchr.lo `test -f 'curl_memrchr.c' || echo '$(srcdir)/'`curl_memrchr.c + +libcurl_la-imap.lo: imap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-imap.lo -MD -MP -MF $(DEPDIR)/libcurl_la-imap.Tpo -c -o libcurl_la-imap.lo `test -f 'imap.c' || echo '$(srcdir)/'`imap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-imap.Tpo $(DEPDIR)/libcurl_la-imap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imap.c' object='libcurl_la-imap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-imap.lo `test -f 'imap.c' || echo '$(srcdir)/'`imap.c + +libcurl_la-pop3.lo: pop3.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-pop3.lo -MD -MP -MF $(DEPDIR)/libcurl_la-pop3.Tpo -c -o libcurl_la-pop3.lo `test -f 'pop3.c' || echo '$(srcdir)/'`pop3.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-pop3.Tpo $(DEPDIR)/libcurl_la-pop3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pop3.c' object='libcurl_la-pop3.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-pop3.lo `test -f 'pop3.c' || echo '$(srcdir)/'`pop3.c + +libcurl_la-smtp.lo: smtp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-smtp.lo -MD -MP -MF $(DEPDIR)/libcurl_la-smtp.Tpo -c -o libcurl_la-smtp.lo `test -f 'smtp.c' || echo '$(srcdir)/'`smtp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-smtp.Tpo $(DEPDIR)/libcurl_la-smtp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtp.c' object='libcurl_la-smtp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-smtp.lo `test -f 'smtp.c' || echo '$(srcdir)/'`smtp.c + +libcurl_la-pingpong.lo: pingpong.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-pingpong.lo -MD -MP -MF $(DEPDIR)/libcurl_la-pingpong.Tpo -c -o libcurl_la-pingpong.lo `test -f 'pingpong.c' || echo '$(srcdir)/'`pingpong.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-pingpong.Tpo $(DEPDIR)/libcurl_la-pingpong.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pingpong.c' object='libcurl_la-pingpong.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-pingpong.lo `test -f 'pingpong.c' || echo '$(srcdir)/'`pingpong.c + +libcurl_la-rtsp.lo: rtsp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-rtsp.lo -MD -MP -MF $(DEPDIR)/libcurl_la-rtsp.Tpo -c -o libcurl_la-rtsp.lo `test -f 'rtsp.c' || echo '$(srcdir)/'`rtsp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-rtsp.Tpo $(DEPDIR)/libcurl_la-rtsp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp.c' object='libcurl_la-rtsp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-rtsp.lo `test -f 'rtsp.c' || echo '$(srcdir)/'`rtsp.c + +libcurl_la-curl_threads.lo: curl_threads.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_threads.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_threads.Tpo -c -o libcurl_la-curl_threads.lo `test -f 'curl_threads.c' || echo '$(srcdir)/'`curl_threads.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_threads.Tpo $(DEPDIR)/libcurl_la-curl_threads.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_threads.c' object='libcurl_la-curl_threads.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_threads.lo `test -f 'curl_threads.c' || echo '$(srcdir)/'`curl_threads.c + +libcurl_la-warnless.lo: warnless.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurl_la-warnless.Tpo -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-warnless.Tpo $(DEPDIR)/libcurl_la-warnless.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='warnless.c' object='libcurl_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c + +libcurl_la-hmac.lo: hmac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hmac.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hmac.Tpo -c -o libcurl_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hmac.Tpo $(DEPDIR)/libcurl_la-hmac.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hmac.c' object='libcurl_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c + +libcurl_la-curl_rtmp.lo: curl_rtmp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_rtmp.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_rtmp.Tpo -c -o libcurl_la-curl_rtmp.lo `test -f 'curl_rtmp.c' || echo '$(srcdir)/'`curl_rtmp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_rtmp.Tpo $(DEPDIR)/libcurl_la-curl_rtmp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_rtmp.c' object='libcurl_la-curl_rtmp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_rtmp.lo `test -f 'curl_rtmp.c' || echo '$(srcdir)/'`curl_rtmp.c + +libcurl_la-openldap.lo: openldap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-openldap.lo -MD -MP -MF $(DEPDIR)/libcurl_la-openldap.Tpo -c -o libcurl_la-openldap.lo `test -f 'openldap.c' || echo '$(srcdir)/'`openldap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-openldap.Tpo $(DEPDIR)/libcurl_la-openldap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='openldap.c' object='libcurl_la-openldap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-openldap.lo `test -f 'openldap.c' || echo '$(srcdir)/'`openldap.c + +libcurl_la-curl_gethostname.lo: curl_gethostname.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_gethostname.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_gethostname.Tpo -c -o libcurl_la-curl_gethostname.lo `test -f 'curl_gethostname.c' || echo '$(srcdir)/'`curl_gethostname.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_gethostname.Tpo $(DEPDIR)/libcurl_la-curl_gethostname.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_gethostname.c' object='libcurl_la-curl_gethostname.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_gethostname.lo `test -f 'curl_gethostname.c' || echo '$(srcdir)/'`curl_gethostname.c + +libcurl_la-gopher.lo: gopher.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-gopher.lo -MD -MP -MF $(DEPDIR)/libcurl_la-gopher.Tpo -c -o libcurl_la-gopher.lo `test -f 'gopher.c' || echo '$(srcdir)/'`gopher.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-gopher.Tpo $(DEPDIR)/libcurl_la-gopher.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gopher.c' object='libcurl_la-gopher.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-gopher.lo `test -f 'gopher.c' || echo '$(srcdir)/'`gopher.c + +libcurl_la-idn_win32.lo: idn_win32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-idn_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-idn_win32.Tpo -c -o libcurl_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-idn_win32.Tpo $(DEPDIR)/libcurl_la-idn_win32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='idn_win32.c' object='libcurl_la-idn_win32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c + +libcurl_la-http_proxy.lo: http_proxy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_proxy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_proxy.Tpo -c -o libcurl_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_proxy.Tpo $(DEPDIR)/libcurl_la-http_proxy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_proxy.c' object='libcurl_la-http_proxy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c + +libcurl_la-non-ascii.lo: non-ascii.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-non-ascii.lo -MD -MP -MF $(DEPDIR)/libcurl_la-non-ascii.Tpo -c -o libcurl_la-non-ascii.lo `test -f 'non-ascii.c' || echo '$(srcdir)/'`non-ascii.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-non-ascii.Tpo $(DEPDIR)/libcurl_la-non-ascii.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='non-ascii.c' object='libcurl_la-non-ascii.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-non-ascii.lo `test -f 'non-ascii.c' || echo '$(srcdir)/'`non-ascii.c + +libcurl_la-asyn-ares.lo: asyn-ares.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-asyn-ares.lo -MD -MP -MF $(DEPDIR)/libcurl_la-asyn-ares.Tpo -c -o libcurl_la-asyn-ares.lo `test -f 'asyn-ares.c' || echo '$(srcdir)/'`asyn-ares.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-asyn-ares.Tpo $(DEPDIR)/libcurl_la-asyn-ares.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-ares.c' object='libcurl_la-asyn-ares.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-asyn-ares.lo `test -f 'asyn-ares.c' || echo '$(srcdir)/'`asyn-ares.c + +libcurl_la-asyn-thread.lo: asyn-thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-asyn-thread.lo -MD -MP -MF $(DEPDIR)/libcurl_la-asyn-thread.Tpo -c -o libcurl_la-asyn-thread.lo `test -f 'asyn-thread.c' || echo '$(srcdir)/'`asyn-thread.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-asyn-thread.Tpo $(DEPDIR)/libcurl_la-asyn-thread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-thread.c' object='libcurl_la-asyn-thread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-asyn-thread.lo `test -f 'asyn-thread.c' || echo '$(srcdir)/'`asyn-thread.c + +libcurl_la-curl_gssapi.lo: curl_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_gssapi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_gssapi.Tpo -c -o libcurl_la-curl_gssapi.lo `test -f 'curl_gssapi.c' || echo '$(srcdir)/'`curl_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_gssapi.Tpo $(DEPDIR)/libcurl_la-curl_gssapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_gssapi.c' object='libcurl_la-curl_gssapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_gssapi.lo `test -f 'curl_gssapi.c' || echo '$(srcdir)/'`curl_gssapi.c + +libcurl_la-http_ntlm.lo: http_ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http_ntlm.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http_ntlm.Tpo -c -o libcurl_la-http_ntlm.lo `test -f 'http_ntlm.c' || echo '$(srcdir)/'`http_ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http_ntlm.Tpo $(DEPDIR)/libcurl_la-http_ntlm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_ntlm.c' object='libcurl_la-http_ntlm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http_ntlm.lo `test -f 'http_ntlm.c' || echo '$(srcdir)/'`http_ntlm.c + +libcurl_la-curl_ntlm_wb.lo: curl_ntlm_wb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_ntlm_wb.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_ntlm_wb.Tpo -c -o libcurl_la-curl_ntlm_wb.lo `test -f 'curl_ntlm_wb.c' || echo '$(srcdir)/'`curl_ntlm_wb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_ntlm_wb.Tpo $(DEPDIR)/libcurl_la-curl_ntlm_wb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_ntlm_wb.c' object='libcurl_la-curl_ntlm_wb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_ntlm_wb.lo `test -f 'curl_ntlm_wb.c' || echo '$(srcdir)/'`curl_ntlm_wb.c + +libcurl_la-curl_ntlm_core.lo: curl_ntlm_core.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_ntlm_core.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_ntlm_core.Tpo -c -o libcurl_la-curl_ntlm_core.lo `test -f 'curl_ntlm_core.c' || echo '$(srcdir)/'`curl_ntlm_core.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_ntlm_core.Tpo $(DEPDIR)/libcurl_la-curl_ntlm_core.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_ntlm_core.c' object='libcurl_la-curl_ntlm_core.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_ntlm_core.lo `test -f 'curl_ntlm_core.c' || echo '$(srcdir)/'`curl_ntlm_core.c + +libcurl_la-curl_sasl.lo: curl_sasl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_sasl.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_sasl.Tpo -c -o libcurl_la-curl_sasl.lo `test -f 'curl_sasl.c' || echo '$(srcdir)/'`curl_sasl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_sasl.Tpo $(DEPDIR)/libcurl_la-curl_sasl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_sasl.c' object='libcurl_la-curl_sasl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_sasl.lo `test -f 'curl_sasl.c' || echo '$(srcdir)/'`curl_sasl.c + +libcurl_la-rand.lo: rand.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-rand.lo -MD -MP -MF $(DEPDIR)/libcurl_la-rand.Tpo -c -o libcurl_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-rand.Tpo $(DEPDIR)/libcurl_la-rand.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rand.c' object='libcurl_la-rand.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c + +libcurl_la-curl_multibyte.lo: curl_multibyte.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_multibyte.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_multibyte.Tpo -c -o libcurl_la-curl_multibyte.lo `test -f 'curl_multibyte.c' || echo '$(srcdir)/'`curl_multibyte.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_multibyte.Tpo $(DEPDIR)/libcurl_la-curl_multibyte.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_multibyte.c' object='libcurl_la-curl_multibyte.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_multibyte.lo `test -f 'curl_multibyte.c' || echo '$(srcdir)/'`curl_multibyte.c + +libcurl_la-hostcheck.lo: hostcheck.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostcheck.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostcheck.Tpo -c -o libcurl_la-hostcheck.lo `test -f 'hostcheck.c' || echo '$(srcdir)/'`hostcheck.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostcheck.Tpo $(DEPDIR)/libcurl_la-hostcheck.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostcheck.c' object='libcurl_la-hostcheck.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostcheck.lo `test -f 'hostcheck.c' || echo '$(srcdir)/'`hostcheck.c + +libcurl_la-conncache.lo: conncache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurl_la-conncache.Tpo -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-conncache.Tpo $(DEPDIR)/libcurl_la-conncache.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conncache.c' object='libcurl_la-conncache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c + +libcurl_la-dotdot.lo: dotdot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dotdot.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dotdot.Tpo -c -o libcurl_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dotdot.Tpo $(DEPDIR)/libcurl_la-dotdot.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dotdot.c' object='libcurl_la-dotdot.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c + +libcurl_la-x509asn1.lo: x509asn1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-x509asn1.lo -MD -MP -MF $(DEPDIR)/libcurl_la-x509asn1.Tpo -c -o libcurl_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-x509asn1.Tpo $(DEPDIR)/libcurl_la-x509asn1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='x509asn1.c' object='libcurl_la-x509asn1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c + +libcurl_la-http2.lo: http2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-http2.lo -MD -MP -MF $(DEPDIR)/libcurl_la-http2.Tpo -c -o libcurl_la-http2.lo `test -f 'http2.c' || echo '$(srcdir)/'`http2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-http2.Tpo $(DEPDIR)/libcurl_la-http2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http2.c' object='libcurl_la-http2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-http2.lo `test -f 'http2.c' || echo '$(srcdir)/'`http2.c + +libcurl_la-smb.lo: smb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-smb.lo -MD -MP -MF $(DEPDIR)/libcurl_la-smb.Tpo -c -o libcurl_la-smb.lo `test -f 'smb.c' || echo '$(srcdir)/'`smb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-smb.Tpo $(DEPDIR)/libcurl_la-smb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smb.c' object='libcurl_la-smb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-smb.lo `test -f 'smb.c' || echo '$(srcdir)/'`smb.c + +libcurl_la-curl_endian.lo: curl_endian.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_endian.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_endian.Tpo -c -o libcurl_la-curl_endian.lo `test -f 'curl_endian.c' || echo '$(srcdir)/'`curl_endian.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_endian.Tpo $(DEPDIR)/libcurl_la-curl_endian.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_endian.c' object='libcurl_la-curl_endian.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_endian.lo `test -f 'curl_endian.c' || echo '$(srcdir)/'`curl_endian.c + +libcurl_la-curl_des.lo: curl_des.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_des.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_des.Tpo -c -o libcurl_la-curl_des.lo `test -f 'curl_des.c' || echo '$(srcdir)/'`curl_des.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_des.Tpo $(DEPDIR)/libcurl_la-curl_des.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_des.c' object='libcurl_la-curl_des.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_des.lo `test -f 'curl_des.c' || echo '$(srcdir)/'`curl_des.c + +libcurl_la-system_win32.lo: system_win32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-system_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-system_win32.Tpo -c -o libcurl_la-system_win32.lo `test -f 'system_win32.c' || echo '$(srcdir)/'`system_win32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-system_win32.Tpo $(DEPDIR)/libcurl_la-system_win32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='system_win32.c' object='libcurl_la-system_win32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-system_win32.lo `test -f 'system_win32.c' || echo '$(srcdir)/'`system_win32.c + +libcurl_la-mime.lo: mime.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-mime.lo -MD -MP -MF $(DEPDIR)/libcurl_la-mime.Tpo -c -o libcurl_la-mime.lo `test -f 'mime.c' || echo '$(srcdir)/'`mime.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-mime.Tpo $(DEPDIR)/libcurl_la-mime.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mime.c' object='libcurl_la-mime.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-mime.lo `test -f 'mime.c' || echo '$(srcdir)/'`mime.c + +libcurl_la-sha256.lo: sha256.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-sha256.lo -MD -MP -MF $(DEPDIR)/libcurl_la-sha256.Tpo -c -o libcurl_la-sha256.lo `test -f 'sha256.c' || echo '$(srcdir)/'`sha256.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-sha256.Tpo $(DEPDIR)/libcurl_la-sha256.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sha256.c' object='libcurl_la-sha256.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-sha256.lo `test -f 'sha256.c' || echo '$(srcdir)/'`sha256.c + +libcurl_la-setopt.lo: setopt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-setopt.lo -MD -MP -MF $(DEPDIR)/libcurl_la-setopt.Tpo -c -o libcurl_la-setopt.lo `test -f 'setopt.c' || echo '$(srcdir)/'`setopt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-setopt.Tpo $(DEPDIR)/libcurl_la-setopt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='setopt.c' object='libcurl_la-setopt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-setopt.lo `test -f 'setopt.c' || echo '$(srcdir)/'`setopt.c + +libcurl_la-curl_path.lo: curl_path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_path.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_path.Tpo -c -o libcurl_la-curl_path.lo `test -f 'curl_path.c' || echo '$(srcdir)/'`curl_path.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_path.Tpo $(DEPDIR)/libcurl_la-curl_path.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_path.c' object='libcurl_la-curl_path.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_path.lo `test -f 'curl_path.c' || echo '$(srcdir)/'`curl_path.c + +libcurl_la-curl_ctype.lo: curl_ctype.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_ctype.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_ctype.Tpo -c -o libcurl_la-curl_ctype.lo `test -f 'curl_ctype.c' || echo '$(srcdir)/'`curl_ctype.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_ctype.Tpo $(DEPDIR)/libcurl_la-curl_ctype.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_ctype.c' object='libcurl_la-curl_ctype.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_ctype.lo `test -f 'curl_ctype.c' || echo '$(srcdir)/'`curl_ctype.c + +libcurl_la-curl_range.lo: curl_range.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_range.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_range.Tpo -c -o libcurl_la-curl_range.lo `test -f 'curl_range.c' || echo '$(srcdir)/'`curl_range.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_range.Tpo $(DEPDIR)/libcurl_la-curl_range.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_range.c' object='libcurl_la-curl_range.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_range.lo `test -f 'curl_range.c' || echo '$(srcdir)/'`curl_range.c + +libcurl_la-psl.lo: psl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-psl.lo -MD -MP -MF $(DEPDIR)/libcurl_la-psl.Tpo -c -o libcurl_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-psl.Tpo $(DEPDIR)/libcurl_la-psl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='psl.c' object='libcurl_la-psl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c + +libcurl_la-doh.lo: doh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurl_la-doh.Tpo -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-doh.Tpo $(DEPDIR)/libcurl_la-doh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh.c' object='libcurl_la-doh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c + +libcurl_la-urlapi.lo: urlapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-urlapi.lo -MD -MP -MF $(DEPDIR)/libcurl_la-urlapi.Tpo -c -o libcurl_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-urlapi.Tpo $(DEPDIR)/libcurl_la-urlapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='urlapi.c' object='libcurl_la-urlapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c + +libcurl_la-curl_get_line.lo: curl_get_line.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_get_line.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_get_line.Tpo -c -o libcurl_la-curl_get_line.lo `test -f 'curl_get_line.c' || echo '$(srcdir)/'`curl_get_line.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_get_line.Tpo $(DEPDIR)/libcurl_la-curl_get_line.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_get_line.c' object='libcurl_la-curl_get_line.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_get_line.lo `test -f 'curl_get_line.c' || echo '$(srcdir)/'`curl_get_line.c + +libcurl_la-altsvc.lo: altsvc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-altsvc.lo -MD -MP -MF $(DEPDIR)/libcurl_la-altsvc.Tpo -c -o libcurl_la-altsvc.lo `test -f 'altsvc.c' || echo '$(srcdir)/'`altsvc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-altsvc.Tpo $(DEPDIR)/libcurl_la-altsvc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='altsvc.c' object='libcurl_la-altsvc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-altsvc.lo `test -f 'altsvc.c' || echo '$(srcdir)/'`altsvc.c + +vauth/libcurl_la-vauth.lo: vauth/vauth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-vauth.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-vauth.Tpo -c -o vauth/libcurl_la-vauth.lo `test -f 'vauth/vauth.c' || echo '$(srcdir)/'`vauth/vauth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-vauth.Tpo vauth/$(DEPDIR)/libcurl_la-vauth.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/vauth.c' object='vauth/libcurl_la-vauth.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-vauth.lo `test -f 'vauth/vauth.c' || echo '$(srcdir)/'`vauth/vauth.c + +vauth/libcurl_la-cleartext.lo: vauth/cleartext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-cleartext.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-cleartext.Tpo -c -o vauth/libcurl_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-cleartext.Tpo vauth/$(DEPDIR)/libcurl_la-cleartext.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/cleartext.c' object='vauth/libcurl_la-cleartext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c + +vauth/libcurl_la-cram.lo: vauth/cram.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-cram.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-cram.Tpo -c -o vauth/libcurl_la-cram.lo `test -f 'vauth/cram.c' || echo '$(srcdir)/'`vauth/cram.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-cram.Tpo vauth/$(DEPDIR)/libcurl_la-cram.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/cram.c' object='vauth/libcurl_la-cram.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-cram.lo `test -f 'vauth/cram.c' || echo '$(srcdir)/'`vauth/cram.c + +vauth/libcurl_la-digest.lo: vauth/digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-digest.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-digest.Tpo -c -o vauth/libcurl_la-digest.lo `test -f 'vauth/digest.c' || echo '$(srcdir)/'`vauth/digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-digest.Tpo vauth/$(DEPDIR)/libcurl_la-digest.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/digest.c' object='vauth/libcurl_la-digest.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-digest.lo `test -f 'vauth/digest.c' || echo '$(srcdir)/'`vauth/digest.c + +vauth/libcurl_la-digest_sspi.lo: vauth/digest_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-digest_sspi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-digest_sspi.Tpo -c -o vauth/libcurl_la-digest_sspi.lo `test -f 'vauth/digest_sspi.c' || echo '$(srcdir)/'`vauth/digest_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-digest_sspi.Tpo vauth/$(DEPDIR)/libcurl_la-digest_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/digest_sspi.c' object='vauth/libcurl_la-digest_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-digest_sspi.lo `test -f 'vauth/digest_sspi.c' || echo '$(srcdir)/'`vauth/digest_sspi.c + +vauth/libcurl_la-krb5_gssapi.lo: vauth/krb5_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-krb5_gssapi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-krb5_gssapi.Tpo -c -o vauth/libcurl_la-krb5_gssapi.lo `test -f 'vauth/krb5_gssapi.c' || echo '$(srcdir)/'`vauth/krb5_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-krb5_gssapi.Tpo vauth/$(DEPDIR)/libcurl_la-krb5_gssapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/krb5_gssapi.c' object='vauth/libcurl_la-krb5_gssapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-krb5_gssapi.lo `test -f 'vauth/krb5_gssapi.c' || echo '$(srcdir)/'`vauth/krb5_gssapi.c + +vauth/libcurl_la-krb5_sspi.lo: vauth/krb5_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-krb5_sspi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-krb5_sspi.Tpo -c -o vauth/libcurl_la-krb5_sspi.lo `test -f 'vauth/krb5_sspi.c' || echo '$(srcdir)/'`vauth/krb5_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-krb5_sspi.Tpo vauth/$(DEPDIR)/libcurl_la-krb5_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/krb5_sspi.c' object='vauth/libcurl_la-krb5_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-krb5_sspi.lo `test -f 'vauth/krb5_sspi.c' || echo '$(srcdir)/'`vauth/krb5_sspi.c + +vauth/libcurl_la-ntlm.lo: vauth/ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-ntlm.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-ntlm.Tpo -c -o vauth/libcurl_la-ntlm.lo `test -f 'vauth/ntlm.c' || echo '$(srcdir)/'`vauth/ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-ntlm.Tpo vauth/$(DEPDIR)/libcurl_la-ntlm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/ntlm.c' object='vauth/libcurl_la-ntlm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-ntlm.lo `test -f 'vauth/ntlm.c' || echo '$(srcdir)/'`vauth/ntlm.c + +vauth/libcurl_la-ntlm_sspi.lo: vauth/ntlm_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-ntlm_sspi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-ntlm_sspi.Tpo -c -o vauth/libcurl_la-ntlm_sspi.lo `test -f 'vauth/ntlm_sspi.c' || echo '$(srcdir)/'`vauth/ntlm_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-ntlm_sspi.Tpo vauth/$(DEPDIR)/libcurl_la-ntlm_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/ntlm_sspi.c' object='vauth/libcurl_la-ntlm_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-ntlm_sspi.lo `test -f 'vauth/ntlm_sspi.c' || echo '$(srcdir)/'`vauth/ntlm_sspi.c + +vauth/libcurl_la-oauth2.lo: vauth/oauth2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-oauth2.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-oauth2.Tpo -c -o vauth/libcurl_la-oauth2.lo `test -f 'vauth/oauth2.c' || echo '$(srcdir)/'`vauth/oauth2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-oauth2.Tpo vauth/$(DEPDIR)/libcurl_la-oauth2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/oauth2.c' object='vauth/libcurl_la-oauth2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-oauth2.lo `test -f 'vauth/oauth2.c' || echo '$(srcdir)/'`vauth/oauth2.c + +vauth/libcurl_la-spnego_gssapi.lo: vauth/spnego_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-spnego_gssapi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-spnego_gssapi.Tpo -c -o vauth/libcurl_la-spnego_gssapi.lo `test -f 'vauth/spnego_gssapi.c' || echo '$(srcdir)/'`vauth/spnego_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-spnego_gssapi.Tpo vauth/$(DEPDIR)/libcurl_la-spnego_gssapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/spnego_gssapi.c' object='vauth/libcurl_la-spnego_gssapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-spnego_gssapi.lo `test -f 'vauth/spnego_gssapi.c' || echo '$(srcdir)/'`vauth/spnego_gssapi.c + +vauth/libcurl_la-spnego_sspi.lo: vauth/spnego_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vauth/libcurl_la-spnego_sspi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurl_la-spnego_sspi.Tpo -c -o vauth/libcurl_la-spnego_sspi.lo `test -f 'vauth/spnego_sspi.c' || echo '$(srcdir)/'`vauth/spnego_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurl_la-spnego_sspi.Tpo vauth/$(DEPDIR)/libcurl_la-spnego_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/spnego_sspi.c' object='vauth/libcurl_la-spnego_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurl_la-spnego_sspi.lo `test -f 'vauth/spnego_sspi.c' || echo '$(srcdir)/'`vauth/spnego_sspi.c + +vtls/libcurl_la-openssl.lo: vtls/openssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-openssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-openssl.Tpo -c -o vtls/libcurl_la-openssl.lo `test -f 'vtls/openssl.c' || echo '$(srcdir)/'`vtls/openssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-openssl.Tpo vtls/$(DEPDIR)/libcurl_la-openssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/openssl.c' object='vtls/libcurl_la-openssl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-openssl.lo `test -f 'vtls/openssl.c' || echo '$(srcdir)/'`vtls/openssl.c + +vtls/libcurl_la-gtls.lo: vtls/gtls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-gtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-gtls.Tpo -c -o vtls/libcurl_la-gtls.lo `test -f 'vtls/gtls.c' || echo '$(srcdir)/'`vtls/gtls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-gtls.Tpo vtls/$(DEPDIR)/libcurl_la-gtls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/gtls.c' object='vtls/libcurl_la-gtls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-gtls.lo `test -f 'vtls/gtls.c' || echo '$(srcdir)/'`vtls/gtls.c + +vtls/libcurl_la-vtls.lo: vtls/vtls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-vtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-vtls.Tpo -c -o vtls/libcurl_la-vtls.lo `test -f 'vtls/vtls.c' || echo '$(srcdir)/'`vtls/vtls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-vtls.Tpo vtls/$(DEPDIR)/libcurl_la-vtls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/vtls.c' object='vtls/libcurl_la-vtls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-vtls.lo `test -f 'vtls/vtls.c' || echo '$(srcdir)/'`vtls/vtls.c + +vtls/libcurl_la-nss.lo: vtls/nss.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-nss.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-nss.Tpo -c -o vtls/libcurl_la-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-nss.Tpo vtls/$(DEPDIR)/libcurl_la-nss.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/nss.c' object='vtls/libcurl_la-nss.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c + +vtls/libcurl_la-polarssl.lo: vtls/polarssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-polarssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-polarssl.Tpo -c -o vtls/libcurl_la-polarssl.lo `test -f 'vtls/polarssl.c' || echo '$(srcdir)/'`vtls/polarssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-polarssl.Tpo vtls/$(DEPDIR)/libcurl_la-polarssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/polarssl.c' object='vtls/libcurl_la-polarssl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-polarssl.lo `test -f 'vtls/polarssl.c' || echo '$(srcdir)/'`vtls/polarssl.c + +vtls/libcurl_la-polarssl_threadlock.lo: vtls/polarssl_threadlock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-polarssl_threadlock.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Tpo -c -o vtls/libcurl_la-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Tpo vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/polarssl_threadlock.c' object='vtls/libcurl_la-polarssl_threadlock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c + +vtls/libcurl_la-wolfssl.lo: vtls/wolfssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-wolfssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-wolfssl.Tpo -c -o vtls/libcurl_la-wolfssl.lo `test -f 'vtls/wolfssl.c' || echo '$(srcdir)/'`vtls/wolfssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-wolfssl.Tpo vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/wolfssl.c' object='vtls/libcurl_la-wolfssl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-wolfssl.lo `test -f 'vtls/wolfssl.c' || echo '$(srcdir)/'`vtls/wolfssl.c + +vtls/libcurl_la-schannel.lo: vtls/schannel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-schannel.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-schannel.Tpo -c -o vtls/libcurl_la-schannel.lo `test -f 'vtls/schannel.c' || echo '$(srcdir)/'`vtls/schannel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-schannel.Tpo vtls/$(DEPDIR)/libcurl_la-schannel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/schannel.c' object='vtls/libcurl_la-schannel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-schannel.lo `test -f 'vtls/schannel.c' || echo '$(srcdir)/'`vtls/schannel.c + +vtls/libcurl_la-schannel_verify.lo: vtls/schannel_verify.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-schannel_verify.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-schannel_verify.Tpo -c -o vtls/libcurl_la-schannel_verify.lo `test -f 'vtls/schannel_verify.c' || echo '$(srcdir)/'`vtls/schannel_verify.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-schannel_verify.Tpo vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/schannel_verify.c' object='vtls/libcurl_la-schannel_verify.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-schannel_verify.lo `test -f 'vtls/schannel_verify.c' || echo '$(srcdir)/'`vtls/schannel_verify.c + +vtls/libcurl_la-sectransp.lo: vtls/sectransp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-sectransp.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-sectransp.Tpo -c -o vtls/libcurl_la-sectransp.lo `test -f 'vtls/sectransp.c' || echo '$(srcdir)/'`vtls/sectransp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-sectransp.Tpo vtls/$(DEPDIR)/libcurl_la-sectransp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/sectransp.c' object='vtls/libcurl_la-sectransp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-sectransp.lo `test -f 'vtls/sectransp.c' || echo '$(srcdir)/'`vtls/sectransp.c + +vtls/libcurl_la-gskit.lo: vtls/gskit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-gskit.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-gskit.Tpo -c -o vtls/libcurl_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-gskit.Tpo vtls/$(DEPDIR)/libcurl_la-gskit.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/gskit.c' object='vtls/libcurl_la-gskit.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c + +vtls/libcurl_la-mbedtls.lo: vtls/mbedtls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-mbedtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-mbedtls.Tpo -c -o vtls/libcurl_la-mbedtls.lo `test -f 'vtls/mbedtls.c' || echo '$(srcdir)/'`vtls/mbedtls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-mbedtls.Tpo vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/mbedtls.c' object='vtls/libcurl_la-mbedtls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-mbedtls.lo `test -f 'vtls/mbedtls.c' || echo '$(srcdir)/'`vtls/mbedtls.c + +vtls/libcurl_la-mesalink.lo: vtls/mesalink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-mesalink.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-mesalink.Tpo -c -o vtls/libcurl_la-mesalink.lo `test -f 'vtls/mesalink.c' || echo '$(srcdir)/'`vtls/mesalink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-mesalink.Tpo vtls/$(DEPDIR)/libcurl_la-mesalink.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/mesalink.c' object='vtls/libcurl_la-mesalink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurl_la-mesalink.lo `test -f 'vtls/mesalink.c' || echo '$(srcdir)/'`vtls/mesalink.c + +libcurlu_la-file.lo: file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-file.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-file.Tpo -c -o libcurlu_la-file.lo `test -f 'file.c' || echo '$(srcdir)/'`file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-file.Tpo $(DEPDIR)/libcurlu_la-file.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='file.c' object='libcurlu_la-file.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-file.lo `test -f 'file.c' || echo '$(srcdir)/'`file.c + +libcurlu_la-timeval.lo: timeval.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-timeval.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-timeval.Tpo -c -o libcurlu_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-timeval.Tpo $(DEPDIR)/libcurlu_la-timeval.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timeval.c' object='libcurlu_la-timeval.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c + +libcurlu_la-base64.lo: base64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-base64.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-base64.Tpo -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-base64.Tpo $(DEPDIR)/libcurlu_la-base64.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='base64.c' object='libcurlu_la-base64.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c + +libcurlu_la-hostip.lo: hostip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostip.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostip.Tpo -c -o libcurlu_la-hostip.lo `test -f 'hostip.c' || echo '$(srcdir)/'`hostip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostip.Tpo $(DEPDIR)/libcurlu_la-hostip.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostip.c' object='libcurlu_la-hostip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostip.lo `test -f 'hostip.c' || echo '$(srcdir)/'`hostip.c + +libcurlu_la-progress.lo: progress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-progress.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-progress.Tpo -c -o libcurlu_la-progress.lo `test -f 'progress.c' || echo '$(srcdir)/'`progress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-progress.Tpo $(DEPDIR)/libcurlu_la-progress.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='progress.c' object='libcurlu_la-progress.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-progress.lo `test -f 'progress.c' || echo '$(srcdir)/'`progress.c + +libcurlu_la-formdata.lo: formdata.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-formdata.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-formdata.Tpo -c -o libcurlu_la-formdata.lo `test -f 'formdata.c' || echo '$(srcdir)/'`formdata.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-formdata.Tpo $(DEPDIR)/libcurlu_la-formdata.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='formdata.c' object='libcurlu_la-formdata.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-formdata.lo `test -f 'formdata.c' || echo '$(srcdir)/'`formdata.c + +libcurlu_la-cookie.lo: cookie.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-cookie.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-cookie.Tpo -c -o libcurlu_la-cookie.lo `test -f 'cookie.c' || echo '$(srcdir)/'`cookie.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-cookie.Tpo $(DEPDIR)/libcurlu_la-cookie.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cookie.c' object='libcurlu_la-cookie.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-cookie.lo `test -f 'cookie.c' || echo '$(srcdir)/'`cookie.c + +libcurlu_la-http.lo: http.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http.Tpo -c -o libcurlu_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http.Tpo $(DEPDIR)/libcurlu_la-http.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='libcurlu_la-http.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c + +libcurlu_la-sendf.lo: sendf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-sendf.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-sendf.Tpo -c -o libcurlu_la-sendf.lo `test -f 'sendf.c' || echo '$(srcdir)/'`sendf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-sendf.Tpo $(DEPDIR)/libcurlu_la-sendf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sendf.c' object='libcurlu_la-sendf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-sendf.lo `test -f 'sendf.c' || echo '$(srcdir)/'`sendf.c + +libcurlu_la-ftp.lo: ftp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ftp.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ftp.Tpo -c -o libcurlu_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ftp.Tpo $(DEPDIR)/libcurlu_la-ftp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ftp.c' object='libcurlu_la-ftp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ftp.lo `test -f 'ftp.c' || echo '$(srcdir)/'`ftp.c + +libcurlu_la-url.lo: url.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-url.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-url.Tpo -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-url.Tpo $(DEPDIR)/libcurlu_la-url.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='url.c' object='libcurlu_la-url.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c + +libcurlu_la-dict.lo: dict.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dict.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dict.Tpo -c -o libcurlu_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dict.Tpo $(DEPDIR)/libcurlu_la-dict.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dict.c' object='libcurlu_la-dict.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dict.lo `test -f 'dict.c' || echo '$(srcdir)/'`dict.c + +libcurlu_la-if2ip.lo: if2ip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-if2ip.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-if2ip.Tpo -c -o libcurlu_la-if2ip.lo `test -f 'if2ip.c' || echo '$(srcdir)/'`if2ip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-if2ip.Tpo $(DEPDIR)/libcurlu_la-if2ip.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='if2ip.c' object='libcurlu_la-if2ip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-if2ip.lo `test -f 'if2ip.c' || echo '$(srcdir)/'`if2ip.c + +libcurlu_la-speedcheck.lo: speedcheck.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-speedcheck.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-speedcheck.Tpo -c -o libcurlu_la-speedcheck.lo `test -f 'speedcheck.c' || echo '$(srcdir)/'`speedcheck.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-speedcheck.Tpo $(DEPDIR)/libcurlu_la-speedcheck.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='speedcheck.c' object='libcurlu_la-speedcheck.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-speedcheck.lo `test -f 'speedcheck.c' || echo '$(srcdir)/'`speedcheck.c + +libcurlu_la-ldap.lo: ldap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ldap.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ldap.Tpo -c -o libcurlu_la-ldap.lo `test -f 'ldap.c' || echo '$(srcdir)/'`ldap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ldap.Tpo $(DEPDIR)/libcurlu_la-ldap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ldap.c' object='libcurlu_la-ldap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ldap.lo `test -f 'ldap.c' || echo '$(srcdir)/'`ldap.c + +libcurlu_la-version.lo: version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-version.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-version.Tpo -c -o libcurlu_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-version.Tpo $(DEPDIR)/libcurlu_la-version.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version.c' object='libcurlu_la-version.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c + +libcurlu_la-getenv.lo: getenv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-getenv.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-getenv.Tpo -c -o libcurlu_la-getenv.lo `test -f 'getenv.c' || echo '$(srcdir)/'`getenv.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-getenv.Tpo $(DEPDIR)/libcurlu_la-getenv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='getenv.c' object='libcurlu_la-getenv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-getenv.lo `test -f 'getenv.c' || echo '$(srcdir)/'`getenv.c + +libcurlu_la-escape.lo: escape.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-escape.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-escape.Tpo -c -o libcurlu_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-escape.Tpo $(DEPDIR)/libcurlu_la-escape.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='escape.c' object='libcurlu_la-escape.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c + +libcurlu_la-mprintf.lo: mprintf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-mprintf.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-mprintf.Tpo -c -o libcurlu_la-mprintf.lo `test -f 'mprintf.c' || echo '$(srcdir)/'`mprintf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-mprintf.Tpo $(DEPDIR)/libcurlu_la-mprintf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mprintf.c' object='libcurlu_la-mprintf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-mprintf.lo `test -f 'mprintf.c' || echo '$(srcdir)/'`mprintf.c + +libcurlu_la-telnet.lo: telnet.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-telnet.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-telnet.Tpo -c -o libcurlu_la-telnet.lo `test -f 'telnet.c' || echo '$(srcdir)/'`telnet.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-telnet.Tpo $(DEPDIR)/libcurlu_la-telnet.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telnet.c' object='libcurlu_la-telnet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-telnet.lo `test -f 'telnet.c' || echo '$(srcdir)/'`telnet.c + +libcurlu_la-netrc.lo: netrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-netrc.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-netrc.Tpo -c -o libcurlu_la-netrc.lo `test -f 'netrc.c' || echo '$(srcdir)/'`netrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-netrc.Tpo $(DEPDIR)/libcurlu_la-netrc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netrc.c' object='libcurlu_la-netrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-netrc.lo `test -f 'netrc.c' || echo '$(srcdir)/'`netrc.c + +libcurlu_la-getinfo.lo: getinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-getinfo.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-getinfo.Tpo -c -o libcurlu_la-getinfo.lo `test -f 'getinfo.c' || echo '$(srcdir)/'`getinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-getinfo.Tpo $(DEPDIR)/libcurlu_la-getinfo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='getinfo.c' object='libcurlu_la-getinfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-getinfo.lo `test -f 'getinfo.c' || echo '$(srcdir)/'`getinfo.c + +libcurlu_la-transfer.lo: transfer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-transfer.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-transfer.Tpo -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-transfer.Tpo $(DEPDIR)/libcurlu_la-transfer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='transfer.c' object='libcurlu_la-transfer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c + +libcurlu_la-strcase.lo: strcase.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-strcase.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-strcase.Tpo -c -o libcurlu_la-strcase.lo `test -f 'strcase.c' || echo '$(srcdir)/'`strcase.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-strcase.Tpo $(DEPDIR)/libcurlu_la-strcase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strcase.c' object='libcurlu_la-strcase.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strcase.lo `test -f 'strcase.c' || echo '$(srcdir)/'`strcase.c + +libcurlu_la-easy.lo: easy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-easy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-easy.Tpo -c -o libcurlu_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-easy.Tpo $(DEPDIR)/libcurlu_la-easy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='easy.c' object='libcurlu_la-easy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-easy.lo `test -f 'easy.c' || echo '$(srcdir)/'`easy.c + +libcurlu_la-security.lo: security.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-security.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-security.Tpo -c -o libcurlu_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-security.Tpo $(DEPDIR)/libcurlu_la-security.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='security.c' object='libcurlu_la-security.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c + +libcurlu_la-curl_fnmatch.lo: curl_fnmatch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_fnmatch.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_fnmatch.Tpo -c -o libcurlu_la-curl_fnmatch.lo `test -f 'curl_fnmatch.c' || echo '$(srcdir)/'`curl_fnmatch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_fnmatch.Tpo $(DEPDIR)/libcurlu_la-curl_fnmatch.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_fnmatch.c' object='libcurlu_la-curl_fnmatch.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_fnmatch.lo `test -f 'curl_fnmatch.c' || echo '$(srcdir)/'`curl_fnmatch.c + +libcurlu_la-fileinfo.lo: fileinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-fileinfo.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-fileinfo.Tpo -c -o libcurlu_la-fileinfo.lo `test -f 'fileinfo.c' || echo '$(srcdir)/'`fileinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-fileinfo.Tpo $(DEPDIR)/libcurlu_la-fileinfo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fileinfo.c' object='libcurlu_la-fileinfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-fileinfo.lo `test -f 'fileinfo.c' || echo '$(srcdir)/'`fileinfo.c + +libcurlu_la-ftplistparser.lo: ftplistparser.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ftplistparser.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ftplistparser.Tpo -c -o libcurlu_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ftplistparser.Tpo $(DEPDIR)/libcurlu_la-ftplistparser.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ftplistparser.c' object='libcurlu_la-ftplistparser.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ftplistparser.lo `test -f 'ftplistparser.c' || echo '$(srcdir)/'`ftplistparser.c + +libcurlu_la-wildcard.lo: wildcard.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-wildcard.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-wildcard.Tpo -c -o libcurlu_la-wildcard.lo `test -f 'wildcard.c' || echo '$(srcdir)/'`wildcard.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-wildcard.Tpo $(DEPDIR)/libcurlu_la-wildcard.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wildcard.c' object='libcurlu_la-wildcard.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-wildcard.lo `test -f 'wildcard.c' || echo '$(srcdir)/'`wildcard.c + +libcurlu_la-krb5.lo: krb5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-krb5.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-krb5.Tpo -c -o libcurlu_la-krb5.lo `test -f 'krb5.c' || echo '$(srcdir)/'`krb5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-krb5.Tpo $(DEPDIR)/libcurlu_la-krb5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='krb5.c' object='libcurlu_la-krb5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-krb5.lo `test -f 'krb5.c' || echo '$(srcdir)/'`krb5.c + +libcurlu_la-memdebug.lo: memdebug.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-memdebug.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-memdebug.Tpo -c -o libcurlu_la-memdebug.lo `test -f 'memdebug.c' || echo '$(srcdir)/'`memdebug.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-memdebug.Tpo $(DEPDIR)/libcurlu_la-memdebug.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='memdebug.c' object='libcurlu_la-memdebug.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-memdebug.lo `test -f 'memdebug.c' || echo '$(srcdir)/'`memdebug.c + +libcurlu_la-http_chunks.lo: http_chunks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_chunks.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_chunks.Tpo -c -o libcurlu_la-http_chunks.lo `test -f 'http_chunks.c' || echo '$(srcdir)/'`http_chunks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_chunks.Tpo $(DEPDIR)/libcurlu_la-http_chunks.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_chunks.c' object='libcurlu_la-http_chunks.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_chunks.lo `test -f 'http_chunks.c' || echo '$(srcdir)/'`http_chunks.c + +libcurlu_la-strtok.lo: strtok.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-strtok.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-strtok.Tpo -c -o libcurlu_la-strtok.lo `test -f 'strtok.c' || echo '$(srcdir)/'`strtok.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-strtok.Tpo $(DEPDIR)/libcurlu_la-strtok.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strtok.c' object='libcurlu_la-strtok.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strtok.lo `test -f 'strtok.c' || echo '$(srcdir)/'`strtok.c + +libcurlu_la-connect.lo: connect.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-connect.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-connect.Tpo -c -o libcurlu_la-connect.lo `test -f 'connect.c' || echo '$(srcdir)/'`connect.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-connect.Tpo $(DEPDIR)/libcurlu_la-connect.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='connect.c' object='libcurlu_la-connect.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-connect.lo `test -f 'connect.c' || echo '$(srcdir)/'`connect.c + +libcurlu_la-llist.lo: llist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-llist.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-llist.Tpo -c -o libcurlu_la-llist.lo `test -f 'llist.c' || echo '$(srcdir)/'`llist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-llist.Tpo $(DEPDIR)/libcurlu_la-llist.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='llist.c' object='libcurlu_la-llist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-llist.lo `test -f 'llist.c' || echo '$(srcdir)/'`llist.c + +libcurlu_la-hash.lo: hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hash.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hash.Tpo -c -o libcurlu_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hash.Tpo $(DEPDIR)/libcurlu_la-hash.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hash.c' object='libcurlu_la-hash.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c + +libcurlu_la-multi.lo: multi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-multi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-multi.Tpo -c -o libcurlu_la-multi.lo `test -f 'multi.c' || echo '$(srcdir)/'`multi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-multi.Tpo $(DEPDIR)/libcurlu_la-multi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='multi.c' object='libcurlu_la-multi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-multi.lo `test -f 'multi.c' || echo '$(srcdir)/'`multi.c + +libcurlu_la-content_encoding.lo: content_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-content_encoding.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-content_encoding.Tpo -c -o libcurlu_la-content_encoding.lo `test -f 'content_encoding.c' || echo '$(srcdir)/'`content_encoding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-content_encoding.Tpo $(DEPDIR)/libcurlu_la-content_encoding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='content_encoding.c' object='libcurlu_la-content_encoding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-content_encoding.lo `test -f 'content_encoding.c' || echo '$(srcdir)/'`content_encoding.c + +libcurlu_la-share.lo: share.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-share.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-share.Tpo -c -o libcurlu_la-share.lo `test -f 'share.c' || echo '$(srcdir)/'`share.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-share.Tpo $(DEPDIR)/libcurlu_la-share.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='share.c' object='libcurlu_la-share.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-share.lo `test -f 'share.c' || echo '$(srcdir)/'`share.c + +libcurlu_la-http_digest.lo: http_digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_digest.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_digest.Tpo -c -o libcurlu_la-http_digest.lo `test -f 'http_digest.c' || echo '$(srcdir)/'`http_digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_digest.Tpo $(DEPDIR)/libcurlu_la-http_digest.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_digest.c' object='libcurlu_la-http_digest.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_digest.lo `test -f 'http_digest.c' || echo '$(srcdir)/'`http_digest.c + +libcurlu_la-md4.lo: md4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-md4.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-md4.Tpo -c -o libcurlu_la-md4.lo `test -f 'md4.c' || echo '$(srcdir)/'`md4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-md4.Tpo $(DEPDIR)/libcurlu_la-md4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md4.c' object='libcurlu_la-md4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-md4.lo `test -f 'md4.c' || echo '$(srcdir)/'`md4.c + +libcurlu_la-md5.lo: md5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-md5.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-md5.Tpo -c -o libcurlu_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-md5.Tpo $(DEPDIR)/libcurlu_la-md5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md5.c' object='libcurlu_la-md5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c + +libcurlu_la-http_negotiate.lo: http_negotiate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_negotiate.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_negotiate.Tpo -c -o libcurlu_la-http_negotiate.lo `test -f 'http_negotiate.c' || echo '$(srcdir)/'`http_negotiate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_negotiate.Tpo $(DEPDIR)/libcurlu_la-http_negotiate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_negotiate.c' object='libcurlu_la-http_negotiate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_negotiate.lo `test -f 'http_negotiate.c' || echo '$(srcdir)/'`http_negotiate.c + +libcurlu_la-inet_pton.lo: inet_pton.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-inet_pton.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-inet_pton.Tpo -c -o libcurlu_la-inet_pton.lo `test -f 'inet_pton.c' || echo '$(srcdir)/'`inet_pton.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-inet_pton.Tpo $(DEPDIR)/libcurlu_la-inet_pton.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inet_pton.c' object='libcurlu_la-inet_pton.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-inet_pton.lo `test -f 'inet_pton.c' || echo '$(srcdir)/'`inet_pton.c + +libcurlu_la-strtoofft.lo: strtoofft.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-strtoofft.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-strtoofft.Tpo -c -o libcurlu_la-strtoofft.lo `test -f 'strtoofft.c' || echo '$(srcdir)/'`strtoofft.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-strtoofft.Tpo $(DEPDIR)/libcurlu_la-strtoofft.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strtoofft.c' object='libcurlu_la-strtoofft.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strtoofft.lo `test -f 'strtoofft.c' || echo '$(srcdir)/'`strtoofft.c + +libcurlu_la-strerror.lo: strerror.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-strerror.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-strerror.Tpo -c -o libcurlu_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-strerror.Tpo $(DEPDIR)/libcurlu_la-strerror.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strerror.c' object='libcurlu_la-strerror.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c + +libcurlu_la-amigaos.lo: amigaos.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-amigaos.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-amigaos.Tpo -c -o libcurlu_la-amigaos.lo `test -f 'amigaos.c' || echo '$(srcdir)/'`amigaos.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-amigaos.Tpo $(DEPDIR)/libcurlu_la-amigaos.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='amigaos.c' object='libcurlu_la-amigaos.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-amigaos.lo `test -f 'amigaos.c' || echo '$(srcdir)/'`amigaos.c + +libcurlu_la-hostasyn.lo: hostasyn.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostasyn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostasyn.Tpo -c -o libcurlu_la-hostasyn.lo `test -f 'hostasyn.c' || echo '$(srcdir)/'`hostasyn.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostasyn.Tpo $(DEPDIR)/libcurlu_la-hostasyn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostasyn.c' object='libcurlu_la-hostasyn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostasyn.lo `test -f 'hostasyn.c' || echo '$(srcdir)/'`hostasyn.c + +libcurlu_la-hostip4.lo: hostip4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostip4.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostip4.Tpo -c -o libcurlu_la-hostip4.lo `test -f 'hostip4.c' || echo '$(srcdir)/'`hostip4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostip4.Tpo $(DEPDIR)/libcurlu_la-hostip4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostip4.c' object='libcurlu_la-hostip4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostip4.lo `test -f 'hostip4.c' || echo '$(srcdir)/'`hostip4.c + +libcurlu_la-hostip6.lo: hostip6.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostip6.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostip6.Tpo -c -o libcurlu_la-hostip6.lo `test -f 'hostip6.c' || echo '$(srcdir)/'`hostip6.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostip6.Tpo $(DEPDIR)/libcurlu_la-hostip6.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostip6.c' object='libcurlu_la-hostip6.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostip6.lo `test -f 'hostip6.c' || echo '$(srcdir)/'`hostip6.c + +libcurlu_la-hostsyn.lo: hostsyn.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostsyn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostsyn.Tpo -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostsyn.Tpo $(DEPDIR)/libcurlu_la-hostsyn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostsyn.c' object='libcurlu_la-hostsyn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c + +libcurlu_la-inet_ntop.lo: inet_ntop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-inet_ntop.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-inet_ntop.Tpo -c -o libcurlu_la-inet_ntop.lo `test -f 'inet_ntop.c' || echo '$(srcdir)/'`inet_ntop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-inet_ntop.Tpo $(DEPDIR)/libcurlu_la-inet_ntop.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inet_ntop.c' object='libcurlu_la-inet_ntop.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-inet_ntop.lo `test -f 'inet_ntop.c' || echo '$(srcdir)/'`inet_ntop.c + +libcurlu_la-parsedate.lo: parsedate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-parsedate.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-parsedate.Tpo -c -o libcurlu_la-parsedate.lo `test -f 'parsedate.c' || echo '$(srcdir)/'`parsedate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-parsedate.Tpo $(DEPDIR)/libcurlu_la-parsedate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parsedate.c' object='libcurlu_la-parsedate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-parsedate.lo `test -f 'parsedate.c' || echo '$(srcdir)/'`parsedate.c + +libcurlu_la-select.lo: select.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-select.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-select.Tpo -c -o libcurlu_la-select.lo `test -f 'select.c' || echo '$(srcdir)/'`select.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-select.Tpo $(DEPDIR)/libcurlu_la-select.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='select.c' object='libcurlu_la-select.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-select.lo `test -f 'select.c' || echo '$(srcdir)/'`select.c + +libcurlu_la-tftp.lo: tftp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-tftp.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-tftp.Tpo -c -o libcurlu_la-tftp.lo `test -f 'tftp.c' || echo '$(srcdir)/'`tftp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-tftp.Tpo $(DEPDIR)/libcurlu_la-tftp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tftp.c' object='libcurlu_la-tftp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-tftp.lo `test -f 'tftp.c' || echo '$(srcdir)/'`tftp.c + +libcurlu_la-splay.lo: splay.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-splay.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-splay.Tpo -c -o libcurlu_la-splay.lo `test -f 'splay.c' || echo '$(srcdir)/'`splay.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-splay.Tpo $(DEPDIR)/libcurlu_la-splay.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='splay.c' object='libcurlu_la-splay.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-splay.lo `test -f 'splay.c' || echo '$(srcdir)/'`splay.c + +libcurlu_la-strdup.lo: strdup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-strdup.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-strdup.Tpo -c -o libcurlu_la-strdup.lo `test -f 'strdup.c' || echo '$(srcdir)/'`strdup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-strdup.Tpo $(DEPDIR)/libcurlu_la-strdup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strdup.c' object='libcurlu_la-strdup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strdup.lo `test -f 'strdup.c' || echo '$(srcdir)/'`strdup.c + +libcurlu_la-socks.lo: socks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-socks.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-socks.Tpo -c -o libcurlu_la-socks.lo `test -f 'socks.c' || echo '$(srcdir)/'`socks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-socks.Tpo $(DEPDIR)/libcurlu_la-socks.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socks.c' object='libcurlu_la-socks.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-socks.lo `test -f 'socks.c' || echo '$(srcdir)/'`socks.c + +libcurlu_la-ssh.lo: ssh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ssh.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ssh.Tpo -c -o libcurlu_la-ssh.lo `test -f 'ssh.c' || echo '$(srcdir)/'`ssh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ssh.Tpo $(DEPDIR)/libcurlu_la-ssh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ssh.c' object='libcurlu_la-ssh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ssh.lo `test -f 'ssh.c' || echo '$(srcdir)/'`ssh.c + +libcurlu_la-ssh-libssh.lo: ssh-libssh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ssh-libssh.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ssh-libssh.Tpo -c -o libcurlu_la-ssh-libssh.lo `test -f 'ssh-libssh.c' || echo '$(srcdir)/'`ssh-libssh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ssh-libssh.Tpo $(DEPDIR)/libcurlu_la-ssh-libssh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ssh-libssh.c' object='libcurlu_la-ssh-libssh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-ssh-libssh.lo `test -f 'ssh-libssh.c' || echo '$(srcdir)/'`ssh-libssh.c + +libcurlu_la-curl_addrinfo.lo: curl_addrinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_addrinfo.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_addrinfo.Tpo -c -o libcurlu_la-curl_addrinfo.lo `test -f 'curl_addrinfo.c' || echo '$(srcdir)/'`curl_addrinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_addrinfo.Tpo $(DEPDIR)/libcurlu_la-curl_addrinfo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_addrinfo.c' object='libcurlu_la-curl_addrinfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_addrinfo.lo `test -f 'curl_addrinfo.c' || echo '$(srcdir)/'`curl_addrinfo.c + +libcurlu_la-socks_gssapi.lo: socks_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-socks_gssapi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-socks_gssapi.Tpo -c -o libcurlu_la-socks_gssapi.lo `test -f 'socks_gssapi.c' || echo '$(srcdir)/'`socks_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-socks_gssapi.Tpo $(DEPDIR)/libcurlu_la-socks_gssapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socks_gssapi.c' object='libcurlu_la-socks_gssapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-socks_gssapi.lo `test -f 'socks_gssapi.c' || echo '$(srcdir)/'`socks_gssapi.c + +libcurlu_la-socks_sspi.lo: socks_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-socks_sspi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-socks_sspi.Tpo -c -o libcurlu_la-socks_sspi.lo `test -f 'socks_sspi.c' || echo '$(srcdir)/'`socks_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-socks_sspi.Tpo $(DEPDIR)/libcurlu_la-socks_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socks_sspi.c' object='libcurlu_la-socks_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-socks_sspi.lo `test -f 'socks_sspi.c' || echo '$(srcdir)/'`socks_sspi.c + +libcurlu_la-curl_sspi.lo: curl_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_sspi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_sspi.Tpo -c -o libcurlu_la-curl_sspi.lo `test -f 'curl_sspi.c' || echo '$(srcdir)/'`curl_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_sspi.Tpo $(DEPDIR)/libcurlu_la-curl_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_sspi.c' object='libcurlu_la-curl_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_sspi.lo `test -f 'curl_sspi.c' || echo '$(srcdir)/'`curl_sspi.c + +libcurlu_la-slist.lo: slist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-slist.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-slist.Tpo -c -o libcurlu_la-slist.lo `test -f 'slist.c' || echo '$(srcdir)/'`slist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-slist.Tpo $(DEPDIR)/libcurlu_la-slist.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slist.c' object='libcurlu_la-slist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-slist.lo `test -f 'slist.c' || echo '$(srcdir)/'`slist.c + +libcurlu_la-nonblock.lo: nonblock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-nonblock.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-nonblock.Tpo -c -o libcurlu_la-nonblock.lo `test -f 'nonblock.c' || echo '$(srcdir)/'`nonblock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-nonblock.Tpo $(DEPDIR)/libcurlu_la-nonblock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nonblock.c' object='libcurlu_la-nonblock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-nonblock.lo `test -f 'nonblock.c' || echo '$(srcdir)/'`nonblock.c + +libcurlu_la-curl_memrchr.lo: curl_memrchr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_memrchr.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_memrchr.Tpo -c -o libcurlu_la-curl_memrchr.lo `test -f 'curl_memrchr.c' || echo '$(srcdir)/'`curl_memrchr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_memrchr.Tpo $(DEPDIR)/libcurlu_la-curl_memrchr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_memrchr.c' object='libcurlu_la-curl_memrchr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_memrchr.lo `test -f 'curl_memrchr.c' || echo '$(srcdir)/'`curl_memrchr.c + +libcurlu_la-imap.lo: imap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-imap.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-imap.Tpo -c -o libcurlu_la-imap.lo `test -f 'imap.c' || echo '$(srcdir)/'`imap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-imap.Tpo $(DEPDIR)/libcurlu_la-imap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imap.c' object='libcurlu_la-imap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-imap.lo `test -f 'imap.c' || echo '$(srcdir)/'`imap.c + +libcurlu_la-pop3.lo: pop3.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-pop3.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-pop3.Tpo -c -o libcurlu_la-pop3.lo `test -f 'pop3.c' || echo '$(srcdir)/'`pop3.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-pop3.Tpo $(DEPDIR)/libcurlu_la-pop3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pop3.c' object='libcurlu_la-pop3.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-pop3.lo `test -f 'pop3.c' || echo '$(srcdir)/'`pop3.c + +libcurlu_la-smtp.lo: smtp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-smtp.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-smtp.Tpo -c -o libcurlu_la-smtp.lo `test -f 'smtp.c' || echo '$(srcdir)/'`smtp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-smtp.Tpo $(DEPDIR)/libcurlu_la-smtp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtp.c' object='libcurlu_la-smtp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-smtp.lo `test -f 'smtp.c' || echo '$(srcdir)/'`smtp.c + +libcurlu_la-pingpong.lo: pingpong.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-pingpong.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-pingpong.Tpo -c -o libcurlu_la-pingpong.lo `test -f 'pingpong.c' || echo '$(srcdir)/'`pingpong.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-pingpong.Tpo $(DEPDIR)/libcurlu_la-pingpong.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pingpong.c' object='libcurlu_la-pingpong.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-pingpong.lo `test -f 'pingpong.c' || echo '$(srcdir)/'`pingpong.c + +libcurlu_la-rtsp.lo: rtsp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-rtsp.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-rtsp.Tpo -c -o libcurlu_la-rtsp.lo `test -f 'rtsp.c' || echo '$(srcdir)/'`rtsp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-rtsp.Tpo $(DEPDIR)/libcurlu_la-rtsp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtsp.c' object='libcurlu_la-rtsp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-rtsp.lo `test -f 'rtsp.c' || echo '$(srcdir)/'`rtsp.c + +libcurlu_la-curl_threads.lo: curl_threads.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_threads.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_threads.Tpo -c -o libcurlu_la-curl_threads.lo `test -f 'curl_threads.c' || echo '$(srcdir)/'`curl_threads.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_threads.Tpo $(DEPDIR)/libcurlu_la-curl_threads.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_threads.c' object='libcurlu_la-curl_threads.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_threads.lo `test -f 'curl_threads.c' || echo '$(srcdir)/'`curl_threads.c + +libcurlu_la-warnless.lo: warnless.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-warnless.Tpo -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-warnless.Tpo $(DEPDIR)/libcurlu_la-warnless.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='warnless.c' object='libcurlu_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c + +libcurlu_la-hmac.lo: hmac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hmac.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hmac.Tpo -c -o libcurlu_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hmac.Tpo $(DEPDIR)/libcurlu_la-hmac.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hmac.c' object='libcurlu_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c + +libcurlu_la-curl_rtmp.lo: curl_rtmp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_rtmp.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_rtmp.Tpo -c -o libcurlu_la-curl_rtmp.lo `test -f 'curl_rtmp.c' || echo '$(srcdir)/'`curl_rtmp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_rtmp.Tpo $(DEPDIR)/libcurlu_la-curl_rtmp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_rtmp.c' object='libcurlu_la-curl_rtmp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_rtmp.lo `test -f 'curl_rtmp.c' || echo '$(srcdir)/'`curl_rtmp.c + +libcurlu_la-openldap.lo: openldap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-openldap.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-openldap.Tpo -c -o libcurlu_la-openldap.lo `test -f 'openldap.c' || echo '$(srcdir)/'`openldap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-openldap.Tpo $(DEPDIR)/libcurlu_la-openldap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='openldap.c' object='libcurlu_la-openldap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-openldap.lo `test -f 'openldap.c' || echo '$(srcdir)/'`openldap.c + +libcurlu_la-curl_gethostname.lo: curl_gethostname.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_gethostname.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_gethostname.Tpo -c -o libcurlu_la-curl_gethostname.lo `test -f 'curl_gethostname.c' || echo '$(srcdir)/'`curl_gethostname.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_gethostname.Tpo $(DEPDIR)/libcurlu_la-curl_gethostname.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_gethostname.c' object='libcurlu_la-curl_gethostname.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_gethostname.lo `test -f 'curl_gethostname.c' || echo '$(srcdir)/'`curl_gethostname.c + +libcurlu_la-gopher.lo: gopher.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-gopher.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-gopher.Tpo -c -o libcurlu_la-gopher.lo `test -f 'gopher.c' || echo '$(srcdir)/'`gopher.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-gopher.Tpo $(DEPDIR)/libcurlu_la-gopher.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gopher.c' object='libcurlu_la-gopher.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-gopher.lo `test -f 'gopher.c' || echo '$(srcdir)/'`gopher.c + +libcurlu_la-idn_win32.lo: idn_win32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-idn_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-idn_win32.Tpo -c -o libcurlu_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-idn_win32.Tpo $(DEPDIR)/libcurlu_la-idn_win32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='idn_win32.c' object='libcurlu_la-idn_win32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-idn_win32.lo `test -f 'idn_win32.c' || echo '$(srcdir)/'`idn_win32.c + +libcurlu_la-http_proxy.lo: http_proxy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_proxy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_proxy.Tpo -c -o libcurlu_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_proxy.Tpo $(DEPDIR)/libcurlu_la-http_proxy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_proxy.c' object='libcurlu_la-http_proxy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_proxy.lo `test -f 'http_proxy.c' || echo '$(srcdir)/'`http_proxy.c + +libcurlu_la-non-ascii.lo: non-ascii.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-non-ascii.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-non-ascii.Tpo -c -o libcurlu_la-non-ascii.lo `test -f 'non-ascii.c' || echo '$(srcdir)/'`non-ascii.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-non-ascii.Tpo $(DEPDIR)/libcurlu_la-non-ascii.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='non-ascii.c' object='libcurlu_la-non-ascii.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-non-ascii.lo `test -f 'non-ascii.c' || echo '$(srcdir)/'`non-ascii.c + +libcurlu_la-asyn-ares.lo: asyn-ares.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-asyn-ares.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-asyn-ares.Tpo -c -o libcurlu_la-asyn-ares.lo `test -f 'asyn-ares.c' || echo '$(srcdir)/'`asyn-ares.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-asyn-ares.Tpo $(DEPDIR)/libcurlu_la-asyn-ares.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-ares.c' object='libcurlu_la-asyn-ares.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-asyn-ares.lo `test -f 'asyn-ares.c' || echo '$(srcdir)/'`asyn-ares.c + +libcurlu_la-asyn-thread.lo: asyn-thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-asyn-thread.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-asyn-thread.Tpo -c -o libcurlu_la-asyn-thread.lo `test -f 'asyn-thread.c' || echo '$(srcdir)/'`asyn-thread.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-asyn-thread.Tpo $(DEPDIR)/libcurlu_la-asyn-thread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-thread.c' object='libcurlu_la-asyn-thread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-asyn-thread.lo `test -f 'asyn-thread.c' || echo '$(srcdir)/'`asyn-thread.c + +libcurlu_la-curl_gssapi.lo: curl_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_gssapi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_gssapi.Tpo -c -o libcurlu_la-curl_gssapi.lo `test -f 'curl_gssapi.c' || echo '$(srcdir)/'`curl_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_gssapi.Tpo $(DEPDIR)/libcurlu_la-curl_gssapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_gssapi.c' object='libcurlu_la-curl_gssapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_gssapi.lo `test -f 'curl_gssapi.c' || echo '$(srcdir)/'`curl_gssapi.c + +libcurlu_la-http_ntlm.lo: http_ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http_ntlm.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http_ntlm.Tpo -c -o libcurlu_la-http_ntlm.lo `test -f 'http_ntlm.c' || echo '$(srcdir)/'`http_ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http_ntlm.Tpo $(DEPDIR)/libcurlu_la-http_ntlm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_ntlm.c' object='libcurlu_la-http_ntlm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http_ntlm.lo `test -f 'http_ntlm.c' || echo '$(srcdir)/'`http_ntlm.c + +libcurlu_la-curl_ntlm_wb.lo: curl_ntlm_wb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_ntlm_wb.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_ntlm_wb.Tpo -c -o libcurlu_la-curl_ntlm_wb.lo `test -f 'curl_ntlm_wb.c' || echo '$(srcdir)/'`curl_ntlm_wb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_ntlm_wb.Tpo $(DEPDIR)/libcurlu_la-curl_ntlm_wb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_ntlm_wb.c' object='libcurlu_la-curl_ntlm_wb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_ntlm_wb.lo `test -f 'curl_ntlm_wb.c' || echo '$(srcdir)/'`curl_ntlm_wb.c + +libcurlu_la-curl_ntlm_core.lo: curl_ntlm_core.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_ntlm_core.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_ntlm_core.Tpo -c -o libcurlu_la-curl_ntlm_core.lo `test -f 'curl_ntlm_core.c' || echo '$(srcdir)/'`curl_ntlm_core.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_ntlm_core.Tpo $(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_ntlm_core.c' object='libcurlu_la-curl_ntlm_core.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_ntlm_core.lo `test -f 'curl_ntlm_core.c' || echo '$(srcdir)/'`curl_ntlm_core.c + +libcurlu_la-curl_sasl.lo: curl_sasl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_sasl.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_sasl.Tpo -c -o libcurlu_la-curl_sasl.lo `test -f 'curl_sasl.c' || echo '$(srcdir)/'`curl_sasl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_sasl.Tpo $(DEPDIR)/libcurlu_la-curl_sasl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_sasl.c' object='libcurlu_la-curl_sasl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_sasl.lo `test -f 'curl_sasl.c' || echo '$(srcdir)/'`curl_sasl.c + +libcurlu_la-rand.lo: rand.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-rand.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-rand.Tpo -c -o libcurlu_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-rand.Tpo $(DEPDIR)/libcurlu_la-rand.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rand.c' object='libcurlu_la-rand.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-rand.lo `test -f 'rand.c' || echo '$(srcdir)/'`rand.c + +libcurlu_la-curl_multibyte.lo: curl_multibyte.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_multibyte.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_multibyte.Tpo -c -o libcurlu_la-curl_multibyte.lo `test -f 'curl_multibyte.c' || echo '$(srcdir)/'`curl_multibyte.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_multibyte.Tpo $(DEPDIR)/libcurlu_la-curl_multibyte.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_multibyte.c' object='libcurlu_la-curl_multibyte.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_multibyte.lo `test -f 'curl_multibyte.c' || echo '$(srcdir)/'`curl_multibyte.c + +libcurlu_la-hostcheck.lo: hostcheck.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostcheck.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostcheck.Tpo -c -o libcurlu_la-hostcheck.lo `test -f 'hostcheck.c' || echo '$(srcdir)/'`hostcheck.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostcheck.Tpo $(DEPDIR)/libcurlu_la-hostcheck.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostcheck.c' object='libcurlu_la-hostcheck.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostcheck.lo `test -f 'hostcheck.c' || echo '$(srcdir)/'`hostcheck.c + +libcurlu_la-conncache.lo: conncache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-conncache.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-conncache.Tpo -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-conncache.Tpo $(DEPDIR)/libcurlu_la-conncache.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conncache.c' object='libcurlu_la-conncache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c + +libcurlu_la-dotdot.lo: dotdot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dotdot.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dotdot.Tpo -c -o libcurlu_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dotdot.Tpo $(DEPDIR)/libcurlu_la-dotdot.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dotdot.c' object='libcurlu_la-dotdot.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dotdot.lo `test -f 'dotdot.c' || echo '$(srcdir)/'`dotdot.c + +libcurlu_la-x509asn1.lo: x509asn1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-x509asn1.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-x509asn1.Tpo -c -o libcurlu_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-x509asn1.Tpo $(DEPDIR)/libcurlu_la-x509asn1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='x509asn1.c' object='libcurlu_la-x509asn1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-x509asn1.lo `test -f 'x509asn1.c' || echo '$(srcdir)/'`x509asn1.c + +libcurlu_la-http2.lo: http2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-http2.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-http2.Tpo -c -o libcurlu_la-http2.lo `test -f 'http2.c' || echo '$(srcdir)/'`http2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-http2.Tpo $(DEPDIR)/libcurlu_la-http2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http2.c' object='libcurlu_la-http2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-http2.lo `test -f 'http2.c' || echo '$(srcdir)/'`http2.c + +libcurlu_la-smb.lo: smb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-smb.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-smb.Tpo -c -o libcurlu_la-smb.lo `test -f 'smb.c' || echo '$(srcdir)/'`smb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-smb.Tpo $(DEPDIR)/libcurlu_la-smb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smb.c' object='libcurlu_la-smb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-smb.lo `test -f 'smb.c' || echo '$(srcdir)/'`smb.c + +libcurlu_la-curl_endian.lo: curl_endian.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_endian.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_endian.Tpo -c -o libcurlu_la-curl_endian.lo `test -f 'curl_endian.c' || echo '$(srcdir)/'`curl_endian.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_endian.Tpo $(DEPDIR)/libcurlu_la-curl_endian.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_endian.c' object='libcurlu_la-curl_endian.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_endian.lo `test -f 'curl_endian.c' || echo '$(srcdir)/'`curl_endian.c + +libcurlu_la-curl_des.lo: curl_des.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_des.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_des.Tpo -c -o libcurlu_la-curl_des.lo `test -f 'curl_des.c' || echo '$(srcdir)/'`curl_des.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_des.Tpo $(DEPDIR)/libcurlu_la-curl_des.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_des.c' object='libcurlu_la-curl_des.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_des.lo `test -f 'curl_des.c' || echo '$(srcdir)/'`curl_des.c + +libcurlu_la-system_win32.lo: system_win32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-system_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-system_win32.Tpo -c -o libcurlu_la-system_win32.lo `test -f 'system_win32.c' || echo '$(srcdir)/'`system_win32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-system_win32.Tpo $(DEPDIR)/libcurlu_la-system_win32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='system_win32.c' object='libcurlu_la-system_win32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-system_win32.lo `test -f 'system_win32.c' || echo '$(srcdir)/'`system_win32.c + +libcurlu_la-mime.lo: mime.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-mime.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-mime.Tpo -c -o libcurlu_la-mime.lo `test -f 'mime.c' || echo '$(srcdir)/'`mime.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-mime.Tpo $(DEPDIR)/libcurlu_la-mime.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mime.c' object='libcurlu_la-mime.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-mime.lo `test -f 'mime.c' || echo '$(srcdir)/'`mime.c + +libcurlu_la-sha256.lo: sha256.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-sha256.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-sha256.Tpo -c -o libcurlu_la-sha256.lo `test -f 'sha256.c' || echo '$(srcdir)/'`sha256.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-sha256.Tpo $(DEPDIR)/libcurlu_la-sha256.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sha256.c' object='libcurlu_la-sha256.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-sha256.lo `test -f 'sha256.c' || echo '$(srcdir)/'`sha256.c + +libcurlu_la-setopt.lo: setopt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-setopt.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-setopt.Tpo -c -o libcurlu_la-setopt.lo `test -f 'setopt.c' || echo '$(srcdir)/'`setopt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-setopt.Tpo $(DEPDIR)/libcurlu_la-setopt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='setopt.c' object='libcurlu_la-setopt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-setopt.lo `test -f 'setopt.c' || echo '$(srcdir)/'`setopt.c + +libcurlu_la-curl_path.lo: curl_path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_path.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_path.Tpo -c -o libcurlu_la-curl_path.lo `test -f 'curl_path.c' || echo '$(srcdir)/'`curl_path.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_path.Tpo $(DEPDIR)/libcurlu_la-curl_path.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_path.c' object='libcurlu_la-curl_path.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_path.lo `test -f 'curl_path.c' || echo '$(srcdir)/'`curl_path.c + +libcurlu_la-curl_ctype.lo: curl_ctype.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_ctype.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_ctype.Tpo -c -o libcurlu_la-curl_ctype.lo `test -f 'curl_ctype.c' || echo '$(srcdir)/'`curl_ctype.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_ctype.Tpo $(DEPDIR)/libcurlu_la-curl_ctype.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_ctype.c' object='libcurlu_la-curl_ctype.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_ctype.lo `test -f 'curl_ctype.c' || echo '$(srcdir)/'`curl_ctype.c + +libcurlu_la-curl_range.lo: curl_range.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_range.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_range.Tpo -c -o libcurlu_la-curl_range.lo `test -f 'curl_range.c' || echo '$(srcdir)/'`curl_range.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_range.Tpo $(DEPDIR)/libcurlu_la-curl_range.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_range.c' object='libcurlu_la-curl_range.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_range.lo `test -f 'curl_range.c' || echo '$(srcdir)/'`curl_range.c + +libcurlu_la-psl.lo: psl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-psl.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-psl.Tpo -c -o libcurlu_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-psl.Tpo $(DEPDIR)/libcurlu_la-psl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='psl.c' object='libcurlu_la-psl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-psl.lo `test -f 'psl.c' || echo '$(srcdir)/'`psl.c + +libcurlu_la-doh.lo: doh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-doh.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-doh.Tpo -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-doh.Tpo $(DEPDIR)/libcurlu_la-doh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh.c' object='libcurlu_la-doh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c + +libcurlu_la-urlapi.lo: urlapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-urlapi.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-urlapi.Tpo -c -o libcurlu_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-urlapi.Tpo $(DEPDIR)/libcurlu_la-urlapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='urlapi.c' object='libcurlu_la-urlapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-urlapi.lo `test -f 'urlapi.c' || echo '$(srcdir)/'`urlapi.c + +libcurlu_la-curl_get_line.lo: curl_get_line.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_get_line.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_get_line.Tpo -c -o libcurlu_la-curl_get_line.lo `test -f 'curl_get_line.c' || echo '$(srcdir)/'`curl_get_line.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_get_line.Tpo $(DEPDIR)/libcurlu_la-curl_get_line.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_get_line.c' object='libcurlu_la-curl_get_line.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_get_line.lo `test -f 'curl_get_line.c' || echo '$(srcdir)/'`curl_get_line.c + +libcurlu_la-altsvc.lo: altsvc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-altsvc.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-altsvc.Tpo -c -o libcurlu_la-altsvc.lo `test -f 'altsvc.c' || echo '$(srcdir)/'`altsvc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-altsvc.Tpo $(DEPDIR)/libcurlu_la-altsvc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='altsvc.c' object='libcurlu_la-altsvc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-altsvc.lo `test -f 'altsvc.c' || echo '$(srcdir)/'`altsvc.c + +vauth/libcurlu_la-vauth.lo: vauth/vauth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-vauth.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-vauth.Tpo -c -o vauth/libcurlu_la-vauth.lo `test -f 'vauth/vauth.c' || echo '$(srcdir)/'`vauth/vauth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-vauth.Tpo vauth/$(DEPDIR)/libcurlu_la-vauth.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/vauth.c' object='vauth/libcurlu_la-vauth.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-vauth.lo `test -f 'vauth/vauth.c' || echo '$(srcdir)/'`vauth/vauth.c + +vauth/libcurlu_la-cleartext.lo: vauth/cleartext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-cleartext.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-cleartext.Tpo -c -o vauth/libcurlu_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-cleartext.Tpo vauth/$(DEPDIR)/libcurlu_la-cleartext.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/cleartext.c' object='vauth/libcurlu_la-cleartext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-cleartext.lo `test -f 'vauth/cleartext.c' || echo '$(srcdir)/'`vauth/cleartext.c + +vauth/libcurlu_la-cram.lo: vauth/cram.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-cram.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-cram.Tpo -c -o vauth/libcurlu_la-cram.lo `test -f 'vauth/cram.c' || echo '$(srcdir)/'`vauth/cram.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-cram.Tpo vauth/$(DEPDIR)/libcurlu_la-cram.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/cram.c' object='vauth/libcurlu_la-cram.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-cram.lo `test -f 'vauth/cram.c' || echo '$(srcdir)/'`vauth/cram.c + +vauth/libcurlu_la-digest.lo: vauth/digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-digest.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-digest.Tpo -c -o vauth/libcurlu_la-digest.lo `test -f 'vauth/digest.c' || echo '$(srcdir)/'`vauth/digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-digest.Tpo vauth/$(DEPDIR)/libcurlu_la-digest.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/digest.c' object='vauth/libcurlu_la-digest.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-digest.lo `test -f 'vauth/digest.c' || echo '$(srcdir)/'`vauth/digest.c + +vauth/libcurlu_la-digest_sspi.lo: vauth/digest_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-digest_sspi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-digest_sspi.Tpo -c -o vauth/libcurlu_la-digest_sspi.lo `test -f 'vauth/digest_sspi.c' || echo '$(srcdir)/'`vauth/digest_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-digest_sspi.Tpo vauth/$(DEPDIR)/libcurlu_la-digest_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/digest_sspi.c' object='vauth/libcurlu_la-digest_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-digest_sspi.lo `test -f 'vauth/digest_sspi.c' || echo '$(srcdir)/'`vauth/digest_sspi.c + +vauth/libcurlu_la-krb5_gssapi.lo: vauth/krb5_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-krb5_gssapi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-krb5_gssapi.Tpo -c -o vauth/libcurlu_la-krb5_gssapi.lo `test -f 'vauth/krb5_gssapi.c' || echo '$(srcdir)/'`vauth/krb5_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-krb5_gssapi.Tpo vauth/$(DEPDIR)/libcurlu_la-krb5_gssapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/krb5_gssapi.c' object='vauth/libcurlu_la-krb5_gssapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-krb5_gssapi.lo `test -f 'vauth/krb5_gssapi.c' || echo '$(srcdir)/'`vauth/krb5_gssapi.c + +vauth/libcurlu_la-krb5_sspi.lo: vauth/krb5_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-krb5_sspi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-krb5_sspi.Tpo -c -o vauth/libcurlu_la-krb5_sspi.lo `test -f 'vauth/krb5_sspi.c' || echo '$(srcdir)/'`vauth/krb5_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-krb5_sspi.Tpo vauth/$(DEPDIR)/libcurlu_la-krb5_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/krb5_sspi.c' object='vauth/libcurlu_la-krb5_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-krb5_sspi.lo `test -f 'vauth/krb5_sspi.c' || echo '$(srcdir)/'`vauth/krb5_sspi.c + +vauth/libcurlu_la-ntlm.lo: vauth/ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-ntlm.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-ntlm.Tpo -c -o vauth/libcurlu_la-ntlm.lo `test -f 'vauth/ntlm.c' || echo '$(srcdir)/'`vauth/ntlm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-ntlm.Tpo vauth/$(DEPDIR)/libcurlu_la-ntlm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/ntlm.c' object='vauth/libcurlu_la-ntlm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-ntlm.lo `test -f 'vauth/ntlm.c' || echo '$(srcdir)/'`vauth/ntlm.c + +vauth/libcurlu_la-ntlm_sspi.lo: vauth/ntlm_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-ntlm_sspi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-ntlm_sspi.Tpo -c -o vauth/libcurlu_la-ntlm_sspi.lo `test -f 'vauth/ntlm_sspi.c' || echo '$(srcdir)/'`vauth/ntlm_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-ntlm_sspi.Tpo vauth/$(DEPDIR)/libcurlu_la-ntlm_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/ntlm_sspi.c' object='vauth/libcurlu_la-ntlm_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-ntlm_sspi.lo `test -f 'vauth/ntlm_sspi.c' || echo '$(srcdir)/'`vauth/ntlm_sspi.c + +vauth/libcurlu_la-oauth2.lo: vauth/oauth2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-oauth2.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-oauth2.Tpo -c -o vauth/libcurlu_la-oauth2.lo `test -f 'vauth/oauth2.c' || echo '$(srcdir)/'`vauth/oauth2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-oauth2.Tpo vauth/$(DEPDIR)/libcurlu_la-oauth2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/oauth2.c' object='vauth/libcurlu_la-oauth2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-oauth2.lo `test -f 'vauth/oauth2.c' || echo '$(srcdir)/'`vauth/oauth2.c + +vauth/libcurlu_la-spnego_gssapi.lo: vauth/spnego_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-spnego_gssapi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Tpo -c -o vauth/libcurlu_la-spnego_gssapi.lo `test -f 'vauth/spnego_gssapi.c' || echo '$(srcdir)/'`vauth/spnego_gssapi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Tpo vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/spnego_gssapi.c' object='vauth/libcurlu_la-spnego_gssapi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-spnego_gssapi.lo `test -f 'vauth/spnego_gssapi.c' || echo '$(srcdir)/'`vauth/spnego_gssapi.c + +vauth/libcurlu_la-spnego_sspi.lo: vauth/spnego_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vauth/libcurlu_la-spnego_sspi.lo -MD -MP -MF vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Tpo -c -o vauth/libcurlu_la-spnego_sspi.lo `test -f 'vauth/spnego_sspi.c' || echo '$(srcdir)/'`vauth/spnego_sspi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Tpo vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vauth/spnego_sspi.c' object='vauth/libcurlu_la-spnego_sspi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vauth/libcurlu_la-spnego_sspi.lo `test -f 'vauth/spnego_sspi.c' || echo '$(srcdir)/'`vauth/spnego_sspi.c + +vtls/libcurlu_la-openssl.lo: vtls/openssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-openssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-openssl.Tpo -c -o vtls/libcurlu_la-openssl.lo `test -f 'vtls/openssl.c' || echo '$(srcdir)/'`vtls/openssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-openssl.Tpo vtls/$(DEPDIR)/libcurlu_la-openssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/openssl.c' object='vtls/libcurlu_la-openssl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-openssl.lo `test -f 'vtls/openssl.c' || echo '$(srcdir)/'`vtls/openssl.c + +vtls/libcurlu_la-gtls.lo: vtls/gtls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-gtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-gtls.Tpo -c -o vtls/libcurlu_la-gtls.lo `test -f 'vtls/gtls.c' || echo '$(srcdir)/'`vtls/gtls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-gtls.Tpo vtls/$(DEPDIR)/libcurlu_la-gtls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/gtls.c' object='vtls/libcurlu_la-gtls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-gtls.lo `test -f 'vtls/gtls.c' || echo '$(srcdir)/'`vtls/gtls.c + +vtls/libcurlu_la-vtls.lo: vtls/vtls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-vtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-vtls.Tpo -c -o vtls/libcurlu_la-vtls.lo `test -f 'vtls/vtls.c' || echo '$(srcdir)/'`vtls/vtls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-vtls.Tpo vtls/$(DEPDIR)/libcurlu_la-vtls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/vtls.c' object='vtls/libcurlu_la-vtls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-vtls.lo `test -f 'vtls/vtls.c' || echo '$(srcdir)/'`vtls/vtls.c + +vtls/libcurlu_la-nss.lo: vtls/nss.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-nss.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-nss.Tpo -c -o vtls/libcurlu_la-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-nss.Tpo vtls/$(DEPDIR)/libcurlu_la-nss.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/nss.c' object='vtls/libcurlu_la-nss.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-nss.lo `test -f 'vtls/nss.c' || echo '$(srcdir)/'`vtls/nss.c + +vtls/libcurlu_la-polarssl.lo: vtls/polarssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-polarssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-polarssl.Tpo -c -o vtls/libcurlu_la-polarssl.lo `test -f 'vtls/polarssl.c' || echo '$(srcdir)/'`vtls/polarssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-polarssl.Tpo vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/polarssl.c' object='vtls/libcurlu_la-polarssl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-polarssl.lo `test -f 'vtls/polarssl.c' || echo '$(srcdir)/'`vtls/polarssl.c + +vtls/libcurlu_la-polarssl_threadlock.lo: vtls/polarssl_threadlock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-polarssl_threadlock.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Tpo -c -o vtls/libcurlu_la-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Tpo vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/polarssl_threadlock.c' object='vtls/libcurlu_la-polarssl_threadlock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-polarssl_threadlock.lo `test -f 'vtls/polarssl_threadlock.c' || echo '$(srcdir)/'`vtls/polarssl_threadlock.c + +vtls/libcurlu_la-wolfssl.lo: vtls/wolfssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-wolfssl.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-wolfssl.Tpo -c -o vtls/libcurlu_la-wolfssl.lo `test -f 'vtls/wolfssl.c' || echo '$(srcdir)/'`vtls/wolfssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-wolfssl.Tpo vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/wolfssl.c' object='vtls/libcurlu_la-wolfssl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-wolfssl.lo `test -f 'vtls/wolfssl.c' || echo '$(srcdir)/'`vtls/wolfssl.c + +vtls/libcurlu_la-schannel.lo: vtls/schannel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-schannel.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-schannel.Tpo -c -o vtls/libcurlu_la-schannel.lo `test -f 'vtls/schannel.c' || echo '$(srcdir)/'`vtls/schannel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-schannel.Tpo vtls/$(DEPDIR)/libcurlu_la-schannel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/schannel.c' object='vtls/libcurlu_la-schannel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-schannel.lo `test -f 'vtls/schannel.c' || echo '$(srcdir)/'`vtls/schannel.c + +vtls/libcurlu_la-schannel_verify.lo: vtls/schannel_verify.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-schannel_verify.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Tpo -c -o vtls/libcurlu_la-schannel_verify.lo `test -f 'vtls/schannel_verify.c' || echo '$(srcdir)/'`vtls/schannel_verify.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Tpo vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/schannel_verify.c' object='vtls/libcurlu_la-schannel_verify.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-schannel_verify.lo `test -f 'vtls/schannel_verify.c' || echo '$(srcdir)/'`vtls/schannel_verify.c + +vtls/libcurlu_la-sectransp.lo: vtls/sectransp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-sectransp.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-sectransp.Tpo -c -o vtls/libcurlu_la-sectransp.lo `test -f 'vtls/sectransp.c' || echo '$(srcdir)/'`vtls/sectransp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-sectransp.Tpo vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/sectransp.c' object='vtls/libcurlu_la-sectransp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-sectransp.lo `test -f 'vtls/sectransp.c' || echo '$(srcdir)/'`vtls/sectransp.c + +vtls/libcurlu_la-gskit.lo: vtls/gskit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-gskit.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-gskit.Tpo -c -o vtls/libcurlu_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-gskit.Tpo vtls/$(DEPDIR)/libcurlu_la-gskit.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/gskit.c' object='vtls/libcurlu_la-gskit.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-gskit.lo `test -f 'vtls/gskit.c' || echo '$(srcdir)/'`vtls/gskit.c + +vtls/libcurlu_la-mbedtls.lo: vtls/mbedtls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-mbedtls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-mbedtls.Tpo -c -o vtls/libcurlu_la-mbedtls.lo `test -f 'vtls/mbedtls.c' || echo '$(srcdir)/'`vtls/mbedtls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-mbedtls.Tpo vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/mbedtls.c' object='vtls/libcurlu_la-mbedtls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-mbedtls.lo `test -f 'vtls/mbedtls.c' || echo '$(srcdir)/'`vtls/mbedtls.c + +vtls/libcurlu_la-mesalink.lo: vtls/mesalink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT vtls/libcurlu_la-mesalink.lo -MD -MP -MF vtls/$(DEPDIR)/libcurlu_la-mesalink.Tpo -c -o vtls/libcurlu_la-mesalink.lo `test -f 'vtls/mesalink.c' || echo '$(srcdir)/'`vtls/mesalink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurlu_la-mesalink.Tpo vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vtls/mesalink.c' object='vtls/libcurlu_la-mesalink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vtls/libcurlu_la-mesalink.lo `test -f 'vtls/mesalink.c' || echo '$(srcdir)/'`vtls/mesalink.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf vauth/.libs vauth/_libs + -rm -rf vtls/.libs vtls/_libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +@CURLDEBUG_FALSE@all-local: +all-am: Makefile $(LTLIBRARIES) curl_config.h all-local +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f vauth/$(DEPDIR)/$(am__dirstamp) + -rm -f vauth/$(am__dirstamp) + -rm -f vtls/$(DEPDIR)/$(am__dirstamp) + -rm -f vtls/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo + -rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo + -rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo + -rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo + -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo + -rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo + -rm -f ./$(DEPDIR)/libcurl_la-connect.Plo + -rm -f ./$(DEPDIR)/libcurl_la-content_encoding.Plo + -rm -f ./$(DEPDIR)/libcurl_la-cookie.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_ctype.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_des.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_endian.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_fnmatch.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_get_line.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_gethostname.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_gssapi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_memrchr.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_multibyte.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_ntlm_wb.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_path.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_range.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_rtmp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_sasl.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_sspi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_threads.Plo + -rm -f ./$(DEPDIR)/libcurl_la-dict.Plo + -rm -f ./$(DEPDIR)/libcurl_la-doh.Plo + -rm -f ./$(DEPDIR)/libcurl_la-dotdot.Plo + -rm -f ./$(DEPDIR)/libcurl_la-easy.Plo + -rm -f ./$(DEPDIR)/libcurl_la-escape.Plo + -rm -f ./$(DEPDIR)/libcurl_la-file.Plo + -rm -f ./$(DEPDIR)/libcurl_la-fileinfo.Plo + -rm -f ./$(DEPDIR)/libcurl_la-formdata.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ftp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ftplistparser.Plo + -rm -f ./$(DEPDIR)/libcurl_la-getenv.Plo + -rm -f ./$(DEPDIR)/libcurl_la-getinfo.Plo + -rm -f ./$(DEPDIR)/libcurl_la-gopher.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hash.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hmac.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostasyn.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostcheck.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostip.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostip4.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostip6.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostsyn.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http2.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_chunks.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_digest.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_ntlm.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_proxy.Plo + -rm -f ./$(DEPDIR)/libcurl_la-idn_win32.Plo + -rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo + -rm -f ./$(DEPDIR)/libcurl_la-imap.Plo + -rm -f ./$(DEPDIR)/libcurl_la-inet_ntop.Plo + -rm -f ./$(DEPDIR)/libcurl_la-inet_pton.Plo + -rm -f ./$(DEPDIR)/libcurl_la-krb5.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ldap.Plo + -rm -f ./$(DEPDIR)/libcurl_la-llist.Plo + -rm -f ./$(DEPDIR)/libcurl_la-md4.Plo + -rm -f ./$(DEPDIR)/libcurl_la-md5.Plo + -rm -f ./$(DEPDIR)/libcurl_la-memdebug.Plo + -rm -f ./$(DEPDIR)/libcurl_la-mime.Plo + -rm -f ./$(DEPDIR)/libcurl_la-mprintf.Plo + -rm -f ./$(DEPDIR)/libcurl_la-multi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-netrc.Plo + -rm -f ./$(DEPDIR)/libcurl_la-non-ascii.Plo + -rm -f ./$(DEPDIR)/libcurl_la-nonblock.Plo + -rm -f ./$(DEPDIR)/libcurl_la-openldap.Plo + -rm -f ./$(DEPDIR)/libcurl_la-parsedate.Plo + -rm -f ./$(DEPDIR)/libcurl_la-pingpong.Plo + -rm -f ./$(DEPDIR)/libcurl_la-pop3.Plo + -rm -f ./$(DEPDIR)/libcurl_la-progress.Plo + -rm -f ./$(DEPDIR)/libcurl_la-psl.Plo + -rm -f ./$(DEPDIR)/libcurl_la-rand.Plo + -rm -f ./$(DEPDIR)/libcurl_la-rtsp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-security.Plo + -rm -f ./$(DEPDIR)/libcurl_la-select.Plo + -rm -f ./$(DEPDIR)/libcurl_la-sendf.Plo + -rm -f ./$(DEPDIR)/libcurl_la-setopt.Plo + -rm -f ./$(DEPDIR)/libcurl_la-sha256.Plo + -rm -f ./$(DEPDIR)/libcurl_la-share.Plo + -rm -f ./$(DEPDIR)/libcurl_la-slist.Plo + -rm -f ./$(DEPDIR)/libcurl_la-smb.Plo + -rm -f ./$(DEPDIR)/libcurl_la-smtp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-socks.Plo + -rm -f ./$(DEPDIR)/libcurl_la-socks_gssapi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-socks_sspi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-speedcheck.Plo + -rm -f ./$(DEPDIR)/libcurl_la-splay.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ssh-libssh.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ssh.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strcase.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strdup.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strerror.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strtok.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strtoofft.Plo + -rm -f ./$(DEPDIR)/libcurl_la-system_win32.Plo + -rm -f ./$(DEPDIR)/libcurl_la-telnet.Plo + -rm -f ./$(DEPDIR)/libcurl_la-tftp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-timeval.Plo + -rm -f ./$(DEPDIR)/libcurl_la-transfer.Plo + -rm -f ./$(DEPDIR)/libcurl_la-url.Plo + -rm -f ./$(DEPDIR)/libcurl_la-urlapi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-version.Plo + -rm -f ./$(DEPDIR)/libcurl_la-warnless.Plo + -rm -f ./$(DEPDIR)/libcurl_la-wildcard.Plo + -rm -f ./$(DEPDIR)/libcurl_la-x509asn1.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-content_encoding.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-cookie.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_ctype.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_des.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_endian.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_fnmatch.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_get_line.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_ntlm_wb.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_path.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_range.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_rtmp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_sasl.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_sspi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_threads.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-dict.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-doh.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-dotdot.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-easy.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-escape.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-file.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-fileinfo.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-formdata.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ftp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ftplistparser.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-getenv.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-getinfo.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-gopher.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hash.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hmac.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostasyn.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostcheck.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostip.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostip4.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostip6.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostsyn.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http2.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_chunks.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_digest.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_proxy.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-idn_win32.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-imap.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-inet_ntop.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-inet_pton.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-krb5.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ldap.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-llist.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-md4.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-md5.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-memdebug.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-mime.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-mprintf.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-multi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-netrc.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-non-ascii.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-nonblock.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-openldap.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-parsedate.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-pingpong.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-pop3.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-progress.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-psl.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-rand.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-rtsp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-security.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-select.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-sendf.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-setopt.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-sha256.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-share.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-slist.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-smb.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-smtp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-socks.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-socks_gssapi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-socks_sspi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-speedcheck.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-splay.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ssh-libssh.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ssh.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strcase.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strdup.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strerror.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strtok.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strtoofft.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-system_win32.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-telnet.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-tftp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-timeval.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-transfer.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-url.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-urlapi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-version.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-warnless.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-wildcard.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-x509asn1.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-cleartext.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-cram.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-digest.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-digest_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-krb5_gssapi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-krb5_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-ntlm.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-ntlm_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-oauth2.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-spnego_gssapi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-spnego_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-vauth.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-cleartext.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-cram.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-digest.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-digest_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-krb5_gssapi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-krb5_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-ntlm.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-ntlm_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-oauth2.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-vauth.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-gskit.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-gtls.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-mesalink.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-nss.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-openssl.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-polarssl.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-schannel.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-sectransp.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-vtls.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-gskit.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-gtls.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-nss.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-openssl.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-vtls.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo + -rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo + -rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo + -rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo + -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo + -rm -f ./$(DEPDIR)/libcurl_la-conncache.Plo + -rm -f ./$(DEPDIR)/libcurl_la-connect.Plo + -rm -f ./$(DEPDIR)/libcurl_la-content_encoding.Plo + -rm -f ./$(DEPDIR)/libcurl_la-cookie.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_addrinfo.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_ctype.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_des.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_endian.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_fnmatch.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_get_line.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_gethostname.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_gssapi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_memrchr.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_multibyte.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_ntlm_wb.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_path.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_range.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_rtmp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_sasl.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_sspi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-curl_threads.Plo + -rm -f ./$(DEPDIR)/libcurl_la-dict.Plo + -rm -f ./$(DEPDIR)/libcurl_la-doh.Plo + -rm -f ./$(DEPDIR)/libcurl_la-dotdot.Plo + -rm -f ./$(DEPDIR)/libcurl_la-easy.Plo + -rm -f ./$(DEPDIR)/libcurl_la-escape.Plo + -rm -f ./$(DEPDIR)/libcurl_la-file.Plo + -rm -f ./$(DEPDIR)/libcurl_la-fileinfo.Plo + -rm -f ./$(DEPDIR)/libcurl_la-formdata.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ftp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ftplistparser.Plo + -rm -f ./$(DEPDIR)/libcurl_la-getenv.Plo + -rm -f ./$(DEPDIR)/libcurl_la-getinfo.Plo + -rm -f ./$(DEPDIR)/libcurl_la-gopher.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hash.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hmac.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostasyn.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostcheck.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostip.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostip4.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostip6.Plo + -rm -f ./$(DEPDIR)/libcurl_la-hostsyn.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http2.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_chunks.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_digest.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_negotiate.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_ntlm.Plo + -rm -f ./$(DEPDIR)/libcurl_la-http_proxy.Plo + -rm -f ./$(DEPDIR)/libcurl_la-idn_win32.Plo + -rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo + -rm -f ./$(DEPDIR)/libcurl_la-imap.Plo + -rm -f ./$(DEPDIR)/libcurl_la-inet_ntop.Plo + -rm -f ./$(DEPDIR)/libcurl_la-inet_pton.Plo + -rm -f ./$(DEPDIR)/libcurl_la-krb5.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ldap.Plo + -rm -f ./$(DEPDIR)/libcurl_la-llist.Plo + -rm -f ./$(DEPDIR)/libcurl_la-md4.Plo + -rm -f ./$(DEPDIR)/libcurl_la-md5.Plo + -rm -f ./$(DEPDIR)/libcurl_la-memdebug.Plo + -rm -f ./$(DEPDIR)/libcurl_la-mime.Plo + -rm -f ./$(DEPDIR)/libcurl_la-mprintf.Plo + -rm -f ./$(DEPDIR)/libcurl_la-multi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-netrc.Plo + -rm -f ./$(DEPDIR)/libcurl_la-non-ascii.Plo + -rm -f ./$(DEPDIR)/libcurl_la-nonblock.Plo + -rm -f ./$(DEPDIR)/libcurl_la-openldap.Plo + -rm -f ./$(DEPDIR)/libcurl_la-parsedate.Plo + -rm -f ./$(DEPDIR)/libcurl_la-pingpong.Plo + -rm -f ./$(DEPDIR)/libcurl_la-pop3.Plo + -rm -f ./$(DEPDIR)/libcurl_la-progress.Plo + -rm -f ./$(DEPDIR)/libcurl_la-psl.Plo + -rm -f ./$(DEPDIR)/libcurl_la-rand.Plo + -rm -f ./$(DEPDIR)/libcurl_la-rtsp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-security.Plo + -rm -f ./$(DEPDIR)/libcurl_la-select.Plo + -rm -f ./$(DEPDIR)/libcurl_la-sendf.Plo + -rm -f ./$(DEPDIR)/libcurl_la-setopt.Plo + -rm -f ./$(DEPDIR)/libcurl_la-sha256.Plo + -rm -f ./$(DEPDIR)/libcurl_la-share.Plo + -rm -f ./$(DEPDIR)/libcurl_la-slist.Plo + -rm -f ./$(DEPDIR)/libcurl_la-smb.Plo + -rm -f ./$(DEPDIR)/libcurl_la-smtp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-socks.Plo + -rm -f ./$(DEPDIR)/libcurl_la-socks_gssapi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-socks_sspi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-speedcheck.Plo + -rm -f ./$(DEPDIR)/libcurl_la-splay.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ssh-libssh.Plo + -rm -f ./$(DEPDIR)/libcurl_la-ssh.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strcase.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strdup.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strerror.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strtok.Plo + -rm -f ./$(DEPDIR)/libcurl_la-strtoofft.Plo + -rm -f ./$(DEPDIR)/libcurl_la-system_win32.Plo + -rm -f ./$(DEPDIR)/libcurl_la-telnet.Plo + -rm -f ./$(DEPDIR)/libcurl_la-tftp.Plo + -rm -f ./$(DEPDIR)/libcurl_la-timeval.Plo + -rm -f ./$(DEPDIR)/libcurl_la-transfer.Plo + -rm -f ./$(DEPDIR)/libcurl_la-url.Plo + -rm -f ./$(DEPDIR)/libcurl_la-urlapi.Plo + -rm -f ./$(DEPDIR)/libcurl_la-version.Plo + -rm -f ./$(DEPDIR)/libcurl_la-warnless.Plo + -rm -f ./$(DEPDIR)/libcurl_la-wildcard.Plo + -rm -f ./$(DEPDIR)/libcurl_la-x509asn1.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-conncache.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-connect.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-content_encoding.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-cookie.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_addrinfo.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_ctype.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_des.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_endian.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_fnmatch.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_get_line.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_ntlm_wb.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_path.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_range.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_rtmp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_sasl.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_sspi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-curl_threads.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-dict.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-doh.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-dotdot.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-easy.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-escape.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-file.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-fileinfo.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-formdata.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ftp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ftplistparser.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-getenv.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-getinfo.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-gopher.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hash.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hmac.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostasyn.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostcheck.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostip.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostip4.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostip6.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-hostsyn.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http2.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_chunks.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_digest.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_negotiate.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_ntlm.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-http_proxy.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-idn_win32.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-imap.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-inet_ntop.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-inet_pton.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-krb5.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ldap.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-llist.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-md4.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-md5.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-memdebug.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-mime.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-mprintf.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-multi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-netrc.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-non-ascii.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-nonblock.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-openldap.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-parsedate.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-pingpong.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-pop3.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-progress.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-psl.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-rand.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-rtsp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-security.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-select.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-sendf.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-setopt.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-sha256.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-share.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-slist.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-smb.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-smtp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-socks.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-socks_gssapi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-socks_sspi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-speedcheck.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-splay.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ssh-libssh.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-ssh.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strcase.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strdup.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strerror.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strtok.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-strtoofft.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-system_win32.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-telnet.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-tftp.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-timeval.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-transfer.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-url.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-urlapi.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-version.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-warnless.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-wildcard.Plo + -rm -f ./$(DEPDIR)/libcurlu_la-x509asn1.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-cleartext.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-cram.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-digest.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-digest_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-krb5_gssapi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-krb5_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-ntlm.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-ntlm_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-oauth2.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-spnego_gssapi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-spnego_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurl_la-vauth.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-cleartext.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-cram.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-digest.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-digest_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-krb5_gssapi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-krb5_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-ntlm.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-ntlm_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-oauth2.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_gssapi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-spnego_sspi.Plo + -rm -f vauth/$(DEPDIR)/libcurlu_la-vauth.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-gskit.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-gtls.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-mbedtls.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-mesalink.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-nss.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-openssl.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-polarssl.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-polarssl_threadlock.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-schannel.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-schannel_verify.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-sectransp.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-vtls.Plo + -rm -f vtls/$(DEPDIR)/libcurl_la-wolfssl.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-gskit.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-gtls.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-mbedtls.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-mesalink.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-nss.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-openssl.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-polarssl.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-polarssl_threadlock.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-schannel_verify.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-sectransp.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-vtls.Plo + -rm -f vtls/$(DEPDIR)/libcurlu_la-wolfssl.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: all install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am all-local am--depfiles check \ + check-am clean clean-generic clean-libLTLIBRARIES \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libLTLIBRARIES + +.PRECIOUS: Makefile + + +checksrc: + $(CHECKSRC)(@PERL@ $(srcdir)/checksrc.pl -D$(srcdir) -W$(srcdir)/curl_config.h \ + $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch]) + +# for debug builds, we scan the sources on all regular make invokes +@CURLDEBUG_TRUE@all-local: checksrc + +tidy: + $(TIDY) $(CSOURCES) $(TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libcurl/lib/Makefile.inc b/libcurl/lib/Makefile.inc new file mode 100644 index 0000000..f795f32 --- /dev/null +++ b/libcurl/lib/Makefile.inc @@ -0,0 +1,85 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### + +LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \ + vauth/digest.c vauth/digest_sspi.c vauth/krb5_gssapi.c \ + vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c vauth/oauth2.c \ + vauth/spnego_gssapi.c vauth/spnego_sspi.c + +LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h + +LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \ + vtls/polarssl.c vtls/polarssl_threadlock.c \ + vtls/wolfssl.c vtls/schannel.c vtls/schannel_verify.c \ + vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c \ + vtls/bearssl.c + +LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ + vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ + vtls/wolfssl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ + vtls/mbedtls.h vtls/mesalink.h vtls/bearssl.h + +LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ + cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \ + ldap.c version.c getenv.c escape.c mprintf.c telnet.c netrc.c \ + getinfo.c transfer.c strcase.c easy.c security.c curl_fnmatch.c \ + fileinfo.c ftplistparser.c wildcard.c krb5.c memdebug.c http_chunks.c \ + strtok.c connect.c llist.c hash.c multi.c content_encoding.c share.c \ + http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \ + strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \ + inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \ + ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \ + curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \ + pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \ + openldap.c curl_gethostname.c gopher.c idn_win32.c \ + http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \ + http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \ + curl_multibyte.c hostcheck.c conncache.c dotdot.c \ + x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \ + mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \ + doh.c urlapi.c curl_get_line.c altsvc.c + +LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ + formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ + speedcheck.h urldata.h curl_ldap.h escape.h telnet.h getinfo.h \ + strcase.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \ + wildcard.h fileinfo.h ftplistparser.h strtok.h connect.h llist.h \ + hash.h content_encoding.h share.h curl_md4.h curl_md5.h http_digest.h \ + http_negotiate.h inet_pton.h amigaos.h strtoofft.h strerror.h \ + inet_ntop.h curlx.h curl_memory.h curl_setup.h transfer.h select.h \ + easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h \ + socks.h ssh.h curl_base64.h curl_addrinfo.h curl_sspi.h \ + slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \ + rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \ + curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \ + http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \ + curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \ + curl_setup_once.h multihandle.h setup-vms.h dotdot.h \ + x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ + curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \ + curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ + curl_get_line.h altsvc.h + +LIB_RCFILES = libcurl.rc + +CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) +HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) diff --git a/libcurl/lib/Makefile.m32 b/libcurl/lib/Makefile.m32 new file mode 100644 index 0000000..ae88f4d --- /dev/null +++ b/libcurl/lib/Makefile.m32 @@ -0,0 +1,387 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1999 - 2017, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +#*************************************************************************** + +########################################################################### +# +## Makefile for building libcurl.a with MingW (GCC-3.2 or later or LLVM/Clang) +## and optionally OpenSSL (1.0.2a), libssh2 (1.5), zlib (1.2.8), librtmp (2.4), +## brotli (1.0.1) +## +## Usage: mingw32-make -f Makefile.m32 CFG=-feature1[-feature2][-feature3][...] +## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn +## +## Hint: you can also set environment vars to control the build, f.e.: +## set ZLIB_PATH=c:/zlib-1.2.8 +## set ZLIB=1 +# +########################################################################### + +# Edit the path below to point to the base of your Zlib sources. +ifndef ZLIB_PATH +ZLIB_PATH = ../../zlib-1.2.8 +endif +# Edit the path below to point to the base of your Brotli sources. +ifndef BROTLI_PATH +BROTLI_PATH = ../../brotli-1.0.1 +endif +# Edit the path below to point to the base of your OpenSSL package. +ifndef OPENSSL_PATH +OPENSSL_PATH = ../../openssl-1.0.2a +endif +# Edit the path below to point to the base of your LibSSH2 package. +ifndef LIBSSH2_PATH +LIBSSH2_PATH = ../../libssh2-1.5.0 +endif +# Edit the path below to point to the base of your librtmp package. +ifndef LIBRTMP_PATH +LIBRTMP_PATH = ../../librtmp-2.4 +endif +# Edit the path below to point to the base of your libidn2 package. +ifndef LIBIDN2_PATH +LIBIDN2_PATH = ../../libidn2-2.0.3 +endif +# Edit the path below to point to the base of your MS IDN package. +# Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1 +# https://www.microsoft.com/en-us/download/details.aspx?id=734 +ifndef WINIDN_PATH +WINIDN_PATH = ../../Microsoft IDN Mitigation APIs +endif +# Edit the path below to point to the base of your Novell LDAP NDK. +ifndef LDAP_SDK +LDAP_SDK = c:/novell/ndk/cldapsdk/win32 +endif +# Edit the path below to point to the base of your nghttp2 package. +ifndef NGHTTP2_PATH +NGHTTP2_PATH = ../../nghttp2-1.0.0 +endif + +PROOT = .. + +# Edit the path below to point to the base of your c-ares package. +ifndef LIBCARES_PATH +LIBCARES_PATH = $(PROOT)/ares +endif + +ifeq ($(CURL_CC),) +CURL_CC := $(CROSSPREFIX)gcc +endif +ifeq ($(CURL_AR),) +CURL_AR := $(CROSSPREFIX)ar +endif +ifeq ($(CURL_RANLIB),) +CURL_RANLIB := $(CROSSPREFIX)ranlib +endif + +CC = $(CURL_CC) +CFLAGS = $(CURL_CFLAG_EXTRAS) -g -O2 -Wall -W +CFLAGS += -fno-strict-aliasing +# comment LDFLAGS below to keep debug info +LDFLAGS = $(CURL_LDFLAG_EXTRAS) $(CURL_LDFLAG_EXTRAS_DLL) -s +AR = $(CURL_AR) +RANLIB = $(CURL_RANLIB) +RC = $(CROSSPREFIX)windres +RCFLAGS = --include-dir=$(PROOT)/include -DDEBUGBUILD=0 -O COFF +STRIP = $(CROSSPREFIX)strip -g + +# Set environment var ARCH to your architecture to override autodetection. +ifndef ARCH +ifeq ($(findstring x86_64,$(shell $(CC) -dumpmachine)),x86_64) +ARCH = w64 +else +ARCH = w32 +endif +endif + +ifeq ($(ARCH),w64) +CFLAGS += -m64 -D_AMD64_ +LDFLAGS += -m64 +RCFLAGS += -F pe-x86-64 +else +CFLAGS += -m32 +LDFLAGS += -m32 +RCFLAGS += -F pe-i386 +endif + +# Platform-dependent helper tool macros +ifeq ($(findstring /sh,$(SHELL)),/sh) +DEL = rm -f $1 +RMDIR = rm -fr $1 +MKDIR = mkdir -p $1 +COPY = -cp -afv $1 $2 +#COPYR = -cp -afr $1/* $2 +COPYR = -rsync -aC $1/* $2 +TOUCH = touch $1 +CAT = cat +ECHONL = echo "" +DL = ' +else +ifeq "$(OS)" "Windows_NT" +DEL = -del 2>NUL /q /f $(subst /,\,$1) +RMDIR = -rd 2>NUL /q /s $(subst /,\,$1) +else +DEL = -del 2>NUL $(subst /,\,$1) +RMDIR = -deltree 2>NUL /y $(subst /,\,$1) +endif +MKDIR = -md 2>NUL $(subst /,\,$1) +COPY = -copy 2>NUL /y $(subst /,\,$1) $(subst /,\,$2) +COPYR = -xcopy 2>NUL /q /y /e $(subst /,\,$1) $(subst /,\,$2) +TOUCH = copy 2>&1>NUL /b $(subst /,\,$1) +,, +CAT = type +ECHONL = $(ComSpec) /c echo. +endif + +######################################################## +## Nothing more to do below this line! + +ifeq ($(findstring -dyn,$(CFG)),-dyn) +DYN = 1 +endif +ifeq ($(findstring -ares,$(CFG)),-ares) +ARES = 1 +endif +ifeq ($(findstring -sync,$(CFG)),-sync) +SYNC = 1 +endif +ifeq ($(findstring -rtmp,$(CFG)),-rtmp) +RTMP = 1 +SSL = 1 +ZLIB = 1 +endif +ifeq ($(findstring -ssh2,$(CFG)),-ssh2) +SSH2 = 1 +SSL = 1 +ZLIB = 1 +endif +ifeq ($(findstring -ssl,$(CFG)),-ssl) +SSL = 1 +endif +ifeq ($(findstring -srp,$(CFG)),-srp) +SRP = 1 +endif +ifeq ($(findstring -zlib,$(CFG)),-zlib) +ZLIB = 1 +endif +ifeq ($(findstring -brotli,$(CFG)),-brotli) +BROTLI = 1 +endif +ifeq ($(findstring -idn2,$(CFG)),-idn2) +IDN2 = 1 +endif +ifeq ($(findstring -winidn,$(CFG)),-winidn) +WINIDN = 1 +endif +ifeq ($(findstring -sspi,$(CFG)),-sspi) +SSPI = 1 +endif +ifeq ($(findstring -ldaps,$(CFG)),-ldaps) +LDAPS = 1 +endif +ifeq ($(findstring -ipv6,$(CFG)),-ipv6) +IPV6 = 1 +endif +ifeq ($(findstring -winssl,$(CFG)),-winssl) +WINSSL = 1 +SSPI = 1 +endif +ifeq ($(findstring -nghttp2,$(CFG)),-nghttp2) +NGHTTP2 = 1 +endif + +INCLUDES = -I. -I../include +CFLAGS += -DBUILDING_LIBCURL +ifdef SSL + ifdef WINSSL + CFLAGS += -DCURL_WITH_MULTI_SSL + endif +endif + +ifdef SYNC + CFLAGS += -DUSE_SYNC_DNS +else + ifdef ARES + INCLUDES += -I"$(LIBCARES_PATH)" + CFLAGS += -DUSE_ARES -DCARES_STATICLIB + DLL_LIBS += -L"$(LIBCARES_PATH)" -lcares + libcurl_dll_DEPENDENCIES = $(LIBCARES_PATH)/libcares.a + endif +endif +ifdef RTMP + INCLUDES += -I"$(LIBRTMP_PATH)" + CFLAGS += -DUSE_LIBRTMP + DLL_LIBS += -L"$(LIBRTMP_PATH)/librtmp" -lrtmp -lwinmm +endif +ifdef NGHTTP2 + INCLUDES += -I"$(NGHTTP2_PATH)/include" + CFLAGS += -DUSE_NGHTTP2 + DLL_LIBS += -L"$(NGHTTP2_PATH)/lib" -lnghttp2 +endif +ifdef SSH2 + INCLUDES += -I"$(LIBSSH2_PATH)/include" -I"$(LIBSSH2_PATH)/win32" + CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H + DLL_LIBS += -L"$(LIBSSH2_PATH)/win32" -lssh2 + ifdef WINSSL + ifndef DYN + DLL_LIBS += -lbcrypt -lcrypt32 + endif + endif +endif +ifdef SSL + ifndef OPENSSL_INCLUDE + ifeq "$(wildcard $(OPENSSL_PATH)/outinc)" "$(OPENSSL_PATH)/outinc" + OPENSSL_INCLUDE = $(OPENSSL_PATH)/outinc + endif + ifeq "$(wildcard $(OPENSSL_PATH)/include)" "$(OPENSSL_PATH)/include" + OPENSSL_INCLUDE = $(OPENSSL_PATH)/include + endif + endif + ifneq "$(wildcard $(OPENSSL_INCLUDE)/openssl/opensslv.h)" "$(OPENSSL_INCLUDE)/openssl/opensslv.h" + $(error Invalid path to OpenSSL package: $(OPENSSL_PATH)) + endif + ifndef OPENSSL_LIBPATH + ifeq "$(wildcard $(OPENSSL_PATH)/out)" "$(OPENSSL_PATH)/out" + OPENSSL_LIBPATH = $(OPENSSL_PATH)/out + OPENSSL_LIBS = -leay32 -lssl32 + endif + ifeq "$(wildcard $(OPENSSL_PATH)/lib)" "$(OPENSSL_PATH)/lib" + OPENSSL_LIBPATH = $(OPENSSL_PATH)/lib + OPENSSL_LIBS = -lcrypto -lssl + endif + endif + ifndef DYN + OPENSSL_LIBS += -lgdi32 -lcrypt32 + endif + INCLUDES += -I"$(OPENSSL_INCLUDE)" + CFLAGS += -DUSE_OPENSSL -DHAVE_OPENSSL_ENGINE_H -DHAVE_OPENSSL_PKCS12_H \ + -DHAVE_ENGINE_LOAD_BUILTIN_ENGINES -DOPENSSL_NO_KRB5 + DLL_LIBS += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS) + ifdef SRP + ifeq "$(wildcard $(OPENSSL_INCLUDE)/openssl/srp.h)" "$(OPENSSL_INCLUDE)/openssl/srp.h" + CFLAGS += -DHAVE_OPENSSL_SRP -DUSE_TLS_SRP + endif + endif +endif +ifdef WINSSL + CFLAGS += -DUSE_SCHANNEL + DLL_LIBS += -lcrypt32 +endif +ifdef ZLIB + INCLUDES += -I"$(ZLIB_PATH)" + CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H + DLL_LIBS += -L"$(ZLIB_PATH)" -lz +endif +ifdef BROTLI + INCLUDES += -I"$(BROTLI_PATH)/include" + CFLAGS += -DHAVE_BROTLI + DLL_LIBS += -L"$(BROTLI_PATH)/lib" + ifdef BROTLI_LIBS + DLL_LIBS += $(BROTLI_LIBS) + else + DLL_LIBS += -lbrotlidec + endif +endif +ifdef IDN2 + INCLUDES += -I"$(LIBIDN2_PATH)/include" + CFLAGS += -DUSE_LIBIDN2 + DLL_LIBS += -L"$(LIBIDN2_PATH)/lib" -lidn2 +else +ifdef WINIDN + CFLAGS += -DUSE_WIN32_IDN + CFLAGS += -DWANT_IDN_PROTOTYPES + DLL_LIBS += -L"$(WINIDN_PATH)" -lnormaliz +endif +endif +ifdef SSPI + CFLAGS += -DUSE_WINDOWS_SSPI +endif +ifdef SPNEGO + CFLAGS += -DHAVE_SPNEGO +endif +ifdef IPV6 + CFLAGS += -DENABLE_IPV6 -D_WIN32_WINNT=0x0501 +endif +ifdef LDAPS + CFLAGS += -DHAVE_LDAP_SSL +endif +ifdef USE_LDAP_NOVELL + INCLUDES += -I"$(LDAP_SDK)/inc" + CFLAGS += -DCURL_HAS_NOVELL_LDAPSDK + DLL_LIBS += -L"$(LDAP_SDK)/lib/mscvc" -lldapsdk -lldapssl -lldapx +endif +ifdef USE_LDAP_OPENLDAP + INCLUDES += -I"$(LDAP_SDK)/include" + CFLAGS += -DCURL_HAS_OPENLDAP_LDAPSDK + DLL_LIBS += -L"$(LDAP_SDK)/lib" -lldap -llber +endif +ifndef USE_LDAP_NOVELL +ifndef USE_LDAP_OPENLDAP + DLL_LIBS += -lwldap32 +endif +endif +DLL_LIBS += -lws2_32 + +# Makefile.inc provides the CSOURCES and HHEADERS defines +include Makefile.inc + +ifeq ($(CURL_DLL_A_SUFFIX),) +CURL_DLL_A_SUFFIX := dll +endif + +libcurl_dll_LIBRARY = libcurl$(CURL_DLL_SUFFIX).dll +libcurl_dll_a_LIBRARY = libcurl$(CURL_DLL_A_SUFFIX).a +libcurl_a_LIBRARY = libcurl.a + +libcurl_a_OBJECTS := $(patsubst %.c,%.o,$(strip $(CSOURCES))) +libcurl_a_DEPENDENCIES := $(strip $(CSOURCES) $(HHEADERS)) + +RESOURCE = libcurl.res + + +all: $(libcurl_a_LIBRARY) $(libcurl_dll_LIBRARY) + +$(libcurl_a_LIBRARY): $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES) + @$(call DEL, $@) + $(AR) cru $@ $(libcurl_a_OBJECTS) + $(RANLIB) $@ + $(STRIP) $@ + +# remove the last line above to keep debug info + +$(libcurl_dll_LIBRARY): $(libcurl_a_OBJECTS) $(RESOURCE) $(libcurl_dll_DEPENDENCIES) + @$(call DEL, $@) + $(CC) $(LDFLAGS) -shared -o $@ \ + -Wl,--output-def,$(@:.dll=.def),--out-implib,$(libcurl_dll_a_LIBRARY) \ + $(libcurl_a_OBJECTS) $(RESOURCE) $(DLL_LIBS) + +%.o: %.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ + +%.res: %.rc + $(RC) $(RCFLAGS) -i $< -o $@ + +clean: + @$(call DEL, $(libcurl_a_OBJECTS) $(RESOURCE)) + +distclean vclean: clean + @$(call DEL, $(libcurl_a_LIBRARY) $(libcurl_dll_LIBRARY) $(libcurl_dll_LIBRARY:.dll=.def) $(libcurl_dll_a_LIBRARY)) + +$(LIBCARES_PATH)/libcares.a: + $(MAKE) -C $(LIBCARES_PATH) -f Makefile.m32 diff --git a/libcurl/lib/Makefile.netware b/libcurl/lib/Makefile.netware new file mode 100644 index 0000000..29885a1 --- /dev/null +++ b/libcurl/lib/Makefile.netware @@ -0,0 +1,734 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 2004 - 2015, Guenter Knauf +# Copyright (C) 2001 - 2018, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +#*************************************************************************** + +################################################################# +# +## Makefile for building libcurl.nlm (NetWare version - gnu make) +## +## Use: make -f Makefile.netware +# +################################################################# + +# Edit the path below to point to the base of your Novell NDK. +ifndef NDKBASE +NDKBASE = c:/novell +endif + +# Edit the path below to point to the base of your Zlib sources. +ifndef ZLIB_PATH +ZLIB_PATH = ../../zlib-1.2.8 +endif + +# Edit the path below to point to the base of your OpenSSL package. +ifndef OPENSSL_PATH +OPENSSL_PATH = ../../openssl-1.0.2a +endif + +# Edit the path below to point to the base of your LibSSH2 package. +ifndef LIBSSH2_PATH +LIBSSH2_PATH = ../../libssh2-1.5.0 +endif + +# Edit the path below to point to the base of your libidn package. +ifndef LIBIDN_PATH +LIBIDN_PATH = ../../libidn-1.18 +endif + +# Edit the path below to point to the base of your librtmp package. +ifndef LIBRTMP_PATH +LIBRTMP_PATH = ../../librtmp-2.3 +endif + +# Edit the path below to point to the base of your nghttp2 package. +ifndef NGHTTP2_PATH +NGHTTP2_PATH = ../../nghttp2-0.6.7 +endif + +# Edit the path below to point to the base of your fbopenssl package. +ifndef FBOPENSSL_PATH +FBOPENSSL_PATH = ../../fbopenssl-0.4 +endif + +# Edit the path below to point to the base of your c-ares package. +ifndef LIBCARES_PATH +LIBCARES_PATH = ../ares +endif + +ifndef INSTDIR +INSTDIR = ..$(DS)curl-$(LIBCURL_VERSION_STR)-bin-nw +endif + +# Edit the vars below to change NLM target settings. +TARGET = libcurl +VERSION = $(LIBCURL_VERSION) +COPYR = Copyright (C) $(LIBCURL_COPYRIGHT_STR) +DESCR = curl libcurl $(LIBCURL_VERSION_STR) ($(LIBARCH)) - https://curl.haxx.se +MTSAFE = YES +STACK = 64000 +SCREEN = none +EXPORTF = $(TARGET).imp +EXPORTS = @$(EXPORTF) + +# Uncomment the next line to enable linking with POSIX semantics. +# POSIXFL = 1 + +# Edit the var below to point to your lib architecture. +ifndef LIBARCH +LIBARCH = LIBC +endif + +# must be equal to NDEBUG or DEBUG, CURLDEBUG +ifndef DB +DB = NDEBUG +endif +# Optimization: -O or debugging: -g +ifeq ($(DB),NDEBUG) + OPT = -O2 + OBJDIR = release +else + OPT = -g + OBJDIR = debug +endif + +# The following lines defines your compiler. +ifdef CWFolder + METROWERKS = $(CWFolder) +endif +ifdef METROWERKS + # MWCW_PATH = $(subst \,/,$(METROWERKS))/Novell Support + MWCW_PATH = $(subst \,/,$(METROWERKS))/Novell Support/Metrowerks Support + CC = mwccnlm +else + CC = gcc +endif +PERL = perl +# Here you can find a native Win32 binary of the original awk: +# http://www.gknw.net/development/prgtools/awk-20100523.zip +AWK = awk +CP = cp -afv +MKDIR = mkdir +# RM = rm -f +# If you want to mark the target as MTSAFE you will need a tool for +# generating the xdc data for the linker; here's a minimal tool: +# http://www.gknw.net/development/prgtools/mkxdc.zip +MPKXDC = mkxdc + +# LIBARCH_U = $(shell $(AWK) 'BEGIN {print toupper(ARGV[1])}' $(LIBARCH)) +LIBARCH_L = $(shell $(AWK) 'BEGIN {print tolower(ARGV[1])}' $(LIBARCH)) + +# Include the version info retrieved from curlver.h +-include $(OBJDIR)/version.inc + +# Global flags for all compilers +CFLAGS += $(OPT) -D$(DB) -DNETWARE -DHAVE_CONFIG_H -nostdinc + +ifeq ($(CC),mwccnlm) + LD = mwldnlm + LDFLAGS = -nostdlib $(PRELUDE) $(OBJL) -o $@ -commandfile + AR = mwldnlm + ARFLAGS = -nostdlib -type library -o + LIBEXT = lib + #RANLIB = + CFLAGS += -msgstyle gcc -gccinc -inline off -opt nointrinsics -proc 586 + CFLAGS += -relax_pointers + #CFLAGS += -w on + ifeq ($(LIBARCH),LIBC) + ifeq ($(POSIXFL),1) + PRELUDE = $(NDK_LIBC)/imports/posixpre.o + else + PRELUDE = $(NDK_LIBC)/imports/libcpre.o + endif + CFLAGS += -align 4 + else + # PRELUDE = $(NDK_CLIB)/imports/clibpre.o + # to avoid the __init_* / __deinit_* woes don't use prelude from NDK + PRELUDE = "$(MWCW_PATH)/libraries/runtime/prelude.obj" + # CFLAGS += -include "$(MWCW_PATH)/headers/nlm_clib_prefix.h" + CFLAGS += -align 1 + endif +else + LD = nlmconv + LDFLAGS = -T + AR = ar + ARFLAGS = -cq + LIBEXT = a + RANLIB = ranlib + CFLAGS += -m32 + CFLAGS += -fno-builtin -fno-strict-aliasing + ifeq ($(findstring gcc,$(CC)),gcc) + CFLAGS += -fpcc-struct-return + endif + CFLAGS += -Wall # -pedantic + ifeq ($(LIBARCH),LIBC) + ifeq ($(POSIXFL),1) + PRELUDE = $(NDK_LIBC)/imports/posixpre.gcc.o + else + PRELUDE = $(NDK_LIBC)/imports/libcpre.gcc.o + endif + else + PRELUDE = $(NDK_CLIB)/imports/clibpre.gcc.o + # to avoid the __init_* / __deinit_* woes don't use prelude from NDK + # http://www.gknw.net/development/mk_nlm/gcc_pre.zip + # PRELUDE = $(NDK_ROOT)/pre/prelude.o + CFLAGS += -include $(NDKBASE)/nlmconv/genlm.h + endif +endif + +NDK_ROOT = $(NDKBASE)/ndk +ifndef NDK_CLIB +NDK_CLIB = $(NDK_ROOT)/nwsdk +endif +ifndef NDK_LIBC +NDK_LIBC = $(NDK_ROOT)/libc +endif +ifndef NDK_LDAP +NDK_LDAP = $(NDK_ROOT)/cldapsdk/netware +endif +CURL_INC = ../include +CURL_LIB = ../lib + +INCLUDES = -I$(CURL_INC) -I$(CURL_LIB) + +ifeq ($(findstring -static,$(CFG)),-static) +LINK_STATIC = 1 +endif +ifeq ($(findstring -ares,$(CFG)),-ares) +WITH_ARES = 1 +endif +ifeq ($(findstring -rtmp,$(CFG)),-rtmp) +WITH_RTMP = 1 +WITH_SSL = 1 +WITH_ZLIB = 1 +endif +ifeq ($(findstring -ssh2,$(CFG)),-ssh2) +WITH_SSH2 = 1 +WITH_SSL = 1 +WITH_ZLIB = 1 +endif +ifeq ($(findstring -ssl,$(CFG)),-ssl) +WITH_SSL = 1 +ifeq ($(findstring -srp,$(CFG)),-srp) +ifeq "$(wildcard $(OPENSSL_PATH)/outinc_nw_$(LIBARCH_L)/openssl/srp.h)" "$(OPENSSL_PATH)/outinc_nw_$(LIBARCH_L)/openssl/srp.h" +WITH_SRP = 1 +endif +endif +endif +ifeq ($(findstring -zlib,$(CFG)),-zlib) +WITH_ZLIB = 1 +endif +ifeq ($(findstring -idn,$(CFG)),-idn) +WITH_IDN = 1 +endif +ifeq ($(findstring -nghttp2,$(CFG)),-nghttp2) +WITH_NGHTTP2 = 1 +endif +ifeq ($(findstring -ipv6,$(CFG)),-ipv6) +ENABLE_IPV6 = 1 +endif + +ifdef WITH_ARES + INCLUDES += -I$(LIBCARES_PATH) + LDLIBS += $(LIBCARES_PATH)/libcares.$(LIBEXT) +endif +ifdef WITH_SSH2 + INCLUDES += -I$(LIBSSH2_PATH)/include +ifdef LINK_STATIC + LDLIBS += $(LIBSSH2_PATH)/nw/libssh2.$(LIBEXT) +else + MODULES += libssh2.nlm + IMPORTS += @$(LIBSSH2_PATH)/nw/libssh2.imp +endif +endif +ifdef WITH_RTMP + INCLUDES += -I$(LIBRTMP_PATH) + LDLIBS += $(LIBRTMP_PATH)/librtmp/librtmp.$(LIBEXT) +endif +ifdef WITH_SSL + INCLUDES += -I$(OPENSSL_PATH)/outinc_nw_$(LIBARCH_L) + LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/ssl.$(LIBEXT) + LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/crypto.$(LIBEXT) + IMPORTS += GetProcessSwitchCount RunningProcess + INSTDEP += ca-bundle.crt +else +endif +ifdef WITH_ZLIB + INCLUDES += -I$(ZLIB_PATH) + ifdef LINK_STATIC + LDLIBS += $(ZLIB_PATH)/nw/$(LIBARCH)/libz.$(LIBEXT) + else + MODULES += libz.nlm + IMPORTS += @$(ZLIB_PATH)/nw/$(LIBARCH)/libz.imp + endif +endif +ifdef WITH_IDN + INCLUDES += -I$(LIBIDN_PATH)/include + LDLIBS += $(LIBIDN_PATH)/lib/libidn.$(LIBEXT) +endif +ifdef WITH_NGHTTP2 + INCLUDES += -I$(NGHTTP2_PATH)/include + LDLIBS += $(NGHTTP2_PATH)/lib/libnghttp2.$(LIBEXT) +endif + +ifeq ($(LIBARCH),LIBC) + INCLUDES += -I$(NDK_LIBC)/include + # INCLUDES += -I$(NDK_LIBC)/include/nks + # INCLUDES += -I$(NDK_LIBC)/include/winsock + CFLAGS += -D_POSIX_SOURCE +else + INCLUDES += -I$(NDK_CLIB)/include/nlm + # INCLUDES += -I$(NDK_CLIB)/include/nlm/obsolete + # INCLUDES += -I$(NDK_CLIB)/include +endif +ifndef DISABLE_LDAP + INCLUDES += -I$(NDK_LDAP)/$(LIBARCH_L)/inc +endif +CFLAGS += $(INCLUDES) + +ifeq ($(MTSAFE),YES) + XDCOPT = -n +endif +ifeq ($(MTSAFE),NO) + XDCOPT = -u +endif +ifdef XDCOPT + XDCDATA = $(OBJDIR)/$(TARGET).xdc +endif + +ifeq ($(findstring /sh,$(SHELL)),/sh) +DL = ' +DS = / +PCT = % +#-include $(NDKBASE)/nlmconv/ncpfs.inc +else +DS = \\ +PCT = %% +endif + +# Makefile.inc provides the CSOURCES and HHEADERS defines +include Makefile.inc + +OBJS := $(patsubst %.c,$(OBJDIR)/%.o,$(strip $(notdir $(CSOURCES)))) $(OBJDIR)/nwos.o + +OBJL = $(OBJS) $(OBJDIR)/nwlib.o $(LDLIBS) + +vpath %.c . vauth vtls + +all: lib nlm + +nlm: prebuild $(TARGET).nlm + +lib: prebuild $(TARGET).$(LIBEXT) + +prebuild: $(OBJDIR) $(OBJDIR)/version.inc curl_config.h + +$(OBJDIR)/%.o: %.c +# @echo Compiling $< + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJDIR)/version.inc: $(CURL_INC)/curl/curlver.h $(OBJDIR) + @echo Creating $@ + @$(AWK) -f ../packages/NetWare/get_ver.awk $< > $@ + +install: $(INSTDIR) all $(INSTDEP) + @$(CP) $(TARGET).nlm $(INSTDIR) + @$(CP) $(TARGET).$(LIBEXT) $(INSTDIR) + @$(CP) ../CHANGES $(INSTDIR) + @$(CP) ../COPYING $(INSTDIR) + @$(CP) ../README $(INSTDIR) + @$(CP) ../RELEASE-NOTES $(INSTDIR) +ifdef WITH_SSL + @-$(CP) ca-bundle.crt $(INSTDIR)/ca-bundle.crt +endif + +clean: + -$(RM) curl_config.h + -$(RM) -r $(OBJDIR) + +distclean vclean: clean + -$(RM) $(TARGET).$(LIBEXT) $(TARGET).nlm $(TARGET).imp + -$(RM) certdata.txt ca-bundle.crt + +$(OBJDIR) $(INSTDIR): + @$(MKDIR) $@ + +$(TARGET).$(LIBEXT): $(OBJS) + @echo Creating $@ + @-$(RM) $@ + @$(AR) $(ARFLAGS) $@ $^ +ifdef RANLIB + @$(RANLIB) $@ +endif + +$(TARGET).nlm: $(OBJDIR)/$(TARGET).def $(OBJL) $(EXPORTF) $(XDCDATA) + @echo Linking $@ + @-$(RM) $@ + @$(LD) $(LDFLAGS) $< + +$(OBJDIR)/%.xdc: Makefile.netware + @echo Creating $@ + @$(MPKXDC) $(XDCOPT) $@ + +$(OBJDIR)/%.def: Makefile.netware + @echo $(DL)# DEF file for linking with $(LD)$(DL) > $@ + @echo $(DL)# Do not edit this file - it is created by make!$(DL) >> $@ + @echo $(DL)# All your changes will be lost!!$(DL) >> $@ + @echo $(DL)#$(DL) >> $@ + @echo $(DL)copyright "$(COPYR)"$(DL) >> $@ + @echo $(DL)description "$(DESCR)"$(DL) >> $@ + @echo $(DL)version $(VERSION)$(DL) >> $@ +ifdef NLMTYPE + @echo $(DL)type $(NLMTYPE)$(DL) >> $@ +endif +ifdef STACK + @echo $(DL)stack $(STACK)$(DL) >> $@ +endif +ifdef SCREEN + @echo $(DL)screenname "$(SCREEN)"$(DL) >> $@ +else + @echo $(DL)screenname "DEFAULT"$(DL) >> $@ +endif +ifneq ($(DB),NDEBUG) + @echo $(DL)debug$(DL) >> $@ +endif + @echo $(DL)threadname "$(TARGET)"$(DL) >> $@ +ifdef XDCDATA + @echo $(DL)xdcdata $(XDCDATA)$(DL) >> $@ +endif + @echo $(DL)flag_on 64$(DL) >> $@ +ifeq ($(LIBARCH),CLIB) + @echo $(DL)start _Prelude$(DL) >> $@ + @echo $(DL)exit _Stop$(DL) >> $@ + @echo $(DL)import @$(NDK_CLIB)/imports/clib.imp$(DL) >> $@ + @echo $(DL)import @$(NDK_CLIB)/imports/threads.imp$(DL) >> $@ + @echo $(DL)import @$(NDK_CLIB)/imports/nlmlib.imp$(DL) >> $@ + @echo $(DL)import @$(NDK_CLIB)/imports/socklib.imp$(DL) >> $@ + @echo $(DL)module clib$(DL) >> $@ +ifndef DISABLE_LDAP + @echo $(DL)import @$(NDK_LDAP)/clib/imports/ldapsdk.imp$(DL) >> $@ + @echo $(DL)import @$(NDK_LDAP)/clib/imports/ldapssl.imp$(DL) >> $@ +# @echo $(DL)import @$(NDK_LDAP)/clib/imports/ldapx.imp$(DL) >> $@ + @echo $(DL)module ldapsdk ldapssl$(DL) >> $@ +endif +else +ifeq ($(POSIXFL),1) + @echo $(DL)flag_on 4194304$(DL) >> $@ +endif + @echo $(DL)pseudopreemption$(DL) >> $@ +ifeq ($(findstring posixpre,$(PRELUDE)),posixpre) + @echo $(DL)start POSIX_Start$(DL) >> $@ + @echo $(DL)exit POSIX_Stop$(DL) >> $@ + @echo $(DL)check POSIX_CheckUnload$(DL) >> $@ +else + @echo $(DL)start _LibCPrelude$(DL) >> $@ + @echo $(DL)exit _LibCPostlude$(DL) >> $@ + @echo $(DL)check _LibCCheckUnload$(DL) >> $@ +endif + @echo $(DL)import @$(NDK_LIBC)/imports/libc.imp$(DL) >> $@ + @echo $(DL)import @$(NDK_LIBC)/imports/netware.imp$(DL) >> $@ + @echo $(DL)module libc$(DL) >> $@ +ifndef DISABLE_LDAP + @echo $(DL)import @$(NDK_LDAP)/libc/imports/lldapsdk.imp$(DL) >> $@ + @echo $(DL)import @$(NDK_LDAP)/libc/imports/lldapssl.imp$(DL) >> $@ +# @echo $(DL)import @$(NDK_LDAP)/libc/imports/lldapx.imp$(DL) >> $@ + @echo $(DL)module lldapsdk lldapssl$(DL) >> $@ +endif +endif +ifdef MODULES + @echo $(DL)module $(MODULES)$(DL) >> $@ +endif +ifdef EXPORTS + @echo $(DL)export $(EXPORTS)$(DL) >> $@ +endif +ifdef IMPORTS + @echo $(DL)import $(IMPORTS)$(DL) >> $@ +endif +ifeq ($(findstring nlmconv,$(LD)),nlmconv) + @echo $(DL)input $(PRELUDE)$(DL) >> $@ + @echo $(DL)input $(OBJL)$(DL) >> $@ +#ifdef LDLIBS +# @echo $(DL)input $(LDLIBS)$(DL) >> $@ +#endif + @echo $(DL)output $(TARGET).nlm$(DL) >> $@ +endif + +curl_config.h: Makefile.netware + @echo Creating $@ + @echo $(DL)/* $@ for NetWare target.$(DL) > $@ + @echo $(DL)** Do not edit this file - it is created by make!$(DL) >> $@ + @echo $(DL)** All your changes will be lost!!$(DL) >> $@ + @echo $(DL)*/$(DL) >> $@ + @echo $(DL)#ifndef NETWARE$(DL) >> $@ + @echo $(DL)#error This $(notdir $@) is created for NetWare platform!$(DL) >> $@ + @echo $(DL)#endif$(DL) >> $@ + @echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@ + @echo $(DL)#define PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.haxx.se/mail/"$(DL) >> $@ +ifeq ($(LIBARCH),CLIB) + @echo $(DL)#define OS "i586-pc-clib-NetWare"$(DL) >> $@ + @echo $(DL)#define NETDB_USE_INTERNET 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRICMP 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRNICMP 1$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_ARG1 int$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_ARG2 char *$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_ARG3 int$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_ARG4 int$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_RETV int$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG1 int$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG2 char$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG3 int$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG4 int$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG5 struct sockaddr$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG6 int$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_RETV int$(DL) >> $@ + @echo $(DL)#define SEND_QUAL_ARG2$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_ARG1 int$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_ARG2 char *$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_ARG3 int$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_RETV int$(DL) >> $@ + @echo $(DL)#define SIZEOF_SIZE_T 4$(DL) >> $@ + @echo $(DL)#define pressanykey PressAnyKeyToContinue$(DL) >> $@ +else + @echo $(DL)#define OS "i586-pc-libc-NetWare"$(DL) >> $@ + @echo $(DL)#define HAVE_FTRUNCATE 1$(DL) >> $@ + @echo $(DL)#define HAVE_GETTIMEOFDAY 1$(DL) >> $@ + @echo $(DL)#define HAVE_INTTYPES_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_LONGLONG 1$(DL) >> $@ + @echo $(DL)#define HAVE_STDINT_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRCASECMP 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRLCAT 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRLCPY 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRTOLL 1$(DL) >> $@ + @echo $(DL)#define HAVE_SYS_PARAM_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_SYS_SELECT_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_TERMIOS_H 1$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_ARG1 int$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_ARG2 void *$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_ARG3 size_t$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_ARG4 int$(DL) >> $@ + @echo $(DL)#define RECV_TYPE_RETV ssize_t$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG1 int$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG2 void$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG3 size_t$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG4 int$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG5 struct sockaddr$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG6 size_t$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_RETV ssize_t$(DL) >> $@ + @echo $(DL)#define RECVFROM_TYPE_ARG2_IS_VOID 1$(DL) >> $@ + @echo $(DL)#define SEND_QUAL_ARG2$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_ARG1 int$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_ARG2 void *$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_ARG3 size_t$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ + @echo $(DL)#define SEND_TYPE_RETV ssize_t$(DL) >> $@ + @echo $(DL)#define SIZEOF_OFF_T 8$(DL) >> $@ + @echo $(DL)#define SIZEOF_SIZE_T 8$(DL) >> $@ + @echo $(DL)#define _LARGEFILE 1$(DL) >> $@ +ifdef ENABLE_IPV6 + @echo $(DL)#define ENABLE_IPV6 1$(DL) >> $@ + @echo $(DL)#define HAVE_AF_INET6 1$(DL) >> $@ + @echo $(DL)#define HAVE_PF_INET6 1$(DL) >> $@ + @echo $(DL)#define HAVE_FREEADDRINFO 1$(DL) >> $@ + @echo $(DL)#define HAVE_GETADDRINFO 1$(DL) >> $@ + @echo $(DL)#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRUCT_ADDRINFO 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRUCT_IN6_ADDR 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRUCT_SOCKADDR_IN6 1$(DL) >> $@ + @echo $(DL)#define SIZEOF_STRUCT_IN6_ADDR 16$(DL) >> $@ +endif +endif + @echo $(DL)#define USE_MANUAL 1$(DL) >> $@ + @echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_ERRNO_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_ERR_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_FCNTL_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_GETHOSTBYADDR 1$(DL) >> $@ + @echo $(DL)#define HAVE_GETHOSTBYNAME 1$(DL) >> $@ + @echo $(DL)#define HAVE_GETPROTOBYNAME 1$(DL) >> $@ + @echo $(DL)#define HAVE_GMTIME_R 1$(DL) >> $@ + @echo $(DL)#define HAVE_INET_ADDR 1$(DL) >> $@ + @echo $(DL)#define HAVE_IOCTL 1$(DL) >> $@ + @echo $(DL)#define HAVE_IOCTL_FIONBIO 1$(DL) >> $@ + @echo $(DL)#define HAVE_LL 1$(DL) >> $@ + @echo $(DL)#define HAVE_LOCALE_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_LOCALTIME_R 1$(DL) >> $@ + @echo $(DL)#define HAVE_MALLOC_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_NETINET_IN_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_RECV 1$(DL) >> $@ + @echo $(DL)#define HAVE_RECVFROM 1$(DL) >> $@ + @echo $(DL)#define HAVE_SELECT 1$(DL) >> $@ + @echo $(DL)#define HAVE_SEND 1$(DL) >> $@ + @echo $(DL)#define HAVE_SETJMP_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_SETLOCALE 1$(DL) >> $@ + @echo $(DL)#define HAVE_SIGNAL 1$(DL) >> $@ + @echo $(DL)#define HAVE_SIGNAL_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_SIG_ATOMIC_T 1$(DL) >> $@ + @echo $(DL)#define HAVE_SOCKET 1$(DL) >> $@ + @echo $(DL)#define HAVE_STDLIB_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRDUP 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRFTIME 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRING_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRSTR 1$(DL) >> $@ + @echo $(DL)#define HAVE_STRUCT_TIMEVAL 1$(DL) >> $@ + @echo $(DL)#define HAVE_SYS_IOCTL_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_SYS_STAT_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_SYS_TIME_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_TIME_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_UNAME 1$(DL) >> $@ + @echo $(DL)#define HAVE_UNISTD_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_UTIME 1$(DL) >> $@ + @echo $(DL)#define HAVE_UTIME_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_WRITEV 1$(DL) >> $@ + @echo $(DL)#define RETSIGTYPE void$(DL) >> $@ + @echo $(DL)#define SIZEOF_INT 4$(DL) >> $@ + @echo $(DL)#define SIZEOF_SHORT 2$(DL) >> $@ + @echo $(DL)#define SIZEOF_STRUCT_IN_ADDR 4$(DL) >> $@ + @echo $(DL)#define STDC_HEADERS 1$(DL) >> $@ + @echo $(DL)#define TIME_WITH_SYS_TIME 1$(DL) >> $@ +ifdef DISABLE_LDAP + @echo $(DL)#define CURL_DISABLE_LDAP 1$(DL) >> $@ +else + @echo $(DL)#define CURL_HAS_NOVELL_LDAPSDK 1$(DL) >> $@ +ifndef DISABLE_LDAPS + @echo $(DL)#define HAVE_LDAP_SSL 1$(DL) >> $@ +endif + @echo $(DL)#define HAVE_LDAP_SSL_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_LDAP_URL_PARSE 1$(DL) >> $@ +endif +ifdef NW_WINSOCK + @echo $(DL)#define HAVE_CLOSESOCKET 1$(DL) >> $@ +else + @echo $(DL)#define USE_BSD_SOCKETS 1$(DL) >> $@ + @echo $(DL)#define HAVE_SYS_TYPES_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_SYS_SOCKET_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_SYS_SOCKIO_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_NETDB_H 1$(DL) >> $@ +endif +ifdef WITH_ARES + @echo $(DL)#define USE_ARES 1$(DL) >> $@ +endif +ifdef WITH_ZLIB + @echo $(DL)#define HAVE_ZLIB_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_LIBZ 1$(DL) >> $@ +endif +ifdef WITH_SSL + @echo $(DL)#define USE_OPENSSL 1$(DL) >> $@ + @echo $(DL)#define HAVE_OPENSSL_X509_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_OPENSSL_SSL_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_OPENSSL_RSA_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_OPENSSL_PEM_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_OPENSSL_ERR_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_OPENSSL_CRYPTO_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_OPENSSL_ENGINE_H 1$(DL) >> $@ + @echo $(DL)#define HAVE_LIBSSL 1$(DL) >> $@ + @echo $(DL)#define HAVE_LIBCRYPTO 1$(DL) >> $@ + @echo $(DL)#define OPENSSL_NO_KRB5 1$(DL) >> $@ +ifdef WITH_SRP + @echo $(DL)#define USE_TLS_SRP 1$(DL) >> $@ +endif +ifdef WITH_SPNEGO + @echo $(DL)#define HAVE_SPNEGO 1$(DL) >> $@ +endif +else +endif +ifdef WITH_SSH2 + @echo $(DL)#define USE_LIBSSH2 1$(DL) >> $@ + @echo $(DL)#define HAVE_LIBSSH2_H 1$(DL) >> $@ +endif +ifdef WITH_IDN + @echo $(DL)#define HAVE_LIBIDN 1$(DL) >> $@ + @echo $(DL)#define HAVE_TLD_H 1$(DL) >> $@ +endif +ifdef WITH_RTMP + @echo $(DL)#define USE_LIBRTMP 1$(DL) >> $@ +endif +ifdef WITH_NGHTTP2 + @echo $(DL)#define USE_NGHTTP2 1$(DL) >> $@ +endif + @echo $(DL)#ifdef __GNUC__$(DL) >> $@ + @echo $(DL)#define HAVE_VARIADIC_MACROS_GCC 1$(DL) >> $@ + @echo $(DL)#else$(DL) >> $@ + @echo $(DL)#define HAVE_VARIADIC_MACROS_C99 1$(DL) >> $@ + @echo $(DL)#endif$(DL) >> $@ +ifdef CABUNDLE + @echo $(DL)#define CURL_CA_BUNDLE "$(CABUNDLE)"$(DL) >> $@ +else + @echo $(DL)#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")$(DL) >> $@ +endif + +$(EXPORTF): $(CURL_INC)/curl/curl.h $(CURL_INC)/curl/easy.h $(CURL_INC)/curl/multi.h $(CURL_INC)/curl/mprintf.h + @echo Creating $@ + @$(AWK) -f ../packages/NetWare/get_exp.awk $^ > $@ + +FORCE: ; + +info: $(OBJDIR)/version.inc + @echo Configured to build $(TARGET) with these options: + @echo libarchitecture: $(LIBARCH) + @echo curl version: $(LIBCURL_VERSION_STR) + @echo compiler/linker: $(CC) / $(LD) +ifdef CABUNDLE + @echo ca-bundle path: $(CABUNDLE) +endif +ifdef WITH_SSL + @echo SSL support: enabled (OpenSSL) +else + @echo SSL support: no +endif +ifdef WITH_SRP + @echo SRP support: enabled +else + @echo SRP support: no +endif +ifdef WITH_SSH2 + @echo SSH2 support: enabled (libssh2) +else + @echo SSH2 support: no +endif +ifdef WITH_ZLIB + @echo zlib support: enabled +else + @echo zlib support: no +endif +ifdef WITH_NGHTTP2 + @echo http2 support: enabled +else + @echo http2 support: no +endif +ifdef WITH_ARES + @echo c-ares support: enabled +else + @echo c-ares support: no +endif +ifdef ENABLE_IPV6 + @echo IPv6 support: enabled +else + @echo IPv6 support: no +endif + +$(LIBCARES_PATH)/libcares.$(LIBEXT): + $(MAKE) -C $(LIBCARES_PATH) -f Makefile.netware lib + +ca-bundle.crt: mk-ca-bundle.pl + @echo Creating $@ + @-$(PERL) $< -b -n $@ diff --git a/libcurl/lib/Makefile.vxworks b/libcurl/lib/Makefile.vxworks new file mode 100644 index 0000000..7ff197f --- /dev/null +++ b/libcurl/lib/Makefile.vxworks @@ -0,0 +1,177 @@ +#***************************************************************************** +# +# +#Filename : Makefile.vxworks +#Description: makefile to be used in order to compile libcurl for VxWoorks 6.3. +# +#How to use: +# 1. Adjust environment variables at the file beginning +# 2. Open the Command Prompt window and change directory ('cd') +# into the 'lib' folder +# 3. Add /bin folder to the PATH environment variable +# For example type 'set PATH=C:/embedded/cygwin/bin;%PATH%' +# 4. Build the library by typing 'make -f ./Makefile.vxworks' +# As a result the libcurl.a should be created in the 'lib' folder. +# To clean package use 'make -f ./Makefile.vxworks clean' +#Requirements: +# 1. WinXP machine +# 2. Full CYGWIN installation (open source) with GNU make version +# v3.78 or higher +# 3. WindRiver Workbench with vxWorks 6.3 (commercial) +#***************************************************************************** + +# ---------------------------------------------------------------------- +# Environment +# ---------------------------------------------------------------------- + +export WIND_HOME := C:/embedded/Workbench2.5.0.1 +export WIND_BASE := $(WIND_HOME)/vxworks-6.3 +export WIND_HOST_TYPE := x86-win32 + +# BUILD_TYE:= | (build with debugging info or optimized) +BUILD_TYPE := debug +USER_CFLAGS:= + +# directories where to seek for includes and libraries +OPENSSL_INC := D:/libraries/openssl/openssl-0.9.8zc-vxWorks6.3/include +OPENSSL_LIB := D:/libraries/openssl/openssl-0.9.8zc-vxWorks6.3 +ZLIB_INC := D:/libraries/zlib/zlib-1.2.8-VxWorks6.3/zlib-1.2.8 +ZLIB_LIB := D:/libraries/zlib/zlib-1.2.8-VxWorks6.3/binaries/vxworks_3.1_gnu/Debug/lib +ARES_INC := +ARES_LIB := + + +# ---------------------------------------------------------------------- +# Compiler +# ---------------------------------------------------------------------- + +CC := ccppc +AR := arppc +LINK := ccppc +CFLAGS := -D__GNUC__ -D__ppc__ -msoft-float -fno-builtin -mcpu=604 -mlongcall -DCPU=PPC604 -D_GNU_TOOL -Wall -W -Winline $(USER_CFLAGS) +LDFLAGS := -nostdlib -Wl,-i -Wl,-X +INCLUDE_FLAG := -I +C_DEBUGFLAG := -g +C_OPTFLAG := -O2 +COMPILE_ONLY_FLAG := -c +OBJ_EXTENSION := .o +CC_OBJ_OUTPUT = -o $@ +ARFLAGS := -rc +LIBS_FLAG := -l +LIBS_DIRFLAG:= -L +LD_DEBUGFLAG := $(C_DEBUGFLAG) +EXECUTE_EXTENSION := .out +TOOL_CHAIN_BIN := $(WIND_HOME)/gnu/3.4.4-vxworks-6.3/$(WIND_HOST_TYPE)/bin/ + +# ---------------------------------------------------------------------- + +# Add -DINET6 if the OS kernel image was built with IPv6 support +# CFLAGS += -DINET6 + +# Set up compiler and linker flags for debug or optimization +ifeq ($(BUILD_TYPE), debug) +CFLAGS += $(C_DEBUGFLAG) +LDFLAGS += $(LD_DEBUGFLAG) +else +CFLAGS += $(C_OPTFLAG) +endif + +# ---------------------------------------------------------------------- + +# Main Makefile and possible sub-make files +MAKEFILES := Makefile.vxworks + +# List of external include directories +#----- +# IMPORTANT: include OPENSSL directories before system +# in order to prevent WindRiver OpenSSL to be used. +#----- +INCLUDE_DIRS := ../include $(OPENSSL_INC) $(ZLIB_INC) $(ARES_INC) $(WIND_BASE)/target/h $(WIND_BASE)/target/h/wrn/coreip + +# List of external libraries and their directories +LIBS_LIST := . +LIB_DIRS := . +ifneq ($(OPENSSL_LIB), ) +LIBS_LIST += crypto ssl +LIB_DIRS += $(OPENSSL_LIB) +endif +ifneq ($(ZLIB_LIB), ) +LIBS_LIST += z +LIB_DIRS += $(ZLIB_LIB) +endif +ifneq ($(ARES_LIB), ) +LIBS_LIST += ares +LIB_DIRS += $(ARES_LIB) +endif + +# Add include and library directories and libraries +CFLAGS += $(INCLUDE_DIRS:%=$(INCLUDE_FLAG)%) +LDFLAGS += $(LIB_DIRS:%=$(LIBS_DIRFLAG)%) + +# List of targets to make for libs target +LIBS_TARGET_LIST := libcurl.a + +# List of execuatble applications to make in addition to libs for all target +EXE_TARGET_LIST := + +# Support for echoing rules +# If ECHORULES variable was set (for example, using 'make' command line) +# some shell commands in the rules will be echoed +ifneq ($(strip $(findstring $(ECHORULES), yes YES 1 true TRUE)),) +_@_ := +else +_@_ := @ +endif + +# Directory to hold compilation intermediate files +TMP_DIR := tmp + +# Get sources and headers to be compiled +include Makefile.inc + +# List of headers +INCLUDE_FILES := $(HHEADERS) +INCLUDE_FILES += $(shell find ../include -name \*.h) + +# List of sources +OBJLIST := $(CSOURCES:%.c=$(TMP_DIR)/%$(OBJ_EXTENSION)) + + +# ---------------------------------------------------------------------- + +#### default rule +# It should be first rule in this file +.PHONY: default +default: libcurl.a + +#### Compiling C files +$(TMP_DIR)/%$(OBJ_EXTENSION): %.c $(MAKEFILES) + @echo Compiling C file $< $(ECHO_STDOUT) + @[ -d $(@D) ] || mkdir -p $(@D) + $(_@_) $(TOOL_CHAIN_BIN)$(CC) $(COMPILE_ONLY_FLAG) $(CFLAGS) $< $(CC_OBJ_OUTPUT) + +#### Creating library +$(LIBS_TARGET_LIST): $(INCLUDE_FILES) $(MAKEFILES) $(OBJLIST) + @echo Creating library $@ $(ECHO_STDOUT) + $(_@_) [ -d $(@D) ] || mkdir -p $(@D) + $(_@_) rm -f $@ + $(_@_) $(TOOL_CHAIN_BIN)$(AR) $(ARFLAGS) $@ $(filter %$(OBJ_EXTENSION), $^) + +#### Creating application +$(EXE_TARGET_LIST): $(INCLUDE_FILES) $(MAKEFILES) $(LIBS_TARGET_LIST) + @echo Creating application $@ + @[ -d $(@D) ] || mkdir -p $(@D) + $(_@_) $(TOOL_CHAIN_BIN)$(LINK) $(CC_OBJ_OUTPUT) $($(@)_EXE_OBJ_LIST) $(LDFLAGS) $($(@)_EXE_LIBS_NEEDED:%=$(LIBS_FLAG)%) $(LIBS_LIST:%=$(LIBS_FLAG)%) $(USER_LIBS_LIST) $(USER_LIBS_LIST) + +#### Master Targets +libs: $(LIBS_TARGET_LIST) + @echo All libs made. + +all: $(LIBS_TARGET_LIST) $(EXE_TARGET_LIST) $(INCLUDE_TARGET_LIST) + @echo All targets made. + +# Clean up +.PHONY: clean +clean: + $(_@_) rm -rf $(TMP_DIR) + @echo libcurl was cleaned. diff --git a/libcurl/lib/altsvc.c b/libcurl/lib/altsvc.c new file mode 100644 index 0000000..85a4e01 --- /dev/null +++ b/libcurl/lib/altsvc.c @@ -0,0 +1,569 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + * The Alt-Svc: header is defined in RFC 7838: + * https://tools.ietf.org/html/rfc7838 + */ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include +#include "urldata.h" +#include "altsvc.h" +#include "curl_get_line.h" +#include "strcase.h" +#include "parsedate.h" +#include "sendf.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define MAX_ALTSVC_LINE 4095 +#define MAX_ALTSVC_DATELENSTR "64" +#define MAX_ALTSVC_DATELEN 64 +#define MAX_ALTSVC_HOSTLENSTR "512" +#define MAX_ALTSVC_HOSTLEN 512 +#define MAX_ALTSVC_ALPNLENSTR "10" +#define MAX_ALTSVC_ALPNLEN 10 + +static enum alpnid alpn2alpnid(char *name) +{ + if(strcasecompare(name, "h1")) + return ALPN_h1; + if(strcasecompare(name, "h2")) + return ALPN_h2; + if(strcasecompare(name, "h2c")) + return ALPN_h2c; + if(strcasecompare(name, "h3")) + return ALPN_h3; + return ALPN_none; /* unknown, probably rubbish input */ +} + +/* Given the ALPN ID, return the name */ +const char *Curl_alpnid2str(enum alpnid id) +{ + switch(id) { + case ALPN_h1: + return "h1"; + case ALPN_h2: + return "h2"; + case ALPN_h2c: + return "h2c"; + case ALPN_h3: + return "h3"; + default: + return ""; /* bad */ + } +} + + +static void altsvc_free(struct altsvc *as) +{ + free(as->srchost); + free(as->dsthost); + free(as); +} + +static struct altsvc *altsvc_createid(const char *srchost, + const char *dsthost, + enum alpnid srcalpnid, + enum alpnid dstalpnid, + unsigned int srcport, + unsigned int dstport) +{ + struct altsvc *as = calloc(sizeof(struct altsvc), 1); + if(!as) + return NULL; + + as->srchost = strdup(srchost); + if(!as->srchost) + goto error; + as->dsthost = strdup(dsthost); + if(!as->dsthost) + goto error; + + as->srcalpnid = srcalpnid; + as->dstalpnid = dstalpnid; + as->srcport = curlx_ultous(srcport); + as->dstport = curlx_ultous(dstport); + + return as; + error: + altsvc_free(as); + return NULL; +} + +static struct altsvc *altsvc_create(char *srchost, + char *dsthost, + char *srcalpn, + char *dstalpn, + unsigned int srcport, + unsigned int dstport) +{ + enum alpnid dstalpnid = alpn2alpnid(dstalpn); + enum alpnid srcalpnid = alpn2alpnid(srcalpn); + if(!srcalpnid || !dstalpnid) + return NULL; + return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid, + srcport, dstport); +} + +/* only returns SERIOUS errors */ +static CURLcode altsvc_add(struct altsvcinfo *asi, char *line) +{ + /* Example line: + h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1 + */ + char srchost[MAX_ALTSVC_HOSTLEN + 1]; + char dsthost[MAX_ALTSVC_HOSTLEN + 1]; + char srcalpn[MAX_ALTSVC_ALPNLEN + 1]; + char dstalpn[MAX_ALTSVC_ALPNLEN + 1]; + char date[MAX_ALTSVC_DATELEN + 1]; + unsigned int srcport; + unsigned int dstport; + unsigned int prio; + unsigned int persist; + int rc; + + rc = sscanf(line, + "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u " + "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u " + "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u", + srcalpn, srchost, &srcport, + dstalpn, dsthost, &dstport, + date, &persist, &prio); + if(9 == rc) { + struct altsvc *as; + time_t expires = curl_getdate(date, NULL); + as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport); + if(as) { + as->expires = expires; + as->prio = prio; + as->persist = persist ? 1 : 0; + Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); + asi->num++; /* one more entry */ + } + } + + return CURLE_OK; +} + +/* + * Load alt-svc entries from the given file. The text based line-oriented file + * format is documented here: + * https://github.com/curl/curl/wiki/QUIC-implementation + * + * This function only returns error on major problems that prevents alt-svc + * handling to work completely. It will ignore individual syntactical errors + * etc. + */ +static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) +{ + CURLcode result = CURLE_OK; + char *line = NULL; + FILE *fp = fopen(file, FOPEN_READTEXT); + if(fp) { + line = malloc(MAX_ALTSVC_LINE); + if(!line) + goto fail; + while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) { + char *lineptr = line; + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + if(*lineptr == '#') + /* skip commented lines */ + continue; + + altsvc_add(asi, lineptr); + } + free(line); /* free the line buffer */ + fclose(fp); + } + return result; + + fail: + free(line); + fclose(fp); + return CURLE_OUT_OF_MEMORY; +} + +/* + * Write this single altsvc entry to a single output line + */ + +static CURLcode altsvc_out(struct altsvc *as, FILE *fp) +{ + struct tm stamp; + CURLcode result = Curl_gmtime(as->expires, &stamp); + if(result) + return result; + + fprintf(fp, + "%s %s %u " + "%s %s %u " + "\"%d%02d%02d " + "%02d:%02d:%02d\" " + "%u %d\n", + Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport, + Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport, + stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, + stamp.tm_hour, stamp.tm_min, stamp.tm_sec, + as->persist, as->prio); + return CURLE_OK; +} + +/* ---- library-wide functions below ---- */ + +/* + * Curl_altsvc_init() creates a new altsvc cache. + * It returns the new instance or NULL if something goes wrong. + */ +struct altsvcinfo *Curl_altsvc_init(void) +{ + struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1); + if(!asi) + return NULL; + Curl_llist_init(&asi->list, NULL); + + /* set default behavior */ + asi->flags = CURLALTSVC_H1 +#ifdef USE_NGHTTP2 + | CURLALTSVC_H2 +#endif +#ifdef USE_HTTP3 + | CURLALTSVC_H3 +#endif + ; + return asi; +} + +/* + * Curl_altsvc_load() loads alt-svc from file. + */ +CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file) +{ + CURLcode result; + DEBUGASSERT(asi); + result = altsvc_load(asi, file); + return result; +} + +/* + * Curl_altsvc_ctrl() passes on the external bitmask. + */ +CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl) +{ + DEBUGASSERT(asi); + if(!ctrl) + /* unexpected */ + return CURLE_BAD_FUNCTION_ARGUMENT; + asi->flags = ctrl; + return CURLE_OK; +} + +/* + * Curl_altsvc_cleanup() frees an altsvc cache instance and all associated + * resources. + */ +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + if(altsvc) { + for(e = altsvc->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + altsvc_free(as); + } + free(altsvc); + } +} + +/* + * Curl_altsvc_save() writes the altsvc cache to a file. + */ +CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + CURLcode result = CURLE_OK; + FILE *out; + + if(!altsvc) + /* no cache activated */ + return CURLE_OK; + + if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0]) + /* marked as read-only or zero length file name */ + return CURLE_OK; + out = fopen(file, FOPEN_WRITETEXT); + if(!out) + return CURLE_WRITE_ERROR; + fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n" + "# This file was generated by libcurl! Edit at your own risk.\n", + out); + for(e = altsvc->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + result = altsvc_out(as, out); + if(result) + break; + } + fclose(out); + return result; +} + +static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen) +{ + size_t len; + const char *protop; + const char *p = *ptr; + while(*p && ISBLANK(*p)) + p++; + protop = p; + while(*p && ISALNUM(*p)) + p++; + len = p - protop; + + if(!len || (len >= buflen)) + return CURLE_BAD_FUNCTION_ARGUMENT; + memcpy(alpnbuf, protop, len); + alpnbuf[len] = 0; + *ptr = p; + return CURLE_OK; +} + +/* altsvc_flush() removes all alternatives for this source origin from the + list */ +static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid, + const char *srchost, unsigned short srcport) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + for(e = asi->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + if((srcalpnid == as->srcalpnid) && + (srcport == as->srcport) && + strcasecompare(srchost, as->srchost)) { + Curl_llist_remove(&asi->list, e, NULL); + altsvc_free(as); + asi->num--; + } + } +} + +#ifdef DEBUGBUILD +/* to play well with debug builds, we can *set* a fixed time this will + return */ +static time_t debugtime(void *unused) +{ + char *timestr = getenv("CURL_TIME"); + (void)unused; + if(timestr) { + unsigned long val = strtol(timestr, NULL, 10); + return (time_t)val; + } + return time(NULL); +} +#define time(x) debugtime(x) +#endif + +/* + * Curl_altsvc_parse() takes an incoming alt-svc response header and stores + * the data correctly in the cache. + * + * 'value' points to the header *value*. That's contents to the right of the + * header name. + */ +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *asi, const char *value, + enum alpnid srcalpnid, const char *srchost, + unsigned short srcport) +{ + const char *p = value; + size_t len; + enum alpnid dstalpnid = srcalpnid; /* the same by default */ + char namebuf[MAX_ALTSVC_HOSTLEN] = ""; + char alpnbuf[MAX_ALTSVC_ALPNLEN] = ""; + struct altsvc *as; + unsigned short dstport = srcport; /* the same by default */ + const char *semip; + time_t maxage = 24 * 3600; /* default is 24 hours */ + bool persist = FALSE; + CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); + if(result) + return result; + + DEBUGASSERT(asi); + + /* Flush all cached alternatives for this source origin, if any */ + altsvc_flush(asi, srcalpnid, srchost, srcport); + + /* "clear" is a magic keyword */ + if(strcasecompare(alpnbuf, "clear")) { + return CURLE_OK; + } + + /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives + but are set after the list on the line. Scan for the semicolons and get + those fields first! */ + semip = p; + do { + semip = strchr(semip, ';'); + if(semip) { + char option[32]; + unsigned long num; + char *end_ptr; + semip++; /* pass the semicolon */ + result = getalnum(&semip, option, sizeof(option)); + if(result) + break; + while(*semip && ISBLANK(*semip)) + semip++; + if(*semip != '=') + continue; + semip++; + num = strtoul(semip, &end_ptr, 10); + if(num < ULONG_MAX) { + if(strcasecompare("ma", option)) + maxage = num; + else if(strcasecompare("persist", option) && (num == 1)) + persist = TRUE; + } + semip = end_ptr; + } + } while(semip); + + do { + if(*p == '=') { + /* [protocol]="[host][:port]" */ + dstalpnid = alpn2alpnid(alpnbuf); + if(!dstalpnid) { + infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf); + return CURLE_OK; + } + p++; + if(*p == '\"') { + const char *dsthost; + p++; + if(*p != ':') { + /* host name starts here */ + const char *hostp = p; + while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-'))) + p++; + len = p - hostp; + if(!len || (len >= MAX_ALTSVC_HOSTLEN)) + return CURLE_BAD_FUNCTION_ARGUMENT; + memcpy(namebuf, hostp, len); + namebuf[len] = 0; + dsthost = namebuf; + } + else { + /* no destination name, use source host */ + dsthost = srchost; + } + if(*p == ':') { + /* a port number */ + char *end_ptr; + unsigned long port = strtoul(++p, &end_ptr, 10); + if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') { + infof(data, "Unknown alt-svc port number, ignoring...\n"); + return CURLE_OK; + } + p = end_ptr; + dstport = curlx_ultous(port); + } + if(*p++ != '\"') + return CURLE_BAD_FUNCTION_ARGUMENT; + as = altsvc_createid(srchost, dsthost, + srcalpnid, dstalpnid, + srcport, dstport); + if(as) { + /* The expires time also needs to take the Age: value (if any) into + account. [See RFC 7838 section 3.1] */ + as->expires = maxage + time(NULL); + as->persist = persist; + Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); + asi->num++; /* one more entry */ + infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport, + Curl_alpnid2str(dstalpnid)); + } + } + /* after the double quote there can be a comma if there's another + string or a semicolon if no more */ + if(*p == ',') { + /* comma means another alternative is presented */ + p++; + result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); + if(result) + /* failed to parse, but since we already did at least one host we + return OK */ + return CURLE_OK; + } + } + } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r')); + + return CURLE_OK; +} + +/* + * Return TRUE on a match + */ +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + time_t now = time(NULL); + DEBUGASSERT(asi); + DEBUGASSERT(srchost); + DEBUGASSERT(dsthost); + + for(e = asi->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + if(as->expires < now) { + /* an expired entry, remove */ + altsvc_free(as); + continue; + } + if((as->srcalpnid == srcalpnid) && + strcasecompare(as->srchost, srchost) && + as->srcport == srcport) { + /* match */ + *dstalpnid = as->dstalpnid; + *dsthost = as->dsthost; + *dstport = as->dstport; + return TRUE; + } + } + return FALSE; +} + +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ diff --git a/libcurl/lib/altsvc.h b/libcurl/lib/altsvc.h new file mode 100644 index 0000000..eefb45b --- /dev/null +++ b/libcurl/lib/altsvc.h @@ -0,0 +1,77 @@ +#ifndef HEADER_CURL_ALTSVC_H +#define HEADER_CURL_ALTSVC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include +#include "llist.h" + +enum alpnid { + ALPN_none, + ALPN_h1, + ALPN_h2, + ALPN_h2c, + ALPN_h3 +}; + +struct altsvc { + char *srchost; + char *dsthost; + unsigned short srcport; + unsigned short dstport; + enum alpnid srcalpnid; + enum alpnid dstalpnid; + time_t expires; + bool persist; + int prio; + struct curl_llist_element node; +}; + +struct altsvcinfo { + char *filename; + struct curl_llist list; /* list of entries */ + size_t num; /* number of alt-svc entries */ + long flags; /* the publicly set bitmask */ +}; + +const char *Curl_alpnid2str(enum alpnid id); +struct altsvcinfo *Curl_altsvc_init(void); +CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl); +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc); +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *altsvc, const char *value, + enum alpnid srcalpn, const char *srchost, + unsigned short srcport); +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport); +#else +/* disabled */ +#define Curl_altsvc_save(a,b) +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ +#endif /* HEADER_CURL_ALTSVC_H */ diff --git a/libcurl/lib/amigaos.c b/libcurl/lib/amigaos.c new file mode 100644 index 0000000..cf44bdc --- /dev/null +++ b/libcurl/lib/amigaos.c @@ -0,0 +1,95 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef __AMIGA__ +# include "amigaos.h" +# if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) +# include +# endif +# ifdef __libnix__ +# include +# endif +#endif + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef __AMIGA__ +#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) +struct Library *SocketBase = NULL; +extern int errno, h_errno; + +#ifdef __libnix__ +void __request(const char *msg); +#else +# define __request(msg) Printf(msg "\n\a") +#endif + +void Curl_amiga_cleanup() +{ + if(SocketBase) { + CloseLibrary(SocketBase); + SocketBase = NULL; + } +} + +bool Curl_amiga_init() +{ + if(!SocketBase) + SocketBase = OpenLibrary("bsdsocket.library", 4); + + if(!SocketBase) { + __request("No TCP/IP Stack running!"); + return FALSE; + } + + if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno, + SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl", + TAG_DONE)) { + __request("SocketBaseTags ERROR"); + return FALSE; + } + +#ifndef __libnix__ + atexit(Curl_amiga_cleanup); +#endif + + return TRUE; +} + +#ifdef __libnix__ +ADD2EXIT(Curl_amiga_cleanup, -50); +#endif + +#endif /* HAVE_PROTO_BSDSOCKET_H */ + +#ifdef USE_AMISSL +void Curl_amiga_X509_free(X509 *a) +{ + X509_free(a); +} +#endif /* USE_AMISSL */ +#endif /* __AMIGA__ */ + diff --git a/libcurl/lib/amigaos.h b/libcurl/lib/amigaos.h new file mode 100644 index 0000000..c776c9c --- /dev/null +++ b/libcurl/lib/amigaos.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_AMIGAOS_H +#define HEADER_CURL_AMIGAOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL) + +bool Curl_amiga_init(); +void Curl_amiga_cleanup(); + +#else + +#define Curl_amiga_init() 1 +#define Curl_amiga_cleanup() Curl_nop_stmt + +#endif + +#ifdef USE_AMISSL +#include +void Curl_amiga_X509_free(X509 *a); +#endif /* USE_AMISSL */ + +#endif /* HEADER_CURL_AMIGAOS_H */ + diff --git a/libcurl/lib/arpa_telnet.h b/libcurl/lib/arpa_telnet.h new file mode 100644 index 0000000..232680e --- /dev/null +++ b/libcurl/lib/arpa_telnet.h @@ -0,0 +1,108 @@ +#ifndef HEADER_CURL_ARPA_TELNET_H +#define HEADER_CURL_ARPA_TELNET_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET +/* + * Telnet option defines. Add more here if in need. + */ +#define CURL_TELOPT_BINARY 0 /* binary 8bit data */ +#define CURL_TELOPT_ECHO 1 /* just echo! */ +#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */ +#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */ +#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */ +#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */ +#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */ + +#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */ +#define CURL_NEW_ENV_VAR 0 +#define CURL_NEW_ENV_VALUE 1 + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* + * The telnet options represented as strings + */ +static const char * const telnetoptions[]= +{ + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", + "NAME", "STATUS", "TIMING MARK", "RCTE", + "NAOL", "NAOP", "NAOCRD", "NAOHTS", + "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", + "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", + "TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", + "TTYLOC", "3270 REGIME", "X3 PAD", "NAWS", + "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC", + "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON" +}; +#endif + +#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON + +#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM) +#define CURL_TELOPT(x) telnetoptions[x] + +#define CURL_NTELOPTS 40 + +/* + * First some defines + */ +#define CURL_xEOF 236 /* End Of File */ +#define CURL_SE 240 /* Sub negotiation End */ +#define CURL_NOP 241 /* No OPeration */ +#define CURL_DM 242 /* Data Mark */ +#define CURL_GA 249 /* Go Ahead, reverse the line */ +#define CURL_SB 250 /* SuBnegotiation */ +#define CURL_WILL 251 /* Our side WILL use this option */ +#define CURL_WONT 252 /* Our side WON'T use this option */ +#define CURL_DO 253 /* DO use this option! */ +#define CURL_DONT 254 /* DON'T use this option! */ +#define CURL_IAC 255 /* Interpret As Command */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* + * Then those numbers represented as strings: + */ +static const char * const telnetcmds[]= +{ + "EOF", "SUSP", "ABORT", "EOR", "SE", + "NOP", "DMARK", "BRK", "IP", "AO", + "AYT", "EC", "EL", "GA", "SB", + "WILL", "WONT", "DO", "DONT", "IAC" +}; +#endif + +#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */ +#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */ + +#define CURL_TELQUAL_IS 0 +#define CURL_TELQUAL_SEND 1 +#define CURL_TELQUAL_INFO 2 +#define CURL_TELQUAL_NAME 3 + +#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \ + ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) ) +#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM] + +#endif /* CURL_DISABLE_TELNET */ + +#endif /* HEADER_CURL_ARPA_TELNET_H */ diff --git a/libcurl/lib/asyn-ares.c b/libcurl/lib/asyn-ares.c new file mode 100644 index 0000000..6b14aa6 --- /dev/null +++ b/libcurl/lib/asyn-ares.c @@ -0,0 +1,830 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for ares-enabled builds + * And only for functions that fulfill the asynch resolver backend API + * as defined in asyn.h, nothing else belongs in this file! + **********************************************************************/ + +#ifdef CURLRES_ARES + +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "multiif.h" +#include "inet_pton.h" +#include "connect.h" +#include "select.h" +#include "progress.h" + +# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + (defined(WIN32) || defined(__SYMBIAN32__)) +# define CARES_STATICLIB +# endif +# include +# include /* really old c-ares didn't include this by + itself */ + +#if ARES_VERSION >= 0x010500 +/* c-ares 1.5.0 or later, the callback proto is modified */ +#define HAVE_CARES_CALLBACK_TIMEOUTS 1 +#endif + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +struct ResolverResults { + int num_pending; /* number of ares_gethostbyname() requests */ + Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ + int last_status; + struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */ +}; + +/* How long we are willing to wait for additional parallel responses after + obtaining a "definitive" one. + + This is intended to equal the c-ares default timeout. cURL always uses that + default value. Unfortunately, c-ares doesn't expose its default timeout in + its API, but it is officially documented as 5 seconds. + + See query_completed_cb() for an explanation of how this is used. + */ +#define HAPPY_EYEBALLS_DNS_TIMEOUT 5000 + +/* + * Curl_resolver_global_init() - the generic low-level asynchronous name + * resolve API. Called from curl_global_init() to initialize global resolver + * environment. Initializes ares library. + */ +int Curl_resolver_global_init(void) +{ +#ifdef CARES_HAVE_ARES_LIBRARY_INIT + if(ares_library_init(ARES_LIB_INIT_ALL)) { + return CURLE_FAILED_INIT; + } +#endif + return CURLE_OK; +} + +/* + * Curl_resolver_global_cleanup() + * + * Called from curl_global_cleanup() to destroy global resolver environment. + * Deinitializes ares library. + */ +void Curl_resolver_global_cleanup(void) +{ +#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP + ares_library_cleanup(); +#endif +} + + +static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd, + int readable, int writable) +{ + struct Curl_easy *easy = data; + if(!readable && !writable) { + DEBUGASSERT(easy); + Curl_multi_closed(easy, socket_fd); + } +} + +/* + * Curl_resolver_init() + * + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Fills the passed pointer by the initialized ares_channel. + */ +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver) +{ + int status; + struct ares_options options; + int optmask = ARES_OPT_SOCK_STATE_CB; + options.sock_state_cb = Curl_ares_sock_state_cb; + options.sock_state_cb_data = easy; + status = ares_init_options((ares_channel*)resolver, &options, optmask); + if(status != ARES_SUCCESS) { + if(status == ARES_ENOMEM) + return CURLE_OUT_OF_MEMORY; + else + return CURLE_FAILED_INIT; + } + return CURLE_OK; + /* make sure that all other returns from this function should destroy the + ares channel before returning error! */ +} + +/* + * Curl_resolver_cleanup() + * + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Destroys the ares channel. + */ +void Curl_resolver_cleanup(void *resolver) +{ + ares_destroy((ares_channel)resolver); +} + +/* + * Curl_resolver_duphandle() + * + * Called from curl_easy_duphandle() to duplicate resolver URL-state specific + * environment ('resolver' member of the UrlState structure). Duplicates the + * 'from' ares channel and passes the resulting channel to the 'to' pointer. + */ +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from) +{ + (void)from; + /* + * it would be better to call ares_dup instead, but right now + * it is not possible to set 'sock_state_cb_data' outside of + * ares_init_options + */ + return Curl_resolver_init(easy, to); +} + +static void destroy_async_data(struct Curl_async *async); + +/* + * Cancel all possibly still on-going resolves for this connection. + */ +void Curl_resolver_cancel(struct connectdata *conn) +{ + if(conn->data && conn->data->state.resolver) + ares_cancel((ares_channel)conn->data->state.resolver); + destroy_async_data(&conn->async); +} + +/* + * We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We + * never block. + */ +void Curl_resolver_kill(struct connectdata *conn) +{ + /* We don't need to check the resolver state because we can be called safely + at any time and we always do the same thing. */ + Curl_resolver_cancel(conn); +} + +/* + * destroy_async_data() cleans up async resolver data. + */ +static void destroy_async_data(struct Curl_async *async) +{ + free(async->hostname); + + if(async->os_specific) { + struct ResolverResults *res = (struct ResolverResults *)async->os_specific; + if(res) { + if(res->temp_ai) { + Curl_freeaddrinfo(res->temp_ai); + res->temp_ai = NULL; + } + free(res); + } + async->os_specific = NULL; + } + + async->hostname = NULL; +} + +/* + * Curl_resolver_getsock() is called when someone from the outside world + * (using curl_multi_fdset()) wants to get our fd_set setup and we're talking + * with ares. The caller must make sure that this function is only called when + * we have a working ares channel. + * + * Returns: sockets-in-use-bitmap + */ + +int Curl_resolver_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) + +{ + struct timeval maxtime; + struct timeval timebuf; + struct timeval *timeout; + long milli; + int max = ares_getsock((ares_channel)conn->data->state.resolver, + (ares_socket_t *)socks, numsocks); + + maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; + maxtime.tv_usec = 0; + + timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, + &timebuf); + milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000); + if(milli == 0) + milli += 10; + Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME); + + return max; +} + +/* + * waitperform() + * + * 1) Ask ares what sockets it currently plays with, then + * 2) wait for the timeout period to check for action on ares' sockets. + * 3) tell ares to act on all the sockets marked as "with action" + * + * return number of sockets it worked on + */ + +static int waitperform(struct connectdata *conn, int timeout_ms) +{ + struct Curl_easy *data = conn->data; + int nfds; + int bitmask; + ares_socket_t socks[ARES_GETSOCK_MAXNUM]; + struct pollfd pfd[ARES_GETSOCK_MAXNUM]; + int i; + int num = 0; + + bitmask = ares_getsock((ares_channel)data->state.resolver, socks, + ARES_GETSOCK_MAXNUM); + + for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) { + pfd[i].events = 0; + pfd[i].revents = 0; + if(ARES_GETSOCK_READABLE(bitmask, i)) { + pfd[i].fd = socks[i]; + pfd[i].events |= POLLRDNORM|POLLIN; + } + if(ARES_GETSOCK_WRITABLE(bitmask, i)) { + pfd[i].fd = socks[i]; + pfd[i].events |= POLLWRNORM|POLLOUT; + } + if(pfd[i].events != 0) + num++; + else + break; + } + + if(num) + nfds = Curl_poll(pfd, num, timeout_ms); + else + nfds = 0; + + if(!nfds) + /* Call ares_process() unconditonally here, even if we simply timed out + above, as otherwise the ares name resolve won't timeout! */ + ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD, + ARES_SOCKET_BAD); + else { + /* move through the descriptors and ask for processing on them */ + for(i = 0; i < num; i++) + ares_process_fd((ares_channel)data->state.resolver, + (pfd[i].revents & (POLLRDNORM|POLLIN))? + pfd[i].fd:ARES_SOCKET_BAD, + (pfd[i].revents & (POLLWRNORM|POLLOUT))? + pfd[i].fd:ARES_SOCKET_BAD); + } + return nfds; +} + +/* + * Curl_resolver_is_resolved() is called repeatedly to check if a previous + * name resolve request has completed. It should also make sure to time-out if + * the operation seems to take too long. + * + * Returns normal CURLcode errors. + */ +CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns) +{ + struct Curl_easy *data = conn->data; + struct ResolverResults *res = (struct ResolverResults *) + conn->async.os_specific; + CURLcode result = CURLE_OK; + + if(dns) + *dns = NULL; + + waitperform(conn, 0); + + /* Now that we've checked for any last minute results above, see if there are + any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer + expires. */ + if(res + && res->num_pending + /* This is only set to non-zero if the timer was started. */ + && (res->happy_eyeballs_dns_time.tv_sec + || res->happy_eyeballs_dns_time.tv_usec) + && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time) + >= HAPPY_EYEBALLS_DNS_TIMEOUT)) { + /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer + running. */ + memset( + &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time)); + + /* Cancel the raw c-ares request, which will fire query_completed_cb() with + ARES_ECANCELLED synchronously for all pending responses. This will + leave us with res->num_pending == 0, which is perfect for the next + block. */ + ares_cancel((ares_channel)data->state.resolver); + DEBUGASSERT(res->num_pending == 0); + } + + if(res && !res->num_pending) { + if(dns) { + (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai); + /* temp_ai ownership is moved to the connection, so we need not free-up + them */ + res->temp_ai = NULL; + } + if(!conn->async.dns) { + failf(data, "Could not resolve: %s (%s)", + conn->async.hostname, ares_strerror(conn->async.status)); + result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: + CURLE_COULDNT_RESOLVE_HOST; + } + else if(dns) + *dns = conn->async.dns; + + destroy_async_data(&conn->async); + } + + return result; +} + +/* + * Curl_resolver_wait_resolv() + * + * Waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, + * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. + */ +CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + timediff_t timeout; + struct curltime now = Curl_now(); + struct Curl_dns_entry *temp_entry; + + if(entry) + *entry = NULL; /* clear on entry */ + + timeout = Curl_timeleft(data, &now, TRUE); + if(timeout < 0) { + /* already expired! */ + connclose(conn, "Timed out before name resolve started"); + return CURLE_OPERATION_TIMEDOUT; + } + if(!timeout) + timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */ + + /* Wait for the name resolve query to complete. */ + while(!result) { + struct timeval *tvp, tv, store; + int itimeout; + int timeout_ms; + + itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; + + store.tv_sec = itimeout/1000; + store.tv_usec = (itimeout%1000)*1000; + + tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv); + + /* use the timeout period ares returned to us above if less than one + second is left, otherwise just use 1000ms to make sure the progress + callback gets called frequent enough */ + if(!tvp->tv_sec) + timeout_ms = (int)(tvp->tv_usec/1000); + else + timeout_ms = 1000; + + waitperform(conn, timeout_ms); + result = Curl_resolver_is_resolved(conn, entry?&temp_entry:NULL); + + if(result || conn->async.done) + break; + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else { + struct curltime now2 = Curl_now(); + timediff_t timediff = Curl_timediff(now2, now); /* spent time */ + if(timediff <= 0) + timeout -= 1; /* always deduct at least 1 */ + else if(timediff > timeout) + timeout = -1; + else + timeout -= (long)timediff; + now = now2; /* for next loop */ + } + if(timeout < 0) + result = CURLE_OPERATION_TIMEDOUT; + } + if(result) + /* failure, so we cancel the ares operation */ + ares_cancel((ares_channel)data->state.resolver); + + /* Operation complete, if the lookup was successful we now have the entry + in the cache. */ + if(entry) + *entry = conn->async.dns; + + if(result) + /* close the connection, since we can't return failure here without + cleaning up this connection properly. */ + connclose(conn, "c-ares resolve failed"); + + return result; +} + +/* Connects results to the list */ +static void compound_results(struct ResolverResults *res, + Curl_addrinfo *ai) +{ + Curl_addrinfo *ai_tail; + if(!ai) + return; + ai_tail = ai; + + while(ai_tail->ai_next) + ai_tail = ai_tail->ai_next; + + /* Add the new results to the list of old results. */ + ai_tail->ai_next = res->temp_ai; + res->temp_ai = ai; +} + +/* + * ares_query_completed_cb() is the callback that ares will call when + * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(), + * when using ares, is completed either successfully or with failure. + */ +static void query_completed_cb(void *arg, /* (struct connectdata *) */ + int status, +#ifdef HAVE_CARES_CALLBACK_TIMEOUTS + int timeouts, +#endif + struct hostent *hostent) +{ + struct connectdata *conn = (struct connectdata *)arg; + struct ResolverResults *res; + +#ifdef HAVE_CARES_CALLBACK_TIMEOUTS + (void)timeouts; /* ignored */ +#endif + + if(ARES_EDESTRUCTION == status) + /* when this ares handle is getting destroyed, the 'arg' pointer may not + be valid so only defer it when we know the 'status' says its fine! */ + return; + + res = (struct ResolverResults *)conn->async.os_specific; + if(res) { + res->num_pending--; + + if(CURL_ASYNC_SUCCESS == status) { + Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port); + if(ai) { + compound_results(res, ai); + } + } + /* A successful result overwrites any previous error */ + if(res->last_status != ARES_SUCCESS) + res->last_status = status; + + /* If there are responses still pending, we presume they must be the + complementary IPv4 or IPv6 lookups that we started in parallel in + Curl_resolver_getaddrinfo() (for Happy Eyeballs). If we've got a + "definitive" response from one of a set of parallel queries, we need to + think about how long we're willing to wait for more responses. */ + if(res->num_pending + /* Only these c-ares status values count as "definitive" for these + purposes. For example, ARES_ENODATA is what we expect when there is + no IPv6 entry for a domain name, and that's not a reason to get more + aggressive in our timeouts for the other response. Other errors are + either a result of bad input (which should affect all parallel + requests), local or network conditions, non-definitive server + responses, or us cancelling the request. */ + && (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) { + /* Right now, there can only be up to two parallel queries, so don't + bother handling any other cases. */ + DEBUGASSERT(res->num_pending == 1); + + /* It's possible that one of these parallel queries could succeed + quickly, but the other could always fail or timeout (when we're + talking to a pool of DNS servers that can only successfully resolve + IPv4 address, for example). + + It's also possible that the other request could always just take + longer because it needs more time or only the second DNS server can + fulfill it successfully. But, to align with the philosophy of Happy + Eyeballs, we don't want to wait _too_ long or users will think + requests are slow when IPv6 lookups don't actually work (but IPv4 ones + do). + + So, now that we have a usable answer (some IPv4 addresses, some IPv6 + addresses, or "no such domain"), we start a timeout for the remaining + pending responses. Even though it is typical that this resolved + request came back quickly, that needn't be the case. It might be that + this completing request didn't get a result from the first DNS server + or even the first round of the whole DNS server pool. So it could + already be quite some time after we issued the DNS queries in the + first place. Without modifying c-ares, we can't know exactly where in + its retry cycle we are. We could guess based on how much time has + gone by, but it doesn't really matter. Happy Eyeballs tells us that, + given usable information in hand, we simply don't want to wait "too + much longer" after we get a result. + + We simply wait an additional amount of time equal to the default + c-ares query timeout. That is enough time for a typical parallel + response to arrive without being "too long". Even on a network + where one of the two types of queries is failing or timing out + constantly, this will usually mean we wait a total of the default + c-ares timeout (5 seconds) plus the round trip time for the successful + request, which seems bearable. The downside is that c-ares might race + with us to issue one more retry just before we give up, but it seems + better to "waste" that request instead of trying to guess the perfect + timeout to prevent it. After all, we don't even know where in the + c-ares retry cycle each request is. + */ + res->happy_eyeballs_dns_time = Curl_now(); + Curl_expire( + conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS); + } + } +} + +/* + * Curl_resolver_getaddrinfo() - when using ares + * + * Returns name information about the given hostname and port number. If + * successful, the 'hostent' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + char *bufp; + struct Curl_easy *data = conn->data; + struct in_addr in; + int family = PF_INET; +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + struct in6_addr in6; +#endif /* CURLRES_IPV6 */ + + *waitp = 0; /* default to synchronous response */ + + /* First check if this is an IPv4 address string */ + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + } + +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + /* Otherwise, check if this is an IPv6 address string */ + if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) + /* This must be an IPv6 address literal. */ + return Curl_ip2addr(AF_INET6, &in6, hostname, port); + + switch(conn->ip_version) { + default: +#if ARES_VERSION >= 0x010601 + family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older + c-ares versions this just falls through and defaults + to PF_INET */ + break; +#endif + case CURL_IPRESOLVE_V4: + family = PF_INET; + break; + case CURL_IPRESOLVE_V6: + family = PF_INET6; + break; + } +#endif /* CURLRES_IPV6 */ + + bufp = strdup(hostname); + if(bufp) { + struct ResolverResults *res = NULL; + free(conn->async.hostname); + conn->async.hostname = bufp; + conn->async.port = port; + conn->async.done = FALSE; /* not done */ + conn->async.status = 0; /* clear */ + conn->async.dns = NULL; /* clear */ + res = calloc(sizeof(struct ResolverResults), 1); + if(!res) { + free(conn->async.hostname); + conn->async.hostname = NULL; + return NULL; + } + conn->async.os_specific = res; + + /* initial status - failed */ + res->last_status = ARES_ENOTFOUND; +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + if(family == PF_UNSPEC) { + if(Curl_ipv6works()) { + res->num_pending = 2; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET, query_completed_cb, conn); + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET6, query_completed_cb, conn); + } + else { + res->num_pending = 1; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, + PF_INET, query_completed_cb, conn); + } + } + else +#endif /* CURLRES_IPV6 */ + { + res->num_pending = 1; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.resolver, hostname, family, + query_completed_cb, conn); + } + + *waitp = 1; /* expect asynchronous response */ + } + return NULL; /* no struct yet */ +} + +CURLcode Curl_set_dns_servers(struct Curl_easy *data, + char *servers) +{ + CURLcode result = CURLE_NOT_BUILT_IN; + int ares_result; + + /* If server is NULL or empty, this would purge all DNS servers + * from ares library, which will cause any and all queries to fail. + * So, just return OK if none are configured and don't actually make + * any changes to c-ares. This lets c-ares use it's defaults, which + * it gets from the OS (for instance from /etc/resolv.conf on Linux). + */ + if(!(servers && servers[0])) + return CURLE_OK; + +#if (ARES_VERSION >= 0x010704) +#if (ARES_VERSION >= 0x010b00) + ares_result = ares_set_servers_ports_csv(data->state.resolver, servers); +#else + ares_result = ares_set_servers_csv(data->state.resolver, servers); +#endif + switch(ares_result) { + case ARES_SUCCESS: + result = CURLE_OK; + break; + case ARES_ENOMEM: + result = CURLE_OUT_OF_MEMORY; + break; + case ARES_ENOTINITIALIZED: + case ARES_ENODATA: + case ARES_EBADSTR: + default: + result = CURLE_BAD_FUNCTION_ARGUMENT; + break; + } +#else /* too old c-ares version! */ + (void)data; + (void)(ares_result); +#endif + return result; +} + +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf) +{ +#if (ARES_VERSION >= 0x010704) + if(!interf) + interf = ""; + + ares_set_local_dev((ares_channel)data->state.resolver, interf); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4) +{ +#if (ARES_VERSION >= 0x010704) + struct in_addr a4; + + if((!local_ip4) || (local_ip4[0] == 0)) { + a4.s_addr = 0; /* disabled: do not bind to a specific address */ + } + else { + if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) { + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + + ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr)); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6) +{ +#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6) + unsigned char a6[INET6_ADDRSTRLEN]; + + if((!local_ip6) || (local_ip6[0] == 0)) { + /* disabled: do not bind to a specific address */ + memset(a6, 0, sizeof(a6)); + } + else { + if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) { + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + + ares_set_local_ip6((ares_channel)data->state.resolver, a6); + + return CURLE_OK; +#else /* c-ares version too old! */ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +#endif +} +#endif /* CURLRES_ARES */ diff --git a/libcurl/lib/asyn-thread.c b/libcurl/lib/asyn-thread.c new file mode 100644 index 0000000..55e0811 --- /dev/null +++ b/libcurl/lib/asyn-thread.c @@ -0,0 +1,760 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for threaded name resolves builds + **********************************************************************/ +#ifdef CURLRES_THREADED + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if defined(USE_THREADS_POSIX) +# ifdef HAVE_PTHREAD_H +# include +# endif +#elif defined(USE_THREADS_WIN32) +# ifdef HAVE_PROCESS_H +# include +# endif +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#ifdef HAVE_GETADDRINFO +# define RESOLVER_ENOMEM EAI_MEMORY +#else +# define RESOLVER_ENOMEM ENOMEM +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "multiif.h" +#include "inet_pton.h" +#include "inet_ntop.h" +#include "curl_threads.h" +#include "connect.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +struct resdata { + struct curltime start; +}; + +/* + * Curl_resolver_global_init() + * Called from curl_global_init() to initialize global resolver environment. + * Does nothing here. + */ +int Curl_resolver_global_init(void) +{ + return CURLE_OK; +} + +/* + * Curl_resolver_global_cleanup() + * Called from curl_global_cleanup() to destroy global resolver environment. + * Does nothing here. + */ +void Curl_resolver_global_cleanup(void) +{ +} + +/* + * Curl_resolver_init() + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). + */ +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver) +{ + (void)easy; + *resolver = calloc(1, sizeof(struct resdata)); + if(!*resolver) + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +} + +/* + * Curl_resolver_cleanup() + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). + */ +void Curl_resolver_cleanup(void *resolver) +{ + free(resolver); +} + +/* + * Curl_resolver_duphandle() + * Called from curl_easy_duphandle() to duplicate resolver URL state-specific + * environment ('resolver' member of the UrlState structure). + */ +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from) +{ + (void)from; + return Curl_resolver_init(easy, to); +} + +static void destroy_async_data(struct Curl_async *); + +/* + * Cancel all possibly still on-going resolves for this connection. + */ +void Curl_resolver_cancel(struct connectdata *conn) +{ + destroy_async_data(&conn->async); +} + +/* This function is used to init a threaded resolve */ +static bool init_resolve_thread(struct connectdata *conn, + const char *hostname, int port, + const struct addrinfo *hints); + + +/* Data for synchronization between resolver thread and its parent */ +struct thread_sync_data { + curl_mutex_t * mtx; + int done; + + char *hostname; /* hostname to resolve, Curl_async.hostname + duplicate */ + int port; + int sock_error; + Curl_addrinfo *res; +#ifdef HAVE_GETADDRINFO + struct addrinfo hints; +#endif + struct thread_data *td; /* for thread-self cleanup */ +}; + +struct thread_data { + curl_thread_t thread_hnd; + unsigned int poll_interval; + time_t interval_end; + struct thread_sync_data tsd; +}; + +static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn) +{ + return &(((struct thread_data *)conn->async.os_specific)->tsd); +} + +/* Destroy resolver thread synchronization data */ +static +void destroy_thread_sync_data(struct thread_sync_data * tsd) +{ + if(tsd->mtx) { + Curl_mutex_destroy(tsd->mtx); + free(tsd->mtx); + } + + free(tsd->hostname); + + if(tsd->res) + Curl_freeaddrinfo(tsd->res); + + memset(tsd, 0, sizeof(*tsd)); +} + +/* Initialize resolver thread synchronization data */ +static +int init_thread_sync_data(struct thread_data * td, + const char *hostname, + int port, + const struct addrinfo *hints) +{ + struct thread_sync_data *tsd = &td->tsd; + + memset(tsd, 0, sizeof(*tsd)); + + tsd->td = td; + tsd->port = port; + /* Treat the request as done until the thread actually starts so any early + * cleanup gets done properly. + */ + tsd->done = 1; +#ifdef HAVE_GETADDRINFO + DEBUGASSERT(hints); + tsd->hints = *hints; +#else + (void) hints; +#endif + + tsd->mtx = malloc(sizeof(curl_mutex_t)); + if(tsd->mtx == NULL) + goto err_exit; + + Curl_mutex_init(tsd->mtx); + + tsd->sock_error = CURL_ASYNC_SUCCESS; + + /* Copying hostname string because original can be destroyed by parent + * thread during gethostbyname execution. + */ + tsd->hostname = strdup(hostname); + if(!tsd->hostname) + goto err_exit; + + return 1; + + err_exit: + /* Memory allocation failed */ + destroy_thread_sync_data(tsd); + return 0; +} + +static int getaddrinfo_complete(struct connectdata *conn) +{ + struct thread_sync_data *tsd = conn_thread_sync_data(conn); + int rc; + + rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res); + /* The tsd->res structure has been copied to async.dns and perhaps the DNS + cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it. + */ + tsd->res = NULL; + + return rc; +} + + +#ifdef HAVE_GETADDRINFO + +/* + * getaddrinfo_thread() resolves a name and then exits. + * + * For builds without ARES, but with ENABLE_IPV6, create a resolver thread + * and wait on it. + */ +static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) +{ + struct thread_sync_data *tsd = (struct thread_sync_data*)arg; + struct thread_data *td = tsd->td; + char service[12]; + int rc; + + msnprintf(service, sizeof(service), "%d", tsd->port); + + rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res); + + if(rc != 0) { + tsd->sock_error = SOCKERRNO?SOCKERRNO:rc; + if(tsd->sock_error == 0) + tsd->sock_error = RESOLVER_ENOMEM; + } + else { + Curl_addrinfo_set_port(tsd->res, tsd->port); + } + + Curl_mutex_acquire(tsd->mtx); + if(tsd->done) { + /* too late, gotta clean up the mess */ + Curl_mutex_release(tsd->mtx); + destroy_thread_sync_data(tsd); + free(td); + } + else { + tsd->done = 1; + Curl_mutex_release(tsd->mtx); + } + + return 0; +} + +#else /* HAVE_GETADDRINFO */ + +/* + * gethostbyname_thread() resolves a name and then exits. + */ +static unsigned int CURL_STDCALL gethostbyname_thread(void *arg) +{ + struct thread_sync_data *tsd = (struct thread_sync_data *)arg; + struct thread_data *td = tsd->td; + + tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port); + + if(!tsd->res) { + tsd->sock_error = SOCKERRNO; + if(tsd->sock_error == 0) + tsd->sock_error = RESOLVER_ENOMEM; + } + + Curl_mutex_acquire(tsd->mtx); + if(tsd->done) { + /* too late, gotta clean up the mess */ + Curl_mutex_release(tsd->mtx); + destroy_thread_sync_data(tsd); + free(td); + } + else { + tsd->done = 1; + Curl_mutex_release(tsd->mtx); + } + + return 0; +} + +#endif /* HAVE_GETADDRINFO */ + +/* + * destroy_async_data() cleans up async resolver data and thread handle. + */ +static void destroy_async_data(struct Curl_async *async) +{ + if(async->os_specific) { + struct thread_data *td = (struct thread_data*) async->os_specific; + int done; + + /* + * if the thread is still blocking in the resolve syscall, detach it and + * let the thread do the cleanup... + */ + Curl_mutex_acquire(td->tsd.mtx); + done = td->tsd.done; + td->tsd.done = 1; + Curl_mutex_release(td->tsd.mtx); + + if(!done) { + Curl_thread_destroy(td->thread_hnd); + } + else { + if(td->thread_hnd != curl_thread_t_null) + Curl_thread_join(&td->thread_hnd); + + destroy_thread_sync_data(&td->tsd); + + free(async->os_specific); + } + } + async->os_specific = NULL; + + free(async->hostname); + async->hostname = NULL; +} + +/* + * init_resolve_thread() starts a new thread that performs the actual + * resolve. This function returns before the resolve is done. + * + * Returns FALSE in case of failure, otherwise TRUE. + */ +static bool init_resolve_thread(struct connectdata *conn, + const char *hostname, int port, + const struct addrinfo *hints) +{ + struct thread_data *td = calloc(1, sizeof(struct thread_data)); + int err = ENOMEM; + + conn->async.os_specific = (void *)td; + if(!td) + goto errno_exit; + + conn->async.port = port; + conn->async.done = FALSE; + conn->async.status = 0; + conn->async.dns = NULL; + td->thread_hnd = curl_thread_t_null; + + if(!init_thread_sync_data(td, hostname, port, hints)) { + conn->async.os_specific = NULL; + free(td); + goto errno_exit; + } + + free(conn->async.hostname); + conn->async.hostname = strdup(hostname); + if(!conn->async.hostname) + goto err_exit; + + /* The thread will set this to 1 when complete. */ + td->tsd.done = 0; + +#ifdef HAVE_GETADDRINFO + td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd); +#else + td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd); +#endif + + if(!td->thread_hnd) { + /* The thread never started, so mark it as done here for proper cleanup. */ + td->tsd.done = 1; + err = errno; + goto err_exit; + } + + return TRUE; + + err_exit: + destroy_async_data(&conn->async); + + errno_exit: + errno = err; + return FALSE; +} + +/* + * resolver_error() calls failf() with the appropriate message after a resolve + * error + */ + +static CURLcode resolver_error(struct connectdata *conn) +{ + const char *host_or_proxy; + CURLcode result; + + if(conn->bits.httpproxy) { + host_or_proxy = "proxy"; + result = CURLE_COULDNT_RESOLVE_PROXY; + } + else { + host_or_proxy = "host"; + result = CURLE_COULDNT_RESOLVE_HOST; + } + + failf(conn->data, "Could not resolve %s: %s", host_or_proxy, + conn->async.hostname); + + return result; +} + +static CURLcode thread_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry, + bool report) +{ + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + CURLcode result = CURLE_OK; + + DEBUGASSERT(conn && td); + DEBUGASSERT(td->thread_hnd != curl_thread_t_null); + + /* wait for the thread to resolve the name */ + if(Curl_thread_join(&td->thread_hnd)) { + if(entry) + result = getaddrinfo_complete(conn); + } + else + DEBUGASSERT(0); + + conn->async.done = TRUE; + + if(entry) + *entry = conn->async.dns; + + if(!conn->async.dns && report) + /* a name was not resolved, report error */ + result = resolver_error(conn); + + destroy_async_data(&conn->async); + + if(!conn->async.dns && report) + connclose(conn, "asynch resolve failed"); + + return result; +} + + +/* + * Until we gain a way to signal the resolver threads to stop early, we must + * simply wait for them and ignore their results. + */ +void Curl_resolver_kill(struct connectdata *conn) +{ + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + + /* If we're still resolving, we must wait for the threads to fully clean up, + unfortunately. Otherwise, we can simply cancel to clean up any resolver + data. */ + if(td && td->thread_hnd != curl_thread_t_null) + (void)thread_wait_resolv(conn, NULL, FALSE); + else + Curl_resolver_cancel(conn); +} + +/* + * Curl_resolver_wait_resolv() + * + * Waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, + * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. + * + * This is the version for resolves-in-a-thread. + */ +CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + return thread_wait_resolv(conn, entry, TRUE); +} + +/* + * Curl_resolver_is_resolved() is called repeatedly to check if a previous + * name resolve request has completed. It should also make sure to time-out if + * the operation seems to take too long. + */ +CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **entry) +{ + struct Curl_easy *data = conn->data; + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + int done = 0; + + *entry = NULL; + + if(!td) { + DEBUGASSERT(td); + return CURLE_COULDNT_RESOLVE_HOST; + } + + Curl_mutex_acquire(td->tsd.mtx); + done = td->tsd.done; + Curl_mutex_release(td->tsd.mtx); + + if(done) { + getaddrinfo_complete(conn); + + if(!conn->async.dns) { + CURLcode result = resolver_error(conn); + destroy_async_data(&conn->async); + return result; + } + destroy_async_data(&conn->async); + *entry = conn->async.dns; + } + else { + /* poll for name lookup done with exponential backoff up to 250ms */ + timediff_t elapsed = Curl_timediff(Curl_now(), + data->progress.t_startsingle); + if(elapsed < 0) + elapsed = 0; + + if(td->poll_interval == 0) + /* Start at 1ms poll interval */ + td->poll_interval = 1; + else if(elapsed >= td->interval_end) + /* Back-off exponentially if last interval expired */ + td->poll_interval *= 2; + + if(td->poll_interval > 250) + td->poll_interval = 250; + + td->interval_end = elapsed + td->poll_interval; + Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME); + } + + return CURLE_OK; +} + +int Curl_resolver_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + time_t milli; + timediff_t ms; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; + (void)socks; + (void)numsocks; + ms = Curl_timediff(Curl_now(), reslv->start); + if(ms < 3) + milli = 0; + else if(ms <= 50) + milli = ms/3; + else if(ms <= 250) + milli = 50; + else + milli = 200; + Curl_expire(data, milli, EXPIRE_ASYNC_NAME); + return 0; +} + +#ifndef HAVE_GETADDRINFO +/* + * Curl_getaddrinfo() - for platforms without getaddrinfo + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct in_addr in; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; + + *waitp = 0; /* default to synchronous response */ + + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + + reslv->start = Curl_now(); + + /* fire up a new resolver thread! */ + if(init_resolve_thread(conn, hostname, port, NULL)) { + *waitp = 1; /* expect asynchronous response */ + return NULL; + } + + failf(conn->data, "getaddrinfo() thread failed\n"); + + return NULL; +} + +#else /* !HAVE_GETADDRINFO */ + +/* + * Curl_resolver_getaddrinfo() - for getaddrinfo + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct addrinfo hints; + char sbuf[12]; + int pf = PF_INET; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; + + *waitp = 0; /* default to synchronous response */ + +#ifndef USE_RESOLVE_ON_IPS + { + struct in_addr in; + /* First check if this is an IPv4 address string */ + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + } +#ifdef CURLRES_IPV6 + { + struct in6_addr in6; + /* check if this is an IPv6 address string */ + if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) + /* This is an IPv6 address literal */ + return Curl_ip2addr(AF_INET6, &in6, hostname, port); + } +#endif /* CURLRES_IPV6 */ +#endif /* !USE_RESOLVE_ON_IPS */ + +#ifdef CURLRES_IPV6 + /* + * Check if a limited name resolve has been requested. + */ + switch(conn->ip_version) { + case CURL_IPRESOLVE_V4: + pf = PF_INET; + break; + case CURL_IPRESOLVE_V6: + pf = PF_INET6; + break; + default: + pf = PF_UNSPEC; + break; + } + + if((pf != PF_INET) && !Curl_ipv6works()) + /* The stack seems to be a non-IPv6 one */ + pf = PF_INET; +#endif /* CURLRES_IPV6 */ + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = pf; + hints.ai_socktype = conn->socktype; + + msnprintf(sbuf, sizeof(sbuf), "%d", port); + + reslv->start = Curl_now(); + /* fire up a new resolver thread! */ + if(init_resolve_thread(conn, hostname, port, &hints)) { + *waitp = 1; /* expect asynchronous response */ + return NULL; + } + + failf(data, "getaddrinfo() thread failed to start\n"); + return NULL; + +} + +#endif /* !HAVE_GETADDRINFO */ + +CURLcode Curl_set_dns_servers(struct Curl_easy *data, + char *servers) +{ + (void)data; + (void)servers; + return CURLE_NOT_BUILT_IN; + +} + +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf) +{ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +} + +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4) +{ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +} + +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6) +{ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +} + +#endif /* CURLRES_THREADED */ diff --git a/libcurl/lib/asyn.h b/libcurl/lib/asyn.h new file mode 100644 index 0000000..ccd4b1f --- /dev/null +++ b/libcurl/lib/asyn.h @@ -0,0 +1,184 @@ +#ifndef HEADER_CURL_ASYN_H +#define HEADER_CURL_ASYN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "curl_addrinfo.h" + +struct addrinfo; +struct hostent; +struct Curl_easy; +struct connectdata; +struct Curl_dns_entry; + +/* + * This header defines all functions in the internal asynch resolver interface. + * All asynch resolvers need to provide these functions. + * asyn-ares.c and asyn-thread.c are the current implementations of asynch + * resolver backends. + */ + +/* + * Curl_resolver_global_init() + * + * Called from curl_global_init() to initialize global resolver environment. + * Returning anything else than CURLE_OK fails curl_global_init(). + */ +int Curl_resolver_global_init(void); + +/* + * Curl_resolver_global_cleanup() + * Called from curl_global_cleanup() to destroy global resolver environment. + */ +void Curl_resolver_global_cleanup(void); + +/* + * Curl_resolver_init() + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Should fill the passed pointer by the initialized handler. + * Returning anything else than CURLE_OK fails curl_easy_init() with the + * correspondent code. + */ +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver); + +/* + * Curl_resolver_cleanup() + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Should destroy the handler and free all resources connected to + * it. + */ +void Curl_resolver_cleanup(void *resolver); + +/* + * Curl_resolver_duphandle() + * Called from curl_easy_duphandle() to duplicate resolver URL-state specific + * environment ('resolver' member of the UrlState structure). Should + * duplicate the 'from' handle and pass the resulting handle to the 'to' + * pointer. Returning anything else than CURLE_OK causes failed + * curl_easy_duphandle() call. + */ +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, + void *from); + +/* + * Curl_resolver_cancel(). + * + * It is called from inside other functions to cancel currently performing + * resolver request. Should also free any temporary resources allocated to + * perform a request. This never waits for resolver threads to complete. + * + * It is safe to call this when conn is in any state. + */ +void Curl_resolver_cancel(struct connectdata *conn); + +/* + * Curl_resolver_kill(). + * + * This acts like Curl_resolver_cancel() except it will block until any threads + * associated with the resolver are complete. This never blocks for resolvers + * that do not use threads. This is intended to be the "last chance" function + * that cleans up an in-progress resolver completely (before its owner is about + * to die). + * + * It is safe to call this when conn is in any state. + */ +void Curl_resolver_kill(struct connectdata *conn); + +/* Curl_resolver_getsock() + * + * This function is called from the multi_getsock() function. 'sock' is a + * pointer to an array to hold the file descriptors, with 'numsock' being the + * size of that array (in number of entries). This function is supposed to + * return bitmask indicating what file descriptors (referring to array indexes + * in the 'sock' array) to wait for, read/write. + */ +int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock, + int numsocks); + +/* + * Curl_resolver_is_resolved() + * + * Called repeatedly to check if a previous name resolve request has + * completed. It should also make sure to time-out if the operation seems to + * take too long. + * + * Returns normal CURLcode errors. + */ +CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns); + +/* + * Curl_resolver_wait_resolv() + * + * Waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, + * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. + */ +CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **dnsentry); + +/* + * Curl_resolver_getaddrinfo() - when using this resolver + * + * Returns name information about the given hostname and port number. If + * successful, the 'hostent' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + * + * Each resolver backend must of course make sure to return data in the + * correct format to comply with this. + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + +#ifndef CURLRES_ASYNCH +/* convert these functions if an asynch resolver isn't used */ +#define Curl_resolver_cancel(x) Curl_nop_stmt +#define Curl_resolver_kill(x) Curl_nop_stmt +#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_resolver_getsock(x,y,z) 0 +#define Curl_resolver_duphandle(x,y,z) CURLE_OK +#define Curl_resolver_init(x,y) CURLE_OK +#define Curl_resolver_global_init() CURLE_OK +#define Curl_resolver_global_cleanup() Curl_nop_stmt +#define Curl_resolver_cleanup(x) Curl_nop_stmt +#endif + +#ifdef CURLRES_ASYNCH +#define Curl_resolver_asynch() 1 +#else +#define Curl_resolver_asynch() 0 +#endif + + +/********** end of generic resolver interface functions *****************/ +#endif /* HEADER_CURL_ASYN_H */ diff --git a/libcurl/lib/base64.c b/libcurl/lib/base64.c new file mode 100644 index 0000000..fb081a6 --- /dev/null +++ b/libcurl/lib/base64.c @@ -0,0 +1,326 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Base64 encoding/decoding */ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_LIBSSH2) || \ + defined(USE_LIBSSH) || !defined(CURL_DISABLE_LDAP) || \ + !defined(CURL_DISABLE_DOH) || defined(USE_SSL) + +#include "urldata.h" /* for the Curl_easy definition */ +#include "warnless.h" +#include "curl_base64.h" +#include "non-ascii.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* ---- Base64 Encoding/Decoding Table --- */ +static const char base64[]= + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648 + section 5 */ +static const char base64url[]= + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +static size_t decodeQuantum(unsigned char *dest, const char *src) +{ + size_t padding = 0; + const char *s, *p; + unsigned long i, x = 0; + + for(i = 0, s = src; i < 4; i++, s++) { + if(*s == '=') { + x = (x << 6); + padding++; + } + else { + unsigned long v = 0; + p = base64; + + while(*p && (*p != *s)) { + v++; + p++; + } + + if(*p == *s) + x = (x << 6) + v; + else + return 0; + } + } + + if(padding < 1) + dest[2] = curlx_ultouc(x & 0xFFUL); + + x >>= 8; + if(padding < 2) + dest[1] = curlx_ultouc(x & 0xFFUL); + + x >>= 8; + dest[0] = curlx_ultouc(x & 0xFFUL); + + return 3 - padding; +} + +/* + * Curl_base64_decode() + * + * Given a base64 NUL-terminated string at src, decode it and return a + * pointer in *outptr to a newly allocated memory area holding decoded + * data. Size of decoded data is returned in variable pointed by outlen. + * + * Returns CURLE_OK on success, otherwise specific error code. Function + * output shall not be considered valid unless CURLE_OK is returned. + * + * When decoded data length is 0, returns NULL in *outptr. + * + * @unittest: 1302 + */ +CURLcode Curl_base64_decode(const char *src, + unsigned char **outptr, size_t *outlen) +{ + size_t srclen = 0; + size_t length = 0; + size_t padding = 0; + size_t i; + size_t numQuantums; + size_t rawlen = 0; + unsigned char *pos; + unsigned char *newstr; + + *outptr = NULL; + *outlen = 0; + srclen = strlen(src); + + /* Check the length of the input string is valid */ + if(!srclen || srclen % 4) + return CURLE_BAD_CONTENT_ENCODING; + + /* Find the position of any = padding characters */ + while((src[length] != '=') && src[length]) + length++; + + /* A maximum of two = padding characters is allowed */ + if(src[length] == '=') { + padding++; + if(src[length + 1] == '=') + padding++; + } + + /* Check the = padding characters weren't part way through the input */ + if(length + padding != srclen) + return CURLE_BAD_CONTENT_ENCODING; + + /* Calculate the number of quantums */ + numQuantums = srclen / 4; + + /* Calculate the size of the decoded string */ + rawlen = (numQuantums * 3) - padding; + + /* Allocate our buffer including room for a zero terminator */ + newstr = malloc(rawlen + 1); + if(!newstr) + return CURLE_OUT_OF_MEMORY; + + pos = newstr; + + /* Decode the quantums */ + for(i = 0; i < numQuantums; i++) { + size_t result = decodeQuantum(pos, src); + if(!result) { + free(newstr); + + return CURLE_BAD_CONTENT_ENCODING; + } + + pos += result; + src += 4; + } + + /* Zero terminate */ + *pos = '\0'; + + /* Return the decoded data */ + *outptr = newstr; + *outlen = rawlen; + + return CURLE_OK; +} + +static CURLcode base64_encode(const char *table64, + struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen) +{ + CURLcode result; + unsigned char ibuf[3]; + unsigned char obuf[4]; + int i; + int inputparts; + char *output; + char *base64data; + char *convbuf = NULL; + + const char *indata = inputbuff; + + *outptr = NULL; + *outlen = 0; + + if(!insize) + insize = strlen(indata); + +#if SIZEOF_SIZE_T == 4 + if(insize > UINT_MAX/4) + return CURLE_OUT_OF_MEMORY; +#endif + + base64data = output = malloc(insize * 4 / 3 + 4); + if(!output) + return CURLE_OUT_OF_MEMORY; + + /* + * The base64 data needs to be created using the network encoding + * not the host encoding. And we can't change the actual input + * so we copy it to a buffer, translate it, and use that instead. + */ + result = Curl_convert_clone(data, indata, insize, &convbuf); + if(result) { + free(output); + return result; + } + + if(convbuf) + indata = (char *)convbuf; + + while(insize > 0) { + for(i = inputparts = 0; i < 3; i++) { + if(insize > 0) { + inputparts++; + ibuf[i] = (unsigned char) *indata; + indata++; + insize--; + } + else + ibuf[i] = 0; + } + + obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); + obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ + ((ibuf[1] & 0xF0) >> 4)); + obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ + ((ibuf[2] & 0xC0) >> 6)); + obuf[3] = (unsigned char) (ibuf[2] & 0x3F); + + switch(inputparts) { + case 1: /* only one byte read */ + msnprintf(output, 5, "%c%c==", + table64[obuf[0]], + table64[obuf[1]]); + break; + + case 2: /* two bytes read */ + msnprintf(output, 5, "%c%c%c=", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]]); + break; + + default: + msnprintf(output, 5, "%c%c%c%c", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]], + table64[obuf[3]]); + break; + } + output += 4; + } + + /* Zero terminate */ + *output = '\0'; + + /* Return the pointer to the new data (allocated memory) */ + *outptr = base64data; + + free(convbuf); + + /* Return the length of the new data */ + *outlen = strlen(base64data); + + return CURLE_OK; +} + +/* + * Curl_base64_encode() + * + * Given a pointer to an input buffer and an input size, encode it and + * return a pointer in *outptr to a newly allocated memory area holding + * encoded data. Size of encoded data is returned in variable pointed by + * outlen. + * + * Input length of 0 indicates input buffer holds a NUL-terminated string. + * + * Returns CURLE_OK on success, otherwise specific error code. Function + * output shall not be considered valid unless CURLE_OK is returned. + * + * When encoded data length is 0, returns NULL in *outptr. + * + * @unittest: 1302 + */ +CURLcode Curl_base64_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen) +{ + return base64_encode(base64, data, inputbuff, insize, outptr, outlen); +} + +/* + * Curl_base64url_encode() + * + * Given a pointer to an input buffer and an input size, encode it and + * return a pointer in *outptr to a newly allocated memory area holding + * encoded data. Size of encoded data is returned in variable pointed by + * outlen. + * + * Input length of 0 indicates input buffer holds a NUL-terminated string. + * + * Returns CURLE_OK on success, otherwise specific error code. Function + * output shall not be considered valid unless CURLE_OK is returned. + * + * When encoded data length is 0, returns NULL in *outptr. + * + * @unittest: 1302 + */ +CURLcode Curl_base64url_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen) +{ + return base64_encode(base64url, data, inputbuff, insize, outptr, outlen); +} + +#endif /* no users so disabled */ diff --git a/libcurl/lib/checksrc.pl b/libcurl/lib/checksrc.pl new file mode 100644 index 0000000..965f0ba --- /dev/null +++ b/libcurl/lib/checksrc.pl @@ -0,0 +1,756 @@ +#!/usr/bin/env perl +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 2011 - 2018, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### + +use strict; +use warnings; + +my $max_column = 79; +my $indent = 2; + +my $warnings = 0; +my $swarnings = 0; +my $errors = 0; +my $serrors = 0; +my $suppressed; # whitelisted problems +my $file; +my $dir="."; +my $wlist=""; +my @alist; +my $windows_os = $^O eq 'MSWin32' || $^O eq 'msys' || $^O eq 'cygwin'; +my $verbose; +my %whitelist; + +my %ignore; +my %ignore_set; +my %ignore_used; +my @ignore_line; + +my %warnings_extended = ( + 'COPYRIGHTYEAR' => 'copyright year incorrect', + ); + +my %warnings = ( + 'LONGLINE' => "Line longer than $max_column", + 'TABS' => 'TAB characters not allowed', + 'TRAILINGSPACE' => 'Trailing white space on the line', + 'CPPCOMMENTS' => '// comment detected', + 'SPACEBEFOREPAREN' => 'space before an open parenthesis', + 'SPACEAFTERPAREN' => 'space after open parenthesis', + 'SPACEBEFORECLOSE' => 'space before a close parenthesis', + 'SPACEBEFORECOMMA' => 'space before a comma', + 'RETURNNOSPACE' => 'return without space', + 'COMMANOSPACE' => 'comma without following space', + 'BRACEELSE' => '} else on the same line', + 'PARENBRACE' => '){ without sufficient space', + 'SPACESEMICOLON' => 'space before semicolon', + 'BANNEDFUNC' => 'a banned function was used', + 'FOPENMODE' => 'fopen needs a macro for the mode string', + 'BRACEPOS' => 'wrong position for an open brace', + 'INDENTATION' => 'wrong start column for code', + 'COPYRIGHT' => 'file missing a copyright statement', + 'BADCOMMAND' => 'bad !checksrc! instruction', + 'UNUSEDIGNORE' => 'a warning ignore was not used', + 'OPENCOMMENT' => 'file ended with a /* comment still "open"', + 'ASTERISKSPACE' => 'pointer declared with space after asterisk', + 'ASTERISKNOSPACE' => 'pointer declared without space before asterisk', + 'ASSIGNWITHINCONDITION' => 'assignment within conditional expression', + 'EQUALSNOSPACE' => 'equals sign without following space', + 'NOSPACEEQUALS' => 'equals sign without preceding space', + 'SEMINOSPACE' => 'semicolon without following space', + 'MULTISPACE' => 'multiple spaces used when not suitable', + 'SIZEOFNOPAREN' => 'use of sizeof without parentheses', + 'SNPRINTF' => 'use of snprintf', + ); + +sub readwhitelist { + open(W, "<$dir/checksrc.whitelist") or return; + my @all=; + for(@all) { + $windows_os ? $_ =~ s/\r?\n$// : chomp; + $whitelist{$_}=1; + } + close(W); +} + +# Reads the .checksrc in $dir for any extended warnings to enable locally. +# Currently there is no support for disabling warnings from the standard set, +# and since that's already handled via !checksrc! commands there is probably +# little use to add it. +sub readlocalfile { + my $i = 0; + + open(my $rcfile, "<", "$dir/.checksrc") or return; + + while(<$rcfile>) { + $i++; + + # Lines starting with '#' are considered comments + if (/^\s*(#.*)/) { + next; + } + elsif (/^\s*enable ([A-Z]+)$/) { + if(!defined($warnings_extended{$1})) { + print STDERR "invalid warning specified in .checksrc: \"$1\"\n"; + next; + } + $warnings{$1} = $warnings_extended{$1}; + } + else { + die "Invalid format in $dir/.checksrc on line $i\n"; + } + } +} + +sub checkwarn { + my ($name, $num, $col, $file, $line, $msg, $error) = @_; + + my $w=$error?"error":"warning"; + my $nowarn=0; + + #if(!$warnings{$name}) { + # print STDERR "Dev! there's no description for $name!\n"; + #} + + # checksrc.whitelist + if($whitelist{$line}) { + $nowarn = 1; + } + # !checksrc! controlled + elsif($ignore{$name}) { + $ignore{$name}--; + $ignore_used{$name}++; + $nowarn = 1; + if(!$ignore{$name}) { + # reached zero, enable again + enable_warn($name, $num, $file, $line); + } + } + + if($nowarn) { + $suppressed++; + if($w) { + $swarnings++; + } + else { + $serrors++; + } + return; + } + + if($w) { + $warnings++; + } + else { + $errors++; + } + + $col++; + print "$file:$num:$col: $w: $msg ($name)\n"; + print " $line\n"; + + if($col < 80) { + my $pref = (' ' x $col); + print "${pref}^\n"; + } +} + +$file = shift @ARGV; + +while(1) { + + if($file =~ /-D(.*)/) { + $dir = $1; + $file = shift @ARGV; + next; + } + elsif($file =~ /-W(.*)/) { + $wlist .= " $1 "; + $file = shift @ARGV; + next; + } + elsif($file =~ /-A(.+)/) { + push @alist, $1; + $file = shift @ARGV; + next; + } + elsif($file =~ /-i([1-9])/) { + $indent = $1 + 0; + $file = shift @ARGV; + next; + } + elsif($file =~ /-m([0-9]+)/) { + $max_column = $1 + 0; + $file = shift @ARGV; + next; + } + elsif($file =~ /^(-h|--help)/) { + undef $file; + last; + } + + last; +} + +if(!$file) { + print "checksrc.pl [option] [file2] ...\n"; + print " Options:\n"; + print " -A[rule] Accept this violation, can be used multiple times\n"; + print " -D[DIR] Directory to prepend file names\n"; + print " -h Show help output\n"; + print " -W[file] Whitelist the given file - ignore all its flaws\n"; + print " -i Indent spaces. Default: 2\n"; + print " -m Maximum line length. Default: 79\n"; + print "\nDetects and warns for these problems:\n"; + for(sort keys %warnings) { + printf (" %-18s: %s\n", $_, $warnings{$_}); + } + exit; +} + +readwhitelist(); +readlocalfile(); + +do { + if("$wlist" !~ / $file /) { + my $fullname = $file; + $fullname = "$dir/$file" if ($fullname !~ '^\.?\.?/'); + scanfile($fullname); + } + $file = shift @ARGV; + +} while($file); + +sub accept_violations { + for my $r (@alist) { + if(!$warnings{$r}) { + print "'$r' is not a warning to accept!\n"; + exit; + } + $ignore{$r}=999999; + $ignore_used{$r}=0; + } +} + +sub checksrc_clear { + undef %ignore; + undef %ignore_set; + undef @ignore_line; +} + +sub checksrc_endoffile { + my ($file) = @_; + for(keys %ignore_set) { + if($ignore_set{$_} && !$ignore_used{$_}) { + checkwarn("UNUSEDIGNORE", $ignore_set{$_}, + length($_)+11, $file, + $ignore_line[$ignore_set{$_}], + "Unused ignore: $_"); + } + } +} + +sub enable_warn { + my ($what, $line, $file, $l) = @_; + + # switch it back on, but warn if not triggered! + if(!$ignore_used{$what}) { + checkwarn("UNUSEDIGNORE", + $line, length($what) + 11, $file, $l, + "No warning was inhibited!"); + } + $ignore_set{$what}=0; + $ignore_used{$what}=0; + $ignore{$what}=0; +} +sub checksrc { + my ($cmd, $line, $file, $l) = @_; + if($cmd =~ / *([^ ]*) *(.*)/) { + my ($enable, $what) = ($1, $2); + $what =~ s: *\*/$::; # cut off end of C comment + # print "ENABLE $enable WHAT $what\n"; + if($enable eq "disable") { + my ($warn, $scope)=($1, $2); + if($what =~ /([^ ]*) +(.*)/) { + ($warn, $scope)=($1, $2); + } + else { + $warn = $what; + $scope = 1; + } + # print "IGNORE $warn for SCOPE $scope\n"; + if($scope eq "all") { + $scope=999999; + } + + # Comparing for a literal zero rather than the scalar value zero + # covers the case where $scope contains the ending '*' from the + # comment. If we use a scalar comparison (==) we induce warnings + # on non-scalar contents. + if($scope eq "0") { + checkwarn("BADCOMMAND", + $line, 0, $file, $l, + "Disable zero not supported, did you mean to enable?"); + } + elsif($ignore_set{$warn}) { + checkwarn("BADCOMMAND", + $line, 0, $file, $l, + "$warn already disabled from line $ignore_set{$warn}"); + } + else { + $ignore{$warn}=$scope; + $ignore_set{$warn}=$line; + $ignore_line[$line]=$l; + } + } + elsif($enable eq "enable") { + enable_warn($what, $line, $file, $l); + } + else { + checkwarn("BADCOMMAND", + $line, 0, $file, $l, + "Illegal !checksrc! command"); + } + } +} + +sub nostrings { + my ($str) = @_; + $str =~ s/\".*\"//g; + return $str; +} + +sub scanfile { + my ($file) = @_; + + my $line = 1; + my $prevl=""; + my $l; + open(R, "<$file") || die "failed to open $file"; + + my $incomment=0; + my @copyright=(); + checksrc_clear(); # for file based ignores + accept_violations(); + + while() { + $windows_os ? $_ =~ s/\r?\n$// : chomp; + my $l = $_; + my $ol = $l; # keep the unmodified line for error reporting + my $column = 0; + + # check for !checksrc! commands + if($l =~ /\!checksrc\! (.*)/) { + my $cmd = $1; + checksrc($cmd, $line, $file, $l) + } + + # check for a copyright statement and save the years + if($l =~ /\* +copyright .* \d\d\d\d/i) { + while($l =~ /([\d]{4})/g) { + push @copyright, { + year => $1, + line => $line, + col => index($l, $1), + code => $l + }; + } + } + + # detect long lines + if(length($l) > $max_column) { + checkwarn("LONGLINE", $line, length($l), $file, $l, + "Longer than $max_column columns"); + } + # detect TAB characters + if($l =~ /^(.*)\t/) { + checkwarn("TABS", + $line, length($1), $file, $l, "Contains TAB character", 1); + } + # detect trailing white space + if($l =~ /^(.*)[ \t]+\z/) { + checkwarn("TRAILINGSPACE", + $line, length($1), $file, $l, "Trailing whitespace"); + } + + # ------------------------------------------------------------ + # Above this marker, the checks were done on lines *including* + # comments + # ------------------------------------------------------------ + + # strip off C89 comments + + comment: + if(!$incomment) { + if($l =~ s/\/\*.*\*\// /g) { + # full /* comments */ were removed! + } + if($l =~ s/\/\*.*//) { + # start of /* comment was removed + $incomment = 1; + } + } + else { + if($l =~ s/.*\*\///) { + # end of comment */ was removed + $incomment = 0; + goto comment; + } + else { + # still within a comment + $l=""; + } + } + + # ------------------------------------------------------------ + # Below this marker, the checks were done on lines *without* + # comments + # ------------------------------------------------------------ + + # crude attempt to detect // comments without too many false + # positives + if($l =~ /^([^"\*]*)[^:"]\/\//) { + checkwarn("CPPCOMMENTS", + $line, length($1), $file, $l, "\/\/ comment"); + } + + my $nostr = nostrings($l); + # check spaces after for/if/while/function call + if($nostr =~ /^(.*)(for|if|while| ([a-zA-Z0-9_]+)) \((.)/) { + if($1 =~ / *\#/) { + # this is a #if, treat it differently + } + elsif(defined $3 && $3 eq "return") { + # return must have a space + } + elsif(defined $3 && $3 eq "case") { + # case must have a space + } + elsif($4 eq "*") { + # (* beginning makes the space OK! + } + elsif($1 =~ / *typedef/) { + # typedefs can use space-paren + } + else { + checkwarn("SPACEBEFOREPAREN", $line, length($1)+length($2), $file, $l, + "$2 with space"); + } + } + + if($nostr =~ /^((.*)(if) *\()(.*)\)/) { + my $pos = length($1); + if($4 =~ / = /) { + checkwarn("ASSIGNWITHINCONDITION", + $line, $pos+1, $file, $l, + "assignment within conditional expression"); + } + } + # check spaces after open parentheses + if($l =~ /^(.*[a-z])\( /i) { + checkwarn("SPACEAFTERPAREN", + $line, length($1)+1, $file, $l, + "space after open parenthesis"); + } + + # check spaces before close parentheses, unless it was a space or a + # close parenthesis! + if($l =~ /(.*[^\) ]) \)/) { + checkwarn("SPACEBEFORECLOSE", + $line, length($1)+1, $file, $l, + "space before close parenthesis"); + } + + # check spaces before comma! + if($l =~ /(.*[^ ]) ,/) { + checkwarn("SPACEBEFORECOMMA", + $line, length($1)+1, $file, $l, + "space before comma"); + } + + # check for "return(" without space + if($l =~ /^(.*)return\(/) { + if($1 =~ / *\#/) { + # this is a #if, treat it differently + } + else { + checkwarn("RETURNNOSPACE", $line, length($1)+6, $file, $l, + "return without space before paren"); + } + } + + # check for "sizeof" without parenthesis + if(($l =~ /^(.*)sizeof *([ (])/) && ($2 ne "(")) { + if($1 =~ / *\#/) { + # this is a #if, treat it differently + } + else { + checkwarn("SIZEOFNOPAREN", $line, length($1)+6, $file, $l, + "sizeof without parenthesis"); + } + } + + # check for comma without space + if($l =~ /^(.*),[^ \n]/) { + my $pref=$1; + my $ign=0; + if($pref =~ / *\#/) { + # this is a #if, treat it differently + $ign=1; + } + elsif($pref =~ /\/\*/) { + # this is a comment + $ign=1; + } + elsif($pref =~ /[\"\']/) { + $ign = 1; + # There is a quote here, figure out whether the comma is + # within a string or '' or not. + if($pref =~ /\"/) { + # within a string + } + elsif($pref =~ /\'$/) { + # a single letter + } + else { + $ign = 0; + } + } + if(!$ign) { + checkwarn("COMMANOSPACE", $line, length($pref)+1, $file, $l, + "comma without following space"); + } + } + + # check for "} else" + if($l =~ /^(.*)\} *else/) { + checkwarn("BRACEELSE", + $line, length($1), $file, $l, "else after closing brace on same line"); + } + # check for "){" + if($l =~ /^(.*)\)\{/) { + checkwarn("PARENBRACE", + $line, length($1)+1, $file, $l, "missing space after close paren"); + } + + # check for space before the semicolon last in a line + if($l =~ /^(.*[^ ].*) ;$/) { + checkwarn("SPACESEMICOLON", + $line, length($1), $file, $ol, "space before last semicolon"); + } + + # scan for use of banned functions + if($l =~ /^(.*\W) + (gets| + strtok| + v?sprintf| + (str|_mbs|_tcs|_wcs)n?cat| + LoadLibrary(Ex)?(A|W)?) + \s*\( + /x) { + checkwarn("BANNEDFUNC", + $line, length($1), $file, $ol, + "use of $2 is banned"); + } + + # scan for use of snprintf for curl-internals reasons + if($l =~ /^(.*\W)(v?snprintf)\s*\(/x) { + checkwarn("SNPRINTF", + $line, length($1), $file, $ol, + "use of $2 is banned"); + } + + # scan for use of non-binary fopen without the macro + if($l =~ /^(.*\W)fopen\s*\([^,]*, *\"([^"]*)/) { + my $mode = $2; + if($mode !~ /b/) { + checkwarn("FOPENMODE", + $line, length($1), $file, $ol, + "use of non-binary fopen without FOPEN_* macro: $mode"); + } + } + + # check for open brace first on line but not first column + # only alert if previous line ended with a close paren and wasn't a cpp + # line + if((($prevl =~ /\)\z/) && ($prevl !~ /^ *#/)) && ($l =~ /^( +)\{/)) { + checkwarn("BRACEPOS", + $line, length($1), $file, $ol, "badly placed open brace"); + } + + # if the previous line starts with if/while/for AND ends with an open + # brace, or an else statement, check that this line is indented $indent + # more steps, if not a cpp line + if($prevl =~ /^( *)((if|while|for)\(.*\{|else)\z/) { + my $first = length($1); + + # this line has some character besides spaces + if(($l !~ /^ *#/) && ($l =~ /^( *)[^ ]/)) { + my $second = length($1); + my $expect = $first+$indent; + if($expect != $second) { + my $diff = $second - $first; + checkwarn("INDENTATION", $line, length($1), $file, $ol, + "not indented $indent steps (uses $diff)"); + + } + } + } + + # check for 'char * name' + if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost) *(\*+)) (\w+)/) && ($4 ne "const")) { + checkwarn("ASTERISKNOSPACE", + $line, length($1), $file, $ol, + "no space after declarative asterisk"); + } + # check for 'char*' + if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost|sockaddr_in|FILE)\*)/)) { + checkwarn("ASTERISKNOSPACE", + $line, length($1)-1, $file, $ol, + "no space before asterisk"); + } + + # check for 'void func() {', but avoid false positives by requiring + # both an open and closed parentheses before the open brace + if($l =~ /^((\w).*)\{\z/) { + my $k = $1; + $k =~ s/const *//; + $k =~ s/static *//; + if($k =~ /\(.*\)/) { + checkwarn("BRACEPOS", + $line, length($l)-1, $file, $ol, + "wrongly placed open brace"); + } + } + + # check for equals sign without spaces next to it + if($nostr =~ /(.*)\=[a-z0-9]/i) { + checkwarn("EQUALSNOSPACE", + $line, length($1)+1, $file, $ol, + "no space after equals sign"); + } + # check for equals sign without spaces before it + elsif($nostr =~ /(.*)[a-z0-9]\=/i) { + checkwarn("NOSPACEEQUALS", + $line, length($1)+1, $file, $ol, + "no space before equals sign"); + } + + # check for plus signs without spaces next to it + if($nostr =~ /(.*)[^+]\+[a-z0-9]/i) { + checkwarn("PLUSNOSPACE", + $line, length($1)+1, $file, $ol, + "no space after plus sign"); + } + # check for plus sign without spaces before it + elsif($nostr =~ /(.*)[a-z0-9]\+[^+]/i) { + checkwarn("NOSPACEPLUS", + $line, length($1)+1, $file, $ol, + "no space before plus sign"); + } + + # check for semicolons without space next to it + if($nostr =~ /(.*)\;[a-z0-9]/i) { + checkwarn("SEMINOSPACE", + $line, length($1)+1, $file, $ol, + "no space after semicolon"); + } + + # check for more than one consecutive space before open brace or + # question mark. Skip lines containing strings since they make it hard + # due to artificially getting multiple spaces + if(($l eq $nostr) && + $nostr =~ /^(.*(\S)) + [{?]/i) { + checkwarn("MULTISPACE", + $line, length($1)+1, $file, $ol, + "multiple space"); + print STDERR "L: $l\n"; + print STDERR "nostr: $nostr\n"; + } + + $line++; + $prevl = $ol; + } + + if(!scalar(@copyright)) { + checkwarn("COPYRIGHT", 1, 0, $file, "", "Missing copyright statement", 1); + } + + # COPYRIGHTYEAR is a extended warning so we must first see if it has been + # enabled in .checksrc + if(defined($warnings{"COPYRIGHTYEAR"})) { + # The check for updated copyrightyear is overly complicated in order to + # not punish current hacking for past sins. The copyright years are + # right now a bit behind, so enforcing copyright year checking on all + # files would cause hundreds of errors. Instead we only look at files + # which are tracked in the Git repo and edited in the workdir, or + # committed locally on the branch without being in upstream master. + # + # The simple and naive test is to simply check for the current year, + # but updating the year even without an edit is against project policy + # (and it would fail every file on January 1st). + # + # A rather more interesting, and correct, check would be to not test + # only locally committed files but inspect all files wrt the year of + # their last commit. Removing the `git rev-list origin/master..HEAD` + # condition below will enfore copyright year checks against the year + # the file was last committed (and thus edited to some degree). + my $commityear = undef; + @copyright = sort {$$b{year} cmp $$a{year}} @copyright; + + if(`git status -s -- $file` =~ /^ [MARCU]/) { + $commityear = (localtime(time))[5] + 1900; + } + elsif (`git rev-list --count origin/master..HEAD -- $file` !~ /^0/) { + my $grl = `git rev-list --max-count=1 --timestamp HEAD -- $file`; + $commityear = (localtime((split(/ /, $grl))[0]))[5] + 1900; + } + + if(defined($commityear) && scalar(@copyright) && + $copyright[0]{year} != $commityear) { + checkwarn("COPYRIGHTYEAR", $copyright[0]{line}, $copyright[0]{col}, + $file, $copyright[0]{code}, + "Copyright year out of date, should be $commityear, " . + "is $copyright[0]{year}", 1); + } + } + + if($incomment) { + checkwarn("OPENCOMMENT", 1, 0, $file, "", "Missing closing comment", 1); + } + + checksrc_endoffile($file); + + close(R); + +} + + +if($errors || $warnings || $verbose) { + printf "checksrc: %d errors and %d warnings\n", $errors, $warnings; + if($suppressed) { + printf "checksrc: %d errors and %d warnings suppressed\n", + $serrors, + $swarnings; + } + exit 5; # return failure +} diff --git a/libcurl/lib/config-amigaos.h b/libcurl/lib/config-amigaos.h new file mode 100644 index 0000000..31cfc3a --- /dev/null +++ b/libcurl/lib/config-amigaos.h @@ -0,0 +1,166 @@ +#ifndef HEADER_CURL_CONFIG_AMIGAOS_H +#define HEADER_CURL_CONFIG_AMIGAOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for AmigaOS */ +/* ================================================================ */ + +#ifdef __AMIGA__ /* Any AmigaOS flavour */ + +#define HAVE_ARPA_INET_H 1 +#define HAVE_CLOSESOCKET_CAMEL 1 +#define HAVE_ERRNO_H 1 +#define HAVE_GETHOSTBYADDR 1 +#define HAVE_INET_ADDR 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_IOCTLSOCKET_CAMEL 1 +#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1 +#define HAVE_LIBCRYPTO 1 +#define HAVE_LIBSSL 1 +#define HAVE_LIBZ 1 +#define HAVE_LONGLONG 1 +#define HAVE_MALLOC_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_OPENSSL_CRYPTO_H 1 +#define HAVE_OPENSSL_ERR_H 1 +#define HAVE_OPENSSL_PEM_H 1 +#define HAVE_OPENSSL_RSA_H 1 +#define HAVE_OPENSSL_SSL_H 1 +#define HAVE_OPENSSL_X509_H 1 +#define HAVE_PERROR 1 +#define HAVE_PWD_H 1 +#define HAVE_RAND_EGD 1 +#define HAVE_RAND_STATUS 1 +#define HAVE_SELECT 1 +#define HAVE_SETJMP_H 1 +#define HAVE_SGTTY_H 1 +#define HAVE_SIGNAL 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SIG_ATOMIC_T 1 +#define HAVE_SOCKET 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRDUP 1 +#define HAVE_STRFTIME 1 +#define HAVE_STRICMP 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRSTR 1 +#define HAVE_STRUCT_TIMEVAL 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_SOCKIO_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UNAME 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UTIME 1 +#define HAVE_UTIME_H 1 +#define HAVE_WRITABLE_ARGV 1 +#define HAVE_ZLIB_H 1 +#define HAVE_SYS_IOCTL_H 1 + +#define NEED_MALLOC_H 1 + +#define SIZEOF_INT 4 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 + +#define USE_MANUAL 1 +#define USE_OPENSSL 1 +#define CURL_DISABLE_LDAP 1 + +#define OS "AmigaOS" + +#define PACKAGE "curl" +#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.haxx.se/mail/" +#define PACKAGE_NAME "curl" +#define PACKAGE_STRING "curl -" +#define PACKAGE_TARNAME "curl" +#define PACKAGE_VERSION "-" +#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt" + +#define RETSIGTYPE void +#define SELECT_TYPE_ARG1 int +#define SELECT_TYPE_ARG234 (fd_set *) +#define SELECT_TYPE_ARG5 (struct timeval *) + +#define STDC_HEADERS 1 +#define TIME_WITH_SYS_TIME 1 + +#define in_addr_t int + +#ifndef F_OK +# define F_OK 0 +#endif + +#ifndef O_RDONLY +# define O_RDONLY 0x0000 +#endif + +#ifndef LONG_MAX +# define LONG_MAX 0x7fffffffL +#endif + +#ifndef LONG_MIN +# define LONG_MIN (-0x7fffffffL-1) +#endif + +#define HAVE_GETNAMEINFO 1 +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 int +#define GETNAMEINFO_TYPE_ARG46 size_t +#define GETNAMEINFO_TYPE_ARG7 int + +#define HAVE_RECV 1 +#define RECV_TYPE_ARG1 long +#define RECV_TYPE_ARG2 char * +#define RECV_TYPE_ARG3 long +#define RECV_TYPE_ARG4 long +#define RECV_TYPE_RETV long + +#define HAVE_RECVFROM 1 +#define RECVFROM_TYPE_ARG1 long +#define RECVFROM_TYPE_ARG2 char +#define RECVFROM_TYPE_ARG3 long +#define RECVFROM_TYPE_ARG4 long +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 long +#define RECVFROM_TYPE_RETV long + +#define HAVE_SEND 1 +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 char * +#define SEND_TYPE_ARG3 int +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV int + +#endif /* __AMIGA__ */ +#endif /* HEADER_CURL_CONFIG_AMIGAOS_H */ diff --git a/libcurl/lib/config-dos.h b/libcurl/lib/config-dos.h new file mode 100644 index 0000000..3e973de --- /dev/null +++ b/libcurl/lib/config-dos.h @@ -0,0 +1,183 @@ +#ifndef HEADER_CURL_CONFIG_DOS_H +#define HEADER_CURL_CONFIG_DOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* ================================================================ */ +/* lib/config-dos.h - Hand crafted config file for DOS */ +/* ================================================================ */ + +#if defined(DJGPP) + #define OS "MSDOS/djgpp" +#elif defined(__HIGHC__) + #define OS "MSDOS/HighC" +#elif defined(__WATCOMC__) + #define OS "MSDOS/Watcom" +#else + #define OS "MSDOS/?" +#endif + +#define PACKAGE "curl" + +#define HAVE_ARPA_INET_H 1 +#define HAVE_ASSERT_H 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FREEADDRINFO 1 +#define HAVE_GETADDRINFO 1 +#define HAVE_GETNAMEINFO 1 +#define HAVE_GETPROTOBYNAME 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_IO_H 1 +#define HAVE_IOCTL 1 +#define HAVE_IOCTL_FIONBIO 1 +#define HAVE_IOCTLSOCKET 1 +#define HAVE_IOCTLSOCKET_FIONBIO 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LONGLONG 1 +#define HAVE_MEMORY_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_NETINET_TCP_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_PROCESS_H 1 +#define HAVE_RECV 1 +#define HAVE_RECVFROM 1 +#define HAVE_SELECT 1 +#define HAVE_SEND 1 +#define HAVE_SETJMP_H 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SETMODE 1 +#define HAVE_SIGNAL 1 +#define HAVE_SOCKET 1 +#define HAVE_STRDUP 1 +#define HAVE_STRICMP 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRUCT_TIMEVAL 1 +#define HAVE_STRUCT_IN6_ADDR 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UNISTD_H 1 + +#define NEED_MALLOC_H 1 + +#define RETSIGTYPE void +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define SIZEOF_LONG_DOUBLE 16 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 +#define SIZEOF_CURL_OFF_T 4 +#define STDC_HEADERS 1 +#define TIME_WITH_SYS_TIME 1 + +/* Qualifiers for send(), recv(), recvfrom() and getnameinfo(). */ + +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void * +#define SEND_TYPE_ARG3 int +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV int + +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void * +#define RECV_TYPE_ARG3 int +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV int + +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 int +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 int +#define RECVFROM_TYPE_RETV int +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 int +#define GETNAMEINFO_TYPE_ARG46 int +#define GETNAMEINFO_TYPE_ARG7 int + +#define BSD + +/* CURLDEBUG definition enables memory tracking */ +/* #define CURLDEBUG */ + +/* USE_ZLIB on cmd-line */ +#ifdef USE_ZLIB + #define HAVE_ZLIB_H 1 + #define HAVE_LIBZ 1 +#endif + +/* USE_OPENSSL on cmd-line */ +#ifdef USE_OPENSSL + #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + #define HAVE_OPENSSL_ENGINE_H 1 + #define OPENSSL_NO_KRB5 1 +#endif + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +#define in_addr_t u_long + +#if defined(__HIGHC__) || \ + (defined(__GNUC__) && (__GNUC__ < 4)) + #define ssize_t int +#endif + +#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE") + +/* Target HAVE_x section */ + +#if defined(DJGPP) + #define HAVE_BASENAME 1 + #define HAVE_STRCASECMP 1 + #define HAVE_SIGACTION 1 + #define HAVE_SIGSETJMP 1 + #define HAVE_SYS_TIME_H 1 + #define HAVE_TERMIOS_H 1 + #define HAVE_VARIADIC_MACROS_GCC 1 + +#elif defined(__WATCOMC__) + #define HAVE_STRCASECMP 1 + +#elif defined(__HIGHC__) + #define HAVE_SYS_TIME_H 1 + #define strerror(e) strerror_s_((e)) +#endif + +#ifdef MSDOS /* Watt-32 */ + #define HAVE_CLOSE_S 1 +#endif + +#undef word +#undef byte + +#endif /* HEADER_CURL_CONFIG_DOS_H */ diff --git a/libcurl/lib/config-mac.h b/libcurl/lib/config-mac.h new file mode 100644 index 0000000..3c12bdf --- /dev/null +++ b/libcurl/lib/config-mac.h @@ -0,0 +1,125 @@ +#ifndef HEADER_CURL_CONFIG_MAC_H +#define HEADER_CURL_CONFIG_MAC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* =================================================================== */ +/* Hand crafted config file for Mac OS 9 */ +/* =================================================================== */ +/* On Mac OS X you must run configure to generate curl_config.h file */ +/* =================================================================== */ + +#define OS "mac" + +/* Define if you want the built-in manual */ +#define USE_MANUAL 1 + +#define HAVE_ERRNO_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_ARPA_INET_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_FCNTL_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_ALLOCA_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UTIME_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_UTIME_H 1 + +#define TIME_WITH_SYS_TIME 1 + +#define HAVE_ALARM 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_UTIME 1 +#define HAVE_SETVBUF 1 +#define HAVE_STRFTIME 1 +#define HAVE_INET_ADDR 1 +#define HAVE_MEMCPY 1 +#define HAVE_SELECT 1 +#define HAVE_SOCKET 1 +#define HAVE_STRUCT_TIMEVAL 1 + +#define HAVE_SIGACTION 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SIG_ATOMIC_T 1 + +#ifdef MACOS_SSL_SUPPORT +# define USE_OPENSSL 1 +#endif + +#define CURL_DISABLE_LDAP 1 + +#define HAVE_RAND_STATUS 1 +#define HAVE_RAND_EGD 1 + +#define HAVE_IOCTL 1 +#define HAVE_IOCTL_FIONBIO 1 + +#define RETSIGTYPE void + +#define SIZEOF_INT 4 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 + +#define HAVE_GETNAMEINFO 1 +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 socklen_t +#define GETNAMEINFO_TYPE_ARG46 size_t +#define GETNAMEINFO_TYPE_ARG7 int + +#define HAVE_RECV 1 +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void * +#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV ssize_t + +#define HAVE_RECVFROM 1 +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 size_t +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 int +#define RECVFROM_TYPE_RETV ssize_t +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define HAVE_SEND 1 +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void * +#define SEND_TYPE_ARG3 size_T +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV ssize_t + +#define HAVE_EXTRA_STRICMP_H 1 +#define HAVE_EXTRA_STRDUP_H 1 + +#endif /* HEADER_CURL_CONFIG_MAC_H */ diff --git a/libcurl/lib/config-os400.h b/libcurl/lib/config-os400.h new file mode 100644 index 0000000..a741e91 --- /dev/null +++ b/libcurl/lib/config-os400.h @@ -0,0 +1,578 @@ +#ifndef HEADER_CURL_CONFIG_OS400_H +#define HEADER_CURL_CONFIG_OS400_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for OS/400 */ +/* ================================================================ */ + +#pragma enum(int) + +#undef PACKAGE + +/* Version number of this archive. */ +#undef VERSION + +/* Define if you have the getpass function. */ +#undef HAVE_GETPASS + +/* Define cpu-machine-OS */ +#define OS "OS/400" + +/* Define if you have the gethostbyaddr_r() function with 5 arguments */ +#define HAVE_GETHOSTBYADDR_R_5 + +/* Define if you have the gethostbyaddr_r() function with 7 arguments */ +#undef HAVE_GETHOSTBYADDR_R_7 + +/* Define if you have the gethostbyaddr_r() function with 8 arguments */ +#undef HAVE_GETHOSTBYADDR_R_8 + +/* OS400 supports a 3-argument ASCII version of gethostbyaddr_r(), but its + * prototype is incompatible with the "standard" one (1st argument is not + * const). However, getaddrinfo() is supported (ASCII version defined as + * a local wrapper in setup-os400.h) in a threadsafe way: we can then + * configure getaddrinfo() as such and get rid of gethostbyname_r() without + * loss of threadsafeness. */ +#undef HAVE_GETHOSTBYNAME_R +#undef HAVE_GETHOSTBYNAME_R_3 +#undef HAVE_GETHOSTBYNAME_R_5 +#undef HAVE_GETHOSTBYNAME_R_6 +#define HAVE_GETADDRINFO +#define HAVE_GETADDRINFO_THREADSAFE + +/* Define if you need the _REENTRANT define for some functions */ +#undef NEED_REENTRANT + +/* Define if you have the Kerberos4 libraries (including -ldes) */ +#undef HAVE_KRB4 + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define this to 'int' if ssize_t is not an available typedefed type */ +#undef ssize_t + +/* Define this as a suitable file to read random data from */ +#undef RANDOM_FILE + +/* Define this to your Entropy Gathering Daemon socket pathname */ +#undef EGD_SOCKET + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Define if you have the header file. */ +#define HAVE_ARPA_INET_H + +/* Define if you have the `closesocket' function. */ +#undef HAVE_CLOSESOCKET + +/* Define if you have the header file. */ +#undef HAVE_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_DES_H + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_ERR_H + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the `geteuid' function. */ +#define HAVE_GETEUID + +/* Define if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR + +/* Define if you have the `gethostbyaddr_r' function. */ +#define HAVE_GETHOSTBYADDR_R + +/* Define if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME + +/* Define if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define if you have the `getpass_r' function. */ +#undef HAVE_GETPASS_R + +/* Define to 1 if you have the getpeername function. */ +#define HAVE_GETPEERNAME 1 + +/* Define if you have the `getpwuid' function. */ +#define HAVE_GETPWUID + +/* Define if you have the `getservbyname' function. */ +#define HAVE_GETSERVBYNAME + +/* Define to 1 if you have the getsockname function. */ +#define HAVE_GETSOCKNAME 1 + +/* Define if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY + +/* Define if you have the `timeval' struct. */ +#define HAVE_STRUCT_TIMEVAL + +/* Define if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR + +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H + +/* Define if you have the header file. */ +#undef HAVE_IO_H + +/* Define if you have the `krb_get_our_ip_for_realm' function. */ +#undef HAVE_KRB_GET_OUR_IP_FOR_REALM + +/* Define if you have the header file. */ +#undef HAVE_KRB_H + +/* Define if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define if you have the `resolve' library (-lresolve). */ +#undef HAVE_LIBRESOLVE + +/* Define if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* Define if you have GSS API. */ +#define HAVE_GSSAPI + +/* Define if you have the GNU gssapi libraries */ +#undef HAVE_GSSGNU + +/* Define if you have the Heimdal gssapi libraries */ +#define HAVE_GSSHEIMDAL + +/* Define if you have the MIT gssapi libraries */ +#undef HAVE_GSSMIT + +/* Define if you have the `ucb' library (-lucb). */ +#undef HAVE_LIBUCB + +/* Define if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R + +/* Define if you have the header file. */ +#define HAVE_MALLOC_H + +/* Define if you need the malloc.h header file even with stdlib.h */ +/* #define NEED_MALLOC_H 1 */ + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#define HAVE_NETDB_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_X509_H + +/* Define if you have the header file. */ +#undef HAVE_PEM_H + +/* Define if you have the `perror' function. */ +#define HAVE_PERROR + +/* Define if you have the header file. */ +#define HAVE_PWD_H + +/* Define if you have the `RAND_egd' function. */ +#undef HAVE_RAND_EGD + +/* Define if you have the `RAND_screen' function. */ +#undef HAVE_RAND_SCREEN + +/* Define if you have the `RAND_status' function. */ +#undef HAVE_RAND_STATUS + +/* Define if you have the header file. */ +#undef HAVE_RSA_H + +/* Define if you have the `select' function. */ +#define HAVE_SELECT + +/* Define if you have the `setvbuf' function. */ +#define HAVE_SETVBUF + +/* Define if you have the header file. */ +#undef HAVE_SGTTY_H + +/* Define if you have the `sigaction' function. */ +#define HAVE_SIGACTION + +/* Define if you have the `signal' function. */ +#undef HAVE_SIGNAL + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T + +/* Define if sig_atomic_t is already defined as volatile. */ +#undef HAVE_SIG_ATOMIC_T_VOLATILE + +/* Define if you have the `socket' function. */ +#define HAVE_SOCKET + +/* Define if you have the header file. */ +#undef HAVE_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H + + +/* The following define is needed on OS400 to enable strcmpi(), stricmp() and + strdup(). */ +#define __cplusplus__strings__ + +/* Define if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the `strcmpi' function. */ +#define HAVE_STRCMPI + +/* Define if you have the `stricmp' function. */ +#define HAVE_STRICMP + +/* Define if you have the `strdup' function. */ +#define HAVE_STRDUP + + +/* Define if you have the `strftime' function. */ +#define HAVE_STRFTIME + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H + +/* Define if you have the header file. */ +#define HAVE_STRING_H + +/* Define if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define if you have the header file. */ +#undef HAVE_STROPTS_H + +/* Define if you have the `strstr' function. */ +#define HAVE_STRSTR + +/* Define if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R + +/* Define if you have the `strtoll' function. */ +#undef HAVE_STRTOLL /* Allows ASCII compile on V5R1. */ + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H + +/* Define if you have the `tcgetattr' function. */ +#undef HAVE_TCGETATTR + +/* Define if you have the `tcsetattr' function. */ +#undef HAVE_TCSETATTR + +/* Define if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define if you have the header file. */ +#define HAVE_TIME_H + +/* Define if you have the `uname' function. */ +#undef HAVE_UNAME + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_WINSOCK_H + +/* Define if you have the header file. */ +#undef HAVE_X509_H + +/* Name of package */ +#undef PACKAGE + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 8 + +/* Define if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG + +/* The size of a `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `curl_off_t', as computed by sizeof. */ +#define SIZEOF_CURL_OFF_T 8 + +/* Whether long long constants must be suffixed by LL. */ + +#define HAVE_LL + +/* Define this if you have struct sockaddr_storage */ +#define HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME + +/* Define to enable alt-svc support (experimental) */ +#undef USE_ALTSVC + +/* Version number of package */ +#undef VERSION + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#define _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* type to use in place of in_addr_t if not defined */ +#define in_addr_t unsigned long + +/* Define to `unsigned' if does not define. */ +#undef size_t + +/* Define if you have the ioctl function. */ +#define HAVE_IOCTL + +/* Define if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO + +/* Define if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR + +/* To disable LDAP */ +#undef CURL_DISABLE_LDAP + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL + +/* Define if you have the ldap_url_parse procedure. */ +/* #define HAVE_LDAP_URL_PARSE */ /* Disabled because of an IBM bug. */ + +/* Define if you have the getnameinfo function. */ +/* OS400 has no ASCII version of this procedure: wrapped in setup-os400.h. */ +#define HAVE_GETNAMEINFO + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 socklen_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* Define to use the GSKit package. */ +#define USE_GSKIT + +/* Define to use the OS/400 crypto library. */ +#define USE_OS400CRYPTO + +/* Define to use Unix sockets. */ +#define USE_UNIX_SOCKETS + +/* Use the system keyring as the default CA bundle. */ +#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB" + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* The following must be defined BEFORE system header files inclusion. */ + +#define __ptr128 /* No teraspace. */ +#define qadrt_use_fputc_inline /* Generate fputc() wrapper inline. */ +#define qadrt_use_fread_inline /* Generate fread() wrapper inline. */ +#define qadrt_use_fwrite_inline /* Generate fwrite() wrapper inline. */ + +#endif /* HEADER_CURL_CONFIG_OS400_H */ diff --git a/libcurl/lib/config-riscos.h b/libcurl/lib/config-riscos.h new file mode 100644 index 0000000..0379524 --- /dev/null +++ b/libcurl/lib/config-riscos.h @@ -0,0 +1,513 @@ +#ifndef HEADER_CURL_CONFIG_RISCOS_H +#define HEADER_CURL_CONFIG_RISCOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for RISC OS */ +/* ================================================================ */ + +/* Name of this package! */ +#undef PACKAGE + +/* Version number of this archive. */ +#undef VERSION + +/* Define if you have the getpass function. */ +#undef HAVE_GETPASS + +/* Define cpu-machine-OS */ +#define OS "ARM-RISC OS" + +/* Define if you want the built-in manual */ +#define USE_MANUAL + +/* Define if you have the gethostbyaddr_r() function with 5 arguments */ +#undef HAVE_GETHOSTBYADDR_R_5 + +/* Define if you have the gethostbyaddr_r() function with 7 arguments */ +#undef HAVE_GETHOSTBYADDR_R_7 + +/* Define if you have the gethostbyaddr_r() function with 8 arguments */ +#undef HAVE_GETHOSTBYADDR_R_8 + +/* Define if you have the gethostbyname_r() function with 3 arguments */ +#undef HAVE_GETHOSTBYNAME_R_3 + +/* Define if you have the gethostbyname_r() function with 5 arguments */ +#undef HAVE_GETHOSTBYNAME_R_5 + +/* Define if you have the gethostbyname_r() function with 6 arguments */ +#undef HAVE_GETHOSTBYNAME_R_6 + +/* Define if you need the _REENTRANT define for some functions */ +#undef NEED_REENTRANT + +/* Define if you have the Kerberos4 libraries (including -ldes) */ +#undef HAVE_KRB4 + +/* Define if you want to enable IPv6 support */ +#undef ENABLE_IPV6 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define this to 'int' if ssize_t is not an available typedefed type */ +#undef ssize_t + +/* Define this as a suitable file to read random data from */ +#undef RANDOM_FILE + +/* Define this to your Entropy Gathering Daemon socket pathname */ +#undef EGD_SOCKET + +/* Define if you want to enable IPv6 support */ +#undef ENABLE_IPV6 + +/* Define if you have the alarm function. */ +#define HAVE_ALARM + +/* Define if you have the header file. */ +#define HAVE_ALLOCA_H + +/* Define if you have the header file. */ +#define HAVE_ARPA_INET_H + +/* Define if you have the `closesocket' function. */ +#undef HAVE_CLOSESOCKET + +/* Define if you have the header file. */ +#undef HAVE_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_DES_H + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_ERR_H + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE + +/* Define if getaddrinfo exists and works */ +#define HAVE_GETADDRINFO + +/* Define if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR + +/* Define if you have the `gethostbyaddr_r' function. */ +#undef HAVE_GETHOSTBYADDR_R + +/* Define if you have the `gethostbyname_r' function. */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME + +/* Define if you have the header file. */ +#define HAVE_GETOPT_H + +/* Define if you have the `getpass_r' function. */ +#undef HAVE_GETPASS_R + +/* Define if you have the `getpwuid' function. */ +#undef HAVE_GETPWUID + +/* Define if you have the `getservbyname' function. */ +#undef HAVE_GETSERVBYNAME + +/* Define if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY + +/* Define if you have the `timeval' struct. */ +#define HAVE_STRUCT_TIMEVAL + +/* Define if you have the `inet_addr' function. */ +#undef HAVE_INET_ADDR + +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H + +/* Define if you have the header file. */ +#undef HAVE_IO_H + +/* Define if you have the `krb_get_our_ip_for_realm' function. */ +#undef HAVE_KRB_GET_OUR_IP_FOR_REALM + +/* Define if you have the header file. */ +#undef HAVE_KRB_H + +/* Define if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define if you have the `resolve' library (-lresolve). */ +#undef HAVE_LIBRESOLVE + +/* Define if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* Define if you have the `ucb' library (-lucb). */ +#undef HAVE_LIBUCB + +/* Define if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define if you have the header file. */ +#define HAVE_MALLOC_H + +/* Define if you need the malloc.h header file even with stdlib.h */ +/* #define NEED_MALLOC_H 1 */ + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#define HAVE_NETDB_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_X509_H + +/* Define if you have the header file. */ +#undef HAVE_PEM_H + +/* Define if you have the `perror' function. */ +#undef HAVE_PERROR + +/* Define if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if you have the `RAND_egd' function. */ +#undef HAVE_RAND_EGD + +/* Define if you have the `RAND_screen' function. */ +#undef HAVE_RAND_SCREEN + +/* Define if you have the `RAND_status' function. */ +#undef HAVE_RAND_STATUS + +/* Define if you have the header file. */ +#undef HAVE_RSA_H + +/* Define if you have the `select' function. */ +#define HAVE_SELECT + +/* Define if you have the `setvbuf' function. */ +#undef HAVE_SETVBUF + +/* Define if you have the header file. */ +#define HAVE_SGTTY_H + +/* Define if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define if you have the `signal' function. */ +#define HAVE_SIGNAL + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T + +/* Define if sig_atomic_t is already defined as volatile. */ +#undef HAVE_SIG_ATOMIC_T_VOLATILE + +/* Define if you have the `socket' function. */ +#define HAVE_SOCKET + +/* Define if you have the header file. */ +#undef HAVE_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the `strcmpi' function. */ +#undef HAVE_STRCMPI + +/* Define if you have the `strdup' function. */ +#define HAVE_STRDUP + +/* Define if you have the `strftime' function. */ +#define HAVE_STRFTIME + +/* Define if you have the `stricmp' function. */ +#define HAVE_STRICMP + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#define HAVE_STRING_H + +/* Define if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define if you have the `strstr' function. */ +#define HAVE_STRSTR + +/* Define if you have the `strtok_r' function. */ +#undef HAVE_STRTOK_R + +/* Define if you have the `strtoll' function. */ +#undef HAVE_STRTOLL + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H + +/* Define if you have the `tcgetattr' function. */ +#define HAVE_TCGETATTR + +/* Define if you have the `tcsetattr' function. */ +#define HAVE_TCSETATTR + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the `uname' function. */ +#define HAVE_UNAME + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_WINSOCK_H + +/* Define if you have the header file. */ +#undef HAVE_X509_H + +/* Name of package */ +#undef PACKAGE + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long double', as computed by sizeof. */ +#undef SIZEOF_LONG_DOUBLE + +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define if you have the ioctl function. */ +#define HAVE_IOCTL + +/* Define if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP + +/* Define if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV ssize_t + +/* Define 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV ssize_t + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV ssize_t + +#endif /* HEADER_CURL_CONFIG_RISCOS_H */ diff --git a/libcurl/lib/config-symbian.h b/libcurl/lib/config-symbian.h new file mode 100644 index 0000000..b7b93c6 --- /dev/null +++ b/libcurl/lib/config-symbian.h @@ -0,0 +1,805 @@ +#ifndef HEADER_CURL_CONFIG_SYMBIAN_H +#define HEADER_CURL_CONFIG_SYMBIAN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for Symbian */ +/* ================================================================ */ + +/* Location of default ca bundle */ +/* #define CURL_CA_BUNDLE "/etc/pki/tls/certs/ca-bundle.crt"*/ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +/* #undef CURL_DISABLE_FTP */ + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable TELNET */ +/* #undef CURL_DISABLE_TELNET */ + +/* to disable TFTP */ +/* #undef CURL_DISABLE_TFTP */ + +/* to disable verbose strings */ +/* #define CURL_DISABLE_VERBOSE_STRINGS 1*/ + +/* Definition to make a library symbol externally visible. */ +/* #undef CURL_EXTERN_SYMBOL */ + +/* Use Windows LDAP implementation */ +/* #undef USE_WIN32_LDAP */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define to 1 if you have the header file. */ +/*#define HAVE_ALLOCA_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_ARPA_TFTP_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +/*#define HAVE_BASENAME 1*/ + +/* Define to 1 if bool is an available type. */ +/*#define HAVE_BOOL_T 1*/ + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/*#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1*/ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/*#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +/*#define HAVE_FORK 1*/ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define if getaddrinfo exists and works */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* If you have gethostbyname */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +/*#define HAVE_GETRLIMIT 1*/ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* we have a glibc-style strerror_r() */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/*#define HAVE_IDNA_STRERROR 1*/ + +/* Define to 1 if you have the `idn_free' function. */ +/*#define HAVE_IDN_FREE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_IDN_FREE_H 1*/ + +/* Define to 1 if you have the `inet_addr' function. */ +/*#define HAVE_INET_ADDR 1*/ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/*#define HAVE_INET_NTOP 1*/ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/*#define HAVE_INET_PTON 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO + function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/*#define HAVE_LBER_H 1*/ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/*#define HAVE_LDAP_H 1*/ + +/* Use LDAPS implementation */ +/*#define HAVE_LDAP_SSL 1*/ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/*#define HAVE_LDAP_URL_PARSE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_LIBGEN_H 1*/ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/*#define HAVE_LIBIDN 1*/ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/*#define HAVE_LIBSSH2 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_LIBSSH2_H 1*/ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/*#define HAVE_LIBSSL 1*/ + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +/*#define HAVE_MALLOC_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/*#define HAVE_MSG_NOSIGNAL 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_NETINET_TCP_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/*#define HAVE_NI_WITHSCOPEID 1*/ + +/* we have no strerror_r() proto */ +/* #undef HAVE_NO_STRERROR_R_DECL */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_CRYPTO_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_ENGINE_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_ERR_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_PEM_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_PKCS12_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_RSA_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_SSL_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_X509_H 1*/ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `poll' function. */ +/*#define HAVE_POLL 1*/ + +/* If you have a fine poll */ +/*#define HAVE_POLL_FINE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_POLL_H 1*/ + +/* we have a POSIX-style strerror_r() */ +#define HAVE_POSIX_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/*#define HAVE_RAND_STATUS 1*/ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +/* #undef HAVE_SETMODE */ + +/* Define to 1 if you have the `setrlimit' function. */ +/*#define HAVE_SETRLIMIT 1*/ + +/* Define to 1 if you have the setsockopt function. */ +/* #undef HAVE_SETSOCKOPT */ + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_SGTTY_H 1*/ + +/* Define to 1 if you have the `sigaction' function. */ +/*#define HAVE_SIGACTION 1*/ + +/* Define to 1 if you have the `siginterrupt' function. */ +/*#define HAVE_SIGINTERRUPT 1*/ + +/* Define to 1 if you have the `signal' function. */ +/*#define HAVE_SIGNAL 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* If you have sigsetjmp */ +/*#define HAVE_SIGSETJMP 1*/ + +/* Define to 1 if sig_atomic_t is an available typedef. */ +/*#define HAVE_SIG_ATOMIC_T 1*/ + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#define HAVE_STRLCPY 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_SYS_POLL_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TERMIOS_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TERMIO_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TLD_H 1*/ + +/* Define to 1 if you have the `tld_strerror' function. */ +/*#define HAVE_TLD_STRERROR 1*/ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +/*#define HAVE_VARIADIC_MACROS_GCC 1*/ + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +/*#define HAVE_WRITABLE_ARGV 1*/ + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* cpu-machine-OS */ +#ifdef __WINS__ +#define OS "i386-pc-epoc32" +#elif __MARM__ +#define OS "arm-unknown-epoc32" +#else +/* This won't happen on any current Symbian version */ +#define OS "unknown-unknown-epoc32" +#endif + +/* Name of package */ +/*#define PACKAGE "curl"*/ + +/* Define to the address where bug reports for this package should be sent. */ +/*#define PACKAGE_BUGREPORT \ + "a suitable curl mailing list => https://curl.haxx.se/mail/"*/ + +/* Define to the full name of this package. */ +/*#define PACKAGE_NAME "curl"*/ + +/* Define to the full name and version of this package. */ +/*#define PACKAGE_STRING "curl -"*/ + +/* Define to the one symbol short name of this package. */ +/*#define PACKAGE_TARNAME "curl"*/ + +/* Define to the version of this package. */ +/*#define PACKAGE_VERSION "-"*/ + +/* a suitable file to read random data from */ +/*#define RANDOM_FILE "/dev/urandom"*/ + +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void * +#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV ssize_t + +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 size_t +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 size_t +#define RECVFROM_TYPE_RETV ssize_t +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void * +#define SEND_TYPE_ARG3 size_t +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV ssize_t + + +/* Define as the return type of signal handlers (`int' or `void'). */ +/*#define RETSIGTYPE void*/ + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable c-ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if libSSH2 is in use */ +/*#define USE_LIBSSH2 1*/ + +/* If you want to build curl with the built-in manual */ +/*#define USE_MANUAL 1*/ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +/*#define VERSION "7.18.2-CVS"*/ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* type to use in place of in_addr_t if not defined */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +/* Enabling curl debug mode when building in Symbian debug mode would work */ +/* except that debug mode introduces new exports that must be frozen. */ +#ifdef _DEBUG +/* #define CURLDEBUG */ +#endif + +/* sys/cdefs.h fails to define this for WINSCW prior to Symbian OS ver. 9.4 */ +#ifndef __LONG_LONG_SUPPORTED +#define __LONG_LONG_SUPPORTED +#endif + +/* Enable appropriate header only when zlib support is enabled */ +#ifdef HAVE_LIBZ +#define HAVE_ZLIB_H 1 +#endif + +#endif /* HEADER_CURL_CONFIG_SYMBIAN_H */ diff --git a/libcurl/lib/config-tpf.h b/libcurl/lib/config-tpf.h new file mode 100644 index 0000000..778d983 --- /dev/null +++ b/libcurl/lib/config-tpf.h @@ -0,0 +1,772 @@ +#ifndef HEADER_CURL_CONFIG_TPF_H +#define HEADER_CURL_CONFIG_TPF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for TPF */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* FEATURES, FUNCTIONS, and DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* NOTE: Refer also to the .mak file for some of the flags below */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +/* #undef CURL_DISABLE_FTP */ + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +/* #undef CURL_DISABLE_LDAP */ + +/* to disable TELNET */ +/* #undef CURL_DISABLE_TELNET */ + +/* to disable TFTP */ +/* #undef CURL_DISABLE_TFTP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* lber dynamic library file */ +/* #undef DL_LBER_FILE */ + +/* ldap dynamic library file */ +/* #undef DL_LDAP_FILE */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ + +/* Define to the type of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG1 */ + +/* Define to the type of arg 2 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG2 */ + +/* Define to the type of args 4 and 6 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG46 */ + +/* Define to the type of arg 7 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG7 */ + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ +#define HAVE_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ +#define HAVE_DES_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ +#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ +#define HAVE_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +/* #undef HAVE_FORK */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define if getaddrinfo exists and works */ +/* #undef HAVE_GETADDRINFO */ + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* If you have gethostbyname */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 1 */ + +/* Define to 1 if you have the getnameinfo function. */ +/* #undef HAVE_GETNAMEINFO */ + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getprotobyname' function. */ +/* #undef HAVE_GETPROTOBYNAME */ + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +/* #undef HAVE_GETRLIMIT */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* we have a glibc-style strerror_r() */ +/* #undef HAVE_GLIBC_STRERROR_R */ +#define HAVE_GLIBC_STRERROR_R 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `iconv' functions. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/* #undef HAVE_INET_NTOP */ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/* #undef HAVE_INET_PTON */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO + function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBGEN_H 1 */ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ +#define HAVE_LIBSSL 1 + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if NI_WITHSCOPEID exists and works */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* we have no strerror_r() proto */ +/* #undef HAVE_NO_STRERROR_R_DECL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ +#define HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ +#define HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ +#define HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ +#define HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ +#define HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ +#define HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ +#define HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ +#define HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ +#define HAVE_PEM_H 1 + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `poll' function. */ +/* #undef HAVE_POLL */ + +/* If you have a fine poll */ +/* #undef HAVE_POLL_FINE */ + +/* we have a POSIX-style strerror_r() */ +/* #undef HAVE_POSIX_STRERROR_R */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ +#define HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ +#define HAVE_RSA_H 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +/* #undef HAVE_SETSOCKOPT */ + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SGTTY_H 1 */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `siginterrupt' function. */ +/* #undef HAVE_SIGINTERRUPT */ + +/* Define to 1 if you have the `signal' function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* If you have sigsetjmp */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ +#define HAVE_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ +#define HAVE_STRICMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE */ + +/* Define this if you have struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +/* #undef HAVE_WRITABLE_ARGV */ + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* cpu-machine-OS */ +#define OS "s390x-ibm-tpf" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT \ + "a suitable curl mailing list => https://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Define to the size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* If you want to build curl with the built-in manual */ +/* #undef USE_MANUAL */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if SSL is enabled */ +/* #undef USE_OPENSSL */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Version number of package */ +#define VERSION "not-used" + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* type to use in place of in_addr_t if not defined */ +/* #undef in_addr_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +/* Define to 1 if you have the getnameinfo function. */ +/* #undef HAVE_GETNAMEINFO 1 */ + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_QUAL_ARG1 const */ + +/* Define to the type of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG1 struct sockaddr * */ + +/* Define to the type of arg 2 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG2 socklen_t */ + +/* Define to the type of args 4 and 6 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG46 size_t */ + +/* Define to the type of arg 7 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG7 int */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +#define CURL_DOES_CONVERSIONS +#ifndef CURL_ICONV_CODESET_OF_HOST +#define CURL_ICONV_CODESET_OF_HOST "IBM-1047" +#endif + + +#endif /* HEADER_CURL_CONFIG_TPF_H */ diff --git a/libcurl/lib/config-vxworks.h b/libcurl/lib/config-vxworks.h new file mode 100644 index 0000000..89af352 --- /dev/null +++ b/libcurl/lib/config-vxworks.h @@ -0,0 +1,916 @@ +#ifndef HEADER_CURL_CONFIG_VXWORKS_H +#define HEADER_CURL_CONFIG_VXWORKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* =============================================================== */ +/* Hand crafted config file for VxWorks */ +/* =============================================================== */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable NTLM authentication */ +#define CURL_DISABLE_NTLM 1 + +/* to disable proxies */ +/* #undef CURL_DISABLE_PROXY */ + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +/* #undef CURL_EXTERN_SYMBOL */ + +/* Use Windows LDAP implementation */ +/* #undef USE_WIN32_LDAP */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 unsigned int + +/* Specifies the number of arguments to getservbyport_r */ +#define GETSERVBYPORT_R_ARGS 6 + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#define GETSERVBYPORT_R_BUFSIZE 4096 + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +/* #undef HAVE_BASENAME */ + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */ + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +/* #undef HAVE_GETEUID */ + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#define HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +#define HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +/* #undef HAVE_GETIFADDRS */ + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +/* #undef HAVE_GETPWUID */ + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IFADDRS_H */ + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/* #undef HAVE_INET_NTOP */ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/* #undef HAVE_INET_PTON */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBGEN_H */ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `libssh2_version' function. */ +/* #undef HAVE_LIBSSH2_VERSION */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#define HAVE_LIBSSL 1 + +/* if zlib is available */ +#define HAVE_LIBZ 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/* #undef HAVE_MSG_NOSIGNAL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +/* #undef HAVE_POLL */ + +/* If you have a fine poll */ +/* #undef HAVE_POLL_FINE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_POLL_H */ + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +/* #undef HAVE_POSIX_STRERROR_R */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 if you have the `RAND_egd' function. */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +#define HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SGTTY_H */ + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +/* #undef HAVE_STRTOLL */ + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_PARAM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_TIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have a working vxworks-style strerror_r function. */ +#define HAVE_VXWORKS_STRERROR_R 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +#define HAVE_ZLIB_H 1 + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to 1 if the open function requires three arguments. */ +#define OPEN_NEEDS_ARG3 1 + +/* cpu-machine-OS */ +#define OS "unknown-unknown-vxworks" + +/* Name of package */ +#define PACKAGE "curl" + +/* a suitable file to read random data from */ +#define RANDOM_FILE "/dev/urandom" + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG5_IS_VOID */ + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 socklen_t + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG6_IS_VOID */ + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +/* #undef STRERROR_R_TYPE_ARG3 */ + +/* Define to 1 if you can safely include both and . */ +/* #undef TIME_WITH_SYS_TIME */ + +/* Define if you want to enable c-ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets. */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* if OpenSSL is in use */ +#define USE_OPENSSL 1 + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +#endif /* HEADER_CURL_CONFIG_VXWORKS_H */ diff --git a/libcurl/lib/config-win32.h b/libcurl/lib/config-win32.h new file mode 100644 index 0000000..4209167 --- /dev/null +++ b/libcurl/lib/config-win32.h @@ -0,0 +1,783 @@ +#ifndef HEADER_CURL_CONFIG_WIN32_H +#define HEADER_CURL_CONFIG_WIN32_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define CURL_DISABLE_LDAP 1 +#define CURL_DISABLE_TELNET 1 +#define CURL_DISABLE_KERBEROS_AUTH 1 +#define CURL_DISABLE_AWS 1 +#define CURL_DISABLE_CA_SEARCH 1 +#define CURL_DISABLE_DICT 1 +#define CURL_DISABLE_DOH 1 +#define CURL_DISABLE_GOPHER 1 +#define CURL_DISABLE_HSTS 1 +#define CURL_DISABLE_IMAP 1 +#define CURL_DISABLE_LDAPS 1 +#define CURL_DISABLE_RTSP 1 +#define CURL_DISABLE_DIGEST_AUTH 1 +#define CURL_DISABLE_BASIC_AUTH 1 +#define CURL_DISABLE_BEARER_AUTH 1 +#define CURL_DISABLE_CRYPTO_AUTH 1 +#define CURL_DISABLE_VERBOSE_STRINGS 1 +#define CURL_DISABLE_POP3 1 +#define CURL_DISABLE_NTLM 1 +#define CURL_DISABLE_MQTT 1 +#define CURL_DISABLE_TFTP 1 +#define CURL_DISABLE_SMB 1 +#define HTTP_ONLY 1 + +/* ================================================================ */ +/* Hand crafted config file for Windows */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* HEADER FILES */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the header file. */ +/* #define HAVE_ARPA_INET_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_CRYPTO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_ERR_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__POCC__) +#define HAVE_GETOPT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_INTTYPES_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you need header even with header file. */ +#if !defined(__SALFORDC__) && !defined(__POCC__) +#define NEED_MALLOC_H 1 +#endif + +/* Define if you have the header file. */ +/* #define HAVE_NETDB_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_NETINET_IN_H 1 */ + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_PROCESS_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SGTTY_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SSL_H 1 */ + +/* Define to 1 if you have the header file. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_STDBOOL_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKIO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#ifndef __BORLANDC__ +#define HAVE_SYS_UTIME_H 1 +#endif + +/* Define if you have the header file. */ +/* #define HAVE_TERMIO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_TERMIOS_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) || \ + defined(__POCC__) +#define HAVE_UNISTD_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define if you have the header file. */ +#define HAVE_WINSOCK_H 1 + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_WINSOCK2_H 1 +#endif + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_WS2TCPIP_H 1 +#endif + +/* ---------------------------------------------------------------- */ +/* OTHER HEADER INFO */ +/* ---------------------------------------------------------------- */ + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +/* #define TIME_WITH_SYS_TIME 1 */ + +/* Define to 1 if bool is an available type. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_BOOL_T 1 +#endif + +/* ---------------------------------------------------------------- */ +/* FUNCTIONS */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the closesocket function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #define HAVE_DOPRNT 1 */ + +/* Define if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `getpeername' function. */ +#define HAVE_GETPEERNAME 1 + +/* Define to 1 if you have the getsockname function. */ +#define HAVE_GETSOCKNAME 1 + +/* Define if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the getpass function. */ +/* #define HAVE_GETPASS 1 */ + +/* Define if you have the getservbyname function. */ +#define HAVE_GETSERVBYNAME 1 + +/* Define if you have the getprotobyname function. */ +#define HAVE_GETPROTOBYNAME + +/* Define if you have the gettimeofday function. */ +/* #define HAVE_GETTIMEOFDAY 1 */ + +/* Define if you have the inet_addr function. */ +#define HAVE_INET_ADDR 1 + +/* Define if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define if you have the perror function. */ +#define HAVE_PERROR 1 + +/* Define if you have the RAND_screen function when using SSL. */ +#define HAVE_RAND_SCREEN 1 + +/* Define if you have the `RAND_status' function when using SSL. */ +#define HAVE_RAND_STATUS 1 + +/* Define if you have the `CRYPTO_cleanup_all_ex_data' function. + This is present in OpenSSL versions after 0.9.6b */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the setlocale function. */ +#define HAVE_SETLOCALE 1 + +/* Define if you have the setmode function. */ +#define HAVE_SETMODE 1 + +/* Define if you have the setvbuf function. */ +#define HAVE_SETVBUF 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strcasecmp function. */ +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have the stricmp function. */ +#define HAVE_STRICMP 1 + +/* Define if you have the strncasecmp function. */ +/* #define HAVE_STRNCASECMP 1 */ + +/* Define if you have the strnicmp function. */ +#define HAVE_STRNICMP 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtoll function. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__POCC__) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1800)) +#define HAVE_STRTOLL 1 +#endif + +/* Define if you have the tcgetattr function. */ +/* #define HAVE_TCGETATTR 1 */ + +/* Define if you have the tcsetattr function. */ +/* #define HAVE_TCSETATTR 1 */ + +/* Define if you have the utime function. */ +#ifndef __BORLANDC__ +#define HAVE_UTIME 1 +#endif + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 DWORD + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* ---------------------------------------------------------------- */ +/* TYPEDEF REPLACEMENTS */ +/* ---------------------------------------------------------------- */ + +/* Define if in_addr_t is not an available 'typedefed' type. */ +#define in_addr_t unsigned long + +/* Define to the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define if ssize_t is not an available 'typedefed' type. */ +#ifndef _SSIZE_T_DEFINED +# if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || \ + defined(__POCC__) || \ + defined(__MINGW32__) +# elif defined(_WIN64) +# define _SSIZE_T_DEFINED +# define ssize_t __int64 +# else +# define _SSIZE_T_DEFINED +# define ssize_t int +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* TYPE SIZES */ +/* ---------------------------------------------------------------- */ + +/* Define to the size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* Define to the size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* Define to the size of `long long', as computed by sizeof. */ +/* #define SIZEOF_LONG_LONG 8 */ + +/* Define to the size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Define to the size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Define to the size of `size_t', as computed by sizeof. */ +#if defined(_WIN64) +# define SIZEOF_SIZE_T 8 +#else +# define SIZEOF_SIZE_T 4 +#endif + +/* Define to the size of `curl_off_t', as computed by sizeof. */ +#define SIZEOF_CURL_OFF_T 8 + +/* ---------------------------------------------------------------- */ +/* BSD-style lwIP TCP/IP stack SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Define to use BSD-style lwIP TCP/IP stack. */ +/* #define USE_LWIPSOCK 1 */ + +#ifdef USE_LWIPSOCK +# undef USE_WINSOCK +# undef HAVE_WINSOCK_H +# undef HAVE_WINSOCK2_H +# undef HAVE_WS2TCPIP_H +# undef HAVE_ERRNO_H +# undef HAVE_GETHOSTNAME +# undef HAVE_GETNAMEINFO +# undef LWIP_POSIX_SOCKETS_IO_NAMES +# undef RECV_TYPE_ARG1 +# undef RECV_TYPE_ARG3 +# undef SEND_TYPE_ARG1 +# undef SEND_TYPE_ARG3 +# define HAVE_FREEADDRINFO +# define HAVE_GETADDRINFO +# define HAVE_GETHOSTBYNAME +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GETHOSTBYNAME_R_6 +# define LWIP_POSIX_SOCKETS_IO_NAMES 0 +# define RECV_TYPE_ARG1 int +# define RECV_TYPE_ARG3 size_t +# define SEND_TYPE_ARG1 int +# define SEND_TYPE_ARG3 size_t +#endif + +/* ---------------------------------------------------------------- */ +/* Watt-32 tcp/ip SPECIFIC */ +/* ---------------------------------------------------------------- */ + +#ifdef USE_WATT32 + #include + #undef byte + #undef word + #undef USE_WINSOCK + #undef HAVE_WINSOCK_H + #undef HAVE_WINSOCK2_H + #undef HAVE_WS2TCPIP_H + #define HAVE_GETADDRINFO + #define HAVE_GETNAMEINFO + #define HAVE_SYS_IOCTL_H + #define HAVE_SYS_SOCKET_H + #define HAVE_NETINET_IN_H + #define HAVE_NETDB_H + #define HAVE_ARPA_INET_H + #define HAVE_FREEADDRINFO + #define SOCKET int +#endif + + +/* ---------------------------------------------------------------- */ +/* COMPILER SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Define to nothing if compiler does not support 'const' qualifier. */ +/* #define const */ + +/* Define to nothing if compiler does not support 'volatile' qualifier. */ +/* #define volatile */ + +/* Windows should not have HAVE_GMTIME_R defined */ +/* #undef HAVE_GMTIME_R */ + +/* Define if the compiler supports C99 variadic macro style. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define HAVE_VARIADIC_MACROS_C99 1 +#endif + +/* Define if the compiler supports the 'long long' data type. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1310)) || \ + (defined(__BORLANDC__) && (__BORLANDC__ >= 0x561)) +#define HAVE_LONGLONG 1 +#endif + +/* Define to avoid VS2005 complaining about portable C functions. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +/* VS2005 and later default size for time_t is 64-bit, unless + _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# ifndef _USE_32BIT_TIME_T +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +#endif + +/* Define some minimum and default build targets for Visual Studio */ +#if defined(_MSC_VER) + /* Officially, Microsoft's Windows SDK versions 6.X does not support Windows + 2000 as a supported build target. VS2008 default installations provides + an embedded Windows SDK v6.0A along with the claim that Windows 2000 is a + valid build target for VS2008. Popular belief is that binaries built with + VS2008 using Windows SDK versions v6.X and Windows 2000 as a build target + are functional. */ +# define VS2008_MIN_TARGET 0x0500 + + /* The minimum build target for VS2012 is Vista unless Update 1 is installed + and the v110_xp toolset is chosen. */ +# if defined(_USING_V110_SDK71_) +# define VS2012_MIN_TARGET 0x0501 +# else +# define VS2012_MIN_TARGET 0x0600 +# endif + + /* VS2008 default build target is Windows Vista. We override default target + to be Windows XP. */ +# define VS2008_DEF_TARGET 0x0501 + + /* VS2012 default build target is Windows Vista unless Update 1 is installed + and the v110_xp toolset is chosen. */ +# if defined(_USING_V110_SDK71_) +# define VS2012_DEF_TARGET 0x0501 +# else +# define VS2012_DEF_TARGET 0x0600 +# endif +#endif + +/* VS2008 default target settings and minimum build target check. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER <= 1600) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT VS2008_DEF_TARGET +# endif +# ifndef WINVER +# define WINVER VS2008_DEF_TARGET +# endif +# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET) +# error VS2008 does not support Windows build targets prior to Windows 2000 +# endif +#endif + +/* VS2012 default target settings and minimum build target check. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT VS2012_DEF_TARGET +# endif +# ifndef WINVER +# define WINVER VS2012_DEF_TARGET +# endif +# if (_WIN32_WINNT < VS2012_MIN_TARGET) || (WINVER < VS2012_MIN_TARGET) +# if defined(_USING_V110_SDK71_) +# error VS2012 does not support Windows build targets prior to Windows XP +# else +# error VS2012 does not support Windows build targets prior to Windows \ +Vista +# endif +# endif +#endif + +/* When no build target is specified Pelles C 5.00 and later default build + target is Windows Vista. We override default target to be Windows 2000. */ +#if defined(__POCC__) && (__POCC__ >= 500) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# ifndef WINVER +# define WINVER 0x0500 +# endif +#endif + +/* Availability of freeaddrinfo, getaddrinfo, getnameinfo and if_nametoindex + functions is quite convoluted, compiler dependent and even build target + dependent. */ +#if defined(HAVE_WS2TCPIP_H) +# if defined(__POCC__) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# elif defined(_MSC_VER) && (_MSC_VER >= 1200) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# endif +#endif + +#if defined(__POCC__) +# ifndef _MSC_VER +# error Microsoft extensions /Ze compiler option is required +# endif +# ifndef __POCC__OLDNAMES +# error Compatibility names /Go compiler option is required +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* STRUCT RELATED */ +/* ---------------------------------------------------------------- */ + +/* Define if you have struct sockaddr_storage. */ +#if !defined(__SALFORDC__) && !defined(__BORLANDC__) +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 +#endif + +/* Define if you have struct timeval. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member. */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +#if defined(HAVE_WINSOCK2_H) && defined(_WIN32_WINNT) && \ + (_WIN32_WINNT >= 0x0600) +#define HAVE_STRUCT_POLLFD 1 +#endif + +/* ---------------------------------------------------------------- */ +/* LARGE FILE SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +#if defined(__MINGW32__) && !defined(USE_WIN32_LARGE_FILES) +# define USE_WIN32_LARGE_FILES +#endif + +#if defined(__WATCOMC__) && !defined(USE_WIN32_LARGE_FILES) +# define USE_WIN32_LARGE_FILES +#endif + +#if defined(__POCC__) +# undef USE_WIN32_LARGE_FILES +#endif + +#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) +# define USE_WIN32_SMALL_FILES +#endif + +/* ---------------------------------------------------------------- */ +/* DNS RESOLVER SPECIALTY */ +/* ---------------------------------------------------------------- */ + +/* + * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS. + */ + +/* Define to enable c-ares asynchronous DNS lookups. */ +/* #define USE_ARES 1 */ + +/* Xbox: Use synchronous DNS resolution (no threading required) */ +#ifdef _XBOX +# define USE_SYNC_DNS 1 +#endif + +/* Default define to enable threaded asynchronous DNS lookups. */ +#if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \ + !defined(USE_THREADS_WIN32) +# define USE_THREADS_WIN32 1 +#endif + +#if defined(USE_ARES) && defined(USE_THREADS_WIN32) +# error "Only one DNS lookup specialty may be defined at most" +#endif + +/* ---------------------------------------------------------------- */ +/* LDAP SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(CURL_HAS_NOVELL_LDAPSDK) || defined(CURL_HAS_MOZILLA_LDAPSDK) +#undef USE_WIN32_LDAP +#define HAVE_LDAP_SSL_H 1 +#define HAVE_LDAP_URL_PARSE 1 +#elif defined(CURL_HAS_OPENLDAP_LDAPSDK) +#undef USE_WIN32_LDAP +#define HAVE_LDAP_URL_PARSE 1 +#else +#undef HAVE_LDAP_URL_PARSE +#define HAVE_LDAP_SSL 1 +#define USE_WIN32_LDAP 1 +#endif + +#if defined(__WATCOMC__) && defined(USE_WIN32_LDAP) +#if __WATCOMC__ < 1280 +#define WINBERAPI __declspec(cdecl) +#define WINLDAPAPI __declspec(cdecl) +#endif +#endif + +#if defined(__POCC__) && defined(USE_WIN32_LDAP) +# define CURL_DISABLE_LDAP 1 +#endif + +/* Define to use the Windows crypto library. */ +#define USE_WIN32_CRYPTO + +/* Define to use Unix sockets. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1500) +/* sdkddkver.h first shipped with Platform SDK v6.0A included with VS2008 */ +#include +#if defined(NTDDI_WIN10_RS4) +#define USE_UNIX_SOCKETS +#endif +#endif + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* Define cpu-machine-OS */ +#undef OS +#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */ +#define OS "i386-pc-win32" +#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */ +#define OS "x86_64-pc-win32" +#elif defined(_M_IA64) /* Itanium */ +#define OS "ia64-pc-win32" +#else +#define OS "unknown-pc-win32" +#endif + +/* Name of package */ +#define PACKAGE "curl" + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +#if defined(__POCC__) || defined(USE_IPV6) +# define ENABLE_IPV6 1 +#endif + +#endif /* HEADER_CURL_CONFIG_WIN32_H */ diff --git a/libcurl/lib/config-win32ce.h b/libcurl/lib/config-win32ce.h new file mode 100644 index 0000000..1820522 --- /dev/null +++ b/libcurl/lib/config-win32ce.h @@ -0,0 +1,448 @@ +#ifndef HEADER_CURL_CONFIG_WIN32CE_H +#define HEADER_CURL_CONFIG_WIN32CE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* lib/config-win32ce.h - Hand crafted config file for windows ce */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* HEADER FILES */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the header file. */ +/* #define HAVE_ARPA_INET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ASSERT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_CRYPTO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ERRNO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ERR_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_GETOPT_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define if you need the malloc.h header header file even with stdlib.h */ +#define NEED_MALLOC_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_NETDB_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_NETINET_IN_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SGTTY_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SSL_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_PROCESS_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKIO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TYPES_H 1 */ + +/* Define if you have the header file */ +#define HAVE_SYS_UTIME_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_TERMIO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_TERMIOS_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) +#define HAVE_UNISTD_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define if you have the header file. */ +#define HAVE_WINSOCK_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_WINSOCK2_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_WS2TCPIP_H 1 */ + +/* ---------------------------------------------------------------- */ +/* OTHER HEADER INFO */ +/* ---------------------------------------------------------------- */ + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +/* #define TIME_WITH_SYS_TIME 1 */ + +/* ---------------------------------------------------------------- */ +/* FUNCTIONS */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the closesocket function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #define HAVE_DOPRNT 1 */ + +/* Define if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the getpass function. */ +/* #define HAVE_GETPASS 1 */ + +/* Define if you have the getservbyname function. */ +#define HAVE_GETSERVBYNAME 1 + +/* Define if you have the gettimeofday function. */ +/* #define HAVE_GETTIMEOFDAY 1 */ + +/* Define if you have the inet_addr function. */ +#define HAVE_INET_ADDR 1 + +/* Define if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define if you have the perror function. */ +#define HAVE_PERROR 1 + +/* Define if you have the RAND_screen function when using SSL */ +#define HAVE_RAND_SCREEN 1 + +/* Define if you have the `RAND_status' function when using SSL. */ +#define HAVE_RAND_STATUS 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the setvbuf function. */ +#define HAVE_SETVBUF 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strcasecmp function. */ +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strdup function. */ +/* #define HAVE_STRDUP 1 */ + +/* Define if you have the strftime function. */ +/* #define HAVE_STRFTIME 1 */ + +/* Define if you have the stricmp function. */ +/* #define HAVE_STRICMP 1 */ + +/* Define if you have the strncasecmp function. */ +/* #define HAVE_STRNCASECMP 1 */ + +/* Define if you have the strnicmp function. */ +/* #define HAVE_STRNICMP 1 */ + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtoll function. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) +#define HAVE_STRTOLL 1 +#endif + +/* Define if you have the tcgetattr function. */ +/* #define HAVE_TCGETATTR 1 */ + +/* Define if you have the tcsetattr function. */ +/* #define HAVE_TCSETATTR 1 */ + +/* Define if you have the utime function */ +#define HAVE_UTIME 1 + +/* Define if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 DWORD + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* ---------------------------------------------------------------- */ +/* TYPEDEF REPLACEMENTS */ +/* ---------------------------------------------------------------- */ + +/* Define this if in_addr_t is not an available 'typedefed' type */ +#define in_addr_t unsigned long + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define ssize_t if it is not an available 'typedefed' type */ +#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__) +#elif defined(_WIN64) +#define ssize_t __int64 +#else +#define ssize_t int +#endif + +/* ---------------------------------------------------------------- */ +/* TYPE SIZES */ +/* ---------------------------------------------------------------- */ + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* The size of `long long', as computed by sizeof. */ +/* #define SIZEOF_LONG_LONG 8 */ + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Define to the size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `size_t', as computed by sizeof. */ +#if defined(_WIN64) +# define SIZEOF_SIZE_T 8 +#else +# define SIZEOF_SIZE_T 4 +#endif + +/* ---------------------------------------------------------------- */ +/* STRUCT RELATED */ +/* ---------------------------------------------------------------- */ + +/* Define this if you have struct sockaddr_storage */ +/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */ + +/* Define this if you have struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define this if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* ---------------------------------------------------------------- */ +/* COMPILER SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Undef keyword 'const' if it does not work. */ +/* #undef const */ + +/* Define to avoid VS2005 complaining about portable C functions */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +/* VS2005 and later default size for time_t is 64-bit, unless */ +/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# ifndef _USE_32BIT_TIME_T +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* LARGE FILE SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) +# define USE_WIN32_SMALL_FILES +#endif + +/* ---------------------------------------------------------------- */ +/* LDAP SUPPORT */ +/* ---------------------------------------------------------------- */ + +#define USE_WIN32_LDAP 1 +#undef HAVE_LDAP_URL_PARSE + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* Define cpu-machine-OS */ +#undef OS +#define OS "i386-pc-win32ce" + +/* Name of package */ +#define PACKAGE "curl" + +/* ---------------------------------------------------------------- */ +/* WinCE */ +/* ---------------------------------------------------------------- */ + +#ifndef UNICODE +# define UNICODE +#endif + +#ifndef _UNICODE +# define _UNICODE +#endif + +#define CURL_DISABLE_FILE 1 +#define CURL_DISABLE_TELNET 1 +#define CURL_DISABLE_LDAP 1 + +#define ENOSPC 1 +#define ENOMEM 2 +#define EAGAIN 3 + +extern int stat(const char *path, struct stat *buffer); + +#endif /* HEADER_CURL_CONFIG_WIN32CE_H */ diff --git a/libcurl/lib/conncache.c b/libcurl/lib/conncache.c new file mode 100644 index 0000000..2f4dd4b --- /dev/null +++ b/libcurl/lib/conncache.c @@ -0,0 +1,638 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "multiif.h" +#include "sendf.h" +#include "conncache.h" +#include "share.h" +#include "sigpipe.h" +#include "connect.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef CURLDEBUG +/* the debug versions of these macros make extra certain that the lock is + never doubly locked or unlocked */ +#define CONN_LOCK(x) if((x)->share) { \ + Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \ + DEBUGASSERT(!(x)->state.conncache_lock); \ + (x)->state.conncache_lock = TRUE; \ + } + +#define CONN_UNLOCK(x) if((x)->share) { \ + DEBUGASSERT((x)->state.conncache_lock); \ + (x)->state.conncache_lock = FALSE; \ + Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \ + } +#else +#define CONN_LOCK(x) if((x)->share) \ + Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE) +#define CONN_UNLOCK(x) if((x)->share) \ + Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT) +#endif + +#define HASHKEY_SIZE 128 + +static void conn_llist_dtor(void *user, void *element) +{ + struct connectdata *conn = element; + (void)user; + conn->bundle = NULL; +} + +static CURLcode bundle_create(struct Curl_easy *data, + struct connectbundle **cb_ptr) +{ + (void)data; + DEBUGASSERT(*cb_ptr == NULL); + *cb_ptr = malloc(sizeof(struct connectbundle)); + if(!*cb_ptr) + return CURLE_OUT_OF_MEMORY; + + (*cb_ptr)->num_connections = 0; + (*cb_ptr)->multiuse = BUNDLE_UNKNOWN; + + Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor); + return CURLE_OK; +} + +static void bundle_destroy(struct connectbundle *cb_ptr) +{ + if(!cb_ptr) + return; + + Curl_llist_destroy(&cb_ptr->conn_list, NULL); + + free(cb_ptr); +} + +/* Add a connection to a bundle */ +static void bundle_add_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn, + &conn->bundle_node); + conn->bundle = cb_ptr; + cb_ptr->num_connections++; +} + +/* Remove a connection from a bundle */ +static int bundle_remove_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + struct curl_llist_element *curr; + + curr = cb_ptr->conn_list.head; + while(curr) { + if(curr->ptr == conn) { + Curl_llist_remove(&cb_ptr->conn_list, curr, NULL); + cb_ptr->num_connections--; + conn->bundle = NULL; + return 1; /* we removed a handle */ + } + curr = curr->next; + } + return 0; +} + +static void free_bundle_hash_entry(void *freethis) +{ + struct connectbundle *b = (struct connectbundle *) freethis; + + bundle_destroy(b); +} + +int Curl_conncache_init(struct conncache *connc, int size) +{ + int rc; + + /* allocate a new easy handle to use when closing cached connections */ + connc->closure_handle = curl_easy_init(); + if(!connc->closure_handle) + return 1; /* bad */ + + rc = Curl_hash_init(&connc->hash, size, Curl_hash_str, + Curl_str_key_compare, free_bundle_hash_entry); + if(rc) { + Curl_close(connc->closure_handle); + connc->closure_handle = NULL; + } + else + connc->closure_handle->state.conn_cache = connc; + + return rc; +} + +void Curl_conncache_destroy(struct conncache *connc) +{ + if(connc) + Curl_hash_destroy(&connc->hash); +} + +/* creates a key to find a bundle for this connection */ +static void hashkey(struct connectdata *conn, char *buf, + size_t len, /* something like 128 is fine */ + const char **hostp) +{ + const char *hostname; + long port = conn->remote_port; + + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + hostname = conn->http_proxy.host.name; + port = conn->port; + } + else if(conn->bits.conn_to_host) + hostname = conn->conn_to_host.name; + else + hostname = conn->host.name; + + if(hostp) + /* report back which name we used */ + *hostp = hostname; + + /* put the number first so that the hostname gets cut off if too long */ + msnprintf(buf, len, "%ld%s", port, hostname); +} + +void Curl_conncache_unlock(struct Curl_easy *data) +{ + CONN_UNLOCK(data); +} + +/* Returns number of connections currently held in the connection cache. + Locks/unlocks the cache itself! +*/ +size_t Curl_conncache_size(struct Curl_easy *data) +{ + size_t num; + CONN_LOCK(data); + num = data->state.conn_cache->num_conn; + CONN_UNLOCK(data); + return num; +} + +/* Returns number of connections currently held in the connections's bundle + Locks/unlocks the cache itself! +*/ +size_t Curl_conncache_bundle_size(struct connectdata *conn) +{ + size_t num; + CONN_LOCK(conn->data); + num = conn->bundle->num_connections; + CONN_UNLOCK(conn->data); + return num; +} + +/* Look up the bundle with all the connections to the same host this + connectdata struct is setup to use. + + **NOTE**: When it returns, it holds the connection cache lock! */ +struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + struct conncache *connc, + const char **hostp) +{ + struct connectbundle *bundle = NULL; + CONN_LOCK(conn->data); + if(connc) { + char key[HASHKEY_SIZE]; + hashkey(conn, key, sizeof(key), hostp); + bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); + } + + return bundle; +} + +static bool conncache_add_bundle(struct conncache *connc, + char *key, + struct connectbundle *bundle) +{ + void *p = Curl_hash_add(&connc->hash, key, strlen(key), bundle); + + return p?TRUE:FALSE; +} + +static void conncache_remove_bundle(struct conncache *connc, + struct connectbundle *bundle) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + + if(!connc) + return; + + Curl_hash_start_iterate(&connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + if(he->ptr == bundle) { + /* The bundle is destroyed by the hash destructor function, + free_bundle_hash_entry() */ + Curl_hash_delete(&connc->hash, he->key, he->key_len); + return; + } + + he = Curl_hash_next_element(&iter); + } +} + +CURLcode Curl_conncache_add_conn(struct conncache *connc, + struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct connectbundle *bundle; + struct connectbundle *new_bundle = NULL; + struct Curl_easy *data = conn->data; + + /* *find_bundle() locks the connection cache */ + bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache, NULL); + if(!bundle) { + int rc; + char key[HASHKEY_SIZE]; + + result = bundle_create(data, &new_bundle); + if(result) { + goto unlock; + } + + hashkey(conn, key, sizeof(key), NULL); + rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); + + if(!rc) { + bundle_destroy(new_bundle); + result = CURLE_OUT_OF_MEMORY; + goto unlock; + } + bundle = new_bundle; + } + + bundle_add_conn(bundle, conn); + conn->connection_id = connc->next_connection_id++; + connc->num_conn++; + + DEBUGF(infof(conn->data, "Added connection %ld. " + "The cache now contains %zu members\n", + conn->connection_id, connc->num_conn)); + + unlock: + CONN_UNLOCK(data); + + return result; +} + +/* + * Removes the connectdata object from the connection cache *and* clears the + * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument + * depending on if the parent function already holds the lock or not. + */ +void Curl_conncache_remove_conn(struct Curl_easy *data, + struct connectdata *conn, bool lock) +{ + struct connectbundle *bundle = conn->bundle; + struct conncache *connc = data->state.conn_cache; + + /* The bundle pointer can be NULL, since this function can be called + due to a failed connection attempt, before being added to a bundle */ + if(bundle) { + if(lock) { + CONN_LOCK(data); + } + bundle_remove_conn(bundle, conn); + if(bundle->num_connections == 0) + conncache_remove_bundle(connc, bundle); + conn->bundle = NULL; /* removed from it */ + if(connc) { + connc->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + connc->num_conn)); + } + conn->data = NULL; /* clear the association */ + if(lock) { + CONN_UNLOCK(data); + } + } +} + +/* This function iterates the entire connection cache and calls the function + func() with the connection pointer as the first argument and the supplied + 'param' argument as the other. + + The conncache lock is still held when the callback is called. It needs it, + so that it can safely continue traversing the lists once the callback + returns. + + Returns 1 if the loop was aborted due to the callback's return code. + + Return 0 from func() to continue the loop, return 1 to abort it. + */ +bool Curl_conncache_foreach(struct Curl_easy *data, + struct conncache *connc, + void *param, + int (*func)(struct connectdata *conn, void *param)) +{ + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + + if(!connc) + return FALSE; + + CONN_LOCK(data); + Curl_hash_start_iterate(&connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectbundle *bundle; + + bundle = he->ptr; + he = Curl_hash_next_element(&iter); + + curr = bundle->conn_list.head; + while(curr) { + /* Yes, we need to update curr before calling func(), because func() + might decide to remove the connection */ + struct connectdata *conn = curr->ptr; + curr = curr->next; + + if(1 == func(conn, param)) { + CONN_UNLOCK(data); + return TRUE; + } + } + } + CONN_UNLOCK(data); + return FALSE; +} + +/* Return the first connection found in the cache. Used when closing all + connections. + + NOTE: no locking is done here as this is presumably only done when cleaning + up a cache! +*/ +static struct connectdata * +conncache_find_first_connection(struct conncache *connc) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + struct connectbundle *bundle; + + Curl_hash_start_iterate(&connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct curl_llist_element *curr; + bundle = he->ptr; + + curr = bundle->conn_list.head; + if(curr) { + return curr->ptr; + } + + he = Curl_hash_next_element(&iter); + } + + return NULL; +} + +/* + * Give ownership of a connection back to the connection cache. Might + * disconnect the oldest existing in there to make space. + * + * Return TRUE if stored, FALSE if closed. + */ +bool Curl_conncache_return_conn(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + + /* data->multi->maxconnects can be negative, deal with it. */ + size_t maxconnects = + (data->multi->maxconnects < 0) ? data->multi->num_easy * 4: + data->multi->maxconnects; + struct connectdata *conn_candidate = NULL; + + conn->data = NULL; /* no owner anymore */ + conn->lastused = Curl_now(); /* it was used up until now */ + if(maxconnects > 0 && + Curl_conncache_size(data) > maxconnects) { + infof(data, "Connection cache is full, closing the oldest one.\n"); + + conn_candidate = Curl_conncache_extract_oldest(data); + if(conn_candidate) { + /* the winner gets the honour of being disconnected */ + (void)Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE); + } + } + + return (conn_candidate == conn) ? FALSE : TRUE; + +} + +/* + * This function finds the connection in the connection bundle that has been + * unused for the longest time. + * + * Does not lock the connection cache! + * + * Returns the pointer to the oldest idle connection, or NULL if none was + * found. + */ +struct connectdata * +Curl_conncache_extract_bundle(struct Curl_easy *data, + struct connectbundle *bundle) +{ + struct curl_llist_element *curr; + timediff_t highscore = -1; + timediff_t score; + struct curltime now; + struct connectdata *conn_candidate = NULL; + struct connectdata *conn; + + (void)data; + + now = Curl_now(); + + curr = bundle->conn_list.head; + while(curr) { + conn = curr->ptr; + + if(!CONN_INUSE(conn) && !conn->data) { + /* Set higher score for the age passed since the connection was used */ + score = Curl_timediff(now, conn->lastused); + + if(score > highscore) { + highscore = score; + conn_candidate = conn; + } + } + curr = curr->next; + } + if(conn_candidate) { + /* remove it to prevent another thread from nicking it */ + bundle_remove_conn(bundle, conn_candidate); + data->state.conn_cache->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + data->state.conn_cache->num_conn)); + conn_candidate->data = data; /* associate! */ + } + + return conn_candidate; +} + +/* + * This function finds the connection in the connection cache that has been + * unused for the longest time and extracts that from the bundle. + * + * Returns the pointer to the connection, or NULL if none was found. + */ +struct connectdata * +Curl_conncache_extract_oldest(struct Curl_easy *data) +{ + struct conncache *connc = data->state.conn_cache; + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + timediff_t highscore =- 1; + timediff_t score; + struct curltime now; + struct connectdata *conn_candidate = NULL; + struct connectbundle *bundle; + struct connectbundle *bundle_candidate = NULL; + + now = Curl_now(); + + CONN_LOCK(data); + Curl_hash_start_iterate(&connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectdata *conn; + + bundle = he->ptr; + + curr = bundle->conn_list.head; + while(curr) { + conn = curr->ptr; + + if(!CONN_INUSE(conn) && !conn->data) { + /* Set higher score for the age passed since the connection was used */ + score = Curl_timediff(now, conn->lastused); + + if(score > highscore) { + highscore = score; + conn_candidate = conn; + bundle_candidate = bundle; + } + } + curr = curr->next; + } + + he = Curl_hash_next_element(&iter); + } + if(conn_candidate) { + /* remove it to prevent another thread from nicking it */ + bundle_remove_conn(bundle_candidate, conn_candidate); + connc->num_conn--; + DEBUGF(infof(data, "The cache now contains %zu members\n", + connc->num_conn)); + conn_candidate->data = data; /* associate! */ + } + CONN_UNLOCK(data); + + return conn_candidate; +} + +void Curl_conncache_close_all_connections(struct conncache *connc) +{ + struct connectdata *conn; + + conn = conncache_find_first_connection(connc); + while(conn) { + SIGPIPE_VARIABLE(pipe_st); + conn->data = connc->closure_handle; + + sigpipe_ignore(conn->data, &pipe_st); + /* This will remove the connection from the cache */ + connclose(conn, "kill all"); + (void)Curl_disconnect(connc->closure_handle, conn, FALSE); + sigpipe_restore(&pipe_st); + + conn = conncache_find_first_connection(connc); + } + + if(connc->closure_handle) { + SIGPIPE_VARIABLE(pipe_st); + sigpipe_ignore(connc->closure_handle, &pipe_st); + + Curl_hostcache_clean(connc->closure_handle, + connc->closure_handle->dns.hostcache); + Curl_close(connc->closure_handle); + sigpipe_restore(&pipe_st); + } +} + +#if 0 +/* Useful for debugging the connection cache */ +void Curl_conncache_print(struct conncache *connc) +{ + struct curl_hash_iterator iter; + struct curl_llist_element *curr; + struct curl_hash_element *he; + + if(!connc) + return; + + fprintf(stderr, "=Bundle cache=\n"); + + Curl_hash_start_iterate(connc->hash, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + struct connectbundle *bundle; + struct connectdata *conn; + + bundle = he->ptr; + + fprintf(stderr, "%s -", he->key); + curr = bundle->conn_list->head; + while(curr) { + conn = curr->ptr; + + fprintf(stderr, " [%p %d]", (void *)conn, conn->inuse); + curr = curr->next; + } + fprintf(stderr, "\n"); + + he = Curl_hash_next_element(&iter); + } +} +#endif diff --git a/libcurl/lib/conncache.h b/libcurl/lib/conncache.h new file mode 100644 index 0000000..58f9024 --- /dev/null +++ b/libcurl/lib/conncache.h @@ -0,0 +1,87 @@ +#ifndef HEADER_CURL_CONNCACHE_H +#define HEADER_CURL_CONNCACHE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * All accesses to struct fields and changing of data in the connection cache + * and connectbundles must be done with the conncache LOCKED. The cache might + * be shared. + */ + +struct conncache { + struct curl_hash hash; + size_t num_conn; + long next_connection_id; + struct curltime last_cleanup; + /* handle used for closing cached connections */ + struct Curl_easy *closure_handle; +}; + +#define BUNDLE_NO_MULTIUSE -1 +#define BUNDLE_UNKNOWN 0 /* initial value */ +#define BUNDLE_MULTIPLEX 2 + +struct connectbundle { + int multiuse; /* supports multi-use */ + size_t num_connections; /* Number of connections in the bundle */ + struct curl_llist conn_list; /* The connectdata members of the bundle */ +}; + +/* returns 1 on error, 0 is fine */ +int Curl_conncache_init(struct conncache *, int size); +void Curl_conncache_destroy(struct conncache *connc); + +/* return the correct bundle, to a host or a proxy */ +struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + struct conncache *connc, + const char **hostp); +void Curl_conncache_unlock(struct Curl_easy *data); +/* returns number of connections currently held in the connection cache */ +size_t Curl_conncache_size(struct Curl_easy *data); +size_t Curl_conncache_bundle_size(struct connectdata *conn); + +bool Curl_conncache_return_conn(struct connectdata *conn); +CURLcode Curl_conncache_add_conn(struct conncache *connc, + struct connectdata *conn) WARN_UNUSED_RESULT; +void Curl_conncache_remove_conn(struct Curl_easy *data, + struct connectdata *conn, + bool lock); +bool Curl_conncache_foreach(struct Curl_easy *data, + struct conncache *connc, + void *param, + int (*func)(struct connectdata *conn, + void *param)); + +struct connectdata * +Curl_conncache_find_first_connection(struct conncache *connc); + +struct connectdata * +Curl_conncache_extract_bundle(struct Curl_easy *data, + struct connectbundle *bundle); +struct connectdata * +Curl_conncache_extract_oldest(struct Curl_easy *data); +void Curl_conncache_close_all_connections(struct conncache *connc); +void Curl_conncache_print(struct conncache *connc); + +#endif /* HEADER_CURL_CONNCACHE_H */ diff --git a/libcurl/lib/connect.c b/libcurl/lib/connect.c new file mode 100644 index 0000000..7ff9f5c --- /dev/null +++ b/libcurl/lib/connect.c @@ -0,0 +1,1472 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include /* may need it */ +#endif +#ifdef HAVE_SYS_UN_H +#include /* for sockaddr_un */ +#endif +#ifdef HAVE_LINUX_TCP_H +#include +#elif defined(HAVE_NETINET_TCP_H) +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) +#include +#endif +#ifdef NETWARE +#undef in_addr_t +#define in_addr_t unsigned long +#endif +#ifdef __VMS +#include +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "if2ip.h" +#include "strerror.h" +#include "connect.h" +#include "select.h" +#include "url.h" /* for Curl_safefree() */ +#include "multiif.h" +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "inet_ntop.h" +#include "inet_pton.h" +#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */ +#include "progress.h" +#include "warnless.h" +#include "conncache.h" +#include "multihandle.h" +#include "system_win32.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef __SYMBIAN32__ +/* This isn't actually supported under Symbian OS */ +#undef SO_NOSIGPIPE +#endif + +static bool verifyconnect(curl_socket_t sockfd, int *error); + +#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H) +/* DragonFlyBSD and Windows use millisecond units */ +#define KEEPALIVE_FACTOR(x) (x *= 1000) +#else +#define KEEPALIVE_FACTOR(x) +#endif + +/*#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS) +#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) + +struct tcp_keepalive { + u_long onoff; + u_long keepalivetime; + u_long keepaliveinterval; +}; +#endif +*/ + +static void +tcpkeepalive(struct Curl_easy *data, + curl_socket_t sockfd) +{ + int optval = data->set.tcp_keepalive?1:0; + + /* only set IDLE and INTVL if setting KEEPALIVE is successful */ +/* + if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); + } + else { +*/ + + +#if defined(SIO_KEEPALIVE_VALS) + struct tcp_keepalive vals; + DWORD dummy; + vals.onoff = 1; + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + vals.keepalivetime = optval; + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + vals.keepaliveinterval = optval; + if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals), + NULL, 0, &dummy, NULL, NULL) != 0) { + infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n", + (int)sockfd, WSAGetLastError()); + } +#else +#ifdef TCP_KEEPIDLE + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); + } +#endif +#ifdef TCP_KEEPINTVL + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); + } +#endif +#ifdef TCP_KEEPALIVE + /* Mac OS X style */ + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd); + } +#endif +#endif + //} +} + +static CURLcode +singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, /* start connecting to this */ + curl_socket_t *sock); + +/* + * Curl_timeleft() returns the amount of milliseconds left allowed for the + * transfer/connection. If the value is negative, the timeout time has already + * elapsed. + * + * The start time is stored in progress.t_startsingle - as set with + * Curl_pgrsTime(..., TIMER_STARTSINGLE); + * + * If 'nowp' is non-NULL, it points to the current time. + * 'duringconnect' is FALSE if not during a connect, as then of course the + * connect timeout is not taken into account! + * + * @unittest: 1303 + */ +timediff_t Curl_timeleft(struct Curl_easy *data, + struct curltime *nowp, + bool duringconnect) +{ + int timeout_set = 0; + timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; + struct curltime now; + + /* if a timeout is set, use the most restrictive one */ + + if(data->set.timeout > 0) + timeout_set |= 1; + if(duringconnect && (data->set.connecttimeout > 0)) + timeout_set |= 2; + + switch(timeout_set) { + case 1: + timeout_ms = data->set.timeout; + break; + case 2: + timeout_ms = data->set.connecttimeout; + break; + case 3: + if(data->set.timeout < data->set.connecttimeout) + timeout_ms = data->set.timeout; + else + timeout_ms = data->set.connecttimeout; + break; + default: + /* use the default */ + if(!duringconnect) + /* if we're not during connect, there's no default timeout so if we're + at zero we better just return zero and not make it a negative number + by the math below */ + return 0; + break; + } + + if(!nowp) { + now = Curl_now(); + nowp = &now; + } + + /* subtract elapsed time */ + if(duringconnect) + /* since this most recent connect started */ + timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle); + else + /* since the entire operation started */ + timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; + + return timeout_ms; +} + +static CURLcode bindlocal(struct connectdata *conn, + curl_socket_t sockfd, int af, unsigned int scope) +{ + struct Curl_easy *data = conn->data; + + struct Curl_sockaddr_storage sa; + struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ + curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ + struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; +#endif + + struct Curl_dns_entry *h = NULL; + unsigned short port = data->set.localport; /* use this port number, 0 for + "random" */ + /* how many port numbers to try to bind to, increasing one at a time */ + int portnum = data->set.localportrange; + const char *dev = data->set.str[STRING_DEVICE]; + int error; + + /************************************************************* + * Select device to bind socket to + *************************************************************/ + if(!dev && !port) + /* no local kind of binding was requested */ + return CURLE_OK; + + memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); + + if(dev && (strlen(dev)<255) ) { + char myhost[256] = ""; + int done = 0; /* -1 for error, 1 for address found */ + bool is_interface = FALSE; + bool is_host = FALSE; + static const char *if_prefix = "if!"; + static const char *host_prefix = "host!"; + + if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) { + dev += strlen(if_prefix); + is_interface = TRUE; + } + else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) { + dev += strlen(host_prefix); + is_host = TRUE; + } + + /* interface */ + if(!is_host) { +#ifdef SO_BINDTODEVICE + /* I am not sure any other OSs than Linux that provide this feature, + * and at the least I cannot test. --Ben + * + * This feature allows one to tightly bind the local socket to a + * particular interface. This will force even requests to other + * local interfaces to go out the external interface. + * + * + * Only bind to the interface when specified as interface, not just + * as a hostname or ip address. + * + * interface might be a VRF, eg: vrf-blue, which means it cannot be + * converted to an IP address and would fail Curl_if2ip. Simply try + * to use it straight away. + */ + if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, + dev, (curl_socklen_t)strlen(dev) + 1) == 0) { + /* This is typically "errno 1, error: Operation not permitted" if + * you're not running as root or another suitable privileged + * user. + * If it succeeds it means the parameter was a valid interface and + * not an IP address. Return immediately. + */ + return CURLE_OK; + } +#endif + + switch(Curl_if2ip(af, scope, conn->scope_id, dev, + myhost, sizeof(myhost))) { + case IF2IP_NOT_FOUND: + if(is_interface) { + /* Do not fall back to treating it as a host name */ + failf(data, "Couldn't bind to interface '%s'", dev); + return CURLE_INTERFACE_FAILED; + } + break; + case IF2IP_AF_NOT_SUPPORTED: + /* Signal the caller to try another address family if available */ + return CURLE_UNSUPPORTED_PROTOCOL; + case IF2IP_FOUND: + is_interface = TRUE; + /* + * We now have the numerical IP address in the 'myhost' buffer + */ + infof(data, "Local Interface %s is ip %s using address family %i\n", + dev, myhost, af); + done = 1; + break; + } + } + if(!is_interface) { + /* + * This was not an interface, resolve the name as a host name + * or IP number + * + * Temporarily force name resolution to use only the address type + * of the connection. The resolve functions should really be changed + * to take a type parameter instead. + */ + long ipver = conn->ip_version; + int rc; + + if(af == AF_INET) + conn->ip_version = CURL_IPRESOLVE_V4; +#ifdef ENABLE_IPV6 + else if(af == AF_INET6) + conn->ip_version = CURL_IPRESOLVE_V6; +#endif + + rc = Curl_resolv(conn, dev, 0, FALSE, &h); + if(rc == CURLRESOLV_PENDING) + (void)Curl_resolver_wait_resolv(conn, &h); + conn->ip_version = ipver; + + if(h) { + /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ + Curl_printable_address(h->addr, myhost, sizeof(myhost)); + infof(data, "Name '%s' family %i resolved to '%s' family %i\n", + dev, af, myhost, h->addr->ai_family); + Curl_resolv_unlock(data, h); + if(af != h->addr->ai_family) { + /* bad IP version combo, signal the caller to try another address + family if available */ + return CURLE_UNSUPPORTED_PROTOCOL; + } + done = 1; + } + else { + /* + * provided dev was no interface (or interfaces are not supported + * e.g. solaris) no ip address and no domain we fail here + */ + done = -1; + } + } + + if(done > 0) { +#ifdef ENABLE_IPV6 + /* IPv6 address */ + if(af == AF_INET6) { +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + char *scope_ptr = strchr(myhost, '%'); + if(scope_ptr) + *(scope_ptr++) = 0; +#endif + if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + if(scope_ptr) + /* The "myhost" string either comes from Curl_if2ip or from + Curl_printable_address. The latter returns only numeric scope + IDs and the former returns none at all. So the scope ID, if + present, is known to be numeric */ + si6->sin6_scope_id = atoi(scope_ptr); +#endif + } + sizeof_sa = sizeof(struct sockaddr_in6); + } + else +#endif + /* IPv4 address */ + if((af == AF_INET) && + (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in); + } + } + + if(done < 1) { + /* errorbuf is set false so failf will overwrite any message already in + the error buffer, so the user receives this error message instead of a + generic resolve error. */ + data->state.errorbuf = FALSE; + failf(data, "Couldn't bind to '%s'", dev); + return CURLE_INTERFACE_FAILED; + } + } + else { + /* no device was given, prepare sa to match af's needs */ +#ifdef ENABLE_IPV6 + if(af == AF_INET6) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in6); + } + else +#endif + if(af == AF_INET) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in); + } + } + + for(;;) { + if(bind(sockfd, sock, sizeof_sa) >= 0) { + /* we succeeded to bind */ + struct Curl_sockaddr_storage add; + curl_socklen_t size = sizeof(add); + memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); + if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { + char buffer[STRERROR_LEN]; + data->state.os_errno = error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + return CURLE_INTERFACE_FAILED; + } + infof(data, "Local port: %hu\n", port); + conn->bits.bound = TRUE; + return CURLE_OK; + } + + if(--portnum > 0) { + infof(data, "Bind to local port %hu failed, trying next\n", port); + port++; /* try next port */ + /* We re-use/clobber the port variable here below */ + if(sock->sa_family == AF_INET) + si4->sin_port = ntohs(port); +#ifdef ENABLE_IPV6 + else + si6->sin6_port = ntohs(port); +#endif + } + else + break; + } + { + char buffer[STRERROR_LEN]; + data->state.os_errno = error = SOCKERRNO; + failf(data, "bind failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + } + + return CURLE_INTERFACE_FAILED; +} + +/* + * verifyconnect() returns TRUE if the connect really has happened. + */ +static bool verifyconnect(curl_socket_t sockfd, int *error) +{ + bool rc = TRUE; +#ifdef SO_ERROR + int err = 0; + curl_socklen_t errSize = sizeof(err); + +#ifdef WIN32 + /* + * In October 2003 we effectively nullified this function on Windows due to + * problems with it using all CPU in multi-threaded cases. + * + * In May 2004, we bring it back to offer more info back on connect failures. + * Gisle Vanem could reproduce the former problems with this function, but + * could avoid them by adding this SleepEx() call below: + * + * "I don't have Rational Quantify, but the hint from his post was + * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe + * just Sleep(0) would be enough?) would release whatever + * mutex/critical-section the ntdll call is waiting on. + * + * Someone got to verify this on Win-NT 4.0, 2000." + */ + +#ifdef _WIN32_WCE + Sleep(0); +#else + SleepEx(0, FALSE); +#endif + +#endif + + if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) + err = SOCKERRNO; +#ifdef _WIN32_WCE + /* Old WinCE versions don't support SO_ERROR */ + if(WSAENOPROTOOPT == err) { + SET_SOCKERRNO(0); + err = 0; + } +#endif +#if defined(EBADIOCTL) && defined(__minix) + /* Minix 3.1.x doesn't support getsockopt on UDP sockets */ + if(EBADIOCTL == err) { + SET_SOCKERRNO(0); + err = 0; + } +#endif + if((0 == err) || (EISCONN == err)) + /* we are connected, awesome! */ + rc = TRUE; + else + /* This wasn't a successful connect */ + rc = FALSE; + if(error) + *error = err; +#else + (void)sockfd; + if(error) + *error = SOCKERRNO; +#endif + return rc; +} + +/* Used within the multi interface. Try next IP address, return TRUE if no + more address exists or error */ +static CURLcode trynextip(struct connectdata *conn, + int sockindex, + int tempindex) +{ + const int other = tempindex ^ 1; + CURLcode result = CURLE_COULDNT_CONNECT; + + /* First clean up after the failed socket. + Don't close it yet to ensure that the next IP's socket gets a different + file descriptor, which can prevent bugs when the curl_multi_socket_action + interface is used with certain select() replacements such as kqueue. */ + curl_socket_t fd_to_close = conn->tempsock[tempindex]; + conn->tempsock[tempindex] = CURL_SOCKET_BAD; + + if(sockindex == FIRSTSOCKET) { + Curl_addrinfo *ai = NULL; + int family = AF_UNSPEC; + + if(conn->tempaddr[tempindex]) { + /* find next address in the same protocol family */ + family = conn->tempaddr[tempindex]->ai_family; + ai = conn->tempaddr[tempindex]->ai_next; + } +#ifdef ENABLE_IPV6 + else if(conn->tempaddr[0]) { + /* happy eyeballs - try the other protocol family */ + int firstfamily = conn->tempaddr[0]->ai_family; + family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET; + ai = conn->tempaddr[0]->ai_next; + } +#endif + + while(ai) { + if(conn->tempaddr[other]) { + /* we can safely skip addresses of the other protocol family */ + while(ai && ai->ai_family != family) + ai = ai->ai_next; + } + + if(ai) { + result = singleipconnect(conn, ai, &conn->tempsock[tempindex]); + if(result == CURLE_COULDNT_CONNECT) { + ai = ai->ai_next; + continue; + } + + conn->tempaddr[tempindex] = ai; + } + break; + } + } + + if(fd_to_close != CURL_SOCKET_BAD) + Curl_closesocket(conn, fd_to_close); + + return result; +} + +/* Copies connection info into the session handle to make it available + when the session handle is no longer associated with a connection. */ +void Curl_persistconninfo(struct connectdata *conn) +{ + memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); + memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); + conn->data->info.conn_scheme = conn->handler->scheme; + conn->data->info.conn_protocol = conn->handler->protocol; + conn->data->info.conn_primary_port = conn->primary_port; + conn->data->info.conn_local_port = conn->local_port; +} + +UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port); + +/* retrieves ip address and port from a sockaddr structure. + note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */ +UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port) +{ + struct sockaddr_in *si = NULL; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *si6 = NULL; +#endif +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + struct sockaddr_un *su = NULL; +#endif + + switch(sa->sa_family) { + case AF_INET: + si = (struct sockaddr_in *)(void *) sa; + if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, + addr, MAX_IPADR_LEN)) { + unsigned short us_port = ntohs(si->sin_port); + *port = us_port; + return TRUE; + } + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + si6 = (struct sockaddr_in6 *)(void *) sa; + if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, + addr, MAX_IPADR_LEN)) { + unsigned short us_port = ntohs(si6->sin6_port); + *port = us_port; + return TRUE; + } + break; +#endif +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + case AF_UNIX: + su = (struct sockaddr_un*)sa; + msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); + *port = 0; + return TRUE; +#endif + default: + break; + } + + addr[0] = '\0'; + *port = 0; + errno = EAFNOSUPPORT; + return FALSE; +} + +/* retrieves the start/end point information of a socket of an established + connection */ +void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) +{ + if(conn->socktype == SOCK_DGRAM) + /* there's no connection! */ + return; + +#if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME) + if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { + struct Curl_easy *data = conn->data; + char buffer[STRERROR_LEN]; + struct Curl_sockaddr_storage ssrem; + struct Curl_sockaddr_storage ssloc; + curl_socklen_t len; +#ifdef HAVE_GETPEERNAME + len = sizeof(struct Curl_sockaddr_storage); + if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { + int error = SOCKERRNO; + failf(data, "getpeername() failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + return; + } +#endif +#ifdef HAVE_GETSOCKNAME + len = sizeof(struct Curl_sockaddr_storage); + memset(&ssloc, 0, sizeof(ssloc)); + if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { + int error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + return; + } +#endif +#ifdef HAVE_GETPEERNAME + if(!getaddressinfo((struct sockaddr*)&ssrem, + conn->primary_ip, &conn->primary_port)) { + failf(data, "ssrem inet_ntop() failed with errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + return; + } + memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); +#endif +#ifdef HAVE_GETSOCKNAME + if(!getaddressinfo((struct sockaddr*)&ssloc, + conn->local_ip, &conn->local_port)) { + failf(data, "ssloc inet_ntop() failed with errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + return; + } +#endif + } +#else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */ + (void)sockfd; /* unused */ +#endif + + /* persist connection info in session handle */ + Curl_persistconninfo(conn); +} + +/* + * Curl_is_connected() checks if the socket has connected. + */ + +CURLcode Curl_is_connected(struct connectdata *conn, + int sockindex, + bool *connected) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + timediff_t allow; + int error = 0; + struct curltime now; + int rc; + int i; + + DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); + + *connected = FALSE; /* a very negative world view is best */ + + if(conn->bits.tcpconnect[sockindex]) { + /* we are connected already! */ + *connected = TRUE; + return CURLE_OK; + } + + now = Curl_now(); + + /* figure out how long time we have left to connect */ + allow = Curl_timeleft(data, &now, TRUE); + + if(allow < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + for(i = 0; i<2; i++) { + const int other = i ^ 1; + if(conn->tempsock[i] == CURL_SOCKET_BAD) + continue; + +#ifdef mpeix + /* Call this function once now, and ignore the results. We do this to + "clear" the error state on the socket so that we can later read it + reliably. This is reported necessary on the MPE/iX operating system. */ + (void)verifyconnect(conn->tempsock[i], NULL); +#endif + + /* check socket for connect */ + rc = SOCKET_WRITABLE(conn->tempsock[i], 0); + + if(rc == 0) { /* no connection yet */ + error = 0; + if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) { + infof(data, "After %ldms connect time, move on!\n", + conn->timeoutms_per_addr); + error = ETIMEDOUT; + } + + /* should we try another protocol family? */ + if(i == 0 && conn->tempaddr[1] == NULL && + (Curl_timediff(now, conn->connecttime) >= + data->set.happy_eyeballs_timeout)) { + trynextip(conn, sockindex, 1); + } + } + else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) { + if(verifyconnect(conn->tempsock[i], &error)) { + /* we are connected with TCP, awesome! */ + + /* use this socket from now on */ + conn->sock[sockindex] = conn->tempsock[i]; + conn->ip_addr = conn->tempaddr[i]; + conn->tempsock[i] = CURL_SOCKET_BAD; +#ifdef ENABLE_IPV6 + conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE; +#endif + + /* close the other socket, if open */ + if(conn->tempsock[other] != CURL_SOCKET_BAD) { + Curl_closesocket(conn, conn->tempsock[other]); + conn->tempsock[other] = CURL_SOCKET_BAD; + } + + /* see if we need to do any proxy magic first once we connected */ + result = Curl_connected_proxy(conn, sockindex); + if(result) + return result; + + conn->bits.tcpconnect[sockindex] = TRUE; + + *connected = TRUE; + if(sockindex == FIRSTSOCKET) + Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ + Curl_updateconninfo(conn, conn->sock[sockindex]); + Curl_verboseconnect(conn); + + return CURLE_OK; + } + infof(data, "Connection failed\n"); + } + else if(rc & CURL_CSELECT_ERR) + (void)verifyconnect(conn->tempsock[i], &error); + + /* + * The connection failed here, we should attempt to connect to the "next + * address" for the given host. But first remember the latest error. + */ + if(error) { + data->state.os_errno = error; + SET_SOCKERRNO(error); + if(conn->tempaddr[i]) { + CURLcode status; + char ipaddress[MAX_IPADR_LEN]; + char buffer[STRERROR_LEN]; + Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN); + infof(data, "connect to %s port %ld failed: %s\n", + ipaddress, conn->port, + Curl_strerror(error, buffer, sizeof(buffer))); + + conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ? + allow : allow / 2; + + status = trynextip(conn, sockindex, i); + if(status != CURLE_COULDNT_CONNECT + || conn->tempsock[other] == CURL_SOCKET_BAD) + /* the last attempt failed and no other sockets remain open */ + result = status; + } + } + } + + if(result) { + /* no more addresses to try */ + const char *hostname; + char buffer[STRERROR_LEN]; + + /* if the first address family runs out of addresses to try before + the happy eyeball timeout, go ahead and try the next family now */ + if(conn->tempaddr[1] == NULL) { + result = trynextip(conn, sockindex, 1); + if(!result) + return result; + } + + if(conn->bits.socksproxy) + hostname = conn->socks_proxy.host.name; + else if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; + else if(conn->bits.conn_to_host) + hostname = conn->conn_to_host.name; + else + hostname = conn->host.name; + + failf(data, "Failed to connect to %s port %ld: %s", + hostname, conn->port, + Curl_strerror(error, buffer, sizeof(buffer))); + } + + return result; +} + +static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) +{ +#if defined(TCP_NODELAY) +//#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + struct Curl_easy *data = conn->data; +//#endif + curl_socklen_t onoff = (curl_socklen_t) 1; + int level = IPPROTO_TCP; + char buffer[STRERROR_LEN]; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) conn; +#endif + + if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, + sizeof(onoff)) < 0) + infof(data, "Could not set TCP_NODELAY: %s\n", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + else + infof(data, "TCP_NODELAY set\n"); +#else + (void)conn; + (void)sockfd; +#endif +} + +#ifdef SO_NOSIGPIPE +/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when + sending data to a dead peer (instead of relying on the 4th argument to send + being MSG_NOSIGNAL). Possibly also existing and in use on other BSD + systems? */ +static void nosigpipe(struct connectdata *conn, + curl_socket_t sockfd) +{ + struct Curl_easy *data = conn->data; + int onoff = 1; + if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, + sizeof(onoff)) < 0) { + char buffer[STRERROR_LEN]; + infof(data, "Could not set SO_NOSIGPIPE: %s\n", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + } +} +#else +#define nosigpipe(x,y) Curl_nop_stmt +#endif + +#ifdef USE_WINSOCK +/* When you run a program that uses the Windows Sockets API, you may + experience slow performance when you copy data to a TCP server. + + https://support.microsoft.com/kb/823764 + + Work-around: Make the Socket Send Buffer Size Larger Than the Program Send + Buffer Size + + The problem described in this knowledge-base is applied only to pre-Vista + Windows. Following function trying to detect OS version and skips + SO_SNDBUF adjustment for Windows Vista and above. +*/ +#define DETECT_OS_NONE 0 +#define DETECT_OS_PREVISTA 1 +#define DETECT_OS_VISTA_OR_LATER 2 + +void Curl_sndbufset(curl_socket_t sockfd) +{ + int val = CURL_MAX_WRITE_SIZE + 32; + int curval = 0; + int curlen = sizeof(curval); + + static int detectOsState = DETECT_OS_NONE; + + if(detectOsState == DETECT_OS_NONE) { + if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) + detectOsState = DETECT_OS_VISTA_OR_LATER; + else + detectOsState = DETECT_OS_PREVISTA; + } + + if(detectOsState == DETECT_OS_VISTA_OR_LATER) + return; + + if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) + if(curval > val) + return; + + setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); +} +#endif + +/* + * singleipconnect() + * + * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to + * CURL_SOCKET_BAD. Other errors will however return proper errors. + * + * singleipconnect() connects to the given IP only, and it may return without + * having connected. + */ +static CURLcode singleipconnect(struct connectdata *conn, + const Curl_addrinfo *ai, + curl_socket_t *sockp) +{ + struct Curl_sockaddr_ex addr; + int rc = -1; + int error = 0; + bool isconnected = FALSE; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd; + CURLcode result; + char ipaddress[MAX_IPADR_LEN]; + long port; + bool is_tcp; +#ifdef TCP_FASTOPEN_CONNECT + int optval = 1; +#endif + char buffer[STRERROR_LEN]; + + *sockp = CURL_SOCKET_BAD; + + result = Curl_socket(conn, ai, &addr, &sockfd); + if(result) + /* Failed to create the socket, but still return OK since we signal the + lack of socket as well. This allows the parent function to keep looping + over alternative addresses/socket families etc. */ + return CURLE_OK; + + /* store remote address and port used in this connection attempt */ + if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, + ipaddress, &port)) { + /* malformed address or bug in inet_ntop, try next address */ + failf(data, "sa_addr inet_ntop() failed with errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + Curl_closesocket(conn, sockfd); + return CURLE_OK; + } + infof(data, " Trying %s:%ld...\n", ipaddress, port); + +#ifdef ENABLE_IPV6 + is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) && + addr.socktype == SOCK_STREAM; +#else + is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM; +#endif + if(is_tcp && data->set.tcp_nodelay) + tcpnodelay(conn, sockfd); + + nosigpipe(conn, sockfd); + + Curl_sndbufset(sockfd); + + if(is_tcp && data->set.tcp_keepalive) + tcpkeepalive(data, sockfd); + + if(data->set.fsockopt) { + /* activate callback for setting socket options */ + Curl_set_in_callback(data, true); + error = data->set.fsockopt(data->set.sockopt_client, + sockfd, + CURLSOCKTYPE_IPCXN); + Curl_set_in_callback(data, false); + + if(error == CURL_SOCKOPT_ALREADY_CONNECTED) + isconnected = TRUE; + else if(error) { + Curl_closesocket(conn, sockfd); /* close the socket and bail out */ + return CURLE_ABORTED_BY_CALLBACK; + } + } + + /* possibly bind the local end to an IP, interface or port */ + if(addr.family == AF_INET +#ifdef ENABLE_IPV6 + || addr.family == AF_INET6 +#endif + ) { + result = bindlocal(conn, sockfd, addr.family, + Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr)); + if(result) { + Curl_closesocket(conn, sockfd); /* close socket and bail out */ + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + /* The address family is not supported on this interface. + We can continue trying addresses */ + return CURLE_COULDNT_CONNECT; + } + return result; + } + } + + /* set socket non-blocking */ + (void)curlx_nonblock(sockfd, TRUE); + + conn->connecttime = Curl_now(); + if(conn->num_addr > 1) + Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME); + + /* Connect TCP sockets, bind UDP */ + if(!isconnected && (conn->socktype == SOCK_STREAM)) { + if(conn->bits.tcp_fastopen) { +#if defined(CONNECT_DATA_IDEMPOTENT) /* Darwin */ +# if defined(HAVE_BUILTIN_AVAILABLE) + /* while connectx function is available since macOS 10.11 / iOS 9, + it did not have the interface declared correctly until + Xcode 9 / macOS SDK 10.13 */ + if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) { + sa_endpoints_t endpoints; + endpoints.sae_srcif = 0; + endpoints.sae_srcaddr = NULL; + endpoints.sae_srcaddrlen = 0; + endpoints.sae_dstaddr = &addr.sa_addr; + endpoints.sae_dstaddrlen = addr.addrlen; + + rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY, + CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT, + NULL, 0, NULL, NULL); + } + else { + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + } +# else + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); +# endif /* HAVE_BUILTIN_AVAILABLE */ +#elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */ + if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, + (void *)&optval, sizeof(optval)) < 0) + infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd); + else + infof(data, "TCP_FASTOPEN_CONNECT set\n"); + + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); +#elif defined(MSG_FASTOPEN) /* old Linux */ + if(conn->given->flags & PROTOPT_SSL) + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + else + rc = 0; /* Do nothing */ +#endif + } + else { + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + } + + if(-1 == rc) + error = SOCKERRNO; + } + else { + *sockp = sockfd; + return CURLE_OK; + } + + if(-1 == rc) { + switch(error) { + case EINPROGRESS: + case EWOULDBLOCK: +#if defined(EAGAIN) +#if (EAGAIN) != (EWOULDBLOCK) + /* On some platforms EAGAIN and EWOULDBLOCK are the + * same value, and on others they are different, hence + * the odd #if + */ + case EAGAIN: +#endif +#endif + result = CURLE_OK; + break; + + default: + /* unknown error, fallthrough and try another address! */ + infof(data, "Immediate connect fail for %s: %s\n", + ipaddress, Curl_strerror(error, buffer, sizeof(buffer))); + data->state.os_errno = error; + + /* connect failed */ + Curl_closesocket(conn, sockfd); + result = CURLE_COULDNT_CONNECT; + } + } + + if(!result) + *sockp = sockfd; + + return result; +} + +/* + * TCP connect to the given host with timeout, proxy or remote doesn't matter. + * There might be more than one IP address to try out. Fill in the passed + * pointer with the connected socket. + */ + +CURLcode Curl_connecthost(struct connectdata *conn, /* context */ + const struct Curl_dns_entry *remotehost) +{ + struct Curl_easy *data = conn->data; + struct curltime before = Curl_now(); + CURLcode result = CURLE_COULDNT_CONNECT; + + timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE); + + if(timeout_ms < 0) { + /* a precaution, no need to continue if time already is up */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + conn->num_addr = Curl_num_addresses(remotehost->addr); + conn->tempaddr[0] = remotehost->addr; + conn->tempaddr[1] = NULL; + conn->tempsock[0] = CURL_SOCKET_BAD; + conn->tempsock[1] = CURL_SOCKET_BAD; + + /* Max time for the next connection attempt */ + conn->timeoutms_per_addr = + conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2; + + /* start connecting to first IP */ + while(conn->tempaddr[0]) { + result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0])); + if(!result) + break; + conn->tempaddr[0] = conn->tempaddr[0]->ai_next; + } + + if(conn->tempsock[0] == CURL_SOCKET_BAD) { + if(!result) + result = CURLE_COULDNT_CONNECT; + return result; + } + + data->info.numconnects++; /* to track the number of connections made */ + Curl_expire(conn->data, data->set.happy_eyeballs_timeout, + EXPIRE_HAPPY_EYEBALLS); + + return CURLE_OK; +} + +struct connfind { + struct connectdata *tofind; + bool found; +}; + +static int conn_is_conn(struct connectdata *conn, void *param) +{ + struct connfind *f = (struct connfind *)param; + if(conn == f->tofind) { + f->found = TRUE; + return 1; + } + return 0; +} + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given Curl_easy. + * + * The returned socket will be CURL_SOCKET_BAD in case of failure! + */ +curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, + struct connectdata **connp) +{ + DEBUGASSERT(data); + + /* this works for an easy handle: + * - that has been used for curl_easy_perform() + * - that is associated with a multi handle, and whose connection + * was detached with CURLOPT_CONNECT_ONLY + */ + if(data->state.lastconnect && (data->multi_easy || data->multi)) { + struct connectdata *c = data->state.lastconnect; + struct connfind find; + find.tofind = data->state.lastconnect; + find.found = FALSE; + + Curl_conncache_foreach(data, data->multi_easy? + &data->multi_easy->conn_cache: + &data->multi->conn_cache, &find, conn_is_conn); + + if(!find.found) { + data->state.lastconnect = NULL; + return CURL_SOCKET_BAD; + } + + if(connp) { + /* only store this if the caller cares for it */ + *connp = c; + c->data = data; + } + return c->sock[FIRSTSOCKET]; + } + else + return CURL_SOCKET_BAD; +} + +/* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn) +{ + /* First determine if ssl */ + if(conn->ssl[FIRSTSOCKET].use) { + /* use the SSL context */ + if(!Curl_ssl_check_cxn(conn)) + return false; /* FIN received */ + } +/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ +#ifdef MSG_PEEK + else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) + return false; + else { + /* use the socket */ + char buf; + if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { + return false; /* FIN received */ + } + } +#endif + return true; +} + +/* + * Close a socket. + * + * 'conn' can be NULL, beware! + */ +int Curl_closesocket(struct connectdata *conn, + curl_socket_t sock) +{ + if(conn && conn->fclosesocket) { + if((sock == conn->sock[SECONDARYSOCKET]) && + conn->sock_accepted[SECONDARYSOCKET]) + /* if this socket matches the second socket, and that was created with + accept, then we MUST NOT call the callback but clear the accepted + status */ + conn->sock_accepted[SECONDARYSOCKET] = FALSE; + else { + int rc; + Curl_multi_closed(conn->data, sock); + Curl_set_in_callback(conn->data, true); + rc = conn->fclosesocket(conn->closesocket_client, sock); + Curl_set_in_callback(conn->data, false); + return rc; + } + } + + if(conn) + /* tell the multi-socket code about this */ + Curl_multi_closed(conn->data, sock); + + sclose(sock); + + return 0; +} + +/* + * Create a socket based on info from 'conn' and 'ai'. + * + * 'addr' should be a pointer to the correct struct to get data back, or NULL. + * 'sockfd' must be a pointer to a socket descriptor. + * + * If the open socket callback is set, used that! + * + */ +CURLcode Curl_socket(struct connectdata *conn, + const Curl_addrinfo *ai, + struct Curl_sockaddr_ex *addr, + curl_socket_t *sockfd) +{ + struct Curl_easy *data = conn->data; + struct Curl_sockaddr_ex dummy; + + if(!addr) + /* if the caller doesn't want info back, use a local temp copy */ + addr = &dummy; + + /* + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold + * any protocol-specific address structures. The variable declared here + * will be used to pass / receive data to/from the fopensocket callback + * if this has been set, before that, it is initialized from parameters. + */ + + addr->family = ai->ai_family; + addr->socktype = conn->socktype; + addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; + addr->addrlen = ai->ai_addrlen; + + if(addr->addrlen > sizeof(struct Curl_sockaddr_storage)) + addr->addrlen = sizeof(struct Curl_sockaddr_storage); + memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen); + + if(data->set.fopensocket) { + /* + * If the opensocket callback is set, all the destination address + * information is passed to the callback. Depending on this information the + * callback may opt to abort the connection, this is indicated returning + * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When + * the callback returns a valid socket the destination address information + * might have been changed and this 'new' address will actually be used + * here to connect. + */ + Curl_set_in_callback(data, true); + *sockfd = data->set.fopensocket(data->set.opensocket_client, + CURLSOCKTYPE_IPCXN, + (struct curl_sockaddr *)addr); + Curl_set_in_callback(data, false); + } + else + /* opensocket callback not set, so simply create the socket now */ + *sockfd = socket(addr->family, addr->socktype, addr->protocol); + + if(*sockfd == CURL_SOCKET_BAD) + /* no socket, no connection */ + return CURLE_COULDNT_CONNECT; + +#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) + if(conn->scope_id && (addr->family == AF_INET6)) { + struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr; + sa6->sin6_scope_id = conn->scope_id; + } +#endif + + return CURLE_OK; + +} + +/* + * Curl_conncontrol() marks streams or connection for closure. + */ +void Curl_conncontrol(struct connectdata *conn, + int ctrl /* see defines in header */ +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + , const char *reason +#endif + ) +{ + /* close if a connection, or a stream that isn't multiplexed */ + bool closeit = (ctrl == CONNCTRL_CONNECTION) || + ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM)); + if((ctrl == CONNCTRL_STREAM) && + (conn->handler->flags & PROTOPT_STREAM)) + DEBUGF(infof(conn->data, "Kill stream: %s\n", reason)); + else if((bit)closeit != conn->bits.close) { + DEBUGF(infof(conn->data, "Marked for [%s]: %s\n", + closeit?"closure":"keep alive", reason)); + conn->bits.close = closeit; /* the only place in the source code that + should assign this bit */ + } +} + +/* Data received can be cached at various levels, so check them all here. */ +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex) +{ + int readable; + + if(Curl_ssl_data_pending(conn, sockindex) || + Curl_recv_has_postponed_data(conn, sockindex)) + return true; + + readable = SOCKET_READABLE(conn->sock[sockindex], 0); + return (readable > 0 && (readable & CURL_CSELECT_IN)); +} diff --git a/libcurl/lib/connect.h b/libcurl/lib/connect.h new file mode 100644 index 0000000..6a5c755 --- /dev/null +++ b/libcurl/lib/connect.h @@ -0,0 +1,144 @@ +#ifndef HEADER_CURL_CONNECT_H +#define HEADER_CURL_CONNECT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */ +#include "sockaddr.h" +#include "timeval.h" + +CURLcode Curl_is_connected(struct connectdata *conn, + int sockindex, + bool *connected); + +CURLcode Curl_connecthost(struct connectdata *conn, + const struct Curl_dns_entry *host); + +/* generic function that returns how much time there's left to run, according + to the timeouts set */ +timediff_t Curl_timeleft(struct Curl_easy *data, + struct curltime *nowp, + bool duringconnect); + +#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given Curl_easy. + * + * The returned socket will be CURL_SOCKET_BAD in case of failure! + */ +curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, + struct connectdata **connp); + +/* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn); + +#ifdef USE_WINSOCK +/* When you run a program that uses the Windows Sockets API, you may + experience slow performance when you copy data to a TCP server. + + https://support.microsoft.com/kb/823764 + + Work-around: Make the Socket Send Buffer Size Larger Than the Program Send + Buffer Size + +*/ +void Curl_sndbufset(curl_socket_t sockfd); +#else +#define Curl_sndbufset(y) Curl_nop_stmt +#endif + +void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); +void Curl_persistconninfo(struct connectdata *conn); +int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); + +/* + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold any + * protocol-specific address structures. The variable declared here will be + * used to pass / receive data to/from the fopensocket callback if this has + * been set, before that, it is initialized from parameters. + */ +struct Curl_sockaddr_ex { + int family; + int socktype; + int protocol; + unsigned int addrlen; + union { + struct sockaddr addr; + struct Curl_sockaddr_storage buff; + } _sa_ex_u; +}; +#define sa_addr _sa_ex_u.addr + +/* + * Create a socket based on info from 'conn' and 'ai'. + * + * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open + * socket callback is set, used that! + * + */ +CURLcode Curl_socket(struct connectdata *conn, + const Curl_addrinfo *ai, + struct Curl_sockaddr_ex *addr, + curl_socket_t *sockfd); + +/* + * Curl_conncontrol() marks the end of a connection/stream. The 'closeit' + * argument specifies if it is the end of a connection or a stream. + * + * For stream-based protocols (such as HTTP/2), a stream close will not cause + * a connection close. Other protocols will close the connection for both + * cases. + * + * It sets the bit.close bit to TRUE (with an explanation for debug builds), + * when the connection will close. + */ + +#define CONNCTRL_KEEP 0 /* undo a marked closure */ +#define CONNCTRL_CONNECTION 1 +#define CONNCTRL_STREAM 2 + +void Curl_conncontrol(struct connectdata *conn, + int closeit +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + , const char *reason +#endif + ); + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y) +#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y) +#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y) +#else /* if !DEBUGBUILD || CURL_DISABLE_VERBOSE_STRINGS */ +#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM) +#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION) +#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP) +#endif + +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex); + +#endif /* HEADER_CURL_CONNECT_H */ diff --git a/libcurl/lib/content_encoding.c b/libcurl/lib/content_encoding.c new file mode 100644 index 0000000..6d47537 --- /dev/null +++ b/libcurl/lib/content_encoding.c @@ -0,0 +1,1020 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include +#include + +#ifdef HAVE_ZLIB_H +#include +#ifdef __SYMBIAN32__ +/* zlib pollutes the namespace with this definition */ +#undef WIN32 +#endif +#endif + +#ifdef HAVE_BROTLI +#include +#endif + +#include "sendf.h" +#include "http.h" +#include "content_encoding.h" +#include "strdup.h" +#include "strcase.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define CONTENT_ENCODING_DEFAULT "identity" + +#ifndef CURL_DISABLE_HTTP + +#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */ + + +#ifdef HAVE_LIBZ + +/* Comment this out if zlib is always going to be at least ver. 1.2.0.4 + (doing so will reduce code size slightly). */ +#define OLD_ZLIB_SUPPORT 1 + +#define GZIP_MAGIC_0 0x1f +#define GZIP_MAGIC_1 0x8b + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef enum { + ZLIB_UNINIT, /* uninitialized */ + ZLIB_INIT, /* initialized */ + ZLIB_INFLATING, /* inflating started. */ + ZLIB_EXTERNAL_TRAILER, /* reading external trailer */ + ZLIB_GZIP_HEADER, /* reading gzip header */ + ZLIB_GZIP_INFLATING, /* inflating gzip stream */ + ZLIB_INIT_GZIP /* initialized in transparent gzip mode */ +} zlibInitState; + +/* Writer parameters. */ +typedef struct { + zlibInitState zlib_init; /* zlib init state */ + uInt trailerlen; /* Remaining trailer byte count. */ + z_stream z; /* State structure for zlib. */ +} zlib_params; + + +static voidpf +zalloc_cb(voidpf opaque, unsigned int items, unsigned int size) +{ + (void) opaque; + /* not a typo, keep it calloc() */ + return (voidpf) calloc(items, size); +} + +static void +zfree_cb(voidpf opaque, voidpf ptr) +{ + (void) opaque; + free(ptr); +} + +static CURLcode +process_zlib_error(struct connectdata *conn, z_stream *z) +{ + struct Curl_easy *data = conn->data; + if(z->msg) + failf(data, "Error while processing content unencoding: %s", + z->msg); + else + failf(data, "Error while processing content unencoding: " + "Unknown failure within decompression software."); + + return CURLE_BAD_CONTENT_ENCODING; +} + +static CURLcode +exit_zlib(struct connectdata *conn, + z_stream *z, zlibInitState *zlib_init, CURLcode result) +{ + if(*zlib_init == ZLIB_GZIP_HEADER) + Curl_safefree(z->next_in); + + if(*zlib_init != ZLIB_UNINIT) { + if(inflateEnd(z) != Z_OK && result == CURLE_OK) + result = process_zlib_error(conn, z); + *zlib_init = ZLIB_UNINIT; + } + + return result; +} + +static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp) +{ + z_stream *z = &zp->z; + CURLcode result = CURLE_OK; + uInt len = z->avail_in < zp->trailerlen? z->avail_in: zp->trailerlen; + + /* Consume expected trailer bytes. Terminate stream if exhausted. + Issue an error if unexpected bytes follow. */ + + zp->trailerlen -= len; + z->avail_in -= len; + z->next_in += len; + if(z->avail_in) + result = CURLE_WRITE_ERROR; + if(result || !zp->trailerlen) + result = exit_zlib(conn, z, &zp->zlib_init, result); + else { + /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */ + zp->zlib_init = ZLIB_EXTERNAL_TRAILER; + } + return result; +} + +static CURLcode inflate_stream(struct connectdata *conn, + contenc_writer *writer, zlibInitState started) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + uInt nread = z->avail_in; + Bytef *orig_in = z->next_in; + bool done = FALSE; + CURLcode result = CURLE_OK; /* Curl_client_write status */ + char *decomp; /* Put the decompressed data here. */ + + /* Check state. */ + if(zp->zlib_init != ZLIB_INIT && + zp->zlib_init != ZLIB_INFLATING && + zp->zlib_init != ZLIB_INIT_GZIP && + zp->zlib_init != ZLIB_GZIP_INFLATING) + return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); + + /* Dynamically allocate a buffer for decompression because it's uncommonly + large to hold on the stack */ + decomp = malloc(DSIZ); + if(decomp == NULL) + return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + + /* because the buffer size is fixed, iteratively decompress and transfer to + the client via downstream_write function. */ + while(!done) { + int status; /* zlib status */ + done = TRUE; + + /* (re)set buffer for decompressed output for every iteration */ + z->next_out = (Bytef *) decomp; + z->avail_out = DSIZ; + +#ifdef Z_BLOCK + /* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */ + status = inflate(z, Z_BLOCK); +#else + /* fallback for zlib ver. < 1.2.0.5 */ + status = inflate(z, Z_SYNC_FLUSH); +#endif + + /* Flush output data if some. */ + if(z->avail_out != DSIZ) { + if(status == Z_OK || status == Z_STREAM_END) { + zp->zlib_init = started; /* Data started. */ + result = Curl_unencode_write(conn, writer->downstream, decomp, + DSIZ - z->avail_out); + if(result) { + exit_zlib(conn, z, &zp->zlib_init, result); + break; + } + } + } + + /* Dispatch by inflate() status. */ + switch(status) { + case Z_OK: + /* Always loop: there may be unflushed latched data in zlib state. */ + done = FALSE; + break; + case Z_BUF_ERROR: + /* No more data to flush: just exit loop. */ + break; + case Z_STREAM_END: + result = process_trailer(conn, zp); + break; + case Z_DATA_ERROR: + /* some servers seem to not generate zlib headers, so this is an attempt + to fix and continue anyway */ + if(zp->zlib_init == ZLIB_INIT) { + /* Do not use inflateReset2(): only available since zlib 1.2.3.4. */ + (void) inflateEnd(z); /* don't care about the return code */ + if(inflateInit2(z, -MAX_WBITS) == Z_OK) { + z->next_in = orig_in; + z->avail_in = nread; + zp->zlib_init = ZLIB_INFLATING; + zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */ + done = FALSE; + break; + } + zp->zlib_init = ZLIB_UNINIT; /* inflateEnd() already called. */ + } + /* FALLTHROUGH */ + default: + result = exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + break; + } + } + free(decomp); + + /* We're about to leave this call so the `nread' data bytes won't be seen + again. If we are in a state that would wrongly allow restart in raw mode + at the next call, assume output has already started. */ + if(nread && zp->zlib_init == ZLIB_INIT) + zp->zlib_init = started; /* Cannot restart anymore. */ + + return result; +} + + +/* Deflate handler. */ +static CURLcode deflate_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + if(!writer->downstream) + return CURLE_WRITE_ERROR; + + /* Initialize zlib */ + z->zalloc = (alloc_func) zalloc_cb; + z->zfree = (free_func) zfree_cb; + + if(inflateInit(z) != Z_OK) + return process_zlib_error(conn, z); + zp->zlib_init = ZLIB_INIT; + return CURLE_OK; +} + +static CURLcode deflate_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + /* Set the compressed input when this function is called */ + z->next_in = (Bytef *) buf; + z->avail_in = (uInt) nbytes; + + if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER) + return process_trailer(conn, zp); + + /* Now uncompress the data */ + return inflate_stream(conn, writer, ZLIB_INFLATING); +} + +static void deflate_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + exit_zlib(conn, z, &zp->zlib_init, CURLE_OK); +} + +static const content_encoding deflate_encoding = { + "deflate", + NULL, + deflate_init_writer, + deflate_unencode_write, + deflate_close_writer, + sizeof(zlib_params) +}; + + +/* Gzip handler. */ +static CURLcode gzip_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + if(!writer->downstream) + return CURLE_WRITE_ERROR; + + /* Initialize zlib */ + z->zalloc = (alloc_func) zalloc_cb; + z->zfree = (free_func) zfree_cb; + + if(strcmp(zlibVersion(), "1.2.0.4") >= 0) { + /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ + if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) { + return process_zlib_error(conn, z); + } + zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ + } + else { + /* we must parse the gzip header and trailer ourselves */ + if(inflateInit2(z, -MAX_WBITS) != Z_OK) { + return process_zlib_error(conn, z); + } + zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */ + zp->zlib_init = ZLIB_INIT; /* Initial call state */ + } + + return CURLE_OK; +} + +#ifdef OLD_ZLIB_SUPPORT +/* Skip over the gzip header */ +static enum { + GZIP_OK, + GZIP_BAD, + GZIP_UNDERFLOW +} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen) +{ + int method, flags; + const ssize_t totallen = len; + + /* The shortest header is 10 bytes */ + if(len < 10) + return GZIP_UNDERFLOW; + + if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1)) + return GZIP_BAD; + + method = data[2]; + flags = data[3]; + + if(method != Z_DEFLATED || (flags & RESERVED) != 0) { + /* Can't handle this compression method or unknown flag */ + return GZIP_BAD; + } + + /* Skip over time, xflags, OS code and all previous bytes */ + len -= 10; + data += 10; + + if(flags & EXTRA_FIELD) { + ssize_t extra_len; + + if(len < 2) + return GZIP_UNDERFLOW; + + extra_len = (data[1] << 8) | data[0]; + + if(len < (extra_len + 2)) + return GZIP_UNDERFLOW; + + len -= (extra_len + 2); + data += (extra_len + 2); + } + + if(flags & ORIG_NAME) { + /* Skip over NUL-terminated file name */ + while(len && *data) { + --len; + ++data; + } + if(!len || *data) + return GZIP_UNDERFLOW; + + /* Skip over the NUL */ + --len; + ++data; + } + + if(flags & COMMENT) { + /* Skip over NUL-terminated comment */ + while(len && *data) { + --len; + ++data; + } + if(!len || *data) + return GZIP_UNDERFLOW; + + /* Skip over the NUL */ + --len; + } + + if(flags & HEAD_CRC) { + if(len < 2) + return GZIP_UNDERFLOW; + + len -= 2; + } + + *headerlen = totallen - len; + return GZIP_OK; +} +#endif + +static CURLcode gzip_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + if(zp->zlib_init == ZLIB_INIT_GZIP) { + /* Let zlib handle the gzip decompression entirely */ + z->next_in = (Bytef *) buf; + z->avail_in = (uInt) nbytes; + /* Now uncompress the data */ + return inflate_stream(conn, writer, ZLIB_INIT_GZIP); + } + +#ifndef OLD_ZLIB_SUPPORT + /* Support for old zlib versions is compiled away and we are running with + an old version, so return an error. */ + return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); + +#else + /* This next mess is to get around the potential case where there isn't + * enough data passed in to skip over the gzip header. If that happens, we + * malloc a block and copy what we have then wait for the next call. If + * there still isn't enough (this is definitely a worst-case scenario), we + * make the block bigger, copy the next part in and keep waiting. + * + * This is only required with zlib versions < 1.2.0.4 as newer versions + * can handle the gzip header themselves. + */ + + switch(zp->zlib_init) { + /* Skip over gzip header? */ + case ZLIB_INIT: + { + /* Initial call state */ + ssize_t hlen; + + switch(check_gzip_header((unsigned char *) buf, nbytes, &hlen)) { + case GZIP_OK: + z->next_in = (Bytef *) buf + hlen; + z->avail_in = (uInt) (nbytes - hlen); + zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ + break; + + case GZIP_UNDERFLOW: + /* We need more data so we can find the end of the gzip header. It's + * possible that the memory block we malloc here will never be freed if + * the transfer abruptly aborts after this point. Since it's unlikely + * that circumstances will be right for this code path to be followed in + * the first place, and it's even more unlikely for a transfer to fail + * immediately afterwards, it should seldom be a problem. + */ + z->avail_in = (uInt) nbytes; + z->next_in = malloc(z->avail_in); + if(z->next_in == NULL) { + return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + } + memcpy(z->next_in, buf, z->avail_in); + zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ + /* We don't have any data to inflate yet */ + return CURLE_OK; + + case GZIP_BAD: + default: + return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + } + + } + break; + + case ZLIB_GZIP_HEADER: + { + /* Need more gzip header data state */ + ssize_t hlen; + z->avail_in += (uInt) nbytes; + z->next_in = Curl_saferealloc(z->next_in, z->avail_in); + if(z->next_in == NULL) { + return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); + } + /* Append the new block of data to the previous one */ + memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes); + + switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) { + case GZIP_OK: + /* This is the zlib stream data */ + free(z->next_in); + /* Don't point into the malloced block since we just freed it */ + z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in; + z->avail_in = (uInt) (z->avail_in - hlen); + zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ + break; + + case GZIP_UNDERFLOW: + /* We still don't have any data to inflate! */ + return CURLE_OK; + + case GZIP_BAD: + default: + return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); + } + + } + break; + + case ZLIB_EXTERNAL_TRAILER: + z->next_in = (Bytef *) buf; + z->avail_in = (uInt) nbytes; + return process_trailer(conn, zp); + + case ZLIB_GZIP_INFLATING: + default: + /* Inflating stream state */ + z->next_in = (Bytef *) buf; + z->avail_in = (uInt) nbytes; + break; + } + + if(z->avail_in == 0) { + /* We don't have any data to inflate; wait until next time */ + return CURLE_OK; + } + + /* We've parsed the header, now uncompress the data */ + return inflate_stream(conn, writer, ZLIB_GZIP_INFLATING); +#endif +} + +static void gzip_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + zlib_params *zp = (zlib_params *) &writer->params; + z_stream *z = &zp->z; /* zlib state structure */ + + exit_zlib(conn, z, &zp->zlib_init, CURLE_OK); +} + +static const content_encoding gzip_encoding = { + "gzip", + "x-gzip", + gzip_init_writer, + gzip_unencode_write, + gzip_close_writer, + sizeof(zlib_params) +}; + +#endif /* HAVE_LIBZ */ + + +#ifdef HAVE_BROTLI + +/* Writer parameters. */ +typedef struct { + BrotliDecoderState *br; /* State structure for brotli. */ +} brotli_params; + + +static CURLcode brotli_map_error(BrotliDecoderErrorCode be) +{ + switch(be) { + case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: + case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: + case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: + case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: + case BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: + case BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: + case BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: + case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: + case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: + case BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: + case BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: + case BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: + case BROTLI_DECODER_ERROR_FORMAT_PADDING_1: + case BROTLI_DECODER_ERROR_FORMAT_PADDING_2: +#ifdef BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY + case BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY: +#endif +#ifdef BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET + case BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: +#endif + case BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: + return CURLE_BAD_CONTENT_ENCODING; + case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: + case BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: + case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: + case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: + case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: + case BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: + return CURLE_OUT_OF_MEMORY; + default: + break; + } + return CURLE_WRITE_ERROR; +} + +static CURLcode brotli_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + brotli_params *bp = (brotli_params *) &writer->params; + + (void) conn; + + if(!writer->downstream) + return CURLE_WRITE_ERROR; + + bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL); + return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY; +} + +static CURLcode brotli_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + brotli_params *bp = (brotli_params *) &writer->params; + const uint8_t *src = (const uint8_t *) buf; + char *decomp; + uint8_t *dst; + size_t dstleft; + CURLcode result = CURLE_OK; + BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; + + if(!bp->br) + return CURLE_WRITE_ERROR; /* Stream already ended. */ + + decomp = malloc(DSIZ); + if(!decomp) + return CURLE_OUT_OF_MEMORY; + + while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) && + result == CURLE_OK) { + dst = (uint8_t *) decomp; + dstleft = DSIZ; + r = BrotliDecoderDecompressStream(bp->br, + &nbytes, &src, &dstleft, &dst, NULL); + result = Curl_unencode_write(conn, writer->downstream, + decomp, DSIZ - dstleft); + if(result) + break; + switch(r) { + case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: + case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: + break; + case BROTLI_DECODER_RESULT_SUCCESS: + BrotliDecoderDestroyInstance(bp->br); + bp->br = NULL; + if(nbytes) + result = CURLE_WRITE_ERROR; + break; + default: + result = brotli_map_error(BrotliDecoderGetErrorCode(bp->br)); + break; + } + } + free(decomp); + return result; +} + +static void brotli_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + brotli_params *bp = (brotli_params *) &writer->params; + + (void) conn; + + if(bp->br) { + BrotliDecoderDestroyInstance(bp->br); + bp->br = NULL; + } +} + +static const content_encoding brotli_encoding = { + "br", + NULL, + brotli_init_writer, + brotli_unencode_write, + brotli_close_writer, + sizeof(brotli_params) +}; +#endif + + +/* Identity handler. */ +static CURLcode identity_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR; +} + +static CURLcode identity_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + return Curl_unencode_write(conn, writer->downstream, buf, nbytes); +} + +static void identity_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + (void) writer; +} + +static const content_encoding identity_encoding = { + "identity", + "none", + identity_init_writer, + identity_unencode_write, + identity_close_writer, + 0 +}; + + +/* supported content encodings table. */ +static const content_encoding * const encodings[] = { + &identity_encoding, +#ifdef HAVE_LIBZ + &deflate_encoding, + &gzip_encoding, +#endif +#ifdef HAVE_BROTLI + &brotli_encoding, +#endif + NULL +}; + + +/* Return a list of comma-separated names of supported encodings. */ +char *Curl_all_content_encodings(void) +{ + size_t len = 0; + const content_encoding * const *cep; + const content_encoding *ce; + char *ace; + + for(cep = encodings; *cep; cep++) { + ce = *cep; + if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) + len += strlen(ce->name) + 2; + } + + if(!len) + return strdup(CONTENT_ENCODING_DEFAULT); + + ace = malloc(len); + if(ace) { + char *p = ace; + for(cep = encodings; *cep; cep++) { + ce = *cep; + if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) { + strcpy(p, ce->name); + p += strlen(p); + *p++ = ','; + *p++ = ' '; + } + } + p[-2] = '\0'; + } + + return ace; +} + + +/* Real client writer: no downstream. */ +static CURLcode client_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK; +} + +static CURLcode client_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + + (void) writer; + + if(!nbytes || k->ignorebody) + return CURLE_OK; + + return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes); +} + +static void client_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + (void) writer; +} + +static const content_encoding client_encoding = { + NULL, + NULL, + client_init_writer, + client_unencode_write, + client_close_writer, + 0 +}; + + +/* Deferred error dummy writer. */ +static CURLcode error_init_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR; +} + +static CURLcode error_unencode_write(struct connectdata *conn, + contenc_writer *writer, + const char *buf, size_t nbytes) +{ + char *all = Curl_all_content_encodings(); + + (void) writer; + (void) buf; + (void) nbytes; + + if(!all) + return CURLE_OUT_OF_MEMORY; + failf(conn->data, "Unrecognized content encoding type. " + "libcurl understands %s content encodings.", all); + free(all); + return CURLE_BAD_CONTENT_ENCODING; +} + +static void error_close_writer(struct connectdata *conn, + contenc_writer *writer) +{ + (void) conn; + (void) writer; +} + +static const content_encoding error_encoding = { + NULL, + NULL, + error_init_writer, + error_unencode_write, + error_close_writer, + 0 +}; + +/* Create an unencoding writer stage using the given handler. */ +static contenc_writer *new_unencoding_writer(struct connectdata *conn, + const content_encoding *handler, + contenc_writer *downstream) +{ + size_t sz = offsetof(contenc_writer, params) + handler->paramsize; + contenc_writer *writer = (contenc_writer *) calloc(1, sz); + + if(writer) { + writer->handler = handler; + writer->downstream = downstream; + if(handler->init_writer(conn, writer)) { + free(writer); + writer = NULL; + } + } + + return writer; +} + +/* Write data using an unencoding writer stack. */ +CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes) +{ + if(!nbytes) + return CURLE_OK; + return writer->handler->unencode_write(conn, writer, buf, nbytes); +} + +/* Close and clean-up the connection's writer stack. */ +void Curl_unencode_cleanup(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + contenc_writer *writer = k->writer_stack; + + while(writer) { + k->writer_stack = writer->downstream; + writer->handler->close_writer(conn, writer); + free(writer); + writer = k->writer_stack; + } +} + +/* Find the content encoding by name. */ +static const content_encoding *find_encoding(const char *name, size_t len) +{ + const content_encoding * const *cep; + + for(cep = encodings; *cep; cep++) { + const content_encoding *ce = *cep; + if((strncasecompare(name, ce->name, len) && !ce->name[len]) || + (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len])) + return ce; + } + return NULL; +} + +/* Set-up the unencoding stack from the Content-Encoding header value. + * See RFC 7231 section 3.1.2.2. */ +CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + const char *enclist, int maybechunked) +{ + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + + do { + const char *name; + size_t namelen; + + /* Parse a single encoding name. */ + while(ISSPACE(*enclist) || *enclist == ',') + enclist++; + + name = enclist; + + for(namelen = 0; *enclist && *enclist != ','; enclist++) + if(!ISSPACE(*enclist)) + namelen = enclist - name + 1; + + /* Special case: chunked encoding is handled at the reader level. */ + if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) { + k->chunk = TRUE; /* chunks coming our way. */ + Curl_httpchunk_init(conn); /* init our chunky engine. */ + } + else if(namelen) { + const content_encoding *encoding = find_encoding(name, namelen); + contenc_writer *writer; + + if(!k->writer_stack) { + k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL); + + if(!k->writer_stack) + return CURLE_OUT_OF_MEMORY; + } + + if(!encoding) + encoding = &error_encoding; /* Defer error at stack use. */ + + /* Stack the unencoding stage. */ + writer = new_unencoding_writer(conn, encoding, k->writer_stack); + if(!writer) + return CURLE_OUT_OF_MEMORY; + k->writer_stack = writer; + } + } while(*enclist); + + return CURLE_OK; +} + +#else +/* Stubs for builds without HTTP. */ +CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + const char *enclist, int maybechunked) +{ + (void) conn; + (void) enclist; + (void) maybechunked; + return CURLE_NOT_BUILT_IN; +} + +CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes) +{ + (void) conn; + (void) writer; + (void) buf; + (void) nbytes; + return CURLE_NOT_BUILT_IN; +} + +void Curl_unencode_cleanup(struct connectdata *conn) +{ + (void) conn; +} + +char *Curl_all_content_encodings(void) +{ + return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */ +} + +#endif /* CURL_DISABLE_HTTP */ diff --git a/libcurl/lib/content_encoding.h b/libcurl/lib/content_encoding.h new file mode 100644 index 0000000..4cd52be --- /dev/null +++ b/libcurl/lib/content_encoding.h @@ -0,0 +1,55 @@ +#ifndef HEADER_CURL_CONTENT_ENCODING_H +#define HEADER_CURL_CONTENT_ENCODING_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* Decoding writer. */ +typedef struct contenc_writer_s contenc_writer; +typedef struct content_encoding_s content_encoding; + +struct contenc_writer_s { + const content_encoding *handler; /* Encoding handler. */ + contenc_writer *downstream; /* Downstream writer. */ + void *params; /* Encoding-specific storage (variable length). */ +}; + +/* Content encoding writer. */ +struct content_encoding_s { + const char *name; /* Encoding name. */ + const char *alias; /* Encoding name alias. */ + CURLcode (*init_writer)(struct connectdata *conn, contenc_writer *writer); + CURLcode (*unencode_write)(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes); + void (*close_writer)(struct connectdata *conn, contenc_writer *writer); + size_t paramsize; +}; + + +CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + const char *enclist, int maybechunked); +CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes); +void Curl_unencode_cleanup(struct connectdata *conn); +char *Curl_all_content_encodings(void); + +#endif /* HEADER_CURL_CONTENT_ENCODING_H */ diff --git a/libcurl/lib/cookie.c b/libcurl/lib/cookie.c new file mode 100644 index 0000000..9a9e14d --- /dev/null +++ b/libcurl/lib/cookie.c @@ -0,0 +1,1657 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/*** + + +RECEIVING COOKIE INFORMATION +============================ + +struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + const char *file, struct CookieInfo *inc, bool newsession); + + Inits a cookie struct to store data in a local file. This is always + called before any cookies are set. + +struct Cookie *Curl_cookie_add(struct Curl_easy *data, + struct CookieInfo *c, bool httpheader, char *lineptr, + const char *domain, const char *path); + + The 'lineptr' parameter is a full "Set-cookie:" line as + received from a server. + + The function need to replace previously stored lines that this new + line supersedes. + + It may remove lines that are expired. + + It should return an indication of success/error. + + +SENDING COOKIE INFORMATION +========================== + +struct Cookies *Curl_cookie_getlist(struct CookieInfo *cookie, + char *host, char *path, bool secure); + + For a given host and path, return a linked list of cookies that + the client should send to the server if used now. The secure + boolean informs the cookie if a secure connection is achieved or + not. + + It shall only return cookies that haven't expired. + + +Example set of cookies: + + Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure + Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/ftgw; secure + Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; + domain=.fidelity.com; path=/; secure + Set-cookie: + Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday, + 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure +****/ + + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + +#include "urldata.h" +#include "cookie.h" +#include "psl.h" +#include "strtok.h" +#include "sendf.h" +#include "slist.h" +#include "share.h" +#include "strtoofft.h" +#include "strcase.h" +#include "curl_get_line.h" +#include "curl_memrchr.h" +#include "inet_pton.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static void freecookie(struct Cookie *co) +{ + free(co->expirestr); + free(co->domain); + free(co->path); + free(co->spath); + free(co->name); + free(co->value); + free(co->maxage); + free(co->version); + free(co); +} + +static bool tailmatch(const char *cooke_domain, const char *hostname) +{ + size_t cookie_domain_len = strlen(cooke_domain); + size_t hostname_len = strlen(hostname); + + if(hostname_len < cookie_domain_len) + return FALSE; + + if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len)) + return FALSE; + + /* A lead char of cookie_domain is not '.'. + RFC6265 4.1.2.3. The Domain Attribute says: + For example, if the value of the Domain attribute is + "example.com", the user agent will include the cookie in the Cookie + header when making HTTP requests to example.com, www.example.com, and + www.corp.example.com. + */ + if(hostname_len == cookie_domain_len) + return TRUE; + if('.' == *(hostname + hostname_len - cookie_domain_len - 1)) + return TRUE; + return FALSE; +} + +/* + * Return true if the given string is an IP(v4|v6) address. + */ +static bool isip(const char *domain) +{ + struct in_addr addr; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + + if(Curl_inet_pton(AF_INET, domain, &addr) +#ifdef ENABLE_IPV6 + || Curl_inet_pton(AF_INET6, domain, &addr6) +#endif + ) { + /* domain name given as IP address */ + return TRUE; + } + + return FALSE; +} + +/* + * matching cookie path and url path + * RFC6265 5.1.4 Paths and Path-Match + */ +static bool pathmatch(const char *cookie_path, const char *request_uri) +{ + size_t cookie_path_len; + size_t uri_path_len; + char *uri_path = NULL; + char *pos; + bool ret = FALSE; + + /* cookie_path must not have last '/' separator. ex: /sample */ + cookie_path_len = strlen(cookie_path); + if(1 == cookie_path_len) { + /* cookie_path must be '/' */ + return TRUE; + } + + uri_path = strdup(request_uri); + if(!uri_path) + return FALSE; + pos = strchr(uri_path, '?'); + if(pos) + *pos = 0x0; + + /* #-fragments are already cut off! */ + if(0 == strlen(uri_path) || uri_path[0] != '/') { + free(uri_path); + uri_path = strdup("/"); + if(!uri_path) + return FALSE; + } + + /* here, RFC6265 5.1.4 says + 4. Output the characters of the uri-path from the first character up + to, but not including, the right-most %x2F ("/"). + but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site + without redirect. + Ignore this algorithm because /hoge is uri path for this case + (uri path is not /). + */ + + uri_path_len = strlen(uri_path); + + if(uri_path_len < cookie_path_len) { + ret = FALSE; + goto pathmatched; + } + + /* not using checkprefix() because matching should be case-sensitive */ + if(strncmp(cookie_path, uri_path, cookie_path_len)) { + ret = FALSE; + goto pathmatched; + } + + /* The cookie-path and the uri-path are identical. */ + if(cookie_path_len == uri_path_len) { + ret = TRUE; + goto pathmatched; + } + + /* here, cookie_path_len < uri_path_len */ + if(uri_path[cookie_path_len] == '/') { + ret = TRUE; + goto pathmatched; + } + + ret = FALSE; + +pathmatched: + free(uri_path); + return ret; +} + +/* + * Return the top-level domain, for optimal hashing. + */ +static const char *get_top_domain(const char * const domain, size_t *outlen) +{ + size_t len; + const char *first = NULL, *last; + + if(!domain) + return NULL; + + len = strlen(domain); + last = memrchr(domain, '.', len); + if(last) { + first = memrchr(domain, '.', (last - domain)); + if(first) + len -= (++first - domain); + } + + if(outlen) + *outlen = len; + + return first? first: domain; +} + +/* + * A case-insensitive hash for the cookie domains. + */ +static size_t cookie_hash_domain(const char *domain, const size_t len) +{ + const char *end = domain + len; + size_t h = 5381; + + while(domain < end) { + h += h << 5; + h ^= Curl_raw_toupper(*domain++); + } + + return (h % COOKIE_HASH_SIZE); +} + +/* + * Hash this domain. + */ +static size_t cookiehash(const char * const domain) +{ + const char *top; + size_t len; + + if(!domain || isip(domain)) + return 0; + + top = get_top_domain(domain, &len); + return cookie_hash_domain(top, len); +} + +/* + * cookie path sanitize + */ +static char *sanitize_cookie_path(const char *cookie_path) +{ + size_t len; + char *new_path = strdup(cookie_path); + if(!new_path) + return NULL; + + /* some stupid site sends path attribute with '"'. */ + len = strlen(new_path); + if(new_path[0] == '\"') { + memmove((void *)new_path, (const void *)(new_path + 1), len); + len--; + } + if(len && (new_path[len - 1] == '\"')) { + new_path[len - 1] = 0x0; + len--; + } + + /* RFC6265 5.2.4 The Path Attribute */ + if(new_path[0] != '/') { + /* Let cookie-path be the default-path. */ + free(new_path); + new_path = strdup("/"); + return new_path; + } + + /* convert /hoge/ to /hoge */ + if(len && new_path[len - 1] == '/') { + new_path[len - 1] = 0x0; + } + + return new_path; +} + +/* + * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). + * + * NOTE: OOM or cookie parsing failures are ignored. + */ +void Curl_cookie_loadfiles(struct Curl_easy *data) +{ + struct curl_slist *list = data->change.cookielist; + if(list) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + while(list) { + struct CookieInfo *newcookies = Curl_cookie_init(data, + list->data, + data->cookies, + data->set.cookiesession); + if(!newcookies) + /* Failure may be due to OOM or a bad cookie; both are ignored + * but only the first should be + */ + infof(data, "ignoring failed cookie_init for %s\n", list->data); + else + data->cookies = newcookies; + list = list->next; + } + curl_slist_free_all(data->change.cookielist); /* clean up list */ + data->change.cookielist = NULL; /* don't do this again! */ + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +} + +/* + * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL + * that will be freed before the allocated string is stored there. + * + * It is meant to easily replace strdup() + */ +static void strstore(char **str, const char *newstr) +{ + free(*str); + *str = strdup(newstr); +} + +/* + * remove_expired() removes expired cookies. + */ +static void remove_expired(struct CookieInfo *cookies) +{ + struct Cookie *co, *nx; + curl_off_t now = (curl_off_t)time(NULL); + unsigned int i; + + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + struct Cookie *pv = NULL; + co = cookies->cookies[i]; + while(co) { + nx = co->next; + if(co->expires && co->expires < now) { + if(!pv) { + cookies->cookies[i] = co->next; + } + else { + pv->next = co->next; + } + cookies->numcookies--; + freecookie(co); + } + else { + pv = co; + } + co = nx; + } + } +} + +/* Make sure domain contains a dot or is localhost. */ +static bool bad_domain(const char *domain) +{ + return !strchr(domain, '.') && !strcasecompare(domain, "localhost"); +} + +/**************************************************************************** + * + * Curl_cookie_add() + * + * Add a single cookie line to the cookie keeping object. + * + * Be aware that sometimes we get an IP-only host name, and that might also be + * a numerical IPv6 address. + * + * Returns NULL on out of memory or invalid cookie. This is suboptimal, + * as they should be treated separately. + ***************************************************************************/ + +struct Cookie * +Curl_cookie_add(struct Curl_easy *data, + /* The 'data' pointer here may be NULL at times, and thus + must only be used very carefully for things that can deal + with data being NULL. Such as infof() and similar */ + + struct CookieInfo *c, + bool httpheader, /* TRUE if HTTP header-style line */ + bool noexpire, /* if TRUE, skip remove_expired() */ + char *lineptr, /* first character of the line */ + const char *domain, /* default domain */ + const char *path, /* full path used when this cookie is set, + used to get default path for the cookie + unless set */ + bool secure) /* TRUE if connection is over secure origin */ +{ + struct Cookie *clist; + struct Cookie *co; + struct Cookie *lastc = NULL; + time_t now = time(NULL); + bool replace_old = FALSE; + bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */ + size_t myhash; + +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)data; +#endif + + /* First, alloc and init a new struct for it */ + co = calloc(1, sizeof(struct Cookie)); + if(!co) + return NULL; /* bail out if we're this low on memory */ + + if(httpheader) { + /* This line was read off a HTTP-header */ + char name[MAX_NAME]; + char what[MAX_NAME]; + const char *ptr; + const char *semiptr; + + size_t linelength = strlen(lineptr); + if(linelength > MAX_COOKIE_LINE) { + /* discard overly long lines at once */ + free(co); + return NULL; + } + + semiptr = strchr(lineptr, ';'); /* first, find a semicolon */ + + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + + ptr = lineptr; + do { + /* we have a = pair or a stand-alone word here */ + name[0] = what[0] = 0; /* init the buffers */ + if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%" + MAX_NAME_TXT "[^;\r\n]", + name, what)) { + /* Use strstore() below to properly deal with received cookie + headers that have the same string property set more than once, + and then we use the last one. */ + const char *whatptr; + bool done = FALSE; + bool sep; + size_t len = strlen(what); + size_t nlen = strlen(name); + const char *endofn = &ptr[ nlen ]; + + if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) || + ((nlen + len) > MAX_NAME)) { + /* too long individual name or contents, or too long combination of + name + contents. Chrome and Firefox support 4095 or 4096 bytes + combo. */ + freecookie(co); + infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n", + nlen, len); + return NULL; + } + + /* name ends with a '=' ? */ + sep = (*endofn == '=')?TRUE:FALSE; + + if(nlen) { + endofn--; /* move to the last character */ + if(ISBLANK(*endofn)) { + /* skip trailing spaces in name */ + while(*endofn && ISBLANK(*endofn) && nlen) { + endofn--; + nlen--; + } + name[nlen] = 0; /* new end of name */ + } + } + + /* Strip off trailing whitespace from the 'what' */ + while(len && ISBLANK(what[len-1])) { + what[len-1] = 0; + len--; + } + + /* Skip leading whitespace from the 'what' */ + whatptr = what; + while(*whatptr && ISBLANK(*whatptr)) + whatptr++; + + /* + * Check if we have a reserved prefix set before anything else, as we + * otherwise have to test for the prefix in both the cookie name and + * "the rest". Prefixes must start with '__' and end with a '-', so + * only test for names where that can possibly be true. + */ + if(nlen > 3 && name[0] == '_' && name[1] == '_') { + if(strncasecompare("__Secure-", name, 9)) + co->prefix |= COOKIE_PREFIX__SECURE; + else if(strncasecompare("__Host-", name, 7)) + co->prefix |= COOKIE_PREFIX__HOST; + } + + if(!co->name) { + /* The very first name/value pair is the actual cookie name */ + if(!sep) { + /* Bad name/value pair. */ + badcookie = TRUE; + break; + } + co->name = strdup(name); + co->value = strdup(whatptr); + done = TRUE; + if(!co->name || !co->value) { + badcookie = TRUE; + break; + } + } + else if(!len) { + /* this was a "=" with no content, and we must allow + 'secure' and 'httponly' specified this weirdly */ + done = TRUE; + /* + * secure cookies are only allowed to be set when the connection is + * using a secure protocol, or when the cookie is being set by + * reading from file + */ + if(strcasecompare("secure", name)) { + if(secure || !c->running) { + co->secure = TRUE; + } + else { + badcookie = TRUE; + break; + } + } + else if(strcasecompare("httponly", name)) + co->httponly = TRUE; + else if(sep) + /* there was a '=' so we're not done parsing this field */ + done = FALSE; + } + if(done) + ; + else if(strcasecompare("path", name)) { + strstore(&co->path, whatptr); + if(!co->path) { + badcookie = TRUE; /* out of memory bad */ + break; + } + free(co->spath); /* if this is set again */ + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) { + badcookie = TRUE; /* out of memory bad */ + break; + } + } + else if(strcasecompare("domain", name)) { + bool is_ip; + + /* Now, we make sure that our host is within the given domain, + or the given domain is not valid and thus cannot be set. */ + + if('.' == whatptr[0]) + whatptr++; /* ignore preceding dot */ + +#ifndef USE_LIBPSL + /* + * Without PSL we don't know when the incoming cookie is set on a + * TLD or otherwise "protected" suffix. To reduce risk, we require a + * dot OR the exact host name being "localhost". + */ + if(bad_domain(whatptr)) + domain = ":"; +#endif + + is_ip = isip(domain ? domain : whatptr); + + if(!domain + || (is_ip && !strcmp(whatptr, domain)) + || (!is_ip && tailmatch(whatptr, domain))) { + strstore(&co->domain, whatptr); + if(!co->domain) { + badcookie = TRUE; + break; + } + if(!is_ip) + co->tailmatch = TRUE; /* we always do that if the domain name was + given */ + } + else { + /* we did not get a tailmatch and then the attempted set domain + is not a domain to which the current host belongs. Mark as + bad. */ + badcookie = TRUE; + infof(data, "skipped cookie with bad tailmatch domain: %s\n", + whatptr); + } + } + else if(strcasecompare("version", name)) { + strstore(&co->version, whatptr); + if(!co->version) { + badcookie = TRUE; + break; + } + } + else if(strcasecompare("max-age", name)) { + /* Defined in RFC2109: + + Optional. The Max-Age attribute defines the lifetime of the + cookie, in seconds. The delta-seconds value is a decimal non- + negative integer. After delta-seconds seconds elapse, the + client should discard the cookie. A value of zero means the + cookie should be discarded immediately. + + */ + strstore(&co->maxage, whatptr); + if(!co->maxage) { + badcookie = TRUE; + break; + } + } + else if(strcasecompare("expires", name)) { + strstore(&co->expirestr, whatptr); + if(!co->expirestr) { + badcookie = TRUE; + break; + } + } + /* + else this is the second (or more) name we don't know + about! */ + } + else { + /* this is an "illegal" = pair */ + } + + if(!semiptr || !*semiptr) { + /* we already know there are no more cookies */ + semiptr = NULL; + continue; + } + + ptr = semiptr + 1; + while(*ptr && ISBLANK(*ptr)) + ptr++; + semiptr = strchr(ptr, ';'); /* now, find the next semicolon */ + + if(!semiptr && *ptr) + /* There are no more semicolons, but there's a final name=value pair + coming up */ + semiptr = strchr(ptr, '\0'); + } while(semiptr); + + if(co->maxage) { + CURLofft offt; + offt = curlx_strtoofft((*co->maxage == '\"')? + &co->maxage[1]:&co->maxage[0], NULL, 10, + &co->expires); + if(offt == CURL_OFFT_FLOW) + /* overflow, used max value */ + co->expires = CURL_OFF_T_MAX; + else if(!offt) { + if(!co->expires) + /* already expired */ + co->expires = 1; + else if(CURL_OFF_T_MAX - now < co->expires) + /* would overflow */ + co->expires = CURL_OFF_T_MAX; + else + co->expires += now; + } + } + else if(co->expirestr) { + /* Note that if the date couldn't get parsed for whatever reason, + the cookie will be treated as a session cookie */ + co->expires = curl_getdate(co->expirestr, NULL); + + /* Session cookies have expires set to 0 so if we get that back + from the date parser let's add a second to make it a + non-session cookie */ + if(co->expires == 0) + co->expires = 1; + else if(co->expires < 0) + co->expires = 0; + } + + if(!badcookie && !co->domain) { + if(domain) { + /* no domain was given in the header line, set the default */ + co->domain = strdup(domain); + if(!co->domain) + badcookie = TRUE; + } + } + + if(!badcookie && !co->path && path) { + /* No path was given in the header line, set the default. + Note that the passed-in path to this function MAY have a '?' and + following part that MUST not be stored as part of the path. */ + char *queryp = strchr(path, '?'); + + /* queryp is where the interesting part of the path ends, so now we + want to the find the last */ + char *endslash; + if(!queryp) + endslash = strrchr(path, '/'); + else + endslash = memrchr(path, '/', (queryp - path)); + if(endslash) { + size_t pathlen = (endslash-path + 1); /* include end slash */ + co->path = malloc(pathlen + 1); /* one extra for the zero byte */ + if(co->path) { + memcpy(co->path, path, pathlen); + co->path[pathlen] = 0; /* zero terminate */ + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) + badcookie = TRUE; /* out of memory bad */ + } + else + badcookie = TRUE; + } + } + + if(badcookie || !co->name) { + /* we didn't get a cookie name or a bad one, + this is an illegal line, bail out */ + freecookie(co); + return NULL; + } + + } + else { + /* This line is NOT a HTTP header style line, we do offer support for + reading the odd netscape cookies-file format here */ + char *ptr; + char *firstptr; + char *tok_buf = NULL; + int fields; + + /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies + marked with httpOnly after the domain name are not accessible + from javascripts, but since curl does not operate at javascript + level, we include them anyway. In Firefox's cookie files, these + lines are preceded with #HttpOnly_ and then everything is + as usual, so we skip 10 characters of the line.. + */ + if(strncmp(lineptr, "#HttpOnly_", 10) == 0) { + lineptr += 10; + co->httponly = TRUE; + } + + if(lineptr[0]=='#') { + /* don't even try the comments */ + free(co); + return NULL; + } + /* strip off the possible end-of-line characters */ + ptr = strchr(lineptr, '\r'); + if(ptr) + *ptr = 0; /* clear it */ + ptr = strchr(lineptr, '\n'); + if(ptr) + *ptr = 0; /* clear it */ + + firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ + + /* Now loop through the fields and init the struct we already have + allocated */ + for(ptr = firstptr, fields = 0; ptr && !badcookie; + ptr = strtok_r(NULL, "\t", &tok_buf), fields++) { + switch(fields) { + case 0: + if(ptr[0]=='.') /* skip preceding dots */ + ptr++; + co->domain = strdup(ptr); + if(!co->domain) + badcookie = TRUE; + break; + case 1: + /* This field got its explanation on the 23rd of May 2001 by + Andrés García: + + flag: A TRUE/FALSE value indicating if all machines within a given + domain can access the variable. This value is set automatically by + the browser, depending on the value you set for the domain. + + As far as I can see, it is set to true when the cookie says + .domain.com and to false when the domain is complete www.domain.com + */ + co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE; + break; + case 2: + /* It turns out, that sometimes the file format allows the path + field to remain not filled in, we try to detect this and work + around it! Andrés García made us aware of this... */ + if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) { + /* only if the path doesn't look like a boolean option! */ + co->path = strdup(ptr); + if(!co->path) + badcookie = TRUE; + else { + co->spath = sanitize_cookie_path(co->path); + if(!co->spath) { + badcookie = TRUE; /* out of memory bad */ + } + } + break; + } + /* this doesn't look like a path, make one up! */ + co->path = strdup("/"); + if(!co->path) + badcookie = TRUE; + co->spath = strdup("/"); + if(!co->spath) + badcookie = TRUE; + fields++; /* add a field and fall down to secure */ + /* FALLTHROUGH */ + case 3: + co->secure = FALSE; + if(strcasecompare(ptr, "TRUE")) { + if(secure || c->running) + co->secure = TRUE; + else + badcookie = TRUE; + } + break; + case 4: + if(curlx_strtoofft(ptr, NULL, 10, &co->expires)) + badcookie = TRUE; + break; + case 5: + co->name = strdup(ptr); + if(!co->name) + badcookie = TRUE; + else { + /* For Netscape file format cookies we check prefix on the name */ + if(strncasecompare("__Secure-", co->name, 9)) + co->prefix |= COOKIE_PREFIX__SECURE; + else if(strncasecompare("__Host-", co->name, 7)) + co->prefix |= COOKIE_PREFIX__HOST; + } + break; + case 6: + co->value = strdup(ptr); + if(!co->value) + badcookie = TRUE; + break; + } + } + if(6 == fields) { + /* we got a cookie with blank contents, fix it */ + co->value = strdup(""); + if(!co->value) + badcookie = TRUE; + else + fields++; + } + + if(!badcookie && (7 != fields)) + /* we did not find the sufficient number of fields */ + badcookie = TRUE; + + if(badcookie) { + freecookie(co); + return NULL; + } + + } + + if(co->prefix & COOKIE_PREFIX__SECURE) { + /* The __Secure- prefix only requires that the cookie be set secure */ + if(!co->secure) { + freecookie(co); + return NULL; + } + } + if(co->prefix & COOKIE_PREFIX__HOST) { + /* + * The __Host- prefix requires the cookie to be secure, have a "/" path + * and not have a domain set. + */ + if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch) + ; + else { + freecookie(co); + return NULL; + } + } + + if(!c->running && /* read from a file */ + c->newsession && /* clean session cookies */ + !co->expires) { /* this is a session cookie since it doesn't expire! */ + freecookie(co); + return NULL; + } + + co->livecookie = c->running; + co->creationtime = ++c->lastct; + + /* now, we have parsed the incoming line, we must now check if this + supersedes an already existing cookie, which it may if the previous have + the same domain and path as this */ + + /* at first, remove expired cookies */ + if(!noexpire) + remove_expired(c); + +#ifdef USE_LIBPSL + /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */ + if(domain && co->domain && !isip(co->domain)) { + const psl_ctx_t *psl = Curl_psl_use(data); + int acceptable; + + if(psl) { + acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain); + Curl_psl_release(data); + } + else + acceptable = !bad_domain(domain); + + if(!acceptable) { + infof(data, "cookie '%s' dropped, domain '%s' must not " + "set cookies for '%s'\n", co->name, domain, co->domain); + freecookie(co); + return NULL; + } + } +#endif + + myhash = cookiehash(co->domain); + clist = c->cookies[myhash]; + replace_old = FALSE; + while(clist) { + if(strcasecompare(clist->name, co->name)) { + /* the names are identical */ + + if(clist->domain && co->domain) { + if(strcasecompare(clist->domain, co->domain) && + (clist->tailmatch == co->tailmatch)) + /* The domains are identical */ + replace_old = TRUE; + } + else if(!clist->domain && !co->domain) + replace_old = TRUE; + + if(replace_old) { + /* the domains were identical */ + + if(clist->spath && co->spath) { + if(clist->secure && !co->secure && !secure) { + size_t cllen; + const char *sep; + + /* + * A non-secure cookie may not overlay an existing secure cookie. + * For an existing cookie "a" with path "/login", refuse a new + * cookie "a" with for example path "/login/en", while the path + * "/loginhelper" is ok. + */ + + sep = strchr(clist->spath + 1, '/'); + + if(sep) + cllen = sep - clist->spath; + else + cllen = strlen(clist->spath); + + if(strncasecompare(clist->spath, co->spath, cllen)) { + freecookie(co); + return NULL; + } + } + else if(strcasecompare(clist->spath, co->spath)) + replace_old = TRUE; + else + replace_old = FALSE; + } + else if(!clist->spath && !co->spath) + replace_old = TRUE; + else + replace_old = FALSE; + + } + + if(replace_old && !co->livecookie && clist->livecookie) { + /* Both cookies matched fine, except that the already present + cookie is "live", which means it was set from a header, while + the new one isn't "live" and thus only read from a file. We let + live cookies stay alive */ + + /* Free the newcomer and get out of here! */ + freecookie(co); + return NULL; + } + + if(replace_old) { + co->next = clist->next; /* get the next-pointer first */ + + /* when replacing, creationtime is kept from old */ + co->creationtime = clist->creationtime; + + /* then free all the old pointers */ + free(clist->name); + free(clist->value); + free(clist->domain); + free(clist->path); + free(clist->spath); + free(clist->expirestr); + free(clist->version); + free(clist->maxage); + + *clist = *co; /* then store all the new data */ + + free(co); /* free the newly alloced memory */ + co = clist; /* point to the previous struct instead */ + + /* We have replaced a cookie, now skip the rest of the list but + make sure the 'lastc' pointer is properly set */ + do { + lastc = clist; + clist = clist->next; + } while(clist); + break; + } + } + lastc = clist; + clist = clist->next; + } + + if(c->running) + /* Only show this when NOT reading the cookies from a file */ + infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, " + "expire %" CURL_FORMAT_CURL_OFF_T "\n", + replace_old?"Replaced":"Added", co->name, co->value, + co->domain, co->path, co->expires); + + if(!replace_old) { + /* then make the last item point on this new one */ + if(lastc) + lastc->next = co; + else + c->cookies[myhash] = co; + c->numcookies++; /* one more cookie in the jar */ + } + + return co; +} + + +/***************************************************************************** + * + * Curl_cookie_init() + * + * Inits a cookie struct to read data from a local file. This is always + * called before any cookies are set. File may be NULL. + * + * If 'newsession' is TRUE, discard all "session cookies" on read from file. + * + * Returns NULL on out of memory. Invalid cookies are ignored. + ****************************************************************************/ +struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + const char *file, + struct CookieInfo *inc, + bool newsession) +{ + struct CookieInfo *c; + FILE *fp = NULL; + bool fromfile = TRUE; + char *line = NULL; + + if(NULL == inc) { + /* we didn't get a struct, create one */ + c = calloc(1, sizeof(struct CookieInfo)); + if(!c) + return NULL; /* failed to get memory */ + c->filename = strdup(file?file:"none"); /* copy the name just in case */ + if(!c->filename) + goto fail; /* failed to get memory */ + } + else { + /* we got an already existing one, use that */ + c = inc; + } + c->running = FALSE; /* this is not running, this is init */ + + if(file && !strcmp(file, "-")) { + fp = stdin; + fromfile = FALSE; + } + else if(file && !*file) { + /* points to a "" string */ + fp = NULL; + } + else + fp = file?fopen(file, FOPEN_READTEXT):NULL; + + c->newsession = newsession; /* new session? */ + + if(fp) { + char *lineptr; + bool headerline; + + line = malloc(MAX_COOKIE_LINE); + if(!line) + goto fail; + while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) { + if(checkprefix("Set-Cookie:", line)) { + /* This is a cookie line, get it! */ + lineptr = &line[11]; + headerline = TRUE; + } + else { + lineptr = line; + headerline = FALSE; + } + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + + Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE); + } + free(line); /* free the line buffer */ + remove_expired(c); /* run this once, not on every cookie */ + + if(fromfile) + fclose(fp); + } + + c->running = TRUE; /* now, we're running */ + + return c; + +fail: + free(line); + if(!inc) + /* Only clean up if we allocated it here, as the original could still be in + * use by a share handle */ + Curl_cookie_cleanup(c); + if(fromfile && fp) + fclose(fp); + return NULL; /* out of memory */ +} + +/* sort this so that the longest path gets before the shorter path */ +static int cookie_sort(const void *p1, const void *p2) +{ + struct Cookie *c1 = *(struct Cookie **)p1; + struct Cookie *c2 = *(struct Cookie **)p2; + size_t l1, l2; + + /* 1 - compare cookie path lengths */ + l1 = c1->path ? strlen(c1->path) : 0; + l2 = c2->path ? strlen(c2->path) : 0; + + if(l1 != l2) + return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */ + + /* 2 - compare cookie domain lengths */ + l1 = c1->domain ? strlen(c1->domain) : 0; + l2 = c2->domain ? strlen(c2->domain) : 0; + + if(l1 != l2) + return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */ + + /* 3 - compare cookie name lengths */ + l1 = c1->name ? strlen(c1->name) : 0; + l2 = c2->name ? strlen(c2->name) : 0; + + if(l1 != l2) + return (l2 > l1) ? 1 : -1; + + /* 4 - compare cookie creation time */ + return (c2->creationtime > c1->creationtime) ? 1 : -1; +} + +/* sort cookies only according to creation time */ +static int cookie_sort_ct(const void *p1, const void *p2) +{ + struct Cookie *c1 = *(struct Cookie **)p1; + struct Cookie *c2 = *(struct Cookie **)p2; + + return (c2->creationtime > c1->creationtime) ? 1 : -1; +} + +#define CLONE(field) \ + do { \ + if(src->field) { \ + d->field = strdup(src->field); \ + if(!d->field) \ + goto fail; \ + } \ + } while(0) + +static struct Cookie *dup_cookie(struct Cookie *src) +{ + struct Cookie *d = calloc(sizeof(struct Cookie), 1); + if(d) { + CLONE(expirestr); + CLONE(domain); + CLONE(path); + CLONE(spath); + CLONE(name); + CLONE(value); + CLONE(maxage); + CLONE(version); + d->expires = src->expires; + d->tailmatch = src->tailmatch; + d->secure = src->secure; + d->livecookie = src->livecookie; + d->httponly = src->httponly; + d->creationtime = src->creationtime; + } + return d; + + fail: + freecookie(d); + return NULL; +} + +/***************************************************************************** + * + * Curl_cookie_getlist() + * + * For a given host and path, return a linked list of cookies that the + * client should send to the server if used now. The secure boolean informs + * the cookie if a secure connection is achieved or not. + * + * It shall only return cookies that haven't expired. + * + ****************************************************************************/ + +struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + const char *host, const char *path, + bool secure) +{ + struct Cookie *newco; + struct Cookie *co; + struct Cookie *mainco = NULL; + size_t matches = 0; + bool is_ip; + const size_t myhash = cookiehash(host); + + if(!c || !c->cookies[myhash]) + return NULL; /* no cookie struct or no cookies in the struct */ + + /* at first, remove expired cookies */ + remove_expired(c); + + /* check if host is an IP(v4|v6) address */ + is_ip = isip(host); + + co = c->cookies[myhash]; + + while(co) { + /* if the cookie requires we're secure we must only continue if we are! */ + if(co->secure?secure:TRUE) { + + /* now check if the domain is correct */ + if(!co->domain || + (co->tailmatch && !is_ip && tailmatch(co->domain, host)) || + ((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) { + /* the right part of the host matches the domain stuff in the + cookie data */ + + /* now check the left part of the path with the cookies path + requirement */ + if(!co->spath || pathmatch(co->spath, path) ) { + + /* and now, we know this is a match and we should create an + entry for the return-linked-list */ + + newco = dup_cookie(co); + if(newco) { + /* then modify our next */ + newco->next = mainco; + + /* point the main to us */ + mainco = newco; + + matches++; + } + else + goto fail; + } + } + } + co = co->next; + } + + if(matches) { + /* Now we need to make sure that if there is a name appearing more than + once, the longest specified path version comes first. To make this + the swiftest way, we just sort them all based on path length. */ + struct Cookie **array; + size_t i; + + /* alloc an array and store all cookie pointers */ + array = malloc(sizeof(struct Cookie *) * matches); + if(!array) + goto fail; + + co = mainco; + + for(i = 0; co; co = co->next) + array[i++] = co; + + /* now sort the cookie pointers in path length order */ + qsort(array, matches, sizeof(struct Cookie *), cookie_sort); + + /* remake the linked list order according to the new order */ + + mainco = array[0]; /* start here */ + for(i = 0; inext = array[i + 1]; + array[matches-1]->next = NULL; /* terminate the list */ + + free(array); /* remove the temporary data again */ + } + + return mainco; /* return the new list */ + +fail: + /* failure, clear up the allocated chain and return NULL */ + Curl_cookie_freelist(mainco); + return NULL; +} + +/***************************************************************************** + * + * Curl_cookie_clearall() + * + * Clear all existing cookies and reset the counter. + * + ****************************************************************************/ +void Curl_cookie_clearall(struct CookieInfo *cookies) +{ + if(cookies) { + unsigned int i; + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + Curl_cookie_freelist(cookies->cookies[i]); + cookies->cookies[i] = NULL; + } + cookies->numcookies = 0; + } +} + +/***************************************************************************** + * + * Curl_cookie_freelist() + * + * Free a list of cookies previously returned by Curl_cookie_getlist(); + * + ****************************************************************************/ + +void Curl_cookie_freelist(struct Cookie *co) +{ + struct Cookie *next; + while(co) { + next = co->next; + freecookie(co); + co = next; + } +} + + +/***************************************************************************** + * + * Curl_cookie_clearsess() + * + * Free all session cookies in the cookies list. + * + ****************************************************************************/ +void Curl_cookie_clearsess(struct CookieInfo *cookies) +{ + struct Cookie *first, *curr, *next, *prev = NULL; + unsigned int i; + + if(!cookies) + return; + + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + if(!cookies->cookies[i]) + continue; + + first = curr = prev = cookies->cookies[i]; + + for(; curr; curr = next) { + next = curr->next; + if(!curr->expires) { + if(first == curr) + first = next; + + if(prev == curr) + prev = next; + else + prev->next = next; + + freecookie(curr); + cookies->numcookies--; + } + else + prev = curr; + } + + cookies->cookies[i] = first; + } +} + + +/***************************************************************************** + * + * Curl_cookie_cleanup() + * + * Free a "cookie object" previous created with Curl_cookie_init(). + * + ****************************************************************************/ +void Curl_cookie_cleanup(struct CookieInfo *c) +{ + if(c) { + unsigned int i; + free(c->filename); + for(i = 0; i < COOKIE_HASH_SIZE; i++) + Curl_cookie_freelist(c->cookies[i]); + free(c); /* free the base struct as well */ + } +} + +/* get_netscape_format() + * + * Formats a string for Netscape output file, w/o a newline at the end. + * + * Function returns a char * to a formatted line. Has to be free()d +*/ +static char *get_netscape_format(const struct Cookie *co) +{ + return aprintf( + "%s" /* httponly preamble */ + "%s%s\t" /* domain */ + "%s\t" /* tailmatch */ + "%s\t" /* path */ + "%s\t" /* secure */ + "%" CURL_FORMAT_CURL_OFF_T "\t" /* expires */ + "%s\t" /* name */ + "%s", /* value */ + co->httponly?"#HttpOnly_":"", + /* Make sure all domains are prefixed with a dot if they allow + tailmatching. This is Mozilla-style. */ + (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"", + co->domain?co->domain:"unknown", + co->tailmatch?"TRUE":"FALSE", + co->path?co->path:"/", + co->secure?"TRUE":"FALSE", + co->expires, + co->name, + co->value?co->value:""); +} + +/* + * cookie_output() + * + * Writes all internally known cookies to the specified file. Specify + * "-" as file name to write to stdout. + * + * The function returns non-zero on write failure. + */ +static int cookie_output(struct CookieInfo *c, const char *dumphere) +{ + struct Cookie *co; + FILE *out; + bool use_stdout = FALSE; + + if(!c) + /* no cookie engine alive */ + return 0; + + /* at first, remove expired cookies */ + remove_expired(c); + + if(!strcmp("-", dumphere)) { + /* use stdout */ + out = stdout; + use_stdout = TRUE; + } + else { + out = fopen(dumphere, FOPEN_WRITETEXT); + if(!out) { + return 1; /* failure */ + } + } + + fputs("# Netscape HTTP Cookie File\n" + "# https://curl.haxx.se/docs/http-cookies.html\n" + "# This file was generated by libcurl! Edit at your own risk.\n\n", + out); + + if(c->numcookies) { + unsigned int i; + unsigned int j; + struct Cookie **array; + + array = malloc(sizeof(struct Cookie *) * c->numcookies); + if(!array) { + if(!use_stdout) + fclose(out); + return 1; + } + + j = 0; + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + for(co = c->cookies[i]; co; co = co->next) { + if(!co->domain) + continue; + array[j++] = co; + } + } + + qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct); + + for(i = 0; i < j; i++) { + char *format_ptr = get_netscape_format(array[i]); + if(format_ptr == NULL) { + fprintf(out, "#\n# Fatal libcurl error\n"); + free(array); + if(!use_stdout) + fclose(out); + return 1; + } + fprintf(out, "%s\n", format_ptr); + free(format_ptr); + } + + free(array); + } + if(!use_stdout) + fclose(out); + + return 0; +} + +static struct curl_slist *cookie_list(struct Curl_easy *data) +{ + struct curl_slist *list = NULL; + struct curl_slist *beg; + struct Cookie *c; + char *line; + unsigned int i; + + if((data->cookies == NULL) || + (data->cookies->numcookies == 0)) + return NULL; + + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + for(c = data->cookies->cookies[i]; c; c = c->next) { + if(!c->domain) + continue; + line = get_netscape_format(c); + if(!line) { + curl_slist_free_all(list); + return NULL; + } + beg = Curl_slist_append_nodup(list, line); + if(!beg) { + free(line); + curl_slist_free_all(list); + return NULL; + } + list = beg; + } + } + + return list; +} + +struct curl_slist *Curl_cookie_list(struct Curl_easy *data) +{ + struct curl_slist *list; + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + list = cookie_list(data); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + return list; +} + +void Curl_flush_cookies(struct Curl_easy *data, int cleanup) +{ + if(data->set.str[STRING_COOKIEJAR]) { + if(data->change.cookielist) { + /* If there is a list of cookie files to read, do it first so that + we have all the told files read before we write the new jar. + Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */ + Curl_cookie_loadfiles(data); + } + + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + + /* if we have a destination file for all the cookies to get dumped to */ + if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR])) + infof(data, "WARNING: failed to save cookies in %s\n", + data->set.str[STRING_COOKIEJAR]); + } + else { + if(cleanup && data->change.cookielist) { + /* since nothing is written, we can just free the list of cookie file + names */ + curl_slist_free_all(data->change.cookielist); /* clean up list */ + data->change.cookielist = NULL; + } + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + } + + if(cleanup && (!data->share || (data->cookies != data->share->cookies))) { + Curl_cookie_cleanup(data->cookies); + } + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); +} + +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */ diff --git a/libcurl/lib/cookie.h b/libcurl/lib/cookie.h new file mode 100644 index 0000000..b2730cf --- /dev/null +++ b/libcurl/lib/cookie.h @@ -0,0 +1,120 @@ +#ifndef HEADER_CURL_COOKIE_H +#define HEADER_CURL_COOKIE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#include + +struct Cookie { + struct Cookie *next; /* next in the chain */ + char *name; /* = value */ + char *value; /* name = */ + char *path; /* path = which is in Set-Cookie: */ + char *spath; /* sanitized cookie path */ + char *domain; /* domain = */ + curl_off_t expires; /* expires = */ + char *expirestr; /* the plain text version */ + bool tailmatch; /* whether we do tail-matching of the domain name */ + + /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ + char *version; /* Version = */ + char *maxage; /* Max-Age = */ + + bool secure; /* whether the 'secure' keyword was used */ + bool livecookie; /* updated from a server, not a stored file */ + bool httponly; /* true if the httponly directive is present */ + int creationtime; /* time when the cookie was written */ + unsigned char prefix; /* bitmap fields indicating which prefix are set */ +}; + +/* + * Available cookie prefixes, as defined in + * draft-ietf-httpbis-rfc6265bis-02 + */ +#define COOKIE_PREFIX__SECURE (1<<0) +#define COOKIE_PREFIX__HOST (1<<1) + +#define COOKIE_HASH_SIZE 256 + +struct CookieInfo { + /* linked list of cookies we know of */ + struct Cookie *cookies[COOKIE_HASH_SIZE]; + + char *filename; /* file we read from/write to */ + bool running; /* state info, for cookie adding information */ + long numcookies; /* number of cookies in the "jar" */ + bool newsession; /* new session, discard session cookies on load */ + int lastct; /* last creation-time used in the jar */ +}; + +/* This is the maximum line length we accept for a cookie line. RFC 2109 + section 6.3 says: + + "at least 4096 bytes per cookie (as measured by the size of the characters + that comprise the cookie non-terminal in the syntax description of the + Set-Cookie header)" + + We allow max 5000 bytes cookie header. Max 4095 bytes length per cookie + name and value. Name + value may not exceed 4096 bytes. + +*/ +#define MAX_COOKIE_LINE 5000 + +/* This is the maximum length of a cookie name or content we deal with: */ +#define MAX_NAME 4096 +#define MAX_NAME_TXT "4095" + +struct Curl_easy; +/* + * Add a cookie to the internal list of cookies. The domain and path arguments + * are only used if the header boolean is TRUE. + */ + +struct Cookie *Curl_cookie_add(struct Curl_easy *data, + struct CookieInfo *, bool header, bool noexpiry, + char *lineptr, + const char *domain, const char *path, + bool secure); + +struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, + const char *, bool); +void Curl_cookie_freelist(struct Cookie *cookies); +void Curl_cookie_clearall(struct CookieInfo *cookies); +void Curl_cookie_clearsess(struct CookieInfo *cookies); + +#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) +#define Curl_cookie_list(x) NULL +#define Curl_cookie_loadfiles(x) Curl_nop_stmt +#define Curl_cookie_init(x,y,z,w) NULL +#define Curl_cookie_cleanup(x) Curl_nop_stmt +#define Curl_flush_cookies(x,y) Curl_nop_stmt +#else +void Curl_flush_cookies(struct Curl_easy *data, int cleanup); +void Curl_cookie_cleanup(struct CookieInfo *); +struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + const char *, struct CookieInfo *, bool); +struct curl_slist *Curl_cookie_list(struct Curl_easy *data); +void Curl_cookie_loadfiles(struct Curl_easy *data); +#endif + +#endif /* HEADER_CURL_COOKIE_H */ diff --git a/libcurl/lib/curl_addrinfo.c b/libcurl/lib/curl_addrinfo.c new file mode 100644 index 0000000..16c4779 --- /dev/null +++ b/libcurl/lib/curl_addrinfo.c @@ -0,0 +1,624 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETINET_IN6_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_SYS_UN_H +# include +#endif + +#ifdef __VMS +# include +# include +#endif + +#if defined(NETWARE) && defined(__NOVELL_LIBC__) +# undef in_addr_t +# define in_addr_t unsigned long +#endif + +#if defined(WIN32) && defined(USE_UNIX_SOCKETS) +#include +#endif + +#include + +#include "curl_addrinfo.h" +#include "inet_pton.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_freeaddrinfo() + * + * This is used to free a linked list of Curl_addrinfo structs along + * with all its associated allocated storage. This function should be + * called once for each successful call to Curl_getaddrinfo_ex() or to + * any function call which actually allocates a Curl_addrinfo struct. + */ + +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ + defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) + /* workaround icc 9.1 optimizer issue */ +# define vqualifier volatile +#else +# define vqualifier +#endif + +void +Curl_freeaddrinfo(Curl_addrinfo *cahead) +{ + Curl_addrinfo *vqualifier canext; + Curl_addrinfo *ca; + + for(ca = cahead; ca != NULL; ca = canext) { + free(ca->ai_addr); + free(ca->ai_canonname); + canext = ca->ai_next; + + free(ca); + } +} + + +#ifdef HAVE_GETADDRINFO +/* + * Curl_getaddrinfo_ex() + * + * This is a wrapper function around system's getaddrinfo(), with + * the only difference that instead of returning a linked list of + * addrinfo structs this one returns a linked list of Curl_addrinfo + * ones. The memory allocated by this function *MUST* be free'd with + * Curl_freeaddrinfo(). For each successful call to this function + * there must be an associated call later to Curl_freeaddrinfo(). + * + * There should be no single call to system's getaddrinfo() in the + * whole library, any such call should be 'routed' through this one. + */ + +int +Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + Curl_addrinfo **result) +{ + const struct addrinfo *ai; + struct addrinfo *aihead; + Curl_addrinfo *cafirst = NULL; + Curl_addrinfo *calast = NULL; + Curl_addrinfo *ca; + size_t ss_size; + int error; + + *result = NULL; /* assume failure */ + + error = getaddrinfo(nodename, servname, hints, &aihead); + if(error) + return error; + + /* traverse the addrinfo list */ + + for(ai = aihead; ai != NULL; ai = ai->ai_next) { + + /* ignore elements with unsupported address family, */ + /* settle family-specific sockaddr structure size. */ + if(ai->ai_family == AF_INET) + ss_size = sizeof(struct sockaddr_in); +#ifdef ENABLE_IPV6 + else if(ai->ai_family == AF_INET6) + ss_size = sizeof(struct sockaddr_in6); +#endif + else + continue; + + /* ignore elements without required address info */ + if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0)) + continue; + + /* ignore elements with bogus address size */ + if((size_t)ai->ai_addrlen < ss_size) + continue; + + ca = malloc(sizeof(Curl_addrinfo)); + if(!ca) { + error = EAI_MEMORY; + break; + } + + /* copy each structure member individually, member ordering, */ + /* size, or padding might be different for each platform. */ + + ca->ai_flags = ai->ai_flags; + ca->ai_family = ai->ai_family; + ca->ai_socktype = ai->ai_socktype; + ca->ai_protocol = ai->ai_protocol; + ca->ai_addrlen = (curl_socklen_t)ss_size; + ca->ai_addr = NULL; + ca->ai_canonname = NULL; + ca->ai_next = NULL; + + ca->ai_addr = malloc(ss_size); + if(!ca->ai_addr) { + error = EAI_MEMORY; + free(ca); + break; + } + memcpy(ca->ai_addr, ai->ai_addr, ss_size); + + if(ai->ai_canonname != NULL) { + ca->ai_canonname = strdup(ai->ai_canonname); + if(!ca->ai_canonname) { + error = EAI_MEMORY; + free(ca->ai_addr); + free(ca); + break; + } + } + + /* if the return list is empty, this becomes the first element */ + if(!cafirst) + cafirst = ca; + + /* add this element last in the return list */ + if(calast) + calast->ai_next = ca; + calast = ca; + + } + + /* destroy the addrinfo list */ + if(aihead) + freeaddrinfo(aihead); + + /* if we failed, also destroy the Curl_addrinfo list */ + if(error) { + Curl_freeaddrinfo(cafirst); + cafirst = NULL; + } + else if(!cafirst) { +#ifdef EAI_NONAME + /* rfc3493 conformant */ + error = EAI_NONAME; +#else + /* rfc3493 obsoleted */ + error = EAI_NODATA; +#endif +#ifdef USE_WINSOCK + SET_SOCKERRNO(error); +#endif + } + + *result = cafirst; + + /* This is not a CURLcode */ + return error; +} +#endif /* HAVE_GETADDRINFO */ + + +/* + * Curl_he2ai() + * + * This function returns a pointer to the first element of a newly allocated + * Curl_addrinfo struct linked list filled with the data of a given hostent. + * Curl_addrinfo is meant to work like the addrinfo struct does for a IPv6 + * stack, but usable also for IPv4, all hosts and environments. + * + * The memory allocated by this function *MUST* be free'd later on calling + * Curl_freeaddrinfo(). For each successful call to this function there + * must be an associated call later to Curl_freeaddrinfo(). + * + * Curl_addrinfo defined in "lib/curl_addrinfo.h" + * + * struct Curl_addrinfo { + * int ai_flags; + * int ai_family; + * int ai_socktype; + * int ai_protocol; + * curl_socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo * + * char *ai_canonname; + * struct sockaddr *ai_addr; + * struct Curl_addrinfo *ai_next; + * }; + * typedef struct Curl_addrinfo Curl_addrinfo; + * + * hostent defined in + * + * struct hostent { + * char *h_name; + * char **h_aliases; + * int h_addrtype; + * int h_length; + * char **h_addr_list; + * }; + * + * for backward compatibility: + * + * #define h_addr h_addr_list[0] + */ + +Curl_addrinfo * +Curl_he2ai(const struct hostent *he, int port) +{ + Curl_addrinfo *ai; + Curl_addrinfo *prevai = NULL; + Curl_addrinfo *firstai = NULL; + struct sockaddr_in *addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *addr6; +#endif + CURLcode result = CURLE_OK; + int i; + char *curr; + + if(!he) + /* no input == no output! */ + return NULL; + + DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL)); + + for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) { + + size_t ss_size; +#ifdef ENABLE_IPV6 + if(he->h_addrtype == AF_INET6) + ss_size = sizeof(struct sockaddr_in6); + else +#endif + ss_size = sizeof(struct sockaddr_in); + + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) { + result = CURLE_OUT_OF_MEMORY; + break; + } + ai->ai_canonname = strdup(he->h_name); + if(!ai->ai_canonname) { + result = CURLE_OUT_OF_MEMORY; + free(ai); + break; + } + ai->ai_addr = calloc(1, ss_size); + if(!ai->ai_addr) { + result = CURLE_OUT_OF_MEMORY; + free(ai->ai_canonname); + free(ai); + break; + } + + if(!firstai) + /* store the pointer we want to return from this function */ + firstai = ai; + + if(prevai) + /* make the previous entry point to this */ + prevai->ai_next = ai; + + ai->ai_family = he->h_addrtype; + + /* we return all names as STREAM, so when using this address for TFTP + the type must be ignored and conn->socktype be used instead! */ + ai->ai_socktype = SOCK_STREAM; + + ai->ai_addrlen = (curl_socklen_t)ss_size; + + /* leave the rest of the struct filled with zero */ + + switch(ai->ai_family) { + case AF_INET: + addr = (void *)ai->ai_addr; /* storage area for this info */ + + memcpy(&addr->sin_addr, curr, sizeof(struct in_addr)); + addr->sin_family = (CURL_SA_FAMILY_T)(he->h_addrtype); + addr->sin_port = htons((unsigned short)port); + break; + +#ifdef ENABLE_IPV6 + case AF_INET6: + addr6 = (void *)ai->ai_addr; /* storage area for this info */ + + memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr)); + addr6->sin6_family = (CURL_SA_FAMILY_T)(he->h_addrtype); + addr6->sin6_port = htons((unsigned short)port); + break; +#endif + } + + prevai = ai; + } + + if(result) { + Curl_freeaddrinfo(firstai); + firstai = NULL; + } + + return firstai; +} + + +struct namebuff { + struct hostent hostentry; + union { + struct in_addr ina4; +#ifdef ENABLE_IPV6 + struct in6_addr ina6; +#endif + } addrentry; + char *h_addr_list[2]; +}; + + +/* + * Curl_ip2addr() + * + * This function takes an internet address, in binary form, as input parameter + * along with its address family and the string version of the address, and it + * returns a Curl_addrinfo chain filled in correctly with information for the + * given address/host + */ + +Curl_addrinfo * +Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) +{ + Curl_addrinfo *ai; + +#if defined(__VMS) && \ + defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) +#pragma pointer_size save +#pragma pointer_size short +#pragma message disable PTRMISMATCH +#endif + + struct hostent *h; + struct namebuff *buf; + char *addrentry; + char *hoststr; + size_t addrsize; + + DEBUGASSERT(inaddr && hostname); + + buf = malloc(sizeof(struct namebuff)); + if(!buf) + return NULL; + + hoststr = strdup(hostname); + if(!hoststr) { + free(buf); + return NULL; + } + + switch(af) { + case AF_INET: + addrsize = sizeof(struct in_addr); + addrentry = (void *)&buf->addrentry.ina4; + memcpy(addrentry, inaddr, sizeof(struct in_addr)); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + addrsize = sizeof(struct in6_addr); + addrentry = (void *)&buf->addrentry.ina6; + memcpy(addrentry, inaddr, sizeof(struct in6_addr)); + break; +#endif + default: + free(hoststr); + free(buf); + return NULL; + } + + h = &buf->hostentry; + h->h_name = hoststr; + h->h_aliases = NULL; + h->h_addrtype = (short)af; + h->h_length = (short)addrsize; + h->h_addr_list = &buf->h_addr_list[0]; + h->h_addr_list[0] = addrentry; + h->h_addr_list[1] = NULL; /* terminate list of entries */ + +#if defined(__VMS) && \ + defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) +#pragma pointer_size restore +#pragma message enable PTRMISMATCH +#endif + + ai = Curl_he2ai(h, port); + + free(hoststr); + free(buf); + + return ai; +} + +/* + * Given an IPv4 or IPv6 dotted string address, this converts it to a proper + * allocated Curl_addrinfo struct and returns it. + */ +Curl_addrinfo *Curl_str2addr(char *address, int port) +{ + struct in_addr in; + if(Curl_inet_pton(AF_INET, address, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, address, port); +#ifdef ENABLE_IPV6 + { + struct in6_addr in6; + if(Curl_inet_pton(AF_INET6, address, &in6) > 0) + /* This is a dotted IPv6 address ::1-style */ + return Curl_ip2addr(AF_INET6, &in6, address, port); + } +#endif + return NULL; /* bad input format */ +} + +#ifdef USE_UNIX_SOCKETS +/** + * Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo + * struct initialized with this path. + * Set '*longpath' to TRUE if the error is a too long path. + */ +Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract) +{ + Curl_addrinfo *ai; + struct sockaddr_un *sa_un; + size_t path_len; + + *longpath = FALSE; + + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) + return NULL; + ai->ai_addr = calloc(1, sizeof(struct sockaddr_un)); + if(!ai->ai_addr) { + free(ai); + return NULL; + } + + sa_un = (void *) ai->ai_addr; + sa_un->sun_family = AF_UNIX; + + /* sun_path must be able to store the NUL-terminated path */ + path_len = strlen(path) + 1; + if(path_len > sizeof(sa_un->sun_path)) { + free(ai->ai_addr); + free(ai); + *longpath = TRUE; + return NULL; + } + + ai->ai_family = AF_UNIX; + ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */ + ai->ai_addrlen = (curl_socklen_t) + ((offsetof(struct sockaddr_un, sun_path) + path_len) & 0x7FFFFFFF); + + /* Abstract Unix domain socket have NULL prefix instead of suffix */ + if(abstract) + memcpy(sa_un->sun_path + 1, path, path_len - 1); + else + memcpy(sa_un->sun_path, path, path_len); /* copy NUL byte */ + + return ai; +} +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ + defined(HAVE_FREEADDRINFO) +/* + * curl_dbg_freeaddrinfo() + * + * This is strictly for memory tracing and are using the same style as the + * family otherwise present in memdebug.c. I put these ones here since they + * require a bunch of structs I didn't want to include in memdebug.c + */ + +void +curl_dbg_freeaddrinfo(struct addrinfo *freethis, + int line, const char *source) +{ + curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n", + source, line, (void *)freethis); +#ifdef USE_LWIPSOCK + lwip_freeaddrinfo(freethis); +#else + (freeaddrinfo)(freethis); +#endif +} +#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */ + + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) +/* + * curl_dbg_getaddrinfo() + * + * This is strictly for memory tracing and are using the same style as the + * family otherwise present in memdebug.c. I put these ones here since they + * require a bunch of structs I didn't want to include in memdebug.c + */ + +int +curl_dbg_getaddrinfo(const char *hostname, + const char *service, + const struct addrinfo *hints, + struct addrinfo **result, + int line, const char *source) +{ +#ifdef USE_LWIPSOCK + int res = lwip_getaddrinfo(hostname, service, hints, result); +#else + int res = (getaddrinfo)(hostname, service, hints, result); +#endif + if(0 == res) + /* success */ + curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n", + source, line, (void *)*result); + else + curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n", + source, line); + return res; +} +#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */ + +#if defined(HAVE_GETADDRINFO) && defined(USE_RESOLVE_ON_IPS) +/* + * Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X + * 10.11.5. + */ +void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port) +{ + Curl_addrinfo *ca; + struct sockaddr_in *addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *addr6; +#endif + for(ca = addrinfo; ca != NULL; ca = ca->ai_next) { + switch(ca->ai_family) { + case AF_INET: + addr = (void *)ca->ai_addr; /* storage area for this info */ + addr->sin_port = htons((unsigned short)port); + break; + +#ifdef ENABLE_IPV6 + case AF_INET6: + addr6 = (void *)ca->ai_addr; /* storage area for this info */ + addr6->sin6_port = htons((unsigned short)port); + break; +#endif + } + } +} +#endif diff --git a/libcurl/lib/curl_addrinfo.h b/libcurl/lib/curl_addrinfo.h new file mode 100644 index 0000000..c174504 --- /dev/null +++ b/libcurl/lib/curl_addrinfo.h @@ -0,0 +1,115 @@ +#ifndef HEADER_CURL_ADDRINFO_H +#define HEADER_CURL_ADDRINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#ifdef __VMS +# include +# include +# include +#endif + +// ADDED FOR XBOX + struct hostent { + char *h_name; + char **h_aliases; + int h_addrtype; + int h_length; + char **h_addr_list; + }; + +/* + * Curl_addrinfo is our internal struct definition that we use to allow + * consistent internal handling of this data. We use this even when the + * system provides an addrinfo structure definition. And we use this for + * all sorts of IPv4 and IPV6 builds. + */ + +struct Curl_addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + curl_socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */ + char *ai_canonname; + struct sockaddr *ai_addr; + struct Curl_addrinfo *ai_next; +}; +typedef struct Curl_addrinfo Curl_addrinfo; + +void +Curl_freeaddrinfo(Curl_addrinfo *cahead); + +#ifdef HAVE_GETADDRINFO +int +Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + Curl_addrinfo **result); +#endif + +Curl_addrinfo * +Curl_he2ai(const struct hostent *he, int port); + +Curl_addrinfo * +Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); + +Curl_addrinfo *Curl_str2addr(char *dotted, int port); + +#ifdef USE_UNIX_SOCKETS +Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract); +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ + defined(HAVE_FREEADDRINFO) +void +curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source); +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) +int +curl_dbg_getaddrinfo(const char *hostname, const char *service, + const struct addrinfo *hints, struct addrinfo **result, + int line, const char *source); +#endif + +#ifdef HAVE_GETADDRINFO +#ifdef USE_RESOLVE_ON_IPS +void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port); +#else +#define Curl_addrinfo_set_port(x,y) +#endif +#endif + +#endif /* HEADER_CURL_ADDRINFO_H */ diff --git a/libcurl/lib/curl_base64.h b/libcurl/lib/curl_base64.h new file mode 100644 index 0000000..7e9fc26 --- /dev/null +++ b/libcurl/lib/curl_base64.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_BASE64_H +#define HEADER_CURL_BASE64_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURLcode Curl_base64_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen); +CURLcode Curl_base64url_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen); + +CURLcode Curl_base64_decode(const char *src, + unsigned char **outptr, size_t *outlen); + +#endif /* HEADER_CURL_BASE64_H */ diff --git a/libcurl/lib/curl_config.h.cmake b/libcurl/lib/curl_config.h.cmake new file mode 100644 index 0000000..5458cba --- /dev/null +++ b/libcurl/lib/curl_config.h.cmake @@ -0,0 +1,1026 @@ +/* lib/curl_config.h.in. Generated somehow by cmake. */ + +/* when building libcurl itself */ +#cmakedefine BUILDING_LIBCURL 1 + +/* Location of default ca bundle */ +#cmakedefine CURL_CA_BUNDLE "${CURL_CA_BUNDLE}" + +/* define "1" to use built-in ca store of TLS backend */ +#cmakedefine CURL_CA_FALLBACK 1 + +/* Location of default ca path */ +#cmakedefine CURL_CA_PATH "${CURL_CA_PATH}" + +/* to disable cookies support */ +#cmakedefine CURL_DISABLE_COOKIES 1 + +/* to disable cryptographic authentication */ +#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1 + +/* to disable DICT */ +#cmakedefine CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#cmakedefine CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#cmakedefine CURL_DISABLE_FTP 1 + +/* to disable GOPHER */ +#cmakedefine CURL_DISABLE_GOPHER 1 + +/* to disable IMAP */ +#cmakedefine CURL_DISABLE_IMAP 1 + +/* to disable HTTP */ +#cmakedefine CURL_DISABLE_HTTP 1 + +/* to disable LDAP */ +#cmakedefine CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#cmakedefine CURL_DISABLE_LDAPS 1 + +/* to disable POP3 */ +#cmakedefine CURL_DISABLE_POP3 1 + +/* to disable proxies */ +#cmakedefine CURL_DISABLE_PROXY 1 + +/* to disable RTSP */ +#cmakedefine CURL_DISABLE_RTSP 1 + +/* to disable SMB */ +#cmakedefine CURL_DISABLE_SMB 1 + +/* to disable SMTP */ +#cmakedefine CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +#cmakedefine CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#cmakedefine CURL_DISABLE_TFTP 1 + +/* to disable verbose strings */ +#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1 + +/* to make a symbol visible */ +#cmakedefine CURL_EXTERN_SYMBOL ${CURL_EXTERN_SYMBOL} +/* Ensure using CURL_EXTERN_SYMBOL is possible */ +#ifndef CURL_EXTERN_SYMBOL +#define CURL_EXTERN_SYMBOL +#endif + +/* Use Windows LDAP implementation */ +#cmakedefine USE_WIN32_LDAP 1 + +/* when not building a shared library */ +#cmakedefine CURL_STATICLIB 1 + +/* your Entropy Gathering Daemon socket pathname */ +#cmakedefine EGD_SOCKET ${EGD_SOCKET} + +/* Define if you want to enable IPv6 support */ +#cmakedefine ENABLE_IPV6 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1} + +/* Define to the type of arg 1 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1} + +/* Define to the type of arg 2 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2} + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46} + +/* Define to the type of arg 7 for getnameinfo. */ +#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7} + +/* Specifies the number of arguments to getservbyport_r */ +#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS} + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#cmakedefine GETSERVBYPORT_R_BUFSIZE ${GETSERVBYPORT_R_BUFSIZE} + +/* Define to 1 if you have the alarm function. */ +#cmakedefine HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +#cmakedefine HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#cmakedefine HAVE_BOOL_T 1 + +/* Define to 1 if you have the __builtin_available function. */ +#cmakedefine HAVE_BUILTIN_AVAILABLE 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the `closesocket' function. */ +#cmakedefine HAVE_CLOSESOCKET 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +#cmakedefine HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERR_H 1 + +/* Define to 1 if you have the fcntl function. */ +#cmakedefine HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#cmakedefine HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#cmakedefine HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#cmakedefine HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#cmakedefine HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#cmakedefine HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the ftruncate function. */ +#cmakedefine HAVE_FTRUNCATE 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#cmakedefine HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +#cmakedefine HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#cmakedefine HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#cmakedefine HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_5 1 + +/* gethostbyaddr_r() takes 7 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_7 1 + +/* gethostbyaddr_r() takes 8 args */ +#cmakedefine HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#cmakedefine HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +#cmakedefine HAVE_GETHOSTBYNAME_R 1 + +/* gethostbyname_r() takes 3 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_3 1 + +/* gethostbyname_r() takes 5 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_5 1 + +/* gethostbyname_r() takes 6 args */ +#cmakedefine HAVE_GETHOSTBYNAME_R_6 1 + +/* Define to 1 if you have the gethostname function. */ +#cmakedefine HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#cmakedefine HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#cmakedefine HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +#cmakedefine HAVE_GETPASS_R 1 + +/* Define to 1 if you have the `getppid' function. */ +#cmakedefine HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#cmakedefine HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpeername' function. */ +#cmakedefine HAVE_GETPEERNAME 1 + +/* Define to 1 if you have the `getsockname' function. */ +#cmakedefine HAVE_GETSOCKNAME 1 + +/* Define to 1 if you have the `if_nametoindex' function. */ +#cmakedefine HAVE_IF_NAMETOINDEX 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#cmakedefine HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#cmakedefine HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#cmakedefine HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +#cmakedefine HAVE_GETSERVBYPORT_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +#cmakedefine HAVE_GLIBC_STRERROR_R 1 + +/* Define to 1 if you have a working gmtime_r function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +#cmakedefine HAVE_GSSAPI 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_GENERIC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GSSAPI_GSSAPI_KRB5_H 1 + +/* if you have the GNU gssapi libraries */ +#cmakedefine HAVE_GSSGNU 1 + +/* if you have the Heimdal gssapi libraries */ +#cmakedefine HAVE_GSSHEIMDAL 1 + +/* if you have the MIT gssapi libraries */ +#cmakedefine HAVE_GSSMIT 1 + +/* Define to 1 if you have the `idna_strerror' function. */ +#cmakedefine HAVE_IDNA_STRERROR 1 + +/* Define to 1 if you have the `idn_free' function. */ +#cmakedefine HAVE_IDN_FREE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IDN_FREE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#cmakedefine HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +#cmakedefine HAVE_INET_NTOA_R 1 + +/* inet_ntoa_r() takes 2 args */ +#cmakedefine HAVE_INET_NTOA_R_2 1 + +/* inet_ntoa_r() takes 3 args */ +#cmakedefine HAVE_INET_NTOA_R_3 1 + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#cmakedefine HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#cmakedefine HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#cmakedefine HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +#cmakedefine HAVE_IOCTLSOCKET 1 + +/* Define to 1 if you have the IoctlSocket camel case function. */ +#cmakedefine HAVE_IOCTLSOCKET_CAMEL 1 + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +#cmakedefine HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1 + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +#cmakedefine HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#cmakedefine HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#cmakedefine HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IO_H 1 + +/* if you have the Kerberos4 libraries (including -ldes) */ +#cmakedefine HAVE_KRB4 1 + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_KRB_H 1 + +/* Define to 1 if you have the lber.h header file. */ +#cmakedefine HAVE_LBER_H 1 + +/* Define to 1 if you have the ldapssl.h header file. */ +#cmakedefine HAVE_LDAPSSL_H 1 + +/* Define to 1 if you have the ldap.h header file. */ +#cmakedefine HAVE_LDAP_H 1 + +/* Use LDAPS implementation */ +#cmakedefine HAVE_LDAP_SSL 1 + +/* Define to 1 if you have the ldap_ssl.h header file. */ +#cmakedefine HAVE_LDAP_SSL_H 1 + +/* Define to 1 if you have the `ldap_url_parse' function. */ +#cmakedefine HAVE_LDAP_URL_PARSE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +#cmakedefine HAVE_LIBIDN 1 + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#cmakedefine HAVE_LIBRESOLV 1 + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +#cmakedefine HAVE_LIBRESOLVE 1 + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#cmakedefine HAVE_LIBSOCKET 1 + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +#cmakedefine HAVE_LIBSSH2 1 + +/* Define to 1 if libssh2 provides `libssh2_version'. */ +#cmakedefine HAVE_LIBSSH2_VERSION 1 + +/* Define to 1 if libssh2 provides `libssh2_init'. */ +#cmakedefine HAVE_LIBSSH2_INIT 1 + +/* Define to 1 if libssh2 provides `libssh2_exit'. */ +#cmakedefine HAVE_LIBSSH2_EXIT 1 + +/* Define to 1 if libssh2 provides `libssh2_scp_send64'. */ +#cmakedefine HAVE_LIBSSH2_SCP_SEND64 1 + +/* Define to 1 if libssh2 provides `libssh2_session_handshake'. */ +#cmakedefine HAVE_LIBSSH2_SESSION_HANDSHAKE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBSSH2_H 1 + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#cmakedefine HAVE_LIBSSL 1 + +/* if zlib is available */ +#cmakedefine HAVE_LIBZ 1 + +/* if brotli is available */ +#cmakedefine HAVE_BROTLI 1 + +/* if your compiler supports LL */ +#cmakedefine HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#cmakedefine HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#cmakedefine HAVE_MALLOC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#cmakedefine HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +#cmakedefine HAVE_NI_WITHSCOPEID 1 + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */ +#cmakedefine HAVE_OLD_GSSMIT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PEM_H 1 + +/* Define to 1 if you have the `perror' function. */ +#cmakedefine HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#cmakedefine HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#cmakedefine HAVE_POLL 1 + +/* If you have a fine poll */ +#cmakedefine HAVE_POLL_FINE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#cmakedefine HAVE_POSIX_STRERROR_R 1 + +/* Define to 1 if you have the header file */ +#cmakedefine HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +#cmakedefine HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +#cmakedefine HAVE_RAND_SCREEN 1 + +/* Define to 1 if you have the `RAND_status' function. */ +#cmakedefine HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the recv function. */ +#cmakedefine HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#cmakedefine HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_RSA_H 1 + +/* Define to 1 if you have the select function. */ +#cmakedefine HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#cmakedefine HAVE_SEND 1 + +/* Define to 1 if you have the 'fsetxattr' function. */ +#cmakedefine HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +#cmakedefine HAVE_FSETXATTR_5 1 + +/* fsetxattr() takes 6 args */ +#cmakedefine HAVE_FSETXATTR_6 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#cmakedefine HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#cmakedefine HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#cmakedefine HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#cmakedefine HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#cmakedefine HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#cmakedefine HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#cmakedefine HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#cmakedefine HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#cmakedefine HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1 + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the `socket' function. */ +#cmakedefine HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#cmakedefine HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcasestr function. */ +#cmakedefine HAVE_STRCASESTR 1 + +/* Define to 1 if you have the strcmpi function. */ +#cmakedefine HAVE_STRCMPI 1 + +/* Define to 1 if you have the strdup function. */ +#cmakedefine HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#cmakedefine HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +#cmakedefine HAVE_STRICMP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the strlcat function. */ +#cmakedefine HAVE_STRLCAT 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#cmakedefine HAVE_STRLCPY 1 + +/* Define to 1 if you have the strncasecmp function. */ +#cmakedefine HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +#cmakedefine HAVE_STRNCMPI 1 + +/* Define to 1 if you have the strnicmp function. */ +#cmakedefine HAVE_STRNICMP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STROPTS_H 1 + +/* Define to 1 if you have the strstr function. */ +#cmakedefine HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#cmakedefine HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#cmakedefine HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#cmakedefine HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TLD_H 1 + +/* Define to 1 if you have the `tld_strerror' function. */ +#cmakedefine HAVE_TLD_STRERROR 1 + +/* Define to 1 if you have the `uname' function. */ +#cmakedefine HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#cmakedefine HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#cmakedefine HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#cmakedefine HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +#cmakedefine HAVE_WINBER_H 1 + +/* Define to 1 if you have the windows.h header file. */ +#cmakedefine HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the winldap.h header file. */ +#cmakedefine HAVE_WINLDAP_H 1 + +/* Define to 1 if you have the winsock2.h header file. */ +#cmakedefine HAVE_WINSOCK2_H 1 + +/* Define to 1 if you have the winsock.h header file. */ +#cmakedefine HAVE_WINSOCK_H 1 + +/* Define this symbol if your OS supports changing the contents of argv */ +#cmakedefine HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#cmakedefine HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +#cmakedefine HAVE_WS2TCPIP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_X509_H 1 + +/* Define if you have the header file. */ +#cmakedefine HAVE_PROCESS_H 1 + +/* if you have the zlib.h header file */ +#cmakedefine HAVE_ZLIB_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#cmakedefine LT_OBJDIR ${LT_OBJDIR} + +/* If you lack a fine basename() prototype */ +#cmakedefine NEED_BASENAME_PROTO 1 + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +#cmakedefine NEED_LBER_H 1 + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +#cmakedefine NEED_MALLOC_H 1 + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +#cmakedefine NEED_REENTRANT 1 + +/* cpu-machine-OS */ +#cmakedefine OS ${OS} + +/* Name of package */ +#cmakedefine PACKAGE ${PACKAGE} + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT} + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME ${PACKAGE_NAME} + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING ${PACKAGE_STRING} + +/* Define to the one symbol short name of this package. */ +#cmakedefine PACKAGE_TARNAME ${PACKAGE_TARNAME} + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION} + +/* a suitable file to read random data from */ +#cmakedefine RANDOM_FILE "${RANDOM_FILE}" + +/* Define to the type of arg 1 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG1 ${RECVFROM_TYPE_ARG1} + +/* Define to the type pointed by arg 2 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG2 ${RECVFROM_TYPE_ARG2} + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG3 ${RECVFROM_TYPE_ARG3} + +/* Define to the type of arg 4 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG4 ${RECVFROM_TYPE_ARG4} + +/* Define to the type pointed by arg 5 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG5 ${RECVFROM_TYPE_ARG5} + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG5_IS_VOID 1 + +/* Define to the type pointed by arg 6 for recvfrom. */ +#cmakedefine RECVFROM_TYPE_ARG6 ${RECVFROM_TYPE_ARG6} + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +#cmakedefine RECVFROM_TYPE_ARG6_IS_VOID 1 + +/* Define to the function return type for recvfrom. */ +#cmakedefine RECVFROM_TYPE_RETV ${RECVFROM_TYPE_RETV} + +/* Define to the type of arg 1 for recv. */ +#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1} + +/* Define to the type of arg 2 for recv. */ +#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2} + +/* Define to the type of arg 3 for recv. */ +#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3} + +/* Define to the type of arg 4 for recv. */ +#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4} + +/* Define to the function return type for recv. */ +#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV} + +/* Define as the return type of signal handlers (`int' or `void'). */ +#cmakedefine RETSIGTYPE ${RETSIGTYPE} + +/* Define to the type qualifier of arg 5 for select. */ +#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5} + +/* Define to the type of arg 1 for select. */ +#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1} + +/* Define to the type of args 2, 3 and 4 for select. */ +#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234} + +/* Define to the type of arg 5 for select. */ +#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5} + +/* Define to the function return type for select. */ +#cmakedefine SELECT_TYPE_RETV ${SELECT_TYPE_RETV} + +/* Define to the type qualifier of arg 2 for send. */ +#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2} + +/* Define to the type of arg 1 for send. */ +#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1} + +/* Define to the type of arg 2 for send. */ +#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2} + +/* Define to the type of arg 3 for send. */ +#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3} + +/* Define to the type of arg 4 for send. */ +#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4} + +/* Define to the function return type for send. */ +#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV} + +/* + Note: SIZEOF_* variables are fetched with CMake through check_type_size(). + As per CMake documentation on CheckTypeSize, C preprocessor code is + generated by CMake into SIZEOF_*_CODE. This is what we use in the + following statements. + + Reference: https://cmake.org/cmake/help/latest/module/CheckTypeSize.html +*/ + +/* The size of `int', as computed by sizeof. */ +${SIZEOF_INT_CODE} + +/* The size of `short', as computed by sizeof. */ +${SIZEOF_SHORT_CODE} + +/* The size of `long', as computed by sizeof. */ +${SIZEOF_LONG_CODE} + +/* The size of `off_t', as computed by sizeof. */ +${SIZEOF_OFF_T_CODE} + +/* The size of `curl_off_t', as computed by sizeof. */ +${SIZEOF_CURL_OFF_T_CODE} + +/* The size of `size_t', as computed by sizeof. */ +${SIZEOF_SIZE_T_CODE} + +/* The size of `time_t', as computed by sizeof. */ +${SIZEOF_TIME_T_CODE} + +/* Define to 1 if you have the ANSI C header files. */ +#cmakedefine STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#cmakedefine STRERROR_R_TYPE_ARG3 ${STRERROR_R_TYPE_ARG3} + +/* Define to 1 if you can safely include both and . */ +#cmakedefine TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable c-ares support */ +#cmakedefine USE_ARES 1 + +/* Define if you want to enable POSIX threaded DNS lookup */ +#cmakedefine USE_THREADS_POSIX 1 + +/* Define if you want to enable WIN32 threaded DNS lookup */ +#cmakedefine USE_THREADS_WIN32 1 + +/* Define to disable non-blocking sockets. */ +#cmakedefine USE_BLOCKING_SOCKETS 1 + +/* if GnuTLS is enabled */ +#cmakedefine USE_GNUTLS 1 + +/* if PolarSSL is enabled */ +#cmakedefine USE_POLARSSL 1 + +/* if Secure Transport is enabled */ +#cmakedefine USE_SECTRANSP 1 + +/* if mbedTLS is enabled */ +#cmakedefine USE_MBEDTLS 1 + +/* if libSSH2 is in use */ +#cmakedefine USE_LIBSSH2 1 + +/* If you want to build curl with the built-in manual */ +#cmakedefine USE_MANUAL 1 + +/* if NSS is enabled */ +#cmakedefine USE_NSS 1 + +/* if you want to use OpenLDAP code instead of legacy ldap implementation */ +#cmakedefine USE_OPENLDAP 1 + +/* if OpenSSL is in use */ +#cmakedefine USE_OPENSSL 1 + +/* to enable NGHTTP2 */ +#cmakedefine USE_NGHTTP2 1 + +/* if Unix domain sockets are enabled */ +#cmakedefine USE_UNIX_SOCKETS + +/* Define to 1 if you are building a Windows target with large file support. */ +#cmakedefine USE_WIN32_LARGE_FILES 1 + +/* to enable SSPI support */ +#cmakedefine USE_WINDOWS_SSPI 1 + +/* to enable Windows SSL */ +#cmakedefine USE_SCHANNEL 1 + +/* enable multiple SSL backends */ +#cmakedefine CURL_WITH_MULTI_SSL 1 + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +#cmakedefine USE_YASSLEMUL 1 + +/* Version number of package */ +#cmakedefine VERSION ${VERSION} + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} + +/* Define for large files, on AIX-style hosts. */ +#cmakedefine _LARGE_FILES ${_LARGE_FILES} + +/* define this if you need it to compile thread-safe code */ +#cmakedefine _THREAD_SAFE ${_THREAD_SAFE} + +/* Define to empty if `const' does not conform to ANSI C. */ +#cmakedefine const ${const} + +/* Type to use in place of in_addr_t when system does not provide it. */ +#cmakedefine in_addr_t ${in_addr_t} + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `unsigned int' if does not define. */ +#cmakedefine size_t ${size_t} + +/* the signed version of size_t */ +#cmakedefine ssize_t ${ssize_t} + +/* Define to 1 if you have the mach_absolute_time function. */ +#cmakedefine HAVE_MACH_ABSOLUTE_TIME 1 diff --git a/libcurl/lib/curl_config.h.in b/libcurl/lib/curl_config.h.in new file mode 100644 index 0000000..871c664 --- /dev/null +++ b/libcurl/lib/curl_config.h.in @@ -0,0 +1,1058 @@ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* to enable curl debug memory tracking */ +#undef CURLDEBUG + +/* Location of default ca bundle */ +#undef CURL_CA_BUNDLE + +/* define "1" to use built in CA store of SSL library */ +#undef CURL_CA_FALLBACK + +/* Location of default ca path */ +#undef CURL_CA_PATH + +/* Default SSL backend */ +#undef CURL_DEFAULT_SSL_BACKEND + +/* to disable cookies support */ +#undef CURL_DISABLE_COOKIES + +/* to disable cryptographic authentication */ +#undef CURL_DISABLE_CRYPTO_AUTH + +/* to disable DICT */ +#undef CURL_DISABLE_DICT + +/* disable DoH */ +#undef CURL_DISABLE_DOH + +/* to disable FILE */ +#undef CURL_DISABLE_FILE + +/* to disable FTP */ +#undef CURL_DISABLE_FTP + +/* to disable Gopher */ +#undef CURL_DISABLE_GOPHER + +/* to disable HTTP */ +#undef CURL_DISABLE_HTTP + +/* disable HTTP authentication */ +#undef CURL_DISABLE_HTTP_AUTH + +/* to disable IMAP */ +#undef CURL_DISABLE_IMAP + +/* to disable LDAP */ +#undef CURL_DISABLE_LDAP + +/* to disable LDAPS */ +#undef CURL_DISABLE_LDAPS + +/* to disable --libcurl C code generation option */ +#undef CURL_DISABLE_LIBCURL_OPTION + +/* disable mime API */ +#undef CURL_DISABLE_MIME + +/* disable netrc parsing */ +#undef CURL_DISABLE_NETRC + +/* if the OpenSSL configuration won't be loaded automatically */ +#undef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG + +/* disable date parsing */ +#undef CURL_DISABLE_PARSEDATE + +/* to disable POP3 */ +#undef CURL_DISABLE_POP3 + +/* disable progress-meter */ +#undef CURL_DISABLE_PROGRESS_METER + +/* to disable proxies */ +#undef CURL_DISABLE_PROXY + +/* to disable RTSP */ +#undef CURL_DISABLE_RTSP + +/* disable DNS shuffling */ +#undef CURL_DISABLE_SHUFFLE_DNS + +/* to disable SMB/CIFS */ +#undef CURL_DISABLE_SMB + +/* to disable SMTP */ +#undef CURL_DISABLE_SMTP + +/* to disable TELNET */ +#undef CURL_DISABLE_TELNET + +/* to disable TFTP */ +#undef CURL_DISABLE_TFTP + +/* to disable verbose strings */ +#undef CURL_DISABLE_VERBOSE_STRINGS + +/* Definition to make a library symbol externally visible. */ +#undef CURL_EXTERN_SYMBOL + +/* IP address type in sockaddr */ +#undef CURL_SA_FAMILY_T + +/* built with multiple SSL backends */ +#undef CURL_WITH_MULTI_SSL + +/* enable debug build options */ +#undef DEBUGBUILD + +/* your Entropy Gathering Daemon socket pathname */ +#undef EGD_SOCKET + +/* Define if you want to enable IPv6 support */ +#undef ENABLE_IPV6 + +/* Define to the type of arg 2 for gethostname. */ +#undef GETHOSTNAME_TYPE_ARG2 + +/* Specifies the number of arguments to getservbyport_r */ +#undef GETSERVBYPORT_R_ARGS + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#undef GETSERVBYPORT_R_BUFSIZE + +/* Define to 1 if you have the alarm function. */ +#undef HAVE_ALARM + +/* Define to 1 if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_TFTP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the basename function. */ +#undef HAVE_BASENAME + +/* Define to 1 if bool is an available type. */ +#undef HAVE_BOOL_T + +/* Define to 1 if using BoringSSL. */ +#undef HAVE_BORINGSSL + +/* if BROTLI is in use */ +#undef HAVE_BROTLI + +/* Define to 1 if you have the header file. */ +#undef HAVE_BROTLI_DECODE_H + +/* Define to 1 if you have the __builtin_available function. */ +#undef HAVE_BUILTIN_AVAILABLE + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#undef HAVE_CLOCK_GETTIME_MONOTONIC + +/* Define to 1 if you have the closesocket function. */ +#undef HAVE_CLOSESOCKET + +/* Define to 1 if you have the CloseSocket camel case function. */ +#undef HAVE_CLOSESOCKET_CAMEL + +/* Define to 1 if you have the connect function. */ +#undef HAVE_CONNECT + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRYPTO_H + +/* Define to 1 if you have the declaration of `getpwuid_r', and to 0 if you + don't. */ +#undef HAVE_DECL_GETPWUID_R + +/* "Set if getpwuid_r() declaration is missing" */ +#undef HAVE_DECL_GETPWUID_R_MISSING + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERR_H + +/* Define to 1 if you have the fcntl function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#undef HAVE_FCNTL_O_NONBLOCK + +/* Define to 1 if you have the `fnmatch' function. */ +#undef HAVE_FNMATCH + +/* Define to 1 if you have the freeaddrinfo function. */ +#undef HAVE_FREEADDRINFO + +/* Define to 1 if you have the freeifaddrs function. */ +#undef HAVE_FREEIFADDRS + +/* Define to 1 if you have the fsetxattr function. */ +#undef HAVE_FSETXATTR + +/* fsetxattr() takes 5 args */ +#undef HAVE_FSETXATTR_5 + +/* fsetxattr() takes 6 args */ +#undef HAVE_FSETXATTR_6 + +/* Define to 1 if you have the ftruncate function. */ +#undef HAVE_FTRUNCATE + +/* Define to 1 if you have the gai_strerror function. */ +#undef HAVE_GAI_STRERROR + +/* Define to 1 if you have a working getaddrinfo function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#undef HAVE_GETADDRINFO_THREADSAFE + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the gethostbyaddr function. */ +#undef HAVE_GETHOSTBYADDR + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#undef HAVE_GETHOSTBYADDR_R + +/* gethostbyaddr_r() takes 5 args */ +#undef HAVE_GETHOSTBYADDR_R_5 + +/* gethostbyaddr_r() takes 7 args */ +#undef HAVE_GETHOSTBYADDR_R_7 + +/* gethostbyaddr_r() takes 8 args */ +#undef HAVE_GETHOSTBYADDR_R_8 + +/* Define to 1 if you have the gethostbyname function. */ +#undef HAVE_GETHOSTBYNAME + +/* Define to 1 if you have the gethostbyname_r function. */ +#undef HAVE_GETHOSTBYNAME_R + +/* gethostbyname_r() takes 3 args */ +#undef HAVE_GETHOSTBYNAME_R_3 + +/* gethostbyname_r() takes 5 args */ +#undef HAVE_GETHOSTBYNAME_R_5 + +/* gethostbyname_r() takes 6 args */ +#undef HAVE_GETHOSTBYNAME_R_6 + +/* Define to 1 if you have the gethostname function. */ +#undef HAVE_GETHOSTNAME + +/* Define to 1 if you have a working getifaddrs function. */ +#undef HAVE_GETIFADDRS + +/* Define to 1 if you have the `getpass_r' function. */ +#undef HAVE_GETPASS_R + +/* Define to 1 if you have the getpeername function. */ +#undef HAVE_GETPEERNAME + +/* Define to 1 if you have the `getppid' function. */ +#undef HAVE_GETPPID + +/* Define to 1 if you have the `getpwuid' function. */ +#undef HAVE_GETPWUID + +/* Define to 1 if you have the `getpwuid_r' function. */ +#undef HAVE_GETPWUID_R + +/* Define to 1 if you have the `getrlimit' function. */ +#undef HAVE_GETRLIMIT + +/* Define to 1 if you have the getservbyport_r function. */ +#undef HAVE_GETSERVBYPORT_R + +/* Define to 1 if you have the getsockname function. */ +#undef HAVE_GETSOCKNAME + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +#undef HAVE_GLIBC_STRERROR_R + +/* Define to 1 if you have a working gmtime_r function. */ +#undef HAVE_GMTIME_R + +/* Define to 1 if you have the `gnutls_alpn_set_protocols' function. */ +#undef HAVE_GNUTLS_ALPN_SET_PROTOCOLS + +/* Define to 1 if you have the `gnutls_certificate_set_x509_key_file2' + function. */ +#undef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 + +/* Define to 1 if you have the `gnutls_ocsp_req_init' function. */ +#undef HAVE_GNUTLS_OCSP_REQ_INIT + +/* if you have the function gnutls_srp_verifier */ +#undef HAVE_GNUTLS_SRP + +/* if you have GSS-API libraries */ +#undef HAVE_GSSAPI + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_GENERIC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_KRB5_H + +/* if you have GNU GSS */ +#undef HAVE_GSSGNU + +/* if you have Heimdal */ +#undef HAVE_GSSHEIMDAL + +/* if you have MIT Kerberos */ +#undef HAVE_GSSMIT + +/* Define to 1 if you have the header file. */ +#undef HAVE_IDN2_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_IFADDRS_H + +/* Define to 1 if you have the `if_nametoindex' function. */ +#undef HAVE_IF_NAMETOINDEX + +/* Define to 1 if you have the inet_ntoa_r function. */ +#undef HAVE_INET_NTOA_R + +/* inet_ntoa_r() takes 2 args */ +#undef HAVE_INET_NTOA_R_2 + +/* inet_ntoa_r() takes 3 args */ +#undef HAVE_INET_NTOA_R_3 + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the ioctl function. */ +#undef HAVE_IOCTL + +/* Define to 1 if you have the ioctlsocket function. */ +#undef HAVE_IOCTLSOCKET + +/* Define to 1 if you have the IoctlSocket camel case function. */ +#undef HAVE_IOCTLSOCKET_CAMEL + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +#undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +#undef HAVE_IOCTLSOCKET_FIONBIO + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#undef HAVE_IOCTL_FIONBIO + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#undef HAVE_IOCTL_SIOCGIFADDR + +/* Define to 1 if you have the header file. */ +#undef HAVE_IO_H + +/* Define to 1 if you have the lber.h header file. */ +#undef HAVE_LBER_H + +/* Define to 1 if you have the ldapssl.h header file. */ +#undef HAVE_LDAPSSL_H + +/* Define to 1 if you have the ldap.h header file. */ +#undef HAVE_LDAP_H + +/* Define to 1 if you have the `ldap_init_fd' function. */ +#undef HAVE_LDAP_INIT_FD + +/* Use LDAPS implementation */ +#undef HAVE_LDAP_SSL + +/* Define to 1 if you have the ldap_ssl.h header file. */ +#undef HAVE_LDAP_SSL_H + +/* Define to 1 if you have the `ldap_url_parse' function. */ +#undef HAVE_LDAP_URL_PARSE + +/* Define to 1 if you have the `brotlidec' library (-lbrotlidec). */ +#undef HAVE_LIBBROTLIDEC + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H + +/* Define to 1 if you have the `idn2' library (-lidn2). */ +#undef HAVE_LIBIDN2 + +/* Define to 1 if using libressl. */ +#undef HAVE_LIBRESSL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBRTMP_RTMP_H + +/* Define to 1 if you have the `ssh' library (-lssh). */ +#undef HAVE_LIBSSH + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +#undef HAVE_LIBSSH2 + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBSSH2_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBSSH_LIBSSH_H + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* if zlib is available */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_TCP_H + +/* if your compiler supports LL */ +#undef HAVE_LL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have a working localtime_r function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#undef HAVE_LONGLONG + +/* Define to 1 if you have the `mach_absolute_time' function. */ +#undef HAVE_MACH_ABSOLUTE_TIME + +/* Define to 1 if you have the malloc.h header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the memory.h header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the memrchr function or macro. */ +#undef HAVE_MEMRCHR + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#undef HAVE_MSG_NOSIGNAL + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN6_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NGHTTP2_NGHTTP2_H + +/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +#undef HAVE_OLD_GSSMIT + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_CRYPTO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* if you have the function SRP_Calc_client_key */ +#undef HAVE_OPENSSL_SRP + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define to 1 if you have the `OpenSSL_version' function. */ +#undef HAVE_OPENSSL_VERSION + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_X509_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PEM_H + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* if you have the PK11_CreateManagedGenericObject function */ +#undef HAVE_PK11_CREATEMANAGEDGENERICOBJECT + +/* Define to 1 if you have a working poll function. */ +#undef HAVE_POLL + +/* If you have a fine poll */ +#undef HAVE_POLL_FINE + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#undef HAVE_POSIX_STRERROR_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_PROTO_BSDSOCKET_H + +/* if you have */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define to 1 if you have the `RAND_egd' function. */ +#undef HAVE_RAND_EGD + +/* Define to 1 if you have the recv function. */ +#undef HAVE_RECV + +/* Define to 1 if you have the header file. */ +#undef HAVE_RSA_H + +/* Define to 1 if you have the select function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the send function. */ +#undef HAVE_SEND + +/* Define to 1 if you have the header file. */ +#undef HAVE_SETJMP_H + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `setmode' function. */ +#undef HAVE_SETMODE + +/* Define to 1 if you have the `setrlimit' function. */ +#undef HAVE_SETRLIMIT + +/* Define to 1 if you have the setsockopt function. */ +#undef HAVE_SETSOCKOPT + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +#undef HAVE_SETSOCKOPT_SO_NONBLOCK + +/* Define to 1 if you have the header file. */ +#undef HAVE_SGTTY_H + +/* Define to 1 if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the siginterrupt function. */ +#undef HAVE_SIGINTERRUPT + +/* Define to 1 if you have the signal function. */ +#undef HAVE_SIGNAL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#undef HAVE_SIGSETJMP + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#undef HAVE_SIG_ATOMIC_T + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +#undef HAVE_SIG_ATOMIC_T_VOLATILE + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + +/* Define to 1 if you have the socket function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the socketpair function. */ +#undef HAVE_SOCKETPAIR + +/* Define to 1 if you have the header file. */ +#undef HAVE_SOCKET_H + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +#undef HAVE_SSLV2_CLIENT_METHOD + +/* Define to 1 if you have the header file. */ +#undef HAVE_SSL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the strcmpi function. */ +#undef HAVE_STRCMPI + +/* Define to 1 if you have the strdup function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the strerror_r function. */ +#undef HAVE_STRERROR_R + +/* Define to 1 if you have the stricmp function. */ +#undef HAVE_STRICMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the strncasecmp function. */ +#undef HAVE_STRNCASECMP + +/* Define to 1 if you have the strncmpi function. */ +#undef HAVE_STRNCMPI + +/* Define to 1 if you have the strnicmp function. */ +#undef HAVE_STRNICMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STROPTS_H + +/* Define to 1 if you have the strstr function. */ +#undef HAVE_STRSTR + +/* Define to 1 if you have the strtok_r function. */ +#undef HAVE_STRTOK_R + +/* Define to 1 if you have the strtoll function. */ +#undef HAVE_STRTOLL + +/* if struct sockaddr_storage is defined */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define to 1 if you have the timeval struct. */ +#undef HAVE_STRUCT_TIMEVAL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_POLL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_XATTR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define this if time_t is unsigned */ +#undef HAVE_TIME_T_UNSIGNED + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `utime' function. */ +#undef HAVE_UTIME + +/* Define to 1 if you have the `utimes' function. */ +#undef HAVE_UTIMES + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#undef HAVE_VARIADIC_MACROS_C99 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#undef HAVE_VARIADIC_MACROS_GCC + +/* Define to 1 if you have the winber.h header file. */ +#undef HAVE_WINBER_H + +/* Define to 1 if you have the windows.h header file. */ +#undef HAVE_WINDOWS_H + +/* Define to 1 if you have the winldap.h header file. */ +#undef HAVE_WINLDAP_H + +/* Define to 1 if you have the winsock2.h header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to 1 if you have the winsock.h header file. */ +#undef HAVE_WINSOCK_H + +/* Define to 1 if you have the `wolfSSLv3_client_method' function. */ +#undef HAVE_WOLFSSLV3_CLIENT_METHOD + +/* Define to 1 if you have the `wolfSSL_get_peer_certificate' function. */ +#undef HAVE_WOLFSSL_GET_PEER_CERTIFICATE + +/* Define to 1 if you have the `wolfSSL_UseALPN' function. */ +#undef HAVE_WOLFSSL_USEALPN + +/* Define this symbol if your OS supports changing the contents of argv */ +#undef HAVE_WRITABLE_ARGV + +/* Define to 1 if you have the writev function. */ +#undef HAVE_WRITEV + +/* Define to 1 if you have the ws2tcpip.h header file. */ +#undef HAVE_WS2TCPIP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_X509_H + +/* if you have the zlib.h header file */ +#undef HAVE_ZLIB_H + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +#undef NEED_LBER_H + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +#undef NEED_MALLOC_H + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +#undef NEED_MEMORY_H + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +#undef NEED_REENTRANT + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +#undef NEED_THREAD_SAFE + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +#undef NTLM_WB_ENABLED + +/* Define absolute filename for winbind's ntlm_auth helper. */ +#undef NTLM_WB_FILE + +/* cpu-machine-OS */ +#undef OS + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* a suitable file to read random data from */ +#undef RANDOM_FILE + +/* Define to the type of arg 1 for recv. */ +#undef RECV_TYPE_ARG1 + +/* Define to the type of arg 2 for recv. */ +#undef RECV_TYPE_ARG2 + +/* Define to the type of arg 3 for recv. */ +#undef RECV_TYPE_ARG3 + +/* Define to the type of arg 4 for recv. */ +#undef RECV_TYPE_ARG4 + +/* Define to the function return type for recv. */ +#undef RECV_TYPE_RETV + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to the type qualifier of arg 5 for select. */ +#undef SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#undef SELECT_TYPE_ARG1 + +/* Define to the type of args 2, 3 and 4 for select. */ +#undef SELECT_TYPE_ARG234 + +/* Define to the type of arg 5 for select. */ +#undef SELECT_TYPE_ARG5 + +/* Define to the function return type for select. */ +#undef SELECT_TYPE_RETV + +/* Define to the type qualifier of arg 2 for send. */ +#undef SEND_QUAL_ARG2 + +/* Define to the type of arg 1 for send. */ +#undef SEND_TYPE_ARG1 + +/* Define to the type of arg 2 for send. */ +#undef SEND_TYPE_ARG2 + +/* Define to the type of arg 3 for send. */ +#undef SEND_TYPE_ARG3 + +/* Define to the type of arg 4 for send. */ +#undef SEND_TYPE_ARG4 + +/* Define to the function return type for send. */ +#undef SEND_TYPE_RETV + +/* The number of bytes in type curl_off_t */ +#undef SIZEOF_CURL_OFF_T + +/* The number of bytes in type int */ +#undef SIZEOF_INT + +/* The number of bytes in type long */ +#undef SIZEOF_LONG + +/* The number of bytes in type long long */ +#undef SIZEOF_LONG_LONG + +/* The number of bytes in type off_t */ +#undef SIZEOF_OFF_T + +/* The number of bytes in type short */ +#undef SIZEOF_SHORT + +/* The number of bytes in type size_t */ +#undef SIZEOF_SIZE_T + +/* The number of bytes in type time_t */ +#undef SIZEOF_TIME_T + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to the type of arg 3 for strerror_r. */ +#undef STRERROR_R_TYPE_ARG3 + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* to enable alt-svc */ +#undef USE_ALTSVC + +/* if AmiSSL is in use */ +#undef USE_AMISSL + +/* Define to enable c-ares support */ +#undef USE_ARES + +/* if GnuTLS is enabled */ +#undef USE_GNUTLS + +/* if GnuTLS uses nettle as crypto backend */ +#undef USE_GNUTLS_NETTLE + +/* PSL support enabled */ +#undef USE_LIBPSL + +/* if librtmp is in use */ +#undef USE_LIBRTMP + +/* if libSSH is in use */ +#undef USE_LIBSSH + +/* if libSSH2 is in use */ +#undef USE_LIBSSH2 + +/* If you want to build curl with the built-in manual */ +#undef USE_MANUAL + +/* if mbedTLS is enabled */ +#undef USE_MBEDTLS + +/* if MesaLink is enabled */ +#undef USE_MESALINK + +/* Define to enable metalink support */ +#undef USE_METALINK + +/* if nghttp2 is in use */ +#undef USE_NGHTTP2 + +/* if NSS is enabled */ +#undef USE_NSS + +/* Use OpenLDAP-specific code */ +#undef USE_OPENLDAP + +/* if OpenSSL is in use */ +#undef USE_OPENSSL + +/* to enable Windows native SSL/TLS support */ +#undef USE_SCHANNEL + +/* enable Secure Transport */ +#undef USE_SECTRANSP + +/* if you want POSIX threaded DNS lookup */ +#undef USE_THREADS_POSIX + +/* if you want Win32 threaded DNS lookup */ +#undef USE_THREADS_WIN32 + +/* Use TLS-SRP authentication */ +#undef USE_TLS_SRP + +/* Use Unix domain sockets */ +#undef USE_UNIX_SOCKETS + +/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ +#undef USE_WIN32_IDN + +/* Define to 1 if you are building a Windows target with large file support. + */ +#undef USE_WIN32_LARGE_FILES + +/* Use Windows LDAP implementation */ +#undef USE_WIN32_LDAP + +/* Define to 1 if you are building a Windows target without large file + support. */ +#undef USE_WIN32_SMALL_FILES + +/* to enable SSPI support */ +#undef USE_WINDOWS_SSPI + +/* if wolfSSL is enabled */ +#undef USE_WOLFSSL + +/* Version number of package */ +#undef VERSION + +/* Define to 1 to provide own prototypes. */ +#undef WANT_IDN_PROTOTYPES + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Type to use in place of in_addr_t when system does not provide it. */ +#undef in_addr_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* the signed version of size_t */ +#undef ssize_t diff --git a/libcurl/lib/curl_ctype.c b/libcurl/lib/curl_ctype.c new file mode 100644 index 0000000..1a47fb5 --- /dev/null +++ b/libcurl/lib/curl_ctype.c @@ -0,0 +1,133 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DOES_CONVERSIONS + +#undef _U +#define _U (1<<0) /* upper case */ +#undef _L +#define _L (1<<1) /* lower case */ +#undef _N +#define _N (1<<2) /* decimal numerical digit */ +#undef _S +#define _S (1<<3) /* space */ +#undef _P +#define _P (1<<4) /* punctuation */ +#undef _C +#define _C (1<<5) /* control */ +#undef _X +#define _X (1<<6) /* hexadecimal letter */ +#undef _B +#define _B (1<<7) /* blank */ + +static const unsigned char ascii[128] = { + _C, _C, _C, _C, _C, _C, _C, _C, + _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C, + _C, _C, _C, _C, _C, _C, _C, _C, + _C, _C, _C, _C, _C, _C, _C, _C, + _S|_B, _P, _P, _P, _P, _P, _P, _P, + _P, _P, _P, _P, _P, _P, _P, _P, + _N, _N, _N, _N, _N, _N, _N, _N, + _N, _N, _P, _P, _P, _P, _P, _P, + _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U, + _U, _U, _U, _U, _U, _U, _U, _U, + _U, _U, _U, _U, _U, _U, _U, _U, + _U, _U, _U, _P, _P, _P, _P, _P, + _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L, + _L, _L, _L, _L, _L, _L, _L, _L, + _L, _L, _L, _L, _L, _L, _L, _L, + _L, _L, _L, _P, _P, _P, _P, _C +}; + +int Curl_isspace(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & _S); +} + +int Curl_isdigit(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & _N); +} + +int Curl_isalnum(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_N|_U|_L)); +} + +int Curl_isxdigit(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_N|_X)); +} + +int Curl_isgraph(int c) +{ + if((c < 0) || (c >= 0x80) || (c == ' ')) + return FALSE; + return (ascii[c] & (_N|_X|_U|_L|_P|_S)); +} + +int Curl_isprint(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_N|_X|_U|_L|_P|_S)); +} + +int Curl_isalpha(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_U|_L)); +} + +int Curl_isupper(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_U)); +} + +int Curl_islower(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_L)); +} + +int Curl_iscntrl(int c) +{ + if((c < 0) || (c >= 0x80)) + return FALSE; + return (ascii[c] & (_C)); +} + +#endif /* !CURL_DOES_CONVERSIONS */ diff --git a/libcurl/lib/curl_ctype.h b/libcurl/lib/curl_ctype.h new file mode 100644 index 0000000..6e94bb1 --- /dev/null +++ b/libcurl/lib/curl_ctype.h @@ -0,0 +1,81 @@ +#ifndef HEADER_CURL_CTYPE_H +#define HEADER_CURL_CTYPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +/* + * Uppercase macro versions of ANSI/ISO is*() functions/macros which + * avoid negative number inputs with argument byte codes > 127. + * + * For non-ASCII platforms the C library character classification routines + * are used despite being locale-dependent, because this is better than + * not to work at all. + */ +#include + +#define ISSPACE(x) (isspace((int) ((unsigned char)x))) +#define ISDIGIT(x) (isdigit((int) ((unsigned char)x))) +#define ISALNUM(x) (isalnum((int) ((unsigned char)x))) +#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) +#define ISGRAPH(x) (isgraph((int) ((unsigned char)x))) +#define ISALPHA(x) (isalpha((int) ((unsigned char)x))) +#define ISPRINT(x) (isprint((int) ((unsigned char)x))) +#define ISUPPER(x) (isupper((int) ((unsigned char)x))) +#define ISLOWER(x) (islower((int) ((unsigned char)x))) +#define ISCNTRL(x) (iscntrl((int) ((unsigned char)x))) +#define ISASCII(x) (isascii((int) ((unsigned char)x))) + +#else + +int Curl_isspace(int c); +int Curl_isdigit(int c); +int Curl_isalnum(int c); +int Curl_isxdigit(int c); +int Curl_isgraph(int c); +int Curl_isprint(int c); +int Curl_isalpha(int c); +int Curl_isupper(int c); +int Curl_islower(int c); +int Curl_iscntrl(int c); + +#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x))) +#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x))) +#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x))) +#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x))) +#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x))) +#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x))) +#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x))) +#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x))) +#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x))) +#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x))) +#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80)) + +#endif + +#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \ + (((unsigned char)x) == '\t')) + +#endif /* HEADER_CURL_CTYPE_H */ diff --git a/libcurl/lib/curl_des.c b/libcurl/lib/curl_des.c new file mode 100644 index 0000000..b123a00 --- /dev/null +++ b/libcurl/lib/curl_des.c @@ -0,0 +1,63 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && !defined(USE_OPENSSL) + +#include "curl_des.h" + +/* + * Curl_des_set_odd_parity() + * + * This is used to apply odd parity to the given byte array. It is typically + * used by when a cryptography engines doesn't have it's own version. + * + * The function is a port of the Java based oddParity() function over at: + * + * https://davenport.sourceforge.io/ntlm.html + * + * Parameters: + * + * bytes [in/out] - The data whose parity bits are to be adjusted for + * odd parity. + * len [out] - The length of the data. + */ +void Curl_des_set_odd_parity(unsigned char *bytes, size_t len) +{ + size_t i; + + for(i = 0; i < len; i++) { + unsigned char b = bytes[i]; + + bool needs_parity = (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ + (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ + (b >> 1)) & 0x01) == 0; + + if(needs_parity) + bytes[i] |= 0x01; + else + bytes[i] &= 0xfe; + } +} + +#endif /* USE_NTLM && !USE_OPENSSL */ diff --git a/libcurl/lib/curl_des.h b/libcurl/lib/curl_des.h new file mode 100644 index 0000000..129060f --- /dev/null +++ b/libcurl/lib/curl_des.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_DES_H +#define HEADER_CURL_DES_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && !defined(USE_OPENSSL) + +/* Applies odd parity to the given byte array */ +void Curl_des_set_odd_parity(unsigned char *bytes, size_t length); + +#endif /* USE_NTLM && !USE_OPENSSL */ + +#endif /* HEADER_CURL_DES_H */ diff --git a/libcurl/lib/curl_endian.c b/libcurl/lib/curl_endian.c new file mode 100644 index 0000000..b7563b3 --- /dev/null +++ b/libcurl/lib/curl_endian.c @@ -0,0 +1,124 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_endian.h" + +/* + * Curl_read16_le() + * + * This function converts a 16-bit integer from the little endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 2 byte buffer. + * + * Returns the integer. + */ +unsigned short Curl_read16_le(const unsigned char *buf) +{ + return (unsigned short)(((unsigned short)buf[0]) | + ((unsigned short)buf[1] << 8)); +} + +/* + * Curl_read32_le() + * + * This function converts a 32-bit integer from the little endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 4 byte buffer. + * + * Returns the integer. + */ +unsigned int Curl_read32_le(const unsigned char *buf) +{ + return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | + ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); +} + +/* + * Curl_read16_be() + * + * This function converts a 16-bit integer from the big endian format, as + * used in the incoming package to whatever endian format we're using + * natively. + * + * Parameters: + * + * buf [in] - A pointer to a 2 byte buffer. + * + * Returns the integer. + */ +unsigned short Curl_read16_be(const unsigned char *buf) +{ + return (unsigned short)(((unsigned short)buf[0] << 8) | + ((unsigned short)buf[1])); +} + +/* + * write32_le() + * + * This function converts a 32-bit integer from the native endian format, + * to little endian format ready for sending down the wire. + * + * Parameters: + * + * value [in] - The 32-bit integer value. + * buffer [in] - A pointer to the output buffer. + */ +static void write32_le(const int value, unsigned char *buffer) +{ + buffer[0] = (char)(value & 0x000000FF); + buffer[1] = (char)((value & 0x0000FF00) >> 8); + buffer[2] = (char)((value & 0x00FF0000) >> 16); + buffer[3] = (char)((value & 0xFF000000) >> 24); +} + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* + * Curl_write64_le() + * + * This function converts a 64-bit integer from the native endian format, + * to little endian format ready for sending down the wire. + * + * Parameters: + * + * value [in] - The 64-bit integer value. + * buffer [in] - A pointer to the output buffer. + */ +#if defined(HAVE_LONGLONG) +void Curl_write64_le(const long long value, unsigned char *buffer) +#else +void Curl_write64_le(const __int64 value, unsigned char *buffer) +#endif +{ + write32_le((int)value, buffer); + write32_le((int)(value >> 32), buffer + 4); +} +#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ diff --git a/libcurl/lib/curl_endian.h b/libcurl/lib/curl_endian.h new file mode 100644 index 0000000..9830e58 --- /dev/null +++ b/libcurl/lib/curl_endian.h @@ -0,0 +1,43 @@ +#ifndef HEADER_CURL_ENDIAN_H +#define HEADER_CURL_ENDIAN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Converts a 16-bit integer from little endian */ +unsigned short Curl_read16_le(const unsigned char *buf); + +/* Converts a 32-bit integer from little endian */ +unsigned int Curl_read32_le(const unsigned char *buf); + +/* Converts a 16-bit integer from big endian */ +unsigned short Curl_read16_be(const unsigned char *buf); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* Converts a 64-bit integer to little endian */ +#if defined(HAVE_LONGLONG) +void Curl_write64_le(const long long value, unsigned char *buffer); +#else +void Curl_write64_le(const __int64 value, unsigned char *buffer); +#endif +#endif + +#endif /* HEADER_CURL_ENDIAN_H */ diff --git a/libcurl/lib/curl_fnmatch.c b/libcurl/lib/curl_fnmatch.c new file mode 100644 index 0000000..ab3e742 --- /dev/null +++ b/libcurl/lib/curl_fnmatch.c @@ -0,0 +1,389 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#ifndef CURL_DISABLE_FTP +#include + +#include "curl_fnmatch.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef HAVE_FNMATCH + +#define CURLFNM_CHARSET_LEN (sizeof(char) * 256) +#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15) + +#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN + +#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1) +#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2) +#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3) +#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4) +#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5) +#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6) +#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7) +#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8) +#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9) +#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10) + +typedef enum { + CURLFNM_SCHS_DEFAULT = 0, + CURLFNM_SCHS_RIGHTBR, + CURLFNM_SCHS_RIGHTBRLEFTBR +} setcharset_state; + +typedef enum { + CURLFNM_PKW_INIT = 0, + CURLFNM_PKW_DDOT +} parsekey_state; + +typedef enum { + CCLASS_OTHER = 0, + CCLASS_DIGIT, + CCLASS_UPPER, + CCLASS_LOWER +} char_class; + +#define SETCHARSET_OK 1 +#define SETCHARSET_FAIL 0 + +static int parsekeyword(unsigned char **pattern, unsigned char *charset) +{ + parsekey_state state = CURLFNM_PKW_INIT; +#define KEYLEN 10 + char keyword[KEYLEN] = { 0 }; + int found = FALSE; + int i; + unsigned char *p = *pattern; + for(i = 0; !found; i++) { + char c = *p++; + if(i >= KEYLEN) + return SETCHARSET_FAIL; + switch(state) { + case CURLFNM_PKW_INIT: + if(ISLOWER(c)) + keyword[i] = c; + else if(c == ':') + state = CURLFNM_PKW_DDOT; + else + return SETCHARSET_FAIL; + break; + case CURLFNM_PKW_DDOT: + if(c == ']') + found = TRUE; + else + return SETCHARSET_FAIL; + } + } +#undef KEYLEN + + *pattern = p; /* move caller's pattern pointer */ + if(strcmp(keyword, "digit") == 0) + charset[CURLFNM_DIGIT] = 1; + else if(strcmp(keyword, "alnum") == 0) + charset[CURLFNM_ALNUM] = 1; + else if(strcmp(keyword, "alpha") == 0) + charset[CURLFNM_ALPHA] = 1; + else if(strcmp(keyword, "xdigit") == 0) + charset[CURLFNM_XDIGIT] = 1; + else if(strcmp(keyword, "print") == 0) + charset[CURLFNM_PRINT] = 1; + else if(strcmp(keyword, "graph") == 0) + charset[CURLFNM_GRAPH] = 1; + else if(strcmp(keyword, "space") == 0) + charset[CURLFNM_SPACE] = 1; + else if(strcmp(keyword, "blank") == 0) + charset[CURLFNM_BLANK] = 1; + else if(strcmp(keyword, "upper") == 0) + charset[CURLFNM_UPPER] = 1; + else if(strcmp(keyword, "lower") == 0) + charset[CURLFNM_LOWER] = 1; + else + return SETCHARSET_FAIL; + return SETCHARSET_OK; +} + +/* Return the character class. */ +static char_class charclass(unsigned char c) +{ + if(ISUPPER(c)) + return CCLASS_UPPER; + if(ISLOWER(c)) + return CCLASS_LOWER; + if(ISDIGIT(c)) + return CCLASS_DIGIT; + return CCLASS_OTHER; +} + +/* Include a character or a range in set. */ +static void setcharorrange(unsigned char **pp, unsigned char *charset) +{ + unsigned char *p = (*pp)++; + unsigned char c = *p++; + + charset[c] = 1; + if(ISALNUM(c) && *p++ == '-') { + char_class cc = charclass(c); + unsigned char endrange = *p++; + + if(endrange == '\\') + endrange = *p++; + if(endrange >= c && charclass(endrange) == cc) { + while(c++ != endrange) + if(charclass(c) == cc) /* Chars in class may be not consecutive. */ + charset[c] = 1; + *pp = p; + } + } +} + +/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */ +static int setcharset(unsigned char **p, unsigned char *charset) +{ + setcharset_state state = CURLFNM_SCHS_DEFAULT; + bool something_found = FALSE; + unsigned char c; + + memset(charset, 0, CURLFNM_CHSET_SIZE); + for(;;) { + c = **p; + if(!c) + return SETCHARSET_FAIL; + + switch(state) { + case CURLFNM_SCHS_DEFAULT: + if(c == ']') { + if(something_found) + return SETCHARSET_OK; + something_found = TRUE; + state = CURLFNM_SCHS_RIGHTBR; + charset[c] = 1; + (*p)++; + } + else if(c == '[') { + unsigned char *pp = *p + 1; + + if(*pp++ == ':' && parsekeyword(&pp, charset)) + *p = pp; + else { + charset[c] = 1; + (*p)++; + } + something_found = TRUE; + } + else if(c == '^' || c == '!') { + if(!something_found) { + if(charset[CURLFNM_NEGATE]) { + charset[c] = 1; + something_found = TRUE; + } + else + charset[CURLFNM_NEGATE] = 1; /* negate charset */ + } + else + charset[c] = 1; + (*p)++; + } + else if(c == '\\') { + c = *(++(*p)); + if(c) + setcharorrange(p, charset); + else + charset['\\'] = 1; + something_found = TRUE; + } + else { + setcharorrange(p, charset); + something_found = TRUE; + } + break; + case CURLFNM_SCHS_RIGHTBR: + if(c == '[') { + state = CURLFNM_SCHS_RIGHTBRLEFTBR; + charset[c] = 1; + (*p)++; + } + else if(c == ']') { + return SETCHARSET_OK; + } + else if(ISPRINT(c)) { + charset[c] = 1; + (*p)++; + state = CURLFNM_SCHS_DEFAULT; + } + else + /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a + * nonsense warning 'statement not reached' at end of the fnc when + * compiling on Solaris */ + goto fail; + break; + case CURLFNM_SCHS_RIGHTBRLEFTBR: + if(c == ']') + return SETCHARSET_OK; + state = CURLFNM_SCHS_DEFAULT; + charset[c] = 1; + (*p)++; + break; + } + } +fail: + return SETCHARSET_FAIL; +} + +static int loop(const unsigned char *pattern, const unsigned char *string, + int maxstars) +{ + unsigned char *p = (unsigned char *)pattern; + unsigned char *s = (unsigned char *)string; + unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 }; + + for(;;) { + unsigned char *pp; + + switch(*p) { + case '*': + if(!maxstars) + return CURL_FNMATCH_NOMATCH; + /* Regroup consecutive stars and question marks. This can be done because + '*?*?*' can be expressed as '??*'. */ + for(;;) { + if(*++p == '\0') + return CURL_FNMATCH_MATCH; + if(*p == '?') { + if(!*s++) + return CURL_FNMATCH_NOMATCH; + } + else if(*p != '*') + break; + } + /* Skip string characters until we find a match with pattern suffix. */ + for(maxstars--; *s; s++) { + if(loop(p, s, maxstars) == CURL_FNMATCH_MATCH) + return CURL_FNMATCH_MATCH; + } + return CURL_FNMATCH_NOMATCH; + case '?': + if(!*s) + return CURL_FNMATCH_NOMATCH; + s++; + p++; + break; + case '\0': + return *s? CURL_FNMATCH_NOMATCH: CURL_FNMATCH_MATCH; + case '\\': + if(p[1]) + p++; + if(*s++ != *p++) + return CURL_FNMATCH_NOMATCH; + break; + case '[': + pp = p + 1; /* Copy in case of syntax error in set. */ + if(setcharset(&pp, charset)) { + int found = FALSE; + if(!*s) + return CURL_FNMATCH_NOMATCH; + if(charset[(unsigned int)*s]) + found = TRUE; + else if(charset[CURLFNM_ALNUM]) + found = ISALNUM(*s); + else if(charset[CURLFNM_ALPHA]) + found = ISALPHA(*s); + else if(charset[CURLFNM_DIGIT]) + found = ISDIGIT(*s); + else if(charset[CURLFNM_XDIGIT]) + found = ISXDIGIT(*s); + else if(charset[CURLFNM_PRINT]) + found = ISPRINT(*s); + else if(charset[CURLFNM_SPACE]) + found = ISSPACE(*s); + else if(charset[CURLFNM_UPPER]) + found = ISUPPER(*s); + else if(charset[CURLFNM_LOWER]) + found = ISLOWER(*s); + else if(charset[CURLFNM_BLANK]) + found = ISBLANK(*s); + else if(charset[CURLFNM_GRAPH]) + found = ISGRAPH(*s); + + if(charset[CURLFNM_NEGATE]) + found = !found; + + if(!found) + return CURL_FNMATCH_NOMATCH; + p = pp + 1; + s++; + break; + } + /* Syntax error in set; mismatch! */ + return CURL_FNMATCH_NOMATCH; + + default: + if(*p++ != *s++) + return CURL_FNMATCH_NOMATCH; + break; + } + } +} + +/* + * @unittest: 1307 + */ +int Curl_fnmatch(void *ptr, const char *pattern, const char *string) +{ + (void)ptr; /* the argument is specified by the curl_fnmatch_callback + prototype, but not used by Curl_fnmatch() */ + if(!pattern || !string) { + return CURL_FNMATCH_FAIL; + } + return loop((unsigned char *)pattern, (unsigned char *)string, 2); +} +#else +#include +/* + * @unittest: 1307 + */ +int Curl_fnmatch(void *ptr, const char *pattern, const char *string) +{ + int rc; + (void)ptr; /* the argument is specified by the curl_fnmatch_callback + prototype, but not used by Curl_fnmatch() */ + if(!pattern || !string) { + return CURL_FNMATCH_FAIL; + } + rc = fnmatch(pattern, string, 0); + switch(rc) { + case 0: + return CURL_FNMATCH_MATCH; + case FNM_NOMATCH: + return CURL_FNMATCH_NOMATCH; + default: + return CURL_FNMATCH_FAIL; + } + /* not reached */ +} + +#endif + +#endif /* if FTP is disabled */ diff --git a/libcurl/lib/curl_fnmatch.h b/libcurl/lib/curl_fnmatch.h new file mode 100644 index 0000000..69ffe39 --- /dev/null +++ b/libcurl/lib/curl_fnmatch.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_FNMATCH_H +#define HEADER_CURL_FNMATCH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define CURL_FNMATCH_MATCH 0 +#define CURL_FNMATCH_NOMATCH 1 +#define CURL_FNMATCH_FAIL 2 + +/* default pattern matching function + * ================================= + * Implemented with recursive backtracking, if you want to use Curl_fnmatch, + * please note that there is not implemented UTF/UNICODE support. + * + * Implemented features: + * '?' notation, does not match UTF characters + * '*' can also work with UTF string + * [a-zA-Z0-9] enumeration support + * + * keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space + * and upper (use as "[[:alnum:]]") + */ +int Curl_fnmatch(void *ptr, const char *pattern, const char *string); + +#endif /* HEADER_CURL_FNMATCH_H */ diff --git a/libcurl/lib/curl_get_line.c b/libcurl/lib/curl_get_line.c new file mode 100644 index 0000000..c419485 --- /dev/null +++ b/libcurl/lib/curl_get_line.c @@ -0,0 +1,55 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_get_line.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * get_line() makes sure to only return complete whole lines that fit in 'len' + * bytes and end with a newline. + */ +char *Curl_get_line(char *buf, int len, FILE *input) +{ + bool partial = FALSE; + while(1) { + char *b = fgets(buf, len, input); + if(b) { + size_t rlen = strlen(b); + if(rlen && (b[rlen-1] == '\n')) { + if(partial) { + partial = FALSE; + continue; + } + return b; + } + /* read a partial, discard the next piece that ends with newline */ + partial = TRUE; + } + else + break; + } + return NULL; +} diff --git a/libcurl/lib/curl_get_line.h b/libcurl/lib/curl_get_line.h new file mode 100644 index 0000000..532ab08 --- /dev/null +++ b/libcurl/lib/curl_get_line.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_GET_LINE_H +#define HEADER_CURL_GET_LINE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* get_line() makes sure to only return complete whole lines that fit in 'len' + * bytes and end with a newline. */ +char *Curl_get_line(char *buf, int len, FILE *input); + +#endif /* HEADER_CURL_GET_LINE_H */ diff --git a/libcurl/lib/curl_gethostname.c b/libcurl/lib/curl_gethostname.c new file mode 100644 index 0000000..95f7ed4 --- /dev/null +++ b/libcurl/lib/curl_gethostname.c @@ -0,0 +1,108 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "curl_gethostname.h" + +/* + * Curl_gethostname() is a wrapper around gethostname() which allows + * overriding the host name that the function would normally return. + * This capability is used by the test suite to verify exact matching + * of NTLM authentication, which exercises libcurl's MD4 and DES code + * as well as by the SMTP module when a hostname is not provided. + * + * For libcurl debug enabled builds host name overriding takes place + * when environment variable CURL_GETHOSTNAME is set, using the value + * held by the variable to override returned host name. + * + * Note: The function always returns the un-qualified hostname rather + * than being provider dependent. + * + * For libcurl shared library release builds the test suite preloads + * another shared library named libhostname using the LD_PRELOAD + * mechanism which intercepts, and might override, the gethostname() + * function call. In this case a given platform must support the + * LD_PRELOAD mechanism and additionally have environment variable + * CURL_GETHOSTNAME set in order to override the returned host name. + * + * For libcurl static library release builds no overriding takes place. + */ + +int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) +{ + +#ifdef _XBOX + (void) name; + (void) namelen; + return -1; +#else + +#ifndef HAVE_GETHOSTNAME + + /* Allow compilation and return failure when unavailable */ + (void) name; + (void) namelen; + return -1; + +#else + int err; + char *dot; + +#ifdef DEBUGBUILD + + /* Override host name when environment variable CURL_GETHOSTNAME is set */ + const char *force_hostname = getenv("CURL_GETHOSTNAME"); + if(force_hostname) { + strncpy(name, force_hostname, namelen); + err = 0; + } + else { + name[0] = '\0'; + err = gethostname(name, namelen); + } + +#else /* DEBUGBUILD */ + + /* The call to system's gethostname() might get intercepted by the + libhostname library when libcurl is built as a non-debug shared + library when running the test suite. */ + name[0] = '\0'; + err = gethostname(name, namelen); + +#endif + + name[namelen - 1] = '\0'; + + if(err) + return err; + + /* Truncate domain, leave only machine name */ + dot = strchr(name, '.'); + if(dot) + *dot = '\0'; + + return 0; +#endif +#endif // _XBOX + +} diff --git a/libcurl/lib/curl_gethostname.h b/libcurl/lib/curl_gethostname.h new file mode 100644 index 0000000..07517c5 --- /dev/null +++ b/libcurl/lib/curl_gethostname.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_GETHOSTNAME_H +#define HEADER_CURL_GETHOSTNAME_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Hostname buffer size */ +#define HOSTNAME_MAX 1024 + +/* This returns the local machine's un-qualified hostname */ +int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen); + +#endif /* HEADER_CURL_GETHOSTNAME_H */ diff --git a/libcurl/lib/curl_gssapi.c b/libcurl/lib/curl_gssapi.c new file mode 100644 index 0000000..d854ab0 --- /dev/null +++ b/libcurl/lib/curl_gssapi.c @@ -0,0 +1,136 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2011 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_GSSAPI + +#include "curl_gssapi.h" +#include "sendf.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02"; +gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes }; +static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"; +gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes }; + +OM_uint32 Curl_gss_init_sec_context( + struct Curl_easy *data, + OM_uint32 *minor_status, + gss_ctx_id_t *context, + gss_name_t target_name, + gss_OID mech_type, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_buffer_t output_token, + const bool mutual_auth, + OM_uint32 *ret_flags) +{ + OM_uint32 req_flags = GSS_C_REPLAY_FLAG; + + if(mutual_auth) + req_flags |= GSS_C_MUTUAL_FLAG; + + if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) { +#ifdef GSS_C_DELEG_POLICY_FLAG + req_flags |= GSS_C_DELEG_POLICY_FLAG; +#else + infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not " + "compiled in\n"); +#endif + } + + if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG) + req_flags |= GSS_C_DELEG_FLAG; + + return gss_init_sec_context(minor_status, + GSS_C_NO_CREDENTIAL, /* cred_handle */ + context, + target_name, + mech_type, + req_flags, + 0, /* time_req */ + input_chan_bindings, + input_token, + NULL, /* actual_mech_type */ + output_token, + ret_flags, + NULL /* time_rec */); +} + +#define GSS_LOG_BUFFER_LEN 1024 +static size_t display_gss_error(OM_uint32 status, int type, + char *buf, size_t len) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + + do { + maj_stat = gss_display_status(&min_stat, + status, + type, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) { + len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len, + "%.*s. ", (int)status_string.length, + (char *)status_string.value); + } + gss_release_buffer(&min_stat, &status_string); + } while(!GSS_ERROR(maj_stat) && msg_ctx != 0); + + return len; +} + +/* + * Curl_gss_log_error() + * + * This is used to log a GSS-API error status. + * + * Parameters: + * + * data [in] - The session handle. + * prefix [in] - The prefix of the log message. + * major [in] - The major status code. + * minor [in] - The minor status code. + */ +void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, + OM_uint32 major, OM_uint32 minor) +{ + char buf[GSS_LOG_BUFFER_LEN]; + size_t len = 0; + + if(major != GSS_S_FAILURE) + len = display_gss_error(major, GSS_C_GSS_CODE, buf, len); + + display_gss_error(minor, GSS_C_MECH_CODE, buf, len); + + infof(data, "%s%s\n", prefix, buf); +} + +#endif /* HAVE_GSSAPI */ diff --git a/libcurl/lib/curl_gssapi.h b/libcurl/lib/curl_gssapi.h new file mode 100644 index 0000000..88f68db --- /dev/null +++ b/libcurl/lib/curl_gssapi.h @@ -0,0 +1,61 @@ +#ifndef HEADER_CURL_GSSAPI_H +#define HEADER_CURL_GSSAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2011 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +#ifdef HAVE_GSSAPI +extern gss_OID_desc Curl_spnego_mech_oid; +extern gss_OID_desc Curl_krb5_mech_oid; + +/* Common method for using GSS-API */ +OM_uint32 Curl_gss_init_sec_context( + struct Curl_easy *data, + OM_uint32 *minor_status, + gss_ctx_id_t *context, + gss_name_t target_name, + gss_OID mech_type, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_buffer_t output_token, + const bool mutual_auth, + OM_uint32 *ret_flags); + +/* Helper to log a GSS-API error status */ +void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, + OM_uint32 major, OM_uint32 minor); + +/* Provide some definitions missing in old headers */ +#ifdef HAVE_OLD_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#define NCOMPAT 1 +#endif + +/* Define our privacy and integrity protection values */ +#define GSSAUTH_P_NONE 1 +#define GSSAUTH_P_INTEGRITY 2 +#define GSSAUTH_P_PRIVACY 4 + +#endif /* HAVE_GSSAPI */ +#endif /* HEADER_CURL_GSSAPI_H */ diff --git a/libcurl/lib/curl_hmac.h b/libcurl/lib/curl_hmac.h new file mode 100644 index 0000000..756dc9e --- /dev/null +++ b/libcurl/lib/curl_hmac.h @@ -0,0 +1,67 @@ +#ifndef HEADER_CURL_HMAC_H +#define HEADER_CURL_HMAC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +typedef void (* HMAC_hinit_func)(void *context); +typedef void (* HMAC_hupdate_func)(void *context, + const unsigned char *data, + unsigned int len); +typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context); + + +/* Per-hash function HMAC parameters. */ + +typedef struct { + HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */ + HMAC_hupdate_func hmac_hupdate; /* Update context with data. */ + HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */ + unsigned int hmac_ctxtsize; /* Context structure size. */ + unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */ + unsigned int hmac_resultlen; /* Result length (bytes). */ +} HMAC_params; + + +/* HMAC computation context. */ + +typedef struct { + const HMAC_params *hmac_hash; /* Hash function definition. */ + void *hmac_hashctxt1; /* Hash function context 1. */ + void *hmac_hashctxt2; /* Hash function context 2. */ +} HMAC_context; + + +/* Prototypes. */ + +HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams, + const unsigned char *key, + unsigned int keylen); +int Curl_HMAC_update(HMAC_context *context, + const unsigned char *data, + unsigned int len); +int Curl_HMAC_final(HMAC_context *context, unsigned char *result); + +#endif + +#endif /* HEADER_CURL_HMAC_H */ diff --git a/libcurl/lib/curl_ldap.h b/libcurl/lib/curl_ldap.h new file mode 100644 index 0000000..94c0029 --- /dev/null +++ b/libcurl/lib/curl_ldap.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_LDAP_H +#define HEADER_CURL_LDAP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_LDAP +extern const struct Curl_handler Curl_handler_ldap; + +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) +extern const struct Curl_handler Curl_handler_ldaps; +#endif + +#endif +#endif /* HEADER_CURL_LDAP_H */ diff --git a/libcurl/lib/curl_md4.h b/libcurl/lib/curl_md4.h new file mode 100644 index 0000000..392203f --- /dev/null +++ b/libcurl/lib/curl_md4.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_MD4_H +#define HEADER_CURL_MD4_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ + (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \ + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) + +void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len); + +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) || + (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */ + +#endif /* HEADER_CURL_MD4_H */ diff --git a/libcurl/lib/curl_md5.h b/libcurl/lib/curl_md5.h new file mode 100644 index 0000000..aaf25f6 --- /dev/null +++ b/libcurl/lib/curl_md5.h @@ -0,0 +1,63 @@ +#ifndef HEADER_CURL_MD5_H +#define HEADER_CURL_MD5_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH +#include "curl_hmac.h" + +#define MD5_DIGEST_LEN 16 + +typedef void (* Curl_MD5_init_func)(void *context); +typedef void (* Curl_MD5_update_func)(void *context, + const unsigned char *data, + unsigned int len); +typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context); + +typedef struct { + Curl_MD5_init_func md5_init_func; /* Initialize context procedure */ + Curl_MD5_update_func md5_update_func; /* Update context with data */ + Curl_MD5_final_func md5_final_func; /* Get final result procedure */ + unsigned int md5_ctxtsize; /* Context structure size */ + unsigned int md5_resultlen; /* Result length (bytes) */ +} MD5_params; + +typedef struct { + const MD5_params *md5_hash; /* Hash function definition */ + void *md5_hashctx; /* Hash function context */ +} MD5_context; + +extern const MD5_params Curl_DIGEST_MD5[1]; +extern const HMAC_params Curl_HMAC_MD5[1]; + +void Curl_md5it(unsigned char *output, + const unsigned char *input); + +MD5_context * Curl_MD5_init(const MD5_params *md5params); +CURLcode Curl_MD5_update(MD5_context *context, + const unsigned char *data, + unsigned int len); +CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result); + +#endif + +#endif /* HEADER_CURL_MD5_H */ diff --git a/libcurl/lib/curl_memory.h b/libcurl/lib/curl_memory.h new file mode 100644 index 0000000..ce38a08 --- /dev/null +++ b/libcurl/lib/curl_memory.h @@ -0,0 +1,156 @@ +#ifndef HEADER_CURL_MEMORY_H +#define HEADER_CURL_MEMORY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Nasty internal details ahead... + * + * File curl_memory.h must be included by _all_ *.c source files + * that use memory related functions strdup, malloc, calloc, realloc + * or free, and given source file is used to build libcurl library. + * It should be included immediately before memdebug.h as the last files + * included to avoid undesired interaction with other memory function + * headers in dependent libraries. + * + * There is nearly no exception to above rule. All libcurl source + * files in 'lib' subdirectory as well as those living deep inside + * 'packages' subdirectories and linked together in order to build + * libcurl library shall follow it. + * + * File lib/strdup.c is an exception, given that it provides a strdup + * clone implementation while using malloc. Extra care needed inside + * this one. + * + * The need for curl_memory.h inclusion is due to libcurl's feature + * of allowing library user to provide memory replacement functions, + * memory callbacks, at runtime with curl_global_init_mem() + * + * Any *.c source file used to build libcurl library that does not + * include curl_memory.h and uses any memory function of the five + * mentioned above will compile without any indication, but it will + * trigger weird memory related issues at runtime. + * + * OTOH some source files from 'lib' subdirectory may additionally be + * used directly as source code when using some curlx_ functions by + * third party programs that don't even use libcurl at all. When using + * these source files in this way it is necessary these are compiled + * with CURLX_NO_MEMORY_CALLBACKS defined, in order to ensure that no + * attempt of calling libcurl's memory callbacks is done from code + * which can not use this machinery. + * + * Notice that libcurl's 'memory tracking' system works chaining into + * the memory callback machinery. This implies that when compiling + * 'lib' source files with CURLX_NO_MEMORY_CALLBACKS defined this file + * disengages usage of libcurl's 'memory tracking' system, defining + * MEMDEBUG_NODEFINES and overriding CURLDEBUG purpose. + * + * CURLX_NO_MEMORY_CALLBACKS takes precedence over CURLDEBUG. This is + * done in order to allow building a 'memory tracking' enabled libcurl + * and at the same time allow building programs which do not use it. + * + * Programs and libraries in 'tests' subdirectories have specific + * purposes and needs, and as such each one will use whatever fits + * best, depending additionally whether it links with libcurl or not. + * + * Caveat emptor. Proper curlx_* separation is a work in progress + * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may + * still be required. IOW don't use them yet, there are sharp edges. + */ + +#ifdef HEADER_CURL_MEMDEBUG_H +#error "Header memdebug.h shall not be included before curl_memory.h" +#endif + +#ifndef CURLX_NO_MEMORY_CALLBACKS + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS /* only if not already done */ +/* + * The following memory function replacement typedef's are COPIED from + * curl/curl.h and MUST match the originals. We copy them to avoid having to + * include curl/curl.h here. We avoid that include since it includes stdio.h + * and other headers that may get messed up with defines done here. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +extern curl_malloc_callback Curl_cmalloc; +extern curl_free_callback Curl_cfree; +extern curl_realloc_callback Curl_crealloc; +extern curl_strdup_callback Curl_cstrdup; +extern curl_calloc_callback Curl_ccalloc; +#if defined(WIN32) && defined(UNICODE) +extern curl_wcsdup_callback Curl_cwcsdup; +#endif + +#ifndef CURLDEBUG + +/* + * libcurl's 'memory tracking' system defines strdup, malloc, calloc, + * realloc and free, along with others, in memdebug.h in a different + * way although still using memory callbacks forward declared above. + * When using the 'memory tracking' system (CURLDEBUG defined) we do + * not define here the five memory functions given that definitions + * from memdebug.h are the ones that shall be used. + */ + +#undef strdup +#define strdup(ptr) Curl_cstrdup(ptr) +#undef malloc +#define malloc(size) Curl_cmalloc(size) +#undef calloc +#define calloc(nbelem,size) Curl_ccalloc(nbelem, size) +#undef realloc +#define realloc(ptr,size) Curl_crealloc(ptr, size) +#undef free +#define free(ptr) Curl_cfree(ptr) + +#ifdef WIN32 +# ifdef UNICODE +# undef wcsdup +# define wcsdup(ptr) Curl_cwcsdup(ptr) +# undef _wcsdup +# define _wcsdup(ptr) Curl_cwcsdup(ptr) +# undef _tcsdup +# define _tcsdup(ptr) Curl_cwcsdup(ptr) +# else +# undef _tcsdup +# define _tcsdup(ptr) Curl_cstrdup(ptr) +# endif +#endif + +#endif /* CURLDEBUG */ + +#else /* CURLX_NO_MEMORY_CALLBACKS */ + +#ifndef MEMDEBUG_NODEFINES +#define MEMDEBUG_NODEFINES +#endif + +#endif /* CURLX_NO_MEMORY_CALLBACKS */ + +#endif /* HEADER_CURL_MEMORY_H */ diff --git a/libcurl/lib/curl_memrchr.c b/libcurl/lib/curl_memrchr.c new file mode 100644 index 0000000..eeb3044 --- /dev/null +++ b/libcurl/lib/curl_memrchr.c @@ -0,0 +1,62 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "curl_memrchr.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef HAVE_MEMRCHR + +/* + * Curl_memrchr() + * + * Our memrchr() function clone for systems which lack this function. The + * memrchr() function is like the memchr() function, except that it searches + * backwards from the end of the n bytes pointed to by s instead of forward + * from the beginning. + */ + +void * +Curl_memrchr(const void *s, int c, size_t n) +{ + if(n > 0) { + const unsigned char *p = s; + const unsigned char *q = s; + + p += n - 1; + + while(p >= q) { + if(*p == (unsigned char)c) + return (void *)p; + p--; + } + } + return NULL; +} + +#endif /* HAVE_MEMRCHR */ diff --git a/libcurl/lib/curl_memrchr.h b/libcurl/lib/curl_memrchr.h new file mode 100644 index 0000000..747509c --- /dev/null +++ b/libcurl/lib/curl_memrchr.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_MEMRCHR_H +#define HEADER_CURL_MEMRCHR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_MEMRCHR + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#else /* HAVE_MEMRCHR */ + +void *Curl_memrchr(const void *s, int c, size_t n); + +#define memrchr(x,y,z) Curl_memrchr((x),(y),(z)) + +#endif /* HAVE_MEMRCHR */ + +#endif /* HEADER_CURL_MEMRCHR_H */ diff --git a/libcurl/lib/curl_multibyte.c b/libcurl/lib/curl_multibyte.c new file mode 100644 index 0000000..e48334f --- /dev/null +++ b/libcurl/lib/curl_multibyte.c @@ -0,0 +1,84 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP)) && defined(UNICODE)) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +#include "curl_multibyte.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8) +{ + wchar_t *str_w = NULL; + + if(str_utf8) { + int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str_utf8, -1, NULL, 0); + if(str_w_len > 0) { + str_w = malloc(str_w_len * sizeof(wchar_t)); + if(str_w) { + if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w, + str_w_len) == 0) { + free(str_w); + return NULL; + } + } + } + } + + return str_w; +} + +char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w) +{ + char *str_utf8 = NULL; + + if(str_w) { + int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, + NULL, 0, NULL, NULL); + if(bytes > 0) { + str_utf8 = malloc(bytes); + if(str_utf8) { + if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes, + NULL, NULL) == 0) { + free(str_utf8); + return NULL; + } + } + } + } + + return str_utf8; +} + +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ diff --git a/libcurl/lib/curl_multibyte.h b/libcurl/lib/curl_multibyte.h new file mode 100644 index 0000000..615f5c0 --- /dev/null +++ b/libcurl/lib/curl_multibyte.h @@ -0,0 +1,92 @@ +#ifndef HEADER_CURL_MULTIBYTE_H +#define HEADER_CURL_MULTIBYTE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP)) && defined(UNICODE)) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8); +char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w); + +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ + + +#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP) + +/* + * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8() + * and Curl_unicodefree() main purpose is to minimize the number of + * preprocessor conditional directives needed by code using these + * to differentiate UNICODE from non-UNICODE builds. + * + * When building with UNICODE defined, this two macros + * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() + * return a pointer to a newly allocated memory area holding result. + * When the result is no longer needed, allocated memory is intended + * to be free'ed with Curl_unicodefree(). + * + * When building without UNICODE defined, this macros + * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() + * return the pointer received as argument. Curl_unicodefree() does + * no actual free'ing of this pointer it is simply set to NULL. + */ + +#ifdef UNICODE + +#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr)) +#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr)) +#define Curl_unicodefree(ptr) \ + do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE + +typedef union { + unsigned short *tchar_ptr; + const unsigned short *const_tchar_ptr; + unsigned short *tbyte_ptr; + const unsigned short *const_tbyte_ptr; +} xcharp_u; + +#else + +#define Curl_convert_UTF8_to_tchar(ptr) (ptr) +#define Curl_convert_tchar_to_UTF8(ptr) (ptr) +#define Curl_unicodefree(ptr) \ + do {(ptr) = NULL;} WHILE_FALSE + +typedef union { + char *tchar_ptr; + const char *const_tchar_ptr; + unsigned char *tbyte_ptr; + const unsigned char *const_tbyte_ptr; +} xcharp_u; + +#endif /* UNICODE */ + +#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */ + +#endif /* HEADER_CURL_MULTIBYTE_H */ diff --git a/libcurl/lib/curl_ntlm_core.c b/libcurl/lib/curl_ntlm_core.c new file mode 100644 index 0000000..9e6fdca --- /dev/null +++ b/libcurl/lib/curl_ntlm_core.c @@ -0,0 +1,823 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) + +/* + * NTLM details: + * + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html + */ + +/* Please keep the SSL backend-specific #if branches in this order: + + 1. USE_OPENSSL + 2. USE_GNUTLS_NETTLE + 3. USE_GNUTLS + 4. USE_NSS + 5. USE_MBEDTLS + 6. USE_SECTRANSP + 7. USE_OS400CRYPTO + 8. USE_WIN32_CRYPTO + + This ensures that: + - the same SSL branch gets activated throughout this source + file even if multiple backends are enabled at the same time. + - OpenSSL and NSS have higher priority than Windows Crypt, due + to issues with the latter supporting NTLM2Session responses + in NTLM type-3 messages. + */ + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#ifdef USE_OPENSSL + +# include +# ifndef OPENSSL_NO_MD4 +# include +# else +# include "curl_md4.h" +# endif +# include +# include +# include +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) +# define DES_key_schedule des_key_schedule +# define DES_cblock des_cblock +# define DES_set_odd_parity des_set_odd_parity +# define DES_set_key des_set_key +# define DES_ecb_encrypt des_ecb_encrypt +# define DESKEY(x) x +# define DESKEYARG(x) x +# else +# define DESKEYARG(x) *x +# define DESKEY(x) &x +# endif + +#elif defined(USE_GNUTLS_NETTLE) + +# include +# include + +#elif defined(USE_GNUTLS) + +# include +# define MD5_DIGEST_LENGTH 16 +# define MD4_DIGEST_LENGTH 16 + +#elif defined(USE_NSS) + +# include +# include +# include +# include "curl_md4.h" +# define MD5_DIGEST_LENGTH MD5_LENGTH + +#elif defined(USE_MBEDTLS) + +# include +# include +# if !defined(MBEDTLS_MD4_C) +# include "curl_md4.h" +# endif + +#elif defined(USE_SECTRANSP) + +# include +# include + +#elif defined(USE_OS400CRYPTO) +# include "cipher.mih" /* mih/cipher */ +# include "curl_md4.h" +#elif defined(USE_WIN32_CRYPTO) +# include +#else +# error "Can't compile NTLM support without a crypto library." +#endif + +#include "urldata.h" +#include "non-ascii.h" +#include "strcase.h" +#include "curl_ntlm_core.h" +#include "curl_md5.h" +#include "curl_hmac.h" +#include "warnless.h" +#include "curl_endian.h" +#include "curl_des.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define NTLM_HMAC_MD5_LEN (16) +#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" +#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) + +/* +* Turns a 56-bit key into being 64-bit wide. +*/ +static void extend_key_56_to_64(const unsigned char *key_56, char *key) +{ + key[0] = key_56[0]; + key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); + key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); + key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); + key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); + key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); + key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); + key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); +} + +#ifdef USE_OPENSSL +/* + * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The + * key schedule ks is also set. + */ +static void setup_des_key(const unsigned char *key_56, + DES_key_schedule DESKEYARG(ks)) +{ + DES_cblock key; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, (char *) &key); + + /* Set the key parity to odd */ + DES_set_odd_parity(&key); + + /* Set the key */ + DES_set_key(&key, ks); +} + +#elif defined(USE_GNUTLS_NETTLE) + +static void setup_des_key(const unsigned char *key_56, + struct des_ctx *des) +{ + char key[8]; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Set the key */ + des_set_key(des, (const uint8_t *) key); +} + +#elif defined(USE_GNUTLS) + +/* + * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. + */ +static void setup_des_key(const unsigned char *key_56, + gcry_cipher_hd_t *des) +{ + char key[8]; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Set the key */ + gcry_cipher_setkey(*des, key, sizeof(key)); +} + +#elif defined(USE_NSS) + +/* + * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using + * the expanded key. The caller is responsible for giving 64 bit of valid + * data is IN and (at least) 64 bit large buffer as OUT. + */ +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */ + char key[8]; /* expanded 64 bit key */ + SECItem key_item; + PK11SymKey *symkey = NULL; + SECItem *param = NULL; + PK11Context *ctx = NULL; + int out_len; /* not used, required by NSS */ + bool rv = FALSE; + + /* use internal slot for DES encryption (requires NSS to be initialized) */ + PK11SlotInfo *slot = PK11_GetInternalKeySlot(); + if(!slot) + return FALSE; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Import the key */ + key_item.data = (unsigned char *)key; + key_item.len = sizeof(key); + symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT, + &key_item, NULL); + if(!symkey) + goto fail; + + /* Create the DES encryption context */ + param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL); + if(!param) + goto fail; + ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param); + if(!ctx) + goto fail; + + /* Perform the encryption */ + if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8, + (unsigned char *)in, /* inbuflen */ 8) + && SECSuccess == PK11_Finalize(ctx)) + rv = /* all OK */ TRUE; + +fail: + /* cleanup */ + if(ctx) + PK11_DestroyContext(ctx, PR_TRUE); + if(symkey) + PK11_FreeSymKey(symkey); + if(param) + SECITEM_FreeItem(param, PR_TRUE); + PK11_FreeSlot(slot); + return rv; +} + +#elif defined(USE_MBEDTLS) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + mbedtls_des_context ctx; + char key[8]; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + mbedtls_des_key_set_parity((unsigned char *) key); + + /* Perform the encryption */ + mbedtls_des_init(&ctx); + mbedtls_des_setkey_enc(&ctx, (unsigned char *) key); + return mbedtls_des_crypt_ecb(&ctx, in, out) == 0; +} + +#elif defined(USE_SECTRANSP) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + char key[8]; + size_t out_len; + CCCryptorStatus err; + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + + /* Perform the encryption */ + err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key, + kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out, + 8 /* outbuflen */, &out_len); + + return err == kCCSuccess; +} + +#elif defined(USE_OS400CRYPTO) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + char key[8]; + _CIPHER_Control_T ctl; + + /* Setup the cipher control structure */ + ctl.Func_ID = ENCRYPT_ONLY; + ctl.Data_Len = sizeof(key); + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, ctl.Crypto_Key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len); + + /* Perform the encryption */ + _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in); + + return TRUE; +} + +#elif defined(USE_WIN32_CRYPTO) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + HCRYPTPROV hprov; + HCRYPTKEY hkey; + struct { + BLOBHEADER hdr; + unsigned int len; + char key[8]; + } blob; + DWORD len = 8; + + /* Acquire the crypto provider */ + if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + return FALSE; + + /* Setup the key blob structure */ + memset(&blob, 0, sizeof(blob)); + blob.hdr.bType = PLAINTEXTKEYBLOB; + blob.hdr.bVersion = 2; + blob.hdr.aiKeyAlg = CALG_DES; + blob.len = sizeof(blob.key); + + /* Expand the 56-bit key to 64-bits */ + extend_key_56_to_64(key_56, blob.key); + + /* Set the key parity to odd */ + Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key)); + + /* Import the key */ + if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) { + CryptReleaseContext(hprov, 0); + + return FALSE; + } + + memcpy(out, in, 8); + + /* Perform the encryption */ + CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len); + + CryptDestroyKey(hkey); + CryptReleaseContext(hprov, 0); + + return TRUE; +} + +#endif /* defined(USE_WIN32_CRYPTO) */ + + /* + * takes a 21 byte array and treats it as 3 56-bit DES keys. The + * 8 byte plaintext is encrypted with each key and the resulting 24 + * bytes are stored in the results array. + */ +void Curl_ntlm_core_lm_resp(const unsigned char *keys, + const unsigned char *plaintext, + unsigned char *results) +{ +#ifdef USE_OPENSSL + DES_key_schedule ks; + + setup_des_key(keys, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(keys + 7, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8), + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(keys + 14, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16), + DESKEY(ks), DES_ENCRYPT); +#elif defined(USE_GNUTLS_NETTLE) + struct des_ctx des; + setup_des_key(keys, &des); + des_encrypt(&des, 8, results, plaintext); + setup_des_key(keys + 7, &des); + des_encrypt(&des, 8, results + 8, plaintext); + setup_des_key(keys + 14, &des); + des_encrypt(&des, 8, results + 16, plaintext); +#elif defined(USE_GNUTLS) + gcry_cipher_hd_t des; + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys, &des); + gcry_cipher_encrypt(des, results, 8, plaintext, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys + 7, &des); + gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(keys + 14, &des); + gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8); + gcry_cipher_close(des); +#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ + || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) + encrypt_des(plaintext, results, keys); + encrypt_des(plaintext, results + 8, keys + 7); + encrypt_des(plaintext, results + 16, keys + 14); +#endif +} + +/* + * Set up lanmanager hashed password + */ +CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, + const char *password, + unsigned char *lmbuffer /* 21 bytes */) +{ + CURLcode result; + unsigned char pw[14]; + static const unsigned char magic[] = { + 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ + }; + size_t len = CURLMIN(strlen(password), 14); + + Curl_strntoupper((char *)pw, password, len); + memset(&pw[len], 0, 14 - len); + + /* + * The LanManager hashed password needs to be created using the + * password in the network encoding not the host encoding. + */ + result = Curl_convert_to_network(data, (char *)pw, 14); + if(result) + return result; + + { + /* Create LanManager hashed password. */ + +#ifdef USE_OPENSSL + DES_key_schedule ks; + + setup_des_key(pw, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer, + DESKEY(ks), DES_ENCRYPT); + + setup_des_key(pw + 7, DESKEY(ks)); + DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8), + DESKEY(ks), DES_ENCRYPT); +#elif defined(USE_GNUTLS_NETTLE) + struct des_ctx des; + setup_des_key(pw, &des); + des_encrypt(&des, 8, lmbuffer, magic); + setup_des_key(pw + 7, &des); + des_encrypt(&des, 8, lmbuffer + 8, magic); +#elif defined(USE_GNUTLS) + gcry_cipher_hd_t des; + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(pw, &des); + gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8); + gcry_cipher_close(des); + + gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); + setup_des_key(pw + 7, &des); + gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8); + gcry_cipher_close(des); +#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ + || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) + encrypt_des(magic, lmbuffer, pw); + encrypt_des(magic, lmbuffer + 8, pw + 7); +#endif + + memset(lmbuffer + 16, 0, 21 - 16); + } + + return CURLE_OK; +} + +#ifdef USE_NTRESPONSES +static void ascii_to_unicode_le(unsigned char *dest, const char *src, + size_t srclen) +{ + size_t i; + for(i = 0; i < srclen; i++) { + dest[2 * i] = (unsigned char)src[i]; + dest[2 * i + 1] = '\0'; + } +} + +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) + +static void ascii_uppercase_to_unicode_le(unsigned char *dest, + const char *src, size_t srclen) +{ + size_t i; + for(i = 0; i < srclen; i++) { + dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i])); + dest[2 * i + 1] = '\0'; + } +} + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +/* + * Set up nt hashed passwords + * @unittest: 1600 + */ +CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, + const char *password, + unsigned char *ntbuffer /* 21 bytes */) +{ + size_t len = strlen(password); + unsigned char *pw; + CURLcode result; + if(len > SIZE_T_MAX/2) /* avoid integer overflow */ + return CURLE_OUT_OF_MEMORY; + pw = len ? malloc(len * 2) : strdup(""); + if(!pw) + return CURLE_OUT_OF_MEMORY; + + ascii_to_unicode_le(pw, password, len); + + /* + * The NT hashed password needs to be created using the password in the + * network encoding not the host encoding. + */ + result = Curl_convert_to_network(data, (char *)pw, len * 2); + if(result) + return result; + + { + /* Create NT hashed password. */ +#ifdef USE_OPENSSL +#if !defined(OPENSSL_NO_MD4) + MD4_CTX MD4pw; + MD4_Init(&MD4pw); + MD4_Update(&MD4pw, pw, 2 * len); + MD4_Final(ntbuffer, &MD4pw); +#else + Curl_md4it(ntbuffer, pw, 2 * len); +#endif +#elif defined(USE_GNUTLS_NETTLE) + struct md4_ctx MD4pw; + md4_init(&MD4pw); + md4_update(&MD4pw, (unsigned int)(2 * len), pw); + md4_digest(&MD4pw, MD4_DIGEST_SIZE, ntbuffer); +#elif defined(USE_GNUTLS) + gcry_md_hd_t MD4pw; + gcry_md_open(&MD4pw, GCRY_MD_MD4, 0); + gcry_md_write(MD4pw, pw, 2 * len); + memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH); + gcry_md_close(MD4pw); +#elif defined(USE_NSS) + Curl_md4it(ntbuffer, pw, 2 * len); +#elif defined(USE_MBEDTLS) +#if defined(MBEDTLS_MD4_C) + mbedtls_md4(pw, 2 * len, ntbuffer); +#else + Curl_md4it(ntbuffer, pw, 2 * len); +#endif +#elif defined(USE_SECTRANSP) + (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer); +#elif defined(USE_OS400CRYPTO) + Curl_md4it(ntbuffer, pw, 2 * len); +#elif defined(USE_WIN32_CRYPTO) + HCRYPTPROV hprov; + if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + HCRYPTHASH hhash; + if(CryptCreateHash(hprov, CALG_MD4, 0, 0, &hhash)) { + DWORD length = 16; + CryptHashData(hhash, pw, (unsigned int)len * 2, 0); + CryptGetHashParam(hhash, HP_HASHVAL, ntbuffer, &length, 0); + CryptDestroyHash(hhash); + } + CryptReleaseContext(hprov, 0); + } +#endif + + memset(ntbuffer + 16, 0, 21 - 16); + } + + free(pw); + + return CURLE_OK; +} + +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) + +/* This returns the HMAC MD5 digest */ +static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output) +{ + HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen); + + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + /* Update the digest with the given challenge */ + Curl_HMAC_update(ctxt, data, datalen); + + /* Finalise the digest */ + Curl_HMAC_final(ctxt, output); + + return CURLE_OK; +} + +/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode + * (uppercase UserName + Domain) as the data + */ +CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, + const char *domain, size_t domlen, + unsigned char *ntlmhash, + unsigned char *ntlmv2hash) +{ + /* Unicode representation */ + size_t identity_len; + unsigned char *identity; + CURLcode result = CURLE_OK; + + /* we do the length checks below separately to avoid integer overflow risk + on extreme data lengths */ + if((userlen > SIZE_T_MAX/2) || + (domlen > SIZE_T_MAX/2) || + ((userlen + domlen) > SIZE_T_MAX/2)) + return CURLE_OUT_OF_MEMORY; + + identity_len = (userlen + domlen) * 2; + identity = malloc(identity_len); + + if(!identity) + return CURLE_OUT_OF_MEMORY; + + ascii_uppercase_to_unicode_le(identity, user, userlen); + ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); + + result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), + ntlmv2hash); + free(identity); + + return result; +} + +/* + * Curl_ntlm_core_mk_ntlmv2_resp() + * + * This creates the NTLMv2 response as set in the ntlm type-3 message. + * + * Parameters: + * + * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) + * challenge_client [in] - The client nonce (8 bytes) + * ntlm [in] - The ntlm data struct being used to read TargetInfo + and Server challenge received in the type-2 message + * ntresp [out] - The address where a pointer to newly allocated + * memory holding the NTLMv2 response. + * ntresp_len [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + struct ntlmdata *ntlm, + unsigned char **ntresp, + unsigned int *ntresp_len) +{ +/* NTLMv2 response structure : +------------------------------------------------------------------------------ +0 HMAC MD5 16 bytes +------BLOB-------------------------------------------------------------------- +16 Signature 0x01010000 +20 Reserved long (0x00000000) +24 Timestamp LE, 64-bit signed value representing the number of + tenths of a microsecond since January 1, 1601. +32 Client Nonce 8 bytes +40 Unknown 4 bytes +44 Target Info N bytes (from the type-2 message) +44+N Unknown 4 bytes +------------------------------------------------------------------------------ +*/ + + unsigned int len = 0; + unsigned char *ptr = NULL; + unsigned char hmac_output[NTLM_HMAC_MD5_LEN]; + curl_off_t tw; + + CURLcode result = CURLE_OK; + +#if CURL_SIZEOF_CURL_OFF_T < 8 +#error "this section needs 64bit support to work" +#endif + + /* Calculate the timestamp */ +#ifdef DEBUGBUILD + char *force_timestamp = getenv("CURL_FORCETIME"); + if(force_timestamp) + tw = CURL_OFF_T_C(11644473600) * 10000000; + else +#endif + tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000; + + /* Calculate the response len */ + len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN; + + /* Allocate the response */ + ptr = calloc(1, len); + if(!ptr) + return CURLE_OUT_OF_MEMORY; + + /* Create the BLOB structure */ + msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN, + "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ + "%c%c%c%c", /* Reserved = 0 */ + NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1], + NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3], + 0, 0, 0, 0); + + Curl_write64_le(tw, ptr + 24); + memcpy(ptr + 32, challenge_client, 8); + memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); + + /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ + memcpy(ptr + 8, &ntlm->nonce[0], 8); + result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, + NTLMv2_BLOB_LEN + 8, hmac_output); + if(result) { + free(ptr); + return result; + } + + /* Concatenate the HMAC MD5 output with the BLOB */ + memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN); + + /* Return the response */ + *ntresp = ptr; + *ntresp_len = len; + + return result; +} + +/* + * Curl_ntlm_core_mk_lmv2_resp() + * + * This creates the LMv2 response as used in the ntlm type-3 message. + * + * Parameters: + * + * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) + * challenge_client [in] - The client nonce (8 bytes) + * challenge_client [in] - The server challenge (8 bytes) + * lmresp [out] - The LMv2 response (24 bytes) + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp) +{ + unsigned char data[16]; + unsigned char hmac_output[16]; + CURLcode result = CURLE_OK; + + memcpy(&data[0], challenge_server, 8); + memcpy(&data[8], challenge_client, 8); + + result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); + if(result) + return result; + + /* Concatenate the HMAC MD5 output with the client nonce */ + memcpy(lmresp, hmac_output, 16); + memcpy(lmresp + 16, challenge_client, 8); + + return result; +} + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +#endif /* USE_NTRESPONSES */ + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* USE_NTLM */ diff --git a/libcurl/lib/curl_ntlm_core.h b/libcurl/lib/curl_ntlm_core.h new file mode 100644 index 0000000..3b4b805 --- /dev/null +++ b/libcurl/lib/curl_ntlm_core.h @@ -0,0 +1,105 @@ +#ifndef HEADER_CURL_NTLM_CORE_H +#define HEADER_CURL_NTLM_CORE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) + +/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c) + then it must be initialized to be used by NTLM. */ +#if !defined(USE_OPENSSL) && \ + !defined(USE_GNUTLS_NETTLE) && \ + !defined(USE_GNUTLS) && \ + defined(USE_NSS) +#define NTLM_NEEDS_NSS_INIT +#endif + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#ifdef USE_OPENSSL +# include +#endif + +/* Define USE_NTRESPONSES in order to make the type-3 message include + * the NT response message. */ +#define USE_NTRESPONSES + +/* Define USE_NTLM2SESSION in order to make the type-3 message include the + NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a + Crypto engine that we have curl_ssl_md5sum() for. */ +#if defined(USE_NTRESPONSES) && !defined(USE_WIN32_CRYPTO) +#define USE_NTLM2SESSION +#endif + +/* Define USE_NTLM_V2 in order to allow the type-3 message to include the + LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 + and support for 64-bit integers. */ +#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4) +#define USE_NTLM_V2 +#endif + +void Curl_ntlm_core_lm_resp(const unsigned char *keys, + const unsigned char *plaintext, + unsigned char *results); + +CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, + const char *password, + unsigned char *lmbuffer /* 21 bytes */); + +#ifdef USE_NTRESPONSES +CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, + const char *password, + unsigned char *ntbuffer /* 21 bytes */); + +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) + +CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output); + +CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, + const char *domain, size_t domlen, + unsigned char *ntlmhash, + unsigned char *ntlmv2hash); + +CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + struct ntlmdata *ntlm, + unsigned char **ntresp, + unsigned int *ntresp_len); + +CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp); + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +#endif /* USE_NTRESPONSES */ + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_CURL_NTLM_CORE_H */ diff --git a/libcurl/lib/curl_ntlm_wb.c b/libcurl/lib/curl_ntlm_wb.c new file mode 100644 index 0000000..80266e2 --- /dev/null +++ b/libcurl/lib/curl_ntlm_wb.c @@ -0,0 +1,489 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + +/* + * NTLM details: + * + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "vauth/ntlm.h" +#include "curl_ntlm_core.h" +#include "curl_ntlm_wb.h" +#include "url.h" +#include "strerror.h" +#include "strdup.h" +#include "strcase.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if DEBUG_ME +# define DEBUG_OUT(x) x +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +/* Portable 'sclose_nolog' used only in child process instead of 'sclose' + to avoid fooling the socket leak detector */ +#if defined(HAVE_CLOSESOCKET) +# define sclose_nolog(x) closesocket((x)) +#elif defined(HAVE_CLOSESOCKET_CAMEL) +# define sclose_nolog(x) CloseSocket((x)) +#else +# define sclose_nolog(x) close((x)) +#endif + +void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn) +{ + if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) { + sclose(conn->ntlm_auth_hlpr_socket); + conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; + } + + if(conn->ntlm_auth_hlpr_pid) { + int i; + for(i = 0; i < 4; i++) { + pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG); + if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD) + break; + switch(i) { + case 0: + kill(conn->ntlm_auth_hlpr_pid, SIGTERM); + break; + case 1: + /* Give the process another moment to shut down cleanly before + bringing down the axe */ + Curl_wait_ms(1); + break; + case 2: + kill(conn->ntlm_auth_hlpr_pid, SIGKILL); + break; + case 3: + break; + } + } + conn->ntlm_auth_hlpr_pid = 0; + } + + free(conn->challenge_header); + conn->challenge_header = NULL; + free(conn->response_header); + conn->response_header = NULL; +} + +static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) +{ + curl_socket_t sockfds[2]; + pid_t child_pid; + const char *username; + char *slash, *domain = NULL; + const char *ntlm_auth = NULL; + char *ntlm_auth_alloc = NULL; +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + struct passwd pw, *pw_res; + char pwbuf[1024]; +#endif + char buffer[STRERROR_LEN]; + + /* Return if communication with ntlm_auth already set up */ + if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || + conn->ntlm_auth_hlpr_pid) + return CURLE_OK; + + username = userp; + /* The real ntlm_auth really doesn't like being invoked with an + empty username. It won't make inferences for itself, and expects + the client to do so (mostly because it's really designed for + servers like squid to use for auth, and client support is an + afterthought for it). So try hard to provide a suitable username + if we don't already have one. But if we can't, provide the + empty one anyway. Perhaps they have an implementation of the + ntlm_auth helper which *doesn't* need it so we might as well try */ + if(!username || !username[0]) { + username = getenv("NTLMUSER"); + if(!username || !username[0]) + username = getenv("LOGNAME"); + if(!username || !username[0]) + username = getenv("USER"); +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + if((!username || !username[0]) && + !getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) && + pw_res) { + username = pw.pw_name; + } +#endif + if(!username || !username[0]) + username = userp; + } + slash = strpbrk(username, "\\/"); + if(slash) { + domain = strdup(username); + if(!domain) + return CURLE_OUT_OF_MEMORY; + slash = domain + (slash - username); + *slash = '\0'; + username = username + (slash - domain) + 1; + } + + /* For testing purposes, when DEBUGBUILD is defined and environment + variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform + NTLM challenge/response which only accepts commands and output + strings pre-written in test case definitions */ +#ifdef DEBUGBUILD + ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE"); + if(ntlm_auth_alloc) + ntlm_auth = ntlm_auth_alloc; + else +#endif + ntlm_auth = NTLM_WB_FILE; + + if(access(ntlm_auth, X_OK) != 0) { + failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s", + ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer))); + goto done; + } + + if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { + failf(conn->data, "Could not open socket pair. errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + goto done; + } + + child_pid = fork(); + if(child_pid == -1) { + sclose(sockfds[0]); + sclose(sockfds[1]); + failf(conn->data, "Could not fork. errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + goto done; + } + else if(!child_pid) { + /* + * child process + */ + + /* Don't use sclose in the child since it fools the socket leak detector */ + sclose_nolog(sockfds[0]); + if(dup2(sockfds[1], STDIN_FILENO) == -1) { + failf(conn->data, "Could not redirect child stdin. errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + exit(1); + } + + if(dup2(sockfds[1], STDOUT_FILENO) == -1) { + failf(conn->data, "Could not redirect child stdout. errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + exit(1); + } + + if(domain) + execl(ntlm_auth, ntlm_auth, + "--helper-protocol", "ntlmssp-client-1", + "--use-cached-creds", + "--username", username, + "--domain", domain, + NULL); + else + execl(ntlm_auth, ntlm_auth, + "--helper-protocol", "ntlmssp-client-1", + "--use-cached-creds", + "--username", username, + NULL); + + sclose_nolog(sockfds[1]); + failf(conn->data, "Could not execl(). errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + exit(1); + } + + sclose(sockfds[1]); + conn->ntlm_auth_hlpr_socket = sockfds[0]; + conn->ntlm_auth_hlpr_pid = child_pid; + free(domain); + free(ntlm_auth_alloc); + return CURLE_OK; + +done: + free(domain); + free(ntlm_auth_alloc); + return CURLE_REMOTE_ACCESS_DENIED; +} + +/* if larger than this, something is seriously wrong */ +#define MAX_NTLM_WB_RESPONSE 100000 + +static CURLcode ntlm_wb_response(struct connectdata *conn, + const char *input, curlntlm state) +{ + char *buf = malloc(NTLM_BUFSIZE); + size_t len_in = strlen(input), len_out = 0; + + if(!buf) + return CURLE_OUT_OF_MEMORY; + + while(len_in > 0) { + ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in); + if(written == -1) { + /* Interrupted by a signal, retry it */ + if(errno == EINTR) + continue; + /* write failed if other errors happen */ + goto done; + } + input += written; + len_in -= written; + } + /* Read one line */ + while(1) { + ssize_t size; + char *newbuf; + + size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE); + if(size == -1) { + if(errno == EINTR) + continue; + goto done; + } + else if(size == 0) + goto done; + + len_out += size; + if(buf[len_out - 1] == '\n') { + buf[len_out - 1] = '\0'; + break; + } + + if(len_out > MAX_NTLM_WB_RESPONSE) { + failf(conn->data, "too large ntlm_wb response!"); + free(buf); + return CURLE_OUT_OF_MEMORY; + } + + newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE); + if(!newbuf) + return CURLE_OUT_OF_MEMORY; + + buf = newbuf; + } + + /* Samba/winbind installed but not configured */ + if(state == NTLMSTATE_TYPE1 && + len_out == 3 && + buf[0] == 'P' && buf[1] == 'W') + goto done; + /* invalid response */ + if(len_out < 4) + goto done; + if(state == NTLMSTATE_TYPE1 && + (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' ')) + goto done; + if(state == NTLMSTATE_TYPE2 && + (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') && + (buf[0]!='A' || buf[1]!='F' || buf[2]!=' ')) + goto done; + + conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3); + free(buf); + if(!conn->response_header) + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +done: + free(buf); + return CURLE_REMOTE_ACCESS_DENIED; +} + +CURLcode Curl_input_ntlm_wb(struct connectdata *conn, + bool proxy, + const char *header) +{ + curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state; + + if(!checkprefix("NTLM", header)) + return CURLE_BAD_CONTENT_ENCODING; + + header += strlen("NTLM"); + while(*header && ISSPACE(*header)) + header++; + + if(*header) { + conn->challenge_header = strdup(header); + if(!conn->challenge_header) + return CURLE_OUT_OF_MEMORY; + + *state = NTLMSTATE_TYPE2; /* We got a type-2 message */ + } + else { + if(*state == NTLMSTATE_LAST) { + infof(conn->data, "NTLM auth restarted\n"); + Curl_http_auth_cleanup_ntlm_wb(conn); + } + else if(*state == NTLMSTATE_TYPE3) { + infof(conn->data, "NTLM handshake rejected\n"); + Curl_http_auth_cleanup_ntlm_wb(conn); + *state = NTLMSTATE_NONE; + return CURLE_REMOTE_ACCESS_DENIED; + } + else if(*state >= NTLMSTATE_TYPE1) { + infof(conn->data, "NTLM handshake failure (internal error)\n"); + return CURLE_REMOTE_ACCESS_DENIED; + } + + *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */ + } + + return CURLE_OK; +} + +/* + * This is for creating ntlm header output by delegating challenge/response + * to Samba's winbind daemon helper ntlm_auth. + */ +CURLcode Curl_output_ntlm_wb(struct connectdata *conn, + bool proxy) +{ + /* point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + /* point to the name and password for this */ + const char *userp; + curlntlm *state; + struct auth *authp; + + CURLcode res = CURLE_OK; + char *input; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + + if(proxy) { + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->http_proxy.user; + state = &conn->proxy_ntlm_state; + authp = &conn->data->state.authproxy; + } + else { + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + state = &conn->http_ntlm_state; + authp = &conn->data->state.authhost; + } + authp->done = FALSE; + + /* not set means empty */ + if(!userp) + userp = ""; + + switch(*state) { + case NTLMSTATE_TYPE1: + default: + /* Use Samba's 'winbind' daemon to support NTLM authentication, + * by delegating the NTLM challenge/response protocol to a helper + * in ntlm_auth. + * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html + * https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html + * https://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html + * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this + * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute + * filename of ntlm_auth helper. + * If NTLM authentication using winbind fails, go back to original + * request handling process. + */ + /* Create communication with ntlm_auth */ + res = ntlm_wb_init(conn, userp); + if(res) + return res; + res = ntlm_wb_response(conn, "YR\n", *state); + if(res) + return res; + + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + proxy ? "Proxy-" : "", + conn->response_header); + DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); + free(conn->response_header); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + conn->response_header = NULL; + break; + + case NTLMSTATE_TYPE2: + input = aprintf("TT %s\n", conn->challenge_header); + if(!input) + return CURLE_OUT_OF_MEMORY; + res = ntlm_wb_response(conn, input, *state); + free(input); + input = NULL; + if(res) + return res; + + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + proxy ? "Proxy-" : "", + conn->response_header); + DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); + *state = NTLMSTATE_TYPE3; /* we sent a type-3 */ + authp->done = TRUE; + Curl_http_auth_cleanup_ntlm_wb(conn); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + break; + + case NTLMSTATE_TYPE3: + /* connection is already authenticated, + * don't send a header in future requests */ + *state = NTLMSTATE_LAST; + /* FALLTHROUGH */ + case NTLMSTATE_LAST: + Curl_safefree(*allocuserpwd); + authp->done = TRUE; + break; + } + + return CURLE_OK; +} + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ diff --git a/libcurl/lib/curl_ntlm_wb.h b/libcurl/lib/curl_ntlm_wb.h new file mode 100644 index 0000000..3cf841c --- /dev/null +++ b/libcurl/lib/curl_ntlm_wb.h @@ -0,0 +1,41 @@ +#ifndef HEADER_CURL_NTLM_WB_H +#define HEADER_CURL_NTLM_WB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + +/* this is for ntlm header input */ +CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating ntlm header output */ +CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy); + +void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ + +#endif /* HEADER_CURL_NTLM_WB_H */ diff --git a/libcurl/lib/curl_path.c b/libcurl/lib/curl_path.c new file mode 100644 index 0000000..85dddce --- /dev/null +++ b/libcurl/lib/curl_path.c @@ -0,0 +1,199 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_SSH) + +#include +#include "curl_memory.h" +#include "curl_path.h" +#include "escape.h" +#include "memdebug.h" + +/* figure out the path to work with in this particular request */ +CURLcode Curl_getworkingpath(struct connectdata *conn, + char *homedir, /* when SFTP is used */ + char **path) /* returns the allocated + real path to work with */ +{ + struct Curl_easy *data = conn->data; + char *real_path = NULL; + char *working_path; + size_t working_path_len; + CURLcode result = + Curl_urldecode(data, data->state.up.path, 0, &working_path, + &working_path_len, FALSE); + if(result) + return result; + + /* Check for /~/, indicating relative to the user's home directory */ + if(conn->handler->protocol & CURLPROTO_SCP) { + real_path = malloc(working_path_len + 1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) + /* It is referenced to the home directory, so strip the leading '/~/' */ + memcpy(real_path, working_path + 3, 4 + working_path_len-3); + else + memcpy(real_path, working_path, 1 + working_path_len); + } + else if(conn->handler->protocol & CURLPROTO_SFTP) { + if((working_path_len > 1) && (working_path[1] == '~')) { + size_t homelen = strlen(homedir); + real_path = malloc(homelen + working_path_len + 1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + /* It is referenced to the home directory, so strip the + leading '/' */ + memcpy(real_path, homedir, homelen); + real_path[homelen] = '/'; + real_path[homelen + 1] = '\0'; + if(working_path_len > 3) { + memcpy(real_path + homelen + 1, working_path + 3, + 1 + working_path_len -3); + } + } + else { + real_path = malloc(working_path_len + 1); + if(real_path == NULL) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } + memcpy(real_path, working_path, 1 + working_path_len); + } + } + + free(working_path); + + /* store the pointer for the caller to receive */ + *path = real_path; + + return CURLE_OK; +} + +/* The get_pathname() function is being borrowed from OpenSSH sftp.c + version 4.6p1. */ +/* + * Copyright (c) 2001-2004 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) +{ + const char *cp = *cpp, *end; + char quot; + unsigned int i, j; + size_t fullPathLength, pathLength; + bool relativePath = false; + static const char WHITESPACE[] = " \t\r\n"; + + if(!*cp) { + *cpp = NULL; + *path = NULL; + return CURLE_QUOTE_ERROR; + } + /* Ignore leading whitespace */ + cp += strspn(cp, WHITESPACE); + /* Allocate enough space for home directory and filename + separator */ + fullPathLength = strlen(cp) + strlen(homedir) + 2; + *path = malloc(fullPathLength); + if(*path == NULL) + return CURLE_OUT_OF_MEMORY; + + /* Check for quoted filenames */ + if(*cp == '\"' || *cp == '\'') { + quot = *cp++; + + /* Search for terminating quote, unescape some chars */ + for(i = j = 0; i <= strlen(cp); i++) { + if(cp[i] == quot) { /* Found quote */ + i++; + (*path)[j] = '\0'; + break; + } + if(cp[i] == '\0') { /* End of string */ + /*error("Unterminated quote");*/ + goto fail; + } + if(cp[i] == '\\') { /* Escaped characters */ + i++; + if(cp[i] != '\'' && cp[i] != '\"' && + cp[i] != '\\') { + /*error("Bad escaped character '\\%c'", + cp[i]);*/ + goto fail; + } + } + (*path)[j++] = cp[i]; + } + + if(j == 0) { + /*error("Empty quotes");*/ + goto fail; + } + *cpp = cp + i + strspn(cp + i, WHITESPACE); + } + else { + /* Read to end of filename - either to white space or terminator */ + end = strpbrk(cp, WHITESPACE); + if(end == NULL) + end = strchr(cp, '\0'); + /* return pointer to second parameter if it exists */ + *cpp = end + strspn(end, WHITESPACE); + pathLength = 0; + relativePath = (cp[0] == '/' && cp[1] == '~' && cp[2] == '/'); + /* Handling for relative path - prepend home directory */ + if(relativePath) { + strcpy(*path, homedir); + pathLength = strlen(homedir); + (*path)[pathLength++] = '/'; + (*path)[pathLength] = '\0'; + cp += 3; + } + /* Copy path name up until first "white space" */ + memcpy(&(*path)[pathLength], cp, (int)(end - cp)); + pathLength += (int)(end - cp); + (*path)[pathLength] = '\0'; + } + return CURLE_OK; + + fail: + Curl_safefree(*path); + return CURLE_QUOTE_ERROR; +} + +#endif /* if SSH is used */ diff --git a/libcurl/lib/curl_path.h b/libcurl/lib/curl_path.h new file mode 100644 index 0000000..636c37f --- /dev/null +++ b/libcurl/lib/curl_path.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_PATH_H +#define HEADER_CURL_PATH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "urldata.h" + +#ifdef WIN32 +# undef PATH_MAX +# define PATH_MAX MAX_PATH +# ifndef R_OK +# define R_OK 4 +# endif +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 /* just an extra precaution since there are systems that + have their definition hidden well */ +#endif + +CURLcode Curl_getworkingpath(struct connectdata *conn, + char *homedir, + char **path); + +CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir); +#endif /* HEADER_CURL_PATH_H */ diff --git a/libcurl/lib/curl_printf.h b/libcurl/lib/curl_printf.h new file mode 100644 index 0000000..0d37b8e --- /dev/null +++ b/libcurl/lib/curl_printf.h @@ -0,0 +1,48 @@ +#ifndef HEADER_CURL_PRINTF_H +#define HEADER_CURL_PRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * This header should be included by ALL code in libcurl that uses any + * *rintf() functions. + */ + +#include + +# undef printf +# undef fprintf +# undef msnprintf +# undef vprintf +# undef vfprintf +# undef vsnprintf +# undef aprintf +# undef vaprintf +# define printf curl_mprintf +# define fprintf curl_mfprintf +# define msnprintf curl_msnprintf +# define vprintf curl_mvprintf +# define vfprintf curl_mvfprintf +# define mvsnprintf curl_mvsnprintf +# define aprintf curl_maprintf +# define vaprintf curl_mvaprintf +#endif /* HEADER_CURL_PRINTF_H */ diff --git a/libcurl/lib/curl_range.c b/libcurl/lib/curl_range.c new file mode 100644 index 0000000..aa3c493 --- /dev/null +++ b/libcurl/lib/curl_range.c @@ -0,0 +1,95 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "curl_range.h" +#include "sendf.h" +#include "strtoofft.h" + +/* Only include this function if one or more of FTP, FILE are enabled. */ +#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE) + + /* + Check if this is a range download, and if so, set the internal variables + properly. + */ +CURLcode Curl_range(struct connectdata *conn) +{ + curl_off_t from, to; + char *ptr; + char *ptr2; + struct Curl_easy *data = conn->data; + + if(data->state.use_range && data->state.range) { + CURLofft from_t; + CURLofft to_t; + from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from); + if(from_t == CURL_OFFT_FLOW) + return CURLE_RANGE_ERROR; + while(*ptr && (ISSPACE(*ptr) || (*ptr == '-'))) + ptr++; + to_t = curlx_strtoofft(ptr, &ptr2, 0, &to); + if(to_t == CURL_OFFT_FLOW) + return CURLE_RANGE_ERROR; + if((to_t == CURL_OFFT_INVAL) && !from_t) { + /* X - */ + data->state.resume_from = from; + DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n", + from)); + } + else if((from_t == CURL_OFFT_INVAL) && !to_t) { + /* -Y */ + data->req.maxdownload = to; + data->state.resume_from = -to; + DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n", + to)); + } + else { + /* X-Y */ + curl_off_t totalsize; + + /* Ensure the range is sensible - to should follow from. */ + if(from > to) + return CURLE_RANGE_ERROR; + + totalsize = to - from; + if(totalsize == CURL_OFF_T_MAX) + return CURLE_RANGE_ERROR; + + data->req.maxdownload = totalsize + 1; /* include last byte */ + data->state.resume_from = from; + DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T + " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n", + from, data->req.maxdownload)); + } + DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T + " to %" CURL_FORMAT_CURL_OFF_T ", totally %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + from, to, data->req.maxdownload)); + } + else + data->req.maxdownload = -1; + return CURLE_OK; +} + +#endif diff --git a/libcurl/lib/curl_range.h b/libcurl/lib/curl_range.h new file mode 100644 index 0000000..2350df9 --- /dev/null +++ b/libcurl/lib/curl_range.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_RANGE_H +#define HEADER_CURL_RANGE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +CURLcode Curl_range(struct connectdata *conn); + +#endif /* HEADER_CURL_RANGE_H */ diff --git a/libcurl/lib/curl_rtmp.c b/libcurl/lib/curl_rtmp.c new file mode 100644 index 0000000..16b1de1 --- /dev/null +++ b/libcurl/lib/curl_rtmp.c @@ -0,0 +1,316 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 2010, Howard Chu, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_LIBRTMP + +#include "curl_rtmp.h" +#include "urldata.h" +#include "nonblock.h" /* for curlx_nonblock */ +#include "progress.h" /* for Curl_pgrsSetUploadSize */ +#include "transfer.h" +#include "warnless.h" +#include +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#if defined(WIN32) && !defined(USE_LWIPSOCK) +#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) +#define SET_RCVTIMEO(tv,s) int tv = s*1000 +#elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) +#define SET_RCVTIMEO(tv,s) int tv = s*1000 +#else +#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} +#endif + +#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */ + +static CURLcode rtmp_setup_connection(struct connectdata *conn); +static CURLcode rtmp_do(struct connectdata *conn, bool *done); +static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature); +static CURLcode rtmp_connect(struct connectdata *conn, bool *done); +static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead); + +static Curl_recv rtmp_recv; +static Curl_send rtmp_send; + +/* + * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu + */ + +const struct Curl_handler Curl_handler_rtmp = { + "RTMP", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMP, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpt = { + "RTMPT", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPT, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpe = { + "RTMPE", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMPE, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpte = { + "RTMPTE", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPTE, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmps = { + "RTMPS", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPS, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +const struct Curl_handler Curl_handler_rtmpts = { + "RTMPTS", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPTS, /* protocol */ + PROTOPT_NONE /* flags*/ +}; + +static CURLcode rtmp_setup_connection(struct connectdata *conn) +{ + RTMP *r = RTMP_Alloc(); + if(!r) + return CURLE_OUT_OF_MEMORY; + + RTMP_Init(r); + RTMP_SetBufferMS(r, DEF_BUFTIME); + if(!RTMP_SetupURL(r, conn->data->change.url)) { + RTMP_Free(r); + return CURLE_URL_MALFORMAT; + } + conn->proto.generic = r; + return CURLE_OK; +} + +static CURLcode rtmp_connect(struct connectdata *conn, bool *done) +{ + RTMP *r = conn->proto.generic; + SET_RCVTIMEO(tv, 10); + + r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET]; + + /* We have to know if it's a write before we send the + * connect request packet + */ + if(conn->data->set.upload) + r->Link.protocol |= RTMP_FEATURE_WRITE; + + /* For plain streams, use the buffer toggle trick to keep data flowing */ + if(!(r->Link.lFlags & RTMP_LF_LIVE) && + !(r->Link.protocol & RTMP_FEATURE_HTTP)) + r->Link.lFlags |= RTMP_LF_BUFX; + + (void)curlx_nonblock(r->m_sb.sb_socket, FALSE); + setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, + (char *)&tv, sizeof(tv)); + + if(!RTMP_Connect1(r, NULL)) + return CURLE_FAILED_INIT; + + /* Clients must send a periodic BytesReceived report to the server */ + r->m_bSendCounter = true; + + *done = TRUE; + conn->recv[FIRSTSOCKET] = rtmp_recv; + conn->send[FIRSTSOCKET] = rtmp_send; + return CURLE_OK; +} + +static CURLcode rtmp_do(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + RTMP *r = conn->proto.generic; + + if(!RTMP_ConnectStream(r, 0)) + return CURLE_FAILED_INIT; + + if(conn->data->set.upload) { + Curl_pgrsSetUploadSize(data, data->state.infilesize); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + } + else + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + *done = TRUE; + return CURLE_OK; +} + +static CURLcode rtmp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void)conn; /* unused */ + (void)status; /* unused */ + (void)premature; /* unused */ + + return CURLE_OK; +} + +static CURLcode rtmp_disconnect(struct connectdata *conn, + bool dead_connection) +{ + RTMP *r = conn->proto.generic; + (void)dead_connection; + if(r) { + conn->proto.generic = NULL; + RTMP_Close(r); + RTMP_Free(r); + } + return CURLE_OK; +} + +static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, + size_t len, CURLcode *err) +{ + RTMP *r = conn->proto.generic; + ssize_t nread; + + (void)sockindex; /* unused */ + + nread = RTMP_Read(r, buf, curlx_uztosi(len)); + if(nread < 0) { + if(r->m_read.status == RTMP_READ_COMPLETE || + r->m_read.status == RTMP_READ_EOF) { + conn->data->req.size = conn->data->req.bytecount; + nread = 0; + } + else + *err = CURLE_RECV_ERROR; + } + return nread; +} + +static ssize_t rtmp_send(struct connectdata *conn, int sockindex, + const void *buf, size_t len, CURLcode *err) +{ + RTMP *r = conn->proto.generic; + ssize_t num; + + (void)sockindex; /* unused */ + + num = RTMP_Write(r, (char *)buf, curlx_uztosi(len)); + if(num < 0) + *err = CURLE_SEND_ERROR; + + return num; +} +#endif /* USE_LIBRTMP */ diff --git a/libcurl/lib/curl_rtmp.h b/libcurl/lib/curl_rtmp.h new file mode 100644 index 0000000..3306e22 --- /dev/null +++ b/libcurl/lib/curl_rtmp.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_RTMP_H +#define HEADER_CURL_RTMP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Howard Chu, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef USE_LIBRTMP +extern const struct Curl_handler Curl_handler_rtmp; +extern const struct Curl_handler Curl_handler_rtmpt; +extern const struct Curl_handler Curl_handler_rtmpe; +extern const struct Curl_handler Curl_handler_rtmpte; +extern const struct Curl_handler Curl_handler_rtmps; +extern const struct Curl_handler Curl_handler_rtmpts; +#endif + +#endif /* HEADER_CURL_RTMP_H */ diff --git a/libcurl/lib/curl_sasl.c b/libcurl/lib/curl_sasl.c new file mode 100644 index 0000000..018e422 --- /dev/null +++ b/libcurl/lib/curl_sasl.c @@ -0,0 +1,629 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2195 CRAM-MD5 authentication + * RFC2617 Basic and Digest Access Authentication + * RFC2831 DIGEST-MD5 authentication + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC6749 OAuth 2.0 Authorization Framework + * RFC7628 A Set of SASL Mechanisms for OAuth + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_POP3) + +#include +#include "urldata.h" + +#include "curl_base64.h" +#include "curl_md5.h" +#include "vauth/vauth.h" +#include "vtls/vtls.h" +#include "curl_hmac.h" +#include "curl_sasl.h" +#include "warnless.h" +#include "strtok.h" +#include "sendf.h" +#include "non-ascii.h" /* included for Curl_convert_... prototypes */ +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Supported mechanisms */ +static const struct { + const char *name; /* Name */ + size_t len; /* Name length */ + unsigned int bit; /* Flag bit */ +} mechtable[] = { + { "LOGIN", 5, SASL_MECH_LOGIN }, + { "PLAIN", 5, SASL_MECH_PLAIN }, + { "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 }, + { "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 }, + { "GSSAPI", 6, SASL_MECH_GSSAPI }, + { "EXTERNAL", 8, SASL_MECH_EXTERNAL }, + { "NTLM", 4, SASL_MECH_NTLM }, + { "XOAUTH2", 7, SASL_MECH_XOAUTH2 }, + { "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER }, + { ZERO_NULL, 0, 0 } +}; + +/* + * Curl_sasl_cleanup() + * + * This is used to cleanup any libraries or curl modules used by the sasl + * functions. + * + * Parameters: + * + * conn [in] - The connection data. + * authused [in] - The authentication mechanism used. + */ +void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) +{ +#if defined(USE_KERBEROS5) + /* Cleanup the gssapi structure */ + if(authused == SASL_MECH_GSSAPI) { + Curl_auth_cleanup_gssapi(&conn->krb5); + } +#endif + +#if defined(USE_NTLM) + /* Cleanup the NTLM structure */ + if(authused == SASL_MECH_NTLM) { + Curl_auth_cleanup_ntlm(&conn->ntlm); + } +#endif + +#if !defined(USE_KERBEROS5) && !defined(USE_NTLM) + /* Reserved for future use */ + (void)conn; + (void)authused; +#endif +} + +/* + * Curl_sasl_decode_mech() + * + * Convert a SASL mechanism name into a token. + * + * Parameters: + * + * ptr [in] - The mechanism string. + * maxlen [in] - Maximum mechanism string length. + * len [out] - If not NULL, effective name length. + * + * Returns the SASL mechanism token or 0 if no match. + */ +unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len) +{ + unsigned int i; + char c; + + for(i = 0; mechtable[i].name; i++) { + if(maxlen >= mechtable[i].len && + !memcmp(ptr, mechtable[i].name, mechtable[i].len)) { + if(len) + *len = mechtable[i].len; + + if(maxlen == mechtable[i].len) + return mechtable[i].bit; + + c = ptr[mechtable[i].len]; + if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_') + return mechtable[i].bit; + } + } + + return 0; +} + +/* + * Curl_sasl_parse_url_auth_option() + * + * Parse the URL login options. + */ +CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, + const char *value, size_t len) +{ + CURLcode result = CURLE_OK; + size_t mechlen; + + if(!len) + return CURLE_URL_MALFORMAT; + + if(sasl->resetprefs) { + sasl->resetprefs = FALSE; + sasl->prefmech = SASL_AUTH_NONE; + } + + if(!strncmp(value, "*", len)) + sasl->prefmech = SASL_AUTH_DEFAULT; + else { + unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen); + if(mechbit && mechlen == len) + sasl->prefmech |= mechbit; + else + result = CURLE_URL_MALFORMAT; + } + + return result; +} + +/* + * Curl_sasl_init() + * + * Initializes the SASL structure. + */ +void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params) +{ + sasl->params = params; /* Set protocol dependent parameters */ + sasl->state = SASL_STOP; /* Not yet running */ + sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */ + sasl->prefmech = SASL_AUTH_DEFAULT; /* Prefer all mechanisms */ + sasl->authused = SASL_AUTH_NONE; /* No the authentication mechanism used */ + sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */ + sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */ + sasl->force_ir = FALSE; /* Respect external option */ +} + +/* + * state() + * + * This is the ONLY way to change SASL state! + */ +static void state(struct SASL *sasl, struct connectdata *conn, + saslstate newstate) +{ +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[]={ + "STOP", + "PLAIN", + "LOGIN", + "LOGIN_PASSWD", + "EXTERNAL", + "CRAMMD5", + "DIGESTMD5", + "DIGESTMD5_RESP", + "NTLM", + "NTLM_TYPE2MSG", + "GSSAPI", + "GSSAPI_TOKEN", + "GSSAPI_NO_DATA", + "OAUTH2", + "OAUTH2_RESP", + "CANCEL", + "FINAL", + /* LAST */ + }; + + if(sasl->state != newstate) + infof(conn->data, "SASL %p state change from %s to %s\n", + (void *)sasl, names[sasl->state], names[newstate]); +#else + (void) conn; +#endif + + sasl->state = newstate; +} + +/* + * Curl_sasl_can_authenticate() + * + * Check if we have enough auth data and capabilities to authenticate. + */ +bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn) +{ + /* Have credentials been provided? */ + if(conn->bits.user_passwd) + return TRUE; + + /* EXTERNAL can authenticate without a user name and/or password */ + if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL) + return TRUE; + + return FALSE; +} + +/* + * Curl_sasl_start() + * + * Calculate the required login details for SASL authentication. + */ +CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, + bool force_ir, saslprogress *progress) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + unsigned int enabledmechs; + const char *mech = NULL; + char *resp = NULL; + size_t len = 0; + saslstate state1 = SASL_STOP; + saslstate state2 = SASL_FINAL; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; +#if defined(USE_KERBEROS5) || defined(USE_NTLM) + const char *service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : + sasl->params->service; +#endif + + sasl->force_ir = force_ir; /* Latch for future use */ + sasl->authused = 0; /* No mechanism used yet */ + enabledmechs = sasl->authmechs & sasl->prefmech; + *progress = SASL_IDLE; + + /* Calculate the supported authentication mechanism, by decreasing order of + security, as well as the initial response where appropriate */ + if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) { + mech = SASL_MECH_STRING_EXTERNAL; + state1 = SASL_EXTERNAL; + sasl->authused = SASL_MECH_EXTERNAL; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_external_message(data, conn->user, &resp, + &len); + } + else if(conn->bits.user_passwd) { +#if defined(USE_KERBEROS5) + if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() && + Curl_auth_user_contains_domain(conn->user)) { + sasl->mutual_auth = FALSE; + mech = SASL_MECH_STRING_GSSAPI; + state1 = SASL_GSSAPI; + state2 = SASL_GSSAPI_TOKEN; + sasl->authused = SASL_MECH_GSSAPI; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_gssapi_user_message(data, conn->user, + conn->passwd, + service, + data->conn->host.name, + sasl->mutual_auth, + NULL, &conn->krb5, + &resp, &len); + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if((enabledmechs & SASL_MECH_DIGEST_MD5) && + Curl_auth_is_digest_supported()) { + mech = SASL_MECH_STRING_DIGEST_MD5; + state1 = SASL_DIGESTMD5; + sasl->authused = SASL_MECH_DIGEST_MD5; + } + else if(enabledmechs & SASL_MECH_CRAM_MD5) { + mech = SASL_MECH_STRING_CRAM_MD5; + state1 = SASL_CRAMMD5; + sasl->authused = SASL_MECH_CRAM_MD5; + } + else +#endif +#ifdef USE_NTLM + if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) { + mech = SASL_MECH_STRING_NTLM; + state1 = SASL_NTLM; + state2 = SASL_NTLM_TYPE2MSG; + sasl->authused = SASL_MECH_NTLM; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_ntlm_type1_message(data, + conn->user, conn->passwd, + service, + hostname, + &conn->ntlm, &resp, + &len); + } + else +#endif + if((enabledmechs & SASL_MECH_OAUTHBEARER) && conn->oauth_bearer) { + mech = SASL_MECH_STRING_OAUTHBEARER; + state1 = SASL_OAUTH2; + state2 = SASL_OAUTH2_RESP; + sasl->authused = SASL_MECH_OAUTHBEARER; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_oauth_bearer_message(data, conn->user, + hostname, + port, + conn->oauth_bearer, + &resp, &len); + } + else if((enabledmechs & SASL_MECH_XOAUTH2) && conn->oauth_bearer) { + mech = SASL_MECH_STRING_XOAUTH2; + state1 = SASL_OAUTH2; + sasl->authused = SASL_MECH_XOAUTH2; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_xoauth_bearer_message(data, conn->user, + conn->oauth_bearer, + &resp, &len); + } + else if(enabledmechs & SASL_MECH_PLAIN) { + mech = SASL_MECH_STRING_PLAIN; + state1 = SASL_PLAIN; + sasl->authused = SASL_MECH_PLAIN; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_plain_message(data, NULL, conn->user, + conn->passwd, &resp, &len); + } + else if(enabledmechs & SASL_MECH_LOGIN) { + mech = SASL_MECH_STRING_LOGIN; + state1 = SASL_LOGIN; + state2 = SASL_LOGIN_PASSWD; + sasl->authused = SASL_MECH_LOGIN; + + if(force_ir || data->set.sasl_ir) + result = Curl_auth_create_login_message(data, conn->user, &resp, &len); + } + } + + if(!result && mech) { + if(resp && sasl->params->maxirlen && + strlen(mech) + len > sasl->params->maxirlen) { + free(resp); + resp = NULL; + } + + result = sasl->params->sendauth(conn, mech, resp); + if(!result) { + *progress = SASL_INPROGRESS; + state(sasl, conn, resp ? state2 : state1); + } + } + + free(resp); + + return result; +} + +/* + * Curl_sasl_continue() + * + * Continue the authentication. + */ +CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, + int code, saslprogress *progress) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + saslstate newstate = SASL_FINAL; + char *resp = NULL; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + char *chlg = NULL; + size_t chlglen = 0; +#endif +#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \ + defined(USE_NTLM) + const char *service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : + sasl->params->service; + char *serverdata; +#endif + size_t len = 0; + + *progress = SASL_INPROGRESS; + + if(sasl->state == SASL_FINAL) { + if(code != sasl->params->finalcode) + result = CURLE_LOGIN_DENIED; + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return result; + } + + if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP && + code != sasl->params->contcode) { + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return CURLE_LOGIN_DENIED; + } + + switch(sasl->state) { + case SASL_STOP: + *progress = SASL_DONE; + return result; + case SASL_PLAIN: + result = Curl_auth_create_plain_message(data, NULL, conn->user, + conn->passwd, &resp, &len); + break; + case SASL_LOGIN: + result = Curl_auth_create_login_message(data, conn->user, &resp, &len); + newstate = SASL_LOGIN_PASSWD; + break; + case SASL_LOGIN_PASSWD: + result = Curl_auth_create_login_message(data, conn->passwd, &resp, &len); + break; + case SASL_EXTERNAL: + result = Curl_auth_create_external_message(data, conn->user, &resp, &len); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case SASL_CRAMMD5: + sasl->params->getmessage(data->state.buffer, &serverdata); + result = Curl_auth_decode_cram_md5_message(serverdata, &chlg, &chlglen); + if(!result) + result = Curl_auth_create_cram_md5_message(data, chlg, conn->user, + conn->passwd, &resp, &len); + free(chlg); + break; + case SASL_DIGESTMD5: + sasl->params->getmessage(data->state.buffer, &serverdata); + result = Curl_auth_create_digest_md5_message(data, serverdata, + conn->user, conn->passwd, + service, + &resp, &len); + newstate = SASL_DIGESTMD5_RESP; + break; + case SASL_DIGESTMD5_RESP: + resp = strdup(""); + if(!resp) + result = CURLE_OUT_OF_MEMORY; + break; +#endif + +#ifdef USE_NTLM + case SASL_NTLM: + /* Create the type-1 message */ + result = Curl_auth_create_ntlm_type1_message(data, + conn->user, conn->passwd, + service, hostname, + &conn->ntlm, &resp, &len); + newstate = SASL_NTLM_TYPE2MSG; + break; + case SASL_NTLM_TYPE2MSG: + /* Decode the type-2 message */ + sasl->params->getmessage(data->state.buffer, &serverdata); + result = Curl_auth_decode_ntlm_type2_message(data, serverdata, + &conn->ntlm); + if(!result) + result = Curl_auth_create_ntlm_type3_message(data, conn->user, + conn->passwd, &conn->ntlm, + &resp, &len); + break; +#endif + +#if defined(USE_KERBEROS5) + case SASL_GSSAPI: + result = Curl_auth_create_gssapi_user_message(data, conn->user, + conn->passwd, + service, + data->conn->host.name, + sasl->mutual_auth, NULL, + &conn->krb5, + &resp, &len); + newstate = SASL_GSSAPI_TOKEN; + break; + case SASL_GSSAPI_TOKEN: + sasl->params->getmessage(data->state.buffer, &serverdata); + if(sasl->mutual_auth) { + /* Decode the user token challenge and create the optional response + message */ + result = Curl_auth_create_gssapi_user_message(data, NULL, NULL, + NULL, NULL, + sasl->mutual_auth, + serverdata, &conn->krb5, + &resp, &len); + newstate = SASL_GSSAPI_NO_DATA; + } + else + /* Decode the security challenge and create the response message */ + result = Curl_auth_create_gssapi_security_message(data, serverdata, + &conn->krb5, + &resp, &len); + break; + case SASL_GSSAPI_NO_DATA: + sasl->params->getmessage(data->state.buffer, &serverdata); + /* Decode the security challenge and create the response message */ + result = Curl_auth_create_gssapi_security_message(data, serverdata, + &conn->krb5, + &resp, &len); + break; +#endif + + case SASL_OAUTH2: + /* Create the authorisation message */ + if(sasl->authused == SASL_MECH_OAUTHBEARER) { + result = Curl_auth_create_oauth_bearer_message(data, conn->user, + hostname, + port, + conn->oauth_bearer, + &resp, &len); + + /* Failures maybe sent by the server as continuations for OAUTHBEARER */ + newstate = SASL_OAUTH2_RESP; + } + else + result = Curl_auth_create_xoauth_bearer_message(data, conn->user, + conn->oauth_bearer, + &resp, &len); + break; + + case SASL_OAUTH2_RESP: + /* The continuation is optional so check the response code */ + if(code == sasl->params->finalcode) { + /* Final response was received so we are done */ + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return result; + } + else if(code == sasl->params->contcode) { + /* Acknowledge the continuation by sending a 0x01 response base64 + encoded */ + resp = strdup("AQ=="); + if(!resp) + result = CURLE_OUT_OF_MEMORY; + break; + } + else { + *progress = SASL_DONE; + state(sasl, conn, SASL_STOP); + return CURLE_LOGIN_DENIED; + } + + case SASL_CANCEL: + /* Remove the offending mechanism from the supported list */ + sasl->authmechs ^= sasl->authused; + + /* Start an alternative SASL authentication */ + result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress); + newstate = sasl->state; /* Use state from Curl_sasl_start() */ + break; + default: + failf(data, "Unsupported SASL authentication mechanism"); + result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ + break; + } + + switch(result) { + case CURLE_BAD_CONTENT_ENCODING: + /* Cancel dialog */ + result = sasl->params->sendcont(conn, "*"); + newstate = SASL_CANCEL; + break; + case CURLE_OK: + if(resp) + result = sasl->params->sendcont(conn, resp); + break; + default: + newstate = SASL_STOP; /* Stop on error */ + *progress = SASL_DONE; + break; + } + + free(resp); + + state(sasl, conn, newstate); + + return result; +} +#endif /* protocols are enabled that use SASL */ diff --git a/libcurl/lib/curl_sasl.h b/libcurl/lib/curl_sasl.h new file mode 100644 index 0000000..7647a48 --- /dev/null +++ b/libcurl/lib/curl_sasl.h @@ -0,0 +1,143 @@ +#ifndef HEADER_CURL_SASL_H +#define HEADER_CURL_SASL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +struct Curl_easy; +struct connectdata; + +/* Authentication mechanism flags */ +#define SASL_MECH_LOGIN (1 << 0) +#define SASL_MECH_PLAIN (1 << 1) +#define SASL_MECH_CRAM_MD5 (1 << 2) +#define SASL_MECH_DIGEST_MD5 (1 << 3) +#define SASL_MECH_GSSAPI (1 << 4) +#define SASL_MECH_EXTERNAL (1 << 5) +#define SASL_MECH_NTLM (1 << 6) +#define SASL_MECH_XOAUTH2 (1 << 7) +#define SASL_MECH_OAUTHBEARER (1 << 8) + +/* Authentication mechanism values */ +#define SASL_AUTH_NONE 0 +#define SASL_AUTH_ANY ~0U +#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL) + +/* Authentication mechanism strings */ +#define SASL_MECH_STRING_LOGIN "LOGIN" +#define SASL_MECH_STRING_PLAIN "PLAIN" +#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5" +#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5" +#define SASL_MECH_STRING_GSSAPI "GSSAPI" +#define SASL_MECH_STRING_EXTERNAL "EXTERNAL" +#define SASL_MECH_STRING_NTLM "NTLM" +#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2" +#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER" + +/* SASL machine states */ +typedef enum { + SASL_STOP, + SASL_PLAIN, + SASL_LOGIN, + SASL_LOGIN_PASSWD, + SASL_EXTERNAL, + SASL_CRAMMD5, + SASL_DIGESTMD5, + SASL_DIGESTMD5_RESP, + SASL_NTLM, + SASL_NTLM_TYPE2MSG, + SASL_GSSAPI, + SASL_GSSAPI_TOKEN, + SASL_GSSAPI_NO_DATA, + SASL_OAUTH2, + SASL_OAUTH2_RESP, + SASL_CANCEL, + SASL_FINAL +} saslstate; + +/* Progress indicator */ +typedef enum { + SASL_IDLE, + SASL_INPROGRESS, + SASL_DONE +} saslprogress; + +/* Protocol dependent SASL parameters */ +struct SASLproto { + const char *service; /* The service name */ + int contcode; /* Code to receive when continuation is expected */ + int finalcode; /* Code to receive upon authentication success */ + size_t maxirlen; /* Maximum initial response length */ + CURLcode (*sendauth)(struct connectdata *conn, + const char *mech, const char *ir); + /* Send authentication command */ + CURLcode (*sendcont)(struct connectdata *conn, const char *contauth); + /* Send authentication continuation */ + void (*getmessage)(char *buffer, char **outptr); + /* Get SASL response message */ +}; + +/* Per-connection parameters */ +struct SASL { + const struct SASLproto *params; /* Protocol dependent parameters */ + saslstate state; /* Current machine state */ + unsigned int authmechs; /* Accepted authentication mechanisms */ + unsigned int prefmech; /* Preferred authentication mechanism */ + unsigned int authused; /* Auth mechanism used for the connection */ + bool resetprefs; /* For URL auth option parsing. */ + bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ + bool force_ir; /* Protocol always supports initial response */ +}; + +/* This is used to test whether the line starts with the given mechanism */ +#define sasl_mech_equal(line, wordlen, mech) \ + (wordlen == (sizeof(mech) - 1) / sizeof(char) && \ + !memcmp(line, mech, wordlen)) + +/* This is used to cleanup any libraries or curl modules used by the sasl + functions */ +void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); + +/* Convert a mechanism name to a token */ +unsigned int Curl_sasl_decode_mech(const char *ptr, + size_t maxlen, size_t *len); + +/* Parse the URL login options */ +CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, + const char *value, size_t len); + +/* Initializes an SASL structure */ +void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params); + +/* Check if we have enough auth data and capabilities to authenticate */ +bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn); + +/* Calculate the required login details for SASL authentication */ +CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, + bool force_ir, saslprogress *progress); + +/* Continue an SASL authentication */ +CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, + int code, saslprogress *progress); + +#endif /* HEADER_CURL_SASL_H */ diff --git a/libcurl/lib/curl_sec.h b/libcurl/lib/curl_sec.h new file mode 100644 index 0000000..7bdde26 --- /dev/null +++ b/libcurl/lib/curl_sec.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_SECURITY_H +#define HEADER_CURL_SECURITY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +struct Curl_sec_client_mech { + const char *name; + size_t size; + int (*init)(void *); + int (*auth)(void *, struct connectdata *); + void (*end)(void *); + int (*check_prot)(void *, int); + int (*overhead)(void *, int, int); + int (*encode)(void *, const void *, int, int, void **); + int (*decode)(void *, void *, int, int, struct connectdata *); +}; + +#define AUTH_OK 0 +#define AUTH_CONTINUE 1 +#define AUTH_ERROR 2 + +#ifdef HAVE_GSSAPI +int Curl_sec_read_msg(struct connectdata *conn, char *, + enum protection_level); +void Curl_sec_end(struct connectdata *); +CURLcode Curl_sec_login(struct connectdata *); +int Curl_sec_request_prot(struct connectdata *conn, const char *level); + +extern struct Curl_sec_client_mech Curl_krb5_client_mech; +#endif + +#endif /* HEADER_CURL_SECURITY_H */ diff --git a/libcurl/lib/curl_setup.h b/libcurl/lib/curl_setup.h new file mode 100644 index 0000000..16bc40a --- /dev/null +++ b/libcurl/lib/curl_setup.h @@ -0,0 +1,832 @@ +#ifndef HEADER_CURL_SETUP_H +#define HEADER_CURL_SETUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#if defined(BUILDING_LIBCURL) && !defined(CURL_NO_OLDIES) +#define CURL_NO_OLDIES +#endif + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \ + !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#ifdef WIN32 +/* + * Don't include unneeded stuff in Windows headers to avoid compiler + * warnings and macro clashes. + * Make sure to define this macro before including any Windows headers. + */ +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# ifndef NOGDI +# define NOGDI +# endif +#endif + +/* + * Include configuration script results or hand-crafted + * configuration file for platforms which lack config tool. + */ + +#ifdef HAVE_CONFIG_H + +#include "curl_config.h" + +#else /* HAVE_CONFIG_H */ + +#ifdef _WIN32_WCE +# include "config-win32ce.h" +#else +# ifdef WIN32 +# include "config-win32.h" +# endif +#endif + +#if defined(macintosh) && defined(__MRC__) +# include "config-mac.h" +#endif + +#ifdef __riscos__ +# include "config-riscos.h" +#endif + +#ifdef __AMIGA__ +# include "config-amigaos.h" +#endif + +#ifdef __SYMBIAN32__ +# include "config-symbian.h" +#endif + +#ifdef __OS400__ +# include "config-os400.h" +#endif + +#ifdef TPF +# include "config-tpf.h" +#endif + +#ifdef __VXWORKS__ +# include "config-vxworks.h" +#endif + +#endif /* HAVE_CONFIG_H */ + +/* ================================================================ */ +/* Definition of preprocessor macros/symbols which modify compiler */ +/* behavior or generated code characteristics must be done here, */ +/* as appropriate, before any system header file is included. It is */ +/* also possible to have them defined in the config file included */ +/* before this point. As a result of all this we frown inclusion of */ +/* system header files in our config files, avoid this at any cost. */ +/* ================================================================ */ + +/* + * AIX 4.3 and newer needs _THREAD_SAFE defined to build + * proper reentrant code. Others may also need it. + */ + +#ifdef NEED_THREAD_SAFE +# ifndef _THREAD_SAFE +# define _THREAD_SAFE +# endif +#endif + +/* + * Tru64 needs _REENTRANT set for a few function prototypes and + * things to appear in the system header files. Unixware needs it + * to build proper reentrant code. Others may also need it. + */ + +#ifdef NEED_REENTRANT +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +/* Solaris needs this to get a POSIX-conformant getpwuid_r */ +#if defined(sun) || defined(__sun) +# ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +# endif +#endif + +/* ================================================================ */ +/* If you need to include a system header file for your platform, */ +/* please, do it beyond the point further indicated in this file. */ +/* ================================================================ */ + +#include + +#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T + +/* + * Disable other protocols when http is the only one desired. + */ + +#ifdef HTTP_ONLY +# ifndef CURL_DISABLE_TFTP +# define CURL_DISABLE_TFTP +# endif +# ifndef CURL_DISABLE_FTP +# define CURL_DISABLE_FTP +# endif +# ifndef CURL_DISABLE_LDAP +# define CURL_DISABLE_LDAP +# endif +# ifndef CURL_DISABLE_TELNET +# define CURL_DISABLE_TELNET +# endif +# ifndef CURL_DISABLE_DICT +# define CURL_DISABLE_DICT +# endif +# ifndef CURL_DISABLE_FILE +# define CURL_DISABLE_FILE +# endif +# ifndef CURL_DISABLE_RTSP +# define CURL_DISABLE_RTSP +# endif +# ifndef CURL_DISABLE_POP3 +# define CURL_DISABLE_POP3 +# endif +# ifndef CURL_DISABLE_IMAP +# define CURL_DISABLE_IMAP +# endif +# ifndef CURL_DISABLE_SMTP +# define CURL_DISABLE_SMTP +# endif +# ifndef CURL_DISABLE_GOPHER +# define CURL_DISABLE_GOPHER +# endif +# ifndef CURL_DISABLE_SMB +# define CURL_DISABLE_SMB +# endif +#endif + +/* + * When http is disabled rtsp is not supported. + */ + +#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP) +# define CURL_DISABLE_RTSP +#endif + +/* ================================================================ */ +/* No system header file shall be included in this file before this */ +/* point. The only allowed ones are those included from curl/system.h */ +/* ================================================================ */ + +/* + * OS/400 setup file includes some system headers. + */ + +#ifdef __OS400__ +# include "setup-os400.h" +#endif + +/* + * VMS setup file includes some system headers. + */ + +#ifdef __VMS +# include "setup-vms.h" +#endif + +/* + * Use getaddrinfo to resolve the IPv4 address literal. If the current network + * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64, + * performing this task will result in a synthesized IPv6 address. + */ +#ifdef __APPLE__ +#define USE_RESOLVE_ON_IPS 1 +#endif + +/* + * Include header files for windows builds before redefining anything. + * Use this preprocessor block only to include or exclude windows.h, + * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs + * to any other further and independent block. Under Cygwin things work + * just as under linux (e.g. ) and the winsock headers should + * never be included when __CYGWIN__ is defined. configure script takes + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H, + * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined. + */ + +#ifdef HAVE_WINDOWS_H +# if defined(UNICODE) && !defined(_UNICODE) +# define _UNICODE +# endif +# if defined(_UNICODE) && !defined(UNICODE) +# define UNICODE +# endif +//# include +//# include +# include +# ifdef HAVE_WINSOCK2_H +//# include +# ifdef HAVE_WS2TCPIP_H +//# include +# endif +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +# include +# ifdef UNICODE + typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str); +# endif +#endif + +/* + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else + * define USE_WINSOCK to 1 if we have and use WINSOCK API, else + * undefine USE_WINSOCK. + */ + +#undef USE_WINSOCK + +#ifdef HAVE_WINSOCK2_H +# define USE_WINSOCK 2 +#else +# ifdef HAVE_WINSOCK_H +# define USE_WINSOCK 1 +# endif +#endif + +#ifdef USE_LWIPSOCK +# include +# include +# include +#endif + +#ifdef HAVE_EXTRA_STRICMP_H +# include +#endif + +#ifdef HAVE_EXTRA_STRDUP_H +# include +#endif + +#ifdef TPF +# include /* for bzero, strcasecmp, and strncasecmp */ +# include /* for strcpy and strlen */ +# include /* for rand and srand */ +# include /* for select and ioctl*/ +# include /* for in_addr_t definition */ +# include /* for tpf_process_signals */ + /* change which select is used for libcurl */ +# define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e) +#endif + +#ifdef __VXWORKS__ +# include /* for generic BSD socket functions */ +# include /* for basic I/O interface functions */ +#endif + +#ifdef __AMIGA__ +# include +# include +# include +# include +# ifdef HAVE_PROTO_BSDSOCKET_H +# include /* ensure bsdsocket.library use */ +# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0) +# endif +#endif + +#include +#ifdef HAVE_ASSERT_H +#include +#endif + +#ifdef __TANDEM /* for nsr-tandem-nsk systems */ +#include +#endif + +#ifndef STDC_HEADERS /* no standard C headers! */ +#include +#endif + +#ifdef __POCC__ +# include +# include +# define sys_nerr EILSEQ +#endif + +/* + * Salford-C kludge section (mostly borrowed from wxWidgets). + */ +#ifdef __SALFORDC__ + #pragma suppress 353 /* Possible nested comments */ + #pragma suppress 593 /* Define not used */ + #pragma suppress 61 /* enum has no name */ + #pragma suppress 106 /* unnamed, unused parameter */ + #include +#endif + +/* + * Large file (>2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_LARGE_FILES +# include +# include +# include +# undef lseek +# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence) +# undef fstat +# define fstat(fdes,stp) _fstati64(fdes, stp) +# undef stat +# define stat(fname,stp) _stati64(fname, stp) +# define struct_stat struct _stati64 +# define LSEEK_ERROR (__int64)-1 +#endif + +/* + * Small file (<2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_SMALL_FILES +# include +# include +# include +# ifndef _WIN32_WCE +# undef lseek +# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence) +# define fstat(fdes,stp) _fstat(fdes, stp) +# define stat(fname,stp) _stat(fname, stp) +# define struct_stat struct _stat +# endif +# define LSEEK_ERROR (long)-1 +#endif + +#ifndef struct_stat +# define struct_stat struct stat +#endif + +#ifndef LSEEK_ERROR +# define LSEEK_ERROR (off_t)-1 +#endif + +#ifndef SIZEOF_TIME_T +/* assume default size of time_t to be 32 bit */ +#define SIZEOF_TIME_T 4 +#endif + +/* + * Default sizeof(off_t) in case it hasn't been defined in config file. + */ + +#ifndef SIZEOF_OFF_T +# if defined(__VMS) && !defined(__VAX) +# if defined(_LARGEFILE) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__OS400__) && defined(__ILEC400__) +# if defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__MVS__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__370__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# endif +# ifndef SIZEOF_OFF_T +# define SIZEOF_OFF_T 4 +# endif +#endif + +#if (SIZEOF_CURL_OFF_T == 4) +# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF) +#else + /* assume CURL_SIZEOF_CURL_OFF_T == 8 */ +# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) +#endif +#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1)) + +#if (SIZEOF_TIME_T == 4) +# ifdef HAVE_TIME_T_UNSIGNED +# define TIME_T_MAX UINT_MAX +# define TIME_T_MIN 0 +# else +# define TIME_T_MAX INT_MAX +# define TIME_T_MIN INT_MIN +# endif +#else +# ifdef HAVE_TIME_T_UNSIGNED +# define TIME_T_MAX 0xFFFFFFFFFFFFFFFF +# define TIME_T_MIN 0 +# else +# define TIME_T_MAX 0x7FFFFFFFFFFFFFFF +# define TIME_T_MIN (-TIME_T_MAX - 1) +# endif +#endif + +#ifndef SIZE_T_MAX +/* some limits.h headers have this defined, some don't */ +#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) +#define SIZE_T_MAX 18446744073709551615U +#else +#define SIZE_T_MAX 4294967295U +#endif +#endif + +/* + * Arg 2 type for gethostname in case it hasn't been defined in config file. + */ + +#ifndef GETHOSTNAME_TYPE_ARG2 +# ifdef USE_WINSOCK +# define GETHOSTNAME_TYPE_ARG2 int +# else +# define GETHOSTNAME_TYPE_ARG2 size_t +# endif +#endif + +/* Below we define some functions. They should + + 4. set the SIGALRM signal timeout + 5. set dir/file naming defines + */ + +#ifdef WIN32 + +# define DIR_CHAR "\\" +# define DOT_CHAR "_" + +#else /* WIN32 */ + +# ifdef MSDOS /* Watt-32 */ + +# include +# define select(n,r,w,x,t) select_s(n,r,w,x,t) +# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z)) +# include +# ifdef word +# undef word +# endif +# ifdef byte +# undef byte +# endif + +# endif /* MSDOS */ + +# ifdef __minix + /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */ + extern char *strtok_r(char *s, const char *delim, char **last); + extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp); +# endif + +# define DIR_CHAR "/" +# ifndef DOT_CHAR +# define DOT_CHAR "." +# endif + +# ifdef MSDOS +# undef DOT_CHAR +# define DOT_CHAR "_" +# endif + +# ifndef fileno /* sunos 4 have this as a macro! */ + int fileno(FILE *stream); +# endif + +#endif /* WIN32 */ + +/* + * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN + * defined in ws2tcpip.h as well as to provide IPv6 support. + * Does not apply if lwIP is used. + */ + +//#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK) +//# if !defined(HAVE_WS2TCPIP_H) || \ +// ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN)) +# undef HAVE_GETADDRINFO_THREADSAFE +# undef HAVE_FREEADDRINFO +# undef HAVE_GETADDRINFO +# undef HAVE_GETNAMEINFO +# undef ENABLE_IPV6 +//# endif +//#endif + +/* ---------------------------------------------------------------- */ +/* resolver specialty compile-time defines */ +/* CURLRES_* defines to use in the host*.c sources */ +/* ---------------------------------------------------------------- */ + +/* + * lcc-win32 doesn't have _beginthreadex(), lacks threads support. + */ + +#if defined(__LCC__) && defined(WIN32) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * MSVC threads support requires a multi-threaded runtime library. + * _beginthreadex() is not available in single-threaded ones. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * Mutually exclusive CURLRES_* definitions. + */ + +#ifdef USE_ARES +# define CURLRES_ASYNCH +# define CURLRES_ARES +/* now undef the stock libc functions just to avoid them being used */ +# undef HAVE_GETADDRINFO +# undef HAVE_FREEADDRINFO +# undef HAVE_GETHOSTBYNAME +#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +# define CURLRES_ASYNCH +# define CURLRES_THREADED +#else +# define CURLRES_SYNCH +#endif + +#ifdef ENABLE_IPV6 +# define CURLRES_IPV6 +#else +# define CURLRES_IPV4 +#endif + +/* ---------------------------------------------------------------- */ + +/* + * When using WINSOCK, TELNET protocol requires WINSOCK2 API. + */ + +#if defined(USE_WINSOCK) && (USE_WINSOCK != 2) +# define CURL_DISABLE_TELNET 1 +#endif + +/* + * msvc 6.0 does not have struct sockaddr_storage and + * does not define IPPROTO_ESP in winsock2.h. But both + * are available if PSDK is properly installed. + */ + +//#if defined(_MSC_VER) && !defined(__POCC__) +//# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP)) +# undef HAVE_STRUCT_SOCKADDR_STORAGE +//# endif +//#endif + +/* + * Intentionally fail to build when using msvc 6.0 without PSDK installed. + * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK + * in lib/config-win32.h although absolutely discouraged and unsupported. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_)) +# if !defined(ALLOW_MSVC6_WITHOUT_PSDK) +# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \ + "Windows Server 2003 PSDK" +# else +# define CURL_DISABLE_LDAP 1 +# endif +# endif +#endif + +#ifdef NETWARE +int netware_init(void); +#ifndef __NOVELL_LIBC__ +#include +#include +#endif +#endif + +#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN) +/* The lib and header are present */ +#define USE_LIBIDN2 +#endif + +#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN) +#error "Both libidn2 and WinIDN are enabled, choose one." +#endif + +#define LIBIDN_REQUIRED_VERSION "0.4.1" + +#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \ + defined(USE_MBEDTLS) || defined(USE_BEARSSL) || \ + defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \ + defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) +#define USE_SSL /* SSL support has been enabled */ +#endif + +/* Single point where USE_SPNEGO definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_SPNEGO +#endif + +/* Single point where USE_KERBEROS5 definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_KERBEROS5 +#endif + +/* Single point where USE_NTLM definition might be defined */ +#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) +#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ + defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ + defined(USE_MBEDTLS) + +#define USE_NTLM + +# if defined(USE_MBEDTLS) +/* Get definition of MBEDTLS_MD4_C */ +# include +# endif + +#endif +#endif + +#ifdef CURL_WANTS_CA_BUNDLE_ENV +#error "No longer supported. Set CURLOPT_CAINFO at runtime instead." +#endif + +#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH) +#define USE_SSH +#endif + +/* + * Provide a mechanism to silence picky compilers, such as gcc 4.6+. + * Parameters should of course normally not be unused, but for example when + * we have multiple implementations of the same interface it may happen. + */ + +#if defined(__GNUC__) && ((__GNUC__ >= 3) || \ + ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7))) +# define UNUSED_PARAM __attribute__((__unused__)) +# define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define UNUSED_PARAM /*NOTHING*/ +# define WARN_UNUSED_RESULT +#endif + +/* + * Include macros and defines that should only be processed once. + */ + +#ifndef HEADER_CURL_SETUP_ONCE_H +#include "curl_setup_once.h" +#endif + +/* + * Definition of our NOP statement Object-like macro + */ + +#ifndef Curl_nop_stmt +# define Curl_nop_stmt do { } WHILE_FALSE +#endif + +/* + * Ensure that Winsock and lwIP TCP/IP stacks are not mixed. + */ + +#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H) +# if defined(SOCKET) || \ + defined(USE_WINSOCK) || \ + defined(HAVE_WINSOCK_H) || \ + defined(HAVE_WINSOCK2_H) || \ + defined(HAVE_WS2TCPIP_H) +# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!" +# endif +#endif + +/* + * Portable symbolic names for Winsock shutdown() mode flags. + */ + +#ifdef USE_WINSOCK +# define SHUT_RD 0x00 +# define SHUT_WR 0x01 +# define SHUT_RDWR 0x02 +#endif + +/* Define S_ISREG if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + +/* Define S_ISDIR if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +/* In Windows the default file mode is text but an application can override it. +Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 +*/ +#if defined(WIN32) || defined(MSDOS) +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "wt" +#define FOPEN_APPENDTEXT "at" +#elif defined(__CYGWIN__) +/* Cygwin has specific behavior we need to address when WIN32 is not defined. +https://cygwin.com/cygwin-ug-net/using-textbinary.html +For write we want our output to have line endings of LF and be compatible with +other Cygwin utilities. For read we want to handle input that may have line +endings either CRLF or LF so 't' is appropriate. +*/ +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "w" +#define FOPEN_APPENDTEXT "a" +#else +#define FOPEN_READTEXT "r" +#define FOPEN_WRITETEXT "w" +#define FOPEN_APPENDTEXT "a" +#endif + +/* WinSock destroys recv() buffer when send() failed. + * Enabled automatically for Windows and for Cygwin as Cygwin sockets are + * wrappers for WinSock sockets. https://github.com/curl/curl/issues/657 + * Define DONT_USE_RECV_BEFORE_SEND_WORKAROUND to force disable workaround. + * Disabled for Xbox - xnet stack doesn't need this workaround. + */ +#if !defined(DONT_USE_RECV_BEFORE_SEND_WORKAROUND) +# if (defined(WIN32) || defined(__CYGWIN__)) && !defined(_XBOX) +# define USE_RECV_BEFORE_SEND_WORKAROUND +# endif +#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */ +# ifdef USE_RECV_BEFORE_SEND_WORKAROUND +# undef USE_RECV_BEFORE_SEND_WORKAROUND +# endif +#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */ + +/* Detect Windows App environment which has a restricted access + * to the Win32 APIs. */ +# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \ + defined(WINAPI_FAMILY) +# include +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ + !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define CURL_WINDOWS_APP +# endif +# endif + +/* for systems that don't detect this in configure, use a sensible default */ +#ifndef CURL_SA_FAMILY_T +#define CURL_SA_FAMILY_T unsigned short +#endif + +/* Some convenience macros to get the larger/smaller value out of two given. + We prefix with CURL to prevent name collisions. */ +#define CURLMAX(x,y) ((x)>(y)?(x):(y)) +#define CURLMIN(x,y) ((x)<(y)?(x):(y)) + +/* Some versions of the Android SDK is missing the declaration */ +#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING) +struct passwd; +int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, + size_t buflen, struct passwd **result); +#endif + +#ifdef DEBUGBUILD +#define UNITTEST +#else +#define UNITTEST static +#endif + +#endif /* HEADER_CURL_SETUP_H */ diff --git a/libcurl/lib/curl_setup_once.h b/libcurl/lib/curl_setup_once.h new file mode 100644 index 0000000..413ccea --- /dev/null +++ b/libcurl/lib/curl_setup_once.h @@ -0,0 +1,517 @@ +#ifndef HEADER_CURL_SETUP_ONCE_H +#define HEADER_CURL_SETUP_ONCE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* + * Inclusion of common header files. + */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_ERRNO_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef NEED_MALLOC_H +#include +#endif + +#ifdef NEED_MEMORY_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#else +#ifdef HAVE_TIME_H +#include +#endif +#endif + +#ifdef WIN32 +#include +#include +#endif + +#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T) +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef __hpux +# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL) +# ifdef _APP32_64BIT_OFF_T +# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T +# undef _APP32_64BIT_OFF_T +# else +# undef OLD_APP32_64BIT_OFF_T +# endif +# endif +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef __hpux +# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL) +# ifdef OLD_APP32_64BIT_OFF_T +# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T +# undef OLD_APP32_64BIT_OFF_T +# endif +# endif +#endif + +/* + * Definition of timeval struct for platforms that don't have it. + */ + +#ifndef HAVE_STRUCT_TIMEVAL +struct timeval { + long tv_sec; + long tv_usec; +}; +#endif + + +/* + * If we have the MSG_NOSIGNAL define, make sure we use + * it as the fourth argument of function send() + */ + +#ifdef HAVE_MSG_NOSIGNAL +#define SEND_4TH_ARG MSG_NOSIGNAL +#else +#define SEND_4TH_ARG 0 +#endif + + +#if defined(__minix) +/* Minix doesn't support recv on TCP sockets */ +#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z)) + +#elif defined(HAVE_RECV) +/* + * The definitions for the return type and arguments types + * of functions recv() and send() belong and come from the + * configuration file. Do not define them in any other place. + * + * HAVE_RECV is defined if you have a function named recv() + * which is used to read incoming data from sockets. If your + * function has another name then don't define HAVE_RECV. + * + * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2, + * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also + * be defined. + * + * HAVE_SEND is defined if you have a function named send() + * which is used to write outgoing data on a connected socket. + * If yours has another name then don't define HAVE_SEND. + * + * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2, + * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and + * SEND_TYPE_RETV must also be defined. + */ + +#if !defined(RECV_TYPE_ARG1) || \ + !defined(RECV_TYPE_ARG2) || \ + !defined(RECV_TYPE_ARG3) || \ + !defined(RECV_TYPE_ARG4) || \ + !defined(RECV_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_recv + /* */ +#else +#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z), \ + (RECV_TYPE_ARG4)(0)) +#endif +#else /* HAVE_RECV */ +#ifndef sread + /* */ + Error Missing_definition_of_macro_sread + /* */ +#endif +#endif /* HAVE_RECV */ + + +#if defined(__minix) +/* Minix doesn't support send on TCP sockets */ +#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \ + (SEND_TYPE_ARG2)(y), \ + (SEND_TYPE_ARG3)(z)) + +#elif defined(HAVE_SEND) +#if !defined(SEND_TYPE_ARG1) || \ + !defined(SEND_QUAL_ARG2) || \ + !defined(SEND_TYPE_ARG2) || \ + !defined(SEND_TYPE_ARG3) || \ + !defined(SEND_TYPE_ARG4) || \ + !defined(SEND_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_send + /* */ +#else +#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ + (SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \ + (SEND_TYPE_ARG3)(z), \ + (SEND_TYPE_ARG4)(SEND_4TH_ARG)) +#endif +#else /* HAVE_SEND */ +#ifndef swrite + /* */ + Error Missing_definition_of_macro_swrite + /* */ +#endif +#endif /* HAVE_SEND */ + + +#if 0 +#if defined(HAVE_RECVFROM) +/* + * Currently recvfrom is only used on udp sockets. + */ +#if !defined(RECVFROM_TYPE_ARG1) || \ + !defined(RECVFROM_TYPE_ARG2) || \ + !defined(RECVFROM_TYPE_ARG3) || \ + !defined(RECVFROM_TYPE_ARG4) || \ + !defined(RECVFROM_TYPE_ARG5) || \ + !defined(RECVFROM_TYPE_ARG6) || \ + !defined(RECVFROM_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_recvfrom + /* */ +#else +#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \ + (RECVFROM_TYPE_ARG2 *)(b), \ + (RECVFROM_TYPE_ARG3) (bl), \ + (RECVFROM_TYPE_ARG4) (0), \ + (RECVFROM_TYPE_ARG5 *)(f), \ + (RECVFROM_TYPE_ARG6 *)(fl)) +#endif +#else /* HAVE_RECVFROM */ +#ifndef sreadfrom + /* */ + Error Missing_definition_of_macro_sreadfrom + /* */ +#endif +#endif /* HAVE_RECVFROM */ + + +#ifdef RECVFROM_TYPE_ARG6_IS_VOID +# define RECVFROM_ARG6_T int +#else +# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6 +#endif +#endif /* if 0 */ + + +/* + * Function-like macro definition used to close a socket. + */ + +#if defined(HAVE_CLOSESOCKET) +# define sclose(x) closesocket((x)) +#elif defined(HAVE_CLOSESOCKET_CAMEL) +# define sclose(x) CloseSocket((x)) +#elif defined(HAVE_CLOSE_S) +# define sclose(x) close_s((x)) +#elif defined(USE_LWIPSOCK) +# define sclose(x) lwip_close((x)) +#else +# define sclose(x) close((x)) +#endif + +/* + * Stack-independent version of fcntl() on sockets: + */ +#if defined(USE_LWIPSOCK) +# define sfcntl lwip_fcntl +#else +# define sfcntl fcntl +#endif + +#define TOLOWER(x) (tolower((int) ((unsigned char)x))) + + +/* + * 'bool' stuff compatible with HP-UX headers. + */ + +#if defined(__hpux) && !defined(HAVE_BOOL_T) + typedef int bool; +# define false 0 +# define true 1 +# define HAVE_BOOL_T +#endif + + +/* + * 'bool' exists on platforms with , i.e. C99 platforms. + * On non-C99 platforms there's no bool, so define an enum for that. + * On C99 platforms 'false' and 'true' also exist. Enum uses a + * global namespace though, so use bool_false and bool_true. + */ + +#ifndef HAVE_BOOL_T + typedef enum { + bool_false = 0, + bool_true = 1 + } bool; + +/* + * Use a define to let 'true' and 'false' use those enums. There + * are currently no use of true and false in libcurl proper, but + * there are some in the examples. This will cater for any later + * code happening to use true and false. + */ +# define false bool_false +# define true bool_true +# define HAVE_BOOL_T +#endif + + +/* + * Redefine TRUE and FALSE too, to catch current use. With this + * change, 'bool found = 1' will give a warning on MIPSPro, but + * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro, + * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too. + */ + +#ifndef TRUE +#define TRUE true +#endif +#ifndef FALSE +#define FALSE false +#endif + +#include "curl_ctype.h" + +/* + * Macro WHILE_FALSE may be used to build single-iteration do-while loops, + * avoiding compiler warnings. Mostly intended for other macro definitions. + */ + +#define WHILE_FALSE while(0) + +#if defined(_MSC_VER) && !defined(__POCC__) +# undef WHILE_FALSE +# if (_MSC_VER < 1500) +# define WHILE_FALSE while(1, 0) +# else +# define WHILE_FALSE \ +__pragma(warning(push)) \ +__pragma(warning(disable:4127)) \ +while(0) \ +__pragma(warning(pop)) +# endif +#endif + + +/* + * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type. + */ + +#ifndef HAVE_SIG_ATOMIC_T +typedef int sig_atomic_t; +#define HAVE_SIG_ATOMIC_T +#endif + + +/* + * Convenience SIG_ATOMIC_T definition + */ + +#ifdef HAVE_SIG_ATOMIC_T_VOLATILE +#define SIG_ATOMIC_T static sig_atomic_t +#else +#define SIG_ATOMIC_T static volatile sig_atomic_t +#endif + + +/* + * Default return type for signal handlers. + */ + +#ifndef RETSIGTYPE +#define RETSIGTYPE void +#endif + + +/* + * Macro used to include code only in debug builds. + */ + +#ifdef DEBUGBUILD +#define DEBUGF(x) x +#else +#define DEBUGF(x) do { } WHILE_FALSE +#endif + + +/* + * Macro used to include assertion code only in debug builds. + */ + +#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H) +#define DEBUGASSERT(x) assert(x) +#else +#define DEBUGASSERT(x) do { } WHILE_FALSE +#endif + + +/* + * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno + * (or equivalent) on this platform to hide platform details to code using it. + */ + +#ifdef USE_WINSOCK +#define SOCKERRNO ((int)WSAGetLastError()) +#define SET_SOCKERRNO(x) (WSASetLastError((int)(x))) +#else +#define SOCKERRNO (errno) +#define SET_SOCKERRNO(x) (errno = (x)) +#endif + + +/* + * Portable error number symbolic names defined to Winsock error codes. + */ + +#ifdef USE_WINSOCK +#undef EBADF /* override definition in errno.h */ +#define EBADF WSAEBADF +#undef EINTR /* override definition in errno.h */ +#define EINTR WSAEINTR +#undef EINVAL /* override definition in errno.h */ +#define EINVAL WSAEINVAL +#undef EWOULDBLOCK /* override definition in errno.h */ +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef EINPROGRESS /* override definition in errno.h */ +#define EINPROGRESS WSAEINPROGRESS +#undef EALREADY /* override definition in errno.h */ +#define EALREADY WSAEALREADY +#undef ENOTSOCK /* override definition in errno.h */ +#define ENOTSOCK WSAENOTSOCK +#undef EDESTADDRREQ /* override definition in errno.h */ +#define EDESTADDRREQ WSAEDESTADDRREQ +#undef EMSGSIZE /* override definition in errno.h */ +#define EMSGSIZE WSAEMSGSIZE +#undef EPROTOTYPE /* override definition in errno.h */ +#define EPROTOTYPE WSAEPROTOTYPE +#undef ENOPROTOOPT /* override definition in errno.h */ +#define ENOPROTOOPT WSAENOPROTOOPT +#undef EPROTONOSUPPORT /* override definition in errno.h */ +#define EPROTONOSUPPORT WSAEPROTONOSUPPORT +#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +#undef EOPNOTSUPP /* override definition in errno.h */ +#define EOPNOTSUPP WSAEOPNOTSUPP +#define EPFNOSUPPORT WSAEPFNOSUPPORT +#undef EAFNOSUPPORT /* override definition in errno.h */ +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#undef EADDRINUSE /* override definition in errno.h */ +#define EADDRINUSE WSAEADDRINUSE +#undef EADDRNOTAVAIL /* override definition in errno.h */ +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL +#undef ENETDOWN /* override definition in errno.h */ +#define ENETDOWN WSAENETDOWN +#undef ENETUNREACH /* override definition in errno.h */ +#define ENETUNREACH WSAENETUNREACH +#undef ENETRESET /* override definition in errno.h */ +#define ENETRESET WSAENETRESET +#undef ECONNABORTED /* override definition in errno.h */ +#define ECONNABORTED WSAECONNABORTED +#undef ECONNRESET /* override definition in errno.h */ +#define ECONNRESET WSAECONNRESET +#undef ENOBUFS /* override definition in errno.h */ +#define ENOBUFS WSAENOBUFS +#undef EISCONN /* override definition in errno.h */ +#define EISCONN WSAEISCONN +#undef ENOTCONN /* override definition in errno.h */ +#define ENOTCONN WSAENOTCONN +#define ESHUTDOWN WSAESHUTDOWN +#define ETOOMANYREFS WSAETOOMANYREFS +#undef ETIMEDOUT /* override definition in errno.h */ +#define ETIMEDOUT WSAETIMEDOUT +#undef ECONNREFUSED /* override definition in errno.h */ +#define ECONNREFUSED WSAECONNREFUSED +#undef ELOOP /* override definition in errno.h */ +#define ELOOP WSAELOOP +#ifndef ENAMETOOLONG /* possible previous definition in errno.h */ +#define ENAMETOOLONG WSAENAMETOOLONG +#endif +#define EHOSTDOWN WSAEHOSTDOWN +#undef EHOSTUNREACH /* override definition in errno.h */ +#define EHOSTUNREACH WSAEHOSTUNREACH +#ifndef ENOTEMPTY /* possible previous definition in errno.h */ +#define ENOTEMPTY WSAENOTEMPTY +#endif +#define EPROCLIM WSAEPROCLIM +#define EUSERS WSAEUSERS +#define EDQUOT WSAEDQUOT +#define ESTALE WSAESTALE +#define EREMOTE WSAEREMOTE +#endif + +/* + * Macro argv_item_t hides platform details to code using it. + */ + +#ifdef __VMS +#define argv_item_t __char_ptr32 +#else +#define argv_item_t char * +#endif + + +/* + * We use this ZERO_NULL to avoid picky compiler warnings, + * when assigning a NULL pointer to a function pointer var. + */ + +#define ZERO_NULL 0 + + +#endif /* HEADER_CURL_SETUP_ONCE_H */ diff --git a/libcurl/lib/curl_sha256.h b/libcurl/lib/curl_sha256.h new file mode 100644 index 0000000..6db4b04 --- /dev/null +++ b/libcurl/lib/curl_sha256.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_SHA256_H +#define HEADER_CURL_SHA256_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Florin Petriuc, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +void Curl_sha256it(unsigned char *outbuffer, + const unsigned char *input); + +#endif + +#endif /* HEADER_CURL_SHA256_H */ diff --git a/libcurl/lib/curl_sspi.c b/libcurl/lib/curl_sspi.c new file mode 100644 index 0000000..1d0de4e --- /dev/null +++ b/libcurl/lib/curl_sspi.c @@ -0,0 +1,236 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WINDOWS_SSPI + +#include +#include "curl_sspi.h" +#include "curl_multibyte.h" +#include "system_win32.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* We use our own typedef here since some headers might lack these */ +typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID); + +/* See definition of SECURITY_ENTRYPOINT in sspi.h */ +#ifdef UNICODE +# ifdef _WIN32_WCE +# define SECURITYENTRYPOINT L"InitSecurityInterfaceW" +# else +# define SECURITYENTRYPOINT "InitSecurityInterfaceW" +# endif +#else +# define SECURITYENTRYPOINT "InitSecurityInterfaceA" +#endif + +/* Handle of security.dll or secur32.dll, depending on Windows version */ +HMODULE s_hSecDll = NULL; + +/* Pointer to SSPI dispatch table */ +PSecurityFunctionTable s_pSecFn = NULL; + +/* + * Curl_sspi_global_init() + * + * This is used to load the Security Service Provider Interface (SSPI) + * dynamic link library portably across all Windows versions, without + * the need to directly link libcurl, nor the application using it, at + * build time. + * + * Once this function has been executed, Windows SSPI functions can be + * called through the Security Service Provider Interface dispatch table. + * + * Parameters: + * + * None. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_sspi_global_init(void) +{ + INITSECURITYINTERFACE_FN pInitSecurityInterface; + + /* If security interface is not yet initialized try to do this */ + if(!s_hSecDll) { + /* Security Service Provider Interface (SSPI) functions are located in + * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP + * have both these DLLs (security.dll forwards calls to secur32.dll) */ + + /* Load SSPI dll into the address space of the calling process */ + if(Curl_verify_windows_version(4, 0, PLATFORM_WINNT, VERSION_EQUAL)) + s_hSecDll = Curl_load_library(TEXT("security.dll")); + else + s_hSecDll = Curl_load_library(TEXT("secur32.dll")); + if(!s_hSecDll) + return CURLE_FAILED_INIT; + + /* Get address of the InitSecurityInterfaceA function from the SSPI dll */ + pInitSecurityInterface = + CURLX_FUNCTION_CAST(INITSECURITYINTERFACE_FN, + (GetProcAddress(s_hSecDll, SECURITYENTRYPOINT))); + if(!pInitSecurityInterface) + return CURLE_FAILED_INIT; + + /* Get pointer to Security Service Provider Interface dispatch table */ + s_pSecFn = pInitSecurityInterface(); + if(!s_pSecFn) + return CURLE_FAILED_INIT; + } + + return CURLE_OK; +} + +/* + * Curl_sspi_global_cleanup() + * + * This deinitializes the Security Service Provider Interface from libcurl. + * + * Parameters: + * + * None. + */ +void Curl_sspi_global_cleanup(void) +{ + if(s_hSecDll) { + FreeLibrary(s_hSecDll); + s_hSecDll = NULL; + s_pSecFn = NULL; + } +} + +/* + * Curl_create_sspi_identity() + * + * This is used to populate a SSPI identity structure based on the supplied + * username and password. + * + * Parameters: + * + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * identity [in/out] - The identity structure. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity) +{ + xcharp_u useranddomain; + xcharp_u user, dup_user; + xcharp_u domain, dup_domain; + xcharp_u passwd, dup_passwd; + size_t domlen = 0; + + domain.const_tchar_ptr = TEXT(""); + + /* Initialize the identity */ + memset(identity, 0, sizeof(*identity)); + + useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp); + if(!useranddomain.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + + user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\')); + if(!user.const_tchar_ptr) + user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/')); + + if(user.tchar_ptr) { + domain.tchar_ptr = useranddomain.tchar_ptr; + domlen = user.tchar_ptr - useranddomain.tchar_ptr; + user.tchar_ptr++; + } + else { + user.tchar_ptr = useranddomain.tchar_ptr; + domain.const_tchar_ptr = TEXT(""); + domlen = 0; + } + + /* Setup the identity's user and length */ + dup_user.tchar_ptr = _tcsdup(user.tchar_ptr); + if(!dup_user.tchar_ptr) { + Curl_unicodefree(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + identity->User = dup_user.tbyte_ptr; + identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr)); + dup_user.tchar_ptr = NULL; + + /* Setup the identity's domain and length */ + dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1)); + if(!dup_domain.tchar_ptr) { + Curl_unicodefree(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen); + *(dup_domain.tchar_ptr + domlen) = TEXT('\0'); + identity->Domain = dup_domain.tbyte_ptr; + identity->DomainLength = curlx_uztoul(domlen); + dup_domain.tchar_ptr = NULL; + + Curl_unicodefree(useranddomain.tchar_ptr); + + /* Setup the identity's password and length */ + passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp); + if(!passwd.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr); + if(!dup_passwd.tchar_ptr) { + Curl_unicodefree(passwd.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + identity->Password = dup_passwd.tbyte_ptr; + identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr)); + dup_passwd.tchar_ptr = NULL; + + Curl_unicodefree(passwd.tchar_ptr); + + /* Setup the identity's flags */ + identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY; + + return CURLE_OK; +} + +/* + * Curl_sspi_free_identity() + * + * This is used to free the contents of a SSPI identifier structure. + * + * Parameters: + * + * identity [in/out] - The identity structure. + */ +void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity) +{ + if(identity) { + Curl_safefree(identity->User); + Curl_safefree(identity->Password); + Curl_safefree(identity->Domain); + } +} + +#endif /* USE_WINDOWS_SSPI */ diff --git a/libcurl/lib/curl_sspi.h b/libcurl/lib/curl_sspi.h new file mode 100644 index 0000000..2bbf947 --- /dev/null +++ b/libcurl/lib/curl_sspi.h @@ -0,0 +1,350 @@ +#ifndef HEADER_CURL_SSPI_H +#define HEADER_CURL_SSPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WINDOWS_SSPI + +#include + +/* + * When including the following three headers, it is mandatory to define either + * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code. + */ + +#undef SECURITY_WIN32 +#undef SECURITY_KERNEL +#define SECURITY_WIN32 1 +#include +#include +#include + +CURLcode Curl_sspi_global_init(void); +void Curl_sspi_global_cleanup(void); + +/* This is used to populate the domain in a SSPI identity structure */ +CURLcode Curl_override_sspi_http_realm(const char *chlg, + SEC_WINNT_AUTH_IDENTITY *identity); + +/* This is used to generate an SSPI identity structure */ +CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity); + +/* This is used to free an SSPI identity structure */ +void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity); + +/* Forward-declaration of global variables defined in curl_sspi.c */ +extern HMODULE s_hSecDll; +extern PSecurityFunctionTable s_pSecFn; + +/* Provide some definitions missing in old headers */ +#define SP_NAME_DIGEST "WDigest" +#define SP_NAME_NTLM "NTLM" +#define SP_NAME_NEGOTIATE "Negotiate" +#define SP_NAME_KERBEROS "Kerberos" + +#ifndef ISC_REQ_USE_HTTP_STYLE +#define ISC_REQ_USE_HTTP_STYLE 0x01000000 +#endif + +#ifndef ISC_RET_REPLAY_DETECT +#define ISC_RET_REPLAY_DETECT 0x00000004 +#endif + +#ifndef ISC_RET_SEQUENCE_DETECT +#define ISC_RET_SEQUENCE_DETECT 0x00000008 +#endif + +#ifndef ISC_RET_CONFIDENTIALITY +#define ISC_RET_CONFIDENTIALITY 0x00000010 +#endif + +#ifndef ISC_RET_ALLOCATED_MEMORY +#define ISC_RET_ALLOCATED_MEMORY 0x00000100 +#endif + +#ifndef ISC_RET_STREAM +#define ISC_RET_STREAM 0x00008000 +#endif + +#ifndef SEC_E_INSUFFICIENT_MEMORY +# define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L) +#endif +#ifndef SEC_E_INVALID_HANDLE +# define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L) +#endif +#ifndef SEC_E_UNSUPPORTED_FUNCTION +# define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L) +#endif +#ifndef SEC_E_TARGET_UNKNOWN +# define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L) +#endif +#ifndef SEC_E_INTERNAL_ERROR +# define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L) +#endif +#ifndef SEC_E_SECPKG_NOT_FOUND +# define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L) +#endif +#ifndef SEC_E_NOT_OWNER +# define SEC_E_NOT_OWNER ((HRESULT)0x80090306L) +#endif +#ifndef SEC_E_CANNOT_INSTALL +# define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L) +#endif +#ifndef SEC_E_INVALID_TOKEN +# define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L) +#endif +#ifndef SEC_E_CANNOT_PACK +# define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L) +#endif +#ifndef SEC_E_QOP_NOT_SUPPORTED +# define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL) +#endif +#ifndef SEC_E_NO_IMPERSONATION +# define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL) +#endif +#ifndef SEC_E_LOGON_DENIED +# define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL) +#endif +#ifndef SEC_E_UNKNOWN_CREDENTIALS +# define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL) +#endif +#ifndef SEC_E_NO_CREDENTIALS +# define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL) +#endif +#ifndef SEC_E_MESSAGE_ALTERED +# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL) +#endif +#ifndef SEC_E_OUT_OF_SEQUENCE +# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L) +#endif +#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY +# define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L) +#endif +#ifndef SEC_E_BAD_PKGID +# define SEC_E_BAD_PKGID ((HRESULT)0x80090316L) +#endif +#ifndef SEC_E_CONTEXT_EXPIRED +# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L) +#endif +#ifndef SEC_E_INCOMPLETE_MESSAGE +# define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L) +#endif +#ifndef SEC_E_INCOMPLETE_CREDENTIALS +# define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L) +#endif +#ifndef SEC_E_BUFFER_TOO_SMALL +# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L) +#endif +#ifndef SEC_E_WRONG_PRINCIPAL +# define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L) +#endif +#ifndef SEC_E_TIME_SKEW +# define SEC_E_TIME_SKEW ((HRESULT)0x80090324L) +#endif +#ifndef SEC_E_UNTRUSTED_ROOT +# define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L) +#endif +#ifndef SEC_E_ILLEGAL_MESSAGE +# define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L) +#endif +#ifndef SEC_E_CERT_UNKNOWN +# define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L) +#endif +#ifndef SEC_E_CERT_EXPIRED +# define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L) +#endif +#ifndef SEC_E_ENCRYPT_FAILURE +# define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L) +#endif +#ifndef SEC_E_DECRYPT_FAILURE +# define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L) +#endif +#ifndef SEC_E_ALGORITHM_MISMATCH +# define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L) +#endif +#ifndef SEC_E_SECURITY_QOS_FAILED +# define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L) +#endif +#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED +# define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L) +#endif +#ifndef SEC_E_NO_TGT_REPLY +# define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L) +#endif +#ifndef SEC_E_NO_IP_ADDRESSES +# define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L) +#endif +#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE +# define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L) +#endif +#ifndef SEC_E_CRYPTO_SYSTEM_INVALID +# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L) +#endif +#ifndef SEC_E_MAX_REFERRALS_EXCEEDED +# define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L) +#endif +#ifndef SEC_E_MUST_BE_KDC +# define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L) +#endif +#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED +# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL) +#endif +#ifndef SEC_E_TOO_MANY_PRINCIPALS +# define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL) +#endif +#ifndef SEC_E_NO_PA_DATA +# define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL) +#endif +#ifndef SEC_E_PKINIT_NAME_MISMATCH +# define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL) +#endif +#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED +# define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL) +#endif +#ifndef SEC_E_SHUTDOWN_IN_PROGRESS +# define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL) +#endif +#ifndef SEC_E_KDC_INVALID_REQUEST +# define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L) +#endif +#ifndef SEC_E_KDC_UNABLE_TO_REFER +# define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L) +#endif +#ifndef SEC_E_KDC_UNKNOWN_ETYPE +# define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L) +#endif +#ifndef SEC_E_UNSUPPORTED_PREAUTH +# define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L) +#endif +#ifndef SEC_E_DELEGATION_REQUIRED +# define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L) +#endif +#ifndef SEC_E_BAD_BINDINGS +# define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L) +#endif +#ifndef SEC_E_MULTIPLE_ACCOUNTS +# define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L) +#endif +#ifndef SEC_E_NO_KERB_KEY +# define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L) +#endif +#ifndef SEC_E_CERT_WRONG_USAGE +# define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L) +#endif +#ifndef SEC_E_DOWNGRADE_DETECTED +# define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L) +#endif +#ifndef SEC_E_SMARTCARD_CERT_REVOKED +# define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L) +#endif +#ifndef SEC_E_ISSUING_CA_UNTRUSTED +# define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L) +#endif +#ifndef SEC_E_REVOCATION_OFFLINE_C +# define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L) +#endif +#ifndef SEC_E_PKINIT_CLIENT_FAILURE +# define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L) +#endif +#ifndef SEC_E_SMARTCARD_CERT_EXPIRED +# define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L) +#endif +#ifndef SEC_E_NO_S4U_PROT_SUPPORT +# define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L) +#endif +#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE +# define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L) +#endif +#ifndef SEC_E_REVOCATION_OFFLINE_KDC +# define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L) +#endif +#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC +# define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L) +#endif +#ifndef SEC_E_KDC_CERT_EXPIRED +# define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL) +#endif +#ifndef SEC_E_KDC_CERT_REVOKED +# define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL) +#endif +#ifndef SEC_E_INVALID_PARAMETER +# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL) +#endif +#ifndef SEC_E_DELEGATION_POLICY +# define SEC_E_DELEGATION_POLICY ((HRESULT)0x8009035EL) +#endif +#ifndef SEC_E_POLICY_NLTM_ONLY +# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL) +#endif + +#ifndef SEC_I_CONTINUE_NEEDED +# define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L) +#endif +#ifndef SEC_I_COMPLETE_NEEDED +# define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L) +#endif +#ifndef SEC_I_COMPLETE_AND_CONTINUE +# define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L) +#endif +#ifndef SEC_I_LOCAL_LOGON +# define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L) +#endif +#ifndef SEC_I_CONTEXT_EXPIRED +# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L) +#endif +#ifndef SEC_I_INCOMPLETE_CREDENTIALS +# define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L) +#endif +#ifndef SEC_I_RENEGOTIATE +# define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L) +#endif +#ifndef SEC_I_NO_LSA_CONTEXT +# define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L) +#endif +#ifndef SEC_I_SIGNATURE_NEEDED +# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL) +#endif + +#ifndef CRYPT_E_REVOKED +# define CRYPT_E_REVOKED ((HRESULT)0x80092010L) +#endif + +#ifdef UNICODE +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE +#else +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI +#endif + +/* + * Definitions required from ntsecapi.h are directly provided below this point + * to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h + */ +#define KERB_WRAP_NO_ENCRYPT 0x80000001 + +#endif /* USE_WINDOWS_SSPI */ + +#endif /* HEADER_CURL_SSPI_H */ diff --git a/libcurl/lib/curl_threads.c b/libcurl/lib/curl_threads.c new file mode 100644 index 0000000..8e5937a --- /dev/null +++ b/libcurl/lib/curl_threads.c @@ -0,0 +1,155 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#if defined(USE_THREADS_POSIX) +# ifdef HAVE_PTHREAD_H +# include +# endif +#elif defined(USE_THREADS_WIN32) +# ifdef HAVE_PROCESS_H +# include +# endif +#endif + +#include "curl_threads.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#if defined(USE_THREADS_POSIX) + +struct curl_actual_call { + unsigned int (*func)(void *); + void *arg; +}; + +static void *curl_thread_create_thunk(void *arg) +{ + struct curl_actual_call * ac = arg; + unsigned int (*func)(void *) = ac->func; + void *real_arg = ac->arg; + + free(ac); + + (*func)(real_arg); + + return 0; +} + +curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg) +{ + curl_thread_t t = malloc(sizeof(pthread_t)); + struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call)); + if(!(ac && t)) + goto err; + + ac->func = func; + ac->arg = arg; + + if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0) + goto err; + + return t; + +err: + free(t); + free(ac); + return curl_thread_t_null; +} + +void Curl_thread_destroy(curl_thread_t hnd) +{ + if(hnd != curl_thread_t_null) { + pthread_detach(*hnd); + free(hnd); + } +} + +int Curl_thread_join(curl_thread_t *hnd) +{ + int ret = (pthread_join(**hnd, NULL) == 0); + + free(*hnd); + *hnd = curl_thread_t_null; + + return ret; +} + +#elif defined(USE_THREADS_WIN32) + +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), + void *arg) +{ +#ifdef _WIN32_WCE + typedef HANDLE curl_win_thread_handle_t; +#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) + typedef unsigned long curl_win_thread_handle_t; +#else + typedef uintptr_t curl_win_thread_handle_t; +#endif + curl_thread_t t; + curl_win_thread_handle_t thread_handle; +#ifdef _WIN32_WCE + thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL); +#else + thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL); +#endif + t = (curl_thread_t)thread_handle; + if((t == 0) || (t == LongToHandle(-1L))) { +#ifdef _WIN32_WCE + DWORD gle = GetLastError(); + errno = ((gle == ERROR_ACCESS_DENIED || + gle == ERROR_NOT_ENOUGH_MEMORY) ? + EACCES : EINVAL); +#endif + return curl_thread_t_null; + } + return t; +} + +void Curl_thread_destroy(curl_thread_t hnd) +{ + CloseHandle(hnd); +} + +int Curl_thread_join(curl_thread_t *hnd) +{ +#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ + (_WIN32_WINNT < _WIN32_WINNT_VISTA) + int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); +#else + int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); +#endif + + Curl_thread_destroy(*hnd); + + *hnd = curl_thread_t_null; + + return ret; +} + +#endif /* USE_THREADS_* */ diff --git a/libcurl/lib/curl_threads.h b/libcurl/lib/curl_threads.h new file mode 100644 index 0000000..2a93644 --- /dev/null +++ b/libcurl/lib/curl_threads.h @@ -0,0 +1,64 @@ +#ifndef HEADER_CURL_THREADS_H +#define HEADER_CURL_THREADS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_THREADS_POSIX) +# define CURL_STDCALL +# define curl_mutex_t pthread_mutex_t +# define curl_thread_t pthread_t * +# define curl_thread_t_null (pthread_t *)0 +# define Curl_mutex_init(m) pthread_mutex_init(m, NULL) +# define Curl_mutex_acquire(m) pthread_mutex_lock(m) +# define Curl_mutex_release(m) pthread_mutex_unlock(m) +# define Curl_mutex_destroy(m) pthread_mutex_destroy(m) +#elif defined(USE_THREADS_WIN32) +# define CURL_STDCALL __stdcall +# define curl_mutex_t CRITICAL_SECTION +# define curl_thread_t HANDLE +# define curl_thread_t_null (HANDLE)0 +# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ + (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \ + (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) +# define Curl_mutex_init(m) InitializeCriticalSection(m) +# else +# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1) +# endif +# define Curl_mutex_acquire(m) EnterCriticalSection(m) +# define Curl_mutex_release(m) LeaveCriticalSection(m) +# define Curl_mutex_destroy(m) DeleteCriticalSection(m) +#endif + +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), + void *arg); + +void Curl_thread_destroy(curl_thread_t hnd); + +int Curl_thread_join(curl_thread_t *hnd); + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* HEADER_CURL_THREADS_H */ diff --git a/libcurl/lib/curlx.h b/libcurl/lib/curlx.h new file mode 100644 index 0000000..3e9b516 --- /dev/null +++ b/libcurl/lib/curlx.h @@ -0,0 +1,103 @@ +#ifndef HEADER_CURL_CURLX_H +#define HEADER_CURL_CURLX_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Defines protos and includes all header files that provide the curlx_* + * functions. The curlx_* functions are not part of the libcurl API, but are + * stand-alone functions whose sources can be built and linked by apps if need + * be. + */ + +#include +/* this is still a public header file that provides the curl_mprintf() + functions while they still are offered publicly. They will be made library- + private one day */ + +#include "strcase.h" +/* "strcase.h" provides the strcasecompare protos */ + +#include "strtoofft.h" +/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a + curl_off_t number from a given string. +*/ + +#include "nonblock.h" +/* "nonblock.h" provides curlx_nonblock() */ + +#include "warnless.h" +/* "warnless.h" provides functions: + + curlx_ultous() + curlx_ultouc() + curlx_uztosi() +*/ + +/* Now setup curlx_ * names for the functions that are to become curlx_ and + be removed from a future libcurl official API: + curlx_getenv + curlx_mprintf (and its variations) + curlx_strcasecompare + curlx_strncasecompare + +*/ + +#define curlx_getenv curl_getenv +#define curlx_mvsnprintf curl_mvsnprintf +#define curlx_msnprintf curl_msnprintf +#define curlx_maprintf curl_maprintf +#define curlx_mvaprintf curl_mvaprintf +#define curlx_msprintf curl_msprintf +#define curlx_mprintf curl_mprintf +#define curlx_mfprintf curl_mfprintf +#define curlx_mvsprintf curl_mvsprintf +#define curlx_mvprintf curl_mvprintf +#define curlx_mvfprintf curl_mvfprintf + +#ifdef ENABLE_CURLX_PRINTF +/* If this define is set, we define all "standard" printf() functions to use + the curlx_* version instead. It makes the source code transparent and + easier to understand/patch. Undefine them first. */ +# undef printf +# undef fprintf +# undef sprintf +# undef msnprintf +# undef vprintf +# undef vfprintf +# undef vsprintf +# undef mvsnprintf +# undef aprintf +# undef vaprintf + +# define printf curlx_mprintf +# define fprintf curlx_mfprintf +# define sprintf curlx_msprintf +# define msnprintf curlx_msnprintf +# define vprintf curlx_mvprintf +# define vfprintf curlx_mvfprintf +# define mvsnprintf curlx_mvsnprintf +# define aprintf curlx_maprintf +# define vaprintf curlx_mvaprintf +#endif /* ENABLE_CURLX_PRINTF */ + +#endif /* HEADER_CURL_CURLX_H */ diff --git a/libcurl/lib/dict.c b/libcurl/lib/dict.c new file mode 100644 index 0000000..208a233 --- /dev/null +++ b/libcurl/lib/dict.c @@ -0,0 +1,276 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_DICT + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "escape.h" +#include "progress.h" +#include "dict.h" +#include "strcase.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static CURLcode dict_do(struct connectdata *conn, bool *done); + +/* + * DICT protocol handler. + */ + +const struct Curl_handler Curl_handler_dict = { + "DICT", /* scheme */ + ZERO_NULL, /* setup_connection */ + dict_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_DICT, /* defport */ + CURLPROTO_DICT, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + +static char *unescape_word(struct Curl_easy *data, const char *inputbuff) +{ + char *newp = NULL; + char *dictp; + size_t len; + + CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE); + if(!newp || result) + return NULL; + + dictp = malloc(len*2 + 1); /* add one for terminating zero */ + if(dictp) { + char *ptr; + char ch; + int olen = 0; + /* According to RFC2229 section 2.2, these letters need to be escaped with + \[letter] */ + for(ptr = newp; + (ch = *ptr) != 0; + ptr++) { + if((ch <= 32) || (ch == 127) || + (ch == '\'') || (ch == '\"') || (ch == '\\')) { + dictp[olen++] = '\\'; + } + dictp[olen++] = ch; + } + dictp[olen] = 0; + } + free(newp); + return dictp; +} + +static CURLcode dict_do(struct connectdata *conn, bool *done) +{ + char *word; + char *eword; + char *ppath; + char *database = NULL; + char *strategy = NULL; + char *nthdef = NULL; /* This is not part of the protocol, but required + by RFC 2229 */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + + char *path = data->state.up.path; + + *done = TRUE; /* unconditionally */ + + if(conn->bits.user_passwd) { + /* AUTH is missing */ + } + + if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) || + strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) || + strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) { + + word = strchr(path, ':'); + if(word) { + word++; + database = strchr(word, ':'); + if(database) { + *database++ = (char)0; + strategy = strchr(database, ':'); + if(strategy) { + *strategy++ = (char)0; + nthdef = strchr(strategy, ':'); + if(nthdef) { + *nthdef = (char)0; + } + } + } + } + + if((word == NULL) || (*word == (char)0)) { + infof(data, "lookup word is missing\n"); + word = (char *)"default"; + } + if((database == NULL) || (*database == (char)0)) { + database = (char *)"!"; + } + if((strategy == NULL) || (*strategy == (char)0)) { + strategy = (char *)"."; + } + + eword = unescape_word(data, word); + if(!eword) + return CURLE_OUT_OF_MEMORY; + + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "MATCH " + "%s " /* database */ + "%s " /* strategy */ + "%s\r\n" /* word */ + "QUIT\r\n", + + database, + strategy, + eword + ); + + free(eword); + + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */ + } + else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) || + strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) || + strncasecompare(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) { + + word = strchr(path, ':'); + if(word) { + word++; + database = strchr(word, ':'); + if(database) { + *database++ = (char)0; + nthdef = strchr(database, ':'); + if(nthdef) { + *nthdef = (char)0; + } + } + } + + if((word == NULL) || (*word == (char)0)) { + infof(data, "lookup word is missing\n"); + word = (char *)"default"; + } + if((database == NULL) || (*database == (char)0)) { + database = (char *)"!"; + } + + eword = unescape_word(data, word); + if(!eword) + return CURLE_OUT_OF_MEMORY; + + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "DEFINE " + "%s " /* database */ + "%s\r\n" /* word */ + "QUIT\r\n", + database, + eword); + + free(eword); + + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + } + else { + + ppath = strchr(path, '/'); + if(ppath) { + int i; + + ppath++; + for(i = 0; ppath[i]; i++) { + if(ppath[i] == ':') + ppath[i] = ' '; + } + result = Curl_sendf(sockfd, conn, + "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" + "%s\r\n" + "QUIT\r\n", ppath); + if(result) { + failf(data, "Failed sending DICT request"); + return result; + } + + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + } + } + + return CURLE_OK; +} +#endif /*CURL_DISABLE_DICT*/ diff --git a/libcurl/lib/dict.h b/libcurl/lib/dict.h new file mode 100644 index 0000000..12c0f33 --- /dev/null +++ b/libcurl/lib/dict.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_DICT_H +#define HEADER_CURL_DICT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_DICT +extern const struct Curl_handler Curl_handler_dict; +#endif + +#endif /* HEADER_CURL_DICT_H */ diff --git a/libcurl/lib/doh.c b/libcurl/lib/doh.c new file mode 100644 index 0000000..6d1f330 --- /dev/null +++ b/libcurl/lib/doh.c @@ -0,0 +1,967 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_DOH + +#include "urldata.h" +#include "curl_addrinfo.h" +#include "doh.h" + +#include "sendf.h" +#include "multiif.h" +#include "url.h" +#include "share.h" +#include "curl_base64.h" +#include "connect.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define DNS_CLASS_IN 0x01 +#define DOH_MAX_RESPONSE_SIZE 3000 /* bytes */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static const char * const errors[]={ + "", + "Bad label", + "Out of range", + "Label loop", + "Too small", + "Out of memory", + "RDATA length", + "Malformat", + "Bad RCODE", + "Unexpected TYPE", + "Unexpected CLASS", + "No content", + "Bad ID" +}; + +static const char *doh_strerror(DOHcode code) +{ + if((code >= DOH_OK) && (code <= DOH_DNS_BAD_ID)) + return errors[code]; + return "bad error code"; +} +#endif + +#ifdef DEBUGBUILD +#define UNITTEST +#else +#define UNITTEST static +#endif + +UNITTEST DOHcode doh_encode(const char *host, + DNStype dnstype, + unsigned char *dnsp, /* buffer */ + size_t len, /* buffer size */ + size_t *olen) /* output length */ +{ + size_t hostlen = strlen(host); + unsigned char *orig = dnsp; + const char *hostp = host; + + if(len < (12 + hostlen + 4)) + return DOH_TOO_SMALL_BUFFER; + + *dnsp++ = 0; /* 16 bit id */ + *dnsp++ = 0; + *dnsp++ = 0x01; /* |QR| Opcode |AA|TC|RD| Set the RD bit */ + *dnsp++ = '\0'; /* |RA| Z | RCODE | */ + *dnsp++ = '\0'; + *dnsp++ = 1; /* QDCOUNT (number of entries in the question section) */ + *dnsp++ = '\0'; + *dnsp++ = '\0'; /* ANCOUNT */ + *dnsp++ = '\0'; + *dnsp++ = '\0'; /* NSCOUNT */ + *dnsp++ = '\0'; + *dnsp++ = '\0'; /* ARCOUNT */ + + /* store a QNAME */ + do { + char *dot = strchr(hostp, '.'); + size_t labellen; + bool found = false; + if(dot) { + found = true; + labellen = dot - hostp; + } + else + labellen = strlen(hostp); + if(labellen > 63) { + /* too long label, error out */ + *olen = 0; + return DOH_DNS_BAD_LABEL; + } + *dnsp++ = (unsigned char)labellen; + memcpy(dnsp, hostp, labellen); + dnsp += labellen; + hostp += labellen + 1; + if(!found) { + *dnsp++ = 0; /* terminating zero */ + break; + } + } while(1); + + *dnsp++ = '\0'; /* upper 8 bit TYPE */ + *dnsp++ = (unsigned char)dnstype; + *dnsp++ = '\0'; /* upper 8 bit CLASS */ + *dnsp++ = DNS_CLASS_IN; /* IN - "the Internet" */ + + *olen = dnsp - orig; + return DOH_OK; +} + +static size_t +doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t realsize = size * nmemb; + struct dohresponse *mem = (struct dohresponse *)userp; + + if((mem->size + realsize) > DOH_MAX_RESPONSE_SIZE) + /* suspiciously much for us */ + return 0; + + mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize); + if(!mem->memory) + /* out of memory! */ + return 0; + + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + + return realsize; +} + +/* called from multi.c when this DOH transfer is complete */ +static int Curl_doh_done(struct Curl_easy *doh, CURLcode result) +{ + struct Curl_easy *data = doh->set.dohfor; + /* so one of the DOH request done for the 'data' transfer is now complete! */ + data->req.doh.pending--; + infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending); + if(result) + infof(data, "DOH request %s\n", curl_easy_strerror(result)); + + if(!data->req.doh.pending) { + /* DOH completed */ + curl_slist_free_all(data->req.doh.headers); + data->req.doh.headers = NULL; + Curl_expire(data, 0, EXPIRE_RUN_NOW); + } + return 0; +} + +#define ERROR_CHECK_SETOPT(x,y) \ +do { \ + result = curl_easy_setopt(doh, x, y); \ + if(result) \ + goto error; \ +} WHILE_FALSE + +static CURLcode dohprobe(struct Curl_easy *data, + struct dnsprobe *p, DNStype dnstype, + const char *host, + const char *url, CURLM *multi, + struct curl_slist *headers) +{ + struct Curl_easy *doh = NULL; + char *nurl = NULL; + CURLcode result = CURLE_OK; + timediff_t timeout_ms; + DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer), + &p->dohlen); + if(d) { + failf(data, "Failed to encode DOH packet [%d]\n", d); + return CURLE_OUT_OF_MEMORY; + } + + p->dnstype = dnstype; + p->serverdoh.memory = NULL; + /* the memory will be grown as needed by realloc in the doh_write_cb + function */ + p->serverdoh.size = 0; + + /* Note: this is code for sending the DoH request with GET but there's still + no logic that actually enables this. We should either add that ability or + yank out the GET code. Discuss! */ + if(data->set.doh_get) { + char *b64; + size_t b64len; + result = Curl_base64url_encode(data, (char *)p->dohbuffer, p->dohlen, + &b64, &b64len); + if(result) + goto error; + nurl = aprintf("%s?dns=%s", url, b64); + free(b64); + if(!nurl) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + url = nurl; + } + + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + /* Curl_open() is the internal version of curl_easy_init() */ + result = Curl_open(&doh); + if(!result) { + /* pass in the struct pointer via a local variable to please coverity and + the gcc typecheck helpers */ + struct dohresponse *resp = &p->serverdoh; + ERROR_CHECK_SETOPT(CURLOPT_URL, url); + ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb); + ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp); + if(!data->set.doh_get) { + ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer); + ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen); + } + ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers); +#ifdef USE_NGHTTP2 + ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); +#endif +#ifndef CURLDEBUG + /* enforce HTTPS if not debug */ + ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); +#endif + ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms); + if(data->set.verbose) + ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L); + if(data->set.no_signal) + ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L); + + /* Inherit *some* SSL options from the user's transfer. This is a + best-guess as to which options are needed for compatibility. #3661 */ + if(data->set.ssl.falsestart) + ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L); + if(data->set.ssl.primary.verifyhost) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L); + if(data->set.proxy_ssl.primary.verifyhost) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L); + if(data->set.ssl.primary.verifypeer) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L); + if(data->set.proxy_ssl.primary.verifypeer) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L); + if(data->set.ssl.primary.verifystatus) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L); + if(data->set.str[STRING_SSL_CAFILE_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CAINFO, + data->set.str[STRING_SSL_CAFILE_ORIG]); + } + if(data->set.str[STRING_SSL_CAFILE_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO, + data->set.str[STRING_SSL_CAFILE_PROXY]); + } + if(data->set.str[STRING_SSL_CAPATH_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CAPATH, + data->set.str[STRING_SSL_CAPATH_ORIG]); + } + if(data->set.str[STRING_SSL_CAPATH_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH, + data->set.str[STRING_SSL_CAPATH_PROXY]); + } + if(data->set.str[STRING_SSL_CRLFILE_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, + data->set.str[STRING_SSL_CRLFILE_ORIG]); + } + if(data->set.str[STRING_SSL_CRLFILE_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE, + data->set.str[STRING_SSL_CRLFILE_PROXY]); + } + if(data->set.ssl.certinfo) + ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L); + if(data->set.str[STRING_SSL_RANDOM_FILE]) { + ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE, + data->set.str[STRING_SSL_RANDOM_FILE]); + } + if(data->set.str[STRING_SSL_EGDSOCKET]) { + ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET, + data->set.str[STRING_SSL_EGDSOCKET]); + } + if(data->set.ssl.no_revoke) + ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + if(data->set.proxy_ssl.no_revoke) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + if(data->set.ssl.fsslctx) + ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx); + if(data->set.ssl.fsslctxp) + ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp); + + doh->set.fmultidone = Curl_doh_done; + doh->set.dohfor = data; /* identify for which transfer this is done */ + p->easy = doh; + + /* add this transfer to the multi handle */ + if(curl_multi_add_handle(multi, doh)) + goto error; + } + else + goto error; + free(nurl); + return CURLE_OK; + + error: + free(nurl); + Curl_close(doh); + return result; +} + +/* + * Curl_doh() resolves a name using DOH. It resolves a name and returns a + * 'Curl_addrinfo *' with the address information. + */ + +Curl_addrinfo *Curl_doh(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + *waitp = TRUE; /* this never returns synchronously */ + (void)conn; + (void)hostname; + (void)port; + + /* start clean, consider allocating this struct on demand */ + memset(&data->req.doh, 0, sizeof(struct dohdata)); + + data->req.doh.host = hostname; + data->req.doh.port = port; + data->req.doh.headers = + curl_slist_append(NULL, + "Content-Type: application/dns-message"); + if(!data->req.doh.headers) + goto error; + + if(conn->ip_version != CURL_IPRESOLVE_V6) { + /* create IPv4 DOH request */ + result = dohprobe(data, &data->req.doh.probe[0], DNS_TYPE_A, + hostname, data->set.str[STRING_DOH], + data->multi, data->req.doh.headers); + if(result) + goto error; + data->req.doh.pending++; + } + + if(conn->ip_version != CURL_IPRESOLVE_V4) { + /* create IPv6 DOH request */ + result = dohprobe(data, &data->req.doh.probe[1], DNS_TYPE_AAAA, + hostname, data->set.str[STRING_DOH], + data->multi, data->req.doh.headers); + if(result) + goto error; + data->req.doh.pending++; + } + return NULL; + + error: + curl_slist_free_all(data->req.doh.headers); + data->req.doh.headers = NULL; + curl_easy_cleanup(data->req.doh.probe[0].easy); + data->req.doh.probe[0].easy = NULL; + curl_easy_cleanup(data->req.doh.probe[1].easy); + data->req.doh.probe[1].easy = NULL; + return NULL; +} + +static DOHcode skipqname(unsigned char *doh, size_t dohlen, + unsigned int *indexp) +{ + unsigned char length; + do { + if(dohlen < (*indexp + 1)) + return DOH_DNS_OUT_OF_RANGE; + length = doh[*indexp]; + if((length & 0xc0) == 0xc0) { + /* name pointer, advance over it and be done */ + if(dohlen < (*indexp + 2)) + return DOH_DNS_OUT_OF_RANGE; + *indexp += 2; + break; + } + if(length & 0xc0) + return DOH_DNS_BAD_LABEL; + if(dohlen < (*indexp + 1 + length)) + return DOH_DNS_OUT_OF_RANGE; + *indexp += 1 + length; + } while(length); + return DOH_OK; +} + +static unsigned short get16bit(unsigned char *doh, int index) +{ + return (unsigned short)((doh[index] << 8) | doh[index + 1]); +} + +static unsigned int get32bit(unsigned char *doh, int index) +{ + return (doh[index] << 24) | (doh[index + 1] << 16) | + (doh[index + 2] << 8) | doh[index + 3]; +} + +static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d) +{ + /* silently ignore addresses over the limit */ + if(d->numaddr < DOH_MAX_ADDR) { + struct dohaddr *a = &d->addr[d->numaddr]; + a->type = DNS_TYPE_A; + memcpy(&a->ip.v4, &doh[index], 4); + d->numaddr++; + } + return DOH_OK; +} + +static DOHcode store_aaaa(unsigned char *doh, int index, struct dohentry *d) +{ + /* silently ignore addresses over the limit */ + if(d->numaddr < DOH_MAX_ADDR) { + struct dohaddr *a = &d->addr[d->numaddr]; + a->type = DNS_TYPE_AAAA; + memcpy(&a->ip.v6, &doh[index], 16); + d->numaddr++; + } + return DOH_OK; +} + +static DOHcode cnameappend(struct cnamestore *c, + unsigned char *src, + size_t len) +{ + if(!c->alloc) { + c->allocsize = len + 1; + c->alloc = malloc(c->allocsize); + if(!c->alloc) + return DOH_OUT_OF_MEM; + } + else if(c->allocsize < (c->allocsize + len + 1)) { + char *ptr; + c->allocsize += len + 1; + ptr = realloc(c->alloc, c->allocsize); + if(!ptr) { + free(c->alloc); + return DOH_OUT_OF_MEM; + } + c->alloc = ptr; + } + memcpy(&c->alloc[c->len], src, len); + c->len += len; + c->alloc[c->len] = 0; /* keep it zero terminated */ + return DOH_OK; +} + +static DOHcode store_cname(unsigned char *doh, + size_t dohlen, + unsigned int index, + struct dohentry *d) +{ + struct cnamestore *c; + unsigned int loop = 128; /* a valid DNS name can never loop this much */ + unsigned char length; + + if(d->numcname == DOH_MAX_CNAME) + return DOH_OK; /* skip! */ + + c = &d->cname[d->numcname++]; + do { + if(index >= dohlen) + return DOH_DNS_OUT_OF_RANGE; + length = doh[index]; + if((length & 0xc0) == 0xc0) { + int newpos; + /* name pointer, get the new offset (14 bits) */ + if((index + 1) >= dohlen) + return DOH_DNS_OUT_OF_RANGE; + + /* move to the the new index */ + newpos = (length & 0x3f) << 8 | doh[index + 1]; + index = newpos; + continue; + } + else if(length & 0xc0) + return DOH_DNS_BAD_LABEL; /* bad input */ + else + index++; + + if(length) { + DOHcode rc; + if(c->len) { + rc = cnameappend(c, (unsigned char *)".", 1); + if(rc) + return rc; + } + if((index + length) > dohlen) + return DOH_DNS_BAD_LABEL; + + rc = cnameappend(c, &doh[index], length); + if(rc) + return rc; + index += length; + } + } while(length && --loop); + + if(!loop) + return DOH_DNS_LABEL_LOOP; + return DOH_OK; +} + +static DOHcode rdata(unsigned char *doh, + size_t dohlen, + unsigned short rdlength, + unsigned short type, + int index, + struct dohentry *d) +{ + /* RDATA + - A (TYPE 1): 4 bytes + - AAAA (TYPE 28): 16 bytes + - NS (TYPE 2): N bytes */ + DOHcode rc; + + switch(type) { + case DNS_TYPE_A: + if(rdlength != 4) + return DOH_DNS_RDATA_LEN; + rc = store_a(doh, index, d); + if(rc) + return rc; + break; + case DNS_TYPE_AAAA: + if(rdlength != 16) + return DOH_DNS_RDATA_LEN; + rc = store_aaaa(doh, index, d); + if(rc) + return rc; + break; + case DNS_TYPE_CNAME: + rc = store_cname(doh, dohlen, index, d); + if(rc) + return rc; + break; + default: + /* unsupported type, just skip it */ + break; + } + return DOH_OK; +} + +static void init_dohentry(struct dohentry *de) +{ + memset(de, 0, sizeof(*de)); + de->ttl = INT_MAX; +} + + +UNITTEST DOHcode doh_decode(unsigned char *doh, + size_t dohlen, + DNStype dnstype, + struct dohentry *d) +{ + unsigned char rcode; + unsigned short qdcount; + unsigned short ancount; + unsigned short type = 0; + unsigned short rdlength; + unsigned short nscount; + unsigned short arcount; + unsigned int index = 12; + DOHcode rc; + + if(dohlen < 12) + return DOH_TOO_SMALL_BUFFER; /* too small */ + if(!doh || doh[0] || doh[1]) + return DOH_DNS_BAD_ID; /* bad ID */ + rcode = doh[3] & 0x0f; + if(rcode) + return DOH_DNS_BAD_RCODE; /* bad rcode */ + + qdcount = get16bit(doh, 4); + while(qdcount) { + rc = skipqname(doh, dohlen, &index); + if(rc) + return rc; /* bad qname */ + if(dohlen < (index + 4)) + return DOH_DNS_OUT_OF_RANGE; + index += 4; /* skip question's type and class */ + qdcount--; + } + + ancount = get16bit(doh, 6); + while(ancount) { + unsigned short class; + unsigned int ttl; + + rc = skipqname(doh, dohlen, &index); + if(rc) + return rc; /* bad qname */ + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + + type = get16bit(doh, index); + if((type != DNS_TYPE_CNAME) && (type != dnstype)) + /* Not the same type as was asked for nor CNAME */ + return DOH_DNS_UNEXPECTED_TYPE; + index += 2; + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + class = get16bit(doh, index); + if(DNS_CLASS_IN != class) + return DOH_DNS_UNEXPECTED_CLASS; /* unsupported */ + index += 2; + + if(dohlen < (index + 4)) + return DOH_DNS_OUT_OF_RANGE; + + ttl = get32bit(doh, index); + if(ttl < d->ttl) + d->ttl = ttl; + index += 4; + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + + rdlength = get16bit(doh, index); + index += 2; + if(dohlen < (index + rdlength)) + return DOH_DNS_OUT_OF_RANGE; + + rc = rdata(doh, dohlen, rdlength, type, index, d); + if(rc) + return rc; /* bad rdata */ + index += rdlength; + ancount--; + } + + nscount = get16bit(doh, 8); + while(nscount) { + rc = skipqname(doh, dohlen, &index); + if(rc) + return rc; /* bad qname */ + + if(dohlen < (index + 8)) + return DOH_DNS_OUT_OF_RANGE; + + index += 2 + 2 + 4; /* type, class and ttl */ + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + + rdlength = get16bit(doh, index); + index += 2; + if(dohlen < (index + rdlength)) + return DOH_DNS_OUT_OF_RANGE; + index += rdlength; + nscount--; + } + + arcount = get16bit(doh, 10); + while(arcount) { + rc = skipqname(doh, dohlen, &index); + if(rc) + return rc; /* bad qname */ + + if(dohlen < (index + 8)) + return DOH_DNS_OUT_OF_RANGE; + + index += 2 + 2 + 4; /* type, class and ttl */ + + if(dohlen < (index + 2)) + return DOH_DNS_OUT_OF_RANGE; + + rdlength = get16bit(doh, index); + index += 2; + if(dohlen < (index + rdlength)) + return DOH_DNS_OUT_OF_RANGE; + index += rdlength; + arcount--; + } + + if(index != dohlen) + return DOH_DNS_MALFORMAT; /* something is wrong */ + + if((type != DNS_TYPE_NS) && !d->numcname && !d->numaddr) + /* nothing stored! */ + return DOH_NO_CONTENT; + + return DOH_OK; /* ok */ +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void showdoh(struct Curl_easy *data, + struct dohentry *d) +{ + int i; + infof(data, "TTL: %u seconds\n", d->ttl); + for(i = 0; i < d->numaddr; i++) { + struct dohaddr *a = &d->addr[i]; + if(a->type == DNS_TYPE_A) { + infof(data, "DOH A: %u.%u.%u.%u\n", + a->ip.v4[0], a->ip.v4[1], + a->ip.v4[2], a->ip.v4[3]); + } + else if(a->type == DNS_TYPE_AAAA) { + int j; + char buffer[128]; + char *ptr; + size_t len; + msnprintf(buffer, 128, "DOH AAAA: "); + ptr = &buffer[10]; + len = 118; + for(j = 0; j < 16; j += 2) { + size_t l; + msnprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j], + d->addr[i].ip.v6[j + 1]); + l = strlen(ptr); + len -= l; + ptr += l; + } + infof(data, "%s\n", buffer); + } + } + for(i = 0; i < d->numcname; i++) { + infof(data, "CNAME: %s\n", d->cname[i].alloc); + } +} +#else +#define showdoh(x,y) +#endif + +/* + * doh2ai() + * + * This function returns a pointer to the first element of a newly allocated + * Curl_addrinfo struct linked list filled with the data from a set of DOH + * lookups. Curl_addrinfo is meant to work like the addrinfo struct does for + * a IPv6 stack, but usable also for IPv4, all hosts and environments. + * + * The memory allocated by this function *MUST* be free'd later on calling + * Curl_freeaddrinfo(). For each successful call to this function there + * must be an associated call later to Curl_freeaddrinfo(). + */ + +static Curl_addrinfo * +doh2ai(const struct dohentry *de, const char *hostname, int port) +{ + Curl_addrinfo *ai; + Curl_addrinfo *prevai = NULL; + Curl_addrinfo *firstai = NULL; + struct sockaddr_in *addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 *addr6; +#endif + CURLcode result = CURLE_OK; + int i; + + if(!de) + /* no input == no output! */ + return NULL; + + for(i = 0; i < de->numaddr; i++) { + size_t ss_size; + CURL_SA_FAMILY_T addrtype; + if(de->addr[i].type == DNS_TYPE_AAAA) { +#ifndef ENABLE_IPV6 + /* we can't handle IPv6 addresses */ + continue; +#else + ss_size = sizeof(struct sockaddr_in6); + addrtype = AF_INET6; +#endif + } + else { + ss_size = sizeof(struct sockaddr_in); + addrtype = AF_INET; + } + + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) { + result = CURLE_OUT_OF_MEMORY; + break; + } + ai->ai_canonname = strdup(hostname); + if(!ai->ai_canonname) { + result = CURLE_OUT_OF_MEMORY; + free(ai); + break; + } + ai->ai_addr = calloc(1, ss_size); + if(!ai->ai_addr) { + result = CURLE_OUT_OF_MEMORY; + free(ai->ai_canonname); + free(ai); + break; + } + + if(!firstai) + /* store the pointer we want to return from this function */ + firstai = ai; + + if(prevai) + /* make the previous entry point to this */ + prevai->ai_next = ai; + + ai->ai_family = addrtype; + + /* we return all names as STREAM, so when using this address for TFTP + the type must be ignored and conn->socktype be used instead! */ + ai->ai_socktype = SOCK_STREAM; + + ai->ai_addrlen = (curl_socklen_t)ss_size; + + /* leave the rest of the struct filled with zero */ + + switch(ai->ai_family) { + case AF_INET: + addr = (void *)ai->ai_addr; /* storage area for this info */ + DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4)); + memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr)); + addr->sin_family = (CURL_SA_FAMILY_T)addrtype; + addr->sin_port = htons((unsigned short)port); + break; + +#ifdef ENABLE_IPV6 + case AF_INET6: + addr6 = (void *)ai->ai_addr; /* storage area for this info */ + DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6)); + memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr)); + addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype; + addr6->sin6_port = htons((unsigned short)port); + break; +#endif + } + + prevai = ai; + } + + if(result) { + Curl_freeaddrinfo(firstai); + firstai = NULL; + } + + return firstai; +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static const char *type2name(DNStype dnstype) +{ + return (dnstype == DNS_TYPE_A)?"A":"AAAA"; +} +#endif + +UNITTEST void de_cleanup(struct dohentry *d) +{ + int i = 0; + for(i = 0; i < d->numcname; i++) { + free(d->cname[i].alloc); + } +} + +CURLcode Curl_doh_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dnsp) +{ + struct Curl_easy *data = conn->data; + *dnsp = NULL; /* defaults to no response */ + + if(!data->req.doh.probe[0].easy && !data->req.doh.probe[1].easy) { + failf(data, "Could not DOH-resolve: %s", conn->async.hostname); + return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: + CURLE_COULDNT_RESOLVE_HOST; + } + else if(!data->req.doh.pending) { + DOHcode rc; + DOHcode rc2; + struct dohentry de; + /* remove DOH handles from multi handle and close them */ + curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy); + Curl_close(data->req.doh.probe[0].easy); + curl_multi_remove_handle(data->multi, data->req.doh.probe[1].easy); + Curl_close(data->req.doh.probe[1].easy); + + /* parse the responses, create the struct and return it! */ + init_dohentry(&de); + rc = doh_decode(data->req.doh.probe[0].serverdoh.memory, + data->req.doh.probe[0].serverdoh.size, + data->req.doh.probe[0].dnstype, + &de); + free(data->req.doh.probe[0].serverdoh.memory); + if(rc) { + infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc), + type2name(data->req.doh.probe[0].dnstype), + data->req.doh.host); + } + rc2 = doh_decode(data->req.doh.probe[1].serverdoh.memory, + data->req.doh.probe[1].serverdoh.size, + data->req.doh.probe[1].dnstype, + &de); + free(data->req.doh.probe[1].serverdoh.memory); + if(rc2) { + infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc2), + type2name(data->req.doh.probe[1].dnstype), + data->req.doh.host); + } + if(!rc || !rc2) { + struct Curl_dns_entry *dns; + struct Curl_addrinfo *ai; + + infof(data, "DOH Host name: %s\n", data->req.doh.host); + showdoh(data, &de); + + ai = doh2ai(&de, data->req.doh.host, data->req.doh.port); + if(!ai) { + de_cleanup(&de); + return CURLE_OUT_OF_MEMORY; + } + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* we got a response, store it in the cache */ + dns = Curl_cache_addr(data, ai, data->req.doh.host, data->req.doh.port); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + de_cleanup(&de); + if(!dns) + /* returned failure, bail out nicely */ + Curl_freeaddrinfo(ai); + else { + conn->async.dns = dns; + *dnsp = dns; + return CURLE_OK; + } + } + de_cleanup(&de); + + return CURLE_COULDNT_RESOLVE_HOST; + } + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_DOH */ diff --git a/libcurl/lib/doh.h b/libcurl/lib/doh.h new file mode 100644 index 0000000..34bfa6f --- /dev/null +++ b/libcurl/lib/doh.h @@ -0,0 +1,113 @@ +#ifndef HEADER_CURL_DOH_H +#define HEADER_CURL_DOH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "urldata.h" +#include "curl_addrinfo.h" + +#ifndef CURL_DISABLE_DOH + +/* + * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name + * and returns a 'Curl_addrinfo *' with the address information. + */ + +Curl_addrinfo *Curl_doh(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + +CURLcode Curl_doh_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns); + +int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); + +typedef enum { + DOH_OK, + DOH_DNS_BAD_LABEL, /* 1 */ + DOH_DNS_OUT_OF_RANGE, /* 2 */ + DOH_DNS_LABEL_LOOP, /* 3 */ + DOH_TOO_SMALL_BUFFER, /* 4 */ + DOH_OUT_OF_MEM, /* 5 */ + DOH_DNS_RDATA_LEN, /* 6 */ + DOH_DNS_MALFORMAT, /* 7 */ + DOH_DNS_BAD_RCODE, /* 8 - no such name */ + DOH_DNS_UNEXPECTED_TYPE, /* 9 */ + DOH_DNS_UNEXPECTED_CLASS, /* 10 */ + DOH_NO_CONTENT, /* 11 */ + DOH_DNS_BAD_ID /* 12 */ +} DOHcode; + +typedef enum { + DNS_TYPE_A = 1, + DNS_TYPE_NS = 2, + DNS_TYPE_CNAME = 5, + DNS_TYPE_AAAA = 28 +} DNStype; + +#define DOH_MAX_ADDR 24 +#define DOH_MAX_CNAME 4 + +struct cnamestore { + size_t len; /* length of cname */ + char *alloc; /* allocated pointer */ + size_t allocsize; /* allocated size */ +}; + +struct dohaddr { + int type; + union { + unsigned char v4[4]; /* network byte order */ + unsigned char v6[16]; + } ip; +}; + +struct dohentry { + unsigned int ttl; + int numaddr; + struct dohaddr addr[DOH_MAX_ADDR]; + int numcname; + struct cnamestore cname[DOH_MAX_CNAME]; +}; + + +#ifdef DEBUGBUILD +DOHcode doh_encode(const char *host, + DNStype dnstype, + unsigned char *dnsp, /* buffer */ + size_t len, /* buffer size */ + size_t *olen); /* output length */ +DOHcode doh_decode(unsigned char *doh, + size_t dohlen, + DNStype dnstype, + struct dohentry *d); +void de_cleanup(struct dohentry *d); +#endif + +#else /* if DOH is disabled */ +#define Curl_doh(a,b,c,d) NULL +#define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST +#endif + +#endif /* HEADER_CURL_DOH_H */ diff --git a/libcurl/lib/dotdot.c b/libcurl/lib/dotdot.c new file mode 100644 index 0000000..2c6177a --- /dev/null +++ b/libcurl/lib/dotdot.c @@ -0,0 +1,182 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "dotdot.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * "Remove Dot Segments" + * https://tools.ietf.org/html/rfc3986#section-5.2.4 + */ + +/* + * Curl_dedotdotify() + * @unittest: 1395 + * + * This function gets a zero-terminated path with dot and dotdot sequences + * passed in and strips them off according to the rules in RFC 3986 section + * 5.2.4. + * + * The function handles a query part ('?' + stuff) appended but it expects + * that fragments ('#' + stuff) have already been cut off. + * + * RETURNS + * + * an allocated dedotdotified output string + */ +char *Curl_dedotdotify(const char *input) +{ + size_t inlen = strlen(input); + char *clone; + size_t clen = inlen; /* the length of the cloned input */ + char *out = malloc(inlen + 1); + char *outptr; + char *orgclone; + char *queryp; + if(!out) + return NULL; /* out of memory */ + + *out = 0; /* zero terminates, for inputs like "./" */ + + /* get a cloned copy of the input */ + clone = strdup(input); + if(!clone) { + free(out); + return NULL; + } + orgclone = clone; + outptr = out; + + if(!*clone) { + /* zero length string, return that */ + free(out); + return clone; + } + + /* + * To handle query-parts properly, we must find it and remove it during the + * dotdot-operation and then append it again at the end to the output + * string. + */ + queryp = strchr(clone, '?'); + if(queryp) + *queryp = 0; + + do { + + /* A. If the input buffer begins with a prefix of "../" or "./", then + remove that prefix from the input buffer; otherwise, */ + + if(!strncmp("./", clone, 2)) { + clone += 2; + clen -= 2; + } + else if(!strncmp("../", clone, 3)) { + clone += 3; + clen -= 3; + } + + /* B. if the input buffer begins with a prefix of "/./" or "/.", where + "." is a complete path segment, then replace that prefix with "/" in + the input buffer; otherwise, */ + else if(!strncmp("/./", clone, 3)) { + clone += 2; + clen -= 2; + } + else if(!strcmp("/.", clone)) { + clone[1]='/'; + clone++; + clen -= 1; + } + + /* C. if the input buffer begins with a prefix of "/../" or "/..", where + ".." is a complete path segment, then replace that prefix with "/" in + the input buffer and remove the last segment and its preceding "/" (if + any) from the output buffer; otherwise, */ + + else if(!strncmp("/../", clone, 4)) { + clone += 3; + clen -= 3; + /* remove the last segment from the output buffer */ + while(outptr > out) { + outptr--; + if(*outptr == '/') + break; + } + *outptr = 0; /* zero-terminate where it stops */ + } + else if(!strcmp("/..", clone)) { + clone[2]='/'; + clone += 2; + clen -= 2; + /* remove the last segment from the output buffer */ + while(outptr > out) { + outptr--; + if(*outptr == '/') + break; + } + *outptr = 0; /* zero-terminate where it stops */ + } + + /* D. if the input buffer consists only of "." or "..", then remove + that from the input buffer; otherwise, */ + + else if(!strcmp(".", clone) || !strcmp("..", clone)) { + *clone = 0; + *out = 0; + } + + else { + /* E. move the first path segment in the input buffer to the end of + the output buffer, including the initial "/" character (if any) and + any subsequent characters up to, but not including, the next "/" + character or the end of the input buffer. */ + + do { + *outptr++ = *clone++; + clen--; + } while(*clone && (*clone != '/')); + *outptr = 0; + } + + } while(*clone); + + if(queryp) { + size_t qlen; + /* There was a query part, append that to the output. The 'clone' string + may now have been altered so we copy from the original input string + from the correct index. */ + size_t oindex = queryp - orgclone; + qlen = strlen(&input[oindex]); + memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */ + } + + free(orgclone); + return out; +} diff --git a/libcurl/lib/dotdot.h b/libcurl/lib/dotdot.h new file mode 100644 index 0000000..125af43 --- /dev/null +++ b/libcurl/lib/dotdot.h @@ -0,0 +1,25 @@ +#ifndef HEADER_CURL_DOTDOT_H +#define HEADER_CURL_DOTDOT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +char *Curl_dedotdotify(const char *input); +#endif /* HEADER_CURL_DOTDOT_H */ diff --git a/libcurl/lib/easy.c b/libcurl/lib/easy.c new file mode 100644 index 0000000..a4fff5b --- /dev/null +++ b/libcurl/lib/easy.c @@ -0,0 +1,1160 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * See comment in curl_memory.h for the explanation of this sanity check. + */ + +#ifdef CURLX_NO_MEMORY_CALLBACKS +#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined" +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "vtls/vtls.h" +#include "url.h" +#include "getinfo.h" +#include "hostip.h" +#include "share.h" +#include "strdup.h" +#include "progress.h" +#include "easyif.h" +#include "multiif.h" +#include "select.h" +#include "sendf.h" /* for failf function prototype */ +#include "connect.h" /* for Curl_getconnectinfo */ +#include "slist.h" +#include "mime.h" +#include "amigaos.h" +#include "non-ascii.h" +#include "warnless.h" +#include "multiif.h" +#include "sigpipe.h" +#include "ssh.h" +#include "setopt.h" +#include "http_digest.h" +#include "system_win32.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +void Curl_version_init(void); + +/* true globals -- for curl_global_init() and curl_global_cleanup() */ +static unsigned int initialized; +static long init_flags; + +/* + * strdup (and other memory functions) is redefined in complicated + * ways, but at this point it must be defined as the system-supplied strdup + * so the callback pointer is initialized correctly. + */ +#if defined(_WIN32_WCE) +#define system_strdup _strdup +#elif !defined(HAVE_STRDUP) +#define system_strdup curlx_strdup +#else +#define system_strdup strdup +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ +#endif + +#ifndef __SYMBIAN32__ +/* + * If a memory-using function (like curl_getenv) is used before + * curl_global_init() is called, we need to have these pointers set already. + */ +curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; +curl_free_callback Curl_cfree = (curl_free_callback)free; +curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; +curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; +curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) +curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif +#else +/* + * Symbian OS doesn't support initialization to code in writable static data. + * Initialization will occur in the curl_global_init() call. + */ +curl_malloc_callback Curl_cmalloc; +curl_free_callback Curl_cfree; +curl_realloc_callback Curl_crealloc; +curl_strdup_callback Curl_cstrdup; +curl_calloc_callback Curl_ccalloc; +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(default:4232) /* MSVC extension, dllimport identity */ +#endif + +/** + * curl_global_init() globally initializes curl given a bitwise set of the + * different features of what to initialize. + */ +static CURLcode global_init(long flags, bool memoryfuncs) +{ + if(initialized++) + return CURLE_OK; + + if(memoryfuncs) { + /* Setup the default memory functions here (again) */ + Curl_cmalloc = (curl_malloc_callback)malloc; + Curl_cfree = (curl_free_callback)free; + Curl_crealloc = (curl_realloc_callback)realloc; + Curl_cstrdup = (curl_strdup_callback)system_strdup; + Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) + Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif + } + + if(!Curl_ssl_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n")); + return CURLE_FAILED_INIT; + } + +#ifdef WIN32 + if(Curl_win32_init(flags)) { + DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#ifdef __AMIGA__ + if(!Curl_amiga_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#ifdef NETWARE + if(netware_init()) { + DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); + } +#endif + + if(Curl_resolver_global_init()) { + DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n")); + return CURLE_FAILED_INIT; + } + + (void)Curl_ipv6works(); + +#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT) + if(libssh2_init(0)) { + DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#if defined(USE_LIBSSH) + if(ssh_init()) { + DEBUGF(fprintf(stderr, "Error: libssh_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + + if(flags & CURL_GLOBAL_ACK_EINTR) + Curl_ack_eintr = 1; + + init_flags = flags; + + Curl_version_init(); + + return CURLE_OK; +} + + +/** + * curl_global_init() globally initializes curl given a bitwise set of the + * different features of what to initialize. + */ +CURLcode curl_global_init(long flags) +{ + return global_init(flags, TRUE); +} + +/* + * curl_global_init_mem() globally initializes curl and also registers the + * user provided callback routines. + */ +CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, + curl_free_callback f, curl_realloc_callback r, + curl_strdup_callback s, curl_calloc_callback c) +{ + /* Invalid input, return immediately */ + if(!m || !f || !r || !s || !c) + return CURLE_FAILED_INIT; + + if(initialized) { + /* Already initialized, don't do it again, but bump the variable anyway to + work like curl_global_init() and require the same amount of cleanup + calls. */ + initialized++; + return CURLE_OK; + } + + /* set memory functions before global_init() in case it wants memory + functions */ + Curl_cmalloc = m; + Curl_cfree = f; + Curl_cstrdup = s; + Curl_crealloc = r; + Curl_ccalloc = c; + + /* Call the actual init function, but without setting */ + return global_init(flags, FALSE); +} + +/** + * curl_global_cleanup() globally cleanups curl, uses the value of + * "init_flags" to determine what needs to be cleaned up and what doesn't. + */ +void curl_global_cleanup(void) +{ + if(!initialized) + return; + + if(--initialized) + return; + + Curl_ssl_cleanup(); + Curl_resolver_global_cleanup(); + +#ifdef WIN32 + Curl_win32_cleanup(init_flags); +#endif + + Curl_amiga_cleanup(); + +#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT) + (void)libssh2_exit(); +#endif + +#if defined(USE_LIBSSH) + (void)ssh_finalize(); +#endif + + init_flags = 0; +} + +/* + * curl_easy_init() is the external interface to alloc, setup and init an + * easy handle that is returned. If anything goes wrong, NULL is returned. + */ +struct Curl_easy *curl_easy_init(void) +{ + CURLcode result; + struct Curl_easy *data; + + /* Make sure we inited the global SSL stuff */ + if(!initialized) { + result = curl_global_init(CURL_GLOBAL_DEFAULT); + if(result) { + /* something in the global init failed, return nothing */ + DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); + return NULL; + } + } + + /* We use curl_open() with undefined URL so far */ + result = Curl_open(&data); + if(result) { + DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); + return NULL; + } + + return data; +} + +#ifdef CURLDEBUG + +struct socketmonitor { + struct socketmonitor *next; /* the next node in the list or NULL */ + struct pollfd socket; /* socket info of what to monitor */ +}; + +struct events { + long ms; /* timeout, run the timeout function when reached */ + bool msbump; /* set TRUE when timeout is set by callback */ + int num_sockets; /* number of nodes in the monitor list */ + struct socketmonitor *list; /* list of sockets to monitor */ + int running_handles; /* store the returned number */ +}; + +/* events_timer + * + * Callback that gets called with a new value when the timeout should be + * updated. + */ + +static int events_timer(struct Curl_multi *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp) /* private callback pointer */ +{ + struct events *ev = userp; + (void)multi; + if(timeout_ms == -1) + /* timeout removed */ + timeout_ms = 0; + else if(timeout_ms == 0) + /* timeout is already reached! */ + timeout_ms = 1; /* trigger asap */ + + ev->ms = timeout_ms; + ev->msbump = TRUE; + return 0; +} + + +/* poll2cselect + * + * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones + */ +static int poll2cselect(int pollmask) +{ + int omask = 0; + if(pollmask & POLLIN) + omask |= CURL_CSELECT_IN; + if(pollmask & POLLOUT) + omask |= CURL_CSELECT_OUT; + if(pollmask & POLLERR) + omask |= CURL_CSELECT_ERR; + return omask; +} + + +/* socketcb2poll + * + * convert from libcurl' CURL_POLL_* bit definitions to poll()'s + */ +static short socketcb2poll(int pollmask) +{ + short omask = 0; + if(pollmask & CURL_POLL_IN) + omask |= POLLIN; + if(pollmask & CURL_POLL_OUT) + omask |= POLLOUT; + return omask; +} + +/* events_socket + * + * Callback that gets called with information about socket activity to + * monitor. + */ +static int events_socket(struct Curl_easy *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp) /* private socket + pointer */ +{ + struct events *ev = userp; + struct socketmonitor *m; + struct socketmonitor *prev = NULL; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) easy; +#endif + (void)socketp; + + m = ev->list; + while(m) { + if(m->socket.fd == s) { + + if(what == CURL_POLL_REMOVE) { + struct socketmonitor *nxt = m->next; + /* remove this node from the list of monitored sockets */ + if(prev) + prev->next = nxt; + else + ev->list = nxt; + free(m); + m = nxt; + infof(easy, "socket cb: socket %d REMOVED\n", s); + } + else { + /* The socket 's' is already being monitored, update the activity + mask. Convert from libcurl bitmask to the poll one. */ + m->socket.events = socketcb2poll(what); + infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s, + (what&CURL_POLL_IN)?"IN":"", + (what&CURL_POLL_OUT)?"OUT":""); + } + break; + } + prev = m; + m = m->next; /* move to next node */ + } + if(!m) { + if(what == CURL_POLL_REMOVE) { + /* this happens a bit too often, libcurl fix perhaps? */ + /* fprintf(stderr, + "%s: socket %d asked to be REMOVED but not present!\n", + __func__, s); */ + } + else { + m = malloc(sizeof(struct socketmonitor)); + if(m) { + m->next = ev->list; + m->socket.fd = s; + m->socket.events = socketcb2poll(what); + m->socket.revents = 0; + ev->list = m; + infof(easy, "socket cb: socket %d ADDED as %s%s\n", s, + (what&CURL_POLL_IN)?"IN":"", + (what&CURL_POLL_OUT)?"OUT":""); + } + else + return CURLE_OUT_OF_MEMORY; + } + } + + return 0; +} + + +/* + * events_setup() + * + * Do the multi handle setups that only event-based transfers need. + */ +static void events_setup(struct Curl_multi *multi, struct events *ev) +{ + /* timer callback */ + curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer); + curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev); + + /* socket callback */ + curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket); + curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev); +} + + +/* wait_or_timeout() + * + * waits for activity on any of the given sockets, or the timeout to trigger. + */ + +static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) +{ + bool done = FALSE; + CURLMcode mcode = CURLM_OK; + CURLcode result = CURLE_OK; + + while(!done) { + CURLMsg *msg; + struct socketmonitor *m; + struct pollfd *f; + struct pollfd fds[4]; + int numfds = 0; + int pollrc; + int i; + struct curltime before; + struct curltime after; + + /* populate the fds[] array */ + for(m = ev->list, f = &fds[0]; m; m = m->next) { + f->fd = m->socket.fd; + f->events = m->socket.events; + f->revents = 0; + /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */ + f++; + numfds++; + } + + /* get the time stamp to use to figure out how long poll takes */ + before = Curl_now(); + + /* wait for activity or timeout */ + pollrc = Curl_poll(fds, numfds, (int)ev->ms); + + after = Curl_now(); + + ev->msbump = FALSE; /* reset here */ + + if(0 == pollrc) { + /* timeout! */ + ev->ms = 0; + /* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */ + mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, + &ev->running_handles); + } + else if(pollrc > 0) { + /* loop over the monitored sockets to see which ones had activity */ + for(i = 0; i< numfds; i++) { + if(fds[i].revents) { + /* socket activity, tell libcurl */ + int act = poll2cselect(fds[i].revents); /* convert */ + infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n", + fds[i].fd); + mcode = curl_multi_socket_action(multi, fds[i].fd, act, + &ev->running_handles); + } + } + + if(!ev->msbump) { + /* If nothing updated the timeout, we decrease it by the spent time. + * If it was updated, it has the new timeout time stored already. + */ + timediff_t timediff = Curl_timediff(after, before); + if(timediff > 0) { + if(timediff > ev->ms) + ev->ms = 0; + else + ev->ms -= (long)timediff; + } + } + } + else + return CURLE_RECV_ERROR; + + if(mcode) + return CURLE_URL_MALFORMAT; + + /* we don't really care about the "msgs_in_queue" value returned in the + second argument */ + msg = curl_multi_info_read(multi, &pollrc); + if(msg) { + result = msg->data.result; + done = TRUE; + } + } + + return result; +} + + +/* easy_events() + * + * Runs a transfer in a blocking manner using the events-based API + */ +static CURLcode easy_events(struct Curl_multi *multi) +{ + /* this struct is made static to allow it to be used after this function + returns and curl_multi_remove_handle() is called */ + static struct events evs = {2, FALSE, 0, NULL, 0}; + + /* if running event-based, do some further multi inits */ + events_setup(multi, &evs); + + return wait_or_timeout(multi, &evs); +} +#else /* CURLDEBUG */ +/* when not built with debug, this function doesn't exist */ +#define easy_events(x) CURLE_NOT_BUILT_IN +#endif + +static CURLcode easy_transfer(struct Curl_multi *multi) +{ + bool done = FALSE; + CURLMcode mcode = CURLM_OK; + CURLcode result = CURLE_OK; + + while(!done && !mcode) { + int still_running = 0; + bool gotsocket = FALSE; + + mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket); + + if(!mcode) { + if(!gotsocket) { + long sleep_ms; + + /* If it returns without any filedescriptor instantly, we need to + avoid busy-looping during periods where it has nothing particular + to wait for */ + curl_multi_timeout(multi, &sleep_ms); + if(sleep_ms) { + if(sleep_ms > 1000) + sleep_ms = 1000; + Curl_wait_ms((int)sleep_ms); + } + } + + mcode = curl_multi_perform(multi, &still_running); + } + + /* only read 'still_running' if curl_multi_perform() return OK */ + if(!mcode && !still_running) { + int rc; + CURLMsg *msg = curl_multi_info_read(multi, &rc); + if(msg) { + result = msg->data.result; + done = TRUE; + } + } + } + + /* Make sure to return some kind of error if there was a multi problem */ + if(mcode) { + result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY : + /* The other multi errors should never happen, so return + something suitably generic */ + CURLE_BAD_FUNCTION_ARGUMENT; + } + + return result; +} + + +/* + * easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + * + * CONCEPT: This function creates a multi handle, adds the easy handle to it, + * runs curl_multi_perform() until the transfer is done, then detaches the + * easy handle, destroys the multi handle and returns the easy handle's return + * code. + * + * REALITY: it can't just create and destroy the multi handle that easily. It + * needs to keep it around since if this easy handle is used again by this + * function, the same multi handle must be re-used so that the same pools and + * caches can be used. + * + * DEBUG: if 'events' is set TRUE, this function will use a replacement engine + * instead of curl_multi_perform() and use curl_multi_socket_action(). + */ +static CURLcode easy_perform(struct Curl_easy *data, bool events) +{ + struct Curl_multi *multi; + CURLMcode mcode; + CURLcode result = CURLE_OK; + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.errorbuffer) + /* clear this as early as possible */ + data->set.errorbuffer[0] = 0; + + if(data->multi) { + failf(data, "easy handle already used in multi handle"); + return CURLE_FAILED_INIT; + } + + if(data->multi_easy) + multi = data->multi_easy; + else { + /* this multi handle will only ever have a single easy handled attached + to it, so make it use minimal hashes */ + multi = Curl_multi_handle(1, 3); + if(!multi) + return CURLE_OUT_OF_MEMORY; + data->multi_easy = multi; + } + + if(multi->in_callback) + return CURLE_RECURSIVE_API_CALL; + + /* Copy the MAXCONNECTS option to the multi handle */ + curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); + + mcode = curl_multi_add_handle(multi, data); + if(mcode) { + curl_multi_cleanup(multi); + if(mcode == CURLM_OUT_OF_MEMORY) + return CURLE_OUT_OF_MEMORY; + return CURLE_FAILED_INIT; + } + + sigpipe_ignore(data, &pipe_st); + + /* assign this after curl_multi_add_handle() since that function checks for + it and rejects this handle otherwise */ + data->multi = multi; + + /* run the transfer */ + result = events ? easy_events(multi) : easy_transfer(multi); + + /* ignoring the return code isn't nice, but atm we can't really handle + a failure here, room for future improvement! */ + (void)curl_multi_remove_handle(multi, data); + + sigpipe_restore(&pipe_st); + + /* The multi handle is kept alive, owned by the easy handle */ + return result; +} + + +/* + * curl_easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + */ +CURLcode curl_easy_perform(struct Curl_easy *data) +{ + return easy_perform(data, FALSE); +} + +#ifdef CURLDEBUG +/* + * curl_easy_perform_ev() is the external interface that performs a blocking + * transfer using the event-based API internally. + */ +CURLcode curl_easy_perform_ev(struct Curl_easy *data) +{ + return easy_perform(data, TRUE); +} + +#endif + +/* + * curl_easy_cleanup() is the external interface to cleaning/freeing the given + * easy handle. + */ +void curl_easy_cleanup(struct Curl_easy *data) +{ + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return; + + sigpipe_ignore(data, &pipe_st); + Curl_close(data); + sigpipe_restore(&pipe_st); +} + +/* + * curl_easy_getinfo() is an external interface that allows an app to retrieve + * information from a performed transfer and similar. + */ +#undef curl_easy_getinfo +CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...) +{ + va_list arg; + void *paramp; + CURLcode result; + + va_start(arg, info); + paramp = va_arg(arg, void *); + + result = Curl_getinfo(data, info, paramp); + + va_end(arg); + return result; +} + +static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) +{ + CURLcode result = CURLE_OK; + enum dupstring i; + + /* Copy src->set into dst->set first, then deal with the strings + afterwards */ + dst->set = src->set; + Curl_mime_initpart(&dst->set.mimepost, dst); + + /* clear all string pointers first */ + memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); + + /* duplicate all strings */ + for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { + result = Curl_setstropt(&dst->set.str[i], src->set.str[i]); + if(result) + return result; + } + + /* duplicate memory areas pointed to */ + i = STRING_COPYPOSTFIELDS; + if(src->set.postfieldsize && src->set.str[i]) { + /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ + dst->set.str[i] = Curl_memdup(src->set.str[i], + curlx_sotouz(src->set.postfieldsize)); + if(!dst->set.str[i]) + return CURLE_OUT_OF_MEMORY; + /* point to the new copy */ + dst->set.postfields = dst->set.str[i]; + } + + /* Duplicate mime data. */ + result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost); + + if(src->set.resolve) + dst->change.resolve = dst->set.resolve; + + return result; +} + +/* + * curl_easy_duphandle() is an external interface to allow duplication of a + * given input easy handle. The returned handle will be a new working handle + * with all options set exactly as the input source handle. + */ +struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) +{ + struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy)); + if(NULL == outcurl) + goto fail; + + /* + * We setup a few buffers we need. We should probably make them + * get setup on-demand in the code, as that would probably decrease + * the likeliness of us forgetting to init a buffer here in the future. + */ + outcurl->set.buffer_size = data->set.buffer_size; + outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1); + if(!outcurl->state.buffer) + goto fail; + + outcurl->state.headerbuff = malloc(HEADERSIZE); + if(!outcurl->state.headerbuff) + goto fail; + outcurl->state.headersize = HEADERSIZE; + + /* copy all userdefined values */ + if(dupset(outcurl, data)) + goto fail; + + /* the connection cache is setup on demand */ + outcurl->state.conn_cache = NULL; + + outcurl->state.lastconnect = NULL; + + outcurl->progress.flags = data->progress.flags; + outcurl->progress.callback = data->progress.callback; + + if(data->cookies) { + /* If cookies are enabled in the parent handle, we enable them + in the clone as well! */ + outcurl->cookies = Curl_cookie_init(data, + data->cookies->filename, + outcurl->cookies, + data->set.cookiesession); + if(!outcurl->cookies) + goto fail; + } + + /* duplicate all values in 'change' */ + if(data->change.cookielist) { + outcurl->change.cookielist = + Curl_slist_duplicate(data->change.cookielist); + if(!outcurl->change.cookielist) + goto fail; + } + + if(data->change.url) { + outcurl->change.url = strdup(data->change.url); + if(!outcurl->change.url) + goto fail; + outcurl->change.url_alloc = TRUE; + } + + if(data->change.referer) { + outcurl->change.referer = strdup(data->change.referer); + if(!outcurl->change.referer) + goto fail; + outcurl->change.referer_alloc = TRUE; + } + + /* Reinitialize an SSL engine for the new handle + * note: the engine name has already been copied by dupset */ + if(outcurl->set.str[STRING_SSL_ENGINE]) { + if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE])) + goto fail; + } + + /* Clone the resolver handle, if present, for the new handle */ + if(Curl_resolver_duphandle(outcurl, + &outcurl->state.resolver, + data->state.resolver)) + goto fail; + + Curl_convert_setup(outcurl); + + Curl_initinfo(outcurl); + + outcurl->magic = CURLEASY_MAGIC_NUMBER; + + /* we reach this point and thus we are OK */ + + return outcurl; + + fail: + + if(outcurl) { + curl_slist_free_all(outcurl->change.cookielist); + outcurl->change.cookielist = NULL; + Curl_safefree(outcurl->state.buffer); + Curl_safefree(outcurl->state.headerbuff); + Curl_safefree(outcurl->change.url); + Curl_safefree(outcurl->change.referer); + Curl_freeset(outcurl); + free(outcurl); + } + + return NULL; +} + +/* + * curl_easy_reset() is an external interface that allows an app to re- + * initialize a session handle to the default values. + */ +void curl_easy_reset(struct Curl_easy *data) +{ + Curl_free_request_state(data); + + /* zero out UserDefined data: */ + Curl_freeset(data); + memset(&data->set, 0, sizeof(struct UserDefined)); + (void)Curl_init_userdefined(data); + + /* zero out Progress data: */ + memset(&data->progress, 0, sizeof(struct Progress)); + + /* zero out PureInfo data: */ + Curl_initinfo(data); + + data->progress.flags |= PGRS_HIDE; + data->state.current_speed = -1; /* init to negative == impossible */ + + /* zero out authentication data: */ + memset(&data->state.authhost, 0, sizeof(struct auth)); + memset(&data->state.authproxy, 0, sizeof(struct auth)); + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + Curl_http_auth_cleanup_digest(data); +#endif +} + +/* + * curl_easy_pause() allows an application to pause or unpause a specific + * transfer and direction. This function sets the full new state for the + * current connection this easy handle operates on. + * + * NOTE: if you have the receiving paused and you call this function to remove + * the pausing, you may get your write callback called at this point. + * + * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h + * + * NOTE: This is one of few API functions that are allowed to be called from + * within a callback. + */ +CURLcode curl_easy_pause(struct Curl_easy *data, int action) +{ + struct SingleRequest *k = &data->req; + CURLcode result = CURLE_OK; + + /* first switch off both pause bits */ + int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); + + /* set the new desired pause bits */ + newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | + ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); + + /* put it back in the keepon */ + k->keepon = newstate; + + if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) { + /* there are buffers for sending that can be delivered as the receive + pausing is lifted! */ + unsigned int i; + unsigned int count = data->state.tempcount; + struct tempbuf writebuf[3]; /* there can only be three */ + struct connectdata *conn = data->conn; + struct Curl_easy *saved_data = NULL; + + /* copy the structs to allow for immediate re-pausing */ + for(i = 0; i < data->state.tempcount; i++) { + writebuf[i] = data->state.tempwrite[i]; + data->state.tempwrite[i].buf = NULL; + } + data->state.tempcount = 0; + + /* set the connection's current owner */ + if(conn->data != data) { + saved_data = conn->data; + conn->data = data; + } + + for(i = 0; i < count; i++) { + /* even if one function returns error, this loops through and frees all + buffers */ + if(!result) + result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf, + writebuf[i].len); + free(writebuf[i].buf); + } + + /* recover previous owner of the connection */ + if(saved_data) + conn->data = saved_data; + + if(result) + return result; + } + + /* if there's no error and we're not pausing both directions, we want + to have this handle checked soon */ + if(!result && + ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != + (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) { + Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ + if(data->multi) + Curl_update_timer(data->multi); + } + + /* This transfer may have been moved in or out of the bundle, update + the corresponding socket callback, if used */ + Curl_updatesocket(data); + + return result; +} + + +static CURLcode easy_connection(struct Curl_easy *data, + curl_socket_t *sfd, + struct connectdata **connp) +{ + if(data == NULL) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ + if(!data->set.connect_only) { + failf(data, "CONNECT_ONLY is required!"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + *sfd = Curl_getconnectinfo(data, connp); + + if(*sfd == CURL_SOCKET_BAD) { + failf(data, "Failed to get recent socket"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + return CURLE_OK; +} + +/* + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + * Returns CURLE_OK on success, error code on error. + */ +CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen, + size_t *n) +{ + curl_socket_t sfd; + CURLcode result; + ssize_t n1; + struct connectdata *c; + + if(Curl_is_in_callback(data)) + return CURLE_RECURSIVE_API_CALL; + + result = easy_connection(data, &sfd, &c); + if(result) + return result; + + *n = 0; + result = Curl_read(c, sfd, buffer, buflen, &n1); + + if(result) + return result; + + *n = (size_t)n1; + + return CURLE_OK; +} + +/* + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, + size_t buflen, size_t *n) +{ + curl_socket_t sfd; + CURLcode result; + ssize_t n1; + struct connectdata *c = NULL; + + if(Curl_is_in_callback(data)) + return CURLE_RECURSIVE_API_CALL; + + result = easy_connection(data, &sfd, &c); + if(result) + return result; + + *n = 0; + result = Curl_write(c, sfd, buffer, buflen, &n1); + + if(n1 == -1) + return CURLE_SEND_ERROR; + + /* detect EAGAIN */ + if(!result && !n1) + return CURLE_AGAIN; + + *n = (size_t)n1; + + return result; +} + +/* + * Performs connection upkeep for the given session handle. + */ +CURLcode curl_easy_upkeep(struct Curl_easy *data) +{ + /* Verify that we got an easy handle we can work with. */ + if(!GOOD_EASY_HANDLE(data)) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->multi_easy) { + /* Use the common function to keep connections alive. */ + return Curl_upkeep(&data->multi_easy->conn_cache, data); + } + else { + /* No connections, so just return success */ + return CURLE_OK; + } +} diff --git a/libcurl/lib/easyif.h b/libcurl/lib/easyif.h new file mode 100644 index 0000000..6ba7e54 --- /dev/null +++ b/libcurl/lib/easyif.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_EASYIF_H +#define HEADER_CURL_EASYIF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by easy.c + */ +#ifdef CURLDEBUG +CURL_EXTERN CURLcode curl_easy_perform_ev(struct Curl_easy *easy); +#endif + +#endif /* HEADER_CURL_EASYIF_H */ diff --git a/libcurl/lib/escape.c b/libcurl/lib/escape.c new file mode 100644 index 0000000..7121db3 --- /dev/null +++ b/libcurl/lib/escape.c @@ -0,0 +1,244 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "warnless.h" +#include "non-ascii.h" +#include "escape.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Portable character check (remember EBCDIC). Do not use isalnum() because + its behavior is altered by the current locale. + See https://tools.ietf.org/html/rfc3986#section-2.3 +*/ +bool Curl_isunreserved(unsigned char in) +{ + switch(in) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '-': case '.': case '_': case '~': + return TRUE; + default: + break; + } + return FALSE; +} + +/* for ABI-compatibility with previous versions */ +char *curl_escape(const char *string, int inlength) +{ + return curl_easy_escape(NULL, string, inlength); +} + +/* for ABI-compatibility with previous versions */ +char *curl_unescape(const char *string, int length) +{ + return curl_easy_unescape(NULL, string, length, NULL); +} + +char *curl_easy_escape(struct Curl_easy *data, const char *string, + int inlength) +{ + size_t alloc; + char *ns; + char *testing_ptr = NULL; + size_t newlen; + size_t strindex = 0; + size_t length; + CURLcode result; + + if(inlength < 0) + return NULL; + + alloc = (inlength?(size_t)inlength:strlen(string)) + 1; + newlen = alloc; + + ns = malloc(alloc); + if(!ns) + return NULL; + + length = alloc-1; + while(length--) { + unsigned char in = *string; /* we need to treat the characters unsigned */ + + if(Curl_isunreserved(in)) + /* just copy this */ + ns[strindex++] = in; + else { + /* encode it */ + newlen += 2; /* the size grows with two, since this'll become a %XX */ + if(newlen > alloc) { + alloc *= 2; + testing_ptr = Curl_saferealloc(ns, alloc); + if(!testing_ptr) + return NULL; + ns = testing_ptr; + } + + result = Curl_convert_to_network(data, (char *)&in, 1); + if(result) { + /* Curl_convert_to_network calls failf if unsuccessful */ + free(ns); + return NULL; + } + + msnprintf(&ns[strindex], 4, "%%%02X", in); + + strindex += 3; + } + string++; + } + ns[strindex] = 0; /* terminate it */ + return ns; +} + +/* + * Curl_urldecode() URL decodes the given string. + * + * Optionally detects control characters (byte codes lower than 32) in the + * data and rejects such data. + * + * Returns a pointer to a malloced string in *ostring with length given in + * *olen. If length == 0, the length is assumed to be strlen(string). + * + * 'data' can be set to NULL but then this function can't convert network + * data to host for non-ascii. + */ +CURLcode Curl_urldecode(struct Curl_easy *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_ctrl) +{ + size_t alloc = (length?length:strlen(string)) + 1; + char *ns = malloc(alloc); + size_t strindex = 0; + unsigned long hex; + CURLcode result = CURLE_OK; + + if(!ns) + return CURLE_OUT_OF_MEMORY; + + while(--alloc > 0) { + unsigned char in = *string; + if(('%' == in) && (alloc > 2) && + ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { + /* this is two hexadecimal digits following a '%' */ + char hexstr[3]; + char *ptr; + hexstr[0] = string[1]; + hexstr[1] = string[2]; + hexstr[2] = 0; + + hex = strtoul(hexstr, &ptr, 16); + + in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */ + + if(data) { + result = Curl_convert_from_network(data, (char *)&in, 1); + if(result) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(ns); + return result; + } + } + + string += 2; + alloc -= 2; + } + + if(reject_ctrl && (in < 0x20)) { + free(ns); + return CURLE_URL_MALFORMAT; + } + + ns[strindex++] = in; + string++; + } + ns[strindex] = 0; /* terminate it */ + + if(olen) + /* store output size */ + *olen = strindex; + + /* store output string */ + *ostring = ns; + + return CURLE_OK; +} + +/* + * Unescapes the given URL escaped string of given length. Returns a + * pointer to a malloced string with length given in *olen. + * If length == 0, the length is assumed to be strlen(string). + * If olen == NULL, no output length is stored. + */ +char *curl_easy_unescape(struct Curl_easy *data, const char *string, + int length, int *olen) +{ + char *str = NULL; + if(length >= 0) { + size_t inputlen = length; + size_t outputlen; + CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen, + FALSE); + if(res) + return NULL; + + if(olen) { + if(outputlen <= (size_t) INT_MAX) + *olen = curlx_uztosi(outputlen); + else + /* too large to return in an int, fail! */ + Curl_safefree(str); + } + } + return str; +} + +/* For operating systems/environments that use different malloc/free + systems for the app and for this library, we provide a free that uses + the library's memory system */ +void curl_free(void *p) +{ + free(p); +} diff --git a/libcurl/lib/escape.h b/libcurl/lib/escape.h new file mode 100644 index 0000000..d8bbe5c --- /dev/null +++ b/libcurl/lib/escape.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_ESCAPE_H +#define HEADER_CURL_ESCAPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ + +bool Curl_isunreserved(unsigned char in); +CURLcode Curl_urldecode(struct Curl_easy *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_crlf); + +#endif /* HEADER_CURL_ESCAPE_H */ diff --git a/libcurl/lib/file.c b/libcurl/lib/file.c new file mode 100644 index 0000000..d349cd9 --- /dev/null +++ b/libcurl/lib/file.c @@ -0,0 +1,544 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FILE + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include "strtoofft.h" +#include "urldata.h" +#include +#include "progress.h" +#include "sendf.h" +#include "escape.h" +#include "file.h" +#include "speedcheck.h" +#include "getinfo.h" +#include "transfer.h" +#include "url.h" +#include "parsedate.h" /* for the week day and month names */ +#include "warnless.h" +#include "curl_range.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \ + defined(__SYMBIAN32__) +#define DOS_FILESYSTEM 1 +#endif + +#ifdef OPEN_NEEDS_ARG3 +# define open_readonly(p,f) open((p),(f),(0)) +#else +# define open_readonly(p,f) open((p),(f)) +#endif + +/* + * Forward declarations. + */ + +static CURLcode file_do(struct connectdata *, bool *done); +static CURLcode file_done(struct connectdata *conn, + CURLcode status, bool premature); +static CURLcode file_connect(struct connectdata *conn, bool *done); +static CURLcode file_disconnect(struct connectdata *conn, + bool dead_connection); +static CURLcode file_setup_connection(struct connectdata *conn); + +/* + * FILE scheme handler. + */ + +const struct Curl_handler Curl_handler_file = { + "FILE", /* scheme */ + file_setup_connection, /* setup_connection */ + file_do, /* do_it */ + file_done, /* done */ + ZERO_NULL, /* do_more */ + file_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + file_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + 0, /* defport */ + CURLPROTO_FILE, /* protocol */ + PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */ +}; + + +static CURLcode file_setup_connection(struct connectdata *conn) +{ + /* allocate the FILE specific struct */ + conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO)); + if(!conn->data->req.protop) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +/* + * file_connect() gets called from Curl_protocol_connect() to allow us to + * do protocol-specific actions at connect-time. We emulate a + * connect-then-transfer protocol and "connect" to the file here + */ +static CURLcode file_connect(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + char *real_path; + struct FILEPROTO *file = data->req.protop; + int fd; +#ifdef DOS_FILESYSTEM + size_t i; + char *actual_path; +#endif + size_t real_path_len; + + CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path, + &real_path_len, FALSE); + if(result) + return result; + +#ifdef DOS_FILESYSTEM + /* If the first character is a slash, and there's + something that looks like a drive at the beginning of + the path, skip the slash. If we remove the initial + slash in all cases, paths without drive letters end up + relative to the current directory which isn't how + browsers work. + + Some browsers accept | instead of : as the drive letter + separator, so we do too. + + On other platforms, we need the slash to indicate an + absolute pathname. On Windows, absolute paths start + with a drive letter. + */ + actual_path = real_path; + if((actual_path[0] == '/') && + actual_path[1] && + (actual_path[2] == ':' || actual_path[2] == '|')) { + actual_path[2] = ':'; + actual_path++; + real_path_len--; + } + + /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */ + for(i = 0; i < real_path_len; ++i) + if(actual_path[i] == '/') + actual_path[i] = '\\'; + else if(!actual_path[i]) { /* binary zero */ + Curl_safefree(real_path); + return CURLE_URL_MALFORMAT; + } + + fd = open_readonly(actual_path, O_RDONLY|O_BINARY); + file->path = actual_path; +#else + if(memchr(real_path, 0, real_path_len)) { + /* binary zeroes indicate foul play */ + Curl_safefree(real_path); + return CURLE_URL_MALFORMAT; + } + + fd = open_readonly(real_path, O_RDONLY); + file->path = real_path; +#endif + file->freepath = real_path; /* free this when done */ + + file->fd = fd; + if(!data->set.upload && (fd == -1)) { + failf(data, "Couldn't open file %s", data->state.up.path); + file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); + return CURLE_FILE_COULDNT_READ_FILE; + } + *done = TRUE; + + return CURLE_OK; +} + +static CURLcode file_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct FILEPROTO *file = conn->data->req.protop; + (void)status; /* not used */ + (void)premature; /* not used */ + + if(file) { + Curl_safefree(file->freepath); + file->path = NULL; + if(file->fd != -1) + close(file->fd); + file->fd = -1; + } + + return CURLE_OK; +} + +static CURLcode file_disconnect(struct connectdata *conn, + bool dead_connection) +{ + struct FILEPROTO *file = conn->data->req.protop; + (void)dead_connection; /* not used */ + + if(file) { + Curl_safefree(file->freepath); + file->path = NULL; + if(file->fd != -1) + close(file->fd); + file->fd = -1; + } + + return CURLE_OK; +} + +#ifdef DOS_FILESYSTEM +#define DIRSEP '\\' +#else +#define DIRSEP '/' +#endif + +static CURLcode file_upload(struct connectdata *conn) +{ + struct FILEPROTO *file = conn->data->req.protop; + const char *dir = strchr(file->path, DIRSEP); + int fd; + int mode; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + char *buf = data->state.buffer; + curl_off_t bytecount = 0; + struct_stat file_stat; + const char *buf2; + + /* + * Since FILE: doesn't do the full init, we need to provide some extra + * assignments here. + */ + conn->data->req.upload_fromhere = buf; + + if(!dir) + return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ + + if(!dir[1]) + return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ + +#ifdef O_BINARY +#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY +#else +#define MODE_DEFAULT O_WRONLY|O_CREAT +#endif + + if(data->state.resume_from) + mode = MODE_DEFAULT|O_APPEND; + else + mode = MODE_DEFAULT|O_TRUNC; + + fd = open(file->path, mode, conn->data->set.new_file_perms); + if(fd < 0) { + failf(data, "Can't open %s for writing", file->path); + return CURLE_WRITE_ERROR; + } + + if(-1 != data->state.infilesize) + /* known size of data to "upload" */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* treat the negative resume offset value as the case of "-" */ + if(data->state.resume_from < 0) { + if(fstat(fd, &file_stat)) { + close(fd); + failf(data, "Can't get the size of %s", file->path); + return CURLE_WRITE_ERROR; + } + data->state.resume_from = (curl_off_t)file_stat.st_size; + } + + while(!result) { + size_t nread; + size_t nwrite; + size_t readcount; + result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount); + if(result) + break; + + if(!readcount) + break; + + nread = readcount; + + /*skip bytes before resume point*/ + if(data->state.resume_from) { + if((curl_off_t)nread <= data->state.resume_from) { + data->state.resume_from -= nread; + nread = 0; + buf2 = buf; + } + else { + buf2 = buf + data->state.resume_from; + nread -= (size_t)data->state.resume_from; + data->state.resume_from = 0; + } + } + else + buf2 = buf; + + /* write the data to the target */ + nwrite = write(fd, buf2, nread); + if(nwrite != nread) { + result = CURLE_SEND_ERROR; + break; + } + + bytecount += nread; + + Curl_pgrsSetUploadCounter(data, bytecount); + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, Curl_now()); + } + if(!result && Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + close(fd); + + return result; +} + +/* + * file_do() is the protocol-specific function for the do-phase, separated + * from the connect-phase above. Other protocols merely setup the transfer in + * the do-phase, to have it done in the main transfer loop but since some + * platforms we support don't allow select()ing etc on file handles (as + * opposed to sockets) we instead perform the whole do-operation in this + * function. + */ +static CURLcode file_do(struct connectdata *conn, bool *done) +{ + /* This implementation ignores the host name in conformance with + RFC 1738. Only local files (reachable via the standard file system) + are supported. This means that files on remotely mounted directories + (via NFS, Samba, NT sharing) can be accessed through a file:// URL + */ + CURLcode result = CURLE_OK; + struct_stat statbuf; /* struct_stat instead of struct stat just to allow the + Windows version to have a different struct without + having to redefine the simple word 'stat' */ + curl_off_t expected_size = 0; + bool size_known; + bool fstated = FALSE; + struct Curl_easy *data = conn->data; + char *buf = data->state.buffer; + curl_off_t bytecount = 0; + int fd; + struct FILEPROTO *file; + + *done = TRUE; /* unconditionally */ + + Curl_pgrsStartNow(data); + + if(data->set.upload) + return file_upload(conn); + + file = conn->data->req.protop; + + /* get the fd from the connection phase */ + fd = file->fd; + + /* VMS: This only works reliable for STREAMLF files */ + if(-1 != fstat(fd, &statbuf)) { + /* we could stat it, then read out the size */ + expected_size = statbuf.st_size; + /* and store the modification time */ + data->info.filetime = statbuf.st_mtime; + fstated = TRUE; + } + + if(fstated && !data->state.range && data->set.timecondition) { + if(!Curl_meets_timecondition(data, data->info.filetime)) { + *done = TRUE; + return CURLE_OK; + } + } + + if(fstated) { + time_t filetime; + struct tm buffer; + const struct tm *tm = &buffer; + char header[80]; + msnprintf(header, sizeof(header), + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", + expected_size); + result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0); + if(result) + return result; + + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + (char *)"Accept-ranges: bytes\r\n", 0); + if(result) + return result; + + filetime = (time_t)statbuf.st_mtime; + result = Curl_gmtime(filetime, &buffer); + if(result) + return result; + + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + msnprintf(header, sizeof(header), + "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + data->set.opt_no_body ? "": "\r\n"); + result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0); + if(result) + return result; + /* set the file size to make it available post transfer */ + Curl_pgrsSetDownloadSize(data, expected_size); + if(data->set.opt_no_body) + return result; + } + + /* Check whether file range has been specified */ + result = Curl_range(conn); + if(result) + return result; + + /* Adjust the start offset in case we want to get the N last bytes + * of the stream if the filesize could be determined */ + if(data->state.resume_from < 0) { + if(!fstated) { + failf(data, "Can't get the size of file."); + return CURLE_READ_ERROR; + } + data->state.resume_from += (curl_off_t)statbuf.st_size; + } + + if(data->state.resume_from <= expected_size) + expected_size -= data->state.resume_from; + else { + failf(data, "failed to resume file:// transfer"); + return CURLE_BAD_DOWNLOAD_RESUME; + } + + /* A high water mark has been specified so we obey... */ + if(data->req.maxdownload > 0) + expected_size = data->req.maxdownload; + + if(!fstated || (expected_size == 0)) + size_known = FALSE; + else + size_known = TRUE; + + /* The following is a shortcut implementation of file reading + this is both more efficient than the former call to download() and + it avoids problems with select() and recv() on file descriptors + in Winsock */ + if(fstated) + Curl_pgrsSetDownloadSize(data, expected_size); + + if(data->state.resume_from) { + if(data->state.resume_from != + lseek(fd, data->state.resume_from, SEEK_SET)) + return CURLE_BAD_DOWNLOAD_RESUME; + } + + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + + while(!result) { + ssize_t nread; + /* Don't fill a whole buffer if we want less than all data */ + size_t bytestoread; + + if(size_known) { + bytestoread = (expected_size < data->set.buffer_size) ? + curlx_sotouz(expected_size) : (size_t)data->set.buffer_size; + } + else + bytestoread = data->set.buffer_size-1; + + nread = read(fd, buf, bytestoread); + + if(nread > 0) + buf[nread] = 0; + + if(nread <= 0 || (size_known && (expected_size == 0))) + break; + + bytecount += nread; + if(size_known) + expected_size -= nread; + + result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); + if(result) + return result; + + Curl_pgrsSetDownloadCounter(data, bytecount); + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, Curl_now()); + } + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + return result; +} + +#endif diff --git a/libcurl/lib/file.h b/libcurl/lib/file.h new file mode 100644 index 0000000..20828ad --- /dev/null +++ b/libcurl/lib/file.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_FILE_H +#define HEADER_CURL_FILE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/**************************************************************************** + * FILE unique setup + ***************************************************************************/ +struct FILEPROTO { + char *path; /* the path we operate on */ + char *freepath; /* pointer to the allocated block we must free, this might + differ from the 'path' pointer */ + int fd; /* open file descriptor to read from! */ +}; + +#ifndef CURL_DISABLE_FILE +extern const struct Curl_handler Curl_handler_file; +#endif + +#endif /* HEADER_CURL_FILE_H */ diff --git a/libcurl/lib/fileinfo.c b/libcurl/lib/fileinfo.c new file mode 100644 index 0000000..2630c9e --- /dev/null +++ b/libcurl/lib/fileinfo.c @@ -0,0 +1,44 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#ifndef CURL_DISABLE_FTP +#include "strdup.h" +#include "fileinfo.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +struct fileinfo *Curl_fileinfo_alloc(void) +{ + return calloc(1, sizeof(struct fileinfo)); +} + +void Curl_fileinfo_cleanup(struct fileinfo *finfo) +{ + if(!finfo) + return; + + Curl_safefree(finfo->info.b_data); + free(finfo); +} +#endif diff --git a/libcurl/lib/fileinfo.h b/libcurl/lib/fileinfo.h new file mode 100644 index 0000000..f4d8f3b --- /dev/null +++ b/libcurl/lib/fileinfo.h @@ -0,0 +1,36 @@ +#ifndef HEADER_CURL_FILEINFO_H +#define HEADER_CURL_FILEINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include "llist.h" + +struct fileinfo { + struct curl_fileinfo info; + struct curl_llist_element list; +}; + +struct fileinfo *Curl_fileinfo_alloc(void); +void Curl_fileinfo_cleanup(struct fileinfo *finfo); + +#endif /* HEADER_CURL_FILEINFO_H */ diff --git a/libcurl/lib/firefox-db2pem.sh b/libcurl/lib/firefox-db2pem.sh new file mode 100644 index 0000000..4548932 --- /dev/null +++ b/libcurl/lib/firefox-db2pem.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# *************************************************************************** +# * _ _ ____ _ +# * Project ___| | | | _ \| | +# * / __| | | | |_) | | +# * | (__| |_| | _ <| |___ +# * \___|\___/|_| \_\_____| +# * +# * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. +# * +# * This software is licensed as described in the file COPYING, which +# * you should have received as part of this distribution. The terms +# * are also available at https://curl.haxx.se/docs/copyright.html. +# * +# * You may opt to use, copy, modify, merge, publish, distribute and/or sell +# * copies of the Software, and permit persons to whom the Software is +# * furnished to do so, under the terms of the COPYING file. +# * +# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# * KIND, either express or implied. +# * +# *************************************************************************** +# This shell script creates a fresh ca-bundle.crt file for use with libcurl. +# It extracts all ca certs it finds in the local Firefox database and converts +# them all into PEM format. +# +db=`ls -1d $HOME/.mozilla/firefox/*default*` +out=$1 + +if test -z "$out"; then + out="ca-bundle.crt" # use a sensible default +fi + +currentdate=`date` + +cat >$out <> $out diff --git a/libcurl/lib/formdata.c b/libcurl/lib/formdata.c new file mode 100644 index 0000000..429d479 --- /dev/null +++ b/libcurl/lib/formdata.c @@ -0,0 +1,950 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "formdata.h" +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME) + +#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) +#include +#endif + +#include "urldata.h" /* for struct Curl_easy */ +#include "mime.h" +#include "non-ascii.h" +#include "vtls/vtls.h" +#include "strcase.h" +#include "sendf.h" +#include "strdup.h" +#include "rand.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + + +#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME +#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME +#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS +#define HTTPPOST_READFILE CURL_HTTPPOST_READFILE +#define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER +#define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK +#define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER + +/*************************************************************************** + * + * AddHttpPost() + * + * Adds a HttpPost structure to the list, if parent_post is given becomes + * a subpost of parent_post instead of a direct list element. + * + * Returns newly allocated HttpPost on success and NULL if malloc failed. + * + ***************************************************************************/ +static struct curl_httppost * +AddHttpPost(char *name, size_t namelength, + char *value, curl_off_t contentslength, + char *buffer, size_t bufferlength, + char *contenttype, + long flags, + struct curl_slist *contentHeader, + char *showfilename, char *userp, + struct curl_httppost *parent_post, + struct curl_httppost **httppost, + struct curl_httppost **last_post) +{ + struct curl_httppost *post; + post = calloc(1, sizeof(struct curl_httppost)); + if(post) { + post->name = name; + post->namelength = (long)(name?(namelength?namelength:strlen(name)):0); + post->contents = value; + post->contentlen = contentslength; + post->buffer = buffer; + post->bufferlength = (long)bufferlength; + post->contenttype = contenttype; + post->contentheader = contentHeader; + post->showfilename = showfilename; + post->userp = userp; + post->flags = flags | CURL_HTTPPOST_LARGE; + } + else + return NULL; + + if(parent_post) { + /* now, point our 'more' to the original 'more' */ + post->more = parent_post->more; + + /* then move the original 'more' to point to ourselves */ + parent_post->more = post; + } + else { + /* make the previous point to this */ + if(*last_post) + (*last_post)->next = post; + else + (*httppost) = post; + + (*last_post) = post; + } + return post; +} + +/*************************************************************************** + * + * AddFormInfo() + * + * Adds a FormInfo structure to the list presented by parent_form_info. + * + * Returns newly allocated FormInfo on success and NULL if malloc failed/ + * parent_form_info is NULL. + * + ***************************************************************************/ +static FormInfo * AddFormInfo(char *value, + char *contenttype, + FormInfo *parent_form_info) +{ + FormInfo *form_info; + form_info = calloc(1, sizeof(struct FormInfo)); + if(form_info) { + if(value) + form_info->value = value; + if(contenttype) + form_info->contenttype = contenttype; + form_info->flags = HTTPPOST_FILENAME; + } + else + return NULL; + + if(parent_form_info) { + /* now, point our 'more' to the original 'more' */ + form_info->more = parent_form_info->more; + + /* then move the original 'more' to point to ourselves */ + parent_form_info->more = form_info; + } + + return form_info; +} + +/*************************************************************************** + * + * FormAdd() + * + * Stores a formpost parameter and builds the appropriate linked list. + * + * Has two principal functionalities: using files and byte arrays as + * post parts. Byte arrays are either copied or just the pointer is stored + * (as the user requests) while for files only the filename and not the + * content is stored. + * + * While you may have only one byte array for each name, multiple filenames + * are allowed (and because of this feature CURLFORM_END is needed after + * using CURLFORM_FILE). + * + * Examples: + * + * Simple name/value pair with copied contents: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_COPYCONTENTS, "value", CURLFORM_END); + * + * name/value pair where only the content pointer is remembered: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END); + * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used) + * + * storing a filename (CONTENTTYPE is optional!): + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text", + * CURLFORM_END); + * + * storing multiple filenames: + * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", + * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ + +static +CURLFORMcode FormAdd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + va_list params) +{ + FormInfo *first_form, *current_form, *form = NULL; + CURLFORMcode return_value = CURL_FORMADD_OK; + const char *prevtype = NULL; + struct curl_httppost *post = NULL; + CURLformoption option; + struct curl_forms *forms = NULL; + char *array_value = NULL; /* value read from an array */ + + /* This is a state variable, that if TRUE means that we're parsing an + array that we got passed to us. If FALSE we're parsing the input + va_list arguments. */ + bool array_state = FALSE; + + /* + * We need to allocate the first struct to fill in. + */ + first_form = calloc(1, sizeof(struct FormInfo)); + if(!first_form) + return CURL_FORMADD_MEMORY; + + current_form = first_form; + + /* + * Loop through all the options set. Break if we have an error to report. + */ + while(return_value == CURL_FORMADD_OK) { + + /* first see if we have more parts of the array param */ + if(array_state && forms) { + /* get the upcoming option from the given array */ + option = forms->option; + array_value = (char *)forms->value; + + forms++; /* advance this to next entry */ + if(CURLFORM_END == option) { + /* end of array state */ + array_state = FALSE; + continue; + } + } + else { + /* This is not array-state, get next option */ + option = va_arg(params, CURLformoption); + if(CURLFORM_END == option) + break; + } + + switch(option) { + case CURLFORM_ARRAY: + if(array_state) + /* we don't support an array from within an array */ + return_value = CURL_FORMADD_ILLEGAL_ARRAY; + else { + forms = va_arg(params, struct curl_forms *); + if(forms) + array_state = TRUE; + else + return_value = CURL_FORMADD_NULL; + } + break; + + /* + * Set the Name property. + */ + case CURLFORM_PTRNAME: +#ifdef CURL_DOES_CONVERSIONS + /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy + * the data in all cases so that we'll have safe memory for the eventual + * conversion. + */ +#else + current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ +#endif + /* FALLTHROUGH */ + case CURLFORM_COPYNAME: + if(current_form->name) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *name = array_state? + array_value:va_arg(params, char *); + if(name) + current_form->name = name; /* store for the moment */ + else + return_value = CURL_FORMADD_NULL; + } + break; + case CURLFORM_NAMELENGTH: + if(current_form->namelength) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->namelength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + /* + * Set the contents property. + */ + case CURLFORM_PTRCONTENTS: + current_form->flags |= HTTPPOST_PTRCONTENTS; + /* FALLTHROUGH */ + case CURLFORM_COPYCONTENTS: + if(current_form->value) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *value = + array_state?array_value:va_arg(params, char *); + if(value) + current_form->value = value; /* store for the moment */ + else + return_value = CURL_FORMADD_NULL; + } + break; + case CURLFORM_CONTENTSLENGTH: + current_form->contentslength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + case CURLFORM_CONTENTLEN: + current_form->flags |= CURL_HTTPPOST_LARGE; + current_form->contentslength = + array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t); + break; + + /* Get contents from a given file name */ + case CURLFORM_FILECONTENT: + if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE)) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + const char *filename = array_state? + array_value:va_arg(params, char *); + if(filename) { + current_form->value = strdup(filename); + if(!current_form->value) + return_value = CURL_FORMADD_MEMORY; + else { + current_form->flags |= HTTPPOST_READFILE; + current_form->value_alloc = TRUE; + } + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + /* We upload a file */ + case CURLFORM_FILE: + { + const char *filename = array_state?array_value: + va_arg(params, char *); + + if(current_form->value) { + if(current_form->flags & HTTPPOST_FILENAME) { + if(filename) { + char *fname = strdup(filename); + if(!fname) + return_value = CURL_FORMADD_MEMORY; + else { + form = AddFormInfo(fname, NULL, current_form); + if(!form) { + free(fname); + return_value = CURL_FORMADD_MEMORY; + } + else { + form->value_alloc = TRUE; + current_form = form; + form = NULL; + } + } + } + else + return_value = CURL_FORMADD_NULL; + } + else + return_value = CURL_FORMADD_OPTION_TWICE; + } + else { + if(filename) { + current_form->value = strdup(filename); + if(!current_form->value) + return_value = CURL_FORMADD_MEMORY; + else { + current_form->flags |= HTTPPOST_FILENAME; + current_form->value_alloc = TRUE; + } + } + else + return_value = CURL_FORMADD_NULL; + } + break; + } + + case CURLFORM_BUFFERPTR: + current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER; + if(current_form->buffer) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *buffer = + array_state?array_value:va_arg(params, char *); + if(buffer) { + current_form->buffer = buffer; /* store for the moment */ + current_form->value = buffer; /* make it non-NULL to be accepted + as fine */ + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + case CURLFORM_BUFFERLENGTH: + if(current_form->bufferlength) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->bufferlength = + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + case CURLFORM_STREAM: + current_form->flags |= HTTPPOST_CALLBACK; + if(current_form->userp) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *userp = + array_state?array_value:va_arg(params, char *); + if(userp) { + current_form->userp = userp; + current_form->value = userp; /* this isn't strictly true but we + derive a value from this later on + and we need this non-NULL to be + accepted as a fine form part */ + } + else + return_value = CURL_FORMADD_NULL; + } + break; + + case CURLFORM_CONTENTTYPE: + { + const char *contenttype = + array_state?array_value:va_arg(params, char *); + if(current_form->contenttype) { + if(current_form->flags & HTTPPOST_FILENAME) { + if(contenttype) { + char *type = strdup(contenttype); + if(!type) + return_value = CURL_FORMADD_MEMORY; + else { + form = AddFormInfo(NULL, type, current_form); + if(!form) { + free(type); + return_value = CURL_FORMADD_MEMORY; + } + else { + form->contenttype_alloc = TRUE; + current_form = form; + form = NULL; + } + } + } + else + return_value = CURL_FORMADD_NULL; + } + else + return_value = CURL_FORMADD_OPTION_TWICE; + } + else { + if(contenttype) { + current_form->contenttype = strdup(contenttype); + if(!current_form->contenttype) + return_value = CURL_FORMADD_MEMORY; + else + current_form->contenttype_alloc = TRUE; + } + else + return_value = CURL_FORMADD_NULL; + } + break; + } + case CURLFORM_CONTENTHEADER: + { + /* this "cast increases required alignment of target type" but + we consider it OK anyway */ + struct curl_slist *list = array_state? + (struct curl_slist *)(void *)array_value: + va_arg(params, struct curl_slist *); + + if(current_form->contentheader) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->contentheader = list; + + break; + } + case CURLFORM_FILENAME: + case CURLFORM_BUFFER: + { + const char *filename = array_state?array_value: + va_arg(params, char *); + if(current_form->showfilename) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + current_form->showfilename = strdup(filename); + if(!current_form->showfilename) + return_value = CURL_FORMADD_MEMORY; + else + current_form->showfilename_alloc = TRUE; + } + break; + } + default: + return_value = CURL_FORMADD_UNKNOWN_OPTION; + break; + } + } + + if(CURL_FORMADD_OK != return_value) { + /* On error, free allocated fields for all nodes of the FormInfo linked + list without deallocating nodes. List nodes are deallocated later on */ + FormInfo *ptr; + for(ptr = first_form; ptr != NULL; ptr = ptr->more) { + if(ptr->name_alloc) { + Curl_safefree(ptr->name); + ptr->name_alloc = FALSE; + } + if(ptr->value_alloc) { + Curl_safefree(ptr->value); + ptr->value_alloc = FALSE; + } + if(ptr->contenttype_alloc) { + Curl_safefree(ptr->contenttype); + ptr->contenttype_alloc = FALSE; + } + if(ptr->showfilename_alloc) { + Curl_safefree(ptr->showfilename); + ptr->showfilename_alloc = FALSE; + } + } + } + + if(CURL_FORMADD_OK == return_value) { + /* go through the list, check for completeness and if everything is + * alright add the HttpPost item otherwise set return_value accordingly */ + + post = NULL; + for(form = first_form; + form != NULL; + form = form->more) { + if(((!form->name || !form->value) && !post) || + ( (form->contentslength) && + (form->flags & HTTPPOST_FILENAME) ) || + ( (form->flags & HTTPPOST_FILENAME) && + (form->flags & HTTPPOST_PTRCONTENTS) ) || + + ( (!form->buffer) && + (form->flags & HTTPPOST_BUFFER) && + (form->flags & HTTPPOST_PTRBUFFER) ) || + + ( (form->flags & HTTPPOST_READFILE) && + (form->flags & HTTPPOST_PTRCONTENTS) ) + ) { + return_value = CURL_FORMADD_INCOMPLETE; + break; + } + if(((form->flags & HTTPPOST_FILENAME) || + (form->flags & HTTPPOST_BUFFER)) && + !form->contenttype) { + char *f = (form->flags & HTTPPOST_BUFFER)? + form->showfilename : form->value; + char const *type; + type = Curl_mime_contenttype(f); + if(!type) + type = prevtype; + if(!type) + type = FILE_CONTENTTYPE_DEFAULT; + + /* our contenttype is missing */ + form->contenttype = strdup(type); + if(!form->contenttype) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->contenttype_alloc = TRUE; + } + if(form->name && form->namelength) { + /* Name should not contain nul bytes. */ + size_t i; + for(i = 0; i < form->namelength; i++) + if(!form->name[i]) { + return_value = CURL_FORMADD_NULL; + break; + } + if(return_value != CURL_FORMADD_OK) + break; + } + if(!(form->flags & HTTPPOST_PTRNAME) && + (form == first_form) ) { + /* Note that there's small risk that form->name is NULL here if the + app passed in a bad combo, so we better check for that first. */ + if(form->name) { + /* copy name (without strdup; possibly not nul-terminated) */ + form->name = Curl_memdup(form->name, form->namelength? + form->namelength: + strlen(form->name) + 1); + } + if(!form->name) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->name_alloc = TRUE; + } + if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | + HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | + HTTPPOST_CALLBACK)) && form->value) { + /* copy value (without strdup; possibly contains null characters) */ + size_t clen = (size_t) form->contentslength; + if(!clen) + clen = strlen(form->value) + 1; + + form->value = Curl_memdup(form->value, clen); + + if(!form->value) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->value_alloc = TRUE; + } + post = AddHttpPost(form->name, form->namelength, + form->value, form->contentslength, + form->buffer, form->bufferlength, + form->contenttype, form->flags, + form->contentheader, form->showfilename, + form->userp, + post, httppost, + last_post); + + if(!post) { + return_value = CURL_FORMADD_MEMORY; + break; + } + + if(form->contenttype) + prevtype = form->contenttype; + } + if(CURL_FORMADD_OK != return_value) { + /* On error, free allocated fields for nodes of the FormInfo linked + list which are not already owned by the httppost linked list + without deallocating nodes. List nodes are deallocated later on */ + FormInfo *ptr; + for(ptr = form; ptr != NULL; ptr = ptr->more) { + if(ptr->name_alloc) { + Curl_safefree(ptr->name); + ptr->name_alloc = FALSE; + } + if(ptr->value_alloc) { + Curl_safefree(ptr->value); + ptr->value_alloc = FALSE; + } + if(ptr->contenttype_alloc) { + Curl_safefree(ptr->contenttype); + ptr->contenttype_alloc = FALSE; + } + if(ptr->showfilename_alloc) { + Curl_safefree(ptr->showfilename); + ptr->showfilename_alloc = FALSE; + } + } + } + } + + /* Always deallocate FormInfo linked list nodes without touching node + fields given that these have either been deallocated or are owned + now by the httppost linked list */ + while(first_form) { + FormInfo *ptr = first_form->more; + free(first_form); + first_form = ptr; + } + + return return_value; +} + +/* + * curl_formadd() is a public API to add a section to the multipart formpost. + * + * @unittest: 1308 + */ + +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...) +{ + va_list arg; + CURLFORMcode result; + va_start(arg, last_post); + result = FormAdd(httppost, last_post, arg); + va_end(arg); + return result; +} + +/* + * curl_formget() + * Serialize a curl_httppost struct. + * Returns 0 on success. + * + * @unittest: 1308 + */ +int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append) +{ + CURLcode result; + curl_mimepart toppart; + + Curl_mime_initpart(&toppart, NULL); /* default form is empty */ + result = Curl_getformdata(NULL, &toppart, form, NULL); + if(!result) + result = Curl_mime_prepare_headers(&toppart, "multipart/form-data", + NULL, MIMESTRATEGY_FORM); + + while(!result) { + char buffer[8192]; + size_t nread = Curl_mime_read(buffer, 1, sizeof(buffer), &toppart); + + if(!nread) + break; + + switch(nread) { + default: + if(append(arg, buffer, nread) != nread) + result = CURLE_READ_ERROR; + break; + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + break; + } + } + + Curl_mime_cleanpart(&toppart); + return (int) result; +} + +/* + * curl_formfree() is an external function to free up a whole form post + * chain + */ +void curl_formfree(struct curl_httppost *form) +{ + struct curl_httppost *next; + + if(!form) + /* no form to free, just get out of this */ + return; + + do { + next = form->next; /* the following form line */ + + /* recurse to sub-contents */ + curl_formfree(form->more); + + if(!(form->flags & HTTPPOST_PTRNAME)) + free(form->name); /* free the name */ + if(!(form->flags & + (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) + ) + free(form->contents); /* free the contents */ + free(form->contenttype); /* free the content type */ + free(form->showfilename); /* free the faked file name */ + free(form); /* free the struct */ + form = next; + } while(form); /* continue */ +} + + +/* Set mime part name, taking care of non nul-terminated name string. */ +static CURLcode setname(curl_mimepart *part, const char *name, size_t len) +{ + char *zname; + CURLcode res; + + if(!name || !len) + return curl_mime_name(part, name); + zname = malloc(len + 1); + if(!zname) + return CURLE_OUT_OF_MEMORY; + memcpy(zname, name, len); + zname[len] = '\0'; + res = curl_mime_name(part, zname); + free(zname); + return res; +} + +/* + * Curl_getformdata() converts a linked list of "meta data" into a mime + * structure. The input list is in 'post', while the output is stored in + * mime part at '*finalform'. + * + * This function will not do a failf() for the potential memory failures but + * should for all other errors it spots. Just note that this function MAY get + * a NULL pointer in the 'data' argument. + */ + +CURLcode Curl_getformdata(struct Curl_easy *data, + curl_mimepart *finalform, + struct curl_httppost *post, + curl_read_callback fread_func) +{ + CURLcode result = CURLE_OK; + curl_mime *form = NULL; + curl_mimepart *part; + struct curl_httppost *file; + + Curl_mime_cleanpart(finalform); /* default form is empty */ + + if(!post) + return result; /* no input => no output! */ + + form = curl_mime_init(data); + if(!form) + result = CURLE_OUT_OF_MEMORY; + + if(!result) + result = curl_mime_subparts(finalform, form); + + /* Process each top part. */ + for(; !result && post; post = post->next) { + /* If we have more than a file here, create a mime subpart and fill it. */ + curl_mime *multipart = form; + if(post->more) { + part = curl_mime_addpart(form); + if(!part) + result = CURLE_OUT_OF_MEMORY; + if(!result) + result = setname(part, post->name, post->namelength); + if(!result) { + multipart = curl_mime_init(data); + if(!multipart) + result = CURLE_OUT_OF_MEMORY; + } + if(!result) + result = curl_mime_subparts(part, multipart); + } + + /* Generate all the part contents. */ + for(file = post; !result && file; file = file->more) { + /* Create the part. */ + part = curl_mime_addpart(multipart); + if(!part) + result = CURLE_OUT_OF_MEMORY; + + /* Set the headers. */ + if(!result) + result = curl_mime_headers(part, file->contentheader, 0); + + /* Set the content type. */ + if(!result && file->contenttype) + result = curl_mime_type(part, file->contenttype); + + /* Set field name. */ + if(!result && !post->more) + result = setname(part, post->name, post->namelength); + + /* Process contents. */ + if(!result) { + curl_off_t clen = post->contentslength; + + if(post->flags & CURL_HTTPPOST_LARGE) + clen = post->contentlen; + if(!clen) + clen = -1; + + if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) { + if(!strcmp(file->contents, "-")) { + /* There are a few cases where the code below won't work; in + particular, freopen(stdin) by the caller is not guaranteed + to result as expected. This feature has been kept for backward + compatibility: use of "-" pseudo file name should be avoided. */ + result = curl_mime_data_cb(part, (curl_off_t) -1, + (curl_read_callback) fread, + CURLX_FUNCTION_CAST(curl_seek_callback, + fseek), + NULL, (void *) stdin); + } + else + result = curl_mime_filedata(part, file->contents); + if(!result && (post->flags & HTTPPOST_READFILE)) + result = curl_mime_filename(part, NULL); + } + else if(post->flags & HTTPPOST_BUFFER) + result = curl_mime_data(part, post->buffer, + post->bufferlength? post->bufferlength: -1); + else if(post->flags & HTTPPOST_CALLBACK) + /* the contents should be read with the callback and the size is set + with the contentslength */ + result = curl_mime_data_cb(part, clen, + fread_func, NULL, NULL, post->userp); + else { + result = curl_mime_data(part, post->contents, (ssize_t) clen); +#ifdef CURL_DOES_CONVERSIONS + /* Convert textual contents now. */ + if(!result && data && part->datasize) + result = Curl_convert_to_network(data, part->data, part->datasize); +#endif + } + } + + /* Set fake file name. */ + if(!result && post->showfilename) + if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER | + HTTPPOST_CALLBACK))) + result = curl_mime_filename(part, post->showfilename); + } + } + + if(result) + Curl_mime_cleanpart(finalform); + + return result; +} + +#else +/* if disabled */ +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...) +{ + (void)httppost; + (void)last_post; + return CURL_FORMADD_DISABLED; +} + +int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append) +{ + (void) form; + (void) arg; + (void) append; + return CURL_FORMADD_DISABLED; +} + +void curl_formfree(struct curl_httppost *form) +{ + (void)form; + /* does nothing HTTP is disabled */ +} + +#endif /* if disabled */ diff --git a/libcurl/lib/formdata.h b/libcurl/lib/formdata.h new file mode 100644 index 0000000..cb20805 --- /dev/null +++ b/libcurl/lib/formdata.h @@ -0,0 +1,60 @@ +#ifndef HEADER_CURL_FORMDATA_H +#define HEADER_CURL_FORMDATA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_MIME + +/* used by FormAdd for temporary storage */ +typedef struct FormInfo { + char *name; + bool name_alloc; + size_t namelength; + char *value; + bool value_alloc; + curl_off_t contentslength; + char *contenttype; + bool contenttype_alloc; + long flags; + char *buffer; /* pointer to existing buffer used for file upload */ + size_t bufferlength; + char *showfilename; /* The file name to show. If not set, the actual + file name will be used */ + bool showfilename_alloc; + char *userp; /* pointer for the read callback */ + struct curl_slist *contentheader; + struct FormInfo *more; +} FormInfo; + +CURLcode Curl_getformdata(struct Curl_easy *data, + curl_mimepart *, + struct curl_httppost *post, + curl_read_callback fread_func); +#else +/* disabled */ +#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN +#endif + + +#endif /* HEADER_CURL_FORMDATA_H */ diff --git a/libcurl/lib/ftp.c b/libcurl/lib/ftp.c new file mode 100644 index 0000000..76ebbc4 --- /dev/null +++ b/libcurl/lib/ftp.c @@ -0,0 +1,4430 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "if2ip.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "ftp.h" +#include "fileinfo.h" +#include "ftplistparser.h" +#include "curl_range.h" +#include "curl_sec.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "inet_pton.h" +#include "select.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "multiif.h" +#include "url.h" +#include "strcase.h" +#include "speedcheck.h" +#include "warnless.h" +#include "http_proxy.h" +#include "non-ascii.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt +#endif + +/* Local API functions */ +#ifndef DEBUGBUILD +static void _state(struct connectdata *conn, + ftpstate newstate); +#define state(x,y) _state(x,y) +#else +static void _state(struct connectdata *conn, + ftpstate newstate, + int lineno); +#define state(x,y) _state(x,y,__LINE__) +#endif + +static CURLcode ftp_sendquote(struct connectdata *conn, + struct curl_slist *quote); +static CURLcode ftp_quit(struct connectdata *conn); +static CURLcode ftp_parse_url_path(struct connectdata *conn); +static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done); +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void ftp_pasv_verbose(struct connectdata *conn, + Curl_addrinfo *ai, + char *newhost, /* ascii version */ + int port); +#endif +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn); +static CURLcode ftp_state_mdtm(struct connectdata *conn); +static CURLcode ftp_state_quote(struct connectdata *conn, + bool init, ftpstate instate); +static CURLcode ftp_nb_type(struct connectdata *conn, + bool ascii, ftpstate newstate); +static int ftp_need_type(struct connectdata *conn, + bool ascii); +static CURLcode ftp_do(struct connectdata *conn, bool *done); +static CURLcode ftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode ftp_connect(struct connectdata *conn, bool *done); +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection); +static CURLcode ftp_do_more(struct connectdata *conn, int *completed); +static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); +static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode ftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode ftp_setup_connection(struct connectdata * conn); + +static CURLcode init_wc_data(struct connectdata *conn); +static CURLcode wc_statemach(struct connectdata *conn); + +static void wc_data_dtor(void *ptr); + +static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize); + +static CURLcode ftp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *ftpcode, + size_t *size); +static CURLcode ftp_dophase_done(struct connectdata *conn, + bool connected); + +/* easy-to-use macro: */ +#define PPSENDF(x,y,z) result = Curl_pp_sendf(x,y,z); \ + if(result) \ + return result + + +/* + * FTP protocol handler. + */ + +const struct Curl_handler Curl_handler_ftp = { + "FTP", /* scheme */ + ftp_setup_connection, /* setup_connection */ + ftp_do, /* do_it */ + ftp_done, /* done */ + ftp_do_more, /* do_more */ + ftp_connect, /* connect_it */ + ftp_multi_statemach, /* connecting */ + ftp_doing, /* doing */ + ftp_getsock, /* proto_getsock */ + ftp_getsock, /* doing_getsock */ + ftp_domore_getsock, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_FTP, /* defport */ + CURLPROTO_FTP, /* protocol */ + PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD | + PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP | + PROTOPT_WILDCARD /* flags */ +}; + + +#ifdef USE_SSL +/* + * FTPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ftps = { + "FTPS", /* scheme */ + ftp_setup_connection, /* setup_connection */ + ftp_do, /* do_it */ + ftp_done, /* done */ + ftp_do_more, /* do_more */ + ftp_connect, /* connect_it */ + ftp_multi_statemach, /* connecting */ + ftp_doing, /* doing */ + ftp_getsock, /* proto_getsock */ + ftp_getsock, /* doing_getsock */ + ftp_domore_getsock, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_FTPS, /* defport */ + CURLPROTO_FTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | + PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */ +}; +#endif + +static void close_secondarysocket(struct connectdata *conn) +{ + if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; + } + conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; +} + +/* + * NOTE: back in the old days, we added code in the FTP code that made NOBODY + * requests on files respond with headers passed to the client/stdout that + * looked like HTTP ones. + * + * This approach is not very elegant, it causes confusion and is error-prone. + * It is subject for removal at the next (or at least a future) soname bump. + * Until then you can test the effects of the removal by undefining the + * following define named CURL_FTP_HTTPSTYLE_HEAD. + */ +#define CURL_FTP_HTTPSTYLE_HEAD 1 + +static void freedirs(struct ftp_conn *ftpc) +{ + if(ftpc->dirs) { + int i; + for(i = 0; i < ftpc->dirdepth; i++) { + free(ftpc->dirs[i]); + ftpc->dirs[i] = NULL; + } + free(ftpc->dirs); + ftpc->dirs = NULL; + ftpc->dirdepth = 0; + } + Curl_safefree(ftpc->file); + + /* no longer of any use */ + Curl_safefree(ftpc->newhost); +} + +/* Returns non-zero if the given string contains CR (\r) or LF (\n), + which are not allowed within RFC 959 . + Note: The input string is in the client's encoding which might + not be ASCII, so escape sequences \r & \n must be used instead + of hex values 0x0d & 0x0a. +*/ +static bool isBadFtpString(const char *string) +{ + return ((NULL != strchr(string, '\r')) || + (NULL != strchr(string, '\n'))) ? TRUE : FALSE; +} + +/*********************************************************************** + * + * AcceptServerConnect() + * + * After connection request is received from the server this function is + * called to accept the connection and close the listening socket + * + */ +static CURLcode AcceptServerConnect(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sock = conn->sock[SECONDARYSOCKET]; + curl_socket_t s = CURL_SOCKET_BAD; +#ifdef ENABLE_IPV6 + struct Curl_sockaddr_storage add; +#else + struct sockaddr_in add; +#endif + curl_socklen_t size = (curl_socklen_t) sizeof(add); + + if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) { + size = sizeof(add); + + s = accept(sock, (struct sockaddr *) &add, &size); + } + Curl_closesocket(conn, sock); /* close the first socket */ + + if(CURL_SOCKET_BAD == s) { + failf(data, "Error accept()ing server connect"); + return CURLE_FTP_PORT_FAILED; + } + infof(data, "Connection accepted from server\n"); + /* when this happens within the DO state it is important that we mark us as + not needing DO_MORE anymore */ + conn->bits.do_more = FALSE; + + conn->sock[SECONDARYSOCKET] = s; + (void)curlx_nonblock(s, TRUE); /* enable non-blocking */ + conn->sock_accepted[SECONDARYSOCKET] = TRUE; + + if(data->set.fsockopt) { + int error = 0; + + /* activate callback for setting socket options */ + Curl_set_in_callback(data, true); + error = data->set.fsockopt(data->set.sockopt_client, + s, + CURLSOCKTYPE_ACCEPT); + Curl_set_in_callback(data, false); + + if(error) { + close_secondarysocket(conn); + return CURLE_ABORTED_BY_CALLBACK; + } + } + + return CURLE_OK; + +} + +/* + * ftp_timeleft_accept() returns the amount of milliseconds left allowed for + * waiting server to connect. If the value is negative, the timeout time has + * already elapsed. + * + * The start time is stored in progress.t_acceptdata - as set with + * Curl_pgrsTime(..., TIMER_STARTACCEPT); + * + */ +static timediff_t ftp_timeleft_accept(struct Curl_easy *data) +{ + timediff_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT; + timediff_t other; + struct curltime now; + + if(data->set.accepttimeout > 0) + timeout_ms = data->set.accepttimeout; + + now = Curl_now(); + + /* check if the generic timeout possibly is set shorter */ + other = Curl_timeleft(data, &now, FALSE); + if(other && (other < timeout_ms)) + /* note that this also works fine for when other happens to be negative + due to it already having elapsed */ + timeout_ms = other; + else { + /* subtract elapsed time */ + timeout_ms -= Curl_timediff(now, data->progress.t_acceptdata); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; + } + + return timeout_ms; +} + + +/*********************************************************************** + * + * ReceivedServerConnect() + * + * After allowing server to connect to us from data port, this function + * checks both data connection for connection establishment and ctrl + * connection for a negative response regarding a failure in connecting + * + */ +static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) +{ + struct Curl_easy *data = conn->data; + curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET]; + curl_socket_t data_sock = conn->sock[SECONDARYSOCKET]; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + int result; + time_t timeout_ms; + ssize_t nread; + int ftpcode; + + *received = FALSE; + + timeout_ms = ftp_timeleft_accept(data); + infof(data, "Checking for server connect\n"); + if(timeout_ms < 0) { + /* if a timeout was already reached, bail out */ + failf(data, "Accept timeout occurred while waiting server connect"); + return CURLE_FTP_ACCEPT_TIMEOUT; + } + + /* First check whether there is a cached response from server */ + if(pp->cache_size && pp->cache && pp->cache[0] > '3') { + /* Data connection could not be established, let's return */ + infof(data, "There is negative response in cache while serv connect\n"); + Curl_GetFTPResponse(&nread, conn, &ftpcode); + return CURLE_FTP_ACCEPT_FAILED; + } + + result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0); + + /* see if the connection request is already here */ + switch(result) { + case -1: /* error */ + /* let's die here */ + failf(data, "Error while waiting for server connect"); + return CURLE_FTP_ACCEPT_FAILED; + case 0: /* Server connect is not received yet */ + break; /* loop */ + default: + + if(result & CURL_CSELECT_IN2) { + infof(data, "Ready to accept data connection from server\n"); + *received = TRUE; + } + else if(result & CURL_CSELECT_IN) { + infof(data, "Ctrl conn has data while waiting for data conn\n"); + Curl_GetFTPResponse(&nread, conn, &ftpcode); + + if(ftpcode/100 > 3) + return CURLE_FTP_ACCEPT_FAILED; + + return CURLE_WEIRD_SERVER_REPLY; + } + + break; + } /* switch() */ + + return CURLE_OK; +} + + +/*********************************************************************** + * + * InitiateTransfer() + * + * After connection from server is accepted this function is called to + * setup transfer parameters and initiate the data transfer. + * + */ +static CURLcode InitiateTransfer(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + + if(conn->bits.ftp_use_data_ssl) { + /* since we only have a plaintext TCP connection here, we must now + * do the TLS stuff */ + infof(data, "Doing the SSL/TLS handshake on the data stream\n"); + result = Curl_ssl_connect(conn, SECONDARYSOCKET); + if(result) + return result; + } + + if(conn->proto.ftpc.state_saved == FTP_STOR) { + /* When we know we're uploading a specified file, we can get the file + size prior to the actual upload. */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* set the SO_SNDBUF for the secondary socket for those who need it */ + Curl_sndbufset(conn->sock[SECONDARYSOCKET]); + + Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET); + } + else { + /* FTP download: */ + Curl_setup_transfer(data, SECONDARYSOCKET, + conn->proto.ftpc.retr_size_saved, FALSE, -1); + } + + conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ + state(conn, FTP_STOP); + + return CURLE_OK; +} + +/*********************************************************************** + * + * AllowServerConnect() + * + * When we've issue the PORT command, we have told the server to connect to + * us. This function checks whether data connection is established if so it is + * accepted. + * + */ +static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) +{ + struct Curl_easy *data = conn->data; + time_t timeout_ms; + CURLcode result = CURLE_OK; + + *connected = FALSE; + infof(data, "Preparing for accepting server on data port\n"); + + /* Save the time we start accepting server connect */ + Curl_pgrsTime(data, TIMER_STARTACCEPT); + + timeout_ms = ftp_timeleft_accept(data); + if(timeout_ms < 0) { + /* if a timeout was already reached, bail out */ + failf(data, "Accept timeout occurred while waiting server connect"); + return CURLE_FTP_ACCEPT_TIMEOUT; + } + + /* see if the connection request is already here */ + result = ReceivedServerConnect(conn, connected); + if(result) + return result; + + if(*connected) { + result = AcceptServerConnect(conn); + if(result) + return result; + + result = InitiateTransfer(conn); + if(result) + return result; + } + else { + /* Add timeout to multi handle and break out of the loop */ + if(!result && *connected == FALSE) { + Curl_expire(data, data->set.accepttimeout > 0 ? + data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0); + } + } + + return result; +} + +/* macro to check for a three-digit ftp status code at the start of the + given string */ +#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \ + ISDIGIT(line[2])) + +/* macro to check for the last line in an FTP server response */ +#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3])) + +static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len, + int *code) +{ + (void)conn; + + if((len > 3) && LASTLINE(line)) { + *code = curlx_sltosi(strtol(line, NULL, 10)); + return TRUE; + } + + return FALSE; +} + +static CURLcode ftp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *ftpcode, /* return the ftp-code if done */ + size_t *size) /* size of the response */ +{ + struct connectdata *conn = pp->conn; + struct Curl_easy *data = conn->data; +#ifdef HAVE_GSSAPI + char * const buf = data->state.buffer; +#endif + int code; + CURLcode result = Curl_pp_readresp(sockfd, pp, &code, size); + +#if defined(HAVE_GSSAPI) + /* handle the security-oriented responses 6xx ***/ + switch(code) { + case 631: + code = Curl_sec_read_msg(conn, buf, PROT_SAFE); + break; + case 632: + code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE); + break; + case 633: + code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL); + break; + default: + /* normal ftp stuff we pass through! */ + break; + } +#endif + + /* store the latest code for later retrieval */ + data->info.httpcode = code; + + if(ftpcode) + *ftpcode = code; + + if(421 == code) { + /* 421 means "Service not available, closing control connection." and FTP + * servers use it to signal that idle session timeout has been exceeded. + * If we ignored the response, it could end up hanging in some cases. + * + * This response code can come at any point so having it treated + * generically is a good idea. + */ + infof(data, "We got a 421 - timeout!\n"); + state(conn, FTP_STOP); + return CURLE_OPERATION_TIMEDOUT; + } + + return result; +} + +/* --- parse FTP server responses --- */ + +/* + * Curl_GetFTPResponse() is a BLOCKING function to read the full response + * from a server after a command. + * + */ + +CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ + struct connectdata *conn, + int *ftpcode) /* return the ftp-code */ +{ + /* + * We cannot read just one byte per read() and then go back to select() as + * the OpenSSL read() doesn't grok that properly. + * + * Alas, read as much as possible, split up into lines, use the ending + * line in a response or continue reading. */ + + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + size_t nread; + int cache_skip = 0; + int value_to_be_ignored = 0; + + if(ftpcode) + *ftpcode = 0; /* 0 for errors */ + else + /* make the pointer point to something for the rest of this function */ + ftpcode = &value_to_be_ignored; + + *nreadp = 0; + + while(!*ftpcode && !result) { + /* check and reset timeout value every lap */ + time_t timeout = Curl_pp_state_timeout(pp, FALSE); + time_t interval_ms; + + if(timeout <= 0) { + failf(data, "FTP response timeout"); + return CURLE_OPERATION_TIMEDOUT; /* already too little time */ + } + + interval_ms = 1000; /* use 1 second timeout intervals */ + if(timeout < interval_ms) + interval_ms = timeout; + + /* + * Since this function is blocking, we need to wait here for input on the + * connection and only then we call the response reading function. We do + * timeout at least every second to make the timeout check run. + * + * A caution here is that the ftp_readresp() function has a cache that may + * contain pieces of a response from the previous invoke and we need to + * make sure we don't just wait for input while there is unhandled data in + * that cache. But also, if the cache is there, we call ftp_readresp() and + * the cache wasn't good enough to continue we must not just busy-loop + * around this function. + * + */ + + if(pp->cache && (cache_skip < 2)) { + /* + * There's a cache left since before. We then skipping the wait for + * socket action, unless this is the same cache like the previous round + * as then the cache was deemed not enough to act on and we then need to + * wait for more data anyway. + */ + } + else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) { + switch(SOCKET_READABLE(sockfd, interval_ms)) { + case -1: /* select() error, stop reading */ + failf(data, "FTP response aborted due to select/poll error: %d", + SOCKERRNO); + return CURLE_RECV_ERROR; + + case 0: /* timeout */ + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + continue; /* just continue in our loop for the timeout duration */ + + default: /* for clarity */ + break; + } + } + result = ftp_readresp(sockfd, pp, ftpcode, &nread); + if(result) + break; + + if(!nread && pp->cache) + /* bump cache skip counter as on repeated skips we must wait for more + data */ + cache_skip++; + else + /* when we got data or there is no cache left, we reset the cache skip + counter */ + cache_skip = 0; + + *nreadp += nread; + + } /* while there's buffer left and loop is requested */ + + pp->pending_resp = FALSE; + + return result; +} + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ +static const char * const ftp_state_names[]={ + "STOP", + "WAIT220", + "AUTH", + "USER", + "PASS", + "ACCT", + "PBSZ", + "PROT", + "CCC", + "PWD", + "SYST", + "NAMEFMT", + "QUOTE", + "RETR_PREQUOTE", + "STOR_PREQUOTE", + "POSTQUOTE", + "CWD", + "MKD", + "MDTM", + "TYPE", + "LIST_TYPE", + "RETR_TYPE", + "STOR_TYPE", + "SIZE", + "RETR_SIZE", + "STOR_SIZE", + "REST", + "RETR_REST", + "PORT", + "PRET", + "PASV", + "LIST", + "RETR", + "STOR", + "QUIT" +}; +#endif + +/* This is the ONLY way to change FTP state! */ +static void _state(struct connectdata *conn, + ftpstate newstate +#ifdef DEBUGBUILD + , int lineno +#endif + ) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + +#if defined(DEBUGBUILD) + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) lineno; +#else + if(ftpc->state != newstate) + infof(conn->data, "FTP %p (line %d) state change from %s to %s\n", + (void *)ftpc, lineno, ftp_state_names[ftpc->state], + ftp_state_names[newstate]); +#endif +#endif + + ftpc->state = newstate; +} + +static CURLcode ftp_state_user(struct connectdata *conn) +{ + CURLcode result; + struct FTP *ftp = conn->data->req.protop; + /* send USER */ + PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:""); + + state(conn, FTP_USER); + conn->data->state.ftp_trying_alternative = FALSE; + + return CURLE_OK; +} + +static CURLcode ftp_state_pwd(struct connectdata *conn) +{ + CURLcode result; + + /* send PWD to discover our entry point */ + PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD"); + state(conn, FTP_PWD); + + return CURLE_OK; +} + +/* For the FTP "protocol connect" and "doing" phases only */ +static int ftp_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); +} + +/* For the FTP "DO_MORE" phase only */ +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(!numsocks) + return GETSOCK_BLANK; + + /* When in DO_MORE state, we could be either waiting for us to connect to a + * remote site, or we could wait for that site to connect to us. Or just + * handle ordinary commands. + */ + + if(FTP_STOP == ftpc->state) { + int bits = GETSOCK_READSOCK(0); + + /* if stopped and still in this state, then we're also waiting for a + connect on the secondary connection */ + socks[0] = conn->sock[FIRSTSOCKET]; + + if(!conn->data->set.ftp_use_port) { + int s; + int i; + /* PORT is used to tell the server to connect to us, and during that we + don't do happy eyeballs, but we do if we connect to the server */ + for(s = 1, i = 0; i<2; i++) { + if(conn->tempsock[i] != CURL_SOCKET_BAD) { + socks[s] = conn->tempsock[i]; + bits |= GETSOCK_WRITESOCK(s++); + } + } + } + else { + socks[1] = conn->sock[SECONDARYSOCKET]; + bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1); + } + + return bits; + } + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); +} + +/* This is called after the FTP_QUOTE state is passed. + + ftp_state_cwd() sends the range of CWD commands to the server to change to + the correct directory. It may also need to send MKD commands to create + missing ones, if that option is enabled. +*/ +static CURLcode ftp_state_cwd(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(ftpc->cwddone) + /* already done and fine */ + result = ftp_state_mdtm(conn); + else { + ftpc->count2 = 0; /* count2 counts failed CWDs */ + + /* count3 is set to allow a MKD to fail once. In the case when first CWD + fails and then MKD fails (due to another session raced it to create the + dir) this then allows for a second try to CWD to it */ + ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0; + + if((conn->data->set.ftp_filemethod == FTPFILE_NOCWD) && !ftpc->cwdcount) + /* No CWD necessary */ + result = ftp_state_mdtm(conn); + else if(conn->bits.reuse && ftpc->entrypath) { + /* This is a re-used connection. Since we change directory to where the + transfer is taking place, we must first get back to the original dir + where we ended up after login: */ + ftpc->cwdcount = 0; /* we count this as the first path, then we add one + for all upcoming ones in the ftp->dirs[] array */ + PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath); + state(conn, FTP_CWD); + } + else { + if(ftpc->dirdepth) { + ftpc->cwdcount = 1; + /* issue the first CWD, the rest is sent when the CWD responses are + received... */ + PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->cwdcount -1]); + state(conn, FTP_CWD); + } + else { + /* No CWD necessary */ + result = ftp_state_mdtm(conn); + } + } + } + return result; +} + +typedef enum { + EPRT, + PORT, + DONE +} ftpport; + +static CURLcode ftp_state_use_port(struct connectdata *conn, + ftpport fcmd) /* start with this */ + +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct Curl_easy *data = conn->data; + curl_socket_t portsock = CURL_SOCKET_BAD; + char myhost[256] = ""; + + struct Curl_sockaddr_storage ss; + Curl_addrinfo *res, *ai; + curl_socklen_t sslen; + char hbuf[NI_MAXHOST]; + struct sockaddr *sa = (struct sockaddr *)&ss; + struct sockaddr_in * const sa4 = (void *)sa; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 * const sa6 = (void *)sa; +#endif + char tmp[1024]; + static const char mode[][5] = { "EPRT", "PORT" }; + int rc; + int error; + char *host = NULL; + char *string_ftpport = data->set.str[STRING_FTPPORT]; + struct Curl_dns_entry *h = NULL; + unsigned short port_min = 0; + unsigned short port_max = 0; + unsigned short port; + bool possibly_non_local = TRUE; + char buffer[STRERROR_LEN]; + char *addr = NULL; + + /* Step 1, figure out what is requested, + * accepted format : + * (ipv4|ipv6|domain|interface)?(:port(-range)?)? + */ + + if(data->set.str[STRING_FTPPORT] && + (strlen(data->set.str[STRING_FTPPORT]) > 1)) { + +#ifdef ENABLE_IPV6 + size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ? + INET6_ADDRSTRLEN : strlen(string_ftpport); +#else + size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ? + INET_ADDRSTRLEN : strlen(string_ftpport); +#endif + char *ip_start = string_ftpport; + char *ip_end = NULL; + char *port_start = NULL; + char *port_sep = NULL; + + addr = calloc(addrlen + 1, 1); + if(!addr) + return CURLE_OUT_OF_MEMORY; + +#ifdef ENABLE_IPV6 + if(*string_ftpport == '[') { + /* [ipv6]:port(-range) */ + ip_start = string_ftpport + 1; + ip_end = strchr(string_ftpport, ']'); + if(ip_end) + strncpy(addr, ip_start, ip_end - ip_start); + } + else +#endif + if(*string_ftpport == ':') { + /* :port */ + ip_end = string_ftpport; + } + else { + ip_end = strchr(string_ftpport, ':'); + if(ip_end) { + /* either ipv6 or (ipv4|domain|interface):port(-range) */ +#ifdef ENABLE_IPV6 + if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { + /* ipv6 */ + port_min = port_max = 0; + strcpy(addr, string_ftpport); + ip_end = NULL; /* this got no port ! */ + } + else +#endif + /* (ipv4|domain|interface):port(-range) */ + strncpy(addr, string_ftpport, ip_end - ip_start); + } + else + /* ipv4|interface */ + strcpy(addr, string_ftpport); + } + + /* parse the port */ + if(ip_end != NULL) { + port_start = strchr(ip_end, ':'); + if(port_start) { + port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10)); + port_sep = strchr(port_start, '-'); + if(port_sep) { + port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); + } + else + port_max = port_min; + } + } + + /* correct errors like: + * :1234-1230 + * :-4711, in this case port_min is (unsigned)-1, + * therefore port_min > port_max for all cases + * but port_max = (unsigned)-1 + */ + if(port_min > port_max) + port_min = port_max = 0; + + + if(*addr != '\0') { + /* attempt to get the address of the given interface name */ + switch(Curl_if2ip(conn->ip_addr->ai_family, + Curl_ipv6_scope(conn->ip_addr->ai_addr), + conn->scope_id, addr, hbuf, sizeof(hbuf))) { + case IF2IP_NOT_FOUND: + /* not an interface, use the given string as host name instead */ + host = addr; + break; + case IF2IP_AF_NOT_SUPPORTED: + return CURLE_FTP_PORT_FAILED; + case IF2IP_FOUND: + host = hbuf; /* use the hbuf for host name */ + } + } + else + /* there was only a port(-range) given, default the host */ + host = NULL; + } /* data->set.ftpport */ + + if(!host) { + /* not an interface and not a host name, get default by extracting + the IP from the control connection */ + sslen = sizeof(ss); + if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + free(addr); + return CURLE_FTP_PORT_FAILED; + } + switch(sa->sa_family) { +#ifdef ENABLE_IPV6 + case AF_INET6: + Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf)); + break; +#endif + default: + Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf)); + break; + } + host = hbuf; /* use this host name */ + possibly_non_local = FALSE; /* we know it is local now */ + } + + /* resolv ip/host to ip */ + rc = Curl_resolv(conn, host, 0, FALSE, &h); + if(rc == CURLRESOLV_PENDING) + (void)Curl_resolver_wait_resolv(conn, &h); + if(h) { + res = h->addr; + /* when we return from this function, we can forget about this entry + to we can unlock it now already */ + Curl_resolv_unlock(data, h); + } /* (h) */ + else + res = NULL; /* failure! */ + + if(res == NULL) { + failf(data, "failed to resolve the address provided to PORT: %s", host); + free(addr); + return CURLE_FTP_PORT_FAILED; + } + + free(addr); + host = NULL; + + /* step 2, create a socket for the requested address */ + + portsock = CURL_SOCKET_BAD; + error = 0; + for(ai = res; ai; ai = ai->ai_next) { + result = Curl_socket(conn, ai, NULL, &portsock); + if(result) { + error = SOCKERRNO; + continue; + } + break; + } + if(!ai) { + failf(data, "socket failure: %s", + Curl_strerror(error, buffer, sizeof(buffer))); + return CURLE_FTP_PORT_FAILED; + } + + /* step 3, bind to a suitable local address */ + + memcpy(sa, ai->ai_addr, ai->ai_addrlen); + sslen = ai->ai_addrlen; + + for(port = port_min; port <= port_max;) { + if(sa->sa_family == AF_INET) + sa4->sin_port = htons(port); +#ifdef ENABLE_IPV6 + else + sa6->sin6_port = htons(port); +#endif + /* Try binding the given address. */ + if(bind(portsock, sa, sslen) ) { + /* It failed. */ + error = SOCKERRNO; + if(possibly_non_local && (error == EADDRNOTAVAIL)) { + /* The requested bind address is not local. Use the address used for + * the control connection instead and restart the port loop + */ + infof(data, "bind(port=%hu) on non-local address failed: %s\n", port, + Curl_strerror(error, buffer, sizeof(buffer))); + + sslen = sizeof(ss); + if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + port = port_min; + possibly_non_local = FALSE; /* don't try this again */ + continue; + } + if(error != EADDRINUSE && error != EACCES) { + failf(data, "bind(port=%hu) failed: %s", port, + Curl_strerror(error, buffer, sizeof(buffer))); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + } + else + break; + + port++; + } + + /* maybe all ports were in use already*/ + if(port > port_max) { + failf(data, "bind() failed, we ran out of ports!"); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* get the name again after the bind() so that we can extract the + port number it uses now */ + sslen = sizeof(ss); + if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* step 4, listen on the socket */ + + if(listen(portsock, 1)) { + failf(data, "socket failure: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* step 5, send the proper FTP command */ + + /* get a plain printable version of the numerical address to work with + below */ + Curl_printable_address(ai, myhost, sizeof(myhost)); + +#ifdef ENABLE_IPV6 + if(!conn->bits.ftp_use_eprt && conn->bits.ipv6) + /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the + request and enable EPRT again! */ + conn->bits.ftp_use_eprt = TRUE; +#endif + + for(; fcmd != DONE; fcmd++) { + + if(!conn->bits.ftp_use_eprt && (EPRT == fcmd)) + /* if disabled, goto next */ + continue; + + if((PORT == fcmd) && sa->sa_family != AF_INET) + /* PORT is IPv4 only */ + continue; + + switch(sa->sa_family) { + case AF_INET: + port = ntohs(sa4->sin_port); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + port = ntohs(sa6->sin6_port); + break; +#endif + default: + continue; /* might as well skip this */ + } + + if(EPRT == fcmd) { + /* + * Two fine examples from RFC2428; + * + * EPRT |1|132.235.1.2|6275| + * + * EPRT |2|1080::8:800:200C:417A|5282| + */ + + result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd], + sa->sa_family == AF_INET?1:2, + myhost, port); + if(result) { + failf(data, "Failure sending EPRT command: %s", + curl_easy_strerror(result)); + Curl_closesocket(conn, portsock); + /* don't retry using PORT */ + ftpc->count1 = PORT; + /* bail out */ + state(conn, FTP_STOP); + return result; + } + break; + } + if(PORT == fcmd) { + char *source = myhost; + char *dest = tmp; + + /* translate x.x.x.x to x,x,x,x */ + while(source && *source) { + if(*source == '.') + *dest = ','; + else + *dest = *source; + dest++; + source++; + } + *dest = 0; + msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff)); + + result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp); + if(result) { + failf(data, "Failure sending PORT command: %s", + curl_easy_strerror(result)); + Curl_closesocket(conn, portsock); + /* bail out */ + state(conn, FTP_STOP); + return result; + } + break; + } + } + + /* store which command was sent */ + ftpc->count1 = fcmd; + + close_secondarysocket(conn); + + /* we set the secondary socket variable to this for now, it is only so that + the cleanup function will close it in case we fail before the true + secondary stuff is made */ + conn->sock[SECONDARYSOCKET] = portsock; + + /* this tcpconnect assignment below is a hackish work-around to make the + multi interface with active FTP work - as it will not wait for a + (passive) connect in Curl_is_connected(). + + The *proper* fix is to make sure that the active connection from the + server is done in a non-blocking way. Currently, it is still BLOCKING. + */ + conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE; + + state(conn, FTP_PORT); + return result; +} + +static CURLcode ftp_state_use_pasv(struct connectdata *conn) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + /* + Here's the excecutive summary on what to do: + + PASV is RFC959, expect: + 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) + + LPSV is RFC1639, expect: + 228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2) + + EPSV is RFC2428, expect: + 229 Entering Extended Passive Mode (|||port|) + + */ + + static const char mode[][5] = { "EPSV", "PASV" }; + int modeoff; + +#ifdef PF_INET6 + if(!conn->bits.ftp_use_epsv && conn->bits.ipv6) + /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the + request and enable EPSV again! */ + conn->bits.ftp_use_epsv = TRUE; +#endif + + modeoff = conn->bits.ftp_use_epsv?0:1; + + PPSENDF(&ftpc->pp, "%s", mode[modeoff]); + + ftpc->count1 = modeoff; + state(conn, FTP_PASV); + infof(conn->data, "Connect data stream passively\n"); + + return result; +} + +/* + * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc. + * + * REST is the last command in the chain of commands when a "head"-like + * request is made. Thus, if an actual transfer is to be made this is where we + * take off for real. + */ +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + + if(ftp->transfer != FTPTRANSFER_BODY) { + /* doesn't transfer any data */ + + /* still possibly do PRE QUOTE jobs */ + state(conn, FTP_RETR_PREQUOTE); + result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + } + else if(data->set.ftp_use_port) { + /* We have chosen to use the PORT (or similar) command */ + result = ftp_state_use_port(conn, EPRT); + } + else { + /* We have chosen (this is default) to use the PASV (or similar) command */ + if(data->set.ftp_use_pret) { + /* The user has requested that we send a PRET command + to prepare the server for the upcoming PASV */ + if(!conn->proto.ftpc.file) { + PPSENDF(&conn->proto.ftpc.pp, "PRET %s", + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->set.ftp_list_only?"NLST":"LIST")); + } + else if(data->set.upload) { + PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file); + } + else { + PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file); + } + state(conn, FTP_PRET); + } + else { + result = ftp_state_use_pasv(conn); + } + } + return result; +} + +static CURLcode ftp_state_rest(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { + /* if a "head"-like request is being made (on a file) */ + + /* Determine if server can respond to REST command and therefore + whether it supports range */ + PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0); + + state(conn, FTP_REST); + } + else + result = ftp_state_prepare_transfer(conn); + + return result; +} + +static CURLcode ftp_state_size(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { + /* if a "head"-like request is being made (on a file) */ + + /* we know ftpc->file is a valid pointer to a file name */ + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + + state(conn, FTP_SIZE); + } + else + result = ftp_state_rest(conn); + + return result; +} + +static CURLcode ftp_state_list(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + + /* If this output is to be machine-parsed, the NLST command might be better + to use, since the LIST command output is not specified or standard in any + way. It has turned out that the NLST list output is not the same on all + servers either... */ + + /* + if FTPFILE_NOCWD was specified, we are currently in + the user's home directory, so we should add the path + as argument for the LIST / NLST / or custom command. + Whether the server will support this, is uncertain. + + The other ftp_filemethods will CWD into dir/dir/ first and + then just do LIST (in that case: nothing to do here) + */ + char *cmd, *lstArg, *slashPos; + const char *inpath = ftp->path; + + lstArg = NULL; + if((data->set.ftp_filemethod == FTPFILE_NOCWD) && + inpath && inpath[0] && strchr(inpath, '/')) { + size_t n = strlen(inpath); + + /* Check if path does not end with /, as then we cut off the file part */ + if(inpath[n - 1] != '/') { + /* chop off the file part if format is dir/dir/file */ + slashPos = strrchr(inpath, '/'); + n = slashPos - inpath; + } + result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE); + if(result) + return result; + } + + cmd = aprintf("%s%s%s", + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->set.ftp_list_only?"NLST":"LIST"), + lstArg? " ": "", + lstArg? lstArg: ""); + + if(!cmd) { + free(lstArg); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd); + + free(lstArg); + free(cmd); + + if(result) + return result; + + state(conn, FTP_LIST); + + return result; +} + +static CURLcode ftp_state_retr_prequote(struct connectdata *conn) +{ + /* We've sent the TYPE, now we must send the list of prequote strings */ + return ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); +} + +static CURLcode ftp_state_stor_prequote(struct connectdata *conn) +{ + /* We've sent the TYPE, now we must send the list of prequote strings */ + return ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE); +} + +static CURLcode ftp_state_type(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + /* If we have selected NOBODY and HEADER, it means that we only want file + information. Which in FTP can't be much more than the file size and + date. */ + if(data->set.opt_no_body && ftpc->file && + ftp_need_type(conn, data->set.prefer_ascii)) { + /* The SIZE command is _not_ RFC 959 specified, and therefore many servers + may not support it! It is however the only way we have to get a file's + size! */ + + ftp->transfer = FTPTRANSFER_INFO; + /* this means no actual transfer will be made */ + + /* Some servers return different sizes for different modes, and thus we + must set the proper type before we check the size */ + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE); + if(result) + return result; + } + else + result = ftp_state_size(conn); + + return result; +} + +/* This is called after the CWD commands have been done in the beginning of + the DO phase */ +static CURLcode ftp_state_mdtm(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + /* Requested time of file or time-depended transfer? */ + if((data->set.get_filetime || data->set.timecondition) && ftpc->file) { + + /* we have requested to get the modified-time of the file, this is a white + spot as the MDTM is not mentioned in RFC959 */ + PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file); + + state(conn, FTP_MDTM); + } + else + result = ftp_state_type(conn); + + return result; +} + + +/* This is called after the TYPE and possible quote commands have been sent */ +static CURLcode ftp_state_ul_setup(struct connectdata *conn, + bool sizechecked) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((data->state.resume_from && !sizechecked) || + ((data->state.resume_from > 0) && sizechecked)) { + /* we're about to continue the uploading of a file */ + /* 1. get already existing file's size. We use the SIZE command for this + which may not exist in the server! The SIZE command is not in + RFC959. */ + + /* 2. This used to set REST. But since we can do append, we + don't another ftp command. We just skip the source file + offset and then we APPEND the rest on the file instead */ + + /* 3. pass file-size number of bytes in the source file */ + /* 4. lower the infilesize counter */ + /* => transfer as usual */ + int seekerr = CURL_SEEKFUNC_OK; + + if(data->state.resume_from < 0) { + /* Got no given size to start from, figure it out */ + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + state(conn, FTP_STOR_SIZE); + return result; + } + + /* enable append */ + data->set.ftp_append = TRUE; + + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + data->state.fread_func(data->state.buffer, 1, readthisamountnow, + data->state.in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); + } + /* now, decrease the size of the read */ + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; + + if(data->state.infilesize <= 0) { + infof(data, "File already completely uploaded\n"); + + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + + /* Set ->transfer so that we won't get any error in + * ftp_done() because we didn't transfer anything! */ + ftp->transfer = FTPTRANSFER_NONE; + + state(conn, FTP_STOP); + return CURLE_OK; + } + } + /* we've passed, proceed as normal */ + } /* resume_from */ + + PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s", + ftpc->file); + + state(conn, FTP_STOR); + + return result; +} + +static CURLcode ftp_state_quote(struct connectdata *conn, + bool init, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + bool quote = FALSE; + struct curl_slist *item; + + switch(instate) { + case FTP_QUOTE: + default: + item = data->set.quote; + break; + case FTP_RETR_PREQUOTE: + case FTP_STOR_PREQUOTE: + item = data->set.prequote; + break; + case FTP_POSTQUOTE: + item = data->set.postquote; + break; + } + + /* + * This state uses: + * 'count1' to iterate over the commands to send + * 'count2' to store whether to allow commands to fail + */ + + if(init) + ftpc->count1 = 0; + else + ftpc->count1++; + + if(item) { + int i = 0; + + /* Skip count1 items in the linked list */ + while((i< ftpc->count1) && item) { + item = item->next; + i++; + } + if(item) { + char *cmd = item->data; + if(cmd[0] == '*') { + cmd++; + ftpc->count2 = 1; /* the sent command is allowed to fail */ + } + else + ftpc->count2 = 0; /* failure means cancel operation */ + + PPSENDF(&ftpc->pp, "%s", cmd); + state(conn, instate); + quote = TRUE; + } + } + + if(!quote) { + /* No more quote to send, continue to ... */ + switch(instate) { + case FTP_QUOTE: + default: + result = ftp_state_cwd(conn); + break; + case FTP_RETR_PREQUOTE: + if(ftp->transfer != FTPTRANSFER_BODY) + state(conn, FTP_STOP); + else { + if(ftpc->known_filesize != -1) { + Curl_pgrsSetDownloadSize(data, ftpc->known_filesize); + result = ftp_state_retr(conn, ftpc->known_filesize); + } + else { + if(data->set.ignorecl) { + /* This code is to support download of growing files. It prevents + the state machine from requesting the file size from the + server. With an unknown file size the download continues until + the server terminates it, otherwise the client stops if the + received byte count exceeds the reported file size. Set option + CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/ + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + else { + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + state(conn, FTP_RETR_SIZE); + } + } + } + break; + case FTP_STOR_PREQUOTE: + result = ftp_state_ul_setup(conn, FALSE); + break; + case FTP_POSTQUOTE: + break; + } + } + + return result; +} + +/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV + problems */ +static CURLcode ftp_epsv_disable(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) { + /* We can't disable EPSV when doing IPv6, so this is instead a fail */ + failf(conn->data, "Failed EPSV attempt, exiting\n"); + return CURLE_WEIRD_SERVER_REPLY; + } + + infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n"); + /* disable it for next transfer */ + conn->bits.ftp_use_epsv = FALSE; + conn->data->state.errorbuf = FALSE; /* allow error message to get + rewritten */ + PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV"); + conn->proto.ftpc.count1++; + /* remain in/go to the FTP_PASV state */ + state(conn, FTP_PASV); + return result; +} + + +static char *control_address(struct connectdata *conn) +{ + /* Returns the control connection IP address. + If a proxy tunnel is used, returns the original host name instead, because + the effective control connection address is the proxy address, + not the ftp host. */ + if(conn->bits.tunnel_proxy || conn->bits.socksproxy) + return conn->host.name; + + return conn->ip_addr_str; +} + +static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + int ftpcode) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result; + struct Curl_easy *data = conn->data; + struct Curl_dns_entry *addr = NULL; + int rc; + unsigned short connectport; /* the local port connect() should use! */ + char *str = &data->state.buffer[4]; /* start on the first letter */ + + /* if we come here again, make sure the former name is cleared */ + Curl_safefree(ftpc->newhost); + + if((ftpc->count1 == 0) && + (ftpcode == 229)) { + /* positive EPSV response */ + char *ptr = strchr(str, '('); + if(ptr) { + unsigned int num; + char separator[4]; + ptr++; + if(5 == sscanf(ptr, "%c%c%c%u%c", + &separator[0], + &separator[1], + &separator[2], + &num, + &separator[3])) { + const char sep1 = separator[0]; + int i; + + /* The four separators should be identical, or else this is an oddly + formatted reply and we bail out immediately. */ + for(i = 1; i<4; i++) { + if(separator[i] != sep1) { + ptr = NULL; /* set to NULL to signal error */ + break; + } + } + if(num > 0xffff) { + failf(data, "Illegal port number in EPSV reply"); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + if(ptr) { + ftpc->newport = (unsigned short)(num & 0xffff); + ftpc->newhost = strdup(control_address(conn)); + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + } + } + else + ptr = NULL; + } + if(!ptr) { + failf(data, "Weirdly formatted EPSV reply"); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + } + else if((ftpc->count1 == 1) && + (ftpcode == 227)) { + /* positive PASV response */ + unsigned int ip[4]; + unsigned int port[2]; + + /* + * Scan for a sequence of six comma-separated numbers and use them as + * IP+port indicators. + * + * Found reply-strings include: + * "227 Entering Passive Mode (127,0,0,1,4,51)" + * "227 Data transfer will passively listen to 127,0,0,1,4,51" + * "227 Entering passive mode. 127,0,0,1,4,51" + */ + while(*str) { + if(6 == sscanf(str, "%u,%u,%u,%u,%u,%u", + &ip[0], &ip[1], &ip[2], &ip[3], + &port[0], &port[1])) + break; + str++; + } + + if(!*str || (ip[0] > 255) || (ip[1] > 255) || (ip[2] > 255) || + (ip[3] > 255) || (port[0] > 255) || (port[1] > 255) ) { + failf(data, "Couldn't interpret the 227-response"); + return CURLE_FTP_WEIRD_227_FORMAT; + } + + /* we got OK from server */ + if(data->set.ftp_skip_ip) { + /* told to ignore the remotely given IP but instead use the host we used + for the control connection */ + infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead\n", + ip[0], ip[1], ip[2], ip[3], + conn->host.name); + ftpc->newhost = strdup(control_address(conn)); + } + else + ftpc->newhost = aprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); + + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + + ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); + } + else if(ftpc->count1 == 0) { + /* EPSV failed, move on to PASV */ + return ftp_epsv_disable(conn); + } + else { + failf(data, "Bad PASV/EPSV response: %03d", ftpcode); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + + if(conn->bits.proxy) { + /* + * This connection uses a proxy and we need to connect to the proxy again + * here. We don't want to rely on a former host lookup that might've + * expired now, instead we remake the lookup here and now! + */ + const char * const host_name = conn->bits.socksproxy ? + conn->socks_proxy.host.name : conn->http_proxy.host.name; + rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING, ignores the return code but 'addr' will be NULL in + case of failure */ + (void)Curl_resolver_wait_resolv(conn, &addr); + + connectport = + (unsigned short)conn->port; /* we connect to the proxy's port */ + + if(!addr) { + failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport); + return CURLE_COULDNT_RESOLVE_PROXY; + } + } + else { + /* normal, direct, ftp connection */ + rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING */ + (void)Curl_resolver_wait_resolv(conn, &addr); + + connectport = ftpc->newport; /* we connect to the remote port */ + + if(!addr) { + failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport); + return CURLE_FTP_CANT_GET_HOST; + } + } + + conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; + result = Curl_connecthost(conn, addr); + + if(result) { + Curl_resolv_unlock(data, addr); /* we're done using this address */ + if(ftpc->count1 == 0 && ftpcode == 229) + return ftp_epsv_disable(conn); + + return result; + } + + + /* + * When this is used from the multi interface, this might've returned with + * the 'connected' set to FALSE and thus we are now awaiting a non-blocking + * connect to connect. + */ + + if(data->set.verbose) + /* this just dumps information about this second connection */ + ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); + + Curl_resolv_unlock(data, addr); /* we're done using this address */ + + Curl_safefree(conn->secondaryhostname); + conn->secondary_port = ftpc->newport; + conn->secondaryhostname = strdup(ftpc->newhost); + if(!conn->secondaryhostname) + return CURLE_OUT_OF_MEMORY; + + conn->bits.do_more = TRUE; + state(conn, FTP_STOP); /* this phase is completed */ + + return result; +} + +static CURLcode ftp_state_port_resp(struct connectdata *conn, + int ftpcode) +{ + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + ftpport fcmd = (ftpport)ftpc->count1; + CURLcode result = CURLE_OK; + + /* The FTP spec tells a positive response should have code 200. + Be more permissive here to tolerate deviant servers. */ + if(ftpcode / 100 != 2) { + /* the command failed */ + + if(EPRT == fcmd) { + infof(data, "disabling EPRT usage\n"); + conn->bits.ftp_use_eprt = FALSE; + } + fcmd++; + + if(fcmd == DONE) { + failf(data, "Failed to do PORT"); + result = CURLE_FTP_PORT_FAILED; + } + else + /* try next */ + result = ftp_state_use_port(conn, fcmd); + } + else { + infof(data, "Connect data stream actively\n"); + state(conn, FTP_STOP); /* end of DO phase */ + result = ftp_dophase_done(conn, FALSE); + } + + return result; +} + +static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, + int ftpcode) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + switch(ftpcode) { + case 213: + { + /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the + last .sss part is optional and means fractions of a second */ + int year, month, day, hour, minute, second; + if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d", + &year, &month, &day, &hour, &minute, &second)) { + /* we have a time, reformat it */ + char timebuf[24]; + time_t secs = time(NULL); + + msnprintf(timebuf, sizeof(timebuf), + "%04d%02d%02d %02d:%02d:%02d GMT", + year, month, day, hour, minute, second); + /* now, convert this into a time() value: */ + data->info.filetime = curl_getdate(timebuf, &secs); + } + +#ifdef CURL_FTP_HTTPSTYLE_HEAD + /* If we asked for a time of the file and we actually got one as well, + we "emulate" a HTTP-style header in our output. */ + + if(data->set.opt_no_body && + ftpc->file && + data->set.get_filetime && + (data->info.filetime >= 0) ) { + char headerbuf[128]; + time_t filetime = data->info.filetime; + struct tm buffer; + const struct tm *tm = &buffer; + + result = Curl_gmtime(filetime, &buffer); + if(result) + return result; + + /* format: "Tue, 15 Nov 1994 12:45:26" */ + msnprintf(headerbuf, sizeof(headerbuf), + "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0); + if(result) + return result; + } /* end of a ridiculous amount of conditionals */ +#endif + } + break; + default: + infof(data, "unsupported MDTM reply format\n"); + break; + case 550: /* "No such file or directory" */ + failf(data, "Given file does not exist"); + result = CURLE_FTP_COULDNT_RETR_FILE; + break; + } + + if(data->set.timecondition) { + if((data->info.filetime > 0) && (data->set.timevalue > 0)) { + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + if(data->info.filetime <= data->set.timevalue) { + infof(data, "The requested document is not new enough\n"); + ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + data->info.timecond = TRUE; + state(conn, FTP_STOP); + return CURLE_OK; + } + break; + case CURL_TIMECOND_IFUNMODSINCE: + if(data->info.filetime > data->set.timevalue) { + infof(data, "The requested document is not old enough\n"); + ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + data->info.timecond = TRUE; + state(conn, FTP_STOP); + return CURLE_OK; + } + break; + } /* switch */ + } + else { + infof(data, "Skipping time comparison\n"); + } + } + + if(!result) + result = ftp_state_type(conn); + + return result; +} + +static CURLcode ftp_state_type_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + if(ftpcode/100 != 2) { + /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a + successful 'TYPE I'. While that is not as RFC959 says, it is still a + positive response code and we allow that. */ + failf(data, "Couldn't set desired mode"); + return CURLE_FTP_COULDNT_SET_TYPE; + } + if(ftpcode != 200) + infof(data, "Got a %03d response code instead of the assumed 200\n", + ftpcode); + + if(instate == FTP_TYPE) + result = ftp_state_size(conn); + else if(instate == FTP_LIST_TYPE) + result = ftp_state_list(conn); + else if(instate == FTP_RETR_TYPE) + result = ftp_state_retr_prequote(conn); + else if(instate == FTP_STOR_TYPE) + result = ftp_state_stor_prequote(conn); + + return result; +} + +static CURLcode ftp_state_retr(struct connectdata *conn, + curl_off_t filesize) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(data->set.max_filesize && (filesize > data->set.max_filesize)) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + ftp->downloadsize = filesize; + + if(data->state.resume_from) { + /* We always (attempt to) get the size of downloads, so it is done before + this even when not doing resumes. */ + if(filesize == -1) { + infof(data, "ftp server doesn't support SIZE\n"); + /* We couldn't get the size and therefore we can't know if there really + is a part of the file left to get, although the server will just + close the connection when we start the connection so it won't cause + us any harm, just not make us exit as nicely. */ + } + else { + /* We got a file size report, so we check that there actually is a + part of the file left to get, or else we go home. */ + if(data->state.resume_from< 0) { + /* We're supposed to download the last abs(from) bytes */ + if(filesize < -data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* convert to size to download */ + ftp->downloadsize = -data->state.resume_from; + /* download from where? */ + data->state.resume_from = filesize - ftp->downloadsize; + } + else { + if(filesize < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* Now store the number of bytes we are expected to download */ + ftp->downloadsize = filesize-data->state.resume_from; + } + } + + if(ftp->downloadsize == 0) { + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + infof(data, "File already completely downloaded\n"); + + /* Set ->transfer so that we won't get any error in ftp_done() + * because we didn't transfer the any file */ + ftp->transfer = FTPTRANSFER_NONE; + state(conn, FTP_STOP); + return CURLE_OK; + } + + /* Set resume file transfer offset */ + infof(data, "Instructs server to resume from offset %" + CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); + + PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T, + data->state.resume_from); + + state(conn, FTP_RETR_REST); + } + else { + /* no resume */ + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + + return result; +} + +static CURLcode ftp_state_size_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + curl_off_t filesize = -1; + char *buf = data->state.buffer; + + /* get the size from the ascii string: */ + if(ftpcode == 213) + /* ignores parsing errors, which will make the size remain unknown */ + (void)curlx_strtoofft(buf + 4, NULL, 0, &filesize); + + if(instate == FTP_SIZE) { +#ifdef CURL_FTP_HTTPSTYLE_HEAD + if(-1 != filesize) { + char clbuf[128]; + msnprintf(clbuf, sizeof(clbuf), + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0); + if(result) + return result; + } +#endif + Curl_pgrsSetDownloadSize(data, filesize); + result = ftp_state_rest(conn); + } + else if(instate == FTP_RETR_SIZE) { + Curl_pgrsSetDownloadSize(data, filesize); + result = ftp_state_retr(conn, filesize); + } + else if(instate == FTP_STOR_SIZE) { + data->state.resume_from = filesize; + result = ftp_state_ul_setup(conn, TRUE); + } + + return result; +} + +static CURLcode ftp_state_rest_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + switch(instate) { + case FTP_REST: + default: +#ifdef CURL_FTP_HTTPSTYLE_HEAD + if(ftpcode == 350) { + char buffer[24]= { "Accept-ranges: bytes\r\n" }; + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0); + if(result) + return result; + } +#endif + result = ftp_state_prepare_transfer(conn); + break; + + case FTP_RETR_REST: + if(ftpcode != 350) { + failf(conn->data, "Couldn't use REST"); + result = CURLE_FTP_COULDNT_USE_REST; + } + else { + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + break; + } + + return result; +} + +static CURLcode ftp_state_stor_resp(struct connectdata *conn, + int ftpcode, ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + if(ftpcode >= 400) { + failf(data, "Failed FTP upload: %0d", ftpcode); + state(conn, FTP_STOP); + /* oops, we never close the sockets! */ + return CURLE_UPLOAD_FAILED; + } + + conn->proto.ftpc.state_saved = instate; + + /* PORT means we are now awaiting the server to connect to us. */ + if(data->set.ftp_use_port) { + bool connected; + + state(conn, FTP_STOP); /* no longer in STOR state */ + + result = AllowServerConnect(conn, &connected); + if(result) + return result; + + if(!connected) { + struct ftp_conn *ftpc = &conn->proto.ftpc; + infof(data, "Data conn was not available immediately\n"); + ftpc->wait_data_conn = TRUE; + } + + return CURLE_OK; + } + return InitiateTransfer(conn); +} + +/* for LIST and RETR responses */ +static CURLcode ftp_state_get_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + + if((ftpcode == 150) || (ftpcode == 125)) { + + /* + A; + 150 Opening BINARY mode data connection for /etc/passwd (2241 + bytes). (ok, the file is being transferred) + + B: + 150 Opening ASCII mode data connection for /bin/ls + + C: + 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes). + + D: + 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes) + + E: + 125 Data connection already open; Transfer starting. */ + + curl_off_t size = -1; /* default unknown size */ + + + /* + * It appears that there are FTP-servers that return size 0 for files when + * SIZE is used on the file while being in BINARY mode. To work around + * that (stupid) behavior, we attempt to parse the RETR response even if + * the SIZE returned size zero. + * + * Debugging help from Salvatore Sorrentino on February 26, 2003. + */ + + if((instate != FTP_LIST) && + !data->set.prefer_ascii && + (ftp->downloadsize < 1)) { + /* + * It seems directory listings either don't show the size or very + * often uses size 0 anyway. ASCII transfers may very well turn out + * that the transferred amount of data is not the same as this line + * tells, why using this number in those cases only confuses us. + * + * Example D above makes this parsing a little tricky */ + char *bytes; + char *buf = data->state.buffer; + bytes = strstr(buf, " bytes"); + if(bytes) { + long in = (long)(--bytes-buf); + /* this is a hint there is size information in there! ;-) */ + while(--in) { + /* scan for the left parenthesis and break there */ + if('(' == *bytes) + break; + /* skip only digits */ + if(!ISDIGIT(*bytes)) { + bytes = NULL; + break; + } + /* one more estep backwards */ + bytes--; + } + /* if we have nothing but digits: */ + if(bytes++) { + /* get the number! */ + (void)curlx_strtoofft(bytes, NULL, 0, &size); + } + } + } + else if(ftp->downloadsize > -1) + size = ftp->downloadsize; + + if(size > data->req.maxdownload && data->req.maxdownload > 0) + size = data->req.size = data->req.maxdownload; + else if((instate != FTP_LIST) && (data->set.prefer_ascii)) + size = -1; /* kludge for servers that understate ASCII mode file size */ + + infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n", + data->req.maxdownload); + + if(instate != FTP_LIST) + infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n", + size); + + /* FTP download: */ + conn->proto.ftpc.state_saved = instate; + conn->proto.ftpc.retr_size_saved = size; + + if(data->set.ftp_use_port) { + bool connected; + + result = AllowServerConnect(conn, &connected); + if(result) + return result; + + if(!connected) { + struct ftp_conn *ftpc = &conn->proto.ftpc; + infof(data, "Data conn was not available immediately\n"); + state(conn, FTP_STOP); + ftpc->wait_data_conn = TRUE; + } + } + else + return InitiateTransfer(conn); + } + else { + if((instate == FTP_LIST) && (ftpcode == 450)) { + /* simply no matching files in the dir listing */ + ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */ + state(conn, FTP_STOP); /* this phase is over */ + } + else { + failf(data, "RETR response: %03d", ftpcode); + return instate == FTP_RETR && ftpcode == 550? + CURLE_REMOTE_FILE_NOT_FOUND: + CURLE_FTP_COULDNT_RETR_FILE; + } + } + + return result; +} + +/* after USER, PASS and ACCT */ +static CURLcode ftp_state_loggedin(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->ssl[FIRSTSOCKET].use) { + /* PBSZ = PROTECTION BUFFER SIZE. + + The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says: + + Specifically, the PROT command MUST be preceded by a PBSZ + command and a PBSZ command MUST be preceded by a successful + security data exchange (the TLS negotiation in this case) + + ... (and on page 8): + + Thus the PBSZ command must still be issued, but must have a + parameter of '0' to indicate that no buffering is taking place + and the data connection should not be encapsulated. + */ + PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0); + state(conn, FTP_PBSZ); + } + else { + result = ftp_state_pwd(conn); + } + return result; +} + +/* for USER and PASS responses */ +static CURLcode ftp_state_user_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + (void)instate; /* no use for this yet */ + + /* some need password anyway, and others just return 2xx ignored */ + if((ftpcode == 331) && (ftpc->state == FTP_USER)) { + /* 331 Password required for ... + (the server requires to send the user's password too) */ + PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:""); + state(conn, FTP_PASS); + } + else if(ftpcode/100 == 2) { + /* 230 User ... logged in. + (the user logged in with or without password) */ + result = ftp_state_loggedin(conn); + } + else if(ftpcode == 332) { + if(data->set.str[STRING_FTP_ACCOUNT]) { + PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]); + state(conn, FTP_ACCT); + } + else { + failf(data, "ACCT requested but none available"); + result = CURLE_LOGIN_DENIED; + } + } + else { + /* All other response codes, like: + + 530 User ... access denied + (the server denies to log the specified user) */ + + if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && + !conn->data->state.ftp_trying_alternative) { + /* Ok, USER failed. Let's try the supplied command. */ + PPSENDF(&conn->proto.ftpc.pp, "%s", + conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); + conn->data->state.ftp_trying_alternative = TRUE; + state(conn, FTP_USER); + result = CURLE_OK; + } + else { + failf(data, "Access denied: %03d", ftpcode); + result = CURLE_LOGIN_DENIED; + } + } + return result; +} + +/* for ACCT response */ +static CURLcode ftp_state_acct_resp(struct connectdata *conn, + int ftpcode) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + if(ftpcode != 230) { + failf(data, "ACCT rejected by server: %03d", ftpcode); + result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */ + } + else + result = ftp_state_loggedin(conn); + + return result; +} + + +static CURLcode ftp_statemach_act(struct connectdata *conn) +{ + CURLcode result; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data = conn->data; + int ftpcode; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + static const char ftpauth[][4] = { "SSL", "TLS" }; + size_t nread = 0; + + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + result = ftp_readresp(sock, pp, &ftpcode, &nread); + if(result) + return result; + + if(ftpcode) { + /* we have now received a full FTP server response */ + switch(ftpc->state) { + case FTP_WAIT220: + if(ftpcode == 230) + /* 230 User logged in - already! */ + return ftp_state_user_resp(conn, ftpcode, ftpc->state); + else if(ftpcode != 220) { + failf(data, "Got a %03d ftp-server response when 220 was expected", + ftpcode); + return CURLE_WEIRD_SERVER_REPLY; + } + + /* We have received a 220 response fine, now we proceed. */ +#ifdef HAVE_GSSAPI + if(data->set.krb) { + /* If not anonymous login, try a secure login. Note that this + procedure is still BLOCKING. */ + + Curl_sec_request_prot(conn, "private"); + /* We set private first as default, in case the line below fails to + set a valid level */ + Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); + + if(Curl_sec_login(conn)) + infof(data, "Logging in with password in cleartext!\n"); + else + infof(data, "Authentication successful\n"); + } +#endif + + if(data->set.use_ssl && + (!conn->ssl[FIRSTSOCKET].use || + (conn->bits.proxy_ssl_connected[FIRSTSOCKET] && + !conn->proxy_ssl[FIRSTSOCKET].use))) { + /* We don't have a SSL/TLS connection yet, but FTPS is + requested. Try a FTPS connection now */ + + ftpc->count3 = 0; + switch(data->set.ftpsslauth) { + case CURLFTPAUTH_DEFAULT: + case CURLFTPAUTH_SSL: + ftpc->count2 = 1; /* add one to get next */ + ftpc->count1 = 0; + break; + case CURLFTPAUTH_TLS: + ftpc->count2 = -1; /* subtract one to get next */ + ftpc->count1 = 1; + break; + default: + failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d", + (int)data->set.ftpsslauth); + return CURLE_UNKNOWN_OPTION; /* we don't know what to do */ + } + PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + state(conn, FTP_AUTH); + } + else { + result = ftp_state_user(conn); + if(result) + return result; + } + + break; + + case FTP_AUTH: + /* we have gotten the response to a previous AUTH command */ + + /* RFC2228 (page 5) says: + * + * If the server is willing to accept the named security mechanism, + * and does not require any security data, it must respond with + * reply code 234/334. + */ + + if((ftpcode == 234) || (ftpcode == 334)) { + /* Curl_ssl_connect is BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(!result) { + conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */ + result = ftp_state_user(conn); + } + } + else if(ftpc->count3 < 1) { + ftpc->count3++; + ftpc->count1 += ftpc->count2; /* get next attempt */ + result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + /* remain in this same state */ + } + else { + if(data->set.use_ssl > CURLUSESSL_TRY) + /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */ + result = CURLE_USE_SSL_FAILED; + else + /* ignore the failure and continue */ + result = ftp_state_user(conn); + } + + if(result) + return result; + break; + + case FTP_USER: + case FTP_PASS: + result = ftp_state_user_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_ACCT: + result = ftp_state_acct_resp(conn, ftpcode); + break; + + case FTP_PBSZ: + PPSENDF(&ftpc->pp, "PROT %c", + data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P'); + state(conn, FTP_PROT); + + break; + + case FTP_PROT: + if(ftpcode/100 == 2) + /* We have enabled SSL for the data connection! */ + conn->bits.ftp_use_data_ssl = + (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE; + /* FTP servers typically responds with 500 if they decide to reject + our 'P' request */ + else if(data->set.use_ssl > CURLUSESSL_CONTROL) + /* we failed and bails out */ + return CURLE_USE_SSL_FAILED; + + if(data->set.ftp_ccc) { + /* CCC - Clear Command Channel + */ + PPSENDF(&ftpc->pp, "%s", "CCC"); + state(conn, FTP_CCC); + } + else { + result = ftp_state_pwd(conn); + if(result) + return result; + } + break; + + case FTP_CCC: + if(ftpcode < 500) { + /* First shut down the SSL layer (note: this call will block) */ + result = Curl_ssl_shutdown(conn, FIRSTSOCKET); + + if(result) { + failf(conn->data, "Failed to clear the command channel (CCC)"); + return result; + } + } + + /* Then continue as normal */ + result = ftp_state_pwd(conn); + if(result) + return result; + break; + + case FTP_PWD: + if(ftpcode == 257) { + char *ptr = &data->state.buffer[4]; /* start on the first letter */ + const size_t buf_size = data->set.buffer_size; + char *dir; + bool entry_extracted = FALSE; + + dir = malloc(nread + 1); + if(!dir) + return CURLE_OUT_OF_MEMORY; + + /* Reply format is like + 257[rubbish]"" and the + RFC959 says + + The directory name can contain any character; embedded + double-quotes should be escaped by double-quotes (the + "quote-doubling" convention). + */ + + /* scan for the first double-quote for non-standard responses */ + while(ptr < &data->state.buffer[buf_size] + && *ptr != '\n' && *ptr != '\0' && *ptr != '"') + ptr++; + + if('\"' == *ptr) { + /* it started good */ + char *store; + ptr++; + for(store = dir; *ptr;) { + if('\"' == *ptr) { + if('\"' == ptr[1]) { + /* "quote-doubling" */ + *store = ptr[1]; + ptr++; + } + else { + /* end of path */ + entry_extracted = TRUE; + break; /* get out of this loop */ + } + } + else + *store = *ptr; + store++; + ptr++; + } + *store = '\0'; /* zero terminate */ + } + if(entry_extracted) { + /* If the path name does not look like an absolute path (i.e.: it + does not start with a '/'), we probably need some server-dependent + adjustments. For example, this is the case when connecting to + an OS400 FTP server: this server supports two name syntaxes, + the default one being incompatible with standard paths. In + addition, this server switches automatically to the regular path + syntax when one is encountered in a command: this results in + having an entrypath in the wrong syntax when later used in CWD. + The method used here is to check the server OS: we do it only + if the path name looks strange to minimize overhead on other + systems. */ + + if(!ftpc->server_os && dir[0] != '/') { + + result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST"); + if(result) { + free(dir); + return result; + } + Curl_safefree(ftpc->entrypath); + ftpc->entrypath = dir; /* remember this */ + infof(data, "Entry path is '%s'\n", ftpc->entrypath); + /* also save it where getinfo can access it: */ + data->state.most_recent_ftp_entrypath = ftpc->entrypath; + state(conn, FTP_SYST); + break; + } + + Curl_safefree(ftpc->entrypath); + ftpc->entrypath = dir; /* remember this */ + infof(data, "Entry path is '%s'\n", ftpc->entrypath); + /* also save it where getinfo can access it: */ + data->state.most_recent_ftp_entrypath = ftpc->entrypath; + } + else { + /* couldn't get the path */ + free(dir); + infof(data, "Failed to figure out path\n"); + } + } + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_SYST: + if(ftpcode == 215) { + char *ptr = &data->state.buffer[4]; /* start on the first letter */ + char *os; + char *store; + + os = malloc(nread + 1); + if(!os) + return CURLE_OUT_OF_MEMORY; + + /* Reply format is like + 215 + */ + while(*ptr == ' ') + ptr++; + for(store = os; *ptr && *ptr != ' ';) + *store++ = *ptr++; + *store = '\0'; /* zero terminate */ + + /* Check for special servers here. */ + + if(strcasecompare(os, "OS/400")) { + /* Force OS400 name format 1. */ + result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1"); + if(result) { + free(os); + return result; + } + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; + state(conn, FTP_NAMEFMT); + break; + } + /* Nothing special for the target server. */ + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; + } + else { + /* Cannot identify server OS. Continue anyway and cross fingers. */ + } + + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_NAMEFMT: + if(ftpcode == 250) { + /* Name format change successful: reload initial path. */ + ftp_state_pwd(conn); + break; + } + + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_QUOTE: + case FTP_POSTQUOTE: + case FTP_RETR_PREQUOTE: + case FTP_STOR_PREQUOTE: + if((ftpcode >= 400) && !ftpc->count2) { + /* failure response code, and not allowed to fail */ + failf(conn->data, "QUOT command failed with %03d", ftpcode); + return CURLE_QUOTE_ERROR; + } + result = ftp_state_quote(conn, FALSE, ftpc->state); + if(result) + return result; + + break; + + case FTP_CWD: + if(ftpcode/100 != 2) { + /* failure to CWD there */ + if(conn->data->set.ftp_create_missing_dirs && + ftpc->cwdcount && !ftpc->count2) { + /* try making it */ + ftpc->count2++; /* counter to prevent CWD-MKD loops */ + PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]); + state(conn, FTP_MKD); + } + else { + /* return failure */ + failf(data, "Server denied you to change to the given directory"); + ftpc->cwdfail = TRUE; /* don't remember this path as we failed + to enter it */ + return CURLE_REMOTE_ACCESS_DENIED; + } + } + else { + /* success */ + ftpc->count2 = 0; + if(++ftpc->cwdcount <= ftpc->dirdepth) { + /* send next CWD */ + PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]); + } + else { + result = ftp_state_mdtm(conn); + if(result) + return result; + } + } + break; + + case FTP_MKD: + if((ftpcode/100 != 2) && !ftpc->count3--) { + /* failure to MKD the dir */ + failf(data, "Failed to MKD dir: %03d", ftpcode); + return CURLE_REMOTE_ACCESS_DENIED; + } + state(conn, FTP_CWD); + /* send CWD */ + PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]); + break; + + case FTP_MDTM: + result = ftp_state_mdtm_resp(conn, ftpcode); + break; + + case FTP_TYPE: + case FTP_LIST_TYPE: + case FTP_RETR_TYPE: + case FTP_STOR_TYPE: + result = ftp_state_type_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_SIZE: + case FTP_RETR_SIZE: + case FTP_STOR_SIZE: + result = ftp_state_size_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_REST: + case FTP_RETR_REST: + result = ftp_state_rest_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_PRET: + if(ftpcode != 200) { + /* there only is this one standard OK return code. */ + failf(data, "PRET command not accepted: %03d", ftpcode); + return CURLE_FTP_PRET_FAILED; + } + result = ftp_state_use_pasv(conn); + break; + + case FTP_PASV: + result = ftp_state_pasv_resp(conn, ftpcode); + break; + + case FTP_PORT: + result = ftp_state_port_resp(conn, ftpcode); + break; + + case FTP_LIST: + case FTP_RETR: + result = ftp_state_get_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_STOR: + result = ftp_state_stor_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, FTP_STOP); + break; + } + } /* if(ftpcode) */ + + return result; +} + + +/* called repeatedly until done from multi.c */ +static CURLcode ftp_multi_statemach(struct connectdata *conn, + bool *done) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE); + + /* Check for the state outside of the Curl_socket_check() return code checks + since at times we are in fact already in this state when this function + gets called. */ + *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode ftp_block_statemach(struct connectdata *conn) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + CURLcode result = CURLE_OK; + + while(ftpc->state != FTP_STOP) { + result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */); + if(result) + break; + } + + return result; +} + +/* + * ftp_connect() should do everything that is to be considered a part of + * the connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + * + */ +static CURLcode ftp_connect(struct connectdata *conn, + bool *done) /* see description above */ +{ + CURLcode result; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections on ftp */ + connkeep(conn, "FTP default"); + + pp->response_time = RESP_TIMEOUT; /* set default response time-out */ + pp->statemach_act = ftp_statemach_act; + pp->endofresp = ftp_endofresp; + pp->conn = conn; + + if(conn->handler->flags & PROTOPT_SSL) { + /* BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(result) + return result; + } + + Curl_pp_init(pp); /* init the generic pingpong data */ + + /* When we connect, we start in the state where we await the 220 + response */ + state(conn, FTP_WAIT220); + + result = ftp_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * ftp_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode ftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + ssize_t nread; + int ftpcode; + CURLcode result = CURLE_OK; + char *path = NULL; + + if(!ftp) + return CURLE_OK; + + switch(status) { + case CURLE_BAD_DOWNLOAD_RESUME: + case CURLE_FTP_WEIRD_PASV_REPLY: + case CURLE_FTP_PORT_FAILED: + case CURLE_FTP_ACCEPT_FAILED: + case CURLE_FTP_ACCEPT_TIMEOUT: + case CURLE_FTP_COULDNT_SET_TYPE: + case CURLE_FTP_COULDNT_RETR_FILE: + case CURLE_PARTIAL_FILE: + case CURLE_UPLOAD_FAILED: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_FILESIZE_EXCEEDED: + case CURLE_REMOTE_FILE_NOT_FOUND: + case CURLE_WRITE_ERROR: + /* the connection stays alive fine even though this happened */ + /* fall-through */ + case CURLE_OK: /* doesn't affect the control connection's status */ + if(!premature) + break; + + /* until we cope better with prematurely ended requests, let them + * fallback as if in complete failure */ + /* FALLTHROUGH */ + default: /* by default, an error means the control connection is + wedged and should not be used anymore */ + ftpc->ctl_valid = FALSE; + ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the + current path, as this connection is going */ + connclose(conn, "FTP ended with bad error code"); + result = status; /* use the already set error code */ + break; + } + + /* now store a copy of the directory we are in */ + free(ftpc->prevpath); + + if(data->state.wildcardmatch) { + if(data->set.chunk_end && ftpc->file) { + Curl_set_in_callback(data, true); + data->set.chunk_end(data->wildcard.customptr); + Curl_set_in_callback(data, false); + } + ftpc->known_filesize = -1; + } + + if(!result) + /* get the "raw" path */ + result = Curl_urldecode(data, ftp->path, 0, &path, NULL, TRUE); + if(result) { + /* We can limp along anyway (and should try to since we may already be in + * the error path) */ + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "FTP: out of memory!"); /* mark for connection closure */ + ftpc->prevpath = NULL; /* no path remembering */ + } + else { + size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */ + size_t dlen = strlen(path)-flen; + if(!ftpc->cwdfail) { + ftpc->prevmethod = data->set.ftp_filemethod; + if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) { + ftpc->prevpath = path; + if(flen) + /* if 'path' is not the whole string */ + ftpc->prevpath[dlen] = 0; /* terminate */ + } + else { + free(path); + /* we never changed dir */ + ftpc->prevpath = strdup(""); + if(!ftpc->prevpath) + return CURLE_OUT_OF_MEMORY; + } + if(ftpc->prevpath) + infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath); + } + else { + ftpc->prevpath = NULL; /* no path */ + free(path); + } + } + /* free the dir tree and file parts */ + freedirs(ftpc); + + /* shut down the socket to inform the server we're done */ + +#ifdef _WIN32_WCE + shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */ +#endif + + if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { + if(!result && ftpc->dont_check && data->req.maxdownload > 0) { + /* partial download completed */ + result = Curl_pp_sendf(pp, "%s", "ABOR"); + if(result) { + failf(data, "Failure sending ABOR command: %s", + curl_easy_strerror(result)); + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "ABOR command failed"); /* connection closure */ + } + } + + if(conn->ssl[SECONDARYSOCKET].use) { + /* The secondary socket is using SSL so we must close down that part + first before we close the socket for real */ + Curl_ssl_close(conn, SECONDARYSOCKET); + + /* Note that we keep "use" set to TRUE since that (next) connection is + still requested to use SSL */ + } + close_secondarysocket(conn); + } + + if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid && + pp->pending_resp && !premature) { + /* + * Let's see what the server says about the transfer we just performed, + * but lower the timeout as sometimes this connection has died while the + * data has been transferred. This happens when doing through NATs etc that + * abandon old silent connections. + */ + long old_time = pp->response_time; + + pp->response_time = 60*1000; /* give it only a minute for now */ + pp->response = Curl_now(); /* timeout relative now */ + + result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + + pp->response_time = old_time; /* set this back to previous value */ + + if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) { + failf(data, "control connection looks dead"); + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */ + } + + if(result) + return result; + + if(ftpc->dont_check && data->req.maxdownload > 0) { + /* we have just sent ABOR and there is no reliable way to check if it was + * successful or not; we have to close the connection now */ + infof(data, "partial download completed, closing connection\n"); + connclose(conn, "Partial download with no ability to check"); + return result; + } + + if(!ftpc->dont_check) { + /* 226 Transfer complete, 250 Requested file action okay, completed. */ + if((ftpcode != 226) && (ftpcode != 250)) { + failf(data, "server did not report OK, got %d", ftpcode); + result = CURLE_PARTIAL_FILE; + } + } + } + + if(result || premature) + /* the response code from the transfer showed an error already so no + use checking further */ + ; + else if(data->set.upload) { + if((-1 != data->state.infilesize) && + (data->state.infilesize != data->req.writebytecount) && + !data->set.crlf && + (ftp->transfer == FTPTRANSFER_BODY)) { + failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T + " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", + data->req.bytecount, data->state.infilesize); + result = CURLE_PARTIAL_FILE; + } + } + else { + if((-1 != data->req.size) && + (data->req.size != data->req.bytecount) && +#ifdef CURL_DO_LINEEND_CONV + /* Most FTP servers don't adjust their file SIZE response for CRLFs, so + * we'll check to see if the discrepancy can be explained by the number + * of CRLFs we've changed to LFs. + */ + ((data->req.size + data->state.crlf_conversions) != + data->req.bytecount) && +#endif /* CURL_DO_LINEEND_CONV */ + (data->req.maxdownload != data->req.bytecount)) { + failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T + " bytes", data->req.bytecount); + result = CURLE_PARTIAL_FILE; + } + else if(!ftpc->dont_check && + !data->req.bytecount && + (data->req.size>0)) { + failf(data, "No data was received!"); + result = CURLE_FTP_COULDNT_RETR_FILE; + } + } + + /* clear these for next connection */ + ftp->transfer = FTPTRANSFER_BODY; + ftpc->dont_check = FALSE; + + /* Send any post-transfer QUOTE strings? */ + if(!status && !result && !premature && data->set.postquote) + result = ftp_sendquote(conn, data->set.postquote); + Curl_safefree(ftp->pathalloc); + return result; +} + +/*********************************************************************** + * + * ftp_sendquote() + * + * Where a 'quote' means a list of custom commands to send to the server. + * The quote list is passed as an argument. + * + * BLOCKING + */ + +static +CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote) +{ + struct curl_slist *item; + ssize_t nread; + int ftpcode; + CURLcode result; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + item = quote; + while(item) { + if(item->data) { + char *cmd = item->data; + bool acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal FTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + acceptfail = TRUE; + } + + PPSENDF(&conn->proto.ftpc.pp, "%s", cmd); + + pp->response = Curl_now(); /* timeout relative now */ + + result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + if(result) + return result; + + if(!acceptfail && (ftpcode >= 400)) { + failf(conn->data, "QUOT string not accepted: %s", cmd); + return CURLE_QUOTE_ERROR; + } + } + + item = item->next; + } + + return CURLE_OK; +} + +/*********************************************************************** + * + * ftp_need_type() + * + * Returns TRUE if we in the current situation should send TYPE + */ +static int ftp_need_type(struct connectdata *conn, + bool ascii_wanted) +{ + return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I'); +} + +/*********************************************************************** + * + * ftp_nb_type() + * + * Set TYPE. We only deal with ASCII or BINARY so this function + * sets one of them. + * If the transfer type is not sent, simulate on OK response in newstate + */ +static CURLcode ftp_nb_type(struct connectdata *conn, + bool ascii, ftpstate newstate) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result; + char want = (char)(ascii?'A':'I'); + + if(ftpc->transfertype == want) { + state(conn, newstate); + return ftp_state_type_resp(conn, 200, newstate); + } + + PPSENDF(&ftpc->pp, "TYPE %c", want); + state(conn, newstate); + + /* keep track of our current transfer type */ + ftpc->transfertype = want; + return CURLE_OK; +} + +/*************************************************************************** + * + * ftp_pasv_verbose() + * + * This function only outputs some informationals about this second connection + * when we've issued a PASV command before and thus we have connected to a + * possibly new IP address. + * + */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void +ftp_pasv_verbose(struct connectdata *conn, + Curl_addrinfo *ai, + char *newhost, /* ascii version */ + int port) +{ + char buf[256]; + Curl_printable_address(ai, buf, sizeof(buf)); + infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port); +} +#endif + +/* + * ftp_do_more() + * + * This function shall be called when the second FTP (data) connection is + * connected. + * + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back + * (which basically is only for when PASV is being sent to retry a failed + * EPSV). + */ + +static CURLcode ftp_do_more(struct connectdata *conn, int *completep) +{ + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + bool connected = FALSE; + bool complete = FALSE; + + /* the ftp struct is inited in ftp_connect() */ + struct FTP *ftp = data->req.protop; + + /* if the second connection isn't done yet, wait for it */ + if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { + if(Curl_connect_ongoing(conn)) { + /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port + aren't used so we blank their arguments. */ + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0); + + return result; + } + + result = Curl_is_connected(conn, SECONDARYSOCKET, &connected); + + /* Ready to do more? */ + if(connected) { + DEBUGF(infof(data, "DO-MORE connected phase starts\n")); + } + else { + if(result && (ftpc->count1 == 0)) { + *completep = -1; /* go back to DOING please */ + /* this is a EPSV connect failing, try PASV instead */ + return ftp_epsv_disable(conn); + } + return result; + } + } + + result = Curl_proxy_connect(conn, SECONDARYSOCKET); + if(result) + return result; + + if(CONNECT_SECONDARYSOCKET_PROXY_SSL()) + return result; + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && + Curl_connect_ongoing(conn)) + return result; + + + if(ftpc->state) { + /* already in a state so skip the initial commands. + They are only done to kickstart the do_more state */ + result = ftp_multi_statemach(conn, &complete); + + *completep = (int)complete; + + /* if we got an error or if we don't wait for a data connection return + immediately */ + if(result || (ftpc->wait_data_conn != TRUE)) + return result; + + if(ftpc->wait_data_conn) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ + *completep = 0; + } + + if(ftp->transfer <= FTPTRANSFER_INFO) { + /* a transfer is about to take place, or if not a file name was given + so we'll do a SIZE on it later and then we need the right TYPE first */ + + if(ftpc->wait_data_conn == TRUE) { + bool serv_conned; + + result = ReceivedServerConnect(conn, &serv_conned); + if(result) + return result; /* Failed to accept data connection */ + + if(serv_conned) { + /* It looks data connection is established */ + result = AcceptServerConnect(conn); + ftpc->wait_data_conn = FALSE; + if(!result) + result = InitiateTransfer(conn); + + if(result) + return result; + + *completep = 1; /* this state is now complete when the server has + connected back to us */ + } + } + else if(data->set.upload) { + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE); + if(result) + return result; + + result = ftp_multi_statemach(conn, &complete); + if(ftpc->wait_data_conn) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ + *completep = 0; + else + *completep = (int)complete; + } + else { + /* download */ + ftp->downloadsize = -1; /* unknown as of yet */ + + result = Curl_range(conn); + + if(result == CURLE_OK && data->req.maxdownload >= 0) { + /* Don't check for successful transfer */ + ftpc->dont_check = TRUE; + } + + if(result) + ; + else if(data->set.ftp_list_only || !ftpc->file) { + /* The specified path ends with a slash, and therefore we think this + is a directory that is requested, use LIST. But before that we + need to set ASCII transfer mode. */ + + /* But only if a body transfer was requested. */ + if(ftp->transfer == FTPTRANSFER_BODY) { + result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE); + if(result) + return result; + } + /* otherwise just fall through */ + } + else { + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE); + if(result) + return result; + } + + result = ftp_multi_statemach(conn, &complete); + *completep = (int)complete; + } + return result; + } + + if(!result && (ftp->transfer != FTPTRANSFER_BODY)) + /* no data to transfer. FIX: it feels like a kludge to have this here + too! */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + + if(!ftpc->wait_data_conn) { + /* no waiting for the data connection so this is now complete */ + *completep = 1; + DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result)); + } + + return result; +} + + + +/*********************************************************************** + * + * ftp_perform() + * + * This is the actual DO function for FTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode ftp_perform(struct connectdata *conn, + bool *connected, /* connect status after PASV / PORT */ + bool *dophase_done) +{ + /* this is FTP and no proxy */ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* requested no body means no transfer... */ + struct FTP *ftp = conn->data->req.protop; + ftp->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + result = ftp_state_quote(conn, TRUE, FTP_QUOTE); + if(result) + return result; + + /* run the state-machine */ + result = ftp_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[SECONDARYSOCKET]; + + infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected); + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete1\n")); + + return result; +} + +static void wc_data_dtor(void *ptr) +{ + struct ftp_wc *ftpwc = ptr; + if(ftpwc && ftpwc->parser) + Curl_ftp_parselist_data_free(&ftpwc->parser); + free(ftpwc); +} + +static CURLcode init_wc_data(struct connectdata *conn) +{ + char *last_slash; + struct FTP *ftp = conn->data->req.protop; + char *path = ftp->path; + struct WildcardData *wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + struct ftp_wc *ftpwc = NULL; + + last_slash = strrchr(ftp->path, '/'); + if(last_slash) { + last_slash++; + if(last_slash[0] == '\0') { + wildcard->state = CURLWC_CLEAN; + result = ftp_parse_url_path(conn); + return result; + } + wildcard->pattern = strdup(last_slash); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + last_slash[0] = '\0'; /* cut file from path */ + } + else { /* there is only 'wildcard pattern' or nothing */ + if(path[0]) { + wildcard->pattern = strdup(path); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + path[0] = '\0'; + } + else { /* only list */ + wildcard->state = CURLWC_CLEAN; + result = ftp_parse_url_path(conn); + return result; + } + } + + /* program continues only if URL is not ending with slash, allocate needed + resources for wildcard transfer */ + + /* allocate ftp protocol specific wildcard data */ + ftpwc = calloc(1, sizeof(struct ftp_wc)); + if(!ftpwc) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + /* INITIALIZE parselist structure */ + ftpwc->parser = Curl_ftp_parselist_data_alloc(); + if(!ftpwc->parser) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */ + wildcard->dtor = wc_data_dtor; + + /* wildcard does not support NOCWD option (assert it?) */ + if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD) + conn->data->set.ftp_filemethod = FTPFILE_MULTICWD; + + /* try to parse ftp url */ + result = ftp_parse_url_path(conn); + if(result) { + goto fail; + } + + wildcard->path = strdup(ftp->path); + if(!wildcard->path) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + /* backup old write_function */ + ftpwc->backup.write_function = conn->data->set.fwrite_func; + /* parsing write function */ + conn->data->set.fwrite_func = Curl_ftp_parselist; + /* backup old file descriptor */ + ftpwc->backup.file_descriptor = conn->data->set.out; + /* let the writefunc callback know what curl pointer is working with */ + conn->data->set.out = conn; + + infof(conn->data, "Wildcard - Parsing started\n"); + return CURLE_OK; + + fail: + if(ftpwc) { + Curl_ftp_parselist_data_free(&ftpwc->parser); + free(ftpwc); + } + Curl_safefree(wildcard->pattern); + wildcard->dtor = ZERO_NULL; + wildcard->protdata = NULL; + return result; +} + +/* This is called recursively */ +static CURLcode wc_statemach(struct connectdata *conn) +{ + struct WildcardData * const wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + + switch(wildcard->state) { + case CURLWC_INIT: + result = init_wc_data(conn); + if(wildcard->state == CURLWC_CLEAN) + /* only listing! */ + break; + wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; + break; + + case CURLWC_MATCHING: { + /* In this state is LIST response successfully parsed, so lets restore + previous WRITEFUNCTION callback and WRITEDATA pointer */ + struct ftp_wc *ftpwc = wildcard->protdata; + conn->data->set.fwrite_func = ftpwc->backup.write_function; + conn->data->set.out = ftpwc->backup.file_descriptor; + ftpwc->backup.write_function = ZERO_NULL; + ftpwc->backup.file_descriptor = NULL; + wildcard->state = CURLWC_DOWNLOADING; + + if(Curl_ftp_parselist_geterror(ftpwc->parser)) { + /* error found in LIST parsing */ + wildcard->state = CURLWC_CLEAN; + return wc_statemach(conn); + } + if(wildcard->filelist.size == 0) { + /* no corresponding file */ + wildcard->state = CURLWC_CLEAN; + return CURLE_REMOTE_FILE_NOT_FOUND; + } + return wc_statemach(conn); + } + + case CURLWC_DOWNLOADING: { + /* filelist has at least one file, lets get first one */ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; + struct FTP *ftp = conn->data->req.protop; + + char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); + if(!tmp_path) + return CURLE_OUT_OF_MEMORY; + + /* switch default ftp->path and tmp_path */ + free(ftp->pathalloc); + ftp->pathalloc = ftp->path = tmp_path; + + infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); + if(conn->data->set.chunk_bgn) { + long userresponse; + Curl_set_in_callback(conn->data, true); + userresponse = conn->data->set.chunk_bgn( + finfo, wildcard->customptr, (int)wildcard->filelist.size); + Curl_set_in_callback(conn->data, false); + switch(userresponse) { + case CURL_CHUNK_BGN_FUNC_SKIP: + infof(conn->data, "Wildcard - \"%s\" skipped by user\n", + finfo->filename); + wildcard->state = CURLWC_SKIP; + return wc_statemach(conn); + case CURL_CHUNK_BGN_FUNC_FAIL: + return CURLE_CHUNK_FAILED; + } + } + + if(finfo->filetype != CURLFILETYPE_FILE) { + wildcard->state = CURLWC_SKIP; + return wc_statemach(conn); + } + + if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) + ftpc->known_filesize = finfo->size; + + result = ftp_parse_url_path(conn); + if(result) + return result; + + /* we don't need the Curl_fileinfo of first file anymore */ + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + + if(wildcard->filelist.size == 0) { /* remains only one file to down. */ + wildcard->state = CURLWC_CLEAN; + /* after that will be ftp_do called once again and no transfer + will be done because of CURLWC_CLEAN state */ + return CURLE_OK; + } + } break; + + case CURLWC_SKIP: { + if(conn->data->set.chunk_end) { + Curl_set_in_callback(conn->data, true); + conn->data->set.chunk_end(conn->data->wildcard.customptr); + Curl_set_in_callback(conn->data, false); + } + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + wildcard->state = (wildcard->filelist.size == 0) ? + CURLWC_CLEAN : CURLWC_DOWNLOADING; + return wc_statemach(conn); + } + + case CURLWC_CLEAN: { + struct ftp_wc *ftpwc = wildcard->protdata; + result = CURLE_OK; + if(ftpwc) + result = Curl_ftp_parselist_geterror(ftpwc->parser); + + wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; + } break; + + case CURLWC_DONE: + case CURLWC_ERROR: + case CURLWC_CLEAR: + if(wildcard->dtor) + wildcard->dtor(wildcard->protdata); + break; + } + + return result; +} + +/*********************************************************************** + * + * ftp_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (ftp_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode ftp_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + *done = FALSE; /* default to false */ + ftpc->wait_data_conn = FALSE; /* default to no such wait */ + + if(conn->data->state.wildcardmatch) { + result = wc_statemach(conn); + if(conn->data->wildcard.state == CURLWC_SKIP || + conn->data->wildcard.state == CURLWC_DONE) { + /* do not call ftp_regular_transfer */ + return CURLE_OK; + } + if(result) /* error, loop or skipping the file */ + return result; + } + else { /* no wildcard FSM needed */ + result = ftp_parse_url_path(conn); + if(result) + return result; + } + + result = ftp_regular_transfer(conn, done); + + return result; +} + + +CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd) +{ + ssize_t bytes_written; +#define SBUF_SIZE 1024 + char s[SBUF_SIZE]; + size_t write_len; + char *sptr = s; + CURLcode result = CURLE_OK; +#ifdef HAVE_GSSAPI + enum protection_level data_sec = conn->data_prot; +#endif + + if(!cmd) + return CURLE_BAD_FUNCTION_ARGUMENT; + + write_len = strlen(cmd); + if(!write_len || write_len > (sizeof(s) -3)) + return CURLE_BAD_FUNCTION_ARGUMENT; + + memcpy(&s, cmd, write_len); + strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */ + write_len += 2; + bytes_written = 0; + + result = Curl_convert_to_network(conn->data, s, write_len); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + + for(;;) { +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CMD; +#endif + result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, + &bytes_written); +#ifdef HAVE_GSSAPI + DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); + conn->data_prot = data_sec; +#endif + + if(result) + break; + + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written); + + if(bytes_written != (ssize_t)write_len) { + write_len -= bytes_written; + sptr += bytes_written; + } + else + break; + } + + return result; +} + +/*********************************************************************** + * + * ftp_quit() + * + * This should be called before calling sclose() on an ftp control connection + * (not data connections). We should then wait for the response from the + * server before returning. The calling code should then try to close the + * connection. + * + */ +static CURLcode ftp_quit(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->proto.ftpc.ctl_valid) { + result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT"); + if(result) { + failf(conn->data, "Failure sending QUIT command: %s", + curl_easy_strerror(result)); + conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "QUIT command failed"); /* mark for connection closure */ + state(conn, FTP_STOP); + return result; + } + + state(conn, FTP_QUIT); + + result = ftp_block_statemach(conn); + } + + return result; +} + +/*********************************************************************** + * + * ftp_disconnect() + * + * Disconnect from an FTP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. + + ftp_quit() will check the state of ftp->ctl_valid. If it's ok it + will try to send the QUIT command, otherwise it will just return. + */ + if(dead_connection) + ftpc->ctl_valid = FALSE; + + /* The FTP session may or may not have been allocated/setup at this point! */ + (void)ftp_quit(conn); /* ignore errors on the QUIT */ + + if(ftpc->entrypath) { + struct Curl_easy *data = conn->data; + if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) { + data->state.most_recent_ftp_entrypath = NULL; + } + free(ftpc->entrypath); + ftpc->entrypath = NULL; + } + + freedirs(ftpc); + free(ftpc->prevpath); + ftpc->prevpath = NULL; + free(ftpc->server_os); + ftpc->server_os = NULL; + + Curl_pp_disconnect(pp); + +#ifdef HAVE_GSSAPI + Curl_sec_end(conn); +#endif + + return CURLE_OK; +} + +/*********************************************************************** + * + * ftp_parse_url_path() + * + * Parse the URL path into separate path components. + * + */ +static +CURLcode ftp_parse_url_path(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + /* the ftp struct is already inited in ftp_connect() */ + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + const char *slash_pos; /* position of the first '/' char in curpos */ + const char *path_to_use = ftp->path; + const char *cur_pos; + const char *filename = NULL; + + cur_pos = path_to_use; /* current position in path. point at the begin of + next path component */ + + ftpc->ctl_valid = FALSE; + ftpc->cwdfail = FALSE; + + switch(data->set.ftp_filemethod) { + case FTPFILE_NOCWD: + /* fastest, but less standard-compliant */ + + /* + The best time to check whether the path is a file or directory is right + here. so: + + the first condition in the if() right here, is there just in case + someone decides to set path to NULL one day + */ + if(path_to_use[0] && + (path_to_use[strlen(path_to_use) - 1] != '/') ) + filename = path_to_use; /* this is a full file path */ + /* + else { + ftpc->file is not used anywhere other than for operations on a file. + In other words, never for directory operations. + So we can safely leave filename as NULL here and use it as a + argument in dir/file decisions. + } + */ + break; + + case FTPFILE_SINGLECWD: + /* get the last slash */ + if(!path_to_use[0]) { + /* no dir, no file */ + ftpc->dirdepth = 0; + break; + } + slash_pos = strrchr(cur_pos, '/'); + if(slash_pos || !*cur_pos) { + size_t dirlen = slash_pos-cur_pos; + CURLcode result; + + ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + if(!dirlen) + dirlen++; + + result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/", + slash_pos ? dirlen : 1, + &ftpc->dirs[0], NULL, + TRUE); + if(result) { + freedirs(ftpc); + return result; + } + ftpc->dirdepth = 1; /* we consider it to be a single dir */ + filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */ + } + else + filename = cur_pos; /* this is a file name only */ + break; + + default: /* allow pretty much anything */ + case FTPFILE_MULTICWD: + ftpc->dirdepth = 0; + ftpc->diralloc = 5; /* default dir depth to allocate */ + ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + /* we have a special case for listing the root dir only */ + if(!strcmp(path_to_use, "/")) { + cur_pos++; /* make it point to the zero byte */ + ftpc->dirs[0] = strdup("/"); + ftpc->dirdepth++; + } + else { + /* parse the URL path into separate path components */ + while((slash_pos = strchr(cur_pos, '/')) != NULL) { + /* 1 or 0 pointer offset to indicate absolute directory */ + ssize_t absolute_dir = ((cur_pos - ftp->path > 0) && + (ftpc->dirdepth == 0))?1:0; + + /* seek out the next path component */ + if(slash_pos-cur_pos) { + /* we skip empty path components, like "x//y" since the FTP command + CWD requires a parameter and a non-existent parameter a) doesn't + work on many servers and b) has no effect on the others. */ + size_t len = slash_pos - cur_pos + absolute_dir; + CURLcode result = + Curl_urldecode(conn->data, cur_pos - absolute_dir, len, + &ftpc->dirs[ftpc->dirdepth], NULL, + TRUE); + if(result) { + freedirs(ftpc); + return result; + } + } + else { + cur_pos = slash_pos + 1; /* jump to the rest of the string */ + if(!ftpc->dirdepth) { + /* path starts with a slash, add that as a directory */ + ftpc->dirs[ftpc->dirdepth] = strdup("/"); + if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */ + failf(data, "no memory"); + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + } + continue; + } + + cur_pos = slash_pos + 1; /* jump to the rest of the string */ + if(++ftpc->dirdepth >= ftpc->diralloc) { + /* enlarge array */ + char **bigger; + ftpc->diralloc *= 2; /* double the size each time */ + bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0])); + if(!bigger) { + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + ftpc->dirs = bigger; + } + } + } + filename = cur_pos; /* the rest is the file name */ + break; + } /* switch */ + + if(filename && *filename) { + CURLcode result = + Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE); + + if(result) { + freedirs(ftpc); + return result; + } + } + else + ftpc->file = NULL; /* instead of point to a zero byte, we make it a NULL + pointer */ + + if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) { + /* We need a file name when uploading. Return error! */ + failf(data, "Uploading to a URL without a file name!"); + return CURLE_URL_MALFORMAT; + } + + ftpc->cwddone = FALSE; /* default to not done */ + + if(ftpc->prevpath) { + /* prevpath is "raw" so we convert the input path before we compare the + strings */ + size_t dlen; + char *path; + CURLcode result = + Curl_urldecode(conn->data, ftp->path, 0, &path, &dlen, TRUE); + if(result) { + freedirs(ftpc); + return result; + } + + dlen -= ftpc->file?strlen(ftpc->file):0; + if((dlen == strlen(ftpc->prevpath)) && + !strncmp(path, ftpc->prevpath, dlen) && + (ftpc->prevmethod == data->set.ftp_filemethod)) { + infof(data, "Request has same path as previous transfer\n"); + ftpc->cwddone = TRUE; + } + free(path); + } + + return CURLE_OK; +} + +/* call this when the DO phase has completed */ +static CURLcode ftp_dophase_done(struct connectdata *conn, + bool connected) +{ + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(connected) { + int completed; + CURLcode result = ftp_do_more(conn, &completed); + + if(result) { + close_secondarysocket(conn); + return result; + } + } + + if(ftp->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + else if(!connected) + /* since we didn't connect now, we want do_more to get called */ + conn->bits.do_more = TRUE; + + ftpc->ctl_valid = TRUE; /* seems good */ + + return CURLE_OK; +} + +/* called from multi.c while DOing */ +static CURLcode ftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = ftp_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = ftp_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete2\n")); + } + return result; +} + +/*********************************************************************** + * + * ftp_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + * + * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the + * ftp_done() function without finding any major problem. + */ +static +CURLcode ftp_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + data->req.size = -1; /* make sure this is unknown at this point */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + ftpc->ctl_valid = TRUE; /* starts good */ + + result = ftp_perform(conn, + &connected, /* have we connected after PASV/PORT */ + dophase_done); /* all commands in the DO-phase done? */ + + if(!result) { + + if(!*dophase_done) + /* the DO phase has not completed yet */ + return CURLE_OK; + + result = ftp_dophase_done(conn, connected); + + if(result) + return result; + } + else + freedirs(ftpc); + + return result; +} + +static CURLcode ftp_setup_connection(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + char *type; + struct FTP *ftp; + + conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1); + if(NULL == ftp) + return CURLE_OUT_OF_MEMORY; + + ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ + + /* FTP URLs support an extension like ";type=" that + * we'll try to get now! */ + type = strstr(ftp->path, ";type="); + + if(!type) + type = strstr(conn->host.rawalloc, ";type="); + + if(type) { + char command; + *type = 0; /* it was in the middle of the hostname */ + command = Curl_raw_toupper(type[6]); + conn->bits.type_set = TRUE; + + switch(command) { + case 'A': /* ASCII mode */ + data->set.prefer_ascii = TRUE; + break; + + case 'D': /* directory mode */ + data->set.ftp_list_only = TRUE; + break; + + case 'I': /* binary mode */ + default: + /* switch off ASCII */ + data->set.prefer_ascii = FALSE; + break; + } + } + + /* get some initial data into the ftp struct */ + ftp->transfer = FTPTRANSFER_BODY; + ftp->downloadsize = 0; + + /* No need to duplicate user+password, the connectdata struct won't change + during a session, but we re-init them here since on subsequent inits + since the conn struct may have changed or been replaced. + */ + ftp->user = conn->user; + ftp->passwd = conn->passwd; + if(isBadFtpString(ftp->user)) + return CURLE_URL_MALFORMAT; + if(isBadFtpString(ftp->passwd)) + return CURLE_URL_MALFORMAT; + + conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_FTP */ diff --git a/libcurl/lib/ftp.h b/libcurl/lib/ftp.h new file mode 100644 index 0000000..828d69a --- /dev/null +++ b/libcurl/lib/ftp.h @@ -0,0 +1,162 @@ +#ifndef HEADER_CURL_FTP_H +#define HEADER_CURL_FTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" + +#ifndef CURL_DISABLE_FTP +extern const struct Curl_handler Curl_handler_ftp; + +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_ftps; +#endif + +CURLcode Curl_ftpsend(struct connectdata *, const char *cmd); +CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn, + int *ftpcode); +#endif /* CURL_DISABLE_FTP */ + +/**************************************************************************** + * FTP unique setup + ***************************************************************************/ +typedef enum { + FTP_STOP, /* do nothing state, stops the state machine */ + FTP_WAIT220, /* waiting for the initial 220 response immediately after + a connect */ + FTP_AUTH, + FTP_USER, + FTP_PASS, + FTP_ACCT, + FTP_PBSZ, + FTP_PROT, + FTP_CCC, + FTP_PWD, + FTP_SYST, + FTP_NAMEFMT, + FTP_QUOTE, /* waiting for a response to a command sent in a quote list */ + FTP_RETR_PREQUOTE, + FTP_STOR_PREQUOTE, + FTP_POSTQUOTE, + FTP_CWD, /* change dir */ + FTP_MKD, /* if the dir didn't exist */ + FTP_MDTM, /* to figure out the datestamp */ + FTP_TYPE, /* to set type when doing a head-like request */ + FTP_LIST_TYPE, /* set type when about to do a dir list */ + FTP_RETR_TYPE, /* set type when about to RETR a file */ + FTP_STOR_TYPE, /* set type when about to STOR a file */ + FTP_SIZE, /* get the remote file's size for head-like request */ + FTP_RETR_SIZE, /* get the remote file's size for RETR */ + FTP_STOR_SIZE, /* get the size for STOR */ + FTP_REST, /* when used to check if the server supports it in head-like */ + FTP_RETR_REST, /* when asking for "resume" in for RETR */ + FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */ + FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */ + FTP_PASV, /* generic state for PASV and EPSV, check count1 */ + FTP_LIST, /* generic state for LIST, NLST or a custom list command */ + FTP_RETR, + FTP_STOR, /* generic state for STOR and APPE */ + FTP_QUIT, + FTP_LAST /* never used */ +} ftpstate; + +struct ftp_parselist_data; /* defined later in ftplistparser.c */ + +struct ftp_wc { + struct ftp_parselist_data *parser; + + struct { + curl_write_callback write_function; + FILE *file_descriptor; + } backup; +}; + +typedef enum { + FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */ + FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */ + FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the + file */ +} curl_ftpfile; + +/* This FTP struct is used in the Curl_easy. All FTP data that is + connection-oriented must be in FTP_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct FTP { + char *user; /* user name string */ + char *passwd; /* password string */ + char *path; /* points to the urlpieces struct field */ + char *pathalloc; /* if non-NULL a pointer to an allocated path */ + + /* transfer a file/body or not, done as a typedefed enum just to make + debuggers display the full symbol and not just the numerical value */ + curl_pp_transfer transfer; + curl_off_t downloadsize; +}; + + +/* ftp_conn is used for struct connection-oriented data in the connectdata + struct */ +struct ftp_conn { + struct pingpong pp; + char *entrypath; /* the PWD reply when we logged on */ + char **dirs; /* realloc()ed array for path components */ + int dirdepth; /* number of entries used in the 'dirs' array */ + int diralloc; /* number of entries allocated for the 'dirs' array */ + char *file; /* decoded file */ + bool dont_check; /* Set to TRUE to prevent the final (post-transfer) + file size and 226/250 status check. It should still + read the line, just ignore the result. */ + bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If + the connection has timed out or been closed, this + should be FALSE when it gets to Curl_ftp_quit() */ + bool cwddone; /* if it has been determined that the proper CWD combo + already has been done */ + int cwdcount; /* number of CWD commands issued */ + bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent + caching the current directory */ + bool wait_data_conn; /* this is set TRUE if data connection is waited */ + char *prevpath; /* conn->path from the previous transfer */ + curl_ftpfile prevmethod; /* ftp method in previous transfer */ + char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a + and others (A/I or zero) */ + int count1; /* general purpose counter for the state machine */ + int count2; /* general purpose counter for the state machine */ + int count3; /* general purpose counter for the state machine */ + ftpstate state; /* always use ftp.c:state() to change state! */ + ftpstate state_saved; /* transfer type saved to be reloaded after + data connection is established */ + curl_off_t retr_size_saved; /* Size of retrieved file saved */ + char *server_os; /* The target server operating system. */ + curl_off_t known_filesize; /* file size is different from -1, if wildcard + LIST parsing was done and wc_statemach set + it */ + /* newhost is the (allocated) IP addr or host name to connect the data + connection to */ + char *newhost; /* this is the pair to connect the DATA... */ + unsigned short newport; /* connection to */ + +}; + +#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */ + +#endif /* HEADER_CURL_FTP_H */ diff --git a/libcurl/lib/ftplistparser.c b/libcurl/lib/ftplistparser.c new file mode 100644 index 0000000..c4eb437 --- /dev/null +++ b/libcurl/lib/ftplistparser.c @@ -0,0 +1,1019 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/** + * Now implemented: + * + * 1) Unix version 1 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog + * 2) Unix version 2 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog + * 3) Unix version 3 + * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog + * 4) Unix symlink + * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000 + * 5) DOS style + * 01-29-97 11:32PM prog + */ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#include + +#include "urldata.h" +#include "fileinfo.h" +#include "llist.h" +#include "strtoofft.h" +#include "ftp.h" +#include "ftplistparser.h" +#include "curl_fnmatch.h" +#include "curl_memory.h" +#include "multiif.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* allocs buffer which will contain one line of LIST command response */ +#define FTP_BUFFER_ALLOCSIZE 160 + +typedef enum { + PL_UNIX_TOTALSIZE = 0, + PL_UNIX_FILETYPE, + PL_UNIX_PERMISSION, + PL_UNIX_HLINKS, + PL_UNIX_USER, + PL_UNIX_GROUP, + PL_UNIX_SIZE, + PL_UNIX_TIME, + PL_UNIX_FILENAME, + PL_UNIX_SYMLINK +} pl_unix_mainstate; + +typedef union { + enum { + PL_UNIX_TOTALSIZE_INIT = 0, + PL_UNIX_TOTALSIZE_READING + } total_dirsize; + + enum { + PL_UNIX_HLINKS_PRESPACE = 0, + PL_UNIX_HLINKS_NUMBER + } hlinks; + + enum { + PL_UNIX_USER_PRESPACE = 0, + PL_UNIX_USER_PARSING + } user; + + enum { + PL_UNIX_GROUP_PRESPACE = 0, + PL_UNIX_GROUP_NAME + } group; + + enum { + PL_UNIX_SIZE_PRESPACE = 0, + PL_UNIX_SIZE_NUMBER + } size; + + enum { + PL_UNIX_TIME_PREPART1 = 0, + PL_UNIX_TIME_PART1, + PL_UNIX_TIME_PREPART2, + PL_UNIX_TIME_PART2, + PL_UNIX_TIME_PREPART3, + PL_UNIX_TIME_PART3 + } time; + + enum { + PL_UNIX_FILENAME_PRESPACE = 0, + PL_UNIX_FILENAME_NAME, + PL_UNIX_FILENAME_WINDOWSEOL + } filename; + + enum { + PL_UNIX_SYMLINK_PRESPACE = 0, + PL_UNIX_SYMLINK_NAME, + PL_UNIX_SYMLINK_PRETARGET1, + PL_UNIX_SYMLINK_PRETARGET2, + PL_UNIX_SYMLINK_PRETARGET3, + PL_UNIX_SYMLINK_PRETARGET4, + PL_UNIX_SYMLINK_TARGET, + PL_UNIX_SYMLINK_WINDOWSEOL + } symlink; +} pl_unix_substate; + +typedef enum { + PL_WINNT_DATE = 0, + PL_WINNT_TIME, + PL_WINNT_DIRORSIZE, + PL_WINNT_FILENAME +} pl_winNT_mainstate; + +typedef union { + enum { + PL_WINNT_TIME_PRESPACE = 0, + PL_WINNT_TIME_TIME + } time; + enum { + PL_WINNT_DIRORSIZE_PRESPACE = 0, + PL_WINNT_DIRORSIZE_CONTENT + } dirorsize; + enum { + PL_WINNT_FILENAME_PRESPACE = 0, + PL_WINNT_FILENAME_CONTENT, + PL_WINNT_FILENAME_WINEOL + } filename; +} pl_winNT_substate; + +/* This struct is used in wildcard downloading - for parsing LIST response */ +struct ftp_parselist_data { + enum { + OS_TYPE_UNKNOWN = 0, + OS_TYPE_UNIX, + OS_TYPE_WIN_NT + } os_type; + + union { + struct { + pl_unix_mainstate main; + pl_unix_substate sub; + } UNIX; + + struct { + pl_winNT_mainstate main; + pl_winNT_substate sub; + } NT; + } state; + + CURLcode error; + struct fileinfo *file_data; + unsigned int item_length; + size_t item_offset; + struct { + size_t filename; + size_t user; + size_t group; + size_t time; + size_t perm; + size_t symlink_target; + } offsets; +}; + +struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) +{ + return calloc(1, sizeof(struct ftp_parselist_data)); +} + + +void Curl_ftp_parselist_data_free(struct ftp_parselist_data **parserp) +{ + struct ftp_parselist_data *parser = *parserp; + if(parser) + Curl_fileinfo_cleanup(parser->file_data); + free(parser); + *parserp = NULL; +} + + +CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data) +{ + return pl_data->error; +} + + +#define FTP_LP_MALFORMATED_PERM 0x01000000 + +static int ftp_pl_get_permission(const char *str) +{ + int permissions = 0; + /* USER */ + if(str[0] == 'r') + permissions |= 1 << 8; + else if(str[0] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[1] == 'w') + permissions |= 1 << 7; + else if(str[1] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + + if(str[2] == 'x') + permissions |= 1 << 6; + else if(str[2] == 's') { + permissions |= 1 << 6; + permissions |= 1 << 11; + } + else if(str[2] == 'S') + permissions |= 1 << 11; + else if(str[2] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + /* GROUP */ + if(str[3] == 'r') + permissions |= 1 << 5; + else if(str[3] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[4] == 'w') + permissions |= 1 << 4; + else if(str[4] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[5] == 'x') + permissions |= 1 << 3; + else if(str[5] == 's') { + permissions |= 1 << 3; + permissions |= 1 << 10; + } + else if(str[5] == 'S') + permissions |= 1 << 10; + else if(str[5] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + /* others */ + if(str[6] == 'r') + permissions |= 1 << 2; + else if(str[6] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[7] == 'w') + permissions |= 1 << 1; + else if(str[7] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[8] == 'x') + permissions |= 1; + else if(str[8] == 't') { + permissions |= 1; + permissions |= 1 << 9; + } + else if(str[8] == 'T') + permissions |= 1 << 9; + else if(str[8] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + + return permissions; +} + +static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, + struct fileinfo *infop) +{ + curl_fnmatch_callback compare; + struct WildcardData *wc = &conn->data->wildcard; + struct ftp_wc *ftpwc = wc->protdata; + struct curl_llist *llist = &wc->filelist; + struct ftp_parselist_data *parser = ftpwc->parser; + bool add = TRUE; + struct curl_fileinfo *finfo = &infop->info; + + /* move finfo pointers to b_data */ + char *str = finfo->b_data; + finfo->filename = str + parser->offsets.filename; + finfo->strings.group = parser->offsets.group ? + str + parser->offsets.group : NULL; + finfo->strings.perm = parser->offsets.perm ? + str + parser->offsets.perm : NULL; + finfo->strings.target = parser->offsets.symlink_target ? + str + parser->offsets.symlink_target : NULL; + finfo->strings.time = str + parser->offsets.time; + finfo->strings.user = parser->offsets.user ? + str + parser->offsets.user : NULL; + + /* get correct fnmatch callback */ + compare = conn->data->set.fnmatch; + if(!compare) + compare = Curl_fnmatch; + + /* filter pattern-corresponding filenames */ + Curl_set_in_callback(conn->data, true); + if(compare(conn->data->set.fnmatch_data, wc->pattern, + finfo->filename) == 0) { + /* discard symlink which is containing multiple " -> " */ + if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target && + (strstr(finfo->strings.target, " -> "))) { + add = FALSE; + } + } + else { + add = FALSE; + } + Curl_set_in_callback(conn->data, false); + + if(add) { + Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list); + } + else { + Curl_fileinfo_cleanup(infop); + } + + ftpwc->parser->file_data = NULL; + return CURLE_OK; +} + +size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, + void *connptr) +{ + size_t bufflen = size*nmemb; + struct connectdata *conn = (struct connectdata *)connptr; + struct ftp_wc *ftpwc = conn->data->wildcard.protdata; + struct ftp_parselist_data *parser = ftpwc->parser; + struct fileinfo *infop; + struct curl_fileinfo *finfo; + unsigned long i = 0; + CURLcode result; + size_t retsize = bufflen; + + if(parser->error) { /* error in previous call */ + /* scenario: + * 1. call => OK.. + * 2. call => OUT_OF_MEMORY (or other error) + * 3. (last) call => is skipped RIGHT HERE and the error is hadled later + * in wc_statemach() + */ + goto fail; + } + + if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) { + /* considering info about FILE response format */ + parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ? + OS_TYPE_WIN_NT : OS_TYPE_UNIX; + } + + while(i < bufflen) { /* FSM */ + + char c = buffer[i]; + if(!parser->file_data) { /* tmp file data is not allocated yet */ + parser->file_data = Curl_fileinfo_alloc(); + if(!parser->file_data) { + parser->error = CURLE_OUT_OF_MEMORY; + goto fail; + } + parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE); + if(!parser->file_data->info.b_data) { + parser->error = CURLE_OUT_OF_MEMORY; + goto fail; + } + parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE; + parser->item_offset = 0; + parser->item_length = 0; + } + + infop = parser->file_data; + finfo = &infop->info; + finfo->b_data[finfo->b_used++] = c; + + if(finfo->b_used >= finfo->b_size - 1) { + /* if it is important, extend buffer space for file data */ + char *tmp = realloc(finfo->b_data, + finfo->b_size + FTP_BUFFER_ALLOCSIZE); + if(tmp) { + finfo->b_size += FTP_BUFFER_ALLOCSIZE; + finfo->b_data = tmp; + } + else { + Curl_fileinfo_cleanup(parser->file_data); + parser->file_data = NULL; + parser->error = CURLE_OUT_OF_MEMORY; + goto fail; + } + } + + switch(parser->os_type) { + case OS_TYPE_UNIX: + switch(parser->state.UNIX.main) { + case PL_UNIX_TOTALSIZE: + switch(parser->state.UNIX.sub.total_dirsize) { + case PL_UNIX_TOTALSIZE_INIT: + if(c == 't') { + parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING; + parser->item_length++; + } + else { + parser->state.UNIX.main = PL_UNIX_FILETYPE; + /* start FSM again not considering size of directory */ + finfo->b_used = 0; + continue; + } + break; + case PL_UNIX_TOTALSIZE_READING: + parser->item_length++; + if(c == '\r') { + parser->item_length--; + finfo->b_used--; + } + else if(c == '\n') { + finfo->b_data[parser->item_length - 1] = 0; + if(strncmp("total ", finfo->b_data, 6) == 0) { + char *endptr = finfo->b_data + 6; + /* here we can deal with directory size, pass the leading white + spaces and then the digits */ + while(ISSPACE(*endptr)) + endptr++; + while(ISDIGIT(*endptr)) + endptr++; + if(*endptr != 0) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + finfo->b_used = 0; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + } + break; + case PL_UNIX_FILETYPE: + switch(c) { + case '-': + finfo->filetype = CURLFILETYPE_FILE; + break; + case 'd': + finfo->filetype = CURLFILETYPE_DIRECTORY; + break; + case 'l': + finfo->filetype = CURLFILETYPE_SYMLINK; + break; + case 'p': + finfo->filetype = CURLFILETYPE_NAMEDPIPE; + break; + case 's': + finfo->filetype = CURLFILETYPE_SOCKET; + break; + case 'c': + finfo->filetype = CURLFILETYPE_DEVICE_CHAR; + break; + case 'b': + finfo->filetype = CURLFILETYPE_DEVICE_BLOCK; + break; + case 'D': + finfo->filetype = CURLFILETYPE_DOOR; + break; + default: + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + parser->state.UNIX.main = PL_UNIX_PERMISSION; + parser->item_length = 0; + parser->item_offset = 1; + break; + case PL_UNIX_PERMISSION: + parser->item_length++; + if(parser->item_length <= 9) { + if(!strchr("rwx-tTsS", c)) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + else if(parser->item_length == 10) { + unsigned int perm; + if(c != ' ') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + finfo->b_data[10] = 0; /* terminate permissions */ + perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset); + if(perm & FTP_LP_MALFORMATED_PERM) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM; + parser->file_data->info.perm = perm; + parser->offsets.perm = parser->item_offset; + + parser->item_length = 0; + parser->state.UNIX.main = PL_UNIX_HLINKS; + parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE; + } + break; + case PL_UNIX_HLINKS: + switch(parser->state.UNIX.sub.hlinks) { + case PL_UNIX_HLINKS_PRESPACE: + if(c != ' ') { + if(c >= '0' && c <= '9') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_HLINKS_NUMBER: + parser->item_length ++; + if(c == ' ') { + char *p; + long int hlinks; + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10); + if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) { + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; + parser->file_data->info.hardlinks = hlinks; + } + parser->item_length = 0; + parser->item_offset = 0; + parser->state.UNIX.main = PL_UNIX_USER; + parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE; + } + else if(c < '0' || c > '9') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_UNIX_USER: + switch(parser->state.UNIX.sub.user) { + case PL_UNIX_USER_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING; + } + break; + case PL_UNIX_USER_PARSING: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.user = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_GROUP; + parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE; + parser->item_offset = 0; + parser->item_length = 0; + } + break; + } + break; + case PL_UNIX_GROUP: + switch(parser->state.UNIX.sub.group) { + case PL_UNIX_GROUP_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME; + } + break; + case PL_UNIX_GROUP_NAME: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.group = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_SIZE; + parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE; + parser->item_offset = 0; + parser->item_length = 0; + } + break; + } + break; + case PL_UNIX_SIZE: + switch(parser->state.UNIX.sub.size) { + case PL_UNIX_SIZE_PRESPACE: + if(c != ' ') { + if(c >= '0' && c <= '9') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_SIZE_NUMBER: + parser->item_length++; + if(c == ' ') { + char *p; + curl_off_t fsize; + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + if(!curlx_strtoofft(finfo->b_data + parser->item_offset, + &p, 10, &fsize)) { + if(p[0] == '\0' && fsize != CURL_OFF_T_MAX && + fsize != CURL_OFF_T_MIN) { + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->file_data->info.size = fsize; + } + parser->item_length = 0; + parser->item_offset = 0; + parser->state.UNIX.main = PL_UNIX_TIME; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1; + } + } + else if(!ISDIGIT(c)) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_UNIX_TIME: + switch(parser->state.UNIX.sub.time) { + case PL_UNIX_TIME_PREPART1: + if(c != ' ') { + if(ISALNUM(c)) { + parser->item_offset = finfo->b_used -1; + parser->item_length = 1; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_TIME_PART1: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2; + } + else if(!ISALNUM(c) && c != '.') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_UNIX_TIME_PREPART2: + parser->item_length++; + if(c != ' ') { + if(ISALNUM(c)) { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_TIME_PART2: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3; + } + else if(!ISALNUM(c) && c != '.') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_UNIX_TIME_PREPART3: + parser->item_length++; + if(c != ' ') { + if(ISALNUM(c)) { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + break; + case PL_UNIX_TIME_PART3: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length -1] = 0; + parser->offsets.time = parser->item_offset; + /* + if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) { + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME; + } + */ + if(finfo->filetype == CURLFILETYPE_SYMLINK) { + parser->state.UNIX.main = PL_UNIX_SYMLINK; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE; + } + else { + parser->state.UNIX.main = PL_UNIX_FILENAME; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE; + } + } + else if(!ISALNUM(c) && c != '.' && c != ':') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_UNIX_FILENAME: + switch(parser->state.UNIX.sub.filename) { + case PL_UNIX_FILENAME_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME; + } + break; + case PL_UNIX_FILENAME_NAME: + parser->item_length++; + if(c == '\r') { + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL; + } + else if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.filename = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_FILETYPE; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + } + break; + case PL_UNIX_FILENAME_WINDOWSEOL: + if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.filename = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_FILETYPE; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_UNIX_SYMLINK: + switch(parser->state.UNIX.sub.symlink) { + case PL_UNIX_SYMLINK_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_NAME: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1; + } + else if(c == '\r' || c == '\n') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_UNIX_SYMLINK_PRETARGET1: + parser->item_length++; + if(c == '-') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2; + } + else if(c == '\r' || c == '\n') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET2: + parser->item_length++; + if(c == '>') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3; + } + else if(c == '\r' || c == '\n') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET3: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4; + /* now place where is symlink following */ + finfo->b_data[parser->item_offset + parser->item_length - 4] = 0; + parser->offsets.filename = parser->item_offset; + parser->item_length = 0; + parser->item_offset = 0; + } + else if(c == '\r' || c == '\n') { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET4: + if(c != '\r' && c != '\n') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET; + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_UNIX_SYMLINK_TARGET: + parser->item_length++; + if(c == '\r') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL; + } + else if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.symlink_target = parser->item_offset; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + } + break; + case PL_UNIX_SYMLINK_WINDOWSEOL: + if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.symlink_target = parser->item_offset; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + } + break; + case OS_TYPE_WIN_NT: + switch(parser->state.NT.main) { + case PL_WINNT_DATE: + parser->item_length++; + if(parser->item_length < 9) { + if(!strchr("0123456789-", c)) { /* only simple control */ + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + else if(parser->item_length == 9) { + if(c == ' ') { + parser->state.NT.main = PL_WINNT_TIME; + parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + case PL_WINNT_TIME: + parser->item_length++; + switch(parser->state.NT.sub.time) { + case PL_WINNT_TIME_PRESPACE: + if(!ISSPACE(c)) { + parser->state.NT.sub.time = PL_WINNT_TIME_TIME; + } + break; + case PL_WINNT_TIME_TIME: + if(c == ' ') { + parser->offsets.time = parser->item_offset; + finfo->b_data[parser->item_offset + parser->item_length -1] = 0; + parser->state.NT.main = PL_WINNT_DIRORSIZE; + parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE; + parser->item_length = 0; + } + else if(!strchr("APM0123456789:", c)) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + case PL_WINNT_DIRORSIZE: + switch(parser->state.NT.sub.dirorsize) { + case PL_WINNT_DIRORSIZE_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT; + } + break; + case PL_WINNT_DIRORSIZE_CONTENT: + parser->item_length ++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + if(strcmp("", finfo->b_data + parser->item_offset) == 0) { + finfo->filetype = CURLFILETYPE_DIRECTORY; + finfo->size = 0; + } + else { + char *endptr; + if(curlx_strtoofft(finfo->b_data + + parser->item_offset, + &endptr, 10, &finfo->size)) { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + /* correct file type */ + parser->file_data->info.filetype = CURLFILETYPE_FILE; + } + + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->item_length = 0; + parser->state.NT.main = PL_WINNT_FILENAME; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + break; + } + break; + case PL_WINNT_FILENAME: + switch(parser->state.NT.sub.filename) { + case PL_WINNT_FILENAME_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used -1; + parser->item_length = 1; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT; + } + break; + case PL_WINNT_FILENAME_CONTENT: + parser->item_length++; + if(c == '\r') { + parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL; + finfo->b_data[finfo->b_used - 1] = 0; + } + else if(c == '\n') { + parser->offsets.filename = parser->item_offset; + finfo->b_data[finfo->b_used - 1] = 0; + parser->offsets.filename = parser->item_offset; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + parser->state.NT.main = PL_WINNT_DATE; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + break; + case PL_WINNT_FILENAME_WINEOL: + if(c == '\n') { + parser->offsets.filename = parser->item_offset; + result = ftp_pl_insert_finfo(conn, infop); + if(result) { + parser->error = result; + goto fail; + } + parser->state.NT.main = PL_WINNT_DATE; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + else { + parser->error = CURLE_FTP_BAD_FILE_LIST; + goto fail; + } + break; + } + break; + } + break; + default: + retsize = bufflen + 1; + goto fail; + } + + i++; + } + return retsize; + +fail: + + /* Clean up any allocated memory. */ + if(parser->file_data) { + Curl_fileinfo_cleanup(parser->file_data); + parser->file_data = NULL; + } + + return retsize; +} + +#endif /* CURL_DISABLE_FTP */ diff --git a/libcurl/lib/ftplistparser.h b/libcurl/lib/ftplistparser.h new file mode 100644 index 0000000..8128887 --- /dev/null +++ b/libcurl/lib/ftplistparser.h @@ -0,0 +1,41 @@ +#ifndef HEADER_CURL_FTPLISTPARSER_H +#define HEADER_CURL_FTPLISTPARSER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +/* WRITEFUNCTION callback for parsing LIST responses */ +size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, + void *connptr); + +struct ftp_parselist_data; /* defined inside ftplibparser.c */ + +CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data); + +struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void); + +void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data); + +#endif /* CURL_DISABLE_FTP */ +#endif /* HEADER_CURL_FTPLISTPARSER_H */ diff --git a/libcurl/lib/getenv.c b/libcurl/lib/getenv.c new file mode 100644 index 0000000..25e0ea3 --- /dev/null +++ b/libcurl/lib/getenv.c @@ -0,0 +1,54 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "curl_memory.h" + +#include "memdebug.h" + +static +char *GetEnv(const char *variable) +{ +#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)|| defined(_XBOX) + (void)variable; + return NULL; +#else +#ifdef WIN32 + char env[MAX_PATH]; /* MAX_PATH is from windef.h */ + char *temp = getenv(variable); + env[0] = '\0'; + if(temp != NULL) + ExpandEnvironmentStringsA(temp, env, sizeof(env)); + return (env[0] != '\0')?strdup(env):NULL; +#else + char *env = getenv(variable); + return (env && env[0])?strdup(env):NULL; +#endif +#endif +} + +char *curl_getenv(const char *v) +{ + return GetEnv(v); +} diff --git a/libcurl/lib/getinfo.c b/libcurl/lib/getinfo.c new file mode 100644 index 0000000..e118da8 --- /dev/null +++ b/libcurl/lib/getinfo.c @@ -0,0 +1,490 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "getinfo.h" + +#include "vtls/vtls.h" +#include "connect.h" /* Curl_getconnectinfo() */ +#include "progress.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Initialize statistical and informational data. + * + * This function is called in curl_easy_reset, curl_easy_duphandle and at the + * beginning of a perform session. It must reset the session-info variables, + * in particular all variables in struct PureInfo. + */ +CURLcode Curl_initinfo(struct Curl_easy *data) +{ + struct Progress *pro = &data->progress; + struct PureInfo *info = &data->info; + + pro->t_nslookup = 0; + pro->t_connect = 0; + pro->t_appconnect = 0; + pro->t_pretransfer = 0; + pro->t_starttransfer = 0; + pro->timespent = 0; + pro->t_redirect = 0; + pro->is_t_startransfer_set = false; + + info->httpcode = 0; + info->httpproxycode = 0; + info->httpversion = 0; + info->filetime = -1; /* -1 is an illegal time and thus means unknown */ + info->timecond = FALSE; + + info->header_size = 0; + info->request_size = 0; + info->proxyauthavail = 0; + info->httpauthavail = 0; + info->numconnects = 0; + + free(info->contenttype); + info->contenttype = NULL; + + free(info->wouldredirect); + info->wouldredirect = NULL; + + info->conn_primary_ip[0] = '\0'; + info->conn_local_ip[0] = '\0'; + info->conn_primary_port = 0; + info->conn_local_port = 0; + + info->conn_scheme = 0; + info->conn_protocol = 0; + +#ifdef USE_SSL + Curl_ssl_free_certinfo(data); +#endif + return CURLE_OK; +} + +static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, + const char **param_charp) +{ + switch(info) { + case CURLINFO_EFFECTIVE_URL: + *param_charp = data->change.url?data->change.url:(char *)""; + break; + case CURLINFO_CONTENT_TYPE: + *param_charp = data->info.contenttype; + break; + case CURLINFO_PRIVATE: + *param_charp = (char *) data->set.private_data; + break; + case CURLINFO_FTP_ENTRY_PATH: + /* Return the entrypath string from the most recent connection. + This pointer was copied from the connectdata structure by FTP. + The actual string may be free()ed by subsequent libcurl calls so + it must be copied to a safer area before the next libcurl call. + Callers must never free it themselves. */ + *param_charp = data->state.most_recent_ftp_entrypath; + break; + case CURLINFO_REDIRECT_URL: + /* Return the URL this request would have been redirected to if that + option had been enabled! */ + *param_charp = data->info.wouldredirect; + break; + case CURLINFO_PRIMARY_IP: + /* Return the ip address of the most recent (primary) connection */ + *param_charp = data->info.conn_primary_ip; + break; + case CURLINFO_LOCAL_IP: + /* Return the source/local ip address of the most recent (primary) + connection */ + *param_charp = data->info.conn_local_ip; + break; + case CURLINFO_RTSP_SESSION_ID: + *param_charp = data->set.str[STRING_RTSP_SESSION_ID]; + break; + case CURLINFO_SCHEME: + *param_charp = data->info.conn_scheme; + break; + + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, + long *param_longp) +{ + curl_socket_t sockfd; + + union { + unsigned long *to_ulong; + long *to_long; + } lptr; + + switch(info) { + case CURLINFO_RESPONSE_CODE: + *param_longp = data->info.httpcode; + break; + case CURLINFO_HTTP_CONNECTCODE: + *param_longp = data->info.httpproxycode; + break; + case CURLINFO_FILETIME: + if(data->info.filetime > LONG_MAX) + *param_longp = LONG_MAX; + else if(data->info.filetime < LONG_MIN) + *param_longp = LONG_MIN; + else + *param_longp = (long)data->info.filetime; + break; + case CURLINFO_HEADER_SIZE: + *param_longp = (long)data->info.header_size; + break; + case CURLINFO_REQUEST_SIZE: + *param_longp = (long)data->info.request_size; + break; + case CURLINFO_SSL_VERIFYRESULT: + *param_longp = data->set.ssl.certverifyresult; + break; + case CURLINFO_PROXY_SSL_VERIFYRESULT: + *param_longp = data->set.proxy_ssl.certverifyresult; + break; + case CURLINFO_REDIRECT_COUNT: + *param_longp = data->set.followlocation; + break; + case CURLINFO_HTTPAUTH_AVAIL: + lptr.to_long = param_longp; + *lptr.to_ulong = data->info.httpauthavail; + break; + case CURLINFO_PROXYAUTH_AVAIL: + lptr.to_long = param_longp; + *lptr.to_ulong = data->info.proxyauthavail; + break; + case CURLINFO_OS_ERRNO: + *param_longp = data->state.os_errno; + break; + case CURLINFO_NUM_CONNECTS: + *param_longp = data->info.numconnects; + break; + case CURLINFO_LASTSOCKET: + sockfd = Curl_getconnectinfo(data, NULL); + + /* note: this is not a good conversion for systems with 64 bit sockets and + 32 bit longs */ + if(sockfd != CURL_SOCKET_BAD) + *param_longp = (long)sockfd; + else + /* this interface is documented to return -1 in case of badness, which + may not be the same as the CURL_SOCKET_BAD value */ + *param_longp = -1; + break; + case CURLINFO_PRIMARY_PORT: + /* Return the (remote) port of the most recent (primary) connection */ + *param_longp = data->info.conn_primary_port; + break; + case CURLINFO_LOCAL_PORT: + /* Return the local port of the most recent (primary) connection */ + *param_longp = data->info.conn_local_port; + break; + case CURLINFO_CONDITION_UNMET: + /* return if the condition prevented the document to get transferred */ + *param_longp = data->info.timecond ? 1L : 0L; + break; + case CURLINFO_RTSP_CLIENT_CSEQ: + *param_longp = data->state.rtsp_next_client_CSeq; + break; + case CURLINFO_RTSP_SERVER_CSEQ: + *param_longp = data->state.rtsp_next_server_CSeq; + break; + case CURLINFO_RTSP_CSEQ_RECV: + *param_longp = data->state.rtsp_CSeq_recv; + break; + case CURLINFO_HTTP_VERSION: + switch(data->info.httpversion) { + case 10: + *param_longp = CURL_HTTP_VERSION_1_0; + break; + case 11: + *param_longp = CURL_HTTP_VERSION_1_1; + break; + case 20: + *param_longp = CURL_HTTP_VERSION_2_0; + break; + default: + *param_longp = CURL_HTTP_VERSION_NONE; + break; + } + break; + case CURLINFO_PROTOCOL: + *param_longp = data->info.conn_protocol; + break; + + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +#define DOUBLE_SECS(x) (double)(x)/1000000 + +static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info, + curl_off_t *param_offt) +{ + switch(info) { + case CURLINFO_FILETIME_T: + *param_offt = (curl_off_t)data->info.filetime; + break; + case CURLINFO_SIZE_UPLOAD_T: + *param_offt = data->progress.uploaded; + break; + case CURLINFO_SIZE_DOWNLOAD_T: + *param_offt = data->progress.downloaded; + break; + case CURLINFO_SPEED_DOWNLOAD_T: + *param_offt = data->progress.dlspeed; + break; + case CURLINFO_SPEED_UPLOAD_T: + *param_offt = data->progress.ulspeed; + break; + case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T: + *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)? + data->progress.size_dl:-1; + break; + case CURLINFO_CONTENT_LENGTH_UPLOAD_T: + *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)? + data->progress.size_ul:-1; + break; + case CURLINFO_TOTAL_TIME_T: + *param_offt = data->progress.timespent; + break; + case CURLINFO_NAMELOOKUP_TIME_T: + *param_offt = data->progress.t_nslookup; + break; + case CURLINFO_CONNECT_TIME_T: + *param_offt = data->progress.t_connect; + break; + case CURLINFO_APPCONNECT_TIME_T: + *param_offt = data->progress.t_appconnect; + break; + case CURLINFO_PRETRANSFER_TIME_T: + *param_offt = data->progress.t_pretransfer; + break; + case CURLINFO_STARTTRANSFER_TIME_T: + *param_offt = data->progress.t_starttransfer; + break; + case CURLINFO_REDIRECT_TIME_T: + *param_offt = data->progress.t_redirect; + break; + + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info, + double *param_doublep) +{ + switch(info) { + case CURLINFO_TOTAL_TIME: + *param_doublep = DOUBLE_SECS(data->progress.timespent); + break; + case CURLINFO_NAMELOOKUP_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_nslookup); + break; + case CURLINFO_CONNECT_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_connect); + break; + case CURLINFO_APPCONNECT_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_appconnect); + break; + case CURLINFO_PRETRANSFER_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_pretransfer); + break; + case CURLINFO_STARTTRANSFER_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer); + break; + case CURLINFO_SIZE_UPLOAD: + *param_doublep = (double)data->progress.uploaded; + break; + case CURLINFO_SIZE_DOWNLOAD: + *param_doublep = (double)data->progress.downloaded; + break; + case CURLINFO_SPEED_DOWNLOAD: + *param_doublep = (double)data->progress.dlspeed; + break; + case CURLINFO_SPEED_UPLOAD: + *param_doublep = (double)data->progress.ulspeed; + break; + case CURLINFO_CONTENT_LENGTH_DOWNLOAD: + *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)? + (double)data->progress.size_dl:-1; + break; + case CURLINFO_CONTENT_LENGTH_UPLOAD: + *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)? + (double)data->progress.size_ul:-1; + break; + case CURLINFO_REDIRECT_TIME: + *param_doublep = DOUBLE_SECS(data->progress.t_redirect); + break; + + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info, + struct curl_slist **param_slistp) +{ + union { + struct curl_certinfo *to_certinfo; + struct curl_slist *to_slist; + } ptr; + + switch(info) { + case CURLINFO_SSL_ENGINES: + *param_slistp = Curl_ssl_engines_list(data); + break; + case CURLINFO_COOKIELIST: + *param_slistp = Curl_cookie_list(data); + break; + case CURLINFO_CERTINFO: + /* Return the a pointer to the certinfo struct. Not really an slist + pointer but we can pretend it is here */ + ptr.to_certinfo = &data->info.certs; + *param_slistp = ptr.to_slist; + break; + case CURLINFO_TLS_SESSION: + case CURLINFO_TLS_SSL_PTR: + { + struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **) + param_slistp; + struct curl_tlssessioninfo *tsi = &data->tsi; +#ifdef USE_SSL + struct connectdata *conn = data->conn; +#endif + + *tsip = tsi; + tsi->backend = Curl_ssl_backend(); + tsi->internals = NULL; + +#ifdef USE_SSL + if(conn && tsi->backend != CURLSSLBACKEND_NONE) { + unsigned int i; + for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) { + if(conn->ssl[i].use) { + tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info); + break; + } + } + } +#endif + } + break; + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info, + curl_socket_t *param_socketp) +{ + switch(info) { + case CURLINFO_ACTIVESOCKET: + *param_socketp = Curl_getconnectinfo(data, NULL); + break; + default: + return CURLE_UNKNOWN_OPTION; + } + + return CURLE_OK; +} + +CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...) +{ + va_list arg; + long *param_longp = NULL; + double *param_doublep = NULL; + curl_off_t *param_offt = NULL; + const char **param_charp = NULL; + struct curl_slist **param_slistp = NULL; + curl_socket_t *param_socketp = NULL; + int type; + CURLcode result = CURLE_UNKNOWN_OPTION; + + if(!data) + return result; + + va_start(arg, info); + + type = CURLINFO_TYPEMASK & (int)info; + switch(type) { + case CURLINFO_STRING: + param_charp = va_arg(arg, const char **); + if(param_charp) + result = getinfo_char(data, info, param_charp); + break; + case CURLINFO_LONG: + param_longp = va_arg(arg, long *); + if(param_longp) + result = getinfo_long(data, info, param_longp); + break; + case CURLINFO_DOUBLE: + param_doublep = va_arg(arg, double *); + if(param_doublep) + result = getinfo_double(data, info, param_doublep); + break; + case CURLINFO_OFF_T: + param_offt = va_arg(arg, curl_off_t *); + if(param_offt) + result = getinfo_offt(data, info, param_offt); + break; + case CURLINFO_SLIST: + param_slistp = va_arg(arg, struct curl_slist **); + if(param_slistp) + result = getinfo_slist(data, info, param_slistp); + break; + case CURLINFO_SOCKET: + param_socketp = va_arg(arg, curl_socket_t *); + if(param_socketp) + result = getinfo_socket(data, info, param_socketp); + break; + default: + break; + } + + va_end(arg); + + return result; +} diff --git a/libcurl/lib/getinfo.h b/libcurl/lib/getinfo.h new file mode 100644 index 0000000..aecf717 --- /dev/null +++ b/libcurl/lib/getinfo.h @@ -0,0 +1,27 @@ +#ifndef HEADER_CURL_GETINFO_H +#define HEADER_CURL_GETINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...); +CURLcode Curl_initinfo(struct Curl_easy *data); + +#endif /* HEADER_CURL_GETINFO_H */ diff --git a/libcurl/lib/gopher.c b/libcurl/lib/gopher.c new file mode 100644 index 0000000..b296c62 --- /dev/null +++ b/libcurl/lib/gopher.c @@ -0,0 +1,174 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_GOPHER + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "progress.h" +#include "gopher.h" +#include "select.h" +#include "strdup.h" +#include "url.h" +#include "escape.h" +#include "warnless.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static CURLcode gopher_do(struct connectdata *conn, bool *done); + +/* + * Gopher protocol handler. + * This is also a nice simple template to build off for simple + * connect-command-download protocols. + */ + +const struct Curl_handler Curl_handler_gopher = { + "GOPHER", /* scheme */ + ZERO_NULL, /* setup_connection */ + gopher_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_GOPHER, /* defport */ + CURLPROTO_GOPHER, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +static CURLcode gopher_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + char *gopherpath; + char *path = data->state.up.path; + char *query = data->state.up.query; + char *sel = NULL; + char *sel_org = NULL; + ssize_t amount, k; + size_t len; + + *done = TRUE; /* unconditionally */ + + /* path is guaranteed non-NULL */ + DEBUGASSERT(path); + + if(query) + gopherpath = aprintf("%s?%s", path, query); + else + gopherpath = strdup(path); + + if(!gopherpath) + return CURLE_OUT_OF_MEMORY; + + /* Create selector. Degenerate cases: / and /1 => convert to "" */ + if(strlen(gopherpath) <= 2) { + sel = (char *)""; + len = strlen(sel); + free(gopherpath); + } + else { + char *newp; + + /* Otherwise, drop / and the first character (i.e., item type) ... */ + newp = gopherpath; + newp += 2; + + /* ... and finally unescape */ + result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE); + free(gopherpath); + if(result) + return result; + sel_org = sel; + } + + /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is + sent, which could be sizeable with long selectors. */ + k = curlx_uztosz(len); + + for(;;) { + result = Curl_write(conn, sockfd, sel, k, &amount); + if(!result) { /* Which may not have written it all! */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount); + if(result) + break; + + k -= amount; + sel += amount; + if(k < 1) + break; /* but it did write it all */ + } + else + break; + + /* Don't busyloop. The entire loop thing is a work-around as it causes a + BLOCKING behavior which is a NO-NO. This function should rather be + split up in a do and a doing piece where the pieces that aren't + possible to send now will be sent in the doing function repeatedly + until the entire request is sent. + + Wait a while for the socket to be writable. Note that this doesn't + acknowledge the timeout. + */ + if(SOCKET_WRITABLE(sockfd, 100) < 0) { + result = CURLE_SEND_ERROR; + break; + } + } + + free(sel_org); + + if(!result) + /* We can use Curl_sendf to send the terminal \r\n relatively safely and + save allocing another string/doing another _write loop. */ + result = Curl_sendf(sockfd, conn, "\r\n"); + if(result) { + failf(data, "Failed sending Gopher request"); + return result; + } + result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2); + if(result) + return result; + + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + return CURLE_OK; +} +#endif /*CURL_DISABLE_GOPHER*/ diff --git a/libcurl/lib/gopher.h b/libcurl/lib/gopher.h new file mode 100644 index 0000000..501c990 --- /dev/null +++ b/libcurl/lib/gopher.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_GOPHER_H +#define HEADER_CURL_GOPHER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_GOPHER +extern const struct Curl_handler Curl_handler_gopher; +#endif + +#endif /* HEADER_CURL_GOPHER_H */ diff --git a/libcurl/lib/hash.c b/libcurl/lib/hash.c new file mode 100644 index 0000000..421d68f --- /dev/null +++ b/libcurl/lib/hash.c @@ -0,0 +1,351 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "hash.h" +#include "llist.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +static void +hash_element_dtor(void *user, void *element) +{ + struct curl_hash *h = (struct curl_hash *) user; + struct curl_hash_element *e = (struct curl_hash_element *) element; + + if(e->ptr) { + h->dtor(e->ptr); + e->ptr = NULL; + } + + e->key_len = 0; + + free(e); +} + +/* Initializes a hash structure. + * Return 1 on error, 0 is fine. + * + * @unittest: 1602 + * @unittest: 1603 + */ +int +Curl_hash_init(struct curl_hash *h, + int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor) +{ + if(!slots || !hfunc || !comparator ||!dtor) { + return 1; /* failure */ + } + + h->hash_func = hfunc; + h->comp_func = comparator; + h->dtor = dtor; + h->size = 0; + h->slots = slots; + + h->table = malloc(slots * sizeof(struct curl_llist)); + if(h->table) { + int i; + for(i = 0; i < slots; ++i) + Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor); + return 0; /* fine */ + } + h->slots = 0; + return 1; /* failure */ +} + +static struct curl_hash_element * +mk_hash_element(const void *key, size_t key_len, const void *p) +{ + /* allocate the struct plus memory after it to store the key */ + struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element) + + key_len); + if(he) { + /* copy the key */ + memcpy(he->key, key, key_len); + he->key_len = key_len; + he->ptr = (void *) p; + } + return he; +} + +#define FETCH_LIST(x,y,z) &x->table[x->hash_func(y, z, x->slots)] + +/* Insert the data in the hash. If there already was a match in the hash, + * that data is replaced. + * + * @unittest: 1305 + * @unittest: 1602 + * @unittest: 1603 + */ +void * +Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p) +{ + struct curl_hash_element *he; + struct curl_llist_element *le; + struct curl_llist *l = FETCH_LIST(h, key, key_len); + + for(le = l->head; le; le = le->next) { + he = (struct curl_hash_element *) le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + Curl_llist_remove(l, le, (void *)h); + --h->size; + break; + } + } + + he = mk_hash_element(key, key_len, p); + if(he) { + Curl_llist_insert_next(l, l->tail, he, &he->list); + ++h->size; + return p; /* return the new entry */ + } + + return NULL; /* failure */ +} + +/* Remove the identified hash entry. + * Returns non-zero on failure. + * + * @unittest: 1603 + */ +int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len) +{ + struct curl_llist_element *le; + struct curl_llist *l = FETCH_LIST(h, key, key_len); + + for(le = l->head; le; le = le->next) { + struct curl_hash_element *he = le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + Curl_llist_remove(l, le, (void *) h); + --h->size; + return 0; + } + } + return 1; +} + +/* Retrieves a hash element. + * + * @unittest: 1603 + */ +void * +Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len) +{ + struct curl_llist_element *le; + struct curl_llist *l; + + if(h) { + l = FETCH_LIST(h, key, key_len); + for(le = l->head; le; le = le->next) { + struct curl_hash_element *he = le->ptr; + if(h->comp_func(he->key, he->key_len, key, key_len)) { + return he->ptr; + } + } + } + + return NULL; +} + +#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST) +void +Curl_hash_apply(curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)) +{ + struct curl_llist_element *le; + int i; + + for(i = 0; i < h->slots; ++i) { + for(le = (h->table[i])->head; + le; + le = le->next) { + curl_hash_element *el = le->ptr; + cb(user, el->ptr); + } + } +} +#endif + +/* Destroys all the entries in the given hash and resets its attributes, + * prepping the given hash for [static|dynamic] deallocation. + * + * @unittest: 1305 + * @unittest: 1602 + * @unittest: 1603 + */ +void +Curl_hash_destroy(struct curl_hash *h) +{ + int i; + + for(i = 0; i < h->slots; ++i) { + Curl_llist_destroy(&h->table[i], (void *) h); + } + + Curl_safefree(h->table); + h->size = 0; + h->slots = 0; +} + +/* Removes all the entries in the given hash. + * + * @unittest: 1602 + */ +void +Curl_hash_clean(struct curl_hash *h) +{ + Curl_hash_clean_with_criterium(h, NULL, NULL); +} + +/* Cleans all entries that pass the comp function criteria. */ +void +Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, + int (*comp)(void *, void *)) +{ + struct curl_llist_element *le; + struct curl_llist_element *lnext; + struct curl_llist *list; + int i; + + if(!h) + return; + + for(i = 0; i < h->slots; ++i) { + list = &h->table[i]; + le = list->head; /* get first list entry */ + while(le) { + struct curl_hash_element *he = le->ptr; + lnext = le->next; + /* ask the callback function if we shall remove this entry or not */ + if(comp == NULL || comp(user, he->ptr)) { + Curl_llist_remove(list, le, (void *) h); + --h->size; /* one less entry in the hash now */ + } + le = lnext; + } + } +} + +size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num) +{ + const char *key_str = (const char *) key; + const char *end = key_str + key_length; + size_t h = 5381; + + while(key_str < end) { + h += h << 5; + h ^= *key_str++; + } + + return (h % slots_num); +} + +size_t Curl_str_key_compare(void *k1, size_t key1_len, + void *k2, size_t key2_len) +{ + if((key1_len == key2_len) && !memcmp(k1, k2, key1_len)) + return 1; + + return 0; +} + +void Curl_hash_start_iterate(struct curl_hash *hash, + struct curl_hash_iterator *iter) +{ + iter->hash = hash; + iter->slot_index = 0; + iter->current_element = NULL; +} + +struct curl_hash_element * +Curl_hash_next_element(struct curl_hash_iterator *iter) +{ + struct curl_hash *h = iter->hash; + + /* Get the next element in the current list, if any */ + if(iter->current_element) + iter->current_element = iter->current_element->next; + + /* If we have reached the end of the list, find the next one */ + if(!iter->current_element) { + int i; + for(i = iter->slot_index; i < h->slots; i++) { + if(h->table[i].head) { + iter->current_element = h->table[i].head; + iter->slot_index = i + 1; + break; + } + } + } + + if(iter->current_element) { + struct curl_hash_element *he = iter->current_element->ptr; + return he; + } + iter->current_element = NULL; + return NULL; +} + +#if 0 /* useful function for debugging hashes and their contents */ +void Curl_hash_print(struct curl_hash *h, + void (*func)(void *)) +{ + struct curl_hash_iterator iter; + struct curl_hash_element *he; + int last_index = -1; + + if(!h) + return; + + fprintf(stderr, "=Hash dump=\n"); + + Curl_hash_start_iterate(h, &iter); + + he = Curl_hash_next_element(&iter); + while(he) { + if(iter.slot_index != last_index) { + fprintf(stderr, "index %d:", iter.slot_index); + if(last_index >= 0) { + fprintf(stderr, "\n"); + } + last_index = iter.slot_index; + } + + if(func) + func(he->ptr); + else + fprintf(stderr, " [%p]", (void *)he->ptr); + + he = Curl_hash_next_element(&iter); + } + fprintf(stderr, "\n"); +} +#endif diff --git a/libcurl/lib/hash.h b/libcurl/lib/hash.h new file mode 100644 index 0000000..558d0f4 --- /dev/null +++ b/libcurl/lib/hash.h @@ -0,0 +1,100 @@ +#ifndef HEADER_CURL_HASH_H +#define HEADER_CURL_HASH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "llist.h" + +/* Hash function prototype */ +typedef size_t (*hash_function) (void *key, + size_t key_length, + size_t slots_num); + +/* + Comparator function prototype. Compares two keys. +*/ +typedef size_t (*comp_function) (void *key1, + size_t key1_len, + void *key2, + size_t key2_len); + +typedef void (*curl_hash_dtor)(void *); + +struct curl_hash { + struct curl_llist *table; + + /* Hash function to be used for this hash table */ + hash_function hash_func; + + /* Comparator function to compare keys */ + comp_function comp_func; + curl_hash_dtor dtor; + int slots; + size_t size; +}; + +struct curl_hash_element { + struct curl_llist_element list; + void *ptr; + size_t key_len; + char key[1]; /* allocated memory following the struct */ +}; + +struct curl_hash_iterator { + struct curl_hash *hash; + int slot_index; + struct curl_llist_element *current_element; +}; + +int Curl_hash_init(struct curl_hash *h, + int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor); + +void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p); +int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len); +void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len); +void Curl_hash_apply(struct curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)); +#define Curl_hash_count(h) ((h)->size) +void Curl_hash_destroy(struct curl_hash *h); +void Curl_hash_clean(struct curl_hash *h); +void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, + int (*comp)(void *, void *)); +size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num); +size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2, + size_t key2_len); +void Curl_hash_start_iterate(struct curl_hash *hash, + struct curl_hash_iterator *iter); +struct curl_hash_element * +Curl_hash_next_element(struct curl_hash_iterator *iter); + +void Curl_hash_print(struct curl_hash *h, + void (*func)(void *)); + + +#endif /* HEADER_CURL_HASH_H */ diff --git a/libcurl/lib/hmac.c b/libcurl/lib/hmac.c new file mode 100644 index 0000000..bf49ebe --- /dev/null +++ b/libcurl/lib/hmac.c @@ -0,0 +1,132 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2104 Keyed-Hashing for Message Authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +#include + +#include "curl_hmac.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Generic HMAC algorithm. + * + * This module computes HMAC digests based on any hash function. Parameters + * and computing procedures are set-up dynamically at HMAC computation + * context initialisation. + */ + +static const unsigned char hmac_ipad = 0x36; +static const unsigned char hmac_opad = 0x5C; + + + +HMAC_context * +Curl_HMAC_init(const HMAC_params * hashparams, + const unsigned char *key, + unsigned int keylen) +{ + size_t i; + HMAC_context *ctxt; + unsigned char *hkey; + unsigned char b; + + /* Create HMAC context. */ + i = sizeof(*ctxt) + 2 * hashparams->hmac_ctxtsize + + hashparams->hmac_resultlen; + ctxt = malloc(i); + + if(!ctxt) + return ctxt; + + ctxt->hmac_hash = hashparams; + ctxt->hmac_hashctxt1 = (void *) (ctxt + 1); + ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 + + hashparams->hmac_ctxtsize); + + /* If the key is too long, replace it by its hash digest. */ + if(keylen > hashparams->hmac_maxkeylen) { + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen); + hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize; + (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1); + key = hkey; + keylen = hashparams->hmac_resultlen; + } + + /* Prime the two hash contexts with the modified key. */ + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); + (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2); + + for(i = 0; i < keylen; i++) { + b = (unsigned char)(*key ^ hmac_ipad); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1); + b = (unsigned char)(*key++ ^ hmac_opad); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1); + } + + for(; i < hashparams->hmac_maxkeylen; i++) { + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1); + } + + /* Done, return pointer to HMAC context. */ + return ctxt; +} + +int Curl_HMAC_update(HMAC_context * ctxt, + const unsigned char *data, + unsigned int len) +{ + /* Update first hash calculation. */ + (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len); + return 0; +} + + +int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result) +{ + const HMAC_params * hashparams = ctxt->hmac_hash; + + /* Do not get result if called with a null parameter: only release + storage. */ + + if(!result) + result = (unsigned char *) ctxt->hmac_hashctxt2 + + ctxt->hmac_hash->hmac_ctxtsize; + + (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1); + (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, + result, hashparams->hmac_resultlen); + (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2); + free((char *) ctxt); + return 0; +} + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libcurl/lib/hostasyn.c b/libcurl/lib/hostasyn.c new file mode 100644 index 0000000..99d872b --- /dev/null +++ b/libcurl/lib/hostasyn.c @@ -0,0 +1,128 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for builds using asynchronous name resolves + **********************************************************************/ +#ifdef CURLRES_ASYNCH + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread() + * or getaddrinfo_thread() when we got the name resolved (or not!). + * + * If the status argument is CURL_ASYNC_SUCCESS, this function takes + * ownership of the Curl_addrinfo passed, storing the resolved data + * in the DNS cache. + * + * The storage operation locks and unlocks the DNS cache. + */ +CURLcode Curl_addrinfo_callback(struct connectdata *conn, + int status, + struct Curl_addrinfo *ai) +{ + struct Curl_dns_entry *dns = NULL; + CURLcode result = CURLE_OK; + + conn->async.status = status; + + if(CURL_ASYNC_SUCCESS == status) { + if(ai) { + struct Curl_easy *data = conn->data; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = Curl_cache_addr(data, ai, + conn->async.hostname, + conn->async.port); + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) { + /* failed to store, cleanup and return error */ + Curl_freeaddrinfo(ai); + result = CURLE_OUT_OF_MEMORY; + } + } + else { + result = CURLE_OUT_OF_MEMORY; + } + } + + conn->async.dns = dns; + + /* Set async.done TRUE last in this function since it may be used multi- + threaded and once this is TRUE the other thread may read fields from the + async struct */ + conn->async.done = TRUE; + + /* IPv4: The input hostent struct will be freed by ares when we return from + this function */ + return result; +} + +/* + * Curl_getaddrinfo() is the generic low-level name resolve API within this + * source file. There are several versions of this function - for different + * name resolve layers (selected at build-time). They all take this same set + * of arguments + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + return Curl_resolver_getaddrinfo(conn, hostname, port, waitp); +} + +#endif /* CURLRES_ASYNCH */ diff --git a/libcurl/lib/hostcheck.c b/libcurl/lib/hostcheck.c new file mode 100644 index 0000000..115d24b --- /dev/null +++ b/libcurl/lib/hostcheck.c @@ -0,0 +1,150 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_OPENSSL) \ + || defined(USE_GSKIT) \ + || defined(USE_SCHANNEL) +/* these backends use functions from this file */ + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif + +#include "hostcheck.h" +#include "strcase.h" +#include "inet_pton.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Match a hostname against a wildcard pattern. + * E.g. + * "foo.host.com" matches "*.host.com". + * + * We use the matching rule described in RFC6125, section 6.4.3. + * https://tools.ietf.org/html/rfc6125#section-6.4.3 + * + * In addition: ignore trailing dots in the host names and wildcards, so that + * the names are used normalized. This is what the browsers do. + * + * Do not allow wildcard matching on IP numbers. There are apparently + * certificates being used with an IP address in the CN field, thus making no + * apparent distinction between a name and an IP. We need to detect the use of + * an IP address and not wildcard match on such names. + * + * NOTE: hostmatch() gets called with copied buffers so that it can modify the + * contents at will. + */ + +static int hostmatch(char *hostname, char *pattern) +{ + const char *pattern_label_end, *pattern_wildcard, *hostname_label_end; + int wildcard_enabled; + size_t prefixlen, suffixlen; + struct in_addr ignored; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 si6; +#endif + + /* normalize pattern and hostname by stripping off trailing dots */ + size_t len = strlen(hostname); + if(hostname[len-1]=='.') + hostname[len-1] = 0; + len = strlen(pattern); + if(pattern[len-1]=='.') + pattern[len-1] = 0; + + pattern_wildcard = strchr(pattern, '*'); + if(pattern_wildcard == NULL) + return strcasecompare(pattern, hostname) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; + + /* detect IP address as hostname and fail the match if so */ + if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0) + return CURL_HOST_NOMATCH; +#ifdef ENABLE_IPV6 + if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0) + return CURL_HOST_NOMATCH; +#endif + + /* We require at least 2 dots in pattern to avoid too wide wildcard + match. */ + wildcard_enabled = 1; + pattern_label_end = strchr(pattern, '.'); + if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL || + pattern_wildcard > pattern_label_end || + strncasecompare(pattern, "xn--", 4)) { + wildcard_enabled = 0; + } + if(!wildcard_enabled) + return strcasecompare(pattern, hostname) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; + + hostname_label_end = strchr(hostname, '.'); + if(hostname_label_end == NULL || + !strcasecompare(pattern_label_end, hostname_label_end)) + return CURL_HOST_NOMATCH; + + /* The wildcard must match at least one character, so the left-most + label of the hostname is at least as large as the left-most label + of the pattern. */ + if(hostname_label_end - hostname < pattern_label_end - pattern) + return CURL_HOST_NOMATCH; + + prefixlen = pattern_wildcard - pattern; + suffixlen = pattern_label_end - (pattern_wildcard + 1); + return strncasecompare(pattern, hostname, prefixlen) && + strncasecompare(pattern_wildcard + 1, hostname_label_end - suffixlen, + suffixlen) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; +} + +int Curl_cert_hostcheck(const char *match_pattern, const char *hostname) +{ + int res = 0; + if(!match_pattern || !*match_pattern || + !hostname || !*hostname) /* sanity check */ + ; + else { + char *matchp = strdup(match_pattern); + if(matchp) { + char *hostp = strdup(hostname); + if(hostp) { + if(hostmatch(hostp, matchp) == CURL_HOST_MATCH) + res = 1; + free(hostp); + } + free(matchp); + } + } + + return res; +} + +#endif /* OPENSSL, GSKIT or schannel+wince */ diff --git a/libcurl/lib/hostcheck.h b/libcurl/lib/hostcheck.h new file mode 100644 index 0000000..f562df9 --- /dev/null +++ b/libcurl/lib/hostcheck.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_HOSTCHECK_H +#define HEADER_CURL_HOSTCHECK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#define CURL_HOST_NOMATCH 0 +#define CURL_HOST_MATCH 1 +int Curl_cert_hostcheck(const char *match_pattern, const char *hostname); + +#endif /* HEADER_CURL_HOSTCHECK_H */ diff --git a/libcurl/lib/hostip.c b/libcurl/lib/hostip.c new file mode 100644 index 0000000..609d809 --- /dev/null +++ b/libcurl/lib/hostip.c @@ -0,0 +1,1071 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_SETJMP_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "rand.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_ntop.h" +#include "multiif.h" +#include "doh.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if defined(CURLRES_SYNCH) && \ + defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP) +/* alarm-based timeouts can only be used with all the dependencies satisfied */ +#define USE_ALARM_TIMEOUT +#endif + +#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */ + +/* + * hostip.c explained + * ================== + * + * The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c + * source file are these: + * + * CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use + * that. The host may not be able to resolve IPv6, but we don't really have to + * take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4 + * defined. + * + * CURLRES_ARES - is defined if libcurl is built to use c-ares for + * asynchronous name resolves. This can be Windows or *nix. + * + * CURLRES_THREADED - is defined if libcurl is built to run under (native) + * Windows, and then the name resolve will be done in a new thread, and the + * supported API will be the same as for ares-builds. + * + * If any of the two previous are defined, CURLRES_ASYNCH is defined too. If + * libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is + * defined. + * + * The host*.c sources files are split up like this: + * + * hostip.c - method-independent resolver functions and utility functions + * hostasyn.c - functions for asynchronous name resolves + * hostsyn.c - functions for synchronous name resolves + * hostip4.c - IPv4 specific functions + * hostip6.c - IPv6 specific functions + * + * The two asynchronous name resolver backends are implemented in: + * asyn-ares.c - functions for ares-using name resolves + * asyn-thread.c - functions for threaded name resolves + + * The hostip.h is the united header file for all this. It defines the + * CURLRES_* defines based on the config*.h and curl_setup.h defines. + */ + +static void freednsentry(void *freethis); + +/* + * Return # of addresses in a Curl_addrinfo struct + */ +int Curl_num_addresses(const Curl_addrinfo *addr) +{ + int i = 0; + while(addr) { + addr = addr->ai_next; + i++; + } + return i; +} + +/* + * Curl_printable_address() returns a printable version of the 1st address + * given in the 'ai' argument. The result will be stored in the buf that is + * bufsize bytes big. + * + * If the conversion fails, it returns NULL. + */ +const char * +Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize) +{ + const struct sockaddr_in *sa4; + const struct in_addr *ipaddr4; +#ifdef ENABLE_IPV6 + const struct sockaddr_in6 *sa6; + const struct in6_addr *ipaddr6; +#endif + + switch(ai->ai_family) { + case AF_INET: + sa4 = (const void *)ai->ai_addr; + ipaddr4 = &sa4->sin_addr; + return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, + bufsize); +#ifdef ENABLE_IPV6 + case AF_INET6: + sa6 = (const void *)ai->ai_addr; + ipaddr6 = &sa6->sin6_addr; + return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, + bufsize); +#endif + default: + break; + } + return NULL; +} + +/* + * Create a hostcache id string for the provided host + port, to be used by + * the DNS caching. Without alloc. + */ +static void +create_hostcache_id(const char *name, int port, char *ptr, size_t buflen) +{ + size_t len = strlen(name); + if(len > (buflen - 7)) + len = buflen - 7; + /* store and lower case the name */ + while(len--) + *ptr++ = (char)TOLOWER(*name++); + msnprintf(ptr, 7, ":%u", port); +} + +struct hostcache_prune_data { + long cache_timeout; + time_t now; +}; + +/* + * This function is set as a callback to be called for every entry in the DNS + * cache when we want to prune old unused entries. + * + * Returning non-zero means remove the entry, return 0 to keep it in the + * cache. + */ +static int +hostcache_timestamp_remove(void *datap, void *hc) +{ + struct hostcache_prune_data *data = + (struct hostcache_prune_data *) datap; + struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc; + + return (0 != c->timestamp) + && (data->now - c->timestamp >= data->cache_timeout); +} + +/* + * Prune the DNS cache. This assumes that a lock has already been taken. + */ +static void +hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now) +{ + struct hostcache_prune_data user; + + user.cache_timeout = cache_timeout; + user.now = now; + + Curl_hash_clean_with_criterium(hostcache, + (void *) &user, + hostcache_timestamp_remove); +} + +/* + * Library-wide function for pruning the DNS cache. This function takes and + * returns the appropriate locks. + */ +void Curl_hostcache_prune(struct Curl_easy *data) +{ + time_t now; + + if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache) + /* cache forever means never prune, and NULL hostcache means + we can't do it */ + return; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + time(&now); + + /* Remove outdated and unused entries from the hostcache */ + hostcache_prune(data->dns.hostcache, + data->set.dns_cache_timeout, + now); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + +#ifdef HAVE_SIGSETJMP +/* Beware this is a global and unique instance. This is used to store the + return address that we can jump back to from inside a signal handler. This + is not thread-safe stuff. */ +sigjmp_buf curl_jmpenv; +#endif + +/* lookup address, returns entry if found and not stale */ +static struct Curl_dns_entry * +fetch_addr(struct connectdata *conn, + const char *hostname, + int port) +{ + struct Curl_dns_entry *dns = NULL; + size_t entry_len; + struct Curl_easy *data = conn->data; + char entry_id[MAX_HOSTCACHE_LEN]; + + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + /* See if its already in our dns cache */ + dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); + + /* No entry found in cache, check if we might have a wildcard entry */ + if(!dns && data->change.wildcard_resolve) { + create_hostcache_id("*", port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + /* See if it's already in our dns cache */ + dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); + } + + if(dns && (data->set.dns_cache_timeout != -1)) { + /* See whether the returned entry is stale. Done before we release lock */ + struct hostcache_prune_data user; + + time(&user.now); + user.cache_timeout = data->set.dns_cache_timeout; + + if(hostcache_timestamp_remove(&user, dns)) { + infof(data, "Hostname in DNS cache was stale, zapped\n"); + dns = NULL; /* the memory deallocation is being handled by the hash */ + Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); + } + } + + return dns; +} + +/* + * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache. + * + * Curl_resolv() checks initially and multi_runsingle() checks each time + * it discovers the handle in the state WAITRESOLVE whether the hostname + * has already been resolved and the address has already been stored in + * the DNS cache. This short circuits waiting for a lot of pending + * lookups for the same hostname requested by different handles. + * + * Returns the Curl_dns_entry entry pointer or NULL if not in the cache. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +struct Curl_dns_entry * +Curl_fetch_addr(struct connectdata *conn, + const char *hostname, + int port) +{ + struct Curl_easy *data = conn->data; + struct Curl_dns_entry *dns = NULL; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = fetch_addr(conn, hostname, port); + + if(dns) + dns->inuse++; /* we use it! */ + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + return dns; +} + +#ifndef CURL_DISABLE_SHUFFLE_DNS +UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, + Curl_addrinfo **addr); +/* + * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo' + * struct by re-linking its linked list. + * + * The addr argument should be the address of a pointer to the head node of a + * `Curl_addrinfo` list and it will be modified to point to the new head after + * shuffling. + * + * Not declared static only to make it easy to use in a unit test! + * + * @unittest: 1608 + */ +UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, + Curl_addrinfo **addr) +{ + CURLcode result = CURLE_OK; + const int num_addrs = Curl_num_addresses(*addr); + + if(num_addrs > 1) { + Curl_addrinfo **nodes; + infof(data, "Shuffling %i addresses", num_addrs); + + nodes = malloc(num_addrs*sizeof(*nodes)); + if(nodes) { + int i; + unsigned int *rnd; + const size_t rnd_size = num_addrs * sizeof(*rnd); + + /* build a plain array of Curl_addrinfo pointers */ + nodes[0] = *addr; + for(i = 1; i < num_addrs; i++) { + nodes[i] = nodes[i-1]->ai_next; + } + + rnd = malloc(rnd_size); + if(rnd) { + /* Fisher-Yates shuffle */ + if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) { + Curl_addrinfo *swap_tmp; + for(i = num_addrs - 1; i > 0; i--) { + swap_tmp = nodes[rnd[i] % (i + 1)]; + nodes[rnd[i] % (i + 1)] = nodes[i]; + nodes[i] = swap_tmp; + } + + /* relink list in the new order */ + for(i = 1; i < num_addrs; i++) { + nodes[i-1]->ai_next = nodes[i]; + } + + nodes[num_addrs-1]->ai_next = NULL; + *addr = nodes[0]; + } + free(rnd); + } + else + result = CURLE_OUT_OF_MEMORY; + free(nodes); + } + else + result = CURLE_OUT_OF_MEMORY; + } + return result; +} +#endif + +/* + * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. + * + * When calling Curl_resolv() has resulted in a response with a returned + * address, we call this function to store the information in the dns + * cache etc + * + * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. + */ +struct Curl_dns_entry * +Curl_cache_addr(struct Curl_easy *data, + Curl_addrinfo *addr, + const char *hostname, + int port) +{ + char entry_id[MAX_HOSTCACHE_LEN]; + size_t entry_len; + struct Curl_dns_entry *dns; + struct Curl_dns_entry *dns2; + +#ifndef CURL_DISABLE_SHUFFLE_DNS + /* shuffle addresses if requested */ + if(data->set.dns_shuffle_addresses) { + CURLcode result = Curl_shuffle_addr(data, &addr); + if(result) + return NULL; + } +#endif + + /* Create a new cache entry */ + dns = calloc(1, sizeof(struct Curl_dns_entry)); + if(!dns) { + return NULL; + } + + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + dns->inuse = 1; /* the cache has the first reference */ + dns->addr = addr; /* this is the address(es) */ + time(&dns->timestamp); + if(dns->timestamp == 0) + dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */ + + /* Store the resolved data in our DNS cache. */ + dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1, + (void *)dns); + if(!dns2) { + free(dns); + return NULL; + } + + dns = dns2; + dns->inuse++; /* mark entry as in-use */ + return dns; +} + +/* + * Curl_resolv() is the main name resolve function within libcurl. It resolves + * a name and returns a pointer to the entry in the 'entry' argument (if one + * is provided). This function might return immediately if we're using asynch + * resolves. See the return codes. + * + * The cache entry we return will get its 'inuse' counter increased when this + * function is used. You MUST call Curl_resolv_unlock() later (when you're + * done using this struct) to decrease the counter again. + * + * In debug mode, we specifically test for an interface name "LocalHost" + * and resolve "localhost" instead as a means to permit test cases + * to connect to a local test server with any host name. + * + * Return codes: + * + * CURLRESOLV_ERROR (-1) = error, no pointer + * CURLRESOLV_RESOLVED (0) = OK, pointer provided + * CURLRESOLV_PENDING (1) = waiting for response, no pointer + */ + +int Curl_resolv(struct connectdata *conn, + const char *hostname, + int port, + bool allowDOH, + struct Curl_dns_entry **entry) +{ + struct Curl_dns_entry *dns = NULL; + struct Curl_easy *data = conn->data; + CURLcode result; + int rc = CURLRESOLV_ERROR; /* default to failure */ + + *entry = NULL; + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + dns = fetch_addr(conn, hostname, port); + + if(dns) { + infof(data, "Hostname %s was found in DNS cache\n", hostname); + dns->inuse++; /* we use it! */ + rc = CURLRESOLV_RESOLVED; + } + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) { + /* The entry was not in the cache. Resolve it to IP address */ + + Curl_addrinfo *addr; + int respwait = 0; + + /* Check what IP specifics the app has requested and if we can provide it. + * If not, bail out. */ + if(!Curl_ipvalid(conn)) + return CURLRESOLV_ERROR; + + /* notify the resolver start callback */ + if(data->set.resolver_start) { + int st; + Curl_set_in_callback(data, true); + st = data->set.resolver_start(data->state.resolver, NULL, + data->set.resolver_start_client); + Curl_set_in_callback(data, false); + if(st) + return CURLRESOLV_ERROR; + } + + if(allowDOH && data->set.doh) { + addr = Curl_doh(conn, hostname, port, &respwait); + } + else { + /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a + non-zero value indicating that we need to wait for the response to the + resolve call */ + addr = Curl_getaddrinfo(conn, +#ifdef DEBUGBUILD + (data->set.str[STRING_DEVICE] + && !strcmp(data->set.str[STRING_DEVICE], + "LocalHost"))?"localhost": +#endif + hostname, port, &respwait); + } + if(!addr) { + if(respwait) { + /* the response to our resolve call will come asynchronously at + a later time, good or bad */ + /* First, check that we haven't received the info by now */ + result = Curl_resolv_check(conn, &dns); + if(result) /* error detected */ + return CURLRESOLV_ERROR; + if(dns) + rc = CURLRESOLV_RESOLVED; /* pointer provided */ + else + rc = CURLRESOLV_PENDING; /* no info yet */ + } + } + else { + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* we got a response, store it in the cache */ + dns = Curl_cache_addr(data, addr, hostname, port); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) + /* returned failure, bail out nicely */ + Curl_freeaddrinfo(addr); + else + rc = CURLRESOLV_RESOLVED; + } + } + + *entry = dns; + + return rc; +} + +#ifdef USE_ALARM_TIMEOUT +/* + * This signal handler jumps back into the main libcurl code and continues + * execution. This effectively causes the remainder of the application to run + * within a signal handler which is nonportable and could lead to problems. + */ +static +RETSIGTYPE alarmfunc(int sig) +{ + /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ + (void)sig; + siglongjmp(curl_jmpenv, 1); +} +#endif /* USE_ALARM_TIMEOUT */ + +/* + * Curl_resolv_timeout() is the same as Curl_resolv() but specifies a + * timeout. This function might return immediately if we're using asynch + * resolves. See the return codes. + * + * The cache entry we return will get its 'inuse' counter increased when this + * function is used. You MUST call Curl_resolv_unlock() later (when you're + * done using this struct) to decrease the counter again. + * + * If built with a synchronous resolver and use of signals is not + * disabled by the application, then a nonzero timeout will cause a + * timeout after the specified number of milliseconds. Otherwise, timeout + * is ignored. + * + * Return codes: + * + * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired + * CURLRESOLV_ERROR (-1) = error, no pointer + * CURLRESOLV_RESOLVED (0) = OK, pointer provided + * CURLRESOLV_PENDING (1) = waiting for response, no pointer + */ + +int Curl_resolv_timeout(struct connectdata *conn, + const char *hostname, + int port, + struct Curl_dns_entry **entry, + time_t timeoutms) +{ +#ifdef USE_ALARM_TIMEOUT +#ifdef HAVE_SIGACTION + struct sigaction keep_sigact; /* store the old struct here */ + volatile bool keep_copysig = FALSE; /* whether old sigact has been saved */ + struct sigaction sigact; +#else +#ifdef HAVE_SIGNAL + void (*keep_sigact)(int); /* store the old handler here */ +#endif /* HAVE_SIGNAL */ +#endif /* HAVE_SIGACTION */ + volatile long timeout; + volatile unsigned int prev_alarm = 0; + struct Curl_easy *data = conn->data; +#endif /* USE_ALARM_TIMEOUT */ + int rc; + + *entry = NULL; + + if(timeoutms < 0) + /* got an already expired timeout */ + return CURLRESOLV_TIMEDOUT; + +#ifdef USE_ALARM_TIMEOUT + if(data->set.no_signal) + /* Ignore the timeout when signals are disabled */ + timeout = 0; + else + timeout = (timeoutms > LONG_MAX) ? LONG_MAX : (long)timeoutms; + + if(!timeout) + /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */ + return Curl_resolv(conn, hostname, port, TRUE, entry); + + if(timeout < 1000) { + /* The alarm() function only provides integer second resolution, so if + we want to wait less than one second we must bail out already now. */ + failf(data, + "remaining timeout of %ld too small to resolve via SIGALRM method", + timeout); + return CURLRESOLV_TIMEDOUT; + } + /* This allows us to time-out from the name resolver, as the timeout + will generate a signal and we will siglongjmp() from that here. + This technique has problems (see alarmfunc). + This should be the last thing we do before calling Curl_resolv(), + as otherwise we'd have to worry about variables that get modified + before we invoke Curl_resolv() (and thus use "volatile"). */ + if(sigsetjmp(curl_jmpenv, 1)) { + /* this is coming from a siglongjmp() after an alarm signal */ + failf(data, "name lookup timed out"); + rc = CURLRESOLV_ERROR; + goto clean_up; + } + else { + /************************************************************* + * Set signal handler to catch SIGALRM + * Store the old value to be able to set it back later! + *************************************************************/ +#ifdef HAVE_SIGACTION + sigaction(SIGALRM, NULL, &sigact); + keep_sigact = sigact; + keep_copysig = TRUE; /* yes, we have a copy */ + sigact.sa_handler = alarmfunc; +#ifdef SA_RESTART + /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ + sigact.sa_flags &= ~SA_RESTART; +#endif + /* now set the new struct */ + sigaction(SIGALRM, &sigact, NULL); +#else /* HAVE_SIGACTION */ + /* no sigaction(), revert to the much lamer signal() */ +#ifdef HAVE_SIGNAL + keep_sigact = signal(SIGALRM, alarmfunc); +#endif +#endif /* HAVE_SIGACTION */ + + /* alarm() makes a signal get sent when the timeout fires off, and that + will abort system calls */ + prev_alarm = alarm(curlx_sltoui(timeout/1000L)); + } + +#else +#ifndef CURLRES_ASYNCH + if(timeoutms) + infof(conn->data, "timeout on name lookup is not supported\n"); +#else + (void)timeoutms; /* timeoutms not used with an async resolver */ +#endif +#endif /* USE_ALARM_TIMEOUT */ + + /* Perform the actual name resolution. This might be interrupted by an + * alarm if it takes too long. + */ + rc = Curl_resolv(conn, hostname, port, TRUE, entry); + +#ifdef USE_ALARM_TIMEOUT +clean_up: + + if(!prev_alarm) + /* deactivate a possibly active alarm before uninstalling the handler */ + alarm(0); + +#ifdef HAVE_SIGACTION + if(keep_copysig) { + /* we got a struct as it looked before, now put that one back nice + and clean */ + sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */ + } +#else +#ifdef HAVE_SIGNAL + /* restore the previous SIGALRM handler */ + signal(SIGALRM, keep_sigact); +#endif +#endif /* HAVE_SIGACTION */ + + /* switch back the alarm() to either zero or to what it was before minus + the time we spent until now! */ + if(prev_alarm) { + /* there was an alarm() set before us, now put it back */ + timediff_t elapsed_secs = Curl_timediff(Curl_now(), + conn->created) / 1000; + + /* the alarm period is counted in even number of seconds */ + unsigned long alarm_set = prev_alarm - elapsed_secs; + + if(!alarm_set || + ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) { + /* if the alarm time-left reached zero or turned "negative" (counted + with unsigned values), we should fire off a SIGALRM here, but we + won't, and zero would be to switch it off so we never set it to + less than 1! */ + alarm(1); + rc = CURLRESOLV_TIMEDOUT; + failf(data, "Previous alarm fired off!"); + } + else + alarm((unsigned int)alarm_set); + } +#endif /* USE_ALARM_TIMEOUT */ + + return rc; +} + +/* + * Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been + * made, the struct may be destroyed due to pruning. It is important that only + * one unlock is made for each Curl_resolv() call. + * + * May be called with 'data' == NULL for global cache. + */ +void Curl_resolv_unlock(struct Curl_easy *data, struct Curl_dns_entry *dns) +{ + if(data && data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + freednsentry(dns); + + if(data && data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + +/* + * File-internal: release cache dns entry reference, free if inuse drops to 0 + */ +static void freednsentry(void *freethis) +{ + struct Curl_dns_entry *dns = (struct Curl_dns_entry *) freethis; + DEBUGASSERT(dns && (dns->inuse>0)); + + dns->inuse--; + if(dns->inuse == 0) { + Curl_freeaddrinfo(dns->addr); + free(dns); + } +} + +/* + * Curl_mk_dnscache() inits a new DNS cache and returns success/failure. + */ +int Curl_mk_dnscache(struct curl_hash *hash) +{ + return Curl_hash_init(hash, 7, Curl_hash_str, Curl_str_key_compare, + freednsentry); +} + +/* + * Curl_hostcache_clean() + * + * This _can_ be called with 'data' == NULL but then of course no locking + * can be done! + */ + +void Curl_hostcache_clean(struct Curl_easy *data, + struct curl_hash *hash) +{ + if(data && data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + Curl_hash_clean(hash); + + if(data && data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); +} + + +CURLcode Curl_loadhostpairs(struct Curl_easy *data) +{ + struct curl_slist *hostp; + char hostname[256]; + int port = 0; + + /* Default is no wildcard found */ + data->change.wildcard_resolve = false; + + for(hostp = data->change.resolve; hostp; hostp = hostp->next) { + char entry_id[MAX_HOSTCACHE_LEN]; + if(!hostp->data) + continue; + if(hostp->data[0] == '-') { + size_t entry_len; + + if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { + infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n", + hostp->data); + continue; + } + + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* delete entry, ignore if it didn't exist */ + Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + } + else { + struct Curl_dns_entry *dns; + Curl_addrinfo *head = NULL, *tail = NULL; + size_t entry_len; + char address[64]; +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + char *addresses = NULL; +#endif + char *addr_begin; + char *addr_end; + char *port_ptr; + char *end_ptr; + char *host_end; + unsigned long tmp_port; + bool error = true; + + host_end = strchr(hostp->data, ':'); + if(!host_end || + ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname))) + goto err; + + memcpy(hostname, hostp->data, host_end - hostp->data); + hostname[host_end - hostp->data] = '\0'; + + port_ptr = host_end + 1; + tmp_port = strtoul(port_ptr, &end_ptr, 10); + if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':') + goto err; + + port = (int)tmp_port; +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + addresses = end_ptr + 1; +#endif + + while(*end_ptr) { + size_t alen; + Curl_addrinfo *ai; + + addr_begin = end_ptr + 1; + addr_end = strchr(addr_begin, ','); + if(!addr_end) + addr_end = addr_begin + strlen(addr_begin); + end_ptr = addr_end; + + /* allow IP(v6) address within [brackets] */ + if(*addr_begin == '[') { + if(addr_end == addr_begin || *(addr_end - 1) != ']') + goto err; + ++addr_begin; + --addr_end; + } + + alen = addr_end - addr_begin; + if(!alen) + continue; + + if(alen >= sizeof(address)) + goto err; + + memcpy(address, addr_begin, alen); + address[alen] = '\0'; + +#ifndef ENABLE_IPV6 + if(strchr(address, ':')) { + infof(data, "Ignoring resolve address '%s', missing IPv6 support.\n", + address); + continue; + } +#endif + + ai = Curl_str2addr(address, port); + if(!ai) { + infof(data, "Resolve address '%s' found illegal!\n", address); + goto err; + } + + if(tail) { + tail->ai_next = ai; + tail = tail->ai_next; + } + else { + head = tail = ai; + } + } + + if(!head) + goto err; + + error = false; + err: + if(error) { + infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n", + hostp->data); + Curl_freeaddrinfo(head); + continue; + } + + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* See if its already in our dns cache */ + dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); + + if(dns) { + infof(data, "RESOLVE %s:%d is - old addresses discarded!\n", + hostname, port); + /* delete old entry entry, there are two reasons for this + 1. old entry may have different addresses. + 2. even if entry with correct addresses is already in the cache, + but if it is close to expire, then by the time next http + request is made, it can get expired and pruned because old + entry is not necessarily marked as added by CURLOPT_RESOLVE. */ + + Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); + } + + /* put this new host in the cache */ + dns = Curl_cache_addr(data, head, hostname, port); + if(dns) { + dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */ + /* release the returned reference; the cache itself will keep the + * entry alive: */ + dns->inuse--; + } + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + + if(!dns) { + Curl_freeaddrinfo(head); + return CURLE_OUT_OF_MEMORY; + } + + //infof(data, "Added %s:%d:%s to DNS cache\n", + //hostname, port, addresses); + + /* Wildcard hostname */ + if(hostname[0] == '*' && hostname[1] == '\0') { + infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n", + hostname, port); + data->change.wildcard_resolve = true; + } + } + } + data->change.resolve = NULL; /* dealt with now */ + + return CURLE_OK; +} + +CURLcode Curl_resolv_check(struct connectdata *conn, + struct Curl_dns_entry **dns) +{ + if(conn->data->set.doh) + return Curl_doh_is_resolved(conn, dns); + return Curl_resolver_is_resolved(conn, dns); +} + +int Curl_resolv_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ +#ifdef CURLRES_ASYNCH + if(conn->data->set.doh) + /* nothing to wait for during DOH resolve, those handles have their own + sockets */ + return GETSOCK_BLANK; + return Curl_resolver_getsock(conn, socks, numsocks); +#else + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +#endif +} + +/* Call this function after Curl_connect() has returned async=TRUE and + then a successful name resolve has been received. + + Note: this function disconnects and frees the conn data in case of + resolve failure */ +CURLcode Curl_once_resolved(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result; + + if(conn->async.dns) { + conn->dns_entry = conn->async.dns; + conn->async.dns = NULL; + } + + result = Curl_setup_conn(conn, protocol_done); + + if(result) + /* We're not allowed to return failure with memory left allocated + in the connectdata struct, free those here */ + Curl_disconnect(conn->data, conn, TRUE); /* close the connection */ + + return result; +} diff --git a/libcurl/lib/hostip.h b/libcurl/lib/hostip.h new file mode 100644 index 0000000..1bda524 --- /dev/null +++ b/libcurl/lib/hostip.h @@ -0,0 +1,246 @@ +#ifndef HEADER_CURL_HOSTIP_H +#define HEADER_CURL_HOSTIP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "hash.h" +#include "curl_addrinfo.h" +#include "asyn.h" + +#ifdef HAVE_SETJMP_H +#include +#endif + +#ifdef NETWARE +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +/* Allocate enough memory to hold the full name information structs and + * everything. OSF1 is known to require at least 8872 bytes. The buffer + * required for storing all possible aliases and IP numbers is according to + * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes! + */ +#define CURL_HOSTENT_SIZE 9000 + +#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this + many seconds for a name resolve */ + +#define CURL_ASYNC_SUCCESS CURLE_OK + +struct addrinfo; +struct hostent; +struct Curl_easy; +struct connectdata; + +/* + * Curl_global_host_cache_init() initializes and sets up a global DNS cache. + * Global DNS cache is general badness. Do not use. This will be removed in + * a future version. Use the share interface instead! + * + * Returns a struct curl_hash pointer on success, NULL on failure. + */ +struct curl_hash *Curl_global_host_cache_init(void); + +struct Curl_dns_entry { + Curl_addrinfo *addr; + /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */ + time_t timestamp; + /* use-counter, use Curl_resolv_unlock to release reference */ + long inuse; +}; + +/* + * Curl_resolv() returns an entry with the info for the specified host + * and port. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +/* return codes */ +#define CURLRESOLV_TIMEDOUT -2 +#define CURLRESOLV_ERROR -1 +#define CURLRESOLV_RESOLVED 0 +#define CURLRESOLV_PENDING 1 +int Curl_resolv(struct connectdata *conn, + const char *hostname, + int port, + bool allowDOH, + struct Curl_dns_entry **dnsentry); +int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, + int port, struct Curl_dns_entry **dnsentry, + time_t timeoutms); + +#ifdef CURLRES_IPV6 +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +bool Curl_ipv6works(void); +#else +#define Curl_ipv6works() FALSE +#endif + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +bool Curl_ipvalid(struct connectdata *conn); + + +/* + * Curl_getaddrinfo() is the generic low-level name resolve API within this + * source file. There are several versions of this function - for different + * name resolve layers (selected at build-time). They all take this same set + * of arguments + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + + +/* unlock a previously resolved dns entry */ +void Curl_resolv_unlock(struct Curl_easy *data, + struct Curl_dns_entry *dns); + +/* init a new dns cache and return success */ +int Curl_mk_dnscache(struct curl_hash *hash); + +/* prune old entries from the DNS cache */ +void Curl_hostcache_prune(struct Curl_easy *data); + +/* Return # of addresses in a Curl_addrinfo struct */ +int Curl_num_addresses(const Curl_addrinfo *addr); + +#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) +int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, + GETNAMEINFO_TYPE_ARG2 salen, + char *host, GETNAMEINFO_TYPE_ARG46 hostlen, + char *serv, GETNAMEINFO_TYPE_ARG46 servlen, + GETNAMEINFO_TYPE_ARG7 flags, + int line, const char *source); +#endif + +/* IPv4 threadsafe resolve function used for synch and asynch builds */ +Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); + +CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect); + +/* + * Curl_addrinfo_callback() is used when we build with any asynch specialty. + * Handles end of async request processing. Inserts ai into hostcache when + * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async + * request completed whether successful or failed. + */ +CURLcode Curl_addrinfo_callback(struct connectdata *conn, + int status, + Curl_addrinfo *ai); + +/* + * Curl_printable_address() returns a printable version of the 1st address + * given in the 'ip' argument. The result will be stored in the buf that is + * bufsize bytes big. + */ +const char *Curl_printable_address(const Curl_addrinfo *ip, + char *buf, size_t bufsize); + +/* + * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache. + * + * Returns the Curl_dns_entry entry pointer or NULL if not in the cache. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +struct Curl_dns_entry * +Curl_fetch_addr(struct connectdata *conn, + const char *hostname, + int port); + +/* + * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. + * + * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. + */ +struct Curl_dns_entry * +Curl_cache_addr(struct Curl_easy *data, Curl_addrinfo *addr, + const char *hostname, int port); + +#ifndef INADDR_NONE +#define CURL_INADDR_NONE (in_addr_t) ~0 +#else +#define CURL_INADDR_NONE INADDR_NONE +#endif + +#ifdef HAVE_SIGSETJMP +/* Forward-declaration of variable defined in hostip.c. Beware this + * is a global and unique instance. This is used to store the return + * address that we can jump back to from inside a signal handler. + * This is not thread-safe stuff. + */ +extern sigjmp_buf curl_jmpenv; +#endif + +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers); + +/* + * Function provided by the resolver backend to set + * outgoing interface to use for DNS requests + */ +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf); + +/* + * Function provided by the resolver backend to set + * local IPv4 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4); + +/* + * Function provided by the resolver backend to set + * local IPv6 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6); + +/* + * Clean off entries from the cache + */ +void Curl_hostcache_clean(struct Curl_easy *data, struct curl_hash *hash); + +/* + * Populate the cache with specified entries from CURLOPT_RESOLVE. + */ +CURLcode Curl_loadhostpairs(struct Curl_easy *data); + +CURLcode Curl_resolv_check(struct connectdata *conn, + struct Curl_dns_entry **dns); +int Curl_resolv_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + +#endif /* HEADER_CURL_HOSTIP_H */ diff --git a/libcurl/lib/hostip4.c b/libcurl/lib/hostip4.c new file mode 100644 index 0000000..47312c3 --- /dev/null +++ b/libcurl/lib/hostip4.c @@ -0,0 +1,503 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for plain IPv4 builds + **********************************************************************/ +#ifdef CURLRES_IPV4 /* plain IPv4 code coming up */ + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_pton.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef _XBOX +/* Forward declaration for Xbox hostent cleanup function */ +void xbox_freehostent(struct hostent *hp); +#endif + +#ifdef _XBOX + +/* + * Xbox-specific gethostbyname() implementation using XNetDnsLookup. + * This allocates memory that MUST be freed by calling xbox_freehostent(). + */ +struct hostent * gethostbyname (char *host) { + struct hostent *hp = NULL; + struct sockaddr_in sa; + char szLocalHostName[256]; + size_t hostLen; + int iLen; + WSAEVENT hEvent = NULL; + XNDNS *heHost = NULL; + + /* Validate input parameter */ + if(host == NULL || host[0] == '\0') { + return NULL; + } + + /* Safely copy hostname with length check */ + hostLen = strlen(host); + if(hostLen >= sizeof(szLocalHostName)) { + return NULL; + } + memcpy(szLocalHostName, host, hostLen + 1); + + /* Determine if this is an IP address or hostname by checking + * if it contains only digits and dots */ + iLen = (int)hostLen; + while(--iLen >= 0 && (szLocalHostName[iLen] == '.' || + isdigit((unsigned char)szLocalHostName[iLen]))); + + if(iLen >= 0) { + /* This is a hostname - perform DNS lookup */ + + /* Create event for async DNS notification */ + hEvent = WSACreateEvent(); + if(hEvent == NULL) { + return NULL; + } + + /* Initiate DNS lookup */ + if(XNetDnsLookup(szLocalHostName, hEvent, &heHost) != 0) { + WSACloseEvent(hEvent); + return NULL; + } + + /* Wait for DNS response with timeout */ + { + DWORD wait_result = WaitForSingleObject(hEvent, 30000); + WSACloseEvent(hEvent); + hEvent = NULL; + + if(wait_result == WAIT_TIMEOUT) { + XNetDnsRelease(heHost); + return NULL; + } + } + + /* Check DNS lookup result */ + if(heHost->iStatus != 0) { + /* DNS lookup failed */ + XNetDnsRelease(heHost); + return NULL; + } + + /* Verify we got at least one address */ + if(heHost->cina == 0) { + XNetDnsRelease(heHost); + return NULL; + } + + /* Allocate and populate hostent structure with ALL returned addresses */ + hp = (struct hostent *)calloc(1, sizeof(struct hostent)); + if(!hp) { + XNetDnsRelease(heHost); + return NULL; + } + + hp->h_aliases = NULL; + hp->h_addrtype = AF_INET; + hp->h_length = sizeof(struct in_addr); + hp->h_name = strdup(host); + if(!hp->h_name) { + free(hp); + XNetDnsRelease(heHost); + return NULL; + } + + /* Allocate pointer array for all addresses + NULL terminator */ + hp->h_addr_list = (char **)calloc(heHost->cina + 1, sizeof(char *)); + if(!hp->h_addr_list) { + free(hp->h_name); + free(hp); + XNetDnsRelease(heHost); + return NULL; + } + + /* Populate all returned addresses */ + { + int i; + for(i = 0; i < (int)heHost->cina; i++) { + hp->h_addr_list[i] = (char *)calloc(1, sizeof(struct in_addr)); + if(!hp->h_addr_list[i]) { + /* Cleanup on allocation failure */ + int j; + for(j = 0; j < i; j++) { + free(hp->h_addr_list[j]); + } + free(hp->h_addr_list); + free(hp->h_name); + free(hp); + XNetDnsRelease(heHost); + return NULL; + } + memcpy(hp->h_addr_list[i], &(heHost->aina[i].S_un.S_addr), hp->h_length); + } + } + XNetDnsRelease(heHost); + } + else { + /* This is an IP address (only digits and dots) - parse it directly */ + if(Curl_inet_pton(AF_INET, host, &(sa.sin_addr)) != 1) { + return NULL; + } + + /* Allocate and populate hostent structure */ + hp = (struct hostent *)calloc(1, sizeof(struct hostent)); + if(!hp) { + return NULL; + } + + hp->h_aliases = NULL; + hp->h_addrtype = AF_INET; + hp->h_length = sizeof(struct in_addr); + hp->h_name = strdup(host); + if(!hp->h_name) { + free(hp); + return NULL; + } + + hp->h_addr_list = (char **)calloc(2, sizeof(char *)); + if(!hp->h_addr_list) { + free(hp->h_name); + free(hp); + return NULL; + } + + hp->h_addr_list[0] = (char *)calloc(1, sizeof(struct in_addr)); + if(!hp->h_addr_list[0]) { + free(hp->h_addr_list); + free(hp->h_name); + free(hp); + return NULL; + } + + memcpy(hp->h_addr_list[0], &(sa.sin_addr), hp->h_length); + } + + return hp; +} + +/* + * Free a hostent structure allocated by Xbox gethostbyname(). + * This is called from Curl_ipv4_resolve_r() after conversion to Curl_addrinfo. + */ +void xbox_freehostent(struct hostent *hp) { + if(hp) { + if(hp->h_addr_list) { + int i; + for(i = 0; hp->h_addr_list[i] != NULL; i++) { + free(hp->h_addr_list[i]); + } + free(hp->h_addr_list); + } + if(hp->h_name) { + free(hp->h_name); + } + free(hp); + } +} + +#endif /* _XBOX */ + + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +bool Curl_ipvalid(struct connectdata *conn) +{ + if(conn->ip_version == CURL_IPRESOLVE_V6) + /* An IPv6 address was requested and we can't get/use one */ + return FALSE; + + return TRUE; /* OK, proceed */ +} + +#ifdef CURLRES_SYNCH + +/* + * Curl_getaddrinfo() - the IPv4 synchronous version. + * + * The original code to this function was from the Dancer source code, written + * by Bjorn Reese, it has since been patched and modified considerably. + * + * gethostbyname_r() is the thread-safe version of the gethostbyname() + * function. When we build for plain IPv4, we attempt to use this + * function. There are _three_ different gethostbyname_r() versions, and we + * detect which one this platform supports in the configure script and set up + * the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or + * HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME + * has the corresponding rules. This is primarily on *nix. Note that some unix + * flavours have thread-safe versions of the plain gethostbyname() etc. + * + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + Curl_addrinfo *ai = NULL; + +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)conn; +#endif + + *waitp = 0; /* synchronous response only */ + + ai = Curl_ipv4_resolve_r(hostname, port); + if(!ai) + infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname); + + return ai; +} +#endif /* CURLRES_SYNCH */ +#endif /* CURLRES_IPV4 */ + +#if defined(CURLRES_IPV4) && !defined(CURLRES_ARES) + +/* + * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function. + * + * This is used for both synchronous and asynchronous resolver builds, + * implying that only threadsafe code and function calls may be used. + * + */ +Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, + int port) +{ +#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3) + int res; +#endif + Curl_addrinfo *ai = NULL; + struct hostent *h = NULL; + struct in_addr in; + struct hostent *buf = NULL; + + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, hostname, port); + +#if defined(HAVE_GETADDRINFO_THREADSAFE) + else { + struct addrinfo hints; + char sbuf[12]; + char *sbufptr = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + if(port) { + msnprintf(sbuf, sizeof(sbuf), "%d", port); + sbufptr = sbuf; + } + + (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai); + +#elif defined(HAVE_GETHOSTBYNAME_R) + /* + * gethostbyname_r() is the preferred resolve function for many platforms. + * Since there are three different versions of it, the following code is + * somewhat #ifdef-ridden. + */ + else { + int h_errnop; + + buf = calloc(1, CURL_HOSTENT_SIZE); + if(!buf) + return NULL; /* major failure */ + /* + * The clearing of the buffer is a workaround for a gethostbyname_r bug in + * qnx nto and it is also _required_ for some of these functions on some + * platforms. + */ + +#if defined(HAVE_GETHOSTBYNAME_R_5) + /* Solaris, IRIX and more */ + h = gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h_errnop); + + /* If the buffer is too small, it returns NULL and sets errno to + * ERANGE. The errno is thread safe if this is compiled with + * -D_REENTRANT as then the 'errno' variable is a macro defined to get + * used properly for threads. + */ + + if(h) { + ; + } + else +#elif defined(HAVE_GETHOSTBYNAME_R_6) + /* Linux */ + + (void)gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h, /* DIFFERENCE */ + &h_errnop); + /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a + * sudden this function returns EAGAIN if the given buffer size is too + * small. Previous versions are known to return ERANGE for the same + * problem. + * + * This wouldn't be such a big problem if older versions wouldn't + * sometimes return EAGAIN on a common failure case. Alas, we can't + * assume that EAGAIN *or* ERANGE means ERANGE for any given version of + * glibc. + * + * For now, we do that and thus we may call the function repeatedly and + * fail for older glibc versions that return EAGAIN, until we run out of + * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). + * + * If anyone has a better fix, please tell us! + * + * ------------------------------------------------------------------- + * + * On October 23rd 2003, Dan C dug up more details on the mysteries of + * gethostbyname_r() in glibc: + * + * In glibc 2.2.5 the interface is different (this has also been + * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't + * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 + * (shipped/upgraded by Redhat 7.2) don't show this behavior! + * + * In this "buggy" version, the return code is -1 on error and 'errno' + * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a + * thread-safe variable. + */ + + if(!h) /* failure */ +#elif defined(HAVE_GETHOSTBYNAME_R_3) + /* AIX, Digital Unix/Tru64, HPUX 10, more? */ + + /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of + * the plain fact that it does not return unique full buffers on each + * call, but instead several of the pointers in the hostent structs will + * point to the same actual data! This have the unfortunate down-side that + * our caching system breaks down horribly. Luckily for us though, AIX 4.3 + * and more recent versions have a "completely thread-safe"[*] libc where + * all the data is stored in thread-specific memory areas making calls to + * the plain old gethostbyname() work fine even for multi-threaded + * programs. + * + * This AIX 4.3 or later detection is all made in the configure script. + * + * Troels Walsted Hansen helped us work this out on March 3rd, 2003. + * + * [*] = much later we've found out that it isn't at all "completely + * thread-safe", but at least the gethostbyname() function is. + */ + + if(CURL_HOSTENT_SIZE >= + (sizeof(struct hostent) + sizeof(struct hostent_data))) { + + /* August 22nd, 2000: Albert Chin-A-Young brought an updated version + * that should work! September 20: Richard Prescott worked on the buffer + * size dilemma. + */ + + res = gethostbyname_r(hostname, + (struct hostent *)buf, + (struct hostent_data *)((char *)buf + + sizeof(struct hostent))); + h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */ + } + else + res = -1; /* failure, too smallish buffer size */ + + if(!res) { /* success */ + + h = buf; /* result expected in h */ + + /* This is the worst kind of the different gethostbyname_r() interfaces. + * Since we don't know how big buffer this particular lookup required, + * we can't realloc down the huge alloc without doing closer analysis of + * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every + * name lookup. Fixing this would require an extra malloc() and then + * calling Curl_addrinfo_copy() that subsequent realloc()s down the new + * memory area to the actually used amount. + */ + } + else +#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */ + { + h = NULL; /* set return code to NULL */ + free(buf); + } +#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ + /* + * Here is code for platforms that don't have a thread safe + * getaddrinfo() nor gethostbyname_r() function or for which + * gethostbyname() is the preferred one. + */ + else { + h = gethostbyname((void *)hostname); +#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ + } + + if(h) { + ai = Curl_he2ai(h, port); + + if(buf) /* used a *_r() function */ + free(buf); +#ifdef _XBOX + /* Xbox gethostbyname() allocates memory that must be freed */ + xbox_freehostent(h); +#endif + } + + return ai; +} +#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */ diff --git a/libcurl/lib/hostip6.c b/libcurl/lib/hostip6.c new file mode 100644 index 0000000..5511f1a --- /dev/null +++ b/libcurl/lib/hostip6.c @@ -0,0 +1,203 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for IPv6-enabled builds + **********************************************************************/ +#ifdef CURLRES_IPV6 + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "inet_pton.h" +#include "connect.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +bool Curl_ipv6works(void) +{ + /* the nature of most system is that IPv6 status doesn't come and go + during a program's lifetime so we only probe the first time and then we + have the info kept for fast re-use */ + static int ipv6_works = -1; + if(-1 == ipv6_works) { + /* probe to see if we have a working IPv6 stack */ + curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); + if(s == CURL_SOCKET_BAD) + /* an IPv6 address was requested but we can't get/use one */ + ipv6_works = 0; + else { + ipv6_works = 1; + Curl_closesocket(NULL, s); + } + } + return (ipv6_works>0)?TRUE:FALSE; +} + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +bool Curl_ipvalid(struct connectdata *conn) +{ + if(conn->ip_version == CURL_IPRESOLVE_V6) + return Curl_ipv6works(); + + return TRUE; +} + +#if defined(CURLRES_SYNCH) + +#ifdef DEBUG_ADDRINFO +static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai) +{ + printf("dump_addrinfo:\n"); + for(; ai; ai = ai->ai_next) { + char buf[INET6_ADDRSTRLEN]; + printf(" fam %2d, CNAME %s, ", + ai->ai_family, ai->ai_canonname ? ai->ai_canonname : ""); + if(Curl_printable_address(ai, buf, sizeof(buf))) + printf("%s\n", buf); + else { + char buffer[STRERROR_LEN]; + printf("failed; %s\n", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + } + } +} +#else +#define dump_addrinfo(x,y) Curl_nop_stmt +#endif + +/* + * Curl_getaddrinfo() when built IPv6-enabled (non-threading and + * non-ares version). + * + * Returns name information about the given hostname and port number. If + * successful, the 'addrinfo' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp) +{ + struct addrinfo hints; + Curl_addrinfo *res; + int error; + char sbuf[12]; + char *sbufptr = NULL; +#ifndef USE_RESOLVE_ON_IPS + char addrbuf[128]; +#endif + int pf; +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + struct Curl_easy *data = conn->data; +#endif + + *waitp = 0; /* synchronous response only */ + + /* Check if a limited name resolve has been requested */ + switch(conn->ip_version) { + case CURL_IPRESOLVE_V4: + pf = PF_INET; + break; + case CURL_IPRESOLVE_V6: + pf = PF_INET6; + break; + default: + pf = PF_UNSPEC; + break; + } + + if((pf != PF_INET) && !Curl_ipv6works()) + /* The stack seems to be a non-IPv6 one */ + pf = PF_INET; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = pf; + hints.ai_socktype = conn->socktype; + +#ifndef USE_RESOLVE_ON_IPS + /* + * The AI_NUMERICHOST must not be set to get synthesized IPv6 address from + * an IPv4 address on iOS and Mac OS X. + */ + if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) || + (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) { + /* the given address is numerical only, prevent a reverse lookup */ + hints.ai_flags = AI_NUMERICHOST; + } +#endif + + if(port) { + msnprintf(sbuf, sizeof(sbuf), "%d", port); + sbufptr = sbuf; + } + + error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res); + if(error) { + infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port); + return NULL; + } + + if(port) { + Curl_addrinfo_set_port(res, port); + } + + dump_addrinfo(conn, res); + + return res; +} +#endif /* CURLRES_SYNCH */ + +#endif /* CURLRES_IPV6 */ diff --git a/libcurl/lib/hostsyn.c b/libcurl/lib/hostsyn.c new file mode 100644 index 0000000..3de6746 --- /dev/null +++ b/libcurl/lib/hostsyn.c @@ -0,0 +1,107 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/*********************************************************************** + * Only for builds using synchronous name resolves + **********************************************************************/ +#ifdef CURLRES_SYNCH + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_PROCESS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "hash.h" +#include "share.h" +#include "strerror.h" +#include "url.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURLcode Curl_set_dns_servers(struct Curl_easy *data, + char *servers) +{ + (void)data; + (void)servers; + return CURLE_NOT_BUILT_IN; + +} + +/* + * Function provided by the resolver backend to set + * outgoing interface to use for DNS requests + */ +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf) +{ + (void)data; + (void)interf; + return CURLE_NOT_BUILT_IN; +} + +/* + * Function provided by the resolver backend to set + * local IPv4 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4) +{ + (void)data; + (void)local_ip4; + return CURLE_NOT_BUILT_IN; +} + +/* + * Function provided by the resolver backend to set + * local IPv6 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6) +{ + (void)data; + (void)local_ip6; + return CURLE_NOT_BUILT_IN; +} + +#endif /* truly sync */ diff --git a/libcurl/lib/http.c b/libcurl/lib/http.c new file mode 100644 index 0000000..f6b8296 --- /dev/null +++ b/libcurl/lib/http.c @@ -0,0 +1,4110 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "formdata.h" +#include "mime.h" +#include "progress.h" +#include "curl_base64.h" +#include "cookie.h" +#include "vauth/vauth.h" +#include "vtls/vtls.h" +#include "http_digest.h" +#include "http_ntlm.h" +#include "curl_ntlm_wb.h" +#include "http_negotiate.h" +#include "url.h" +#include "share.h" +#include "hostip.h" +#include "http.h" +#include "select.h" +#include "parsedate.h" /* for the week day and month names */ +#include "strtoofft.h" +#include "multiif.h" +#include "strcase.h" +#include "content_encoding.h" +#include "http_proxy.h" +#include "warnless.h" +#include "non-ascii.h" +#include "http2.h" +#include "connect.h" +#include "strdup.h" +#include "altsvc.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Forward declarations. + */ + +static int http_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +static int http_should_fail(struct connectdata *conn); + +#ifndef CURL_DISABLE_PROXY +static CURLcode add_haproxy_protocol_header(struct connectdata *conn); +#endif + +#ifdef USE_SSL +static CURLcode https_connecting(struct connectdata *conn, bool *done); +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +#else +#define https_connecting(x,y) CURLE_COULDNT_CONNECT +#endif +static CURLcode http_setup_conn(struct connectdata *conn); + +/* + * HTTP handler interface. + */ +const struct Curl_handler Curl_handler_http = { + "HTTP", /* scheme */ + http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + Curl_http_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_CREDSPERREQUEST /* flags */ +}; + +#ifdef USE_SSL +/* + * HTTPS handler interface. + */ +const struct Curl_handler Curl_handler_https = { + "HTTPS", /* scheme */ + http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + Curl_http_connect, /* connect_it */ + https_connecting, /* connecting */ + ZERO_NULL, /* doing */ + https_getsock, /* proto_getsock */ + http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_HTTPS, /* defport */ + CURLPROTO_HTTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */ +}; +#endif + +static CURLcode http_setup_conn(struct connectdata *conn) +{ + /* allocate the HTTP-specific struct for the Curl_easy, only to survive + during this request */ + struct HTTP *http; + struct Curl_easy *data = conn->data; + DEBUGASSERT(data->req.protop == NULL); + + http = calloc(1, sizeof(struct HTTP)); + if(!http) + return CURLE_OUT_OF_MEMORY; + + Curl_mime_initpart(&http->form, conn->data); + data->req.protop = http; + + if(!CONN_INUSE(conn)) + /* if not already multi-using, setup connection details */ + Curl_http2_setup_conn(conn); + Curl_http2_setup_req(data); + return CURLE_OK; +} + +#ifndef CURL_DISABLE_PROXY +/* + * checkProxyHeaders() checks the linked list of custom proxy headers + * if proxy headers are not available, then it will lookup into http header + * link list + * + * It takes a connectdata struct as input instead of the Curl_easy simply to + * know if this is a proxy request or not, as it then might check a different + * header list. Provide the header prefix without colon!. + */ +char *Curl_checkProxyheaders(const struct connectdata *conn, + const char *thisheader) +{ + struct curl_slist *head; + size_t thislen = strlen(thisheader); + struct Curl_easy *data = conn->data; + + for(head = (conn->bits.proxy && data->set.sep_headers) ? + data->set.proxyheaders : data->set.headers; + head; head = head->next) { + if(strncasecompare(head->data, thisheader, thislen) && + Curl_headersep(head->data[thislen])) + return head->data; + } + + return NULL; +} +#else +/* disabled */ +#define Curl_checkProxyheaders(x,y) NULL +#endif + +/* + * Strip off leading and trailing whitespace from the value in the + * given HTTP header line and return a strdupped copy. Returns NULL in + * case of allocation failure. Returns an empty string if the header value + * consists entirely of whitespace. + */ +char *Curl_copy_header_value(const char *header) +{ + const char *start; + const char *end; + char *value; + size_t len; + + /* Find the end of the header name */ + while(*header && (*header != ':')) + ++header; + + if(*header) + /* Skip over colon */ + ++header; + + /* Find the first non-space letter */ + start = header; + while(*start && ISSPACE(*start)) + start++; + + /* data is in the host encoding so + use '\r' and '\n' instead of 0x0d and 0x0a */ + end = strchr(start, '\r'); + if(!end) + end = strchr(start, '\n'); + if(!end) + end = strchr(start, '\0'); + if(!end) + return NULL; + + /* skip all trailing space letters */ + while((end > start) && ISSPACE(*end)) + end--; + + /* get length of the type */ + len = end - start + 1; + + value = malloc(len + 1); + if(!value) + return NULL; + + memcpy(value, start, len); + value[len] = 0; /* zero terminate */ + + return value; +} + +#ifndef CURL_DISABLE_HTTP_AUTH +/* + * http_output_basic() sets up an Authorization: header (or the proxy version) + * for HTTP Basic authentication. + * + * Returns CURLcode. + */ +static CURLcode http_output_basic(struct connectdata *conn, bool proxy) +{ + size_t size = 0; + char *authorization = NULL; + struct Curl_easy *data = conn->data; + char **userp; + const char *user; + const char *pwd; + CURLcode result; + char *out; + + if(proxy) { + userp = &conn->allocptr.proxyuserpwd; + user = conn->http_proxy.user; + pwd = conn->http_proxy.passwd; + } + else { + userp = &conn->allocptr.userpwd; + user = conn->user; + pwd = conn->passwd; + } + + out = aprintf("%s:%s", user, pwd); + if(!out) + return CURLE_OUT_OF_MEMORY; + + result = Curl_base64_encode(data, out, strlen(out), &authorization, &size); + if(result) + goto fail; + + if(!authorization) { + result = CURLE_REMOTE_ACCESS_DENIED; + goto fail; + } + + free(*userp); + *userp = aprintf("%sAuthorization: Basic %s\r\n", + proxy ? "Proxy-" : "", + authorization); + free(authorization); + if(!*userp) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + fail: + free(out); + return result; +} + +/* + * http_output_bearer() sets up an Authorization: header + * for HTTP Bearer authentication. + * + * Returns CURLcode. + */ +static CURLcode http_output_bearer(struct connectdata *conn) +{ + char **userp; + CURLcode result = CURLE_OK; + + userp = &conn->allocptr.userpwd; + free(*userp); + *userp = aprintf("Authorization: Bearer %s\r\n", + conn->oauth_bearer); + + if(!*userp) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } + + fail: + return result; +} + +#endif + +/* pickoneauth() selects the most favourable authentication method from the + * ones available and the ones we want. + * + * return TRUE if one was picked + */ +static bool pickoneauth(struct auth *pick, unsigned long mask) +{ + bool picked; + /* only deal with authentication we want */ + unsigned long avail = pick->avail & pick->want & mask; + picked = TRUE; + + /* The order of these checks is highly relevant, as this will be the order + of preference in case of the existence of multiple accepted types. */ + if(avail & CURLAUTH_NEGOTIATE) + pick->picked = CURLAUTH_NEGOTIATE; + else if(avail & CURLAUTH_BEARER) + pick->picked = CURLAUTH_BEARER; + else if(avail & CURLAUTH_DIGEST) + pick->picked = CURLAUTH_DIGEST; + else if(avail & CURLAUTH_NTLM) + pick->picked = CURLAUTH_NTLM; + else if(avail & CURLAUTH_NTLM_WB) + pick->picked = CURLAUTH_NTLM_WB; + else if(avail & CURLAUTH_BASIC) + pick->picked = CURLAUTH_BASIC; + else { + pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */ + picked = FALSE; + } + pick->avail = CURLAUTH_NONE; /* clear it here */ + + return picked; +} + +/* + * http_perhapsrewind() + * + * If we are doing POST or PUT { + * If we have more data to send { + * If we are doing NTLM { + * Keep sending since we must not disconnect + * } + * else { + * If there is more than just a little data left to send, close + * the current connection by force. + * } + * } + * If we have sent any data { + * If we don't have track of all the data { + * call app to tell it to rewind + * } + * else { + * rewind internally so that the operation can restart fine + * } + * } + * } + */ +static CURLcode http_perhapsrewind(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct HTTP *http = data->req.protop; + curl_off_t bytessent; + curl_off_t expectsend = -1; /* default is unknown */ + + if(!http) + /* If this is still NULL, we have not reach very far and we can safely + skip this rewinding stuff */ + return CURLE_OK; + + switch(data->set.httpreq) { + case HTTPREQ_GET: + case HTTPREQ_HEAD: + return CURLE_OK; + default: + break; + } + + bytessent = data->req.writebytecount; + + if(conn->bits.authneg) { + /* This is a state where we are known to be negotiating and we don't send + any data then. */ + expectsend = 0; + } + else if(!conn->bits.protoconnstart) { + /* HTTP CONNECT in progress: there is no body */ + expectsend = 0; + } + else { + /* figure out how much data we are expected to send */ + switch(data->set.httpreq) { + case HTTPREQ_POST: + if(data->state.infilesize != -1) + expectsend = data->state.infilesize; + break; + case HTTPREQ_PUT: + if(data->state.infilesize != -1) + expectsend = data->state.infilesize; + break; + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + expectsend = http->postsize; + break; + default: + break; + } + } + + conn->bits.rewindaftersend = FALSE; /* default */ + + if((expectsend == -1) || (expectsend > bytessent)) { +#if defined(USE_NTLM) + /* There is still data left to send */ + if((data->state.authproxy.picked == CURLAUTH_NTLM) || + (data->state.authhost.picked == CURLAUTH_NTLM) || + (data->state.authproxy.picked == CURLAUTH_NTLM_WB) || + (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { + if(((expectsend - bytessent) < 2000) || + (conn->http_ntlm_state != NTLMSTATE_NONE) || + (conn->proxy_ntlm_state != NTLMSTATE_NONE)) { + /* The NTLM-negotiation has started *OR* there is just a little (<2K) + data left to send, keep on sending. */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return CURLE_OK; + } + + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; + + infof(data, "NTLM send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + (curl_off_t)(expectsend - bytessent)); + } +#endif +#if defined(USE_SPNEGO) + /* There is still data left to send */ + if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) || + (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) { + if(((expectsend - bytessent) < 2000) || + (conn->http_negotiate_state != GSS_AUTHNONE) || + (conn->proxy_negotiate_state != GSS_AUTHNONE)) { + /* The NEGOTIATE-negotiation has started *OR* + there is just a little (<2K) data left to send, keep on sending. */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return CURLE_OK; + } + + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; + + infof(data, "NEGOTIATE send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + (curl_off_t)(expectsend - bytessent)); + } +#endif + + /* This is not NEGOTIATE/NTLM or many bytes left to send: close */ + streamclose(conn, "Mid-auth HTTP and much data left to send"); + data->req.size = 0; /* don't download any more than 0 bytes */ + + /* There still is data left to send, but this connection is marked for + closure so we can safely do the rewind right now */ + } + + if(bytessent) + /* we rewind now at once since if we already sent something */ + return Curl_readrewind(conn); + + return CURLE_OK; +} + +/* + * Curl_http_auth_act() gets called when all HTTP headers have been received + * and it checks what authentication methods that are available and decides + * which one (if any) to use. It will set 'newurl' if an auth method was + * picked. + */ + +CURLcode Curl_http_auth_act(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + bool pickhost = FALSE; + bool pickproxy = FALSE; + CURLcode result = CURLE_OK; + unsigned long authmask = ~0ul; + + if(!conn->oauth_bearer) + authmask &= (unsigned long)~CURLAUTH_BEARER; + + if(100 <= data->req.httpcode && 199 >= data->req.httpcode) + /* this is a transient response code, ignore */ + return CURLE_OK; + + if(data->state.authproblem) + return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; + + if((conn->bits.user_passwd || conn->oauth_bearer) && + ((data->req.httpcode == 401) || + (conn->bits.authneg && data->req.httpcode < 300))) { + pickhost = pickoneauth(&data->state.authhost, authmask); + if(!pickhost) + data->state.authproblem = TRUE; + if(data->state.authhost.picked == CURLAUTH_NTLM && + conn->httpversion > 11) { + infof(data, "Forcing HTTP/1.1 for NTLM"); + connclose(conn, "Force HTTP/1.1 connection"); + conn->data->set.httpversion = CURL_HTTP_VERSION_1_1; + } + } + if(conn->bits.proxy_user_passwd && + ((data->req.httpcode == 407) || + (conn->bits.authneg && data->req.httpcode < 300))) { + pickproxy = pickoneauth(&data->state.authproxy, + authmask & ~CURLAUTH_BEARER); + if(!pickproxy) + data->state.authproblem = TRUE; + } + + if(pickhost || pickproxy) { + if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD) && + !conn->bits.rewindaftersend) { + result = http_perhapsrewind(conn); + if(result) + return result; + } + /* In case this is GSS auth, the newurl field is already allocated so + we must make sure to free it before allocating a new one. As figured + out in bug #2284386 */ + Curl_safefree(data->req.newurl); + data->req.newurl = strdup(data->change.url); /* clone URL */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + } + else if((data->req.httpcode < 300) && + (!data->state.authhost.done) && + conn->bits.authneg) { + /* no (known) authentication available, + authentication is not "done" yet and + no authentication seems to be required and + we didn't try HEAD or GET */ + if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { + data->req.newurl = strdup(data->change.url); /* clone URL */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authhost.done = TRUE; + } + } + if(http_should_fail(conn)) { + failf(data, "The requested URL returned error: %d", + data->req.httpcode); + result = CURLE_HTTP_RETURNED_ERROR; + } + + return result; +} + +#ifndef CURL_DISABLE_HTTP_AUTH +/* + * Output the correct authentication header depending on the auth type + * and whether or not it is to a proxy. + */ +static CURLcode +output_auth_headers(struct connectdata *conn, + struct auth *authstatus, + const char *request, + const char *path, + bool proxy) +{ + const char *auth = NULL; + CURLcode result = CURLE_OK; +//#if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO) + struct Curl_easy *data = conn->data; +//#endif + +#ifdef CURL_DISABLE_CRYPTO_AUTH + (void)request; + (void)path; +#endif + +#ifdef USE_SPNEGO + if(authstatus->picked == CURLAUTH_NEGOTIATE) { + auth = "Negotiate"; + result = Curl_output_negotiate(conn, proxy); + if(result) + return result; + } + else +#endif +#ifdef USE_NTLM + if(authstatus->picked == CURLAUTH_NTLM) { + auth = "NTLM"; + result = Curl_output_ntlm(conn, proxy); + if(result) + return result; + } + else +#endif +#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) + if(authstatus->picked == CURLAUTH_NTLM_WB) { + auth = "NTLM_WB"; + result = Curl_output_ntlm_wb(conn, proxy); + if(result) + return result; + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(authstatus->picked == CURLAUTH_DIGEST) { + auth = "Digest"; + result = Curl_output_digest(conn, + proxy, + (const unsigned char *)request, + (const unsigned char *)path); + if(result) + return result; + } + else +#endif + if(authstatus->picked == CURLAUTH_BASIC) { + /* Basic */ + if((proxy && conn->bits.proxy_user_passwd && + !Curl_checkProxyheaders(conn, "Proxy-authorization")) || + (!proxy && conn->bits.user_passwd && + !Curl_checkheaders(conn, "Authorization"))) { + auth = "Basic"; + result = http_output_basic(conn, proxy); + if(result) + return result; + } + + /* NOTE: this function should set 'done' TRUE, as the other auth + functions work that way */ + authstatus->done = TRUE; + } + if(authstatus->picked == CURLAUTH_BEARER) { + /* Bearer */ + if((!proxy && conn->oauth_bearer && + !Curl_checkheaders(conn, "Authorization:"))) { + auth = "Bearer"; + result = http_output_bearer(conn); + if(result) + return result; + } + + /* NOTE: this function should set 'done' TRUE, as the other auth + functions work that way */ + authstatus->done = TRUE; + } + + if(auth) { + infof(data, "%s auth using %s with user '%s'\n", + proxy ? "Proxy" : "Server", auth, + proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") : + (conn->user ? conn->user : "")); + authstatus->multipass = (!authstatus->done) ? TRUE : FALSE; + } + else + authstatus->multipass = FALSE; + + return CURLE_OK; +} + +/** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication + * method. conn->data->state.authdone is set to TRUE when authentication is + * done. + * + * @param conn all information about the current connection + * @param request pointer to the request keyword + * @param path pointer to the requested path; should include query part + * @param proxytunnel boolean if this is the request setting up a "proxy + * tunnel" + * + * @returns CURLcode + */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel) /* TRUE if this is the request setting + up the proxy tunnel */ +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct auth *authhost; + struct auth *authproxy; + + DEBUGASSERT(data); + + authhost = &data->state.authhost; + authproxy = &data->state.authproxy; + + if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || + conn->bits.user_passwd || conn->oauth_bearer) + /* continue please */; + else { + authhost->done = TRUE; + authproxy->done = TRUE; + return CURLE_OK; /* no authentication with no user or password */ + } + + if(authhost->want && !authhost->picked) + /* The app has selected one or more methods, but none has been picked + so far by a server round-trip. Then we set the picked one to the + want one, and if this is one single bit it'll be used instantly. */ + authhost->picked = authhost->want; + + if(authproxy->want && !authproxy->picked) + /* The app has selected one or more methods, but none has been picked so + far by a proxy round-trip. Then we set the picked one to the want one, + and if this is one single bit it'll be used instantly. */ + authproxy->picked = authproxy->want; + +#ifndef CURL_DISABLE_PROXY + /* Send proxy authentication header if needed */ + if(conn->bits.httpproxy && + (conn->bits.tunnel_proxy == (bit)proxytunnel)) { + result = output_auth_headers(conn, authproxy, request, path, TRUE); + if(result) + return result; + } + else +#else + (void)proxytunnel; +#endif /* CURL_DISABLE_PROXY */ + /* we have no proxy so let's pretend we're done authenticating + with it */ + authproxy->done = TRUE; + + /* To prevent the user+password to get sent to other than the original + host due to a location-follow, we do some weirdo checks here */ + if(!data->state.this_is_a_follow || + conn->bits.netrc || + !data->state.first_host || + data->set.allow_auth_to_other_hosts || + strcasecompare(data->state.first_host, conn->host.name)) { + result = output_auth_headers(conn, authhost, request, path, FALSE); + } + else + authhost->done = TRUE; + + return result; +} + +#else +/* when disabled */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel) +{ + (void)conn; + (void)request; + (void)path; + (void)proxytunnel; + return CURLE_OK; +} +#endif + +/* + * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: + * headers. They are dealt with both in the transfer.c main loop and in the + * proxy CONNECT loop. + */ + +CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, + const char *auth) /* the first non-space */ +{ + /* + * This resource requires authentication + */ + struct Curl_easy *data = conn->data; + +#ifdef USE_SPNEGO + curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state : + &conn->http_negotiate_state; +#endif + unsigned long *availp; + struct auth *authp; + + if(proxy) { + availp = &data->info.proxyauthavail; + authp = &data->state.authproxy; + } + else { + availp = &data->info.httpauthavail; + authp = &data->state.authhost; + } + + /* + * Here we check if we want the specific single authentication (using ==) and + * if we do, we initiate usage of it. + * + * If the provided authentication is wanted as one out of several accepted + * types (using &), we OR this authentication type to the authavail + * variable. + * + * Note: + * + * ->picked is first set to the 'want' value (one or more bits) before the + * request is sent, and then it is again set _after_ all response 401/407 + * headers have been received but then only to a single preferred method + * (bit). + */ + + while(*auth) { +#ifdef USE_SPNEGO + if(checkprefix("Negotiate", auth)) { + if((authp->avail & CURLAUTH_NEGOTIATE) || + Curl_auth_is_spnego_supported()) { + *availp |= CURLAUTH_NEGOTIATE; + authp->avail |= CURLAUTH_NEGOTIATE; + + if(authp->picked == CURLAUTH_NEGOTIATE) { + CURLcode result = Curl_input_negotiate(conn, proxy, auth); + if(!result) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->change.url); + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authproblem = FALSE; + /* we received a GSS auth token and we dealt with it fine */ + *negstate = GSS_AUTHRECV; + } + else + data->state.authproblem = TRUE; + } + } + } + else +#endif +#ifdef USE_NTLM + /* NTLM support requires the SSL crypto libs */ + if(checkprefix("NTLM", auth)) { + if((authp->avail & CURLAUTH_NTLM) || + (authp->avail & CURLAUTH_NTLM_WB) || + Curl_auth_is_ntlm_supported()) { + *availp |= CURLAUTH_NTLM; + authp->avail |= CURLAUTH_NTLM; + + if(authp->picked == CURLAUTH_NTLM || + authp->picked == CURLAUTH_NTLM_WB) { + /* NTLM authentication is picked and activated */ + CURLcode result = Curl_input_ntlm(conn, proxy, auth); + if(!result) { + data->state.authproblem = FALSE; +#ifdef NTLM_WB_ENABLED + if(authp->picked == CURLAUTH_NTLM_WB) { + *availp &= ~CURLAUTH_NTLM; + authp->avail &= ~CURLAUTH_NTLM; + *availp |= CURLAUTH_NTLM_WB; + authp->avail |= CURLAUTH_NTLM_WB; + + result = Curl_input_ntlm_wb(conn, proxy, auth); + if(result) { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } +#endif + } + else { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + } + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(checkprefix("Digest", auth)) { + if((authp->avail & CURLAUTH_DIGEST) != 0) + infof(data, "Ignoring duplicate digest auth header.\n"); + else if(Curl_auth_is_digest_supported()) { + CURLcode result; + + *availp |= CURLAUTH_DIGEST; + authp->avail |= CURLAUTH_DIGEST; + + /* We call this function on input Digest headers even if Digest + * authentication isn't activated yet, as we need to store the + * incoming data from this header in case we are going to use + * Digest */ + result = Curl_input_digest(conn, proxy, auth); + if(result) { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + } + else +#endif + if(checkprefix("Basic", auth)) { + *availp |= CURLAUTH_BASIC; + authp->avail |= CURLAUTH_BASIC; + if(authp->picked == CURLAUTH_BASIC) { + /* We asked for Basic authentication but got a 40X back + anyway, which basically means our name+password isn't + valid. */ + authp->avail = CURLAUTH_NONE; + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + else + if(checkprefix("Bearer", auth)) { + *availp |= CURLAUTH_BEARER; + authp->avail |= CURLAUTH_BEARER; + if(authp->picked == CURLAUTH_BEARER) { + /* We asked for Bearer authentication but got a 40X back + anyway, which basically means our token isn't valid. */ + authp->avail = CURLAUTH_NONE; + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + + /* there may be multiple methods on one line, so keep reading */ + while(*auth && *auth != ',') /* read up to the next comma */ + auth++; + if(*auth == ',') /* if we're on a comma, skip it */ + auth++; + while(*auth && ISSPACE(*auth)) + auth++; + } + + return CURLE_OK; +} + +/** + * http_should_fail() determines whether an HTTP response has gotten us + * into an error state or not. + * + * @param conn all information about the current connection + * + * @retval 0 communications should continue + * + * @retval 1 communications should not continue + */ +static int http_should_fail(struct connectdata *conn) +{ + struct Curl_easy *data; + int httpcode; + + DEBUGASSERT(conn); + data = conn->data; + DEBUGASSERT(data); + + httpcode = data->req.httpcode; + + /* + ** If we haven't been asked to fail on error, + ** don't fail. + */ + if(!data->set.http_fail_on_error) + return 0; + + /* + ** Any code < 400 is never terminal. + */ + if(httpcode < 400) + return 0; + + /* + ** Any code >= 400 that's not 401 or 407 is always + ** a terminal error + */ + if((httpcode != 401) && (httpcode != 407)) + return 1; + + /* + ** All we have left to deal with is 401 and 407 + */ + DEBUGASSERT((httpcode == 401) || (httpcode == 407)); + + /* + ** Examine the current authentication state to see if this + ** is an error. The idea is for this function to get + ** called after processing all the headers in a response + ** message. So, if we've been to asked to authenticate a + ** particular stage, and we've done it, we're OK. But, if + ** we're already completely authenticated, it's not OK to + ** get another 401 or 407. + ** + ** It is possible for authentication to go stale such that + ** the client needs to reauthenticate. Once that info is + ** available, use it here. + */ + + /* + ** Either we're not authenticating, or we're supposed to + ** be authenticating something else. This is an error. + */ + if((httpcode == 401) && !conn->bits.user_passwd) + return TRUE; + if((httpcode == 407) && !conn->bits.proxy_user_passwd) + return TRUE; + + return data->state.authproblem; +} + +/* + * readmoredata() is a "fread() emulation" to provide POST and/or request + * data. It is used when a huge POST is to be made and the entire chunk wasn't + * sent in the first send(). This function will then be called from the + * transfer.c loop when more data is to be sent to the peer. + * + * Returns the amount of bytes it filled the buffer with. + */ +static size_t readmoredata(char *buffer, + size_t size, + size_t nitems, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct HTTP *http = conn->data->req.protop; + size_t fullsize = size * nitems; + + if(!http->postsize) + /* nothing to return */ + return 0; + + /* make sure that a HTTP request is never sent away chunked! */ + conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; + + if(http->postsize <= (curl_off_t)fullsize) { + memcpy(buffer, http->postdata, (size_t)http->postsize); + fullsize = (size_t)http->postsize; + + if(http->backup.postsize) { + /* move backup data into focus and continue on that */ + http->postdata = http->backup.postdata; + http->postsize = http->backup.postsize; + conn->data->state.fread_func = http->backup.fread_func; + conn->data->state.in = http->backup.fread_in; + + http->sending++; /* move one step up */ + + http->backup.postsize = 0; + } + else + http->postsize = 0; + + return fullsize; + } + + memcpy(buffer, http->postdata, fullsize); + http->postdata += fullsize; + http->postsize -= fullsize; + + return fullsize; +} + +/* ------------------------------------------------------------------------- */ +/* add_buffer functions */ + +/* + * Curl_add_buffer_init() sets up and returns a fine buffer struct + */ +Curl_send_buffer *Curl_add_buffer_init(void) +{ + return calloc(1, sizeof(Curl_send_buffer)); +} + +/* + * Curl_add_buffer_free() frees all associated resources. + */ +void Curl_add_buffer_free(Curl_send_buffer **inp) +{ + Curl_send_buffer *in = *inp; + if(in) /* deal with NULL input */ + free(in->buffer); + free(in); + *inp = NULL; +} + +/* + * Curl_add_buffer_send() sends a header buffer and frees all associated + * memory. Body data may be appended to the header data if desired. + * + * Returns CURLcode + */ +CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, + struct connectdata *conn, + + /* add the number of sent bytes to this + counter */ + curl_off_t *bytes_written, + + /* how much of the buffer contains body data */ + size_t included_body_bytes, + int socketindex) +{ + ssize_t amount; + CURLcode result; + char *ptr; + size_t size; + struct Curl_easy *data = conn->data; + struct HTTP *http = data->req.protop; + size_t sendsize; + curl_socket_t sockfd; + size_t headersize; + Curl_send_buffer *in = *inp; + + DEBUGASSERT(socketindex <= SECONDARYSOCKET); + + sockfd = conn->sock[socketindex]; + + /* The looping below is required since we use non-blocking sockets, but due + to the circumstances we will just loop and try again and again etc */ + + ptr = in->buffer; + size = in->size_used; + + headersize = size - included_body_bytes; /* the initial part that isn't body + is header */ + + DEBUGASSERT(size > included_body_bytes); + + result = Curl_convert_to_network(data, ptr, headersize); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) { + /* conversion failed, free memory and return to the caller */ + Curl_add_buffer_free(inp); + return result; + } + + if((conn->handler->flags & PROTOPT_SSL || + conn->http_proxy.proxytype == CURLPROXY_HTTPS) + && conn->httpversion != 20) { + /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk + when we speak HTTPS, as if only a fraction of it is sent now, this data + needs to fit into the normal read-callback buffer later on and that + buffer is using this size. + */ + + sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE); + + /* OpenSSL is very picky and we must send the SAME buffer pointer to the + library when we attempt to re-send this buffer. Sending the same data + is not enough, we must use the exact same address. For this reason, we + must copy the data to the uploadbuffer first, since that is the buffer + we will be using if this send is retried later. + */ + result = Curl_get_upload_buffer(data); + if(result) { + /* malloc failed, free memory and return to the caller */ + Curl_add_buffer_free(&in); + return result; + } + memcpy(data->state.ulbuf, ptr, sendsize); + ptr = data->state.ulbuf; + } + else + sendsize = size; + + result = Curl_write(conn, sockfd, ptr, sendsize, &amount); + + if(!result) { + /* + * Note that we may not send the entire chunk at once, and we have a set + * number of data bytes at the end of the big buffer (out of which we may + * only send away a part). + */ + /* how much of the header that was sent */ + size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount; + size_t bodylen = amount - headlen; + + if(data->set.verbose) { + /* this data _may_ contain binary stuff */ + Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen); + if(bodylen) { + /* there was body data sent beyond the initial header part, pass that + on to the debug callback too */ + Curl_debug(data, CURLINFO_DATA_OUT, + ptr + headlen, bodylen); + } + } + + /* 'amount' can never be a very large value here so typecasting it so a + signed 31 bit value should not cause problems even if ssize_t is + 64bit */ + *bytes_written += (long)amount; + + if(http) { + /* if we sent a piece of the body here, up the byte counter for it + accordingly */ + data->req.writebytecount += bodylen; + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); + + if((size_t)amount != size) { + /* The whole request could not be sent in one system call. We must + queue it up and send it later when we get the chance. We must not + loop here and wait until it might work again. */ + + size -= amount; + + ptr = in->buffer + amount; + + /* backup the currently set pointers */ + http->backup.fread_func = data->state.fread_func; + http->backup.fread_in = data->state.in; + http->backup.postdata = http->postdata; + http->backup.postsize = http->postsize; + + /* set the new pointers for the request-sending */ + data->state.fread_func = (curl_read_callback)readmoredata; + data->state.in = (void *)conn; + http->postdata = ptr; + http->postsize = (curl_off_t)size; + + http->send_buffer = in; + http->sending = HTTPSEND_REQUEST; + + return CURLE_OK; + } + http->sending = HTTPSEND_BODY; + /* the full buffer was sent, clean up and return */ + } + else { + if((size_t)amount != size) + /* We have no continue-send mechanism now, fail. This can only happen + when this function is used from the CONNECT sending function. We + currently (stupidly) assume that the whole request is always sent + away in the first single chunk. + + This needs FIXing. + */ + return CURLE_SEND_ERROR; + } + } + Curl_add_buffer_free(&in); + + return result; +} + + +/* + * add_bufferf() add the formatted input to the buffer. + */ +CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...) +{ + char *s; + va_list ap; + Curl_send_buffer *in = *inp; + va_start(ap, fmt); + s = vaprintf(fmt, ap); /* this allocs a new string to append */ + va_end(ap); + + if(s) { + CURLcode result = Curl_add_buffer(inp, s, strlen(s)); + free(s); + return result; + } + /* If we failed, we cleanup the whole buffer and return error */ + free(in->buffer); + free(in); + *inp = NULL; + return CURLE_OUT_OF_MEMORY; +} + +/* + * Curl_add_buffer() appends a memory chunk to the existing buffer + */ +CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr, + size_t size) +{ + char *new_rb; + Curl_send_buffer *in = *inp; + + if(~size < in->size_used) { + /* If resulting used size of send buffer would wrap size_t, cleanup + the whole buffer and return error. Otherwise the required buffer + size will fit into a single allocatable memory chunk */ + Curl_safefree(in->buffer); + free(in); + *inp = NULL; + return CURLE_OUT_OF_MEMORY; + } + + if(!in->buffer || + ((in->size_used + size) > (in->size_max - 1))) { + /* If current buffer size isn't enough to hold the result, use a + buffer size that doubles the required size. If this new size + would wrap size_t, then just use the largest possible one */ + size_t new_size; + + if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) || + (~(size * 2) < (in->size_used * 2))) + new_size = (size_t)-1; + else + new_size = (in->size_used + size) * 2; + + if(in->buffer) + /* we have a buffer, enlarge the existing one */ + new_rb = Curl_saferealloc(in->buffer, new_size); + else + /* create a new buffer */ + new_rb = malloc(new_size); + + if(!new_rb) { + /* If we failed, we cleanup the whole buffer and return error */ + free(in); + *inp = NULL; + return CURLE_OUT_OF_MEMORY; + } + + in->buffer = new_rb; + in->size_max = new_size; + } + memcpy(&in->buffer[in->size_used], inptr, size); + + in->size_used += size; + + return CURLE_OK; +} + +/* end of the add_buffer functions */ +/* ------------------------------------------------------------------------- */ + + + +/* + * Curl_compareheader() + * + * Returns TRUE if 'headerline' contains the 'header' with given 'content'. + * Pass headers WITH the colon. + */ +bool +Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const char *content) /* content string to find */ +{ + /* RFC2616, section 4.2 says: "Each header field consists of a name followed + * by a colon (":") and the field value. Field names are case-insensitive. + * The field value MAY be preceded by any amount of LWS, though a single SP + * is preferred." */ + + size_t hlen = strlen(header); + size_t clen; + size_t len; + const char *start; + const char *end; + + if(!strncasecompare(headerline, header, hlen)) + return FALSE; /* doesn't start with header */ + + /* pass the header */ + start = &headerline[hlen]; + + /* pass all white spaces */ + while(*start && ISSPACE(*start)) + start++; + + /* find the end of the header line */ + end = strchr(start, '\r'); /* lines end with CRLF */ + if(!end) { + /* in case there's a non-standard compliant line here */ + end = strchr(start, '\n'); + + if(!end) + /* hm, there's no line ending here, use the zero byte! */ + end = strchr(start, '\0'); + } + + len = end-start; /* length of the content part of the input line */ + clen = strlen(content); /* length of the word to find */ + + /* find the content string in the rest of the line */ + for(; len >= clen; len--, start++) { + if(strncasecompare(start, content, clen)) + return TRUE; /* match! */ + } + + return FALSE; /* no match */ +} + +/* + * Curl_http_connect() performs HTTP stuff to do at connect-time, called from + * the generic Curl_connect(). + */ +CURLcode Curl_http_connect(struct connectdata *conn, bool *done) +{ + CURLcode result; + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "HTTP default"); + + /* the CONNECT procedure might not have been completed */ + result = Curl_proxy_connect(conn, FIRSTSOCKET); + if(result) + return result; + + if(conn->bits.proxy_connect_closed) + /* this is not an error, just part of the connection negotiation */ + return CURLE_OK; + + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */ + + if(Curl_connect_ongoing(conn)) + /* nothing else to do except wait right now - we're not done here. */ + return CURLE_OK; + +#ifndef CURL_DISABLE_PROXY + if(conn->data->set.haproxyprotocol) { + /* add HAProxy PROXY protocol header */ + result = add_haproxy_protocol_header(conn); + if(result) + return result; + } +#endif + + if(conn->given->protocol & CURLPROTO_HTTPS) { + /* perform SSL initialization */ + result = https_connecting(conn, done); + if(result) + return result; + } + else + *done = TRUE; + + return CURLE_OK; +} + +/* this returns the socket to wait for in the DO and DOING state for the multi + interface and then we're always _sending_ a request and thus we wait for + the single socket to become writable only */ +static int http_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + /* write mode */ + (void)numsocks; /* unused, we trust it to be at least 1 */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); +} + +#ifndef CURL_DISABLE_PROXY +static CURLcode add_haproxy_protocol_header(struct connectdata *conn) +{ + char proxy_header[128]; + Curl_send_buffer *req_buffer; + CURLcode result; + char tcp_version[5]; + + /* Emit the correct prefix for IPv6 */ + if(conn->bits.ipv6) { + strcpy(tcp_version, "TCP6"); + } + else { + strcpy(tcp_version, "TCP4"); + } + + msnprintf(proxy_header, + sizeof(proxy_header), + "PROXY %s %s %s %li %li\r\n", + tcp_version, + conn->data->info.conn_local_ip, + conn->data->info.conn_primary_ip, + conn->data->info.conn_local_port, + conn->data->info.conn_primary_port); + + req_buffer = Curl_add_buffer_init(); + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + result = Curl_add_bufferf(&req_buffer, proxy_header); + if(result) + return result; + + result = Curl_add_buffer_send(&req_buffer, + conn, + &conn->data->info.request_size, + 0, + FIRSTSOCKET); + + return result; +} +#endif + +#ifdef USE_SSL +static CURLcode https_connecting(struct connectdata *conn, bool *done) +{ + CURLcode result; + DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL)); + + /* perform SSL initialization for this socket */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); + if(result) + connclose(conn, "Failed HTTPS connection"); + + return result; +} + +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn->handler->flags & PROTOPT_SSL) + return Curl_ssl_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} +#endif /* USE_SSL */ + +/* + * Curl_http_done() gets called after a single HTTP request has been + * performed. + */ + +CURLcode Curl_http_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct Curl_easy *data = conn->data; + struct HTTP *http = data->req.protop; + + /* Clear multipass flag. If authentication isn't done yet, then it will get + * a chance to be set back to true when we output the next auth header */ + data->state.authhost.multipass = FALSE; + data->state.authproxy.multipass = FALSE; + + Curl_unencode_cleanup(conn); + + /* set the proper values (possibly modified on POST) */ + conn->seek_func = data->set.seek_func; /* restore */ + conn->seek_client = data->set.seek_client; /* restore */ + + if(!http) + return CURLE_OK; + + if(http->send_buffer) { + Curl_add_buffer_free(&http->send_buffer); + } + + Curl_http2_done(conn, premature); + + Curl_mime_cleanpart(&http->form); + + if(status) + return status; + + if(!premature && /* this check is pointless when DONE is called before the + entire operation is complete */ + !conn->bits.retry && + !data->set.connect_only && + (data->req.bytecount + + data->req.headerbytecount - + data->req.deductheadercount) <= 0) { + /* If this connection isn't simply closed to be retried, AND nothing was + read from the HTTP server (that counts), this can't be right so we + return an error here */ + failf(data, "Empty reply from server"); + return CURLE_GOT_NOTHING; + } + + return CURLE_OK; +} + +/* + * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons + * to avoid it include: + * + * - if the user specifically requested HTTP 1.0 + * - if the server we are connected to only supports 1.0 + * - if any server previously contacted to handle this request only supports + * 1.0. + */ +static bool use_http_1_1plus(const struct Curl_easy *data, + const struct connectdata *conn) +{ + if((data->state.httpversion == 10) || (conn->httpversion == 10)) + return FALSE; + if((data->set.httpversion == CURL_HTTP_VERSION_1_0) && + (conn->httpversion <= 10)) + return FALSE; + return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) || + (data->set.httpversion >= CURL_HTTP_VERSION_1_1)); +} + +static const char *get_http_string(const struct Curl_easy *data, + const struct connectdata *conn) +{ +#ifdef USE_NGHTTP2 + if(conn->proto.httpc.h2) + return "2"; +#endif + + if(use_http_1_1plus(data, conn)) + return "1.1"; + + return "1.0"; +} + +/* check and possibly add an Expect: header */ +static CURLcode expect100(struct Curl_easy *data, + struct connectdata *conn, + Curl_send_buffer *req_buffer) +{ + CURLcode result = CURLE_OK; + data->state.expect100header = FALSE; /* default to false unless it is set + to TRUE below */ + if(use_http_1_1plus(data, conn) && + (conn->httpversion != 20)) { + /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an + Expect: 100-continue to the headers which actually speeds up post + operations (as there is one packet coming back from the web server) */ + const char *ptr = Curl_checkheaders(conn, "Expect"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else { + result = Curl_add_bufferf(&req_buffer, + "Expect: 100-continue\r\n"); + if(!result) + data->state.expect100header = TRUE; + } + } + + return result; +} + +enum proxy_use { + HEADER_SERVER, /* direct to server */ + HEADER_PROXY, /* regular request to proxy */ + HEADER_CONNECT /* sending CONNECT to a proxy */ +}; + +/* used to compile the provided trailers into one buffer + will return an error code if one of the headers is + not formatted correctly */ +CURLcode Curl_http_compile_trailers(struct curl_slist *trailers, + Curl_send_buffer *buffer, + struct Curl_easy *handle) +{ + char *ptr = NULL; + CURLcode result = CURLE_OK; + const char *endofline_native = NULL; + const char *endofline_network = NULL; + + if( +#ifdef CURL_DO_LINEEND_CONV + (handle->set.prefer_ascii) || +#endif + (handle->set.crlf)) { + /* \n will become \r\n later on */ + endofline_native = "\n"; + endofline_network = "\x0a"; + } + else { + endofline_native = "\r\n"; + endofline_network = "\x0d\x0a"; + } + + while(trailers) { + /* only add correctly formatted trailers */ + ptr = strchr(trailers->data, ':'); + if(ptr && *(ptr + 1) == ' ') { + result = Curl_add_bufferf(&buffer, "%s%s", trailers->data, + endofline_native); + if(result) + return result; + } + else + infof(handle, "Malformatted trailing header ! Skipping trailer."); + trailers = trailers->next; + } + result = Curl_add_buffer(&buffer, endofline_network, + strlen(endofline_network)); + return result; +} + +CURLcode Curl_add_custom_headers(struct connectdata *conn, + bool is_connect, + Curl_send_buffer *req_buffer) +{ + char *ptr; + struct curl_slist *h[2]; + struct curl_slist *headers; + int numlists = 1; /* by default */ + struct Curl_easy *data = conn->data; + int i; + + enum proxy_use proxy; + + if(is_connect) + proxy = HEADER_CONNECT; + else + proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy? + HEADER_PROXY:HEADER_SERVER; + + switch(proxy) { + case HEADER_SERVER: + h[0] = data->set.headers; + break; + case HEADER_PROXY: + h[0] = data->set.headers; + if(data->set.sep_headers) { + h[1] = data->set.proxyheaders; + numlists++; + } + break; + case HEADER_CONNECT: + if(data->set.sep_headers) + h[0] = data->set.proxyheaders; + else + h[0] = data->set.headers; + break; + } + + /* loop through one or two lists */ + for(i = 0; i < numlists; i++) { + headers = h[i]; + + while(headers) { + char *semicolonp = NULL; + ptr = strchr(headers->data, ':'); + if(!ptr) { + char *optr; + /* no colon, semicolon? */ + ptr = strchr(headers->data, ';'); + if(ptr) { + optr = ptr; + ptr++; /* pass the semicolon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr) { + /* this may be used for something else in the future */ + optr = NULL; + } + else { + if(*(--ptr) == ';') { + /* copy the source */ + semicolonp = strdup(headers->data); + if(!semicolonp) { + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + /* put a colon where the semicolon is */ + semicolonp[ptr - headers->data] = ':'; + /* point at the colon */ + optr = &semicolonp [ptr - headers->data]; + } + } + ptr = optr; + } + } + if(ptr) { + /* we require a colon for this to be a true header */ + + ptr++; /* pass the colon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr || semicolonp) { + /* only send this if the contents was non-blank or done special */ + CURLcode result = CURLE_OK; + char *compare = semicolonp ? semicolonp : headers->data; + + if(conn->allocptr.host && + /* a Host: header was sent already, don't pass on any custom Host: + header as that will produce *two* in the same request! */ + checkprefix("Host:", compare)) + ; + else if(data->set.httpreq == HTTPREQ_POST_FORM && + /* this header (extended by formdata.c) is sent later */ + checkprefix("Content-Type:", compare)) + ; + else if(data->set.httpreq == HTTPREQ_POST_MIME && + /* this header is sent later */ + checkprefix("Content-Type:", compare)) + ; + else if(conn->bits.authneg && + /* while doing auth neg, don't allow the custom length since + we will force length zero then */ + checkprefix("Content-Length:", compare)) + ; + else if(conn->allocptr.te && + /* when asking for Transfer-Encoding, don't pass on a custom + Connection: */ + checkprefix("Connection:", compare)) + ; + else if((conn->httpversion == 20) && + checkprefix("Transfer-Encoding:", compare)) + /* HTTP/2 doesn't support chunked requests */ + ; + else if((checkprefix("Authorization:", compare) || + checkprefix("Cookie:", compare)) && + /* be careful of sending this potentially sensitive header to + other hosts */ + (data->state.this_is_a_follow && + data->state.first_host && + !data->set.allow_auth_to_other_hosts && + !strcasecompare(data->state.first_host, conn->host.name))) + ; + else { + result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare); + } + if(semicolonp) + free(semicolonp); + if(result) + return result; + } + } + headers = headers->next; + } + } + + return CURLE_OK; +} + +#ifndef CURL_DISABLE_PARSEDATE +CURLcode Curl_add_timecondition(const struct connectdata *conn, + Curl_send_buffer *req_buffer) +{ + struct Curl_easy *data = conn->data; + const struct tm *tm; + struct tm keeptime; + CURLcode result; + char datestr[80]; + const char *condp; + + if(data->set.timecondition == CURL_TIMECOND_NONE) + /* no condition was asked for */ + return CURLE_OK; + + result = Curl_gmtime(data->set.timevalue, &keeptime); + if(result) { + failf(data, "Invalid TIMEVALUE"); + return result; + } + tm = &keeptime; + + switch(data->set.timecondition) { + default: + return CURLE_BAD_FUNCTION_ARGUMENT; + + case CURL_TIMECOND_IFMODSINCE: + condp = "If-Modified-Since"; + break; + case CURL_TIMECOND_IFUNMODSINCE: + condp = "If-Unmodified-Since"; + break; + case CURL_TIMECOND_LASTMOD: + condp = "Last-Modified"; + break; + } + + if(Curl_checkheaders(conn, condp)) { + /* A custom header was specified; it will be sent instead. */ + return CURLE_OK; + } + + /* The If-Modified-Since header family should have their times set in + * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be + * represented in Greenwich Mean Time (GMT), without exception. For the + * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal + * Time)." (see page 20 of RFC2616). + */ + + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + msnprintf(datestr, sizeof(datestr), + "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", + condp, + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + + result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr)); + + return result; +} +#else +/* disabled */ +CURLcode Curl_add_timecondition(const struct connectdata *conn, + Curl_send_buffer *req_buffer) +{ + (void)conn; + (void)req_buffer; + return CURLE_OK; +} +#endif + +/* + * Curl_http() gets called from the generic multi_do() function when a HTTP + * request is to be performed. This creates and sends a properly constructed + * HTTP request. + */ +CURLcode Curl_http(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + struct HTTP *http; + const char *path = data->state.up.path; + const char *query = data->state.up.query; + bool paste_ftp_userpwd = FALSE; + char ftp_typecode[sizeof("/;type=?")] = ""; + const char *host = conn->host.name; + const char *te = ""; /* transfer-encoding */ + const char *ptr; + const char *request; + Curl_HttpReq httpreq = data->set.httpreq; +#if !defined(CURL_DISABLE_COOKIES) + char *addcookies = NULL; +#endif + curl_off_t included_body = 0; + const char *httpstring; + Curl_send_buffer *req_buffer; + curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */ + + /* Always consider the DO phase done after this function call, even if there + may be parts of the request that is not yet sent, since we can deal with + the rest of the request in the PERFORM phase. */ + *done = TRUE; + + if(conn->httpversion < 20) { /* unless the connection is re-used and already + http2 */ + switch(conn->negnpn) { + case CURL_HTTP_VERSION_2: + conn->httpversion = 20; /* we know we're on HTTP/2 now */ + + result = Curl_http2_switched(conn, NULL, 0); + if(result) + return result; + break; + case CURL_HTTP_VERSION_1_1: + /* continue with HTTP/1.1 when explicitly requested */ + break; + default: + /* Check if user wants to use HTTP/2 with clear TCP*/ +#ifdef USE_NGHTTP2 + if(conn->data->set.httpversion == + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) { + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + /* We don't support HTTP/2 proxies yet. Also it's debatable whether + or not this setting should apply to HTTP/2 proxies. */ + infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n"); + break; + } + + DEBUGF(infof(data, "HTTP/2 over clean TCP\n")); + conn->httpversion = 20; + + result = Curl_http2_switched(conn, NULL, 0); + if(result) + return result; + } +#endif + break; + } + } + else { + /* prepare for a http2 request */ + result = Curl_http2_setup(conn); + if(result) + return result; + } + + http = data->req.protop; + DEBUGASSERT(http); + + if(!data->state.this_is_a_follow) { + /* Free to avoid leaking memory on multiple requests*/ + free(data->state.first_host); + + data->state.first_host = strdup(conn->host.name); + if(!data->state.first_host) + return CURLE_OUT_OF_MEMORY; + + data->state.first_remote_port = conn->remote_port; + } + + if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && + data->set.upload) { + httpreq = HTTPREQ_PUT; + } + + /* Now set the 'request' pointer to the proper request string */ + if(data->set.str[STRING_CUSTOMREQUEST]) + request = data->set.str[STRING_CUSTOMREQUEST]; + else { + if(data->set.opt_no_body) + request = "HEAD"; + else { + DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); + switch(httpreq) { + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + request = "POST"; + break; + case HTTPREQ_PUT: + request = "PUT"; + break; + case HTTPREQ_OPTIONS: + request = "OPTIONS"; + break; + default: /* this should never happen */ + case HTTPREQ_GET: + request = "GET"; + break; + case HTTPREQ_HEAD: + request = "HEAD"; + break; + } + } + } + + /* The User-Agent string might have been allocated in url.c already, because + it might have been used in the proxy connect, but if we have got a header + with the user-agent string specified, we erase the previously made string + here. */ + if(Curl_checkheaders(conn, "User-Agent")) { + free(conn->allocptr.uagent); + conn->allocptr.uagent = NULL; + } + + /* setup the authentication headers */ + { + char *pq = NULL; + if(query && *query) { + pq = aprintf("%s?%s", path, query); + if(!pq) + return CURLE_OUT_OF_MEMORY; + } + result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE); + free(pq); + if(result) + return result; + } + + if(((data->state.authhost.multipass && !data->state.authhost.done) + || (data->state.authproxy.multipass && !data->state.authproxy.done)) && + (httpreq != HTTPREQ_GET) && + (httpreq != HTTPREQ_HEAD)) { + /* Auth is required and we are not authenticated yet. Make a PUT or POST + with content-length zero as a "probe". */ + conn->bits.authneg = TRUE; + } + else + conn->bits.authneg = FALSE; + + Curl_safefree(conn->allocptr.ref); + if(data->change.referer && !Curl_checkheaders(conn, "Referer")) { + conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + if(!conn->allocptr.ref) + return CURLE_OUT_OF_MEMORY; + } + else + conn->allocptr.ref = NULL; + +#if !defined(CURL_DISABLE_COOKIES) + if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie")) + addcookies = data->set.str[STRING_COOKIE]; +#endif + + if(!Curl_checkheaders(conn, "Accept-Encoding") && + data->set.str[STRING_ENCODING]) { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = + aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); + if(!conn->allocptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; + } + else { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = NULL; + } + +#ifdef HAVE_LIBZ + /* we only consider transfer-encoding magic if libz support is built-in */ + + if(!Curl_checkheaders(conn, "TE") && + data->set.http_transfer_encoding) { + /* When we are to insert a TE: header in the request, we must also insert + TE in a Connection: header, so we need to merge the custom provided + Connection: header and prevent the original to get sent. Note that if + the user has inserted his/hers own TE: header we don't do this magic + but then assume that the user will handle it all! */ + char *cptr = Curl_checkheaders(conn, "Connection"); +#define TE_HEADER "TE: gzip\r\n" + + Curl_safefree(conn->allocptr.te); + + if(cptr) { + cptr = Curl_copy_header_value(cptr); + if(!cptr) + return CURLE_OUT_OF_MEMORY; + } + + /* Create the (updated) Connection: header */ + conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER, + cptr ? cptr : "", (cptr && *cptr) ? ", ":""); + + free(cptr); + if(!conn->allocptr.te) + return CURLE_OUT_OF_MEMORY; + } +#endif + + switch(httpreq) { + case HTTPREQ_POST_MIME: + http->sendit = &data->set.mimepost; + break; + case HTTPREQ_POST_FORM: + /* Convert the form structure into a mime structure. */ + Curl_mime_cleanpart(&http->form); + result = Curl_getformdata(data, &http->form, data->set.httppost, + data->state.fread_func); + if(result) + return result; + http->sendit = &http->form; + break; + default: + http->sendit = NULL; + } + +#ifndef CURL_DISABLE_MIME + if(http->sendit) { + const char *cthdr = Curl_checkheaders(conn, "Content-Type"); + + /* Read and seek body only. */ + http->sendit->flags |= MIME_BODY_ONLY; + + /* Prepare the mime structure headers & set content type. */ + + if(cthdr) + for(cthdr += 13; *cthdr == ' '; cthdr++) + ; + else if(http->sendit->kind == MIMEKIND_MULTIPART) + cthdr = "multipart/form-data"; + + curl_mime_headers(http->sendit, data->set.headers, 0); + result = Curl_mime_prepare_headers(http->sendit, cthdr, + NULL, MIMESTRATEGY_FORM); + curl_mime_headers(http->sendit, NULL, 0); + if(!result) + result = Curl_mime_rewind(http->sendit); + if(result) + return result; + http->postsize = Curl_mime_size(http->sendit); + } +#endif + + ptr = Curl_checkheaders(conn, "Transfer-Encoding"); + if(ptr) { + /* Some kind of TE is requested, check if 'chunked' is chosen */ + data->req.upload_chunky = + Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); + } + else { + if((conn->handler->protocol & PROTO_FAMILY_HTTP) && + (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) && + http->postsize < 0) || + (data->set.upload && data->state.infilesize == -1))) { + if(conn->bits.authneg) + /* don't enable chunked during auth neg */ + ; + else if(use_http_1_1plus(data, conn)) { + /* HTTP, upload, unknown file size and not HTTP 1.0 */ + data->req.upload_chunky = TRUE; + } + else { + failf(data, "Chunky upload is not supported by HTTP 1.0"); + return CURLE_UPLOAD_FAILED; + } + } + else { + /* else, no chunky upload */ + data->req.upload_chunky = FALSE; + } + + if(data->req.upload_chunky) + te = "Transfer-Encoding: chunked\r\n"; + } + + Curl_safefree(conn->allocptr.host); + + ptr = Curl_checkheaders(conn, "Host"); + if(ptr && (!data->state.this_is_a_follow || + strcasecompare(data->state.first_host, conn->host.name))) { +#if !defined(CURL_DISABLE_COOKIES) + /* If we have a given custom Host: header, we extract the host name in + order to possibly use it for cookie reasons later on. We only allow the + custom Host: header if this is NOT a redirect, as setting Host: in the + redirected request is being out on thin ice. Except if the host name + is the same as the first one! */ + char *cookiehost = Curl_copy_header_value(ptr); + if(!cookiehost) + return CURLE_OUT_OF_MEMORY; + if(!*cookiehost) + /* ignore empty data */ + free(cookiehost); + else { + /* If the host begins with '[', we start searching for the port after + the bracket has been closed */ + if(*cookiehost == '[') { + char *closingbracket; + /* since the 'cookiehost' is an allocated memory area that will be + freed later we cannot simply increment the pointer */ + memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1); + closingbracket = strchr(cookiehost, ']'); + if(closingbracket) + *closingbracket = 0; + } + else { + int startsearch = 0; + char *colon = strchr(cookiehost + startsearch, ':'); + if(colon) + *colon = 0; /* The host must not include an embedded port number */ + } + Curl_safefree(conn->allocptr.cookiehost); + conn->allocptr.cookiehost = cookiehost; + } +#endif + + if(strcmp("Host:", ptr)) { + conn->allocptr.host = aprintf("Host:%s\r\n", &ptr[5]); + if(!conn->allocptr.host) + return CURLE_OUT_OF_MEMORY; + } + else + /* when clearing the header */ + conn->allocptr.host = NULL; + } + else { + /* When building Host: headers, we must put the host name within + [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ + + if(((conn->given->protocol&CURLPROTO_HTTPS) && + (conn->remote_port == PORT_HTTPS)) || + ((conn->given->protocol&CURLPROTO_HTTP) && + (conn->remote_port == PORT_HTTP)) ) + /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include + the port number in the host string */ + conn->allocptr.host = aprintf("Host: %s%s%s\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":""); + else + conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":"", + conn->remote_port); + + if(!conn->allocptr.host) + /* without Host: we can't make a nice request */ + return CURLE_OUT_OF_MEMORY; + } + +#ifndef CURL_DISABLE_PROXY + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + /* Using a proxy but does not tunnel through it */ + + /* The path sent to the proxy is in fact the entire URL. But if the remote + host is a IDN-name, we must make sure that the request we produce only + uses the encoded host name! */ + + /* and no fragment part */ + CURLUcode uc; + char *url; + CURLU *h = curl_url_dup(data->state.uh); + if(!h) + return CURLE_OUT_OF_MEMORY; + + if(conn->host.dispname != conn->host.name) { + uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + } + uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + + if(strcasecompare("http", data->state.up.scheme)) { + /* when getting HTTP, we don't want the userinfo the URL */ + uc = curl_url_set(h, CURLUPART_USER, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + } + /* now extract the new version of the URL */ + uc = curl_url_get(h, CURLUPART_URL, &url, 0); + if(uc) { + curl_url_cleanup(h); + return CURLE_OUT_OF_MEMORY; + } + + if(data->change.url_alloc) + free(data->change.url); + + data->change.url = url; + data->change.url_alloc = TRUE; + + curl_url_cleanup(h); + + if(strcasecompare("ftp", data->state.up.scheme)) { + if(data->set.proxy_transfer_mode) { + /* when doing ftp, append ;type= if not present */ + char *type = strstr(path, ";type="); + if(type && type[6] && type[7] == 0) { + switch(Curl_raw_toupper(type[6])) { + case 'A': + case 'D': + case 'I': + break; + default: + type = NULL; + } + } + if(!type) { + char *p = ftp_typecode; + /* avoid sending invalid URLs like ftp://example.com;type=i if the + * user specified ftp://example.com without the slash */ + if(!*data->state.up.path && path[strlen(path) - 1] != '/') { + *p++ = '/'; + } + msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c", + data->set.prefer_ascii ? 'a' : 'i'); + } + } + if(conn->bits.user_passwd && !conn->bits.userpwd_in_url) + paste_ftp_userpwd = TRUE; + } + } +#endif /* CURL_DISABLE_PROXY */ + + http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n"; + + if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) && + data->state.resume_from) { + /********************************************************************** + * Resuming upload in HTTP means that we PUT or POST and that we have + * got a resume_from value set. The resume value has already created + * a Range: header that will be passed along. We need to "fast forward" + * the file the given number of bytes and decrease the assume upload + * file size before we continue this venture in the dark lands of HTTP. + * Resuming mime/form posting at an offset > 0 has no sense and is ignored. + *********************************************************************/ + + if(data->state.resume_from < 0) { + /* + * This is meant to get the size of the present remote-file by itself. + * We don't support this now. Bail out! + */ + data->state.resume_from = 0; + } + + if(data->state.resume_from && !data->state.this_is_a_follow) { + /* do we still game? */ + + /* Now, let's read off the proper amount of bytes from the + input. */ + int seekerr = CURL_SEEKFUNC_CANTSEEK; + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_READ_ERROR; + } + /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + data->state.fread_func(data->state.buffer, 1, readthisamountnow, + data->state.in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T + " bytes from the input", passed); + return CURLE_READ_ERROR; + } + } while(passed < data->state.resume_from); + } + + /* now, decrease the size of the read */ + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; + + if(data->state.infilesize <= 0) { + failf(data, "File already completely uploaded"); + return CURLE_PARTIAL_FILE; + } + } + /* we've passed, proceed as normal */ + } + } + if(data->state.use_range) { + /* + * A range is selected. We use different headers whether we're downloading + * or uploading and we always let customized headers override our internal + * ones if any such are specified. + */ + if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && + !Curl_checkheaders(conn, "Range")) { + /* if a line like this was already allocated, free the previous one */ + free(conn->allocptr.rangeline); + conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", + data->state.range); + } + else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) && + !Curl_checkheaders(conn, "Content-Range")) { + + /* if a line like this was already allocated, free the previous one */ + free(conn->allocptr.rangeline); + + if(data->set.set_resume_from < 0) { + /* Upload resume was asked for, but we don't know the size of the + remote part so we tell the server (and act accordingly) that we + upload the whole file (again) */ + conn->allocptr.rangeline = + aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.infilesize - 1, data->state.infilesize); + + } + else if(data->state.resume_from) { + /* This is because "resume" was selected */ + curl_off_t total_expected_size = + data->state.resume_from + data->state.infilesize; + conn->allocptr.rangeline = + aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.range, total_expected_size-1, + total_expected_size); + } + else { + /* Range was selected and then we just pass the incoming range and + append total size */ + conn->allocptr.rangeline = + aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", + data->state.range, data->state.infilesize); + } + if(!conn->allocptr.rangeline) + return CURLE_OUT_OF_MEMORY; + } + } + + httpstring = get_http_string(data, conn); + + /* initialize a dynamic send-buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + /* add the main request stuff */ + /* GET/HEAD/POST/PUT */ + result = Curl_add_bufferf(&req_buffer, "%s ", request); + if(result) + return result; + + if(data->set.str[STRING_TARGET]) { + path = data->set.str[STRING_TARGET]; + query = NULL; + } + + /* url */ + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + char *url = data->change.url; + result = Curl_add_buffer(&req_buffer, url, strlen(url)); + } + else if(paste_ftp_userpwd) + result = Curl_add_bufferf(&req_buffer, "ftp://%s:%s@%s", + conn->user, conn->passwd, + path + sizeof("ftp://") - 1); + else { + result = Curl_add_buffer(&req_buffer, path, strlen(path)); + if(result) + return result; + if(query) + result = Curl_add_bufferf(&req_buffer, "?%s", query); + } + if(result) + return result; + + result = + Curl_add_bufferf(&req_buffer, + "%s" /* ftp typecode (;type=x) */ + " HTTP/%s\r\n" /* HTTP version */ + "%s" /* host */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + "%s" /* range */ + "%s" /* user agent */ + "%s" /* accept */ + "%s" /* TE: */ + "%s" /* accept-encoding */ + "%s" /* referer */ + "%s" /* Proxy-Connection */ + "%s",/* transfer-encoding */ + + ftp_typecode, + httpstring, + (conn->allocptr.host?conn->allocptr.host:""), + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + conn->allocptr.userpwd?conn->allocptr.userpwd:"", + (data->state.use_range && conn->allocptr.rangeline)? + conn->allocptr.rangeline:"", + (data->set.str[STRING_USERAGENT] && + *data->set.str[STRING_USERAGENT] && + conn->allocptr.uagent)? + conn->allocptr.uagent:"", + http->p_accept?http->p_accept:"", + conn->allocptr.te?conn->allocptr.te:"", + (data->set.str[STRING_ENCODING] && + *data->set.str[STRING_ENCODING] && + conn->allocptr.accept_encoding)? + conn->allocptr.accept_encoding:"", + (data->change.referer && conn->allocptr.ref)? + conn->allocptr.ref:"" /* Referer: */, + (conn->bits.httpproxy && + !conn->bits.tunnel_proxy && + !Curl_checkProxyheaders(conn, "Proxy-Connection"))? + "Proxy-Connection: Keep-Alive\r\n":"", + te + ); + + /* clear userpwd and proxyuserpwd to avoid re-using old credentials + * from re-used connections */ + Curl_safefree(conn->allocptr.userpwd); + Curl_safefree(conn->allocptr.proxyuserpwd); + + if(result) + return result; + + if(!(conn->handler->flags&PROTOPT_SSL) && + conn->httpversion != 20 && + (data->set.httpversion == CURL_HTTP_VERSION_2)) { + /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done + over SSL */ + result = Curl_http2_request_upgrade(req_buffer, conn); + if(result) + return result; + } + +#if !defined(CURL_DISABLE_COOKIES) + if(data->cookies || addcookies) { + struct Cookie *co = NULL; /* no cookies from start */ + int count = 0; + + if(data->cookies) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + co = Curl_cookie_getlist(data->cookies, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:host, + data->state.up.path, + (conn->handler->protocol&CURLPROTO_HTTPS)? + TRUE:FALSE); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + if(co) { + struct Cookie *store = co; + /* now loop through all cookies that matched */ + while(co) { + if(co->value) { + if(0 == count) { + result = Curl_add_bufferf(&req_buffer, "Cookie: "); + if(result) + break; + } + result = Curl_add_bufferf(&req_buffer, + "%s%s=%s", count?"; ":"", + co->name, co->value); + if(result) + break; + count++; + } + co = co->next; /* next cookie please */ + } + Curl_cookie_freelist(store); + } + if(addcookies && !result) { + if(!count) + result = Curl_add_bufferf(&req_buffer, "Cookie: "); + if(!result) { + result = Curl_add_bufferf(&req_buffer, "%s%s", count?"; ":"", + addcookies); + count++; + } + } + if(count && !result) + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + + if(result) + return result; + } +#endif + + result = Curl_add_timecondition(conn, req_buffer); + if(result) + return result; + + result = Curl_add_custom_headers(conn, FALSE, req_buffer); + if(result) + return result; + + http->postdata = NULL; /* nothing to post at this point */ + Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */ + + /* If 'authdone' is FALSE, we must not set the write socket index to the + Curl_transfer() call below, as we're not ready to actually upload any + data yet. */ + + switch(httpreq) { + + case HTTPREQ_PUT: /* Let's PUT the data to the server! */ + + if(conn->bits.authneg) + postsize = 0; + else + postsize = data->state.infilesize; + + if((postsize != -1) && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { + /* only add Content-Length if not uploading chunked */ + result = Curl_add_bufferf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", postsize); + if(result) + return result; + } + + if(postsize != 0) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + + result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers */ + if(result) + return result; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize); + + /* this sends the buffer and frees all the buffer resources */ + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending PUT request"); + else + /* prepare for transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + postsize?FIRSTSOCKET:-1); + if(result) + return result; + break; + + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + /* This is form posting using mime data. */ + if(conn->bits.authneg) { + /* nothing to post! */ + result = Curl_add_bufferf(&req_buffer, "Content-Length: 0\r\n\r\n"); + if(result) + return result; + + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); + break; + } + + data->state.infilesize = postsize = http->postsize; + + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + if(postsize != -1 && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { + /* we allow replacing this header if not during auth negotiation, + although it isn't very wise to actually set your own */ + result = Curl_add_bufferf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", postsize); + if(result) + return result; + } + +#ifndef CURL_DISABLE_MIME + /* Output mime-generated headers. */ + { + struct curl_slist *hdr; + + for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) { + result = Curl_add_bufferf(&req_buffer, "%s\r\n", hdr->data); + if(result) + return result; + } + } +#endif + + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(conn, "Expect"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; + + /* make the request end in a true CRLF */ + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + if(result) + return result; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize); + + /* Read from mime structure. */ + data->state.fread_func = (curl_read_callback) Curl_mime_read; + data->state.in = (void *) http->sendit; + http->sending = HTTPSEND_BODY; + + /* this sends the buffer and frees all the buffer resources */ + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* prepare for transfer */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + postsize?FIRSTSOCKET:-1); + if(result) + return result; + + break; + + case HTTPREQ_POST: + /* this is the simple POST, using x-www-form-urlencoded style */ + + if(conn->bits.authneg) + postsize = 0; + else + /* the size of the post body */ + postsize = data->state.infilesize; + + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + if((postsize != -1) && !data->req.upload_chunky && + (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { + /* we allow replacing this header if not during auth negotiation, + although it isn't very wise to actually set your own */ + result = Curl_add_bufferf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T + "\r\n", postsize); + if(result) + return result; + } + + if(!Curl_checkheaders(conn, "Content-Type")) { + result = Curl_add_bufferf(&req_buffer, + "Content-Type: application/" + "x-www-form-urlencoded\r\n"); + if(result) + return result; + } + + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(conn, "Expect"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; + + if(data->set.postfields) { + + /* In HTTP2, we send request body in DATA frame regardless of + its size. */ + if(conn->httpversion != 20 && + !data->state.expect100header && + (postsize < MAX_INITIAL_POST_SIZE)) { + /* if we don't use expect: 100 AND + postsize is less than MAX_INITIAL_POST_SIZE + + then append the post data to the HTTP request header. This limit + is no magic limit but only set to prevent really huge POSTs to + get the data duplicated with malloc() and family. */ + + result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + + if(!data->req.upload_chunky) { + /* We're not sending it 'chunked', append it to the request + already now to reduce the number if send() calls */ + result = Curl_add_buffer(&req_buffer, data->set.postfields, + (size_t)postsize); + included_body = postsize; + } + else { + if(postsize) { + /* Append the POST data chunky-style */ + result = Curl_add_bufferf(&req_buffer, "%x\r\n", (int)postsize); + if(!result) { + result = Curl_add_buffer(&req_buffer, data->set.postfields, + (size_t)postsize); + if(!result) + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + included_body = postsize + 2; + } + } + if(!result) + result = Curl_add_buffer(&req_buffer, "\x30\x0d\x0a\x0d\x0a", 5); + /* 0 CR LF CR LF */ + included_body += 5; + } + if(result) + return result; + /* Make sure the progress information is accurate */ + Curl_pgrsSetUploadSize(data, postsize); + } + else { + /* A huge POST coming up, do data separate from the request */ + http->postsize = postsize; + http->postdata = data->set.postfields; + + http->sending = HTTPSEND_BODY; + + data->state.fread_func = (curl_read_callback)readmoredata; + data->state.in = (void *)conn; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); + + result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + } + } + else { + result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + + if(data->req.upload_chunky && conn->bits.authneg) { + /* Chunky upload is selected and we're negotiating auth still, send + end-of-data only */ + result = Curl_add_buffer(&req_buffer, + "\x30\x0d\x0a\x0d\x0a", 5); + /* 0 CR LF CR LF */ + if(result) + return result; + } + + else if(data->state.infilesize) { + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize?postsize:-1); + + /* set the pointer to mark that we will send the post body using the + read callback, but only if we're not in authenticate + negotiation */ + if(!conn->bits.authneg) { + http->postdata = (char *)&http->postdata; + http->postsize = postsize; + } + } + } + /* issue the request */ + result = Curl_add_buffer_send(&req_buffer, conn, &data->info.request_size, + (size_t)included_body, FIRSTSOCKET); + + if(result) + failf(data, "Failed sending HTTP POST request"); + else + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); + break; + + default: + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + if(result) + return result; + + /* issue the request */ + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + + if(result) + failf(data, "Failed sending HTTP request"); + else + /* HTTP GET/HEAD download: */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); + } + if(result) + return result; + + if(data->req.writebytecount) { + /* if a request-body has been sent off, we make sure this progress is noted + properly */ + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + + if(data->req.writebytecount >= postsize) { + /* already sent the entire request body, mark the "upload" as + complete */ + infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T + " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n", + data->req.writebytecount, postsize); + data->req.upload_done = TRUE; + data->req.keepon &= ~KEEP_SEND; /* we're done writing */ + data->req.exp100 = EXP100_SEND_DATA; /* already sent */ + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + } + } + + if((conn->httpversion == 20) && data->req.upload_chunky) + /* upload_chunky was set above to set up the request in a chunky fashion, + but is disabled here again to avoid that the chunked encoded version is + actually used when sending the request body over h2 */ + data->req.upload_chunky = FALSE; + return result; +} + +typedef enum { + STATUS_UNKNOWN, /* not enough data to tell yet */ + STATUS_DONE, /* a status line was read */ + STATUS_BAD /* not a status line */ +} statusline; + + +/* Check a string for a prefix. Check no more than 'len' bytes */ +static bool checkprefixmax(const char *prefix, const char *buffer, size_t len) +{ + size_t ch = CURLMIN(strlen(prefix), len); + return curl_strnequal(prefix, buffer, ch); +} + +/* + * checkhttpprefix() + * + * Returns TRUE if member of the list matches prefix of string + */ +static statusline +checkhttpprefix(struct Curl_easy *data, + const char *s, size_t len) +{ + struct curl_slist *head = data->set.http200aliases; + statusline rc = STATUS_BAD; + statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN; +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding using a scratch area */ + char *scratch = strdup(s); + if(NULL == scratch) { + failf(data, "Failed to allocate memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + } + if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(scratch); + return FALSE; /* can't return CURLE_foobar so return FALSE */ + } + s = scratch; +#endif /* CURL_DOES_CONVERSIONS */ + + while(head) { + if(checkprefixmax(head->data, s, len)) { + rc = onmatch; + break; + } + head = head->next; + } + + if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len))) + rc = onmatch; + +#ifdef CURL_DOES_CONVERSIONS + free(scratch); +#endif /* CURL_DOES_CONVERSIONS */ + return rc; +} + +#ifndef CURL_DISABLE_RTSP +static statusline +checkrtspprefix(struct Curl_easy *data, + const char *s, size_t len) +{ + statusline result = STATUS_BAD; + statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN; + +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding using a scratch area */ + char *scratch = strdup(s); + if(NULL == scratch) { + failf(data, "Failed to allocate memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + } + if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) { + /* Curl_convert_from_network calls failf if unsuccessful */ + result = FALSE; /* can't return CURLE_foobar so return FALSE */ + } + else if(checkprefixmax("RTSP/", scratch, len)) + result = onmatch; + free(scratch); +#else + (void)data; /* unused */ + if(checkprefixmax("RTSP/", s, len)) + result = onmatch; +#endif /* CURL_DOES_CONVERSIONS */ + + return result; +} +#endif /* CURL_DISABLE_RTSP */ + +static statusline +checkprotoprefix(struct Curl_easy *data, struct connectdata *conn, + const char *s, size_t len) +{ +#ifndef CURL_DISABLE_RTSP + if(conn->handler->protocol & CURLPROTO_RTSP) + return checkrtspprefix(data, s, len); +#else + (void)conn; +#endif /* CURL_DISABLE_RTSP */ + + return checkhttpprefix(data, s, len); +} + +/* + * header_append() copies a chunk of data to the end of the already received + * header. We make sure that the full string fit in the allocated header + * buffer, or else we enlarge it. + */ +static CURLcode header_append(struct Curl_easy *data, + struct SingleRequest *k, + size_t length) +{ + /* length is at most the size of a full read buffer, for which the upper + bound is CURL_MAX_READ_SIZE. There is thus no chance of overflow in this + calculation. */ + size_t newsize = k->hbuflen + length; + if(newsize > CURL_MAX_HTTP_HEADER) { + /* The reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause + reallocs infinitely */ + failf(data, "Rejected %zu bytes header (max is %d)!", newsize, + CURL_MAX_HTTP_HEADER); + return CURLE_OUT_OF_MEMORY; + } + if(newsize >= data->state.headersize) { + /* We enlarge the header buffer as it is too small */ + char *newbuff; + size_t hbufp_index; + + newsize = CURLMAX((k->hbuflen + length) * 3 / 2, data->state.headersize*2); + hbufp_index = k->hbufp - data->state.headerbuff; + newbuff = realloc(data->state.headerbuff, newsize); + if(!newbuff) { + failf(data, "Failed to alloc memory for big header!"); + return CURLE_OUT_OF_MEMORY; + } + data->state.headersize = newsize; + data->state.headerbuff = newbuff; + k->hbufp = data->state.headerbuff + hbufp_index; + } + memcpy(k->hbufp, k->str_start, length); + k->hbufp += length; + k->hbuflen += length; + *k->hbufp = 0; + + return CURLE_OK; +} + +static void print_http_error(struct Curl_easy *data) +{ + struct SingleRequest *k = &data->req; + char *beg = k->p; + + /* make sure that data->req.p points to the HTTP status line */ + if(!strncmp(beg, "HTTP", 4)) { + + /* skip to HTTP status code */ + beg = strchr(beg, ' '); + if(beg && *++beg) { + + /* find trailing CR */ + char end_char = '\r'; + char *end = strchr(beg, end_char); + if(!end) { + /* try to find LF (workaround for non-compliant HTTP servers) */ + end_char = '\n'; + end = strchr(beg, end_char); + } + + if(end) { + /* temporarily replace CR or LF by NUL and print the error message */ + *end = '\0'; + failf(data, "The requested URL returned error: %s", beg); + + /* restore the previously replaced CR or LF */ + *end = end_char; + return; + } + } + } + + /* fall-back to printing the HTTP status code only */ + failf(data, "The requested URL returned error: %d", k->httpcode); +} + +/* + * Read any HTTP header lines from the server and pass them to the client app. + */ +CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *stop_reading) +{ + CURLcode result; + struct SingleRequest *k = &data->req; + ssize_t onread = *nread; + char *ostr = k->str; + + /* header line within buffer loop */ + do { + size_t rest_length; + size_t full_length; + int writetype; + + /* str_start is start of line within buf */ + k->str_start = k->str; + + /* data is in network encoding so use 0x0a instead of '\n' */ + k->end_ptr = memchr(k->str_start, 0x0a, *nread); + + if(!k->end_ptr) { + /* Not a complete header line within buffer, append the data to + the end of the headerbuff. */ + result = header_append(data, k, *nread); + if(result) + return result; + + if(!k->headerline) { + /* check if this looks like a protocol header */ + statusline st = checkprotoprefix(data, conn, data->state.headerbuff, + k->hbuflen); + if(st == STATUS_BAD) { + /* this is not the beginning of a protocol first header line */ + k->header = FALSE; + k->badheader = HEADER_ALLBAD; + streamclose(conn, "bad HTTP: No end-of-message indicator"); + if(!data->set.http09_allowed) { + failf(data, "Received HTTP/0.9 when not allowed\n"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + break; + } + } + + break; /* read more and try again */ + } + + /* decrease the size of the remaining (supposed) header line */ + rest_length = (k->end_ptr - k->str) + 1; + *nread -= (ssize_t)rest_length; + + k->str = k->end_ptr + 1; /* move past new line */ + + full_length = k->str - k->str_start; + + result = header_append(data, k, full_length); + if(result) + return result; + + k->end_ptr = k->hbufp; + k->p = data->state.headerbuff; + + /**** + * We now have a FULL header line that p points to + *****/ + + if(!k->headerline) { + /* the first read header */ + statusline st = checkprotoprefix(data, conn, data->state.headerbuff, + k->hbuflen); + if(st == STATUS_BAD) { + streamclose(conn, "bad HTTP: No end-of-message indicator"); + /* this is not the beginning of a protocol first header line */ + if(!data->set.http09_allowed) { + failf(data, "Received HTTP/0.9 when not allowed\n"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + k->header = FALSE; + if(*nread) + /* since there's more, this is a partial bad header */ + k->badheader = HEADER_PARTHEADER; + else { + /* this was all we read so it's all a bad header */ + k->badheader = HEADER_ALLBAD; + *nread = onread; + k->str = ostr; + return CURLE_OK; + } + break; + } + } + + /* headers are in network encoding so + use 0x0a and 0x0d instead of '\n' and '\r' */ + if((0x0a == *k->p) || (0x0d == *k->p)) { + size_t headerlen; + /* Zero-length header line means end of headers! */ + +#ifdef CURL_DOES_CONVERSIONS + if(0x0d == *k->p) { + *k->p = '\r'; /* replace with CR in host encoding */ + k->p++; /* pass the CR byte */ + } + if(0x0a == *k->p) { + *k->p = '\n'; /* replace with LF in host encoding */ + k->p++; /* pass the LF byte */ + } +#else + if('\r' == *k->p) + k->p++; /* pass the \r byte */ + if('\n' == *k->p) + k->p++; /* pass the \n byte */ +#endif /* CURL_DOES_CONVERSIONS */ + + if(100 <= k->httpcode && 199 >= k->httpcode) { + /* "A user agent MAY ignore unexpected 1xx status responses." */ + switch(k->httpcode) { + case 100: + /* + * We have made a HTTP PUT or POST and this is 1.1-lingo + * that tells us that the server is OK with this and ready + * to receive the data. + * However, we'll get more headers now so we must get + * back into the header-parsing state! + */ + k->header = TRUE; + k->headerline = 0; /* restart the header line counter */ + + /* if we did wait for this do enable write now! */ + if(k->exp100 > EXP100_SEND_DATA) { + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + } + break; + case 101: + /* Switching Protocols */ + if(k->upgr101 == UPGR101_REQUESTED) { + /* Switching to HTTP/2 */ + infof(data, "Received 101\n"); + k->upgr101 = UPGR101_RECEIVED; + + /* we'll get more headers (HTTP/2 response) */ + k->header = TRUE; + k->headerline = 0; /* restart the header line counter */ + + /* switch to http2 now. The bytes after response headers + are also processed here, otherwise they are lost. */ + result = Curl_http2_switched(conn, k->str, *nread); + if(result) + return result; + *nread = 0; + } + else { + /* Switching to another protocol (e.g. WebSocket) */ + k->header = FALSE; /* no more header to parse! */ + } + break; + default: + /* the status code 1xx indicates a provisional response, so + we'll get another set of headers */ + k->header = TRUE; + k->headerline = 0; /* restart the header line counter */ + break; + } + } + else { + k->header = FALSE; /* no more header to parse! */ + + if((k->size == -1) && !k->chunk && !conn->bits.close && + (conn->httpversion == 11) && + !(conn->handler->protocol & CURLPROTO_RTSP) && + data->set.httpreq != HTTPREQ_HEAD) { + /* On HTTP 1.1, when connection is not to get closed, but no + Content-Length nor Transfer-Encoding chunked have been + received, according to RFC2616 section 4.4 point 5, we + assume that the server will close the connection to + signal the end of the document. */ + infof(data, "no chunk, no close, no size. Assume close to " + "signal end\n"); + streamclose(conn, "HTTP: No end-of-message indicator"); + } + } + + /* At this point we have some idea about the fate of the connection. + If we are closing the connection it may result auth failure. */ +#if defined(USE_NTLM) + if(conn->bits.close && + (((data->req.httpcode == 401) && + (conn->http_ntlm_state == NTLMSTATE_TYPE2)) || + ((data->req.httpcode == 407) && + (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) { + infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); + data->state.authproblem = TRUE; + } +#endif +#if defined(USE_SPNEGO) + if(conn->bits.close && + (((data->req.httpcode == 401) && + (conn->http_negotiate_state == GSS_AUTHRECV)) || + ((data->req.httpcode == 407) && + (conn->proxy_negotiate_state == GSS_AUTHRECV)))) { + infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); + data->state.authproblem = TRUE; + } + if((conn->http_negotiate_state == GSS_AUTHDONE) && + (data->req.httpcode != 401)) { + conn->http_negotiate_state = GSS_AUTHSUCC; + } + if((conn->proxy_negotiate_state == GSS_AUTHDONE) && + (data->req.httpcode != 407)) { + conn->proxy_negotiate_state = GSS_AUTHSUCC; + } +#endif + /* + * When all the headers have been parsed, see if we should give + * up and return an error. + */ + if(http_should_fail(conn)) { + failf(data, "The requested URL returned error: %d", + k->httpcode); + return CURLE_HTTP_RETURNED_ERROR; + } + + /* now, only output this if the header AND body are requested: + */ + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + headerlen = k->p - data->state.headerbuff; + + result = Curl_client_write(conn, writetype, + data->state.headerbuff, + headerlen); + if(result) + return result; + + data->info.header_size += (long)headerlen; + data->req.headerbytecount += (long)headerlen; + + data->req.deductheadercount = + (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0; + + /* Curl_http_auth_act() checks what authentication methods + * that are available and decides which one (if any) to + * use. It will set 'newurl' if an auth method was picked. */ + result = Curl_http_auth_act(conn); + + if(result) + return result; + + if(k->httpcode >= 300) { + if((!conn->bits.authneg) && !conn->bits.close && + !conn->bits.rewindaftersend) { + /* + * General treatment of errors when about to send data. Including : + * "417 Expectation Failed", while waiting for 100-continue. + * + * The check for close above is done simply because of something + * else has already deemed the connection to get closed then + * something else should've considered the big picture and we + * avoid this check. + * + * rewindaftersend indicates that something has told libcurl to + * continue sending even if it gets discarded + */ + + switch(data->set.httpreq) { + case HTTPREQ_PUT: + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + /* We got an error response. If this happened before the whole + * request body has been sent we stop sending and mark the + * connection for closure after we've read the entire response. + */ + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + if(!k->upload_done) { + if(data->set.http_keep_sending_on_error) { + infof(data, "HTTP error before end of send, keep sending\n"); + if(k->exp100 > EXP100_SEND_DATA) { + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + } + } + else { + infof(data, "HTTP error before end of send, stop sending\n"); + streamclose(conn, "Stop sending data before everything sent"); + result = Curl_done_sending(conn, k); + if(result) + return result; + k->upload_done = TRUE; + if(data->state.expect100header) + k->exp100 = EXP100_FAILED; + } + } + break; + + default: /* default label present to avoid compiler warnings */ + break; + } + } + + if(conn->bits.rewindaftersend) { + /* We rewind after a complete send, so thus we continue + sending now */ + infof(data, "Keep sending data to get tossed away!\n"); + k->keepon |= KEEP_SEND; + } + } + + if(!k->header) { + /* + * really end-of-headers. + * + * If we requested a "no body", this is a good time to get + * out and return home. + */ + if(data->set.opt_no_body) + *stop_reading = TRUE; +#ifndef CURL_DISABLE_RTSP + else if((conn->handler->protocol & CURLPROTO_RTSP) && + (data->set.rtspreq == RTSPREQ_DESCRIBE) && + (k->size <= -1)) + /* Respect section 4.4 of rfc2326: If the Content-Length header is + absent, a length 0 must be assumed. It will prevent libcurl from + hanging on DESCRIBE request that got refused for whatever + reason */ + *stop_reading = TRUE; +#endif + else { + /* If we know the expected size of this document, we set the + maximum download size to the size of the expected + document or else, we won't know when to stop reading! + + Note that we set the download maximum even if we read a + "Connection: close" header, to make sure that + "Content-Length: 0" still prevents us from attempting to + read the (missing) response-body. + */ + /* According to RFC2616 section 4.4, we MUST ignore + Content-Length: headers if we are now receiving data + using chunked Transfer-Encoding. + */ + if(k->chunk) + k->maxdownload = k->size = -1; + } + if(-1 != k->size) { + /* We do this operation even if no_body is true, since this + data might be retrieved later with curl_easy_getinfo() + and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */ + + Curl_pgrsSetDownloadSize(data, k->size); + k->maxdownload = k->size; + } + + /* If max download size is *zero* (nothing) we already have + nothing and can safely return ok now! But for HTTP/2, we'd + like to call http2_handle_stream_close to properly close a + stream. In order to do this, we keep reading until we + close the stream. */ + if(0 == k->maxdownload +#if defined(USE_NGHTTP2) + && !((conn->handler->protocol & PROTO_FAMILY_HTTP) && + conn->httpversion == 20) +#endif + ) + *stop_reading = TRUE; + + if(*stop_reading) { + /* we make sure that this socket isn't read more now */ + k->keepon &= ~KEEP_RECV; + } + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + k->str_start, headerlen); + break; /* exit header line loop */ + } + + /* We continue reading headers, so reset the line-based + header parsing variables hbufp && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + continue; + } + + /* + * Checks for special headers coming up. + */ + + if(!k->headerline++) { + /* This is the first header, it MUST be the error code line + or else we consider this to be the body right away! */ + int httpversion_major; + int rtspversion_major; + int nc = 0; +#ifdef CURL_DOES_CONVERSIONS +#define HEADER1 scratch +#define SCRATCHSIZE 21 + CURLcode res; + char scratch[SCRATCHSIZE + 1]; /* "HTTP/major.minor 123" */ + /* We can't really convert this yet because we + don't know if it's the 1st header line or the body. + So we do a partial conversion into a scratch area, + leaving the data at k->p as-is. + */ + strncpy(&scratch[0], k->p, SCRATCHSIZE); + scratch[SCRATCHSIZE] = 0; /* null terminate */ + res = Curl_convert_from_network(data, + &scratch[0], + SCRATCHSIZE); + if(res) + /* Curl_convert_from_network calls failf if unsuccessful */ + return res; +#else +#define HEADER1 k->p /* no conversion needed, just use k->p */ +#endif /* CURL_DOES_CONVERSIONS */ + + if(conn->handler->protocol & PROTO_FAMILY_HTTP) { + /* + * https://tools.ietf.org/html/rfc7230#section-3.1.2 + * + * The response code is always a three-digit number in HTTP as the spec + * says. We try to allow any number here, but we cannot make + * guarantees on future behaviors since it isn't within the protocol. + */ + char separator; + nc = sscanf(HEADER1, + " HTTP/%1d.%1d%c%3d", + &httpversion_major, + &conn->httpversion, + &separator, + &k->httpcode); + + if(nc == 1 && httpversion_major == 2 && + 1 == sscanf(HEADER1, " HTTP/2 %d", &k->httpcode)) { + conn->httpversion = 0; + nc = 4; + separator = ' '; + } + + if((nc == 4) && (' ' == separator)) { + conn->httpversion += 10 * httpversion_major; + + if(k->upgr101 == UPGR101_RECEIVED) { + /* supposedly upgraded to http2 now */ + if(conn->httpversion != 20) + infof(data, "Lying server, not serving HTTP/2\n"); + } + if(conn->httpversion < 20) { + conn->bundle->multiuse = BUNDLE_NO_MULTIUSE; + infof(data, "Mark bundle as not supporting multiuse\n"); + } + } + else if(!nc) { + /* this is the real world, not a Nirvana + NCSA 1.5.x returns this crap when asked for HTTP/1.1 + */ + nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode); + conn->httpversion = 10; + + /* If user has set option HTTP200ALIASES, + compare header line against list of aliases + */ + if(!nc) { + if(checkhttpprefix(data, k->p, k->hbuflen) == STATUS_DONE) { + nc = 1; + k->httpcode = 200; + conn->httpversion = 10; + } + } + } + else { + failf(data, "Unsupported HTTP version in response\n"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + } + else if(conn->handler->protocol & CURLPROTO_RTSP) { + char separator; + nc = sscanf(HEADER1, + " RTSP/%1d.%1d%c%3d", + &rtspversion_major, + &conn->rtspversion, + &separator, + &k->httpcode); + if((nc == 4) && (' ' == separator)) { + conn->rtspversion += 10 * rtspversion_major; + conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */ + } + else { + nc = 0; + } + } + + if(nc) { + data->info.httpcode = k->httpcode; + + data->info.httpversion = conn->httpversion; + if(!data->state.httpversion || + data->state.httpversion > conn->httpversion) + /* store the lowest server version we encounter */ + data->state.httpversion = conn->httpversion; + + /* + * This code executes as part of processing the header. As a + * result, it's not totally clear how to interpret the + * response code yet as that depends on what other headers may + * be present. 401 and 407 may be errors, but may be OK + * depending on how authentication is working. Other codes + * are definitely errors, so give up here. + */ + if(data->state.resume_from && data->set.httpreq == HTTPREQ_GET && + k->httpcode == 416) { + /* "Requested Range Not Satisfiable", just proceed and + pretend this is no error */ + k->ignorebody = TRUE; /* Avoid appending error msg to good data. */ + } + else if(data->set.http_fail_on_error && (k->httpcode >= 400) && + ((k->httpcode != 401) || !conn->bits.user_passwd) && + ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) { + /* serious error, go home! */ + print_http_error(data); + return CURLE_HTTP_RETURNED_ERROR; + } + + if(conn->httpversion == 10) { + /* Default action for HTTP/1.0 must be to close, unless + we get one of those fancy headers that tell us the + server keeps it open for us! */ + infof(data, "HTTP 1.0, assume close after body\n"); + connclose(conn, "HTTP/1.0 close after body"); + } + else if(conn->httpversion == 20 || + (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) { + DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n")); + + /* HTTP/2 cannot blacklist multiplexing since it is a core + functionality of the protocol */ + conn->bundle->multiuse = BUNDLE_MULTIPLEX; + } + else if(conn->httpversion >= 11 && + !conn->bits.close) { + /* If HTTP version is >= 1.1 and connection is persistent */ + DEBUGF(infof(data, + "HTTP 1.1 or later with persistent connection\n")); + } + + k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200; + switch(k->httpcode) { + case 304: + /* (quote from RFC2616, section 10.3.5): The 304 response + * MUST NOT contain a message-body, and thus is always + * terminated by the first empty line after the header + * fields. */ + if(data->set.timecondition) + data->info.timecond = TRUE; + /* FALLTHROUGH */ + case 204: + /* (quote from RFC2616, section 10.2.5): The server has + * fulfilled the request but does not need to return an + * entity-body ... The 204 response MUST NOT include a + * message-body, and thus is always terminated by the first + * empty line after the header fields. */ + k->size = 0; + k->maxdownload = 0; + k->http_bodyless = TRUE; + break; + default: + break; + } + } + else { + k->header = FALSE; /* this is not a header line */ + break; + } + } + + result = Curl_convert_from_network(data, k->p, strlen(k->p)); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + + /* Check for Content-Length: header lines to get size */ + if(!k->http_bodyless && + !data->set.ignorecl && checkprefix("Content-Length:", k->p)) { + curl_off_t contentlength; + CURLofft offt = curlx_strtoofft(k->p + 15, NULL, 10, &contentlength); + + if(offt == CURL_OFFT_OK) { + if(data->set.max_filesize && + contentlength > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + k->size = contentlength; + k->maxdownload = k->size; + /* we set the progress download size already at this point + just to make it easier for apps/callbacks to extract this + info as soon as possible */ + Curl_pgrsSetDownloadSize(data, k->size); + } + else if(offt == CURL_OFFT_FLOW) { + /* out of range */ + if(data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + streamclose(conn, "overflow content-length"); + infof(data, "Overflow Content-Length: value!\n"); + } + else { + /* negative or just rubbish - bad HTTP */ + failf(data, "Invalid Content-Length: value"); + return CURLE_WEIRD_SERVER_REPLY; + } + } + /* check for Content-Type: header lines to get the MIME-type */ + else if(checkprefix("Content-Type:", k->p)) { + char *contenttype = Curl_copy_header_value(k->p); + if(!contenttype) + return CURLE_OUT_OF_MEMORY; + if(!*contenttype) + /* ignore empty data */ + free(contenttype); + else { + Curl_safefree(data->info.contenttype); + data->info.contenttype = contenttype; + } + } + else if((conn->httpversion == 10) && + conn->bits.httpproxy && + Curl_compareheader(k->p, + "Proxy-Connection:", "keep-alive")) { + /* + * When a HTTP/1.0 reply comes when using a proxy, the + * 'Proxy-Connection: keep-alive' line tells us the + * connection will be kept alive for our pleasure. + * Default action for 1.0 is to close. + */ + connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */ + infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); + } + else if((conn->httpversion == 11) && + conn->bits.httpproxy && + Curl_compareheader(k->p, + "Proxy-Connection:", "close")) { + /* + * We get a HTTP/1.1 response from a proxy and it says it'll + * close down after this transfer. + */ + connclose(conn, "Proxy-Connection: asked to close after done"); + infof(data, "HTTP/1.1 proxy connection set close!\n"); + } + else if((conn->httpversion == 10) && + Curl_compareheader(k->p, "Connection:", "keep-alive")) { + /* + * A HTTP/1.0 reply with the 'Connection: keep-alive' line + * tells us the connection will be kept alive for our + * pleasure. Default action for 1.0 is to close. + * + * [RFC2068, section 19.7.1] */ + connkeep(conn, "Connection keep-alive"); + infof(data, "HTTP/1.0 connection set to keep alive!\n"); + } + else if(Curl_compareheader(k->p, "Connection:", "close")) { + /* + * [RFC 2616, section 8.1.2.1] + * "Connection: close" is HTTP/1.1 language and means that + * the connection will close when this request has been + * served. + */ + streamclose(conn, "Connection: close used"); + } + else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", k->p)) { + /* One or more encodings. We check for chunked and/or a compression + algorithm. */ + /* + * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding + * means that the server will send a series of "chunks". Each + * chunk starts with line with info (including size of the + * coming block) (terminated with CRLF), then a block of data + * with the previously mentioned size. There can be any amount + * of chunks, and a chunk-data set to zero signals the + * end-of-chunks. */ + + result = Curl_build_unencoding_stack(conn, k->p + 18, TRUE); + if(result) + return result; + } + else if(!k->http_bodyless && checkprefix("Content-Encoding:", k->p) && + data->set.str[STRING_ENCODING]) { + /* + * Process Content-Encoding. Look for the values: identity, + * gzip, deflate, compress, x-gzip and x-compress. x-gzip and + * x-compress are the same as gzip and compress. (Sec 3.5 RFC + * 2616). zlib cannot handle compress. However, errors are + * handled further down when the response body is processed + */ + result = Curl_build_unencoding_stack(conn, k->p + 17, FALSE); + if(result) + return result; + } + else if(!k->http_bodyless && checkprefix("Content-Range:", k->p)) { + /* Content-Range: bytes [num]- + Content-Range: bytes: [num]- + Content-Range: [num]- + Content-Range: [asterisk]/[total] + + The second format was added since Sun's webserver + JavaWebServer/1.1.1 obviously sends the header this way! + The third added since some servers use that! + The forth means the requested range was unsatisfied. + */ + + char *ptr = k->p + 14; + + /* Move forward until first digit or asterisk */ + while(*ptr && !ISDIGIT(*ptr) && *ptr != '*') + ptr++; + + /* if it truly stopped on a digit */ + if(ISDIGIT(*ptr)) { + if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) { + if(data->state.resume_from == k->offset) + /* we asked for a resume and we got it */ + k->content_range = TRUE; + } + } + else + data->state.resume_from = 0; /* get everything */ + } +#if !defined(CURL_DISABLE_COOKIES) + else if(data->cookies && + checkprefix("Set-Cookie:", k->p)) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, + CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_add(data, + data->cookies, TRUE, FALSE, k->p + 11, + /* If there is a custom-set Host: name, use it + here, or else use real peer host name. */ + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:conn->host.name, + data->state.up.path, + (conn->handler->protocol&CURLPROTO_HTTPS)? + TRUE:FALSE); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +#endif + else if(!k->http_bodyless && checkprefix("Last-Modified:", k->p) && + (data->set.timecondition || data->set.get_filetime) ) { + time_t secs = time(NULL); + k->timeofdoc = curl_getdate(k->p + strlen("Last-Modified:"), + &secs); + if(data->set.get_filetime) + data->info.filetime = k->timeofdoc; + } + else if((checkprefix("WWW-Authenticate:", k->p) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", k->p) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(k->p); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(conn, proxy, auth); + + free(auth); + + if(result) + return result; + } + #ifdef USE_SPNEGO + else if(checkprefix("Persistent-Auth", k->p)) { + struct negotiatedata *negdata = &conn->negotiate; + struct auth *authp = &data->state.authhost; + if(authp->picked == CURLAUTH_NEGOTIATE) { + char *persistentauth = Curl_copy_header_value(k->p); + if(!persistentauth) + return CURLE_OUT_OF_MEMORY; + negdata->noauthpersist = checkprefix("false", persistentauth); + negdata->havenoauthpersist = TRUE; + infof(data, "Negotiate: noauthpersist -> %d, header part: %s", + negdata->noauthpersist, persistentauth); + free(persistentauth); + } + } + #endif + else if((k->httpcode >= 300 && k->httpcode < 400) && + checkprefix("Location:", k->p) && + !data->req.location) { + /* this is the URL that the server advises us to use instead */ + char *location = Curl_copy_header_value(k->p); + if(!location) + return CURLE_OUT_OF_MEMORY; + if(!*location) + /* ignore empty data */ + free(location); + else { + data->req.location = location; + + if(data->set.http_follow_location) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->req.location); /* clone */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + + /* some cases of POST and PUT etc needs to rewind the data + stream at this point */ + result = http_perhapsrewind(conn); + if(result) + return result; + } + } + } +#ifdef USE_ALTSVC + /* If enabled, the header is incoming and this is over HTTPS */ + else if(data->asi && checkprefix("Alt-Svc:", k->p) && + ((conn->handler->flags & PROTOPT_SSL) || +#ifdef CURLDEBUG + /* allow debug builds to circumvent the HTTPS restriction */ + getenv("CURL_ALTSVC_HTTP") +#else + 0 +#endif + )) { + /* the ALPN of the current request */ + enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1; + result = Curl_altsvc_parse(data, data->asi, + &k->p[ strlen("Alt-Svc:") ], + id, conn->host.name, + curlx_uitous(conn->remote_port)); + if(result) + return result; + } +#endif + else if(conn->handler->protocol & CURLPROTO_RTSP) { + result = Curl_rtsp_parseheader(conn, k->p); + if(result) + return result; + } + + /* + * End of header-checks. Write them to the client. + */ + + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, k->p, (size_t)k->hbuflen); + + result = Curl_client_write(conn, writetype, k->p, k->hbuflen); + if(result) + return result; + + data->info.header_size += (long)k->hbuflen; + data->req.headerbytecount += (long)k->hbuflen; + + /* reset hbufp pointer && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + } + while(*k->str); /* header line within buffer */ + + /* We might have reached the end of the header part here, but + there might be a non-header part left in the end of the read + buffer. */ + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_HTTP */ diff --git a/libcurl/lib/http.h b/libcurl/lib/http.h new file mode 100644 index 0000000..72161f6 --- /dev/null +++ b/libcurl/lib/http.h @@ -0,0 +1,257 @@ +#ifndef HEADER_CURL_HTTP_H +#define HEADER_CURL_HTTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#ifdef USE_NGHTTP2 +#include +#endif + +extern const struct Curl_handler Curl_handler_http; + +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_https; +#endif + +/* Header specific functions */ +bool Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const char *content); /* content string to find */ + +char *Curl_copy_header_value(const char *header); + +char *Curl_checkProxyheaders(const struct connectdata *conn, + const char *thisheader); +/* ------------------------------------------------------------------------- */ +/* + * The add_buffer series of functions are used to build one large memory chunk + * from repeated function invokes. Used so that the entire HTTP request can + * be sent in one go. + */ +struct Curl_send_buffer { + char *buffer; + size_t size_max; + size_t size_used; +}; +typedef struct Curl_send_buffer Curl_send_buffer; + +Curl_send_buffer *Curl_add_buffer_init(void); +void Curl_add_buffer_free(Curl_send_buffer **inp); +CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...) + WARN_UNUSED_RESULT; +CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr, + size_t size) WARN_UNUSED_RESULT; +CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, + struct connectdata *conn, + curl_off_t *bytes_written, + size_t included_body_bytes, + int socketindex); + +CURLcode Curl_add_timecondition(const struct connectdata *conn, + Curl_send_buffer *buf); +CURLcode Curl_add_custom_headers(struct connectdata *conn, + bool is_connect, + Curl_send_buffer *req_buffer); +CURLcode Curl_http_compile_trailers(struct curl_slist *trailers, + Curl_send_buffer *buffer, + struct Curl_easy *handle); + +/* protocol-specific functions set up to be called by the main engine */ +CURLcode Curl_http(struct connectdata *conn, bool *done); +CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); +CURLcode Curl_http_connect(struct connectdata *conn, bool *done); + +/* The following functions are defined in http_chunks.c */ +void Curl_httpchunk_init(struct connectdata *conn); +CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, + ssize_t length, ssize_t *wrote); + +/* These functions are in http.c */ +CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, + const char *auth); +CURLcode Curl_http_auth_act(struct connectdata *conn); + +/* If only the PICKNONE bit is set, there has been a round-trip and we + selected to use no auth at all. Ie, we actively select no auth, as opposed + to not having one selected. The other CURLAUTH_* defines are present in the + public curl/curl.h header. */ +#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */ + +/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST + data get included in the initial data chunk sent to the server. If the + data is larger than this, it will automatically get split up in multiple + system calls. + + This value used to be fairly big (100K), but we must take into account that + if the server rejects the POST due for authentication reasons, this data + will always be unconditionally sent and thus it may not be larger than can + always be afforded to send twice. + + It must not be greater than 64K to work on VMS. +*/ +#ifndef MAX_INITIAL_POST_SIZE +#define MAX_INITIAL_POST_SIZE (64*1024) +#endif + +/* EXPECT_100_THRESHOLD is the request body size limit for when libcurl will + * automatically add an "Expect: 100-continue" header in HTTP requests. When + * the size is unknown, it will always add it. + * + */ +#ifndef EXPECT_100_THRESHOLD +#define EXPECT_100_THRESHOLD 1024 +#endif + +#endif /* CURL_DISABLE_HTTP */ + +/**************************************************************************** + * HTTP unique setup + ***************************************************************************/ +struct HTTP { + curl_mimepart *sendit; + curl_off_t postsize; /* off_t to handle large file sizes */ + const char *postdata; + + const char *p_pragma; /* Pragma: string */ + const char *p_accept; /* Accept: string */ + + /* For FORM posting */ + curl_mimepart form; + + struct back { + curl_read_callback fread_func; /* backup storage for fread pointer */ + void *fread_in; /* backup storage for fread_in pointer */ + const char *postdata; + curl_off_t postsize; + } backup; + + enum { + HTTPSEND_NADA, /* init */ + HTTPSEND_REQUEST, /* sending a request */ + HTTPSEND_BODY, /* sending body */ + HTTPSEND_LAST /* never use this */ + } sending; + +#ifndef CURL_DISABLE_HTTP + Curl_send_buffer *send_buffer; /* used if the request couldn't be sent in + one chunk, points to an allocated + send_buffer struct */ +#endif +#ifdef USE_NGHTTP2 + /*********** for HTTP/2 we store stream-local data here *************/ + int32_t stream_id; /* stream we are interested in */ + + bool bodystarted; + /* We store non-final and final response headers here, per-stream */ + Curl_send_buffer *header_recvbuf; + size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into + upper layer */ + Curl_send_buffer *trailer_recvbuf; + int status_code; /* HTTP status code */ + const uint8_t *pausedata; /* pointer to data received in on_data_chunk */ + size_t pauselen; /* the number of bytes left in data */ + bool closed; /* TRUE on HTTP2 stream close */ + bool close_handled; /* TRUE if stream closure is handled by libcurl */ + char *mem; /* points to a buffer in memory to store received data */ + size_t len; /* size of the buffer 'mem' points to */ + size_t memlen; /* size of data copied to mem */ + + const uint8_t *upload_mem; /* points to a buffer to read from */ + size_t upload_len; /* size of the buffer 'upload_mem' points to */ + curl_off_t upload_left; /* number of bytes left to upload */ + + char **push_headers; /* allocated array */ + size_t push_headers_used; /* number of entries filled in */ + size_t push_headers_alloc; /* number of entries allocated */ +#endif +}; + +#ifdef USE_NGHTTP2 +/* h2 settings for this connection */ +struct h2settings { + uint32_t max_concurrent_streams; + bool enable_push; +}; +#endif + +struct http_conn { +#ifdef USE_NGHTTP2 +#define H2_BINSETTINGS_LEN 80 + nghttp2_session *h2; + uint8_t binsettings[H2_BINSETTINGS_LEN]; + size_t binlen; /* length of the binsettings data */ + Curl_send *send_underlying; /* underlying send Curl_send callback */ + Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */ + char *inbuf; /* buffer to receive data from underlying socket */ + size_t inbuflen; /* number of bytes filled in inbuf */ + size_t nread_inbuf; /* number of bytes read from in inbuf */ + /* We need separate buffer for transmission and reception because we + may call nghttp2_session_send() after the + nghttp2_session_mem_recv() but mem buffer is still not full. In + this case, we wrongly sends the content of mem buffer if we share + them for both cases. */ + int32_t pause_stream_id; /* stream ID which paused + nghttp2_session_mem_recv */ + size_t drain_total; /* sum of all stream's UrlState.drain */ + + /* this is a hash of all individual streams (Curl_easy structs) */ + struct h2settings settings; + + /* list of settings that will be sent */ + nghttp2_settings_entry local_settings[3]; + size_t local_settings_num; + uint32_t error_code; /* HTTP/2 error code */ +#else + int unused; /* prevent a compiler warning */ +#endif +}; + +CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *stop_reading); + +/** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication + * method. conn->data->state.authdone is set to TRUE when authentication is + * done. + * + * @param conn all information about the current connection + * @param request pointer to the request keyword + * @param path pointer to the requested path + * @param proxytunnel boolean if this is the request setting up a "proxy + * tunnel" + * + * @returns CURLcode + */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel); /* TRUE if this is the request setting + up the proxy tunnel */ + +#endif /* HEADER_CURL_HTTP_H */ diff --git a/libcurl/lib/http2.c b/libcurl/lib/http2.c new file mode 100644 index 0000000..eb55e62 --- /dev/null +++ b/libcurl/lib/http2.c @@ -0,0 +1,2437 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NGHTTP2 +#include +#include "urldata.h" +#include "http2.h" +#include "http.h" +#include "sendf.h" +#include "select.h" +#include "curl_base64.h" +#include "strcase.h" +#include "multiif.h" +#include "url.h" +#include "connect.h" +#include "strtoofft.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define H2_BUFSIZE 32768 + +#if (NGHTTP2_VERSION_NUM < 0x010000) +#error too old nghttp2 version, upgrade! +#endif + +#if (NGHTTP2_VERSION_NUM > 0x010800) +#define NGHTTP2_HAS_HTTP2_STRERROR 1 +#endif + +#if (NGHTTP2_VERSION_NUM >= 0x010900) +/* nghttp2_session_callbacks_set_error_callback is present in nghttp2 1.9.0 or + later */ +#define NGHTTP2_HAS_ERROR_CALLBACK 1 +#else +#define nghttp2_session_callbacks_set_error_callback(x,y) +#endif + +#if (NGHTTP2_VERSION_NUM >= 0x010c00) +#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1 +#endif + +#define HTTP2_HUGE_WINDOW_SIZE (1 << 30) + +#ifdef DEBUG_HTTP2 +#define H2BUGF(x) x +#else +#define H2BUGF(x) do { } WHILE_FALSE +#endif + + +static ssize_t http2_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err); +static bool http2_connisdead(struct connectdata *conn); +static int h2_session_send(struct Curl_easy *data, + nghttp2_session *h2); +static int h2_process_pending_input(struct connectdata *conn, + struct http_conn *httpc, + CURLcode *err); + +/* + * Curl_http2_init_state() is called when the easy handle is created and + * allows for HTTP/2 specific init of state. + */ +void Curl_http2_init_state(struct UrlState *state) +{ + state->stream_weight = NGHTTP2_DEFAULT_WEIGHT; +} + +/* + * Curl_http2_init_userset() is called when the easy handle is created and + * allows for HTTP/2 specific user-set fields. + */ +void Curl_http2_init_userset(struct UserDefined *set) +{ + set->stream_weight = NGHTTP2_DEFAULT_WEIGHT; +} + +static int http2_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to + numsocks + number of + sockets */ + int numsocks) +{ + const struct http_conn *c = &conn->proto.httpc; + struct SingleRequest *k = &conn->data->req; + int bitmap = GETSOCK_BLANK; + (void)numsocks; + + sock[0] = conn->sock[FIRSTSOCKET]; + + /* in a HTTP/2 connection we can basically always get a frame so we should + always be ready for one */ + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + + /* we're still uploading or the HTTP/2 layer wants to send data */ + if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) || + nghttp2_session_want_write(c->h2)) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +} + +static int http2_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ + return http2_perform_getsock(conn, sock, numsocks); +} + +/* + * http2_stream_free() free HTTP2 stream related data + */ +static void http2_stream_free(struct HTTP *http) +{ + if(http) { + Curl_add_buffer_free(&http->header_recvbuf); + Curl_add_buffer_free(&http->trailer_recvbuf); + for(; http->push_headers_used > 0; --http->push_headers_used) { + free(http->push_headers[http->push_headers_used - 1]); + } + free(http->push_headers); + http->push_headers = NULL; + } +} + +/* + * Disconnects *a* connection used for HTTP/2. It might be an old one from the + * connection cache and not the "main" one. Don't touch the easy handle! + */ + +static CURLcode http2_disconnect(struct connectdata *conn, + bool dead_connection) +{ + struct http_conn *c = &conn->proto.httpc; + (void)dead_connection; + + H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); + + nghttp2_session_del(c->h2); + Curl_safefree(c->inbuf); + + H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); + + return CURLE_OK; +} + +/* + * The server may send us data at any point (e.g. PING frames). Therefore, + * we cannot assume that an HTTP/2 socket is dead just because it is readable. + * + * Instead, if it is readable, run Curl_connalive() to peek at the socket + * and distinguish between closed and data. + */ +static bool http2_connisdead(struct connectdata *conn) +{ + int sval; + bool dead = TRUE; + + if(conn->bits.close) + return TRUE; + + sval = SOCKET_READABLE(conn->sock[FIRSTSOCKET], 0); + if(sval == 0) { + /* timeout */ + dead = FALSE; + } + else if(sval & CURL_CSELECT_ERR) { + /* socket is in an error state */ + dead = TRUE; + } + else if(sval & CURL_CSELECT_IN) { + /* readable with no error. could still be closed */ + dead = !Curl_connalive(conn); + if(!dead) { + /* This happens before we've sent off a request and the connection is + not in use by any other transfer, there shouldn't be any data here, + only "protocol frames" */ + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + ssize_t nread = -1; + if(httpc->recv_underlying) + /* if called "too early", this pointer isn't setup yet! */ + nread = ((Curl_recv *)httpc->recv_underlying)( + conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); + if(nread != -1) { + infof(conn->data, + "%d bytes stray data read before trying h2 connection\n", + (int)nread); + httpc->nread_inbuf = 0; + httpc->inbuflen = nread; + (void)h2_process_pending_input(conn, httpc, &result); + } + else + /* the read failed so let's say this is dead anyway */ + dead = TRUE; + } + } + + return dead; +} + +static unsigned int http2_conncheck(struct connectdata *check, + unsigned int checks_to_perform) +{ + unsigned int ret_val = CONNRESULT_NONE; + struct http_conn *c = &check->proto.httpc; + int rc; + bool send_frames = false; + + if(checks_to_perform & CONNCHECK_ISDEAD) { + if(http2_connisdead(check)) + ret_val |= CONNRESULT_DEAD; + } + + if(checks_to_perform & CONNCHECK_KEEPALIVE) { + struct curltime now = Curl_now(); + time_t elapsed = Curl_timediff(now, check->keepalive); + + if(elapsed > check->upkeep_interval_ms) { + /* Perform an HTTP/2 PING */ + rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL); + if(!rc) { + /* Successfully added a PING frame to the session. Need to flag this + so the frame is sent. */ + send_frames = true; + } + else { + failf(check->data, "nghttp2_submit_ping() failed: %s(%d)", + nghttp2_strerror(rc), rc); + } + + check->keepalive = now; + } + } + + if(send_frames) { + rc = nghttp2_session_send(c->h2); + if(rc) + failf(check->data, "nghttp2_session_send() failed: %s(%d)", + nghttp2_strerror(rc), rc); + } + + return ret_val; +} + +/* called from http_setup_conn */ +void Curl_http2_setup_req(struct Curl_easy *data) +{ + struct HTTP *http = data->req.protop; + + http->nread_header_recvbuf = 0; + http->bodystarted = FALSE; + http->status_code = -1; + http->pausedata = NULL; + http->pauselen = 0; + http->closed = FALSE; + http->close_handled = FALSE; + http->mem = data->state.buffer; + http->len = data->set.buffer_size; + http->memlen = 0; +} + +/* called from http_setup_conn */ +void Curl_http2_setup_conn(struct connectdata *conn) +{ + conn->proto.httpc.settings.max_concurrent_streams = + DEFAULT_MAX_CONCURRENT_STREAMS; + conn->proto.httpc.error_code = NGHTTP2_NO_ERROR; +} + +/* + * HTTP2 handler interface. This isn't added to the general list of protocols + * but will be used at run-time when the protocol is dynamically switched from + * HTTP to HTTP2. + */ +static const struct Curl_handler Curl_handler_http2 = { + "HTTP", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + http2_getsock, /* proto_getsock */ + http2_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + http2_perform_getsock, /* perform_getsock */ + http2_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + http2_conncheck, /* connection_check */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_STREAM /* flags */ +}; + +static const struct Curl_handler Curl_handler_http2_ssl = { + "HTTPS", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + http2_getsock, /* proto_getsock */ + http2_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + http2_perform_getsock, /* perform_getsock */ + http2_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + http2_conncheck, /* connection_check */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_STREAM /* flags */ +}; + +/* + * Store nghttp2 version info in this buffer, Prefix with a space. Return + * total length written. + */ +int Curl_http2_ver(char *p, size_t len) +{ + nghttp2_info *h2 = nghttp2_version(0); + return msnprintf(p, len, " nghttp2/%s", h2->version_str); +} + +/* HTTP/2 error code to name based on the Error Code Registry. +https://tools.ietf.org/html/rfc7540#page-77 +nghttp2_error_code enums are identical. +*/ +static const char *http2_strerror(uint32_t err) +{ +#ifndef NGHTTP2_HAS_HTTP2_STRERROR + const char *str[] = { + "NO_ERROR", /* 0x0 */ + "PROTOCOL_ERROR", /* 0x1 */ + "INTERNAL_ERROR", /* 0x2 */ + "FLOW_CONTROL_ERROR", /* 0x3 */ + "SETTINGS_TIMEOUT", /* 0x4 */ + "STREAM_CLOSED", /* 0x5 */ + "FRAME_SIZE_ERROR", /* 0x6 */ + "REFUSED_STREAM", /* 0x7 */ + "CANCEL", /* 0x8 */ + "COMPRESSION_ERROR", /* 0x9 */ + "CONNECT_ERROR", /* 0xA */ + "ENHANCE_YOUR_CALM", /* 0xB */ + "INADEQUATE_SECURITY", /* 0xC */ + "HTTP_1_1_REQUIRED" /* 0xD */ + }; + return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown"; +#else + return nghttp2_http2_strerror(err); +#endif +} + +/* + * The implementation of nghttp2_send_callback type. Here we write |data| with + * size |length| to the network and return the number of bytes actually + * written. See the documentation of nghttp2_send_callback for the details. + */ +static ssize_t send_callback(nghttp2_session *h2, + const uint8_t *data, size_t length, int flags, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; + ssize_t written; + CURLcode result = CURLE_OK; + + (void)h2; + (void)flags; + + if(!c->send_underlying) + /* called before setup properly! */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + + written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET, + data, length, &result); + + if(result == CURLE_AGAIN) { + return NGHTTP2_ERR_WOULDBLOCK; + } + + if(written == -1) { + failf(conn->data, "Failed sending HTTP2 data"); + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + if(!written) + return NGHTTP2_ERR_WOULDBLOCK; + + return written; +} + + +/* We pass a pointer to this struct in the push callback, but the contents of + the struct are hidden from the user. */ +struct curl_pushheaders { + struct Curl_easy *data; + const nghttp2_push_promise *frame; +}; + +/* + * push header access function. Only to be used from within the push callback + */ +char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num) +{ + /* Verify that we got a good easy handle in the push header struct, mostly to + detect rubbish input fast(er). */ + if(!h || !GOOD_EASY_HANDLE(h->data)) + return NULL; + else { + struct HTTP *stream = h->data->req.protop; + if(num < stream->push_headers_used) + return stream->push_headers[num]; + } + return NULL; +} + +/* + * push header access function. Only to be used from within the push callback + */ +char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header) +{ + /* Verify that we got a good easy handle in the push header struct, + mostly to detect rubbish input fast(er). Also empty header name + is just a rubbish too. We have to allow ":" at the beginning of + the header, but header == ":" must be rejected. If we have ':' in + the middle of header, it could be matched in middle of the value, + this is because we do prefix match.*/ + if(!h || !GOOD_EASY_HANDLE(h->data) || !header || !header[0] || + !strcmp(header, ":") || strchr(header + 1, ':')) + return NULL; + else { + struct HTTP *stream = h->data->req.protop; + size_t len = strlen(header); + size_t i; + for(i = 0; ipush_headers_used; i++) { + if(!strncmp(header, stream->push_headers[i], len)) { + /* sub-match, make sure that it is followed by a colon */ + if(stream->push_headers[i][len] != ':') + continue; + return &stream->push_headers[i][len + 1]; + } + } + } + return NULL; +} + +/* + * This specific transfer on this connection has been "drained". + */ +static void drained_transfer(struct Curl_easy *data, + struct http_conn *httpc) +{ + DEBUGASSERT(httpc->drain_total >= data->state.drain); + httpc->drain_total -= data->state.drain; + data->state.drain = 0; +} + +/* + * Mark this transfer to get "drained". + */ +static void drain_this(struct Curl_easy *data, + struct http_conn *httpc) +{ + data->state.drain++; + httpc->drain_total++; + DEBUGASSERT(httpc->drain_total >= data->state.drain); +} + +static struct Curl_easy *duphandle(struct Curl_easy *data) +{ + struct Curl_easy *second = curl_easy_duphandle(data); + if(second) { + /* setup the request struct */ + struct HTTP *http = calloc(1, sizeof(struct HTTP)); + if(!http) { + (void)Curl_close(second); + second = NULL; + } + else { + second->req.protop = http; + http->header_recvbuf = Curl_add_buffer_init(); + if(!http->header_recvbuf) { + free(http); + (void)Curl_close(second); + second = NULL; + } + else { + Curl_http2_setup_req(second); + second->state.stream_weight = data->state.stream_weight; + } + } + } + return second; +} + + +static int push_promise(struct Curl_easy *data, + struct connectdata *conn, + const nghttp2_push_promise *frame) +{ + int rv; + H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n", + frame->promised_stream_id)); + if(data->multi->push_cb) { + struct HTTP *stream; + struct HTTP *newstream; + struct curl_pushheaders heads; + CURLMcode rc; + struct http_conn *httpc; + size_t i; + /* clone the parent */ + struct Curl_easy *newhandle = duphandle(data); + if(!newhandle) { + infof(data, "failed to duplicate handle\n"); + rv = 1; /* FAIL HARD */ + goto fail; + } + + heads.data = data; + heads.frame = frame; + /* ask the application */ + H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n")); + + stream = data->req.protop; + if(!stream) { + failf(data, "Internal NULL stream!\n"); + (void)Curl_close(newhandle); + rv = 1; + goto fail; + } + + Curl_set_in_callback(data, true); + rv = data->multi->push_cb(data, newhandle, + stream->push_headers_used, &heads, + data->multi->push_userp); + Curl_set_in_callback(data, false); + + /* free the headers again */ + for(i = 0; ipush_headers_used; i++) + free(stream->push_headers[i]); + free(stream->push_headers); + stream->push_headers = NULL; + stream->push_headers_used = 0; + + if(rv) { + /* denied, kill off the new handle again */ + http2_stream_free(newhandle->req.protop); + newhandle->req.protop = NULL; + (void)Curl_close(newhandle); + goto fail; + } + + newstream = newhandle->req.protop; + newstream->stream_id = frame->promised_stream_id; + newhandle->req.maxdownload = -1; + newhandle->req.size = -1; + + /* approved, add to the multi handle and immediately switch to PERFORM + state with the given connection !*/ + rc = Curl_multi_add_perform(data->multi, newhandle, conn); + if(rc) { + infof(data, "failed to add handle to multi\n"); + http2_stream_free(newhandle->req.protop); + newhandle->req.protop = NULL; + Curl_close(newhandle); + rv = 1; + goto fail; + } + + httpc = &conn->proto.httpc; + rv = nghttp2_session_set_stream_user_data(httpc->h2, + frame->promised_stream_id, + newhandle); + if(rv) { + infof(data, "failed to set user_data for stream %d\n", + frame->promised_stream_id); + DEBUGASSERT(0); + goto fail; + } + } + else { + H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n")); + rv = 1; + } + fail: + return rv; +} + +/* + * multi_connchanged() is called to tell that there is a connection in + * this multi handle that has changed state (multiplexing become possible, the + * number of allowed streams changed or similar), and a subsequent use of this + * multi handle should move CONNECT_PEND handles back to CONNECT to have them + * retry. + */ +static void multi_connchanged(struct Curl_multi *multi) +{ + multi->recheckstate = TRUE; +} + +static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *httpc = &conn->proto.httpc; + struct Curl_easy *data_s = NULL; + struct HTTP *stream = NULL; + int rv; + size_t left, ncopy; + int32_t stream_id = frame->hd.stream_id; + CURLcode result; + + if(!stream_id) { + /* stream ID zero is for connection-oriented stuff */ + if(frame->hd.type == NGHTTP2_SETTINGS) { + uint32_t max_conn = httpc->settings.max_concurrent_streams; + H2BUGF(infof(conn->data, "Got SETTINGS\n")); + httpc->settings.max_concurrent_streams = + nghttp2_session_get_remote_settings( + session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); + httpc->settings.enable_push = + nghttp2_session_get_remote_settings( + session, NGHTTP2_SETTINGS_ENABLE_PUSH); + H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n", + httpc->settings.max_concurrent_streams)); + H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n", + httpc->settings.enable_push?"TRUE":"false")); + if(max_conn != httpc->settings.max_concurrent_streams) { + /* only signal change if the value actually changed */ + infof(conn->data, + "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n", + httpc->settings.max_concurrent_streams); + multi_connchanged(conn->data->multi); + } + } + return 0; + } + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) { + H2BUGF(infof(conn->data, + "No Curl_easy associated with stream: %x\n", + stream_id)); + return 0; + } + + stream = data_s->req.protop; + if(!stream) { + H2BUGF(infof(data_s, "No proto pointer for stream: %x\n", + stream_id)); + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n", + frame->hd.type, stream_id)); + + switch(frame->hd.type) { + case NGHTTP2_DATA: + /* If body started on this stream, then receiving DATA is illegal. */ + if(!stream->bodystarted) { + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + stream_id, NGHTTP2_PROTOCOL_ERROR); + + if(nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + break; + case NGHTTP2_HEADERS: + if(stream->bodystarted) { + /* Only valid HEADERS after body started is trailer HEADERS. We + buffer them in on_header callback. */ + break; + } + + /* nghttp2 guarantees that :status is received, and we store it to + stream->status_code. Fuzzing has proven this can still be reached + without status code having been set. */ + if(stream->status_code == -1) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + /* Only final status code signals the end of header */ + if(stream->status_code / 100 != 1) { + stream->bodystarted = TRUE; + stream->status_code = -1; + } + + result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf; + ncopy = CURLMIN(stream->len, left); + + memcpy(&stream->mem[stream->memlen], + stream->header_recvbuf->buffer + stream->nread_header_recvbuf, + ncopy); + stream->nread_header_recvbuf += ncopy; + + H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n", + ncopy, stream_id, stream->mem)); + + stream->len -= ncopy; + stream->memlen += ncopy; + + drain_this(data_s, httpc); + { + /* get the pointer from userp again since it was re-assigned above */ + struct connectdata *conn_s = (struct connectdata *)userp; + + /* if we receive data for another handle, wake that up */ + if(conn_s->data != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); + } + break; + case NGHTTP2_PUSH_PROMISE: + rv = push_promise(data_s, conn, &frame->push_promise); + if(rv) { /* deny! */ + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_CANCEL); + if(nghttp2_is_fatal(rv)) { + return rv; + } + } + break; + default: + H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n", + frame->hd.type, stream_id)); + break; + } + return 0; +} + +static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const uint8_t *data, size_t len, void *userp) +{ + struct HTTP *stream; + struct Curl_easy *data_s; + size_t nread; + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + (void)flags; + (void)data; + + DEBUGASSERT(stream_id); /* should never be a zero stream ID here */ + + /* get the stream from the hash based on Stream ID */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) + /* Receiving a Stream ID not in the hash should not happen, this is an + internal error more than anything else! */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + + stream = data_s->req.protop; + if(!stream) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + nread = CURLMIN(stream->len, len); + memcpy(&stream->mem[stream->memlen], data, nread); + + stream->len -= nread; + stream->memlen += nread; + + drain_this(data_s, &conn->proto.httpc); + + /* if we receive data for another handle, wake that up */ + if(conn->data != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); + + H2BUGF(infof(data_s, "%zu data received for stream %u " + "(%zu left in buffer %p, total %zu)\n", + nread, stream_id, + stream->len, stream->mem, + stream->memlen)); + + if(nread < len) { + stream->pausedata = data + nread; + stream->pauselen = len - nread; + H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer" + ", stream %u\n", + len - nread, stream_id)); + data_s->conn->proto.httpc.pause_stream_id = stream_id; + + return NGHTTP2_ERR_PAUSE; + } + + /* pause execution of nghttp2 if we received data for another handle + in order to process them first. */ + if(conn->data != data_s) { + data_s->conn->proto.httpc.pause_stream_id = stream_id; + + return NGHTTP2_ERR_PAUSE; + } + + return 0; +} + +static int on_stream_close(nghttp2_session *session, int32_t stream_id, + uint32_t error_code, void *userp) +{ + struct Curl_easy *data_s; + struct HTTP *stream; + struct connectdata *conn = (struct connectdata *)userp; + int rv; + (void)session; + (void)stream_id; + + if(stream_id) { + struct http_conn *httpc; + /* get the stream from the hash based on Stream ID, stream ID zero is for + connection-oriented stuff */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) { + /* We could get stream ID not in the hash. For example, if we + decided to reject stream (e.g., PUSH_PROMISE). */ + return 0; + } + H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", + http2_strerror(error_code), error_code, stream_id)); + stream = data_s->req.protop; + if(!stream) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + stream->closed = TRUE; + httpc = &conn->proto.httpc; + drain_this(data_s, httpc); + httpc->error_code = error_code; + + /* remove the entry from the hash as the stream is now gone */ + rv = nghttp2_session_set_stream_user_data(session, stream_id, 0); + if(rv) { + infof(data_s, "http/2: failed to clear user_data for stream %d!\n", + stream_id); + DEBUGASSERT(0); + } + if(stream_id == httpc->pause_stream_id) { + H2BUGF(infof(data_s, "Stopped the pause stream!\n")); + httpc->pause_stream_id = 0; + } + H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id)); + stream->stream_id = 0; /* cleared */ + } + return 0; +} + +static int on_begin_headers(nghttp2_session *session, + const nghttp2_frame *frame, void *userp) +{ + struct HTTP *stream; + struct Curl_easy *data_s = NULL; + (void)userp; + + data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); + if(!data_s) { + return 0; + } + + H2BUGF(infof(data_s, "on_begin_headers() was called\n")); + + if(frame->hd.type != NGHTTP2_HEADERS) { + return 0; + } + + stream = data_s->req.protop; + if(!stream || !stream->bodystarted) { + return 0; + } + + if(!stream->trailer_recvbuf) { + stream->trailer_recvbuf = Curl_add_buffer_init(); + if(!stream->trailer_recvbuf) { + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + } + return 0; +} + +/* Decode HTTP status code. Returns -1 if no valid status code was + decoded. */ +static int decode_status_code(const uint8_t *value, size_t len) +{ + int i; + int res; + + if(len != 3) { + return -1; + } + + res = 0; + + for(i = 0; i < 3; ++i) { + char c = value[i]; + + if(c < '0' || c > '9') { + return -1; + } + + res *= 10; + res += c - '0'; + } + + return res; +} + +/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */ +static int on_header(nghttp2_session *session, const nghttp2_frame *frame, + const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, + uint8_t flags, + void *userp) +{ + struct HTTP *stream; + struct Curl_easy *data_s; + int32_t stream_id = frame->hd.stream_id; + struct connectdata *conn = (struct connectdata *)userp; + CURLcode result; + (void)flags; + + DEBUGASSERT(stream_id); /* should never be a zero stream ID here */ + + /* get the stream from the hash based on Stream ID */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) + /* Receiving a Stream ID not in the hash should not happen, this is an + internal error more than anything else! */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + + stream = data_s->req.protop; + if(!stream) { + failf(data_s, "Internal NULL stream! 5\n"); + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + /* Store received PUSH_PROMISE headers to be used when the subsequent + PUSH_PROMISE callback comes */ + if(frame->hd.type == NGHTTP2_PUSH_PROMISE) { + char *h; + + if(!strcmp(":authority", (const char *)name)) { + /* pseudo headers are lower case */ + int rc = 0; + char *check = aprintf("%s:%d", conn->host.name, conn->remote_port); + if(!check) + /* no memory */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + if(!Curl_strcasecompare(check, (const char *)value)) { + /* This is push is not for the same authority that was asked for in + * the URL. RFC 7540 section 8.2 says: "A client MUST treat a + * PUSH_PROMISE for which the server is not authoritative as a stream + * error of type PROTOCOL_ERROR." + */ + (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + stream_id, NGHTTP2_PROTOCOL_ERROR); + rc = NGHTTP2_ERR_CALLBACK_FAILURE; + } + free(check); + if(rc) + return rc; + } + + if(!stream->push_headers) { + stream->push_headers_alloc = 10; + stream->push_headers = malloc(stream->push_headers_alloc * + sizeof(char *)); + if(!stream->push_headers) + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + stream->push_headers_used = 0; + } + else if(stream->push_headers_used == + stream->push_headers_alloc) { + char **headp; + stream->push_headers_alloc *= 2; + headp = Curl_saferealloc(stream->push_headers, + stream->push_headers_alloc * sizeof(char *)); + if(!headp) { + stream->push_headers = NULL; + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + stream->push_headers = headp; + } + h = aprintf("%s:%s", name, value); + if(h) + stream->push_headers[stream->push_headers_used++] = h; + return 0; + } + + if(stream->bodystarted) { + /* This is trailer fields. */ + /* 4 is for ": " and "\r\n". */ + uint32_t n = (uint32_t)(namelen + valuelen + 4); + + H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen, + value)); + + result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n)); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + + return 0; + } + + if(namelen == sizeof(":status") - 1 && + memcmp(":status", name, namelen) == 0) { + /* nghttp2 guarantees :status is received first and only once, and + value is 3 digits status code, and decode_status_code always + succeeds. */ + stream->status_code = decode_status_code(value, valuelen); + DEBUGASSERT(stream->status_code != -1); + + result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + /* the space character after the status code is mandatory */ + result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + /* if we receive data for another handle, wake that up */ + if(conn->data != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); + + H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n", + stream->status_code, data_s)); + return 0; + } + + /* nghttp2 guarantees that namelen > 0, and :status was already + received, and this is not pseudo-header field . */ + /* convert to a HTTP1-style header */ + result = Curl_add_buffer(&stream->header_recvbuf, name, namelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2); + if(result) + return NGHTTP2_ERR_CALLBACK_FAILURE; + /* if we receive data for another handle, wake that up */ + if(conn->data != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); + + H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen, + value)); + + return 0; /* 0 is successful */ +} + +static ssize_t data_source_read_callback(nghttp2_session *session, + int32_t stream_id, + uint8_t *buf, size_t length, + uint32_t *data_flags, + nghttp2_data_source *source, + void *userp) +{ + struct Curl_easy *data_s; + struct HTTP *stream = NULL; + size_t nread; + (void)source; + (void)userp; + + if(stream_id) { + /* get the stream from the hash based on Stream ID, stream ID zero is for + connection-oriented stuff */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); + if(!data_s) + /* Receiving a Stream ID not in the hash should not happen, this is an + internal error more than anything else! */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + + stream = data_s->req.protop; + if(!stream) + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + else + return NGHTTP2_ERR_INVALID_ARGUMENT; + + nread = CURLMIN(stream->upload_len, length); + if(nread > 0) { + memcpy(buf, stream->upload_mem, nread); + stream->upload_mem += nread; + stream->upload_len -= nread; + if(data_s->state.infilesize != -1) + stream->upload_left -= nread; + } + + if(stream->upload_left == 0) + *data_flags = NGHTTP2_DATA_FLAG_EOF; + else if(nread == 0) + return NGHTTP2_ERR_DEFERRED; + + H2BUGF(infof(data_s, "data_source_read_callback: " + "returns %zu bytes stream %u\n", + nread, stream_id)); + + return nread; +} + +#if defined(NGHTTP2_HAS_ERROR_CALLBACK) && \ + !defined(CURL_DISABLE_VERBOSE_STRINGS) +static int error_callback(nghttp2_session *session, + const char *msg, + size_t len, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + (void)session; + infof(conn->data, "http2 error: %.*s\n", len, msg); + return 0; +} +#endif + +static void populate_settings(struct connectdata *conn, + struct http_conn *httpc) +{ + nghttp2_settings_entry *iv = httpc->local_settings; + + iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; + iv[0].value = 100; + + iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + iv[1].value = HTTP2_HUGE_WINDOW_SIZE; + + iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; + iv[2].value = conn->data->multi->push_cb != NULL; + + httpc->local_settings_num = 3; +} + +void Curl_http2_done(struct connectdata *conn, bool premature) +{ + struct Curl_easy *data = conn->data; + struct HTTP *http = data->req.protop; + struct http_conn *httpc = &conn->proto.httpc; + + /* there might be allocated resources done before this got the 'h2' pointer + setup */ + if(http->header_recvbuf) { + Curl_add_buffer_free(&http->header_recvbuf); + Curl_add_buffer_free(&http->trailer_recvbuf); + if(http->push_headers) { + /* if they weren't used and then freed before */ + for(; http->push_headers_used > 0; --http->push_headers_used) { + free(http->push_headers[http->push_headers_used - 1]); + } + free(http->push_headers); + http->push_headers = NULL; + } + } + + if(!httpc->h2) /* not HTTP/2 ? */ + return; + + if(premature) { + /* RST_STREAM */ + if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, + http->stream_id, NGHTTP2_STREAM_CLOSED)) + (void)nghttp2_session_send(httpc->h2); + + if(http->stream_id == httpc->pause_stream_id) { + infof(data, "stopped the pause stream!\n"); + httpc->pause_stream_id = 0; + } + } + + if(data->state.drain) + drained_transfer(data, httpc); + + /* -1 means unassigned and 0 means cleared */ + if(http->stream_id > 0) { + int rv = nghttp2_session_set_stream_user_data(httpc->h2, + http->stream_id, 0); + if(rv) { + infof(data, "http/2: failed to clear user_data for stream %d!\n", + http->stream_id); + DEBUGASSERT(0); + } + http->stream_id = 0; + } +} + +/* + * Initialize nghttp2 for a Curl connection + */ +static CURLcode http2_init(struct connectdata *conn) +{ + if(!conn->proto.httpc.h2) { + int rc; + nghttp2_session_callbacks *callbacks; + + conn->proto.httpc.inbuf = malloc(H2_BUFSIZE); + if(conn->proto.httpc.inbuf == NULL) + return CURLE_OUT_OF_MEMORY; + + rc = nghttp2_session_callbacks_new(&callbacks); + + if(rc) { + failf(conn->data, "Couldn't initialize nghttp2 callbacks!"); + return CURLE_OUT_OF_MEMORY; /* most likely at least */ + } + + /* nghttp2_send_callback */ + nghttp2_session_callbacks_set_send_callback(callbacks, send_callback); + /* nghttp2_on_frame_recv_callback */ + nghttp2_session_callbacks_set_on_frame_recv_callback + (callbacks, on_frame_recv); + /* nghttp2_on_data_chunk_recv_callback */ + nghttp2_session_callbacks_set_on_data_chunk_recv_callback + (callbacks, on_data_chunk_recv); + /* nghttp2_on_stream_close_callback */ + nghttp2_session_callbacks_set_on_stream_close_callback + (callbacks, on_stream_close); + /* nghttp2_on_begin_headers_callback */ + nghttp2_session_callbacks_set_on_begin_headers_callback + (callbacks, on_begin_headers); + /* nghttp2_on_header_callback */ + nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header); + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + nghttp2_session_callbacks_set_error_callback(callbacks, error_callback); +#endif + + /* The nghttp2 session is not yet setup, do it */ + rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn); + + nghttp2_session_callbacks_del(callbacks); + + if(rc) { + failf(conn->data, "Couldn't initialize nghttp2!"); + return CURLE_OUT_OF_MEMORY; /* most likely at least */ + } + } + return CURLE_OK; +} + +/* + * Append headers to ask for a HTTP1.1 to HTTP2 upgrade. + */ +CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, + struct connectdata *conn) +{ + CURLcode result; + ssize_t binlen; + char *base64; + size_t blen; + struct SingleRequest *k = &conn->data->req; + uint8_t *binsettings = conn->proto.httpc.binsettings; + struct http_conn *httpc = &conn->proto.httpc; + + populate_settings(conn, httpc); + + /* this returns number of bytes it wrote */ + binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, + httpc->local_settings, + httpc->local_settings_num); + if(!binlen) { + failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); + Curl_add_buffer_free(&req); + return CURLE_FAILED_INIT; + } + conn->proto.httpc.binlen = binlen; + + result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen, + &base64, &blen); + if(result) { + Curl_add_buffer_free(&req); + return result; + } + + result = Curl_add_bufferf(&req, + "Connection: Upgrade, HTTP2-Settings\r\n" + "Upgrade: %s\r\n" + "HTTP2-Settings: %s\r\n", + NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64); + free(base64); + + k->upgr101 = UPGR101_REQUESTED; + + return result; +} + +/* + * Returns nonzero if current HTTP/2 session should be closed. + */ +static int should_close_session(struct http_conn *httpc) +{ + return httpc->drain_total == 0 && !nghttp2_session_want_read(httpc->h2) && + !nghttp2_session_want_write(httpc->h2); +} + +/* + * h2_process_pending_input() processes pending input left in + * httpc->inbuf. Then, call h2_session_send() to send pending data. + * This function returns 0 if it succeeds, or -1 and error code will + * be assigned to *err. + */ +static int h2_process_pending_input(struct connectdata *conn, + struct http_conn *httpc, + CURLcode *err) +{ + ssize_t nread; + char *inbuf; + ssize_t rv; + struct Curl_easy *data = conn->data; + + nread = httpc->inbuflen - httpc->nread_inbuf; + inbuf = httpc->inbuf + httpc->nread_inbuf; + + rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread); + if(rv < 0) { + failf(data, + "h2_process_pending_input: nghttp2_session_mem_recv() returned " + "%zd:%s\n", rv, nghttp2_strerror((int)rv)); + *err = CURLE_RECV_ERROR; + return -1; + } + + if(nread == rv) { + H2BUGF(infof(data, + "h2_process_pending_input: All data in connection buffer " + "processed\n")); + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + } + else { + httpc->nread_inbuf += rv; + H2BUGF(infof(data, + "h2_process_pending_input: %zu bytes left in connection " + "buffer\n", + httpc->inbuflen - httpc->nread_inbuf)); + } + + rv = h2_session_send(data, httpc->h2); + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return -1; + } + + if(should_close_session(httpc)) { + H2BUGF(infof(data, + "h2_process_pending_input: nothing to do in this session\n")); + if(httpc->error_code) + *err = CURLE_HTTP2; + else { + /* not an error per se, but should still close the connection */ + connclose(conn, "GOAWAY received"); + *err = CURLE_OK; + } + return -1; + } + + return 0; +} + +/* + * Called from transfer.c:done_sending when we stop uploading. + */ +CURLcode Curl_http2_done_sending(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if((conn->handler == &Curl_handler_http2_ssl) || + (conn->handler == &Curl_handler_http2)) { + /* make sure this is only attempted for HTTP/2 transfers */ + + struct HTTP *stream = conn->data->req.protop; + + if(stream->upload_left) { + /* If the stream still thinks there's data left to upload. */ + struct http_conn *httpc = &conn->proto.httpc; + nghttp2_session *h2 = httpc->h2; + + stream->upload_left = 0; /* DONE! */ + + /* resume sending here to trigger the callback to get called again so + that it can signal EOF to nghttp2 */ + (void)nghttp2_session_resume_data(h2, stream->stream_id); + + (void)h2_process_pending_input(conn, httpc, &result); + } + } + return result; +} + +static ssize_t http2_handle_stream_close(struct connectdata *conn, + struct Curl_easy *data, + struct HTTP *stream, CURLcode *err) +{ + char *trailer_pos, *trailer_end; + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + + if(httpc->pause_stream_id == stream->stream_id) { + httpc->pause_stream_id = 0; + } + + drained_transfer(data, httpc); + + if(httpc->pause_stream_id == 0) { + if(h2_process_pending_input(conn, httpc, err) != 0) { + return -1; + } + } + + DEBUGASSERT(data->state.drain == 0); + + /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ + stream->closed = FALSE; + if(httpc->error_code == NGHTTP2_REFUSED_STREAM) { + H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n", + stream->stream_id)); + connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */ + data->state.refused_stream = TRUE; + *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */ + return -1; + } + else if(httpc->error_code != NGHTTP2_NO_ERROR) { + failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)", + stream->stream_id, http2_strerror(httpc->error_code), + httpc->error_code); + *err = CURLE_HTTP2_STREAM; + return -1; + } + + if(!stream->bodystarted) { + failf(data, "HTTP/2 stream %d was closed cleanly, but before getting " + " all response header fields, treated as error", + stream->stream_id); + *err = CURLE_HTTP2_STREAM; + return -1; + } + + if(stream->trailer_recvbuf && stream->trailer_recvbuf->buffer) { + trailer_pos = stream->trailer_recvbuf->buffer; + trailer_end = trailer_pos + stream->trailer_recvbuf->size_used; + + for(; trailer_pos < trailer_end;) { + uint32_t n; + memcpy(&n, trailer_pos, sizeof(n)); + trailer_pos += sizeof(n); + + result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailer_pos, n); + if(result) { + *err = result; + return -1; + } + + trailer_pos += n + 1; + } + } + + stream->close_handled = TRUE; + + H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n")); + return 0; +} + +/* + * h2_pri_spec() fills in the pri_spec struct, used by nghttp2 to send weight + * and dependency to the peer. It also stores the updated values in the state + * struct. + */ + +static void h2_pri_spec(struct Curl_easy *data, + nghttp2_priority_spec *pri_spec) +{ + struct HTTP *depstream = (data->set.stream_depends_on? + data->set.stream_depends_on->req.protop:NULL); + int32_t depstream_id = depstream? depstream->stream_id:0; + nghttp2_priority_spec_init(pri_spec, depstream_id, data->set.stream_weight, + data->set.stream_depends_e); + data->state.stream_weight = data->set.stream_weight; + data->state.stream_depends_e = data->set.stream_depends_e; + data->state.stream_depends_on = data->set.stream_depends_on; +} + +/* + * h2_session_send() checks if there's been an update in the priority / + * dependency settings and if so it submits a PRIORITY frame with the updated + * info. + */ +static int h2_session_send(struct Curl_easy *data, + nghttp2_session *h2) +{ + struct HTTP *stream = data->req.protop; + if((data->set.stream_weight != data->state.stream_weight) || + (data->set.stream_depends_e != data->state.stream_depends_e) || + (data->set.stream_depends_on != data->state.stream_depends_on) ) { + /* send new weight and/or dependency */ + nghttp2_priority_spec pri_spec; + int rv; + + h2_pri_spec(data, &pri_spec); + + H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n", + stream->stream_id, data)); + rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id, + &pri_spec); + if(rv) + return rv; + } + + return nghttp2_session_send(h2); +} + +static ssize_t http2_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + CURLcode result = CURLE_OK; + ssize_t rv; + ssize_t nread; + struct http_conn *httpc = &conn->proto.httpc; + struct Curl_easy *data = conn->data; + struct HTTP *stream = data->req.protop; + + (void)sockindex; /* we always do HTTP2 on sockindex 0 */ + + if(should_close_session(httpc)) { + H2BUGF(infof(data, + "http2_recv: nothing to do in this session\n")); + *err = CURLE_HTTP2; + return -1; + } + + /* Nullify here because we call nghttp2_session_send() and they + might refer to the old buffer. */ + stream->upload_mem = NULL; + stream->upload_len = 0; + + /* + * At this point 'stream' is just in the Curl_easy the connection + * identifies as its owner at this time. + */ + + if(stream->bodystarted && + stream->nread_header_recvbuf < stream->header_recvbuf->size_used) { + /* If there is body data pending for this stream to return, do that */ + size_t left = + stream->header_recvbuf->size_used - stream->nread_header_recvbuf; + size_t ncopy = CURLMIN(len, left); + memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf, + ncopy); + stream->nread_header_recvbuf += ncopy; + + H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n", + (int)ncopy)); + return ncopy; + } + + H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n", + data, stream->stream_id)); + + if((data->state.drain) && stream->memlen) { + H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n", + stream->memlen, stream->stream_id, + stream->mem, mem)); + if(mem != stream->mem) { + /* if we didn't get the same buffer this time, we must move the data to + the beginning */ + memmove(mem, stream->mem, stream->memlen); + stream->len = len - stream->memlen; + stream->mem = mem; + } + if(httpc->pause_stream_id == stream->stream_id && !stream->pausedata) { + /* We have paused nghttp2, but we have no pause data (see + on_data_chunk_recv). */ + httpc->pause_stream_id = 0; + if(h2_process_pending_input(conn, httpc, &result) != 0) { + *err = result; + return -1; + } + } + } + else if(stream->pausedata) { + DEBUGASSERT(httpc->pause_stream_id == stream->stream_id); + nread = CURLMIN(len, stream->pauselen); + memcpy(mem, stream->pausedata, nread); + + stream->pausedata += nread; + stream->pauselen -= nread; + + infof(data, "%zd data bytes written\n", nread); + if(stream->pauselen == 0) { + H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id)); + DEBUGASSERT(httpc->pause_stream_id == stream->stream_id); + httpc->pause_stream_id = 0; + + stream->pausedata = NULL; + stream->pauselen = 0; + + /* When NGHTTP2_ERR_PAUSE is returned from + data_source_read_callback, we might not process DATA frame + fully. Calling nghttp2_session_mem_recv() again will + continue to process DATA frame, but if there is no incoming + frames, then we have to call it again with 0-length data. + Without this, on_stream_close callback will not be called, + and stream could be hanged. */ + if(h2_process_pending_input(conn, httpc, &result) != 0) { + *err = result; + return -1; + } + } + H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n", + nread, stream->stream_id)); + return nread; + } + else if(httpc->pause_stream_id) { + /* If a stream paused nghttp2_session_mem_recv previously, and has + not processed all data, it still refers to the buffer in + nghttp2_session. If we call nghttp2_session_mem_recv(), we may + overwrite that buffer. To avoid that situation, just return + here with CURLE_AGAIN. This could be busy loop since data in + socket is not read. But it seems that usually streams are + notified with its drain property, and socket is read again + quickly. */ + H2BUGF(infof(data, "stream %x is paused, pause id: %x\n", + stream->stream_id, httpc->pause_stream_id)); + *err = CURLE_AGAIN; + return -1; + } + else { + char *inbuf; + /* remember where to store incoming data for this stream and how big the + buffer is */ + stream->mem = mem; + stream->len = len; + stream->memlen = 0; + + if(httpc->inbuflen == 0) { + nread = ((Curl_recv *)httpc->recv_underlying)( + conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); + + if(nread == -1) { + if(result != CURLE_AGAIN) + failf(data, "Failed receiving HTTP2 data"); + else if(stream->closed) + /* received when the stream was already closed! */ + return http2_handle_stream_close(conn, data, stream, err); + + *err = result; + return -1; + } + + if(nread == 0) { + H2BUGF(infof(data, "end of stream\n")); + *err = CURLE_OK; + return 0; + } + + H2BUGF(infof(data, "nread=%zd\n", nread)); + + httpc->inbuflen = nread; + inbuf = httpc->inbuf; + } + else { + nread = httpc->inbuflen - httpc->nread_inbuf; + inbuf = httpc->inbuf + httpc->nread_inbuf; + + H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n", + nread)); + } + rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread); + + if(nghttp2_is_fatal((int)rv)) { + failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n", + rv, nghttp2_strerror((int)rv)); + *err = CURLE_RECV_ERROR; + return -1; + } + H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv)); + if(nread == rv) { + H2BUGF(infof(data, "All data in connection buffer processed\n")); + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + } + else { + httpc->nread_inbuf += rv; + H2BUGF(infof(data, "%zu bytes left in connection buffer\n", + httpc->inbuflen - httpc->nread_inbuf)); + } + /* Always send pending frames in nghttp2 session, because + nghttp2_session_mem_recv() may queue new frame */ + rv = h2_session_send(data, httpc->h2); + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return -1; + } + + if(should_close_session(httpc)) { + H2BUGF(infof(data, "http2_recv: nothing to do in this session\n")); + *err = CURLE_HTTP2; + return -1; + } + } + if(stream->memlen) { + ssize_t retlen = stream->memlen; + H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n", + retlen, stream->stream_id)); + stream->memlen = 0; + + if(httpc->pause_stream_id == stream->stream_id) { + /* data for this stream is returned now, but this stream caused a pause + already so we need it called again asap */ + H2BUGF(infof(data, "Data returned for PAUSED stream %u\n", + stream->stream_id)); + } + else if(!stream->closed) { + drained_transfer(data, httpc); + } + + return retlen; + } + /* If this stream is closed, return 0 to signal the http routine to close + the connection */ + if(stream->closed) + return 0; + *err = CURLE_AGAIN; + H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n", + stream->stream_id)); + return -1; +} + +/* Index where :authority header field will appear in request header + field list. */ +#define AUTHORITY_DST_IDX 3 + +#define HEADER_OVERFLOW(x) \ + (x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen) + +/* + * Check header memory for the token "trailers". + * Parse the tokens as separated by comma and surrounded by whitespace. + * Returns TRUE if found or FALSE if not. + */ +static bool contains_trailers(const char *p, size_t len) +{ + const char *end = p + len; + for(;;) { + for(; p != end && (*p == ' ' || *p == '\t'); ++p) + ; + if(p == end || (size_t)(end - p) < sizeof("trailers") - 1) + return FALSE; + if(strncasecompare("trailers", p, sizeof("trailers") - 1)) { + p += sizeof("trailers") - 1; + for(; p != end && (*p == ' ' || *p == '\t'); ++p) + ; + if(p == end || *p == ',') + return TRUE; + } + /* skip to next token */ + for(; p != end && *p != ','; ++p) + ; + if(p == end) + return FALSE; + ++p; + } +} + +typedef enum { + /* Send header to server */ + HEADERINST_FORWARD, + /* Don't send header to server */ + HEADERINST_IGNORE, + /* Discard header, and replace it with "te: trailers" */ + HEADERINST_TE_TRAILERS +} header_instruction; + +/* Decides how to treat given header field. */ +static header_instruction inspect_header(const char *name, size_t namelen, + const char *value, size_t valuelen) { + switch(namelen) { + case 2: + if(!strncasecompare("te", name, namelen)) + return HEADERINST_FORWARD; + + return contains_trailers(value, valuelen) ? + HEADERINST_TE_TRAILERS : HEADERINST_IGNORE; + case 7: + return strncasecompare("upgrade", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 10: + return (strncasecompare("connection", name, namelen) || + strncasecompare("keep-alive", name, namelen)) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 16: + return strncasecompare("proxy-connection", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 17: + return strncasecompare("transfer-encoding", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + default: + return HEADERINST_FORWARD; + } +} + +static ssize_t http2_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + /* + * Currently, we send request in this function, but this function is also + * used to send request body. It would be nice to add dedicated function for + * request. + */ + int rv; + struct http_conn *httpc = &conn->proto.httpc; + struct HTTP *stream = conn->data->req.protop; + nghttp2_nv *nva = NULL; + size_t nheader; + size_t i; + size_t authority_idx; + char *hdbuf = (char *)mem; + char *end, *line_end; + nghttp2_data_provider data_prd; + int32_t stream_id; + nghttp2_session *h2 = httpc->h2; + nghttp2_priority_spec pri_spec; + + (void)sockindex; + + H2BUGF(infof(conn->data, "http2_send len=%zu\n", len)); + + if(stream->stream_id != -1) { + if(stream->close_handled) { + infof(conn->data, "stream %d closed\n", stream->stream_id); + *err = CURLE_HTTP2_STREAM; + return -1; + } + else if(stream->closed) { + return http2_handle_stream_close(conn, conn->data, stream, err); + } + /* If stream_id != -1, we have dispatched request HEADERS, and now + are going to send or sending request body in DATA frame */ + stream->upload_mem = mem; + stream->upload_len = len; + rv = nghttp2_session_resume_data(h2, stream->stream_id); + if(nghttp2_is_fatal(rv)) { + *err = CURLE_SEND_ERROR; + return -1; + } + rv = h2_session_send(conn->data, h2); + if(nghttp2_is_fatal(rv)) { + *err = CURLE_SEND_ERROR; + return -1; + } + len -= stream->upload_len; + + /* Nullify here because we call nghttp2_session_send() and they + might refer to the old buffer. */ + stream->upload_mem = NULL; + stream->upload_len = 0; + + if(should_close_session(httpc)) { + H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n")); + *err = CURLE_HTTP2; + return -1; + } + + if(stream->upload_left) { + /* we are sure that we have more data to send here. Calling the + following API will make nghttp2_session_want_write() return + nonzero if remote window allows it, which then libcurl checks + socket is writable or not. See http2_perform_getsock(). */ + nghttp2_session_resume_data(h2, stream->stream_id); + } + + H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len, + stream->stream_id)); + return len; + } + + /* Calculate number of headers contained in [mem, mem + len) */ + /* Here, we assume the curl http code generate *correct* HTTP header + field block */ + nheader = 0; + for(i = 1; i < len; ++i) { + if(hdbuf[i] == '\n' && hdbuf[i - 1] == '\r') { + ++nheader; + ++i; + } + } + if(nheader < 2) + goto fail; + + /* We counted additional 2 \r\n in the first and last line. We need 3 + new headers: :method, :path and :scheme. Therefore we need one + more space. */ + nheader += 1; + nva = malloc(sizeof(nghttp2_nv) * nheader); + if(nva == NULL) { + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + + /* Extract :method, :path from request line + We do line endings with CRLF so checking for CR is enough */ + line_end = memchr(hdbuf, '\r', len); + if(!line_end) + goto fail; + + /* Method does not contain spaces */ + end = memchr(hdbuf, ' ', line_end - hdbuf); + if(!end || end == hdbuf) + goto fail; + nva[0].name = (unsigned char *)":method"; + nva[0].namelen = strlen((char *)nva[0].name); + nva[0].value = (unsigned char *)hdbuf; + nva[0].valuelen = (size_t)(end - hdbuf); + nva[0].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[0])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + + hdbuf = end + 1; + + /* Path may contain spaces so scan backwards */ + end = NULL; + for(i = (size_t)(line_end - hdbuf); i; --i) { + if(hdbuf[i - 1] == ' ') { + end = &hdbuf[i - 1]; + break; + } + } + if(!end || end == hdbuf) + goto fail; + nva[1].name = (unsigned char *)":path"; + nva[1].namelen = strlen((char *)nva[1].name); + nva[1].value = (unsigned char *)hdbuf; + nva[1].valuelen = (size_t)(end - hdbuf); + nva[1].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[1])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + + nva[2].name = (unsigned char *)":scheme"; + nva[2].namelen = strlen((char *)nva[2].name); + if(conn->handler->flags & PROTOPT_SSL) + nva[2].value = (unsigned char *)"https"; + else + nva[2].value = (unsigned char *)"http"; + nva[2].valuelen = strlen((char *)nva[2].value); + nva[2].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[2])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + + authority_idx = 0; + i = 3; + while(i < nheader) { + size_t hlen; + + hdbuf = line_end + 2; + + /* check for next CR, but only within the piece of data left in the given + buffer */ + line_end = memchr(hdbuf, '\r', len - (hdbuf - (char *)mem)); + if(!line_end || (line_end == hdbuf)) + goto fail; + + /* header continuation lines are not supported */ + if(*hdbuf == ' ' || *hdbuf == '\t') + goto fail; + + for(end = hdbuf; end < line_end && *end != ':'; ++end) + ; + if(end == hdbuf || end == line_end) + goto fail; + hlen = end - hdbuf; + + if(hlen == 4 && strncasecompare("host", hdbuf, 4)) { + authority_idx = i; + nva[i].name = (unsigned char *)":authority"; + nva[i].namelen = strlen((char *)nva[i].name); + } + else { + nva[i].name = (unsigned char *)hdbuf; + nva[i].namelen = (size_t)(end - hdbuf); + } + hdbuf = end + 1; + while(*hdbuf == ' ' || *hdbuf == '\t') + ++hdbuf; + end = line_end; + + switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf, + end - hdbuf)) { + case HEADERINST_IGNORE: + /* skip header fields prohibited by HTTP/2 specification. */ + --nheader; + continue; + case HEADERINST_TE_TRAILERS: + nva[i].value = (uint8_t*)"trailers"; + nva[i].valuelen = sizeof("trailers") - 1; + break; + default: + nva[i].value = (unsigned char *)hdbuf; + nva[i].valuelen = (size_t)(end - hdbuf); + } + + nva[i].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[i])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + ++i; + } + + /* :authority must come before non-pseudo header fields */ + if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) { + nghttp2_nv authority = nva[authority_idx]; + for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) { + nva[i] = nva[i - 1]; + } + nva[i] = authority; + } + + /* Warn stream may be rejected if cumulative length of headers is too large. + It appears nghttp2 will not send a header frame larger than 64KB. */ +#define MAX_ACC 60000 /* <64KB to account for some overhead */ + { + size_t acc = 0; + + for(i = 0; i < nheader; ++i) { + acc += nva[i].namelen + nva[i].valuelen; + + H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n", + nva[i].namelen, nva[i].name, + nva[i].valuelen, nva[i].value)); + } + + if(acc > MAX_ACC) { + infof(conn->data, "http2_send: Warning: The cumulative length of all " + "headers exceeds %zu bytes and that could cause the " + "stream to be rejected.\n", MAX_ACC); + } + } + + h2_pri_spec(conn->data, &pri_spec); + + switch(conn->data->set.httpreq) { + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + case HTTPREQ_PUT: + if(conn->data->state.infilesize != -1) + stream->upload_left = conn->data->state.infilesize; + else + /* data sending without specifying the data amount up front */ + stream->upload_left = -1; /* unknown, but not zero */ + + data_prd.read_callback = data_source_read_callback; + data_prd.source.ptr = NULL; + stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader, + &data_prd, conn->data); + break; + default: + stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader, + NULL, conn->data); + } + + Curl_safefree(nva); + + if(stream_id < 0) { + H2BUGF(infof(conn->data, "http2_send() send error\n")); + *err = CURLE_SEND_ERROR; + return -1; + } + + infof(conn->data, "Using Stream ID: %x (easy handle %p)\n", + stream_id, (void *)conn->data); + stream->stream_id = stream_id; + + /* this does not call h2_session_send() since there can not have been any + * priority upodate since the nghttp2_submit_request() call above */ + rv = nghttp2_session_send(h2); + + if(rv != 0) { + *err = CURLE_SEND_ERROR; + return -1; + } + + if(should_close_session(httpc)) { + H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n")); + *err = CURLE_HTTP2; + return -1; + } + + if(stream->stream_id != -1) { + /* If whole HEADERS frame was sent off to the underlying socket, + the nghttp2 library calls data_source_read_callback. But only + it found that no data available, so it deferred the DATA + transmission. Which means that nghttp2_session_want_write() + returns 0 on http2_perform_getsock(), which results that no + writable socket check is performed. To workaround this, we + issue nghttp2_session_resume_data() here to bring back DATA + transmission from deferred state. */ + nghttp2_session_resume_data(h2, stream->stream_id); + } + + return len; + +fail: + free(nva); + *err = CURLE_SEND_ERROR; + return -1; +} + +CURLcode Curl_http2_setup(struct connectdata *conn) +{ + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + struct HTTP *stream = conn->data->req.protop; + + stream->stream_id = -1; + + if(!stream->header_recvbuf) { + stream->header_recvbuf = Curl_add_buffer_init(); + if(!stream->header_recvbuf) + return CURLE_OUT_OF_MEMORY; + } + + if((conn->handler == &Curl_handler_http2_ssl) || + (conn->handler == &Curl_handler_http2)) + return CURLE_OK; /* already done */ + + if(conn->handler->flags & PROTOPT_SSL) + conn->handler = &Curl_handler_http2_ssl; + else + conn->handler = &Curl_handler_http2; + + result = http2_init(conn); + if(result) { + Curl_add_buffer_free(&stream->header_recvbuf); + return result; + } + + infof(conn->data, "Using HTTP2, server supports multi-use\n"); + stream->upload_left = 0; + stream->upload_mem = NULL; + stream->upload_len = 0; + + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + + httpc->pause_stream_id = 0; + httpc->drain_total = 0; + + conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ + conn->httpversion = 20; + conn->bundle->multiuse = BUNDLE_MULTIPLEX; + + infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); + multi_connchanged(conn->data->multi); + + return CURLE_OK; +} + +CURLcode Curl_http2_switched(struct connectdata *conn, + const char *mem, size_t nread) +{ + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + int rv; + ssize_t nproc; + struct Curl_easy *data = conn->data; + struct HTTP *stream = conn->data->req.protop; + + result = Curl_http2_setup(conn); + if(result) + return result; + + httpc->recv_underlying = conn->recv[FIRSTSOCKET]; + httpc->send_underlying = conn->send[FIRSTSOCKET]; + conn->recv[FIRSTSOCKET] = http2_recv; + conn->send[FIRSTSOCKET] = http2_send; + + if(conn->data->req.upgr101 == UPGR101_RECEIVED) { + /* stream 1 is opened implicitly on upgrade */ + stream->stream_id = 1; + /* queue SETTINGS frame (again) */ + rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings, + httpc->binlen, NULL); + if(rv != 0) { + failf(data, "nghttp2_session_upgrade() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + + rv = nghttp2_session_set_stream_user_data(httpc->h2, + stream->stream_id, + data); + if(rv) { + infof(data, "http/2: failed to set user_data for stream %d!\n", + stream->stream_id); + DEBUGASSERT(0); + } + } + else { + populate_settings(conn, httpc); + + /* stream ID is unknown at this point */ + stream->stream_id = -1; + rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, + httpc->local_settings, + httpc->local_settings_num); + if(rv != 0) { + failf(data, "nghttp2_submit_settings() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + } + +#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE + rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0, + HTTP2_HUGE_WINDOW_SIZE); + if(rv != 0) { + failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } +#endif + + /* we are going to copy mem to httpc->inbuf. This is required since + mem is part of buffer pointed by stream->mem, and callbacks + called by nghttp2_session_mem_recv() will write stream specific + data into stream->mem, overwriting data already there. */ + if(H2_BUFSIZE < nread) { + failf(data, "connection buffer size is too small to store data following " + "HTTP Upgrade response header: buflen=%zu, datalen=%zu", + H2_BUFSIZE, nread); + return CURLE_HTTP2; + } + + infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer" + " after upgrade: len=%zu\n", + nread); + + if(nread) + memcpy(httpc->inbuf, mem, nread); + httpc->inbuflen = nread; + + nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf, + httpc->inbuflen); + + if(nghttp2_is_fatal((int)nproc)) { + failf(data, "nghttp2_session_mem_recv() failed: %s(%d)", + nghttp2_strerror((int)nproc), (int)nproc); + return CURLE_HTTP2; + } + + H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc)); + + if((ssize_t)nread == nproc) { + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + } + else { + httpc->nread_inbuf += nproc; + } + + /* Try to send some frames since we may read SETTINGS already. */ + rv = h2_session_send(data, httpc->h2); + + if(rv != 0) { + failf(data, "nghttp2_session_send() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } + + if(should_close_session(httpc)) { + H2BUGF(infof(data, + "nghttp2_session_send(): nothing to do in this session\n")); + return CURLE_HTTP2; + } + + return CURLE_OK; +} + +CURLcode Curl_http2_add_child(struct Curl_easy *parent, + struct Curl_easy *child, + bool exclusive) +{ + if(parent) { + struct Curl_http2_dep **tail; + struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep)); + if(!dep) + return CURLE_OUT_OF_MEMORY; + dep->data = child; + + if(parent->set.stream_dependents && exclusive) { + struct Curl_http2_dep *node = parent->set.stream_dependents; + while(node) { + node->data->set.stream_depends_on = child; + node = node->next; + } + + tail = &child->set.stream_dependents; + while(*tail) + tail = &(*tail)->next; + + DEBUGASSERT(!*tail); + *tail = parent->set.stream_dependents; + parent->set.stream_dependents = 0; + } + + tail = &parent->set.stream_dependents; + while(*tail) { + (*tail)->data->set.stream_depends_e = FALSE; + tail = &(*tail)->next; + } + + DEBUGASSERT(!*tail); + *tail = dep; + } + + child->set.stream_depends_on = parent; + child->set.stream_depends_e = exclusive; + return CURLE_OK; +} + +void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child) +{ + struct Curl_http2_dep *last = 0; + struct Curl_http2_dep *data = parent->set.stream_dependents; + DEBUGASSERT(child->set.stream_depends_on == parent); + + while(data && data->data != child) { + last = data; + data = data->next; + } + + DEBUGASSERT(data); + + if(data) { + if(last) { + last->next = data->next; + } + else { + parent->set.stream_dependents = data->next; + } + free(data); + } + + child->set.stream_depends_on = 0; + child->set.stream_depends_e = FALSE; +} + +void Curl_http2_cleanup_dependencies(struct Curl_easy *data) +{ + while(data->set.stream_dependents) { + struct Curl_easy *tmp = data->set.stream_dependents->data; + Curl_http2_remove_child(data, tmp); + if(data->set.stream_depends_on) + Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE); + } + + if(data->set.stream_depends_on) + Curl_http2_remove_child(data->set.stream_depends_on, data); +} + +/* Only call this function for a transfer that already got a HTTP/2 + CURLE_HTTP2_STREAM error! */ +bool Curl_h2_http_1_1_error(struct connectdata *conn) +{ + struct http_conn *httpc = &conn->proto.httpc; + return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED); +} + +#else /* !USE_NGHTTP2 */ + +/* Satisfy external references even if http2 is not compiled in. */ +#include + +char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num) +{ + (void) h; + (void) num; + return NULL; +} + +char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header) +{ + (void) h; + (void) header; + return NULL; +} + +#endif /* USE_NGHTTP2 */ diff --git a/libcurl/lib/http2.h b/libcurl/lib/http2.h new file mode 100644 index 0000000..93058cc --- /dev/null +++ b/libcurl/lib/http2.h @@ -0,0 +1,80 @@ +#ifndef HEADER_CURL_HTTP2_H +#define HEADER_CURL_HTTP2_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NGHTTP2 +#include "http.h" + +/* value for MAX_CONCURRENT_STREAMS we use until we get an updated setting + from the peer */ +#define DEFAULT_MAX_CONCURRENT_STREAMS 13 + +/* + * Store nghttp2 version info in this buffer, Prefix with a space. Return + * total length written. + */ +int Curl_http2_ver(char *p, size_t len); + +const char *Curl_http2_strerror(uint32_t err); + +CURLcode Curl_http2_init(struct connectdata *conn); +void Curl_http2_init_state(struct UrlState *state); +void Curl_http2_init_userset(struct UserDefined *set); +CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, + struct connectdata *conn); +CURLcode Curl_http2_setup(struct connectdata *conn); +CURLcode Curl_http2_switched(struct connectdata *conn, + const char *data, size_t nread); +/* called from http_setup_conn */ +void Curl_http2_setup_conn(struct connectdata *conn); +void Curl_http2_setup_req(struct Curl_easy *data); +void Curl_http2_done(struct connectdata *conn, bool premature); +CURLcode Curl_http2_done_sending(struct connectdata *conn); +CURLcode Curl_http2_add_child(struct Curl_easy *parent, + struct Curl_easy *child, + bool exclusive); +void Curl_http2_remove_child(struct Curl_easy *parent, + struct Curl_easy *child); +void Curl_http2_cleanup_dependencies(struct Curl_easy *data); + +/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ +bool Curl_h2_http_1_1_error(struct connectdata *conn); +#else /* USE_NGHTTP2 */ +#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_setup_conn(x) Curl_nop_stmt +#define Curl_http2_setup_req(x) +#define Curl_http2_init_state(x) +#define Curl_http2_init_userset(x) +#define Curl_http2_done(x,y) +#define Curl_http2_done_sending(x) +#define Curl_http2_add_child(x, y, z) +#define Curl_http2_remove_child(x, y) +#define Curl_http2_cleanup_dependencies(x) +#define Curl_h2_http_1_1_error(x) 0 +#endif + +#endif /* HEADER_CURL_HTTP2_H */ diff --git a/libcurl/lib/http_chunks.c b/libcurl/lib/http_chunks.c new file mode 100644 index 0000000..18dfcb2 --- /dev/null +++ b/libcurl/lib/http_chunks.c @@ -0,0 +1,351 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#include "urldata.h" /* it includes http_chunks.h */ +#include "sendf.h" /* for the client write stuff */ + +#include "content_encoding.h" +#include "http.h" +#include "non-ascii.h" /* for Curl_convert_to_network prototype */ +#include "strtoofft.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Chunk format (simplified): + * + * [ chunk extension ] CRLF + * CRLF + * + * Highlights from RFC2616 section 3.6 say: + + The chunked encoding modifies the body of a message in order to + transfer it as a series of chunks, each with its own size indicator, + followed by an OPTIONAL trailer containing entity-header fields. This + allows dynamically produced content to be transferred along with the + information necessary for the recipient to verify that it has + received the full message. + + Chunked-Body = *chunk + last-chunk + trailer + CRLF + + chunk = chunk-size [ chunk-extension ] CRLF + chunk-data CRLF + chunk-size = 1*HEX + last-chunk = 1*("0") [ chunk-extension ] CRLF + + chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) + chunk-ext-name = token + chunk-ext-val = token | quoted-string + chunk-data = chunk-size(OCTET) + trailer = *(entity-header CRLF) + + The chunk-size field is a string of hex digits indicating the size of + the chunk. The chunked encoding is ended by any chunk whose size is + zero, followed by the trailer, which is terminated by an empty line. + + */ + +#ifdef CURL_DOES_CONVERSIONS +/* Check for an ASCII hex digit. + We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */ +static bool Curl_isxdigit_ascii(char digit) +{ + return (digit >= 0x30 && digit <= 0x39) /* 0-9 */ + || (digit >= 0x41 && digit <= 0x46) /* A-F */ + || (digit >= 0x61 && digit <= 0x66); /* a-f */ +} +#else +#define Curl_isxdigit_ascii(x) Curl_isxdigit(x) +#endif + +void Curl_httpchunk_init(struct connectdata *conn) +{ + struct Curl_chunker *chunk = &conn->chunk; + chunk->hexindex = 0; /* start at 0 */ + chunk->dataleft = 0; /* no data left yet! */ + chunk->state = CHUNK_HEX; /* we get hex first! */ +} + +/* + * chunk_read() returns a OK for normal operations, or a positive return code + * for errors. STOP means this sequence of chunks is complete. The 'wrote' + * argument is set to tell the caller how many bytes we actually passed to the + * client (for byte-counting and whatever). + * + * The states and the state-machine is further explained in the header file. + * + * This function always uses ASCII hex values to accommodate non-ASCII hosts. + * For example, 0x0d and 0x0a are used instead of '\r' and '\n'. + */ +CHUNKcode Curl_httpchunk_read(struct connectdata *conn, + char *datap, + ssize_t datalen, + ssize_t *wrotep) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct Curl_chunker *ch = &conn->chunk; + struct SingleRequest *k = &data->req; + size_t piece; + curl_off_t length = (curl_off_t)datalen; + size_t *wrote = (size_t *)wrotep; + + *wrote = 0; /* nothing's written yet */ + + /* the original data is written to the client, but we go on with the + chunk read process, to properly calculate the content length*/ + if(data->set.http_te_skip && !k->ignorebody) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen); + if(result) + return CHUNKE_WRITE_ERROR; + } + + while(length) { + switch(ch->state) { + case CHUNK_HEX: + if(Curl_isxdigit_ascii(*datap)) { + if(ch->hexindex < MAXNUM_SIZE) { + ch->hexbuffer[ch->hexindex] = *datap; + datap++; + length--; + ch->hexindex++; + } + else { + return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */ + } + } + else { + char *endptr; + if(0 == ch->hexindex) + /* This is illegal data, we received junk where we expected + a hexadecimal digit. */ + return CHUNKE_ILLEGAL_HEX; + + /* length and datap are unmodified */ + ch->hexbuffer[ch->hexindex] = 0; + + /* convert to host encoding before calling strtoul */ + result = Curl_convert_from_network(conn->data, ch->hexbuffer, + ch->hexindex); + if(result) { + /* Curl_convert_from_network calls failf if unsuccessful */ + /* Treat it as a bad hex character */ + return CHUNKE_ILLEGAL_HEX; + } + + if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize)) + return CHUNKE_ILLEGAL_HEX; + ch->state = CHUNK_LF; /* now wait for the CRLF */ + } + break; + + case CHUNK_LF: + /* waiting for the LF after a chunk size */ + if(*datap == 0x0a) { + /* we're now expecting data to come, unless size was zero! */ + if(0 == ch->datasize) { + ch->state = CHUNK_TRAILER; /* now check for trailers */ + conn->trlPos = 0; + } + else + ch->state = CHUNK_DATA; + } + + datap++; + length--; + break; + + case CHUNK_DATA: + /* We expect 'datasize' of data. We have 'length' right now, it can be + more or less than 'datasize'. Get the smallest piece. + */ + piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize); + + /* Write the data portion available */ + if(!conn->data->set.http_te_skip && !k->ignorebody) { + if(!conn->data->set.http_ce_skip && k->writer_stack) + result = Curl_unencode_write(conn, k->writer_stack, datap, piece); + else + result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece); + + if(result) + return CHUNKE_WRITE_ERROR; + } + + *wrote += piece; + ch->datasize -= piece; /* decrease amount left to expect */ + datap += piece; /* move read pointer forward */ + length -= piece; /* decrease space left in this round */ + + if(0 == ch->datasize) + /* end of data this round, we now expect a trailing CRLF */ + ch->state = CHUNK_POSTLF; + break; + + case CHUNK_POSTLF: + if(*datap == 0x0a) { + /* The last one before we go back to hex state and start all over. */ + Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */ + } + else if(*datap != 0x0d) + return CHUNKE_BAD_CHUNK; + datap++; + length--; + break; + + case CHUNK_TRAILER: + if((*datap == 0x0d) || (*datap == 0x0a)) { + /* this is the end of a trailer, but if the trailer was zero bytes + there was no trailer and we move on */ + + if(conn->trlPos) { + /* we allocate trailer with 3 bytes extra room to fit this */ + conn->trailer[conn->trlPos++] = 0x0d; + conn->trailer[conn->trlPos++] = 0x0a; + conn->trailer[conn->trlPos] = 0; + + /* Convert to host encoding before calling Curl_client_write */ + result = Curl_convert_from_network(conn->data, conn->trailer, + conn->trlPos); + if(result) + /* Curl_convert_from_network calls failf if unsuccessful */ + /* Treat it as a bad chunk */ + return CHUNKE_BAD_CHUNK; + + if(!data->set.http_te_skip) { + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + conn->trailer, conn->trlPos); + if(result) + return CHUNKE_WRITE_ERROR; + } + conn->trlPos = 0; + ch->state = CHUNK_TRAILER_CR; + if(*datap == 0x0a) + /* already on the LF */ + break; + } + else { + /* no trailer, we're on the final CRLF pair */ + ch->state = CHUNK_TRAILER_POSTCR; + break; /* don't advance the pointer */ + } + } + else { + /* conn->trailer is assumed to be freed in url.c on a + connection basis */ + if(conn->trlPos >= conn->trlMax) { + /* we always allocate three extra bytes, just because when the full + header has been received we append CRLF\0 */ + char *ptr; + if(conn->trlMax) { + conn->trlMax *= 2; + ptr = realloc(conn->trailer, conn->trlMax + 3); + } + else { + conn->trlMax = 128; + ptr = malloc(conn->trlMax + 3); + } + if(!ptr) + return CHUNKE_OUT_OF_MEMORY; + conn->trailer = ptr; + } + conn->trailer[conn->trlPos++]=*datap; + } + datap++; + length--; + break; + + case CHUNK_TRAILER_CR: + if(*datap == 0x0a) { + ch->state = CHUNK_TRAILER_POSTCR; + datap++; + length--; + } + else + return CHUNKE_BAD_CHUNK; + break; + + case CHUNK_TRAILER_POSTCR: + /* We enter this state when a CR should arrive so we expect to + have to first pass a CR before we wait for LF */ + if((*datap != 0x0d) && (*datap != 0x0a)) { + /* not a CR then it must be another header in the trailer */ + ch->state = CHUNK_TRAILER; + break; + } + if(*datap == 0x0d) { + /* skip if CR */ + datap++; + length--; + } + /* now wait for the final LF */ + ch->state = CHUNK_STOP; + break; + + case CHUNK_STOP: + if(*datap == 0x0a) { + length--; + + /* Record the length of any data left in the end of the buffer + even if there's no more chunks to read */ + ch->dataleft = curlx_sotouz(length); + + return CHUNKE_STOP; /* return stop */ + } + else + return CHUNKE_BAD_CHUNK; + } + } + return CHUNKE_OK; +} + +const char *Curl_chunked_strerror(CHUNKcode code) +{ + switch(code) { + default: + return "OK"; + case CHUNKE_TOO_LONG_HEX: + return "Too long hexadecimal number"; + case CHUNKE_ILLEGAL_HEX: + return "Illegal or missing hexadecimal sequence"; + case CHUNKE_BAD_CHUNK: + return "Malformed encoding found"; + case CHUNKE_WRITE_ERROR: + return "Write error"; + case CHUNKE_BAD_ENCODING: + return "Bad content-encoding found"; + case CHUNKE_OUT_OF_MEMORY: + return "Out of memory"; + } +} + +#endif /* CURL_DISABLE_HTTP */ diff --git a/libcurl/lib/http_chunks.h b/libcurl/lib/http_chunks.h new file mode 100644 index 0000000..b969c55 --- /dev/null +++ b/libcurl/lib/http_chunks.h @@ -0,0 +1,90 @@ +#ifndef HEADER_CURL_HTTP_CHUNKS_H +#define HEADER_CURL_HTTP_CHUNKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + * The longest possible hexadecimal number we support in a chunked transfer. + * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul() + * to convert it, we "only" support 2^32 bytes chunk data. + */ +#define MAXNUM_SIZE 16 + +typedef enum { + /* await and buffer all hexadecimal digits until we get one that isn't a + hexadecimal digit. When done, we go CHUNK_LF */ + CHUNK_HEX, + + /* wait for LF, ignore all else */ + CHUNK_LF, + + /* We eat the amount of data specified. When done, we move on to the + POST_CR state. */ + CHUNK_DATA, + + /* POSTLF should get a CR and then a LF and nothing else, then move back to + HEX as the CRLF combination marks the end of a chunk. A missing CR is no + big deal. */ + CHUNK_POSTLF, + + /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft' + field in the struct that will tell how many bytes that were not passed to + the client in the end of the last buffer! */ + CHUNK_STOP, + + /* At this point optional trailer headers can be found, unless the next line + is CRLF */ + CHUNK_TRAILER, + + /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR. + Next char must be a LF */ + CHUNK_TRAILER_CR, + + /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be + signalled If this is an empty trailer CHUNKE_STOP will be signalled. + Otherwise the trailer will be broadcasted via Curl_client_write() and the + next state will be CHUNK_TRAILER */ + CHUNK_TRAILER_POSTCR +} ChunkyState; + +typedef enum { + CHUNKE_STOP = -1, + CHUNKE_OK = 0, + CHUNKE_TOO_LONG_HEX = 1, + CHUNKE_ILLEGAL_HEX, + CHUNKE_BAD_CHUNK, + CHUNKE_WRITE_ERROR, + CHUNKE_BAD_ENCODING, + CHUNKE_OUT_OF_MEMORY, + CHUNKE_LAST +} CHUNKcode; + +const char *Curl_chunked_strerror(CHUNKcode code); + +struct Curl_chunker { + char hexbuffer[ MAXNUM_SIZE + 1]; + int hexindex; + ChunkyState state; + curl_off_t datasize; + size_t dataleft; /* untouched data amount at the end of the last buffer */ +}; + +#endif /* HEADER_CURL_HTTP_CHUNKS_H */ diff --git a/libcurl/lib/http_digest.c b/libcurl/lib/http_digest.c new file mode 100644 index 0000000..9616c30 --- /dev/null +++ b/libcurl/lib/http_digest.c @@ -0,0 +1,181 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include "urldata.h" +#include "strcase.h" +#include "vauth/vauth.h" +#include "http_digest.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Test example headers: + +WWW-Authenticate: Digest realm="testrealm", nonce="1053604598" +Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598" + +*/ + +CURLcode Curl_input_digest(struct connectdata *conn, + bool proxy, + const char *header) /* rest of the *-authenticate: + header */ +{ + struct Curl_easy *data = conn->data; + + /* Point to the correct struct with this */ + struct digestdata *digest; + + if(proxy) { + digest = &data->state.proxydigest; + } + else { + digest = &data->state.digest; + } + + if(!checkprefix("Digest", header)) + return CURLE_BAD_CONTENT_ENCODING; + + header += strlen("Digest"); + while(*header && ISSPACE(*header)) + header++; + + return Curl_auth_decode_digest_http_message(header, digest); +} + +CURLcode Curl_output_digest(struct connectdata *conn, + bool proxy, + const unsigned char *request, + const unsigned char *uripath) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + unsigned char *path = NULL; + char *tmp = NULL; + char *response; + size_t len; + bool have_chlg; + + /* Point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + + /* Point to the name and password for this */ + const char *userp; + const char *passwdp; + + /* Point to the correct struct with this */ + struct digestdata *digest; + struct auth *authp; + + if(proxy) { + digest = &data->state.proxydigest; + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; + authp = &data->state.authproxy; + } + else { + digest = &data->state.digest; + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + passwdp = conn->passwd; + authp = &data->state.authhost; + } + + Curl_safefree(*allocuserpwd); + + /* not set means empty */ + if(!userp) + userp = ""; + + if(!passwdp) + passwdp = ""; + +#if defined(USE_WINDOWS_SSPI) + have_chlg = digest->input_token ? TRUE : FALSE; +#else + have_chlg = digest->nonce ? TRUE : FALSE; +#endif + + if(!have_chlg) { + authp->done = FALSE; + return CURLE_OK; + } + + /* So IE browsers < v7 cut off the URI part at the query part when they + evaluate the MD5 and some (IIS?) servers work with them so we may need to + do the Digest IE-style. Note that the different ways cause different MD5 + sums to get sent. + + Apache servers can be set to do the Digest IE-style automatically using + the BrowserMatch feature: + https://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html#msie + + Further details on Digest implementation differences: + http://www.fngtps.com/2006/09/http-authentication + */ + + if(authp->iestyle) { + tmp = strchr((char *)uripath, '?'); + if(tmp) { + size_t urilen = tmp - (char *)uripath; + path = (unsigned char *) aprintf("%.*s", urilen, uripath); + } + } + if(!tmp) + path = (unsigned char *) strdup((char *) uripath); + + if(!path) + return CURLE_OUT_OF_MEMORY; + + result = Curl_auth_create_digest_http_message(data, userp, passwdp, request, + path, digest, &response, &len); + free(path); + if(result) + return result; + + *allocuserpwd = aprintf("%sAuthorization: Digest %s\r\n", + proxy ? "Proxy-" : "", + response); + free(response); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + authp->done = TRUE; + + return CURLE_OK; +} + +void Curl_http_auth_cleanup_digest(struct Curl_easy *data) +{ + Curl_auth_digest_cleanup(&data->state.digest); + Curl_auth_digest_cleanup(&data->state.proxydigest); +} + +#endif diff --git a/libcurl/lib/http_digest.h b/libcurl/lib/http_digest.h new file mode 100644 index 0000000..73410ae --- /dev/null +++ b/libcurl/lib/http_digest.h @@ -0,0 +1,42 @@ +#ifndef HEADER_CURL_HTTP_DIGEST_H +#define HEADER_CURL_HTTP_DIGEST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + +/* this is for digest header input */ +CURLcode Curl_input_digest(struct connectdata *conn, + bool proxy, const char *header); + +/* this is for creating digest header output */ +CURLcode Curl_output_digest(struct connectdata *conn, + bool proxy, + const unsigned char *request, + const unsigned char *uripath); + +void Curl_http_auth_cleanup_digest(struct Curl_easy *data); + +#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */ + +#endif /* HEADER_CURL_HTTP_DIGEST_H */ diff --git a/libcurl/lib/http_negotiate.c b/libcurl/lib/http_negotiate.c new file mode 100644 index 0000000..c8f4064 --- /dev/null +++ b/libcurl/lib/http_negotiate.c @@ -0,0 +1,220 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + +#include "urldata.h" +#include "sendf.h" +#include "http_negotiate.h" +#include "vauth/vauth.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + size_t len; + + /* Point to the username, password, service and host */ + const char *userp; + const char *passwdp; + const char *service; + const char *host; + + /* Point to the correct struct with this */ + struct negotiatedata *neg_ctx; + curlnegotiate state; + + if(proxy) { + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; + service = data->set.str[STRING_PROXY_SERVICE_NAME] ? + data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; + host = conn->http_proxy.host.name; + neg_ctx = &conn->proxyneg; + state = conn->proxy_negotiate_state; + } + else { + userp = conn->user; + passwdp = conn->passwd; + service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : "HTTP"; + host = conn->host.name; + neg_ctx = &conn->negotiate; + state = conn->http_negotiate_state; + } + + /* Not set means empty */ + if(!userp) + userp = ""; + + if(!passwdp) + passwdp = ""; + + /* Obtain the input token, if any */ + header += strlen("Negotiate"); + while(*header && ISSPACE(*header)) + header++; + + len = strlen(header); + neg_ctx->havenegdata = len != 0; + if(!len) { + if(state == GSS_AUTHSUCC) { + infof(conn->data, "Negotiate auth restarted\n"); + Curl_http_auth_cleanup_negotiate(conn); + } + else if(state != GSS_AUTHNONE) { + /* The server rejected our authentication and hasn't supplied any more + negotiation mechanisms */ + Curl_http_auth_cleanup_negotiate(conn); + return CURLE_LOGIN_DENIED; + } + } + + /* Supports SSL channel binding for Windows ISS extended protection */ +#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS) + neg_ctx->sslContext = conn->sslContext; +#endif + + /* Initialize the security context and decode our challenge */ + result = Curl_auth_decode_spnego_message(data, userp, passwdp, service, + host, header, neg_ctx); + + if(result) + Curl_http_auth_cleanup_negotiate(conn); + + return result; +} + +CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) +{ + struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg : + &conn->negotiate; + struct auth *authp = proxy ? &conn->data->state.authproxy : + &conn->data->state.authhost; + curlnegotiate *state = proxy ? &conn->proxy_negotiate_state : + &conn->http_negotiate_state; + char *base64 = NULL; + size_t len = 0; + char *userp; + CURLcode result; + + authp->done = FALSE; + + if(*state == GSS_AUTHRECV) { + if(neg_ctx->havenegdata) { + neg_ctx->havemultiplerequests = TRUE; + } + } + else if(*state == GSS_AUTHSUCC) { + if(!neg_ctx->havenoauthpersist) { + neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests; + } + } + + if(neg_ctx->noauthpersist || + (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) { + + if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) { + infof(conn->data, "Curl_output_negotiate, " + "no persistent authentication: cleanup existing context"); + Curl_http_auth_cleanup_negotiate(conn); + } + if(!neg_ctx->context) { + result = Curl_input_negotiate(conn, proxy, "Negotiate"); + if(result == CURLE_LOGIN_DENIED) { + /* negotiate auth failed, let's continue unauthenticated to stay + * compatible with the behavior before curl-7_64_0-158-g6c6035532 */ + conn->data->state.authproblem = TRUE; + return CURLE_OK; + } + else if(result) + return result; + } + + result = Curl_auth_create_spnego_message(conn->data, + neg_ctx, &base64, &len); + if(result) + return result; + + userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", + base64); + + if(proxy) { + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = userp; + } + else { + Curl_safefree(conn->allocptr.userpwd); + conn->allocptr.userpwd = userp; + } + + free(base64); + + if(userp == NULL) { + return CURLE_OUT_OF_MEMORY; + } + + *state = GSS_AUTHSENT; + #ifdef HAVE_GSSAPI + if(neg_ctx->status == GSS_S_COMPLETE || + neg_ctx->status == GSS_S_CONTINUE_NEEDED) { + *state = GSS_AUTHDONE; + } + #else + #ifdef USE_WINDOWS_SSPI + if(neg_ctx->status == SEC_E_OK || + neg_ctx->status == SEC_I_CONTINUE_NEEDED) { + *state = GSS_AUTHDONE; + } + #endif + #endif + } + + if(*state == GSS_AUTHDONE || *state == GSS_AUTHSUCC) { + /* connection is already authenticated, + * don't send a header in future requests */ + authp->done = TRUE; + } + + neg_ctx->havenegdata = FALSE; + + return CURLE_OK; +} + +void Curl_http_auth_cleanup_negotiate(struct connectdata *conn) +{ + conn->http_negotiate_state = GSS_AUTHNONE; + conn->proxy_negotiate_state = GSS_AUTHNONE; + + Curl_auth_cleanup_spnego(&conn->negotiate); + Curl_auth_cleanup_spnego(&conn->proxyneg); +} + +#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ diff --git a/libcurl/lib/http_negotiate.h b/libcurl/lib/http_negotiate.h new file mode 100644 index 0000000..4f0ac16 --- /dev/null +++ b/libcurl/lib/http_negotiate.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_HTTP_NEGOTIATE_H +#define HEADER_CURL_HTTP_NEGOTIATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + +/* this is for Negotiate header input */ +CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating Negotiate header output */ +CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); + +void Curl_http_auth_cleanup_negotiate(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ + +#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */ diff --git a/libcurl/lib/http_ntlm.c b/libcurl/lib/http_ntlm.c new file mode 100644 index 0000000..e4a4fe0 --- /dev/null +++ b/libcurl/lib/http_ntlm.c @@ -0,0 +1,259 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + +/* + * NTLM details: + * + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#include "urldata.h" +#include "sendf.h" +#include "strcase.h" +#include "http_ntlm.h" +#include "curl_ntlm_core.h" +#include "curl_ntlm_wb.h" +#include "vauth/vauth.h" +#include "url.h" + +/* SSL backend-specific #if branches in this file must be kept in the order + documented in curl_ntlm_core. */ +#if defined(NTLM_NEEDS_NSS_INIT) +#include "vtls/nssg.h" +#elif defined(USE_WINDOWS_SSPI) +#include "curl_sspi.h" +#endif + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if DEBUG_ME +# define DEBUG_OUT(x) x +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +CURLcode Curl_input_ntlm(struct connectdata *conn, + bool proxy, /* if proxy or not */ + const char *header) /* rest of the www-authenticate: + header */ +{ + /* point to the correct struct with this */ + struct ntlmdata *ntlm; + curlntlm *state; + CURLcode result = CURLE_OK; + + ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; + state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state; + + if(checkprefix("NTLM", header)) { + header += strlen("NTLM"); + + while(*header && ISSPACE(*header)) + header++; + + if(*header) { + result = Curl_auth_decode_ntlm_type2_message(conn->data, header, ntlm); + if(result) + return result; + + *state = NTLMSTATE_TYPE2; /* We got a type-2 message */ + } + else { + if(*state == NTLMSTATE_LAST) { + infof(conn->data, "NTLM auth restarted\n"); + Curl_http_auth_cleanup_ntlm(conn); + } + else if(*state == NTLMSTATE_TYPE3) { + infof(conn->data, "NTLM handshake rejected\n"); + Curl_http_auth_cleanup_ntlm(conn); + *state = NTLMSTATE_NONE; + return CURLE_REMOTE_ACCESS_DENIED; + } + else if(*state >= NTLMSTATE_TYPE1) { + infof(conn->data, "NTLM handshake failure (internal error)\n"); + return CURLE_REMOTE_ACCESS_DENIED; + } + + *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */ + } + } + + return result; +} + +/* + * This is for creating ntlm header output + */ +CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) +{ + char *base64 = NULL; + size_t len = 0; + CURLcode result; + + /* point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + + /* point to the username, password, service and host */ + const char *userp; + const char *passwdp; + const char *service = NULL; + const char *hostname = NULL; + + /* point to the correct struct with this */ + struct ntlmdata *ntlm; + curlntlm *state; + struct auth *authp; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + +#if defined(NTLM_NEEDS_NSS_INIT) + if(CURLE_OK != Curl_nss_force_init(conn->data)) + return CURLE_OUT_OF_MEMORY; +#endif + + if(proxy) { + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; + service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ? + conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; + hostname = conn->http_proxy.host.name; + ntlm = &conn->proxyntlm; + state = &conn->proxy_ntlm_state; + authp = &conn->data->state.authproxy; + } + else { + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + passwdp = conn->passwd; + service = conn->data->set.str[STRING_SERVICE_NAME] ? + conn->data->set.str[STRING_SERVICE_NAME] : "HTTP"; + hostname = conn->host.name; + ntlm = &conn->ntlm; + state = &conn->http_ntlm_state; + authp = &conn->data->state.authhost; + } + authp->done = FALSE; + + /* not set means empty */ + if(!userp) + userp = ""; + + if(!passwdp) + passwdp = ""; + +#ifdef USE_WINDOWS_SSPI + if(s_hSecDll == NULL) { + /* not thread safe and leaks - use curl_global_init() to avoid */ + CURLcode err = Curl_sspi_global_init(); + if(s_hSecDll == NULL) + return err; + } +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + ntlm->sslContext = conn->sslContext; +#endif +#endif + + switch(*state) { + case NTLMSTATE_TYPE1: + default: /* for the weird cases we (re)start here */ + /* Create a type-1 message */ + result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp, + service, hostname, + ntlm, &base64, + &len); + if(result) + return result; + + if(base64) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); + } + break; + + case NTLMSTATE_TYPE2: + /* We already received the type-2 message, create a type-3 message */ + result = Curl_auth_create_ntlm_type3_message(conn->data, userp, passwdp, + ntlm, &base64, &len); + if(result) + return result; + + if(base64) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + return CURLE_OUT_OF_MEMORY; + + DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); + + *state = NTLMSTATE_TYPE3; /* we send a type-3 */ + authp->done = TRUE; + } + break; + + case NTLMSTATE_TYPE3: + /* connection is already authenticated, + * don't send a header in future requests */ + *state = NTLMSTATE_LAST; + /* FALLTHROUGH */ + case NTLMSTATE_LAST: + Curl_safefree(*allocuserpwd); + authp->done = TRUE; + break; + } + + return CURLE_OK; +} + +void Curl_http_auth_cleanup_ntlm(struct connectdata *conn) +{ + Curl_auth_cleanup_ntlm(&conn->ntlm); + Curl_auth_cleanup_ntlm(&conn->proxyntlm); + +#if defined(NTLM_WB_ENABLED) + Curl_http_auth_cleanup_ntlm_wb(conn); +#endif +} + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM */ diff --git a/libcurl/lib/http_ntlm.h b/libcurl/lib/http_ntlm.h new file mode 100644 index 0000000..003714d --- /dev/null +++ b/libcurl/lib/http_ntlm.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_HTTP_NTLM_H +#define HEADER_CURL_HTTP_NTLM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + +/* this is for ntlm header input */ +CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating ntlm header output */ +CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); + +void Curl_http_auth_cleanup_ntlm(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM */ + +#endif /* HEADER_CURL_HTTP_NTLM_H */ diff --git a/libcurl/lib/http_proxy.c b/libcurl/lib/http_proxy.c new file mode 100644 index 0000000..ba67b86 --- /dev/null +++ b/libcurl/lib/http_proxy.c @@ -0,0 +1,686 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "http_proxy.h" + +#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) + +#include +#include "sendf.h" +#include "http.h" +#include "url.h" +#include "select.h" +#include "progress.h" +#include "non-ascii.h" +#include "connect.h" +#include "curlx.h" +#include "vtls/vtls.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Perform SSL initialization for HTTPS proxy. Sets + * proxy_ssl_connected connection bit when complete. Can be + * called multiple times. + */ +static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex) +{ +#ifdef USE_SSL + CURLcode result = CURLE_OK; + DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS); + if(!conn->bits.proxy_ssl_connected[sockindex]) { + /* perform SSL initialization for this socket */ + result = + Curl_ssl_connect_nonblocking(conn, sockindex, + &conn->bits.proxy_ssl_connected[sockindex]); + if(result) + conn->bits.close = TRUE; /* a failed connection is marked for closure to + prevent (bad) re-use or similar */ + } + return result; +#else + (void) conn; + (void) sockindex; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex) +{ + if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) { + const CURLcode result = https_proxy_connect(conn, sockindex); + if(result) + return result; + if(!conn->bits.proxy_ssl_connected[sockindex]) + return result; /* wait for HTTPS proxy SSL initialization to complete */ + } + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { +#ifndef CURL_DISABLE_PROXY + /* for [protocol] tunneled through HTTP proxy */ + struct HTTP http_proxy; + void *prot_save; + const char *hostname; + int remote_port; + CURLcode result; + + /* BLOCKING */ + /* We want "seamless" operations through HTTP proxy tunnel */ + + /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the + * member conn->proto.http; we want [protocol] through HTTP and we have + * to change the member temporarily for connecting to the HTTP + * proxy. After Curl_proxyCONNECT we have to set back the member to the + * original pointer + * + * This function might be called several times in the multi interface case + * if the proxy's CONNECT response is not instant. + */ + prot_save = conn->data->req.protop; + memset(&http_proxy, 0, sizeof(http_proxy)); + conn->data->req.protop = &http_proxy; + connkeep(conn, "HTTP proxy CONNECT"); + + /* for the secondary socket (FTP), use the "connect to host" + * but ignore the "connect to port" (use the secondary port) + */ + + if(conn->bits.conn_to_host) + hostname = conn->conn_to_host.name; + else if(sockindex == SECONDARYSOCKET) + hostname = conn->secondaryhostname; + else + hostname = conn->host.name; + + if(sockindex == SECONDARYSOCKET) + remote_port = conn->secondary_port; + else if(conn->bits.conn_to_port) + remote_port = conn->conn_to_port; + else + remote_port = conn->remote_port; + result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port); + conn->data->req.protop = prot_save; + if(CURLE_OK != result) + return result; + Curl_safefree(conn->allocptr.proxyuserpwd); +#else + return CURLE_NOT_BUILT_IN; +#endif + } + /* no HTTP tunnel proxy, just return */ + return CURLE_OK; +} + +bool Curl_connect_complete(struct connectdata *conn) +{ + return !conn->connect_state || + (conn->connect_state->tunnel_state == TUNNEL_COMPLETE); +} + +bool Curl_connect_ongoing(struct connectdata *conn) +{ + return conn->connect_state && + (conn->connect_state->tunnel_state != TUNNEL_COMPLETE); +} + +static CURLcode connect_init(struct connectdata *conn, bool reinit) +{ + struct http_connect_state *s; + if(!reinit) { + DEBUGASSERT(!conn->connect_state); + s = calloc(1, sizeof(struct http_connect_state)); + if(!s) + return CURLE_OUT_OF_MEMORY; + infof(conn->data, "allocate connect buffer!\n"); + conn->connect_state = s; + } + else { + DEBUGASSERT(conn->connect_state); + s = conn->connect_state; + } + s->tunnel_state = TUNNEL_INIT; + s->keepon = TRUE; + s->line_start = s->connect_buffer; + s->ptr = s->line_start; + s->cl = 0; + s->close_connection = FALSE; + return CURLE_OK; +} + +static void connect_done(struct connectdata *conn) +{ + struct http_connect_state *s = conn->connect_state; + s->tunnel_state = TUNNEL_COMPLETE; + infof(conn->data, "CONNECT phase completed!\n"); +} + +static CURLcode CONNECT(struct connectdata *conn, + int sockindex, + const char *hostname, + int remote_port) +{ + int subversion = 0; + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + CURLcode result; + curl_socket_t tunnelsocket = conn->sock[sockindex]; + struct http_connect_state *s = conn->connect_state; + +#define SELECT_OK 0 +#define SELECT_ERROR 1 + + if(Curl_connect_complete(conn)) + return CURLE_OK; /* CONNECT is already completed */ + + conn->bits.proxy_connect_closed = FALSE; + + do { + timediff_t check; + if(TUNNEL_INIT == s->tunnel_state) { + /* BEGIN CONNECT PHASE */ + char *host_port; + Curl_send_buffer *req_buffer; + + infof(data, "Establish HTTP proxy tunnel to %s:%d\n", + hostname, remote_port); + + /* This only happens if we've looped here due to authentication + reasons, and we don't really use the newly cloned URL here + then. Just free() it. */ + free(data->req.newurl); + data->req.newurl = NULL; + + /* initialize a dynamic send-buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + host_port = aprintf("%s:%d", hostname, remote_port); + if(!host_port) { + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the proxy-authorization header, if any */ + result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE); + + free(host_port); + + if(!result) { + char *host = NULL; + const char *proxyconn = ""; + const char *useragent = ""; + const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? + "1.0" : "1.1"; + bool ipv6_ip = conn->bits.ipv6_ip; + char *hostheader; + + /* the hostname may be different */ + if(hostname != conn->host.name) + ipv6_ip = (strchr(hostname, ':') != NULL); + hostheader = /* host:port with IPv6 support */ + aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", + remote_port); + if(!hostheader) { + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + + if(!Curl_checkProxyheaders(conn, "Host")) { + host = aprintf("Host: %s\r\n", hostheader); + if(!host) { + free(hostheader); + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + } + if(!Curl_checkProxyheaders(conn, "Proxy-Connection")) + proxyconn = "Proxy-Connection: Keep-Alive\r\n"; + + if(!Curl_checkProxyheaders(conn, "User-Agent") && + data->set.str[STRING_USERAGENT]) + useragent = conn->allocptr.uagent; + + result = + Curl_add_bufferf(&req_buffer, + "CONNECT %s HTTP/%s\r\n" + "%s" /* Host: */ + "%s" /* Proxy-Authorization */ + "%s" /* User-Agent */ + "%s", /* Proxy-Connection */ + hostheader, + http, + host?host:"", + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + useragent, + proxyconn); + + if(host) + free(host); + free(hostheader); + + if(!result) + result = Curl_add_custom_headers(conn, TRUE, req_buffer); + + if(!result) + /* CRLF terminate the request */ + result = Curl_add_bufferf(&req_buffer, "\r\n"); + + if(!result) { + /* Send the connect request to the proxy */ + /* BLOCKING */ + result = + Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, sockindex); + } + req_buffer = NULL; + if(result) + failf(data, "Failed sending CONNECT to proxy"); + } + + Curl_add_buffer_free(&req_buffer); + if(result) + return result; + + s->tunnel_state = TUNNEL_CONNECT; + s->perline = 0; + } /* END CONNECT PHASE */ + + check = Curl_timeleft(data, NULL, TRUE); + if(check <= 0) { + failf(data, "Proxy CONNECT aborted due to timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(!Curl_conn_data_pending(conn, sockindex)) + /* return so we'll be called again polling-style */ + return CURLE_OK; + + /* at this point, the tunnel_connecting phase is over. */ + + { /* READING RESPONSE PHASE */ + int error = SELECT_OK; + + while(s->keepon && !error) { + ssize_t gotbytes; + + /* make sure we have space to read more data */ + if(s->ptr >= &s->connect_buffer[CONNECT_BUFFER_SIZE]) { + failf(data, "CONNECT response too large!"); + return CURLE_RECV_ERROR; + } + + /* Read one byte at a time to avoid a race condition. Wait at most one + second before looping to ensure continuous pgrsUpdates. */ + result = Curl_read(conn, tunnelsocket, s->ptr, 1, &gotbytes); + if(result == CURLE_AGAIN) + /* socket buffer drained, return */ + return CURLE_OK; + + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + if(result) { + s->keepon = FALSE; + break; + } + else if(gotbytes <= 0) { + if(data->set.proxyauth && data->state.authproxy.avail) { + /* proxy auth was requested and there was proxy auth available, + then deem this as "mere" proxy disconnect */ + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Proxy CONNECT connection closed\n"); + } + else { + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted"); + } + s->keepon = FALSE; + break; + } + + + if(s->keepon > TRUE) { + /* This means we are currently ignoring a response-body */ + + s->ptr = s->connect_buffer; + if(s->cl) { + /* A Content-Length based body: simply count down the counter + and make sure to break out of the loop when we're done! */ + s->cl--; + if(s->cl <= 0) { + s->keepon = FALSE; + s->tunnel_state = TUNNEL_COMPLETE; + break; + } + } + else { + /* chunked-encoded body, so we need to do the chunked dance + properly to know when the end of the body is reached */ + CHUNKcode r; + ssize_t tookcareof = 0; + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, s->ptr, 1, &tookcareof); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + s->keepon = FALSE; + /* we did the full CONNECT treatment, go COMPLETE */ + s->tunnel_state = TUNNEL_COMPLETE; + } + } + continue; + } + + s->perline++; /* amount of bytes in this line so far */ + + /* if this is not the end of a header line then continue */ + if(*s->ptr != 0x0a) { + s->ptr++; + continue; + } + + /* convert from the network encoding */ + result = Curl_convert_from_network(data, s->line_start, + (size_t)s->perline); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + + /* output debug if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + s->line_start, (size_t)s->perline); + + if(!data->set.suppress_connect_headers) { + /* send the header to the callback */ + int writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + result = Curl_client_write(conn, writetype, + s->line_start, s->perline); + if(result) + return result; + } + + data->info.header_size += (long)s->perline; + data->req.headerbytecount += (long)s->perline; + + /* Newlines are CRLF, so the CR is ignored as the line isn't + really terminated until the LF comes. Treat a following CR + as end-of-headers as well.*/ + + if(('\r' == s->line_start[0]) || + ('\n' == s->line_start[0])) { + /* end of response-headers from the proxy */ + s->ptr = s->connect_buffer; + if((407 == k->httpcode) && !data->state.authproblem) { + /* If we get a 407 response code with content length + when we have no auth problem, we must ignore the + whole response-body */ + s->keepon = 2; + + if(s->cl) { + infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T + " bytes of response-body\n", s->cl); + } + else if(s->chunked_encoding) { + CHUNKcode r; + + infof(data, "Ignore chunked response-body\n"); + + /* We set ignorebody true here since the chunked + decoder function will acknowledge that. Pay + attention so that this is cleared again when this + function returns! */ + k->ignorebody = TRUE; + + if(s->line_start[1] == '\n') { + /* this can only be a LF if the letter at index 0 + was a CR */ + s->line_start++; + } + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, s->line_start + 1, 1, &gotbytes); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + s->keepon = FALSE; + /* we did the full CONNECT treatment, go to COMPLETE */ + s->tunnel_state = TUNNEL_COMPLETE; + } + } + else { + /* without content-length or chunked encoding, we + can't keep the connection alive since the close is + the end signal so we bail out at once instead */ + s->keepon = FALSE; + } + } + else + s->keepon = FALSE; + if(!s->cl) + /* we did the full CONNECT treatment, go to COMPLETE */ + s->tunnel_state = TUNNEL_COMPLETE; + continue; + } + + s->line_start[s->perline] = 0; /* zero terminate the buffer */ + if((checkprefix("WWW-Authenticate:", s->line_start) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", s->line_start) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(s->line_start); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(conn, proxy, auth); + + free(auth); + + if(result) + return result; + } + else if(checkprefix("Content-Length:", s->line_start)) { + if(k->httpcode/100 == 2) { + /* A client MUST ignore any Content-Length or Transfer-Encoding + header fields received in a successful response to CONNECT. + "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ + infof(data, "Ignoring Content-Length in CONNECT %03d response\n", + k->httpcode); + } + else { + (void)curlx_strtoofft(s->line_start + + strlen("Content-Length:"), NULL, 10, &s->cl); + } + } + else if(Curl_compareheader(s->line_start, "Connection:", "close")) + s->close_connection = TRUE; + else if(checkprefix("Transfer-Encoding:", s->line_start)) { + if(k->httpcode/100 == 2) { + /* A client MUST ignore any Content-Length or Transfer-Encoding + header fields received in a successful response to CONNECT. + "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ + infof(data, "Ignoring Transfer-Encoding in " + "CONNECT %03d response\n", k->httpcode); + } + else if(Curl_compareheader(s->line_start, + "Transfer-Encoding:", "chunked")) { + infof(data, "CONNECT responded chunked\n"); + s->chunked_encoding = TRUE; + /* init our chunky engine */ + Curl_httpchunk_init(conn); + } + } + else if(Curl_compareheader(s->line_start, + "Proxy-Connection:", "close")) + s->close_connection = TRUE; + else if(2 == sscanf(s->line_start, "HTTP/1.%d %d", + &subversion, + &k->httpcode)) { + /* store the HTTP code from the proxy */ + data->info.httpproxycode = k->httpcode; + } + + s->perline = 0; /* line starts over here */ + s->ptr = s->connect_buffer; + s->line_start = s->ptr; + } /* while there's buffer left and loop is requested */ + + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + if(error) + return CURLE_RECV_ERROR; + + if(data->info.httpproxycode/100 != 2) { + /* Deal with the possibly already received authenticate + headers. 'newurl' is set to a new URL if we must loop. */ + result = Curl_http_auth_act(conn); + if(result) + return result; + + if(conn->bits.close) + /* the connection has been marked for closure, most likely in the + Curl_http_auth_act() function and thus we can kill it at once + below */ + s->close_connection = TRUE; + } + + if(s->close_connection && data->req.newurl) { + /* Connection closed by server. Don't use it anymore */ + Curl_closesocket(conn, conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + break; + } + } /* END READING RESPONSE PHASE */ + + /* If we are supposed to continue and request a new URL, which basically + * means the HTTP authentication is still going on so if the tunnel + * is complete we start over in INIT state */ + if(data->req.newurl && (TUNNEL_COMPLETE == s->tunnel_state)) { + connect_init(conn, TRUE); /* reinit */ + } + + } while(data->req.newurl); + + if(data->info.httpproxycode/100 != 2) { + if(s->close_connection && data->req.newurl) { + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Connect me again please\n"); + connect_done(conn); + } + else { + free(data->req.newurl); + data->req.newurl = NULL; + /* failure, close this connection to avoid re-use */ + streamclose(conn, "proxy CONNECT failure"); + Curl_closesocket(conn, conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + } + + /* to back to init state */ + s->tunnel_state = TUNNEL_INIT; + + if(conn->bits.proxy_connect_closed) + /* this is not an error, just part of the connection negotiation */ + return CURLE_OK; + failf(data, "Received HTTP code %d from proxy after CONNECT", + data->req.httpcode); + return CURLE_RECV_ERROR; + } + + s->tunnel_state = TUNNEL_COMPLETE; + + /* If a proxy-authorization header was used for the proxy, then we should + make sure that it isn't accidentally used for the document request + after we've connected. So let's free and clear it here. */ + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = NULL; + + data->state.authproxy.done = TRUE; + data->state.authproxy.multipass = FALSE; + + infof(data, "Proxy replied %d to CONNECT request\n", + data->info.httpproxycode); + data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ + conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the + document request */ + return CURLE_OK; +} + +void Curl_connect_free(struct Curl_easy *data) +{ + struct connectdata *conn = data->conn; + struct http_connect_state *s = conn->connect_state; + if(s) { + free(s); + conn->connect_state = NULL; + } +} + +/* + * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This + * function will issue the necessary commands to get a seamless tunnel through + * this proxy. After that, the socket can be used just as a normal socket. + */ + +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int sockindex, + const char *hostname, + int remote_port) +{ + CURLcode result; + if(!conn->connect_state) { + result = connect_init(conn, FALSE); + if(result) + return result; + } + result = CONNECT(conn, sockindex, hostname, remote_port); + + if(result || Curl_connect_complete(conn)) + connect_done(conn); + + return result; +} + +#else +void Curl_connect_free(struct Curl_easy *data) +{ + (void)data; +} + +#endif /* CURL_DISABLE_PROXY */ diff --git a/libcurl/lib/http_proxy.h b/libcurl/lib/http_proxy.h new file mode 100644 index 0000000..e19fa85 --- /dev/null +++ b/libcurl/lib/http_proxy.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_HTTP_PROXY_H +#define HEADER_CURL_HTTP_PROXY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) +/* ftp can use this as well */ +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int tunnelsocket, + const char *hostname, int remote_port); + +/* Default proxy timeout in milliseconds */ +#define PROXY_TIMEOUT (3600*1000) + +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex); + +bool Curl_connect_complete(struct connectdata *conn); +bool Curl_connect_ongoing(struct connectdata *conn); + +#else +#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN +#define Curl_proxy_connect(x,y) CURLE_OK +#define Curl_connect_complete(x) CURLE_OK +#define Curl_connect_ongoing(x) FALSE +#endif + +void Curl_connect_free(struct Curl_easy *data); + +#endif /* HEADER_CURL_HTTP_PROXY_H */ diff --git a/libcurl/lib/idn_win32.c b/libcurl/lib/idn_win32.c new file mode 100644 index 0000000..8dc300b --- /dev/null +++ b/libcurl/lib/idn_win32.c @@ -0,0 +1,111 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + /* + * IDN conversions using Windows kernel32 and normaliz libraries. + */ + +#include "curl_setup.h" + +#ifdef USE_WIN32_IDN + +#include "curl_multibyte.h" +#include "curl_memory.h" +#include "warnless.h" + + /* The last #include file should be: */ +#include "memdebug.h" + +#ifdef WANT_IDN_PROTOTYPES +# if defined(_SAL_VERSION) +WINNORMALIZEAPI int WINAPI +IdnToAscii(_In_ DWORD dwFlags, + _In_reads_(cchUnicodeChar) LPCWSTR lpUnicodeCharStr, + _In_ int cchUnicodeChar, + _Out_writes_opt_(cchASCIIChar) LPWSTR lpASCIICharStr, + _In_ int cchASCIIChar); +WINNORMALIZEAPI int WINAPI +IdnToUnicode(_In_ DWORD dwFlags, + _In_reads_(cchASCIIChar) LPCWSTR lpASCIICharStr, + _In_ int cchASCIIChar, + _Out_writes_opt_(cchUnicodeChar) LPWSTR lpUnicodeCharStr, + _In_ int cchUnicodeChar); +# else +WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags, + const WCHAR *lpUnicodeCharStr, + int cchUnicodeChar, + WCHAR *lpASCIICharStr, + int cchASCIIChar); +WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags, + const WCHAR *lpASCIICharStr, + int cchASCIIChar, + WCHAR *lpUnicodeCharStr, + int cchUnicodeChar); +# endif +#endif + +#define IDN_MAX_LENGTH 255 + +bool curl_win32_idn_to_ascii(const char *in, char **out); +bool curl_win32_ascii_to_idn(const char *in, char **out); + +bool curl_win32_idn_to_ascii(const char *in, char **out) +{ + bool success = FALSE; + + wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); + if(in_w) { + wchar_t punycode[IDN_MAX_LENGTH]; + int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH); + free(in_w); + if(chars) { + *out = Curl_convert_wchar_to_UTF8(punycode); + if(*out) + success = TRUE; + } + } + + return success; +} + +bool curl_win32_ascii_to_idn(const char *in, char **out) +{ + bool success = FALSE; + + wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); + if(in_w) { + size_t in_len = wcslen(in_w) + 1; + wchar_t unicode[IDN_MAX_LENGTH]; + int chars = IdnToUnicode(0, in_w, curlx_uztosi(in_len), + unicode, IDN_MAX_LENGTH); + free(in_w); + if(chars) { + *out = Curl_convert_wchar_to_UTF8(unicode); + if(*out) + success = TRUE; + } + } + + return success; +} + +#endif /* USE_WIN32_IDN */ diff --git a/libcurl/lib/if2ip.c b/libcurl/lib/if2ip.c new file mode 100644 index 0000000..d003de6 --- /dev/null +++ b/libcurl/lib/if2ip.c @@ -0,0 +1,243 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_NET_IF_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif +#ifdef HAVE_IFADDRS_H +# include +#endif +#ifdef HAVE_STROPTS_H +# include +#endif +#ifdef __VMS +# include +#endif + +#include "inet_ntop.h" +#include "strcase.h" +#include "if2ip.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* ------------------------------------------------------------------ */ + +/* Return the scope of the given address. */ +unsigned int Curl_ipv6_scope(const struct sockaddr *sa) +{ +#ifndef ENABLE_IPV6 + (void) sa; +#else + if(sa->sa_family == AF_INET6) { + const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa; + const unsigned char *b = sa6->sin6_addr.s6_addr; + unsigned short w = (unsigned short) ((b[0] << 8) | b[1]); + + if((b[0] & 0xFE) == 0xFC) /* Handle ULAs */ + return IPV6_SCOPE_UNIQUELOCAL; + switch(w & 0xFFC0) { + case 0xFE80: + return IPV6_SCOPE_LINKLOCAL; + case 0xFEC0: + return IPV6_SCOPE_SITELOCAL; + case 0x0000: + w = b[1] | b[2] | b[3] | b[4] | b[5] | b[6] | b[7] | b[8] | b[9] | + b[10] | b[11] | b[12] | b[13] | b[14]; + if(w || b[15] != 0x01) + break; + return IPV6_SCOPE_NODELOCAL; + default: + break; + } + } +#endif + + return IPV6_SCOPE_GLOBAL; +} + + +#if defined(HAVE_GETIFADDRS) + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int local_scope_id, const char *interf, + char *buf, int buf_size) +{ + struct ifaddrs *iface, *head; + if2ip_result_t res = IF2IP_NOT_FOUND; + +#ifndef ENABLE_IPV6 + (void) remote_scope; +#endif + +#if !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) || \ + !defined(ENABLE_IPV6) + (void) local_scope_id; +#endif + + if(getifaddrs(&head) >= 0) { + for(iface = head; iface != NULL; iface = iface->ifa_next) { + if(iface->ifa_addr != NULL) { + if(iface->ifa_addr->sa_family == af) { + if(strcasecompare(iface->ifa_name, interf)) { + void *addr; + char *ip; + char scope[12] = ""; + char ipstr[64]; +#ifdef ENABLE_IPV6 + if(af == AF_INET6) { +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + unsigned int scopeid = 0; +#endif + unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr); + + if(ifscope != remote_scope) { + /* We are interested only in interface addresses whose + scope matches the remote address we want to + connect to: global for global, link-local for + link-local, etc... */ + if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED; + continue; + } + + addr = + &((struct sockaddr_in6 *)(void *)iface->ifa_addr)->sin6_addr; +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + /* Include the scope of this interface as part of the address */ + scopeid = ((struct sockaddr_in6 *)(void *)iface->ifa_addr) + ->sin6_scope_id; + + /* If given, scope id should match. */ + if(local_scope_id && scopeid != local_scope_id) { + if(res == IF2IP_NOT_FOUND) + res = IF2IP_AF_NOT_SUPPORTED; + + continue; + } + + if(scopeid) + msnprintf(scope, sizeof(scope), "%%%u", scopeid); +#endif + } + else +#endif + addr = + &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr; + res = IF2IP_FOUND; + ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr)); + msnprintf(buf, buf_size, "%s%s", ip, scope); + break; + } + } + else if((res == IF2IP_NOT_FOUND) && + strcasecompare(iface->ifa_name, interf)) { + res = IF2IP_AF_NOT_SUPPORTED; + } + } + } + + freeifaddrs(head); + } + + return res; +} + +#elif defined(HAVE_IOCTL_SIOCGIFADDR) + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int local_scope_id, const char *interf, + char *buf, int buf_size) +{ + struct ifreq req; + struct in_addr in; + struct sockaddr_in *s; + curl_socket_t dummy; + size_t len; + + (void)remote_scope; + (void)local_scope_id; + + if(!interf || (af != AF_INET)) + return IF2IP_NOT_FOUND; + + len = strlen(interf); + if(len >= sizeof(req.ifr_name)) + return IF2IP_NOT_FOUND; + + dummy = socket(AF_INET, SOCK_STREAM, 0); + if(CURL_SOCKET_BAD == dummy) + return IF2IP_NOT_FOUND; + + memset(&req, 0, sizeof(req)); + memcpy(req.ifr_name, interf, len + 1); + req.ifr_addr.sa_family = AF_INET; + + if(ioctl(dummy, SIOCGIFADDR, &req) < 0) { + sclose(dummy); + /* With SIOCGIFADDR, we cannot tell the difference between an interface + that does not exist and an interface that has no address of the + correct family. Assume the interface does not exist */ + return IF2IP_NOT_FOUND; + } + + s = (struct sockaddr_in *)(void *)&req.ifr_addr; + memcpy(&in, &s->sin_addr, sizeof(in)); + Curl_inet_ntop(s->sin_family, &in, buf, buf_size); + + sclose(dummy); + return IF2IP_FOUND; +} + +#else + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int local_scope_id, const char *interf, + char *buf, int buf_size) +{ + (void) af; + (void) remote_scope; + (void) local_scope_id; + (void) interf; + (void) buf; + (void) buf_size; + return IF2IP_NOT_FOUND; +} + +#endif diff --git a/libcurl/lib/if2ip.h b/libcurl/lib/if2ip.h new file mode 100644 index 0000000..f193d42 --- /dev/null +++ b/libcurl/lib/if2ip.h @@ -0,0 +1,82 @@ +#ifndef HEADER_CURL_IF2IP_H +#define HEADER_CURL_IF2IP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* IPv6 address scopes. */ +#define IPV6_SCOPE_GLOBAL 0 /* Global scope. */ +#define IPV6_SCOPE_LINKLOCAL 1 /* Link-local scope. */ +#define IPV6_SCOPE_SITELOCAL 2 /* Site-local scope (deprecated). */ +#define IPV6_SCOPE_UNIQUELOCAL 3 /* Unique local */ +#define IPV6_SCOPE_NODELOCAL 4 /* Loopback. */ + +unsigned int Curl_ipv6_scope(const struct sockaddr *sa); + +typedef enum { + IF2IP_NOT_FOUND = 0, /* Interface not found */ + IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */ + IF2IP_FOUND = 2 /* The address has been stored in "buf" */ +} if2ip_result_t; + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int local_scope_id, const char *interf, + char *buf, int buf_size); + +#ifdef __INTERIX + +/* Nedelcho Stanev's work-around for SFU 3.0 */ +struct ifreq { +#define IFNAMSIZ 16 +#define IFHWADDRLEN 6 + union { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_metric; + int ifru_mtu; + } ifr_ifru; +}; + +/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the + C code. */ + +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ + +#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ + +#endif /* __INTERIX */ + +#endif /* HEADER_CURL_IF2IP_H */ diff --git a/libcurl/lib/imap.c b/libcurl/lib/imap.c new file mode 100644 index 0000000..f3ffa29 --- /dev/null +++ b/libcurl/lib/imap.c @@ -0,0 +1,2107 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2195 CRAM-MD5 authentication + * RFC2595 Using TLS with IMAP, POP3 and ACAP + * RFC2831 DIGEST-MD5 authentication + * RFC3501 IMAPv4 protocol + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC4959 IMAP Extension for SASL Initial Client Response + * RFC5092 IMAP URL Scheme + * RFC6749 OAuth 2.0 Authorization Framework + * RFC8314 Use of TLS for Email Submission and Access + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_IMAP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "imap.h" +#include "mime.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "strcase.h" +#include "curl_sasl.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode imap_do(struct connectdata *conn, bool *done); +static CURLcode imap_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode imap_connect(struct connectdata *conn, bool *done); +static CURLcode imap_disconnect(struct connectdata *conn, bool dead); +static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done); +static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode imap_setup_connection(struct connectdata *conn); +static char *imap_atom(const char *str, bool escape_only); +static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...); +static CURLcode imap_parse_url_options(struct connectdata *conn); +static CURLcode imap_parse_url_path(struct connectdata *conn); +static CURLcode imap_parse_custom_request(struct connectdata *conn); +static CURLcode imap_perform_authenticate(struct connectdata *conn, + const char *mech, + const char *initresp); +static CURLcode imap_continue_authenticate(struct connectdata *conn, + const char *resp); +static void imap_get_message(char *buffer, char **outptr); + +/* + * IMAP protocol handler. + */ + +const struct Curl_handler Curl_handler_imap = { + "IMAP", /* scheme */ + imap_setup_connection, /* setup_connection */ + imap_do, /* do_it */ + imap_done, /* done */ + ZERO_NULL, /* do_more */ + imap_connect, /* connect_it */ + imap_multi_statemach, /* connecting */ + imap_doing, /* doing */ + imap_getsock, /* proto_getsock */ + imap_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + imap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_IMAP, /* defport */ + CURLPROTO_IMAP, /* protocol */ + PROTOPT_CLOSEACTION| /* flags */ + PROTOPT_URLOPTIONS +}; + +#ifdef USE_SSL +/* + * IMAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_imaps = { + "IMAPS", /* scheme */ + imap_setup_connection, /* setup_connection */ + imap_do, /* do_it */ + imap_done, /* done */ + ZERO_NULL, /* do_more */ + imap_connect, /* connect_it */ + imap_multi_statemach, /* connecting */ + imap_doing, /* doing */ + imap_getsock, /* proto_getsock */ + imap_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + imap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_IMAPS, /* defport */ + CURLPROTO_IMAPS, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ + PROTOPT_URLOPTIONS +}; +#endif + +#define IMAP_RESP_OK 1 +#define IMAP_RESP_NOT_OK 2 +#define IMAP_RESP_PREAUTH 3 + +/* SASL parameters for the imap protocol */ +static const struct SASLproto saslimap = { + "imap", /* The service name */ + '+', /* Code received when continuation is expected */ + IMAP_RESP_OK, /* Code to receive upon authentication success */ + 0, /* Maximum initial response length (no max) */ + imap_perform_authenticate, /* Send authentication command */ + imap_continue_authenticate, /* Send authentication continuation */ + imap_get_message /* Get SASL response message */ +}; + + +#ifdef USE_SSL +static void imap_to_imaps(struct connectdata *conn) +{ + /* Change the connection handler */ + conn->handler = &Curl_handler_imaps; + + /* Set the connection's upgraded to TLS flag */ + conn->tls_upgraded = TRUE; +} +#else +#define imap_to_imaps(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * imap_matchresp() + * + * Determines whether the untagged response is related to the specified + * command by checking if it is in format "* ..." or + * "* ...". + * + * The "* " marker is assumed to have already been checked by the caller. + */ +static bool imap_matchresp(const char *line, size_t len, const char *cmd) +{ + const char *end = line + len; + size_t cmd_len = strlen(cmd); + + /* Skip the untagged response marker */ + line += 2; + + /* Do we have a number after the marker? */ + if(line < end && ISDIGIT(*line)) { + /* Skip the number */ + do + line++; + while(line < end && ISDIGIT(*line)); + + /* Do we have the space character? */ + if(line == end || *line != ' ') + return FALSE; + + line++; + } + + /* Does the command name match and is it followed by a space character or at + the end of line? */ + if(line + cmd_len <= end && strncasecompare(line, cmd, cmd_len) && + (line[cmd_len] == ' ' || line + cmd_len + 2 == end)) + return TRUE; + + return FALSE; +} + +/*********************************************************************** + * + * imap_endofresp() + * + * Checks whether the given string is a valid tagged, untagged or continuation + * response which can be processed by the response handler. + */ +static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct IMAP *imap = conn->data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + const char *id = imapc->resptag; + size_t id_len = strlen(id); + + /* Do we have a tagged command response? */ + if(len >= id_len + 1 && !memcmp(id, line, id_len) && line[id_len] == ' ') { + line += id_len + 1; + len -= id_len + 1; + + if(len >= 2 && !memcmp(line, "OK", 2)) + *resp = IMAP_RESP_OK; + else if(len >= 7 && !memcmp(line, "PREAUTH", 7)) + *resp = IMAP_RESP_PREAUTH; + else + *resp = IMAP_RESP_NOT_OK; + + return TRUE; + } + + /* Do we have an untagged command response? */ + if(len >= 2 && !memcmp("* ", line, 2)) { + switch(imapc->state) { + /* States which are interested in untagged responses */ + case IMAP_CAPABILITY: + if(!imap_matchresp(line, len, "CAPABILITY")) + return FALSE; + break; + + case IMAP_LIST: + if((!imap->custom && !imap_matchresp(line, len, "LIST")) || + (imap->custom && !imap_matchresp(line, len, imap->custom) && + (!strcasecompare(imap->custom, "STORE") || + !imap_matchresp(line, len, "FETCH")) && + !strcasecompare(imap->custom, "SELECT") && + !strcasecompare(imap->custom, "EXAMINE") && + !strcasecompare(imap->custom, "SEARCH") && + !strcasecompare(imap->custom, "EXPUNGE") && + !strcasecompare(imap->custom, "LSUB") && + !strcasecompare(imap->custom, "UID") && + !strcasecompare(imap->custom, "NOOP"))) + return FALSE; + break; + + case IMAP_SELECT: + /* SELECT is special in that its untagged responses do not have a + common prefix so accept anything! */ + break; + + case IMAP_FETCH: + if(!imap_matchresp(line, len, "FETCH")) + return FALSE; + break; + + case IMAP_SEARCH: + if(!imap_matchresp(line, len, "SEARCH")) + return FALSE; + break; + + /* Ignore other untagged responses */ + default: + return FALSE; + } + + *resp = '*'; + return TRUE; + } + + /* Do we have a continuation response? This should be a + symbol followed by + a space and optionally some text as per RFC-3501 for the AUTHENTICATE and + APPEND commands and as outlined in Section 4. Examples of RFC-4959 but + some e-mail servers ignore this and only send a single + instead. */ + if(imap && !imap->custom && ((len == 3 && line[0] == '+') || + (len >= 2 && !memcmp("+ ", line, 2)))) { + switch(imapc->state) { + /* States which are interested in continuation responses */ + case IMAP_AUTHENTICATE: + case IMAP_APPEND: + *resp = '+'; + break; + + default: + failf(conn->data, "Unexpected continuation response"); + *resp = -1; + break; + } + + return TRUE; + } + + return FALSE; /* Nothing for us */ +} + +/*********************************************************************** + * + * imap_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void imap_get_message(char *buffer, char **outptr) +{ + size_t len = strlen(buffer); + char *message = NULL; + + if(len > 2) { + /* Find the start of the message */ + len -= 2; + for(message = buffer + 2; *message == ' ' || *message == '\t'; + message++, len--) + ; + + /* Find the end of the message */ + for(; len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + } + else + /* junk input => zero length output */ + message = &buffer[len]; + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change IMAP state! + */ +static void state(struct connectdata *conn, imapstate newstate) +{ + struct imap_conn *imapc = &conn->proto.imapc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[]={ + "STOP", + "SERVERGREET", + "CAPABILITY", + "STARTTLS", + "UPGRADETLS", + "AUTHENTICATE", + "LOGIN", + "LIST", + "SELECT", + "FETCH", + "FETCH_FINAL", + "APPEND", + "APPEND_FINAL", + "SEARCH", + "LOGOUT", + /* LAST */ + }; + + if(imapc->state != newstate) + infof(conn->data, "IMAP %p state change from %s to %s\n", + (void *)imapc, names[imapc->state], names[newstate]); +#endif + + imapc->state = newstate; +} + +/*********************************************************************** + * + * imap_perform_capability() + * + * Sends the CAPABILITY command in order to obtain a list of server side + * supported capabilities. + */ +static CURLcode imap_perform_capability(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */ + imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */ + imapc->tls_supported = FALSE; /* Clear the TLS capability */ + + /* Send the CAPABILITY command */ + result = imap_sendf(conn, "CAPABILITY"); + + if(!result) + state(conn, IMAP_CAPABILITY); + + return result; +} + +/*********************************************************************** + * + * imap_perform_starttls() + * + * Sends the STARTTLS command to start the upgrade to TLS. + */ +static CURLcode imap_perform_starttls(struct connectdata *conn) +{ + /* Send the STARTTLS command */ + CURLcode result = imap_sendf(conn, "STARTTLS"); + + if(!result) + state(conn, IMAP_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * imap_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode imap_perform_upgrade_tls(struct connectdata *conn) +{ + /* Start the SSL connection */ + struct imap_conn *imapc = &conn->proto.imapc; + CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + &imapc->ssldone); + + if(!result) { + if(imapc->state != IMAP_UPGRADETLS) + state(conn, IMAP_UPGRADETLS); + + if(imapc->ssldone) { + imap_to_imaps(conn); + result = imap_perform_capability(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * imap_perform_login() + * + * Sends a clear text LOGIN command to authenticate with. + */ +static CURLcode imap_perform_login(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + char *user; + char *passwd; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, IMAP_STOP); + + return result; + } + + /* Make sure the username and password are in the correct atom format */ + user = imap_atom(conn->user, false); + passwd = imap_atom(conn->passwd, false); + + /* Send the LOGIN command */ + result = imap_sendf(conn, "LOGIN %s %s", user ? user : "", + passwd ? passwd : ""); + + free(user); + free(passwd); + + if(!result) + state(conn, IMAP_LOGIN); + + return result; +} + +/*********************************************************************** + * + * imap_perform_authenticate() + * + * Sends an AUTHENTICATE command allowing the client to login with the given + * SASL authentication mechanism. + */ +static CURLcode imap_perform_authenticate(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + + if(initresp) { + /* Send the AUTHENTICATE command with the initial response */ + result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp); + } + else { + /* Send the AUTHENTICATE command */ + result = imap_sendf(conn, "AUTHENTICATE %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * imap_continue_authenticate() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode imap_continue_authenticate(struct connectdata *conn, + const char *resp) +{ + struct imap_conn *imapc = &conn->proto.imapc; + + return Curl_pp_sendf(&imapc->pp, "%s", resp); +} + +/*********************************************************************** + * + * imap_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism, falling back to clear text should a common + * mechanism not be available between the client and server. + */ +static CURLcode imap_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + saslprogress progress; + + /* Check if already authenticated OR if there is enough data to authenticate + with and end the connect phase if we don't */ + if(imapc->preauth || + !Curl_sasl_can_authenticate(&imapc->sasl, conn)) { + state(conn, IMAP_STOP); + return result; + } + + /* Calculate the SASL login details */ + result = Curl_sasl_start(&imapc->sasl, conn, imapc->ir_supported, &progress); + + if(!result) { + if(progress == SASL_INPROGRESS) + state(conn, IMAP_AUTHENTICATE); + else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) + /* Perform clear text authentication */ + result = imap_perform_login(conn); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * imap_perform_list() + * + * Sends a LIST command or an alternative custom request. + */ +static CURLcode imap_perform_list(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + + if(imap->custom) + /* Send the custom request */ + result = imap_sendf(conn, "%s%s", imap->custom, + imap->custom_params ? imap->custom_params : ""); + else { + /* Make sure the mailbox is in the correct atom format if necessary */ + char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, true) + : strdup(""); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the LIST command */ + result = imap_sendf(conn, "LIST \"%s\" *", mailbox); + + free(mailbox); + } + + if(!result) + state(conn, IMAP_LIST); + + return result; +} + +/*********************************************************************** + * + * imap_perform_select() + * + * Sends a SELECT command to ask the server to change the selected mailbox. + */ +static CURLcode imap_perform_select(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + char *mailbox; + + /* Invalidate old information as we are switching mailboxes */ + Curl_safefree(imapc->mailbox); + Curl_safefree(imapc->mailbox_uidvalidity); + + /* Check we have a mailbox */ + if(!imap->mailbox) { + failf(conn->data, "Cannot SELECT without a mailbox."); + return CURLE_URL_MALFORMAT; + } + + /* Make sure the mailbox is in the correct atom format */ + mailbox = imap_atom(imap->mailbox, false); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the SELECT command */ + result = imap_sendf(conn, "SELECT %s", mailbox); + + free(mailbox); + + if(!result) + state(conn, IMAP_SELECT); + + return result; +} + +/*********************************************************************** + * + * imap_perform_fetch() + * + * Sends a FETCH command to initiate the download of a message. + */ +static CURLcode imap_perform_fetch(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct IMAP *imap = conn->data->req.protop; + /* Check we have a UID */ + if(imap->uid) { + + /* Send the FETCH command */ + if(imap->partial) + result = imap_sendf(conn, "UID FETCH %s BODY[%s]<%s>", + imap->uid, + imap->section ? imap->section : "", + imap->partial); + else + result = imap_sendf(conn, "UID FETCH %s BODY[%s]", + imap->uid, + imap->section ? imap->section : ""); + } + else if(imap->mindex) { + + /* Send the FETCH command */ + if(imap->partial) + result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>", + imap->mindex, + imap->section ? imap->section : "", + imap->partial); + else + result = imap_sendf(conn, "FETCH %s BODY[%s]", + imap->mindex, + imap->section ? imap->section : ""); + } + else { + failf(conn->data, "Cannot FETCH without a UID."); + return CURLE_URL_MALFORMAT; + } + if(!result) + state(conn, IMAP_FETCH); + + return result; +} + +/*********************************************************************** + * + * imap_perform_append() + * + * Sends an APPEND command to initiate the upload of a message. + */ +static CURLcode imap_perform_append(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + char *mailbox; + + /* Check we have a mailbox */ + if(!imap->mailbox) { + failf(data, "Cannot APPEND without a mailbox."); + return CURLE_URL_MALFORMAT; + } + + /* Prepare the mime data if some. */ + if(data->set.mimepost.kind != MIMEKIND_NONE) { + /* Use the whole structure as data. */ + data->set.mimepost.flags &= ~MIME_BODY_ONLY; + + /* Add external headers and mime version. */ + curl_mime_headers(&data->set.mimepost, data->set.headers, 0); + result = Curl_mime_prepare_headers(&data->set.mimepost, NULL, + NULL, MIMESTRATEGY_MAIL); + + if(!result) + if(!Curl_checkheaders(conn, "Mime-Version")) + result = Curl_mime_add_header(&data->set.mimepost.curlheaders, + "Mime-Version: 1.0"); + + /* Make sure we will read the entire mime structure. */ + if(!result) + result = Curl_mime_rewind(&data->set.mimepost); + + if(result) + return result; + + data->state.infilesize = Curl_mime_size(&data->set.mimepost); + + /* Read from mime structure. */ + data->state.fread_func = (curl_read_callback) Curl_mime_read; + data->state.in = (void *) &data->set.mimepost; + } + + /* Check we know the size of the upload */ + if(data->state.infilesize < 0) { + failf(data, "Cannot APPEND with unknown input file size\n"); + return CURLE_UPLOAD_FAILED; + } + + /* Make sure the mailbox is in the correct atom format */ + mailbox = imap_atom(imap->mailbox, false); + if(!mailbox) + return CURLE_OUT_OF_MEMORY; + + /* Send the APPEND command */ + result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", + mailbox, data->state.infilesize); + + free(mailbox); + + if(!result) + state(conn, IMAP_APPEND); + + return result; +} + +/*********************************************************************** + * + * imap_perform_search() + * + * Sends a SEARCH command. + */ +static CURLcode imap_perform_search(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct IMAP *imap = conn->data->req.protop; + + /* Check we have a query string */ + if(!imap->query) { + failf(conn->data, "Cannot SEARCH without a query string."); + return CURLE_URL_MALFORMAT; + } + + /* Send the SEARCH command */ + result = imap_sendf(conn, "SEARCH %s", imap->query); + + if(!result) + state(conn, IMAP_SEARCH); + + return result; +} + +/*********************************************************************** + * + * imap_perform_logout() + * + * Performs the logout action prior to sclose() being called. + */ +static CURLcode imap_perform_logout(struct connectdata *conn) +{ + /* Send the LOGOUT command */ + CURLcode result = imap_sendf(conn, "LOGOUT"); + + if(!result) + state(conn, IMAP_LOGOUT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode imap_state_servergreet_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + struct Curl_easy *data = conn->data; + (void)instate; /* no use for this yet */ + + if(imapcode == IMAP_RESP_PREAUTH) { + /* PREAUTH */ + struct imap_conn *imapc = &conn->proto.imapc; + imapc->preauth = TRUE; + infof(data, "PREAUTH connection, already authenticated!\n"); + } + else if(imapcode != IMAP_RESP_OK) { + failf(data, "Got unexpected imap-server response"); + return CURLE_WEIRD_SERVER_REPLY; + } + + return imap_perform_capability(conn); +} + +/* For CAPABILITY responses */ +static CURLcode imap_state_capability_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + const char *line = data->state.buffer; + + (void)instate; /* no use for this yet */ + + /* Do we have a untagged response? */ + if(imapcode == '*') { + line += 2; + + /* Loop through the data line */ + for(;;) { + size_t wordlen; + while(*line && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + } + + if(!*line) + break; + + /* Extract the word */ + for(wordlen = 0; line[wordlen] && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Does the server support the STARTTLS capability? */ + if(wordlen == 8 && !memcmp(line, "STARTTLS", 8)) + imapc->tls_supported = TRUE; + + /* Has the server explicitly disabled clear text authentication? */ + else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13)) + imapc->login_disabled = TRUE; + + /* Does the server support the SASL-IR capability? */ + else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7)) + imapc->ir_supported = TRUE; + + /* Do we have a SASL based authentication mechanism? */ + else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { + size_t llen; + unsigned int mechbit; + + line += 5; + wordlen -= 5; + + /* Test the word for a matching authentication mechanism */ + mechbit = Curl_sasl_decode_mech(line, wordlen, &llen); + if(mechbit && llen == wordlen) + imapc->sasl.authmechs |= mechbit; + } + + line += wordlen; + } + } + else if(imapcode == IMAP_RESP_OK) { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(imapc->tls_supported) + /* Switch to TLS connection now */ + result = imap_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = imap_perform_authentication(conn); + else { + failf(data, "STARTTLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = imap_perform_authentication(conn); + } + else + result = imap_perform_authentication(conn); + + return result; +} + +/* For STARTTLS responses */ +static CURLcode imap_state_starttls_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != IMAP_RESP_OK) { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied"); + result = CURLE_USE_SSL_FAILED; + } + else + result = imap_perform_authentication(conn); + } + else + result = imap_perform_upgrade_tls(conn); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode imap_state_auth_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&imapc->sasl, conn, imapcode, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, IMAP_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ + if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) + /* Perform clear text authentication */ + result = imap_perform_login(conn); + else { + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + } + break; + default: + break; + } + + return result; +} + +/* For LOGIN responses */ +static CURLcode imap_state_login_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(imapcode != IMAP_RESP_OK) { + failf(data, "Access denied. %c", imapcode); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For LIST and SEARCH responses */ +static CURLcode imap_state_listsearch_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + char *line = conn->data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* No use for this yet */ + + if(imapcode == '*') { + /* Temporarily add the LF character back and send as body to the client */ + line[len] = '\n'; + result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + line[len] = '\0'; + } + else if(imapcode != IMAP_RESP_OK) + result = CURLE_QUOTE_ERROR; + else + /* End of DO phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For SELECT responses */ +static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = conn->data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + const char *line = data->state.buffer; + + (void)instate; /* no use for this yet */ + + if(imapcode == '*') { + /* See if this is an UIDVALIDITY response */ + char tmp[20]; + if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) { + Curl_safefree(imapc->mailbox_uidvalidity); + imapc->mailbox_uidvalidity = strdup(tmp); + } + } + else if(imapcode == IMAP_RESP_OK) { + /* Check if the UIDVALIDITY has been specified and matches */ + if(imap->uidvalidity && imapc->mailbox_uidvalidity && + !strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)) { + failf(conn->data, "Mailbox UIDVALIDITY has changed"); + result = CURLE_REMOTE_FILE_NOT_FOUND; + } + else { + /* Note the currently opened mailbox on this connection */ + imapc->mailbox = strdup(imap->mailbox); + + if(imap->custom) + result = imap_perform_list(conn); + else if(imap->query) + result = imap_perform_search(conn); + else + result = imap_perform_fetch(conn); + } + } + else { + failf(data, "Select failed"); + result = CURLE_LOGIN_DENIED; + } + + return result; +} + +/* For the (first line of the) FETCH responses */ +static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + const char *ptr = data->state.buffer; + bool parsed = FALSE; + curl_off_t size = 0; + + (void)instate; /* no use for this yet */ + + if(imapcode != '*') { + Curl_pgrsSetDownloadSize(data, -1); + state(conn, IMAP_STOP); + return CURLE_REMOTE_FILE_NOT_FOUND; + } + + /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse + the continuation data contained within the curly brackets */ + while(*ptr && (*ptr != '{')) + ptr++; + + if(*ptr == '{') { + char *endptr; + if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size)) { + if(endptr - ptr > 1 && endptr[0] == '}' && + endptr[1] == '\r' && endptr[2] == '\0') + parsed = TRUE; + } + } + + if(parsed) { + infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download\n", + size); + Curl_pgrsSetDownloadSize(data, size); + + if(pp->cache) { + /* At this point there is a bunch of data in the header "cache" that is + actually body content, send it as body and then skip it. Do note + that there may even be additional "headers" after the body. */ + size_t chunk = pp->cache_size; + + if(chunk > (size_t)size) + /* The conversion from curl_off_t to size_t is always fine here */ + chunk = (size_t)size; + + if(!chunk) { + /* no size, we're done with the data */ + state(conn, IMAP_STOP); + return CURLE_OK; + } + result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk); + if(result) + return result; + + data->req.bytecount += chunk; + + infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU + " bytes are left for transfer\n", chunk, size - chunk); + + /* Have we used the entire cache or just part of it?*/ + if(pp->cache_size > chunk) { + /* Only part of it so shrink the cache to fit the trailing data */ + memmove(pp->cache, pp->cache + chunk, pp->cache_size - chunk); + pp->cache_size -= chunk; + } + else { + /* Free the cache */ + Curl_safefree(pp->cache); + + /* Reset the cache size */ + pp->cache_size = 0; + } + } + + if(data->req.bytecount == size) + /* The entire data is already transferred! */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + else { + /* IMAP download */ + data->req.maxdownload = size; + Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1); + } + } + else { + /* We don't know how to parse this line */ + failf(pp->conn->data, "Failed to parse FETCH response."); + result = CURLE_WEIRD_SERVER_REPLY; + } + + /* End of DO phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For final FETCH responses performed after the download */ +static CURLcode imap_state_fetch_final_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* No use for this yet */ + + if(imapcode != IMAP_RESP_OK) + result = CURLE_WEIRD_SERVER_REPLY; + else + /* End of DONE phase */ + state(conn, IMAP_STOP); + + return result; +} + +/* For APPEND responses */ +static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* No use for this yet */ + + if(imapcode != '+') { + result = CURLE_UPLOAD_FAILED; + } + else { + /* Set the progress upload size */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* IMAP upload */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* End of DO phase */ + state(conn, IMAP_STOP); + } + + return result; +} + +/* For final APPEND responses performed after the upload */ +static CURLcode imap_state_append_final_resp(struct connectdata *conn, + int imapcode, + imapstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* No use for this yet */ + + if(imapcode != IMAP_RESP_OK) + result = CURLE_UPLOAD_FAILED; + else + /* End of DONE phase */ + state(conn, IMAP_STOP); + + return result; +} + +static CURLcode imap_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int imapcode; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */ + if(imapc->state == IMAP_UPGRADETLS) + return imap_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &imapcode, &nread); + if(result) + return result; + + /* Was there an error parsing the response line? */ + if(imapcode == -1) + return CURLE_WEIRD_SERVER_REPLY; + + if(!imapcode) + break; + + /* We have now received a full IMAP server response */ + switch(imapc->state) { + case IMAP_SERVERGREET: + result = imap_state_servergreet_resp(conn, imapcode, imapc->state); + break; + + case IMAP_CAPABILITY: + result = imap_state_capability_resp(conn, imapcode, imapc->state); + break; + + case IMAP_STARTTLS: + result = imap_state_starttls_resp(conn, imapcode, imapc->state); + break; + + case IMAP_AUTHENTICATE: + result = imap_state_auth_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LOGIN: + result = imap_state_login_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LIST: + result = imap_state_listsearch_resp(conn, imapcode, imapc->state); + break; + + case IMAP_SELECT: + result = imap_state_select_resp(conn, imapcode, imapc->state); + break; + + case IMAP_FETCH: + result = imap_state_fetch_resp(conn, imapcode, imapc->state); + break; + + case IMAP_FETCH_FINAL: + result = imap_state_fetch_final_resp(conn, imapcode, imapc->state); + break; + + case IMAP_APPEND: + result = imap_state_append_resp(conn, imapcode, imapc->state); + break; + + case IMAP_APPEND_FINAL: + result = imap_state_append_final_resp(conn, imapcode, imapc->state); + break; + + case IMAP_SEARCH: + result = imap_state_listsearch_resp(conn, imapcode, imapc->state); + break; + + case IMAP_LOGOUT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, IMAP_STOP); + break; + } + } while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); + if(result || !imapc->ssldone) + return result; + } + + result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE); + *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode imap_block_statemach(struct connectdata *conn, + bool disconnecting) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + + while(imapc->state != IMAP_STOP && !result) + result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting); + + return result; +} + +/* Allocate and initialize the struct IMAP for the current Curl_easy if + required */ +static CURLcode imap_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap; + + imap = data->req.protop = calloc(sizeof(struct IMAP), 1); + if(!imap) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the IMAP "protocol connect" and "doing" phases only */ +static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks); +} + +/*********************************************************************** + * + * imap_connect() + * + * This function should do everything that is to be considered a part of the + * connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + */ +static CURLcode imap_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + struct pingpong *pp = &imapc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in IMAP */ + connkeep(conn, "IMAP default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = imap_statemach_act; + pp->endofresp = imap_endofresp; + pp->conn = conn; + + /* Set the default preferred authentication type and mechanism */ + imapc->preftype = IMAP_TYPE_ANY; + Curl_sasl_init(&imapc->sasl, &saslimap); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = imap_parse_url_options(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, IMAP_SERVERGREET); + + /* Start off with an response id of '*' */ + strcpy(imapc->resptag, "*"); + + result = imap_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * imap_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode imap_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + + (void)premature; + + if(!imap) + return CURLE_OK; + + if(status) { + connclose(conn, "IMAP done with bad status"); /* marked for closure */ + result = status; /* use the already set error code */ + } + else if(!data->set.connect_only && !imap->custom && + (imap->uid || imap->mindex || data->set.upload || + data->set.mimepost.kind != MIMEKIND_NONE)) { + /* Handle responses after FETCH or APPEND transfer has finished */ + + if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE) + state(conn, IMAP_FETCH_FINAL); + else { + /* End the APPEND command first by sending an empty line */ + result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", ""); + if(!result) + state(conn, IMAP_APPEND_FINAL); + } + + /* Run the state-machine */ + if(!result) + result = imap_block_statemach(conn, FALSE); + } + + /* Cleanup our per-request based variables */ + Curl_safefree(imap->mailbox); + Curl_safefree(imap->uidvalidity); + Curl_safefree(imap->uid); + Curl_safefree(imap->mindex); + Curl_safefree(imap->section); + Curl_safefree(imap->partial); + Curl_safefree(imap->query); + Curl_safefree(imap->custom); + Curl_safefree(imap->custom_params); + + /* Clear the transfer mode for the next request */ + imap->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * imap_perform() + * + * This is the actual DO function for IMAP. Fetch or append a message, or do + * other things according to the options previously setup. + */ +static CURLcode imap_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is IMAP and no proxy */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + struct imap_conn *imapc = &conn->proto.imapc; + bool selected = FALSE; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* Requested no body means no transfer */ + imap->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Determine if the requested mailbox (with the same UIDVALIDITY if set) + has already been selected on this connection */ + if(imap->mailbox && imapc->mailbox && + strcasecompare(imap->mailbox, imapc->mailbox) && + (!imap->uidvalidity || !imapc->mailbox_uidvalidity || + strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity))) + selected = TRUE; + + /* Start the first command in the DO phase */ + if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE) + /* APPEND can be executed directly */ + result = imap_perform_append(conn); + else if(imap->custom && (selected || !imap->mailbox)) + /* Custom command using the same mailbox or no mailbox */ + result = imap_perform_list(conn); + else if(!imap->custom && selected && (imap->uid || imap->mindex)) + /* FETCH from the same mailbox */ + result = imap_perform_fetch(conn); + else if(!imap->custom && selected && imap->query) + /* SEARCH the current mailbox */ + result = imap_perform_search(conn); + else if(imap->mailbox && !selected && + (imap->custom || imap->uid || imap->mindex || imap->query)) + /* SELECT the mailbox */ + result = imap_perform_select(conn); + else + /* LIST */ + result = imap_perform_list(conn); + + if(result) + return result; + + /* Run the state-machine */ + result = imap_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * imap_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (imap_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode imap_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the URL path */ + result = imap_parse_url_path(conn); + if(result) + return result; + + /* Parse the custom request */ + result = imap_parse_custom_request(conn); + if(result) + return result; + + result = imap_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * imap_disconnect() + * + * Disconnect from an IMAP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct imap_conn *imapc = &conn->proto.imapc; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The IMAP session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart) + if(!imap_perform_logout(conn)) + (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&imapc->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, imapc->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(imapc->mailbox); + Curl_safefree(imapc->mailbox_uidvalidity); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) +{ + struct IMAP *imap = conn->data->req.protop; + + (void)connected; + + if(imap->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = imap_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = imap_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * imap_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode imap_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct Curl_easy *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = imap_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = imap_dophase_done(conn, connected); + + return result; +} + +static CURLcode imap_setup_connection(struct connectdata *conn) +{ + /* Initialise the IMAP layer */ + CURLcode result = imap_init(conn); + if(result) + return result; + + /* Clear the TLS upgraded flag */ + conn->tls_upgraded = FALSE; + + return CURLE_OK; +} + +/*********************************************************************** + * + * imap_sendf() + * + * Sends the formatted string as an IMAP command to the server. + * + * Designed to never block. + */ +static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + char *taggedfmt; + va_list ap; + + DEBUGASSERT(fmt); + + /* Calculate the next command ID wrapping at 3 digits */ + imapc->cmdid = (imapc->cmdid + 1) % 1000; + + /* Calculate the tag based on the connection ID and command ID */ + msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d", + 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid); + + /* Prefix the format with the tag */ + taggedfmt = aprintf("%s %s", imapc->resptag, fmt); + if(!taggedfmt) + return CURLE_OUT_OF_MEMORY; + + /* Send the data with the tag */ + va_start(ap, fmt); + result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap); + va_end(ap); + + free(taggedfmt); + + return result; +} + +/*********************************************************************** + * + * imap_atom() + * + * Checks the input string for characters that need escaping and returns an + * atom ready for sending to the server. + * + * The returned string needs to be freed. + * + */ +static char *imap_atom(const char *str, bool escape_only) +{ + /* !checksrc! disable PARENBRACE 1 */ + const char atom_specials[] = "(){ %*]"; + const char *p1; + char *p2; + size_t backsp_count = 0; + size_t quote_count = 0; + bool others_exists = FALSE; + size_t newlen = 0; + char *newstr = NULL; + + if(!str) + return NULL; + + /* Look for "atom-specials", counting the backslash and quote characters as + these will need escaping */ + p1 = str; + while(*p1) { + if(*p1 == '\\') + backsp_count++; + else if(*p1 == '"') + quote_count++; + else if(!escape_only) { + const char *p3 = atom_specials; + + while(*p3 && !others_exists) { + if(*p1 == *p3) + others_exists = TRUE; + + p3++; + } + } + + p1++; + } + + /* Does the input contain any "atom-special" characters? */ + if(!backsp_count && !quote_count && !others_exists) + return strdup(str); + + /* Calculate the new string length */ + newlen = strlen(str) + backsp_count + quote_count + (escape_only ? 0 : 2); + + /* Allocate the new string */ + newstr = (char *) malloc((newlen + 1) * sizeof(char)); + if(!newstr) + return NULL; + + /* Surround the string in quotes if necessary */ + p2 = newstr; + if(!escape_only) { + newstr[0] = '"'; + newstr[newlen - 1] = '"'; + p2++; + } + + /* Copy the string, escaping backslash and quote characters along the way */ + p1 = str; + while(*p1) { + if(*p1 == '\\' || *p1 == '"') { + *p2 = '\\'; + p2++; + } + + *p2 = *p1; + + p1++; + p2++; + } + + /* Terminate the string */ + newstr[newlen] = '\0'; + + return newstr; +} + +/*********************************************************************** + * + * imap_is_bchar() + * + * Portable test of whether the specified char is a "bchar" as defined in the + * grammar of RFC-5092. + */ +static bool imap_is_bchar(char ch) +{ + switch(ch) { + /* bchar */ + case ':': case '@': case '/': + /* bchar -> achar */ + case '&': case '=': + /* bchar -> achar -> uchar -> unreserved */ + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': + case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': + case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': + case 'V': case 'W': case 'X': case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': + case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': + case 'v': case 'w': case 'x': case 'y': case 'z': + case '-': case '.': case '_': case '~': + /* bchar -> achar -> uchar -> sub-delims-sh */ + case '!': case '$': case '\'': case '(': case ')': case '*': + case '+': case ',': + /* bchar -> achar -> uchar -> pct-encoded */ + case '%': /* HEXDIG chars are already included above */ + return true; + + default: + return false; + } +} + +/*********************************************************************** + * + * imap_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode imap_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct imap_conn *imapc = &conn->proto.imapc; + const char *ptr = conn->options; + + imapc->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strncasecompare(key, "AUTH=", 5)) + result = Curl_sasl_parse_url_auth_option(&imapc->sasl, + value, ptr - value); + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + switch(imapc->sasl.prefmech) { + case SASL_AUTH_NONE: + imapc->preftype = IMAP_TYPE_NONE; + break; + case SASL_AUTH_DEFAULT: + imapc->preftype = IMAP_TYPE_ANY; + break; + default: + imapc->preftype = IMAP_TYPE_SASL; + break; + } + + return result; +} + +/*********************************************************************** + * + * imap_parse_url_path() + * + * Parse the URL path into separate path components. + * + */ +static CURLcode imap_parse_url_path(struct connectdata *conn) +{ + /* The imap struct is already initialised in imap_connect() */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + const char *begin = &data->state.up.path[1]; /* skip leading slash */ + const char *ptr = begin; + + /* See how much of the URL is a valid path and decode it */ + while(imap_is_bchar(*ptr)) + ptr++; + + if(ptr != begin) { + /* Remove the trailing slash if present */ + const char *end = ptr; + if(end > begin && end[-1] == '/') + end--; + + result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL, + TRUE); + if(result) + return result; + } + else + imap->mailbox = NULL; + + /* There can be any number of parameters in the form ";NAME=VALUE" */ + while(*ptr == ';') { + char *name; + char *value; + size_t valuelen; + + /* Find the length of the name parameter */ + begin = ++ptr; + while(*ptr && *ptr != '=') + ptr++; + + if(!*ptr) + return CURLE_URL_MALFORMAT; + + /* Decode the name parameter */ + result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE); + if(result) + return result; + + /* Find the length of the value parameter */ + begin = ++ptr; + while(imap_is_bchar(*ptr)) + ptr++; + + /* Decode the value parameter */ + result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE); + if(result) { + free(name); + return result; + } + + DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value)); + + /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and + PARTIAL) stripping of the trailing slash character if it is present. + + Note: Unknown parameters trigger a URL_MALFORMAT error. */ + if(strcasecompare(name, "UIDVALIDITY") && !imap->uidvalidity) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->uidvalidity = value; + value = NULL; + } + else if(strcasecompare(name, "UID") && !imap->uid) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->uid = value; + value = NULL; + } + else if(strcasecompare(name, "MAILINDEX") && !imap->mindex) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->mindex = value; + value = NULL; + } + else if(strcasecompare(name, "SECTION") && !imap->section) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->section = value; + value = NULL; + } + else if(strcasecompare(name, "PARTIAL") && !imap->partial) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->partial = value; + value = NULL; + } + else { + free(name); + free(value); + + return CURLE_URL_MALFORMAT; + } + + free(name); + free(value); + } + + /* Does the URL contain a query parameter? Only valid when we have a mailbox + and no UID as per RFC-5092 */ + if(imap->mailbox && !imap->uid && !imap->mindex) { + /* Get the query parameter, URL decoded */ + (void)curl_url_get(data->state.uh, CURLUPART_QUERY, &imap->query, + CURLU_URLDECODE); + } + + /* Any extra stuff at the end of the URL is an error */ + if(*ptr) + return CURLE_URL_MALFORMAT; + + return CURLE_OK; +} + +/*********************************************************************** + * + * imap_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode imap_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct IMAP *imap = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + if(custom) { + /* URL decode the custom request */ + result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE); + + /* Extract the parameters if specified */ + if(!result) { + const char *params = imap->custom; + + while(*params && *params != ' ') + params++; + + if(*params) { + imap->custom_params = strdup(params); + imap->custom[params - imap->custom] = '\0'; + + if(!imap->custom_params) + result = CURLE_OUT_OF_MEMORY; + } + } + } + + return result; +} + +#endif /* CURL_DISABLE_IMAP */ diff --git a/libcurl/lib/imap.h b/libcurl/lib/imap.h new file mode 100644 index 0000000..0efcfd2 --- /dev/null +++ b/libcurl/lib/imap.h @@ -0,0 +1,98 @@ +#ifndef HEADER_CURL_IMAP_H +#define HEADER_CURL_IMAP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * IMAP unique setup + ***************************************************************************/ +typedef enum { + IMAP_STOP, /* do nothing state, stops the state machine */ + IMAP_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + IMAP_CAPABILITY, + IMAP_STARTTLS, + IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + IMAP_AUTHENTICATE, + IMAP_LOGIN, + IMAP_LIST, + IMAP_SELECT, + IMAP_FETCH, + IMAP_FETCH_FINAL, + IMAP_APPEND, + IMAP_APPEND_FINAL, + IMAP_SEARCH, + IMAP_LOGOUT, + IMAP_LAST /* never used */ +} imapstate; + +/* This IMAP struct is used in the Curl_easy. All IMAP data that is + connection-oriented must be in imap_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct IMAP { + curl_pp_transfer transfer; + char *mailbox; /* Mailbox to select */ + char *uidvalidity; /* UIDVALIDITY to check in select */ + char *uid; /* Message UID to fetch */ + char *mindex; /* Index in mail box of mail to fetch */ + char *section; /* Message SECTION to fetch */ + char *partial; /* Message PARTIAL to fetch */ + char *query; /* Query to search for */ + char *custom; /* Custom request */ + char *custom_params; /* Parameters for the custom request */ +}; + +/* imap_conn is used for struct connection-oriented data in the connectdata + struct */ +struct imap_conn { + struct pingpong pp; + imapstate state; /* Always use imap.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + bool preauth; /* Is this connection PREAUTH? */ + struct SASL sasl; /* SASL-related parameters */ + unsigned int preftype; /* Preferred authentication type */ + int cmdid; /* Last used command ID */ + char resptag[5]; /* Response tag to wait for */ + bool tls_supported; /* StartTLS capability supported by server */ + bool login_disabled; /* LOGIN command disabled by server */ + bool ir_supported; /* Initial response supported by server */ + char *mailbox; /* The last selected mailbox */ + char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */ +}; + +extern const struct Curl_handler Curl_handler_imap; +extern const struct Curl_handler Curl_handler_imaps; + +/* Authentication type flags */ +#define IMAP_TYPE_CLEARTEXT (1 << 0) +#define IMAP_TYPE_SASL (1 << 1) + +/* Authentication type values */ +#define IMAP_TYPE_NONE 0 +#define IMAP_TYPE_ANY ~0U + +#endif /* HEADER_CURL_IMAP_H */ diff --git a/libcurl/lib/inet_ntop.c b/libcurl/lib/inet_ntop.c new file mode 100644 index 0000000..855981c --- /dev/null +++ b/libcurl/lib/inet_ntop.c @@ -0,0 +1,197 @@ +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Original code by Paul Vixie. "curlified" by Gisle Vanem. + */ + +#include "curl_setup.h" + +#ifndef HAVE_INET_NTOP + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "inet_ntop.h" +#include "curl_printf.h" + +#define IN6ADDRSZ 16 +#define INADDRSZ 4 +#define INT16SZ 2 + +/* + * Format an IPv4 address, more or less like inet_ntoa(). + * + * Returns `dst' (as a const) + * Note: + * - uses no statics + * - takes a unsigned char* not an in_addr as input + */ +static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size) +{ + char tmp[sizeof("255.255.255.255")]; + size_t len; + + DEBUGASSERT(size >= 16); + + tmp[0] = '\0'; + (void)msnprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", + ((int)((unsigned char)src[0])) & 0xff, + ((int)((unsigned char)src[1])) & 0xff, + ((int)((unsigned char)src[2])) & 0xff, + ((int)((unsigned char)src[3])) & 0xff); + + len = strlen(tmp); + if(len == 0 || len >= size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return dst; +} + +#ifdef ENABLE_IPV6 +/* + * Convert IPv6 binary address into presentation (printable) format. + */ +static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + char *tp; + struct { + long base; + long len; + } best, cur; + unsigned long words[IN6ADDRSZ / INT16SZ]; + int i; + + /* Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof(words)); + for(i = 0; i < IN6ADDRSZ; i++) + words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); + + best.base = -1; + cur.base = -1; + best.len = 0; + cur.len = 0; + + for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if(words[i] == 0) { + if(cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } + else if(cur.base != -1) { + if(best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + if((cur.base != -1) && (best.base == -1 || cur.len > best.len)) + best = cur; + if(best.base != -1 && best.len < 2) + best.base = -1; + /* Format the result. */ + tp = tmp; + for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if(best.base != -1 && i >= best.base && i < (best.base + best.len)) { + if(i == best.base) + *tp++ = ':'; + continue; + } + + /* Are we following an initial run of 0x00s or any real hex? + */ + if(i != 0) + *tp++ = ':'; + + /* Is this address an encapsulated IPv4? + */ + if(i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) { + errno = ENOSPC; + return (NULL); + } + tp += strlen(tp); + break; + } + tp += msnprintf(tp, 5, "%lx", words[i]); + } + + /* Was it a trailing run of 0x00's? + */ + if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* Check for overflow, copy, and we're done. + */ + if((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return dst; +} +#endif /* ENABLE_IPV6 */ + +/* + * Convert a network format address to presentation format. + * + * Returns pointer to presentation format address (`buf'). + * Returns NULL on error and errno set with the specific + * error, EAFNOSUPPORT or ENOSPC. + * + * On Windows we store the error in the thread errno, not + * in the winsock error code. This is to avoid losing the + * actual last winsock error. So when this function returns + * NULL, check errno not SOCKERRNO. + */ +char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size) +{ + switch(af) { + case AF_INET: + return inet_ntop4((const unsigned char *)src, buf, size); +#ifdef ENABLE_IPV6 + case AF_INET6: + return inet_ntop6((const unsigned char *)src, buf, size); +#endif + default: + errno = EAFNOSUPPORT; + return NULL; + } +} +#endif /* HAVE_INET_NTOP */ diff --git a/libcurl/lib/inet_ntop.h b/libcurl/lib/inet_ntop.h new file mode 100644 index 0000000..d150bb6 --- /dev/null +++ b/libcurl/lib/inet_ntop.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_INET_NTOP_H +#define HEADER_CURL_INET_NTOP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size); + +#ifdef HAVE_INET_NTOP +#ifdef HAVE_ARPA_INET_H +#include +#endif +#define Curl_inet_ntop(af,addr,buf,size) \ + inet_ntop(af, addr, buf, (curl_socklen_t)size) +#endif + +#endif /* HEADER_CURL_INET_NTOP_H */ diff --git a/libcurl/lib/inet_pton.c b/libcurl/lib/inet_pton.c new file mode 100644 index 0000000..0d65ae0 --- /dev/null +++ b/libcurl/lib/inet_pton.c @@ -0,0 +1,237 @@ +/* This is from the BIND 4.9.4 release, modified to compile by itself */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "curl_setup.h" + +#ifndef HAVE_INET_PTON + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "inet_pton.h" + +#define IN6ADDRSZ 16 +#define INADDRSZ 4 +#define INT16SZ 2 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4(const char *src, unsigned char *dst); +#ifdef ENABLE_IPV6 +static int inet_pton6(const char *src, unsigned char *dst); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * notice: + * On Windows we store the error in the thread errno, not + * in the winsock error code. This is to avoid losing the + * actual last winsock error. So when this function returns + * -1, check errno not SOCKERRNO. + * author: + * Paul Vixie, 1996. + */ +int +Curl_inet_pton(int af, const char *src, void *dst) +{ + switch(af) { + case AF_INET: + return (inet_pton4(src, (unsigned char *)dst)); +#ifdef ENABLE_IPV6 + case AF_INET6: + return (inet_pton6(src, (unsigned char *)dst)); +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, unsigned char *dst) +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + tp = tmp; + *tp = 0; + while((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if(pch) { + unsigned int val = *tp * 10 + (unsigned int)(pch - digits); + + if(saw_digit && *tp == 0) + return (0); + if(val > 255) + return (0); + *tp = (unsigned char)val; + if(! saw_digit) { + if(++octets > 4) + return (0); + saw_digit = 1; + } + } + else if(ch == '.' && saw_digit) { + if(octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } + else + return (0); + } + if(octets < 4) + return (0); + memcpy(dst, tmp, INADDRSZ); + return (1); +} + +#ifdef ENABLE_IPV6 +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(const char *src, unsigned char *dst) +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; + const char *curtok; + int ch, saw_xdigit; + size_t val; + + memset((tp = tmp), 0, IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if(*src == ':') + if(*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while((ch = *src++) != '\0') { + const char *xdigits; + const char *pch; + + pch = strchr((xdigits = xdigits_l), ch); + if(!pch) + pch = strchr((xdigits = xdigits_u), ch); + if(pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if(++saw_xdigit > 4) + return (0); + continue; + } + if(ch == ':') { + curtok = src; + if(!saw_xdigit) { + if(colonp) + return (0); + colonp = tp; + continue; + } + if(tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) ((val >> 8) & 0xff); + *tp++ = (unsigned char) (val & 0xff); + saw_xdigit = 0; + val = 0; + continue; + } + if(ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if(saw_xdigit) { + if(tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) ((val >> 8) & 0xff); + *tp++ = (unsigned char) (val & 0xff); + } + if(colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const ssize_t n = tp - colonp; + ssize_t i; + + if(tp == endp) + return (0); + for(i = 1; i <= n; i++) { + *(endp - i) = *(colonp + n - i); + *(colonp + n - i) = 0; + } + tp = endp; + } + if(tp != endp) + return (0); + memcpy(dst, tmp, IN6ADDRSZ); + return (1); +} +#endif /* ENABLE_IPV6 */ + +#endif /* HAVE_INET_PTON */ diff --git a/libcurl/lib/inet_pton.h b/libcurl/lib/inet_pton.h new file mode 100644 index 0000000..0209b9b --- /dev/null +++ b/libcurl/lib/inet_pton.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_INET_PTON_H +#define HEADER_CURL_INET_PTON_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +int Curl_inet_pton(int, const char *, void *); + +#ifdef HAVE_INET_PTON +#ifdef HAVE_ARPA_INET_H +#include +#elif defined(HAVE_WS2TCPIP_H) +/* inet_pton() exists in Vista or later */ +#include +#endif +#define Curl_inet_pton(x,y,z) inet_pton(x,y,z) +#endif + +#endif /* HEADER_CURL_INET_PTON_H */ diff --git a/libcurl/lib/krb5.c b/libcurl/lib/krb5.c new file mode 100644 index 0000000..5a47d48 --- /dev/null +++ b/libcurl/lib/krb5.c @@ -0,0 +1,341 @@ +/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c + * + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Copyright (c) 2004 - 2017 Daniel Stenberg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_FTP) + +#ifdef HAVE_NETDB_H +#include +#endif + +#include "urldata.h" +#include "curl_base64.h" +#include "ftp.h" +#include "curl_gssapi.h" +#include "sendf.h" +#include "curl_sec.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static int +krb5_init(void *app_data) +{ + gss_ctx_id_t *context = app_data; + /* Make sure our context is initialized for krb5_end. */ + *context = GSS_C_NO_CONTEXT; + return 0; +} + +static int +krb5_check_prot(void *app_data, int level) +{ + (void)app_data; /* unused */ + if(level == PROT_CONFIDENTIAL) + return -1; + return 0; +} + +static int +krb5_decode(void *app_data, void *buf, int len, + int level UNUSED_PARAM, + struct connectdata *conn UNUSED_PARAM) +{ + gss_ctx_id_t *context = app_data; + OM_uint32 maj, min; + gss_buffer_desc enc, dec; + + (void)level; + (void)conn; + + enc.value = buf; + enc.length = len; + maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL); + if(maj != GSS_S_COMPLETE) { + if(len >= 4) + strcpy(buf, "599 "); + return -1; + } + + memcpy(buf, dec.value, dec.length); + len = curlx_uztosi(dec.length); + gss_release_buffer(&min, &dec); + + return len; +} + +static int +krb5_overhead(void *app_data, int level, int len) +{ + /* no arguments are used */ + (void)app_data; + (void)level; + (void)len; + return 0; +} + +static int +krb5_encode(void *app_data, const void *from, int length, int level, void **to) +{ + gss_ctx_id_t *context = app_data; + gss_buffer_desc dec, enc; + OM_uint32 maj, min; + int state; + int len; + + /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal + * libraries modify the input buffer in gss_wrap() + */ + dec.value = (void *)from; + dec.length = length; + maj = gss_wrap(&min, *context, + level == PROT_PRIVATE, + GSS_C_QOP_DEFAULT, + &dec, &state, &enc); + + if(maj != GSS_S_COMPLETE) + return -1; + + /* malloc a new buffer, in case gss_release_buffer doesn't work as + expected */ + *to = malloc(enc.length); + if(!*to) + return -1; + memcpy(*to, enc.value, enc.length); + len = curlx_uztosi(enc.length); + gss_release_buffer(&min, &enc); + return len; +} + +static int +krb5_auth(void *app_data, struct connectdata *conn) +{ + int ret = AUTH_OK; + char *p; + const char *host = conn->host.name; + ssize_t nread; + curl_socklen_t l = sizeof(conn->local_addr); + struct Curl_easy *data = conn->data; + CURLcode result; + const char *service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : + "ftp"; + const char *srv_host = "host"; + gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp; + OM_uint32 maj, min; + gss_name_t gssname; + gss_ctx_id_t *context = app_data; + struct gss_channel_bindings_struct chan; + size_t base64_sz = 0; + struct sockaddr_in **remote_addr = + (struct sockaddr_in **)&conn->ip_addr->ai_addr; + char *stringp; + + if(getsockname(conn->sock[FIRSTSOCKET], + (struct sockaddr *)&conn->local_addr, &l) < 0) + perror("getsockname()"); + + chan.initiator_addrtype = GSS_C_AF_INET; + chan.initiator_address.length = l - 4; + chan.initiator_address.value = &conn->local_addr.sin_addr.s_addr; + chan.acceptor_addrtype = GSS_C_AF_INET; + chan.acceptor_address.length = l - 4; + chan.acceptor_address.value = &(*remote_addr)->sin_addr.s_addr; + chan.application_data.length = 0; + chan.application_data.value = NULL; + + /* this loop will execute twice (once for service, once for host) */ + for(;;) { + /* this really shouldn't be repeated here, but can't help it */ + if(service == srv_host) { + result = Curl_ftpsend(conn, "AUTH GSSAPI"); + if(result) + return -2; + + if(Curl_GetFTPResponse(&nread, conn, NULL)) + return -1; + + if(data->state.buffer[0] != '3') + return -1; + } + + stringp = aprintf("%s@%s", service, host); + if(!stringp) + return -2; + + input_buffer.value = stringp; + input_buffer.length = strlen(stringp); + maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE, + &gssname); + free(stringp); + if(maj != GSS_S_COMPLETE) { + gss_release_name(&min, &gssname); + if(service == srv_host) { + failf(data, "Error importing service name %s@%s", service, host); + return AUTH_ERROR; + } + service = srv_host; + continue; + } + /* We pass NULL as |output_name_type| to avoid a leak. */ + gss_display_name(&min, gssname, &output_buffer, NULL); + Curl_infof(data, "Trying against %s\n", output_buffer.value); + gssresp = GSS_C_NO_BUFFER; + *context = GSS_C_NO_CONTEXT; + + do { + /* Release the buffer at each iteration to avoid leaking: the first time + we are releasing the memory from gss_display_name. The last item is + taken care by a final gss_release_buffer. */ + gss_release_buffer(&min, &output_buffer); + ret = AUTH_OK; + maj = Curl_gss_init_sec_context(data, + &min, + context, + gssname, + &Curl_krb5_mech_oid, + &chan, + gssresp, + &output_buffer, + TRUE, + NULL); + + if(gssresp) { + free(_gssresp.value); + gssresp = NULL; + } + + if(GSS_ERROR(maj)) { + Curl_infof(data, "Error creating security context\n"); + ret = AUTH_ERROR; + break; + } + + if(output_buffer.length != 0) { + char *cmd; + + result = Curl_base64_encode(data, (char *)output_buffer.value, + output_buffer.length, &p, &base64_sz); + if(result) { + Curl_infof(data, "base64-encoding: %s\n", + curl_easy_strerror(result)); + ret = AUTH_ERROR; + break; + } + + cmd = aprintf("ADAT %s", p); + if(cmd) + result = Curl_ftpsend(conn, cmd); + else + result = CURLE_OUT_OF_MEMORY; + + free(p); + free(cmd); + + if(result) { + ret = -2; + break; + } + + if(Curl_GetFTPResponse(&nread, conn, NULL)) { + ret = -1; + break; + } + + if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') { + Curl_infof(data, "Server didn't accept auth data\n"); + ret = AUTH_ERROR; + break; + } + + _gssresp.value = NULL; /* make sure it is initialized */ + p = data->state.buffer + 4; + p = strstr(p, "ADAT="); + if(p) { + result = Curl_base64_decode(p + 5, + (unsigned char **)&_gssresp.value, + &_gssresp.length); + if(result) { + failf(data, "base64-decoding: %s", curl_easy_strerror(result)); + ret = AUTH_CONTINUE; + break; + } + } + + gssresp = &_gssresp; + } + } while(maj == GSS_S_CONTINUE_NEEDED); + + gss_release_name(&min, &gssname); + gss_release_buffer(&min, &output_buffer); + + if(gssresp) + free(_gssresp.value); + + if(ret == AUTH_OK || service == srv_host) + return ret; + + service = srv_host; + } + return ret; +} + +static void krb5_end(void *app_data) +{ + OM_uint32 min; + gss_ctx_id_t *context = app_data; + if(*context != GSS_C_NO_CONTEXT) { + OM_uint32 maj = gss_delete_sec_context(&min, context, GSS_C_NO_BUFFER); + (void)maj; + DEBUGASSERT(maj == GSS_S_COMPLETE); + } +} + +struct Curl_sec_client_mech Curl_krb5_client_mech = { + "GSSAPI", + sizeof(gss_ctx_id_t), + krb5_init, + krb5_auth, + krb5_end, + krb5_check_prot, + krb5_overhead, + krb5_encode, + krb5_decode +}; + +#endif /* HAVE_GSSAPI && !CURL_DISABLE_FTP */ diff --git a/libcurl/lib/ldap.c b/libcurl/lib/ldap.c new file mode 100644 index 0000000..fd31faa --- /dev/null +++ b/libcurl/lib/ldap.c @@ -0,0 +1,1088 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP) + +/* + * Notice that USE_OPENLDAP is only a source code selection switch. When + * libcurl is built with USE_OPENLDAP defined the libcurl source code that + * gets compiled is the code from openldap.c, otherwise the code that gets + * compiled is the code from ldap.c. + * + * When USE_OPENLDAP is defined a recent version of the OpenLDAP library + * might be required for compilation and runtime. In order to use ancient + * OpenLDAP library versions, USE_OPENLDAP shall not be defined. + */ + +#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */ +# include +# ifndef LDAP_VENDOR_NAME +# error Your Platform SDK is NOT sufficient for LDAP support! \ + Update your Platform SDK, or disable LDAP support! +# else +# include +# endif +#else +# define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */ +# ifdef HAVE_LBER_H +# include +# endif +# include +# if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H)) +# include +# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */ +#endif + +#include "urldata.h" +#include +#include "sendf.h" +#include "escape.h" +#include "progress.h" +#include "transfer.h" +#include "strcase.h" +#include "strtok.h" +#include "curl_ldap.h" +#include "curl_multibyte.h" +#include "curl_base64.h" +#include "connect.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef HAVE_LDAP_URL_PARSE + +/* Use our own implementation. */ + +typedef struct { + char *lud_host; + int lud_port; +#if defined(USE_WIN32_LDAP) + TCHAR *lud_dn; + TCHAR **lud_attrs; +#else + char *lud_dn; + char **lud_attrs; +#endif + int lud_scope; +#if defined(USE_WIN32_LDAP) + TCHAR *lud_filter; +#else + char *lud_filter; +#endif + char **lud_exts; + size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the + "real" struct so can only be used in code + without HAVE_LDAP_URL_PARSE defined */ +} CURL_LDAPURLDesc; + +#undef LDAPURLDesc +#define LDAPURLDesc CURL_LDAPURLDesc + +static int _ldap_url_parse(const struct connectdata *conn, + LDAPURLDesc **ludp); +static void _ldap_free_urldesc(LDAPURLDesc *ludp); + +#undef ldap_free_urldesc +#define ldap_free_urldesc _ldap_free_urldesc +#endif + +#ifdef DEBUG_LDAP + #define LDAP_TRACE(x) do { \ + _ldap_trace("%u: ", __LINE__); \ + _ldap_trace x; \ + } WHILE_FALSE + + static void _ldap_trace(const char *fmt, ...); +#else + #define LDAP_TRACE(x) Curl_nop_stmt +#endif + + +static CURLcode Curl_ldap(struct connectdata *conn, bool *done); + +/* + * LDAP protocol handler. + */ + +const struct Curl_handler Curl_handler_ldap = { + "LDAP", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_ldap, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef HAVE_LDAP_SSL +/* + * LDAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ldaps = { + "LDAPS", /* scheme */ + ZERO_NULL, /* setup_connection */ + Curl_ldap, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAPS, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + +#if defined(USE_WIN32_LDAP) + +#if defined(USE_WINDOWS_SSPI) +static int ldap_win_bind_auth(LDAP *server, const char *user, + const char *passwd, unsigned long authflags) +{ + ULONG method = 0; + SEC_WINNT_AUTH_IDENTITY cred; + int rc = LDAP_AUTH_METHOD_NOT_SUPPORTED; + + memset(&cred, 0, sizeof(cred)); + +#if defined(USE_SPNEGO) + if(authflags & CURLAUTH_NEGOTIATE) { + method = LDAP_AUTH_NEGOTIATE; + } + else +#endif +#if defined(USE_NTLM) + if(authflags & CURLAUTH_NTLM) { + method = LDAP_AUTH_NTLM; + } + else +#endif +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + if(authflags & CURLAUTH_DIGEST) { + method = LDAP_AUTH_DIGEST; + } + else +#endif + { + /* required anyway if one of upper preprocessor definitions enabled */ + } + + if(method && user && passwd) { + rc = Curl_create_sspi_identity(user, passwd, &cred); + if(!rc) { + rc = ldap_bind_s(server, NULL, (TCHAR *)&cred, method); + Curl_sspi_free_identity(&cred); + } + } + else { + /* proceed with current user credentials */ + method = LDAP_AUTH_NEGOTIATE; + rc = ldap_bind_s(server, NULL, NULL, method); + } + return rc; +} +#endif /* #if defined(USE_WINDOWS_SSPI) */ + +static int ldap_win_bind(struct connectdata *conn, LDAP *server, + const char *user, const char *passwd) +{ + int rc = LDAP_INVALID_CREDENTIALS; + + PTCHAR inuser = NULL; + PTCHAR inpass = NULL; + + if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) { + inuser = Curl_convert_UTF8_to_tchar((char *) user); + inpass = Curl_convert_UTF8_to_tchar((char *) passwd); + + rc = ldap_simple_bind_s(server, inuser, inpass); + + Curl_unicodefree(inuser); + Curl_unicodefree(inpass); + } +#if defined(USE_WINDOWS_SSPI) + else { + rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth); + } +#endif + + return rc; +} +#endif /* #if defined(USE_WIN32_LDAP) */ + +static CURLcode Curl_ldap(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + int rc = 0; + LDAP *server = NULL; + LDAPURLDesc *ludp = NULL; + LDAPMessage *ldapmsg = NULL; + LDAPMessage *entryIterator; + int num = 0; + struct Curl_easy *data = conn->data; + int ldap_proto = LDAP_VERSION3; + int ldap_ssl = 0; + char *val_b64 = NULL; + size_t val_b64_sz = 0; + curl_off_t dlsize = 0; +#ifdef LDAP_OPT_NETWORK_TIMEOUT + struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */ +#endif +#if defined(USE_WIN32_LDAP) + TCHAR *host = NULL; +#else + char *host = NULL; +#endif + char *user = NULL; + char *passwd = NULL; + + *done = TRUE; /* unconditionally */ + infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n", + LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); + infof(data, "LDAP local: %s\n", data->change.url); + +#ifdef HAVE_LDAP_URL_PARSE + rc = ldap_url_parse(data->change.url, &ludp); +#else + rc = _ldap_url_parse(conn, &ludp); +#endif + if(rc != 0) { + failf(data, "LDAP local: %s", ldap_err2string(rc)); + result = CURLE_LDAP_INVALID_URL; + goto quit; + } + + /* Get the URL scheme (either ldap or ldaps) */ + if(conn->given->flags & PROTOPT_SSL) + ldap_ssl = 1; + infof(data, "LDAP local: trying to establish %s connection\n", + ldap_ssl ? "encrypted" : "cleartext"); + +#if defined(USE_WIN32_LDAP) + host = Curl_convert_UTF8_to_tchar(conn->host.name); + if(!host) { + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } +#else + host = conn->host.name; +#endif + + if(conn->bits.user_passwd) { + user = conn->user; + passwd = conn->passwd; + } + +#ifdef LDAP_OPT_NETWORK_TIMEOUT + ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout); +#endif + ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); + + if(ldap_ssl) { +#ifdef HAVE_LDAP_SSL +#ifdef USE_WIN32_LDAP + /* Win32 LDAP SDK doesn't support insecure mode without CA! */ + server = ldap_sslinit(host, (int)conn->port, 1); + ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); +#else + int ldap_option; + char *ldap_ca = conn->ssl_config.CAfile; +#if defined(CURL_HAS_NOVELL_LDAPSDK) + rc = ldapssl_client_init(NULL, NULL); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + if(conn->ssl_config.verifypeer) { + /* Novell SDK supports DER or BASE64 files. */ + int cert_type = LDAPSSL_CERT_FILETYPE_B64; + if((data->set.ssl.cert_type) && + (strcasecompare(data->set.ssl.cert_type, "DER"))) + cert_type = LDAPSSL_CERT_FILETYPE_DER; + if(!ldap_ca) { + failf(data, "LDAP local: ERROR %s CA cert not set!", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM")); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + infof(data, "LDAP local: using %s CA cert '%s'\n", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), + ldap_ca); + rc = ldapssl_add_trusted_cert(ldap_ca, cert_type); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting %s CA cert: %s", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + ldap_option = LDAPSSL_VERIFY_SERVER; + } + else + ldap_option = LDAPSSL_VERIFY_NONE; + rc = ldapssl_set_verify_mode(ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting cert verify mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + server = ldapssl_init(host, (int)conn->port, 1); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } +#elif defined(LDAP_OPT_X_TLS) + if(conn->ssl_config.verifypeer) { + /* OpenLDAP SDK supports BASE64 files. */ + if((data->set.ssl.cert_type) && + (!strcasecompare(data->set.ssl.cert_type, "PEM"))) { + failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + if(!ldap_ca) { + failf(data, "LDAP local: ERROR PEM CA cert not set!"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca); + rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting PEM CA cert: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + ldap_option = LDAP_OPT_X_TLS_DEMAND; + } + else + ldap_option = LDAP_OPT_X_TLS_NEVER; + + rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting cert verify mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } + server = ldap_init(host, (int)conn->port); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } + ldap_option = LDAP_OPT_X_TLS_HARD; + rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } +/* + rc = ldap_start_tls_s(server, NULL, NULL); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s", + ldap_err2string(rc)); + result = CURLE_SSL_CERTPROBLEM; + goto quit; + } +*/ +#else + /* we should probably never come up to here since configure + should check in first place if we can support LDAP SSL/TLS */ + failf(data, "LDAP local: SSL/TLS not supported with this version " + "of the OpenLDAP toolkit\n"); + result = CURLE_SSL_CERTPROBLEM; + goto quit; +#endif +#endif +#endif /* CURL_LDAP_USE_SSL */ + } + else { + server = ldap_init(host, (int)conn->port); + if(server == NULL) { + failf(data, "LDAP local: Cannot connect to %s:%ld", + conn->host.dispname, conn->port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } + } +#ifdef USE_WIN32_LDAP + ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); +#endif + +#ifdef USE_WIN32_LDAP + rc = ldap_win_bind(conn, server, user, passwd); +#else + rc = ldap_simple_bind_s(server, user, passwd); +#endif + if(!ldap_ssl && rc != 0) { + ldap_proto = LDAP_VERSION2; + ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); +#ifdef USE_WIN32_LDAP + rc = ldap_win_bind(conn, server, user, passwd); +#else + rc = ldap_simple_bind_s(server, user, passwd); +#endif + } + if(rc != 0) { +#ifdef USE_WIN32_LDAP + failf(data, "LDAP local: bind via ldap_win_bind %s", + ldap_err2string(rc)); +#else + failf(data, "LDAP local: bind via ldap_simple_bind_s %s", + ldap_err2string(rc)); +#endif + result = CURLE_LDAP_CANNOT_BIND; + goto quit; + } + + rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, + ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); + + if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) { + failf(data, "LDAP remote: %s", ldap_err2string(rc)); + result = CURLE_LDAP_SEARCH_FAILED; + goto quit; + } + + for(num = 0, entryIterator = ldap_first_entry(server, ldapmsg); + entryIterator; + entryIterator = ldap_next_entry(server, entryIterator), num++) { + BerElement *ber = NULL; +#if defined(USE_WIN32_LDAP) + TCHAR *attribute; +#else + char *attribute; /*! suspicious that this isn't 'const' */ +#endif + int i; + + /* Get the DN and write it to the client */ + { + char *name; + size_t name_len; +#if defined(USE_WIN32_LDAP) + TCHAR *dn = ldap_get_dn(server, entryIterator); + name = Curl_convert_tchar_to_UTF8(dn); + if(!name) { + ldap_memfree(dn); + + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } +#else + char *dn = name = ldap_get_dn(server, entryIterator); +#endif + name_len = strlen(name); + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name, + name_len); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) { +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + + goto quit; + } + + dlsize += name_len + 5; + +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(name); +#endif + ldap_memfree(dn); + } + + /* Get the attributes and write them to the client */ + for(attribute = ldap_first_attribute(server, entryIterator, &ber); + attribute; + attribute = ldap_next_attribute(server, entryIterator, ber)) { + BerValue **vals; + size_t attr_len; +#if defined(USE_WIN32_LDAP) + char *attr = Curl_convert_tchar_to_UTF8(attribute); + if(!attr) { + if(ber) + ber_free(ber, 0); + + result = CURLE_OUT_OF_MEMORY; + + goto quit; + } +#else + char *attr = attribute; +#endif + attr_len = strlen(attr); + + vals = ldap_get_values_len(server, entryIterator, attribute); + if(vals != NULL) { + for(i = 0; (vals[i] != NULL); i++) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *) attr, attr_len); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += attr_len + 3; + + if((attr_len > 7) && + (strcmp(";binary", (char *) attr + (attr_len - 7)) == 0)) { + /* Binary attribute, encode to base64. */ + result = Curl_base64_encode(data, + vals[i]->bv_val, + vals[i]->bv_len, + &val_b64, + &val_b64_sz); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + if(val_b64_sz > 0) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, + val_b64_sz); + free(val_b64); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += val_b64_sz; + } + } + else { + result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val, + vals[i]->bv_len); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize += vals[i]->bv_len; + } + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) { + ldap_value_free_len(vals); +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + if(ber) + ber_free(ber, 0); + + goto quit; + } + + dlsize++; + } + + /* Free memory used to store values */ + ldap_value_free_len(vals); + } + + /* Free the attribute as we are done with it */ +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(attr); +#endif + ldap_memfree(attribute); + + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(result) + goto quit; + dlsize++; + Curl_pgrsSetDownloadCounter(data, dlsize); + } + + if(ber) + ber_free(ber, 0); + } + +quit: + if(ldapmsg) { + ldap_msgfree(ldapmsg); + LDAP_TRACE(("Received %d entries\n", num)); + } + if(rc == LDAP_SIZELIMIT_EXCEEDED) + infof(data, "There are more than %d entries\n", num); + if(ludp) + ldap_free_urldesc(ludp); + if(server) + ldap_unbind_s(server); +#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK) + if(ldap_ssl) + ldapssl_client_deinit(); +#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */ + +#if defined(USE_WIN32_LDAP) + Curl_unicodefree(host); +#endif + + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + connclose(conn, "LDAP connection always disable re-use"); + + return result; +} + +#ifdef DEBUG_LDAP +static void _ldap_trace(const char *fmt, ...) +{ + static int do_trace = -1; + va_list args; + + if(do_trace == -1) { + const char *env = getenv("CURL_TRACE"); + do_trace = (env && strtol(env, NULL, 10) > 0); + } + if(!do_trace) + return; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} +#endif + +#ifndef HAVE_LDAP_URL_PARSE + +/* + * Return scope-value for a scope-string. + */ +static int str2scope(const char *p) +{ + if(strcasecompare(p, "one")) + return LDAP_SCOPE_ONELEVEL; + if(strcasecompare(p, "onetree")) + return LDAP_SCOPE_ONELEVEL; + if(strcasecompare(p, "base")) + return LDAP_SCOPE_BASE; + if(strcasecompare(p, "sub")) + return LDAP_SCOPE_SUBTREE; + if(strcasecompare(p, "subtree")) + return LDAP_SCOPE_SUBTREE; + return (-1); +} + +/* + * Split 'str' into strings separated by commas. + * Note: out[] points into 'str'. + */ +static bool split_str(char *str, char ***out, size_t *count) +{ + char **res; + char *lasts; + char *s; + size_t i; + size_t items = 1; + + s = strchr(str, ','); + while(s) { + items++; + s = strchr(++s, ','); + } + + res = calloc(items, sizeof(char *)); + if(!res) + return FALSE; + + for(i = 0, s = strtok_r(str, ",", &lasts); s && i < items; + s = strtok_r(NULL, ",", &lasts), i++) + res[i] = s; + + *out = res; + *count = items; + + return TRUE; +} + +/* + * Break apart the pieces of an LDAP URL. + * Syntax: + * ldap://:/???? + * + * already known from 'conn->host.name'. + * already known from 'conn->remote_port'. + * extract the rest from 'conn->data->state.path+1'. All fields are optional. + * e.g. + * ldap://:/??? + * yields ludp->lud_dn = "". + * + * Defined in RFC4516 section 2. + */ +static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) +{ + int rc = LDAP_SUCCESS; + char *path; + char *query; + char *p; + char *q; + size_t i; + + if(!conn->data || + !conn->data->state.up.path || + conn->data->state.up.path[0] != '/' || + !strncasecompare("LDAP", conn->data->state.up.scheme, 4)) + return LDAP_INVALID_SYNTAX; + + ludp->lud_scope = LDAP_SCOPE_BASE; + ludp->lud_port = conn->remote_port; + ludp->lud_host = conn->host.name; + + /* Duplicate the path */ + p = path = strdup(conn->data->state.up.path + 1); + if(!path) + return LDAP_NO_MEMORY; + + /* Duplicate the query */ + q = query = strdup(conn->data->state.up.query); + if(!query) { + free(path); + return LDAP_NO_MEMORY; + } + + /* Parse the DN (Distinguished Name) */ + if(*p) { + char *dn = p; + char *unescaped; + CURLcode result; + + LDAP_TRACE(("DN '%s'\n", dn)); + + /* Unescape the DN */ + result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE); + if(result) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_dn) { + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_dn = unescaped; +#endif + } + + p = q; + if(!p) + goto quit; + + /* Parse the attributes. skip "??" */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + char **attributes; + size_t count = 0; + + /* Split the string into an array of attributes */ + if(!split_str(p, &attributes, &count)) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + + /* Allocate our array (+1 for the NULL entry) */ +#if defined(USE_WIN32_LDAP) + ludp->lud_attrs = calloc(count + 1, sizeof(TCHAR *)); +#else + ludp->lud_attrs = calloc(count + 1, sizeof(char *)); +#endif + if(!ludp->lud_attrs) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } + + for(i = 0; i < count; i++) { + char *unescaped; + CURLcode result; + + LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i])); + + /* Unescape the attribute */ + result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL, + FALSE); + if(result) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_attrs[i]) { + free(attributes); + + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_attrs[i] = unescaped; +#endif + + ludp->lud_attrs_dups++; + } + + free(attributes); + } + + p = q; + if(!p) + goto quit; + + /* Parse the scope. skip "??" */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + ludp->lud_scope = str2scope(p); + if(ludp->lud_scope == -1) { + rc = LDAP_INVALID_SYNTAX; + + goto quit; + } + LDAP_TRACE(("scope %d\n", ludp->lud_scope)); + } + + p = q; + if(!p) + goto quit; + + /* Parse the filter */ + q = strchr(p, '?'); + if(q) + *q++ = '\0'; + + if(*p) { + char *filter = p; + char *unescaped; + CURLcode result; + + LDAP_TRACE(("filter '%s'\n", filter)); + + /* Unescape the filter */ + result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE); + if(result) { + rc = LDAP_NO_MEMORY; + + goto quit; + } + +#if defined(USE_WIN32_LDAP) + /* Convert the unescaped string to a tchar */ + ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped); + + /* Free the unescaped string as we are done with it */ + Curl_unicodefree(unescaped); + + if(!ludp->lud_filter) { + rc = LDAP_NO_MEMORY; + + goto quit; + } +#else + ludp->lud_filter = unescaped; +#endif + } + + p = q; + if(p && !*p) { + rc = LDAP_INVALID_SYNTAX; + + goto quit; + } + +quit: + free(path); + free(query); + + return rc; +} + +static int _ldap_url_parse(const struct connectdata *conn, + LDAPURLDesc **ludpp) +{ + LDAPURLDesc *ludp = calloc(1, sizeof(*ludp)); + int rc; + + *ludpp = NULL; + if(!ludp) + return LDAP_NO_MEMORY; + + rc = _ldap_url_parse2(conn, ludp); + if(rc != LDAP_SUCCESS) { + _ldap_free_urldesc(ludp); + ludp = NULL; + } + *ludpp = ludp; + return (rc); +} + +static void _ldap_free_urldesc(LDAPURLDesc *ludp) +{ + if(!ludp) + return; + + free(ludp->lud_dn); + free(ludp->lud_filter); + + if(ludp->lud_attrs) { + size_t i; + for(i = 0; i < ludp->lud_attrs_dups; i++) + free(ludp->lud_attrs[i]); + free(ludp->lud_attrs); + } + + free(ludp); +} +#endif /* !HAVE_LDAP_URL_PARSE */ +#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */ diff --git a/libcurl/lib/libcurl.plist b/libcurl/lib/libcurl.plist new file mode 100644 index 0000000..c0adf43 --- /dev/null +++ b/libcurl/lib/libcurl.plist @@ -0,0 +1,35 @@ + + + + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundleDevelopmentRegion + English + + CFBundleExecutable + curl + + CFBundleIdentifier + se.haxx.curl.libcurl + + CFBundleVersion + 7.65.3 + + CFBundleName + libcurl + + CFBundlePackageType + FMWK + + CFBundleSignature + ???? + + CFBundleShortVersionString + libcurl 7.65.3 + + CFBundleGetInfoString + libcurl.plist 7.65.3 + + diff --git a/libcurl/lib/libcurl.rc b/libcurl/lib/libcurl.rc new file mode 100644 index 0000000..4839d0a --- /dev/null +++ b/libcurl/lib/libcurl.rc @@ -0,0 +1,63 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include +#include "../include/curl/curlver.h" + +LANGUAGE 0, 0 + +#define RC_VERSION LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0 + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RC_VERSION + PRODUCTVERSION RC_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#if defined(DEBUGBUILD) || defined(_DEBUG) + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0L + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "The curl library, https://curl.haxx.se/\0" + VALUE "FileDescription", "libcurl Shared Library\0" + VALUE "FileVersion", LIBCURL_VERSION "\0" + VALUE "InternalName", "libcurl\0" + VALUE "OriginalFilename", "libcurl.dll\0" + VALUE "ProductName", "The curl library\0" + VALUE "ProductVersion", LIBCURL_VERSION "\0" + VALUE "LegalCopyright", "\xa9 " LIBCURL_COPYRIGHT "\0" /* a9: Copyright symbol */ + VALUE "License", "https://curl.haxx.se/docs/copyright.html\0" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/libcurl/lib/libcurl.vers.in b/libcurl/lib/libcurl.vers.in new file mode 100644 index 0000000..ae978a4 --- /dev/null +++ b/libcurl/lib/libcurl.vers.in @@ -0,0 +1,13 @@ +HIDDEN +{ + local: + __*; + _rest*; + _save*; +}; + +CURL_@CURL_LT_SHLIB_VERSIONED_FLAVOUR@4 +{ + global: curl_*; + local: *; +}; diff --git a/libcurl/lib/llist.c b/libcurl/lib/llist.c new file mode 100644 index 0000000..f8769c2 --- /dev/null +++ b/libcurl/lib/llist.c @@ -0,0 +1,197 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "llist.h" +#include "curl_memory.h" + +/* this must be the last include file */ +#include "memdebug.h" + +/* + * @unittest: 1300 + */ +void +Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor) +{ + l->size = 0; + l->dtor = dtor; + l->head = NULL; + l->tail = NULL; +} + +/* + * Curl_llist_insert_next() + * + * Inserts a new list element after the given one 'e'. If the given existing + * entry is NULL and the list already has elements, the new one will be + * inserted first in the list. + * + * The 'ne' argument should be a pointer into the object to store. + * + * @unittest: 1300 + */ +void +Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, + const void *p, + struct curl_llist_element *ne) +{ + ne->ptr = (void *) p; + if(list->size == 0) { + list->head = ne; + list->head->prev = NULL; + list->head->next = NULL; + list->tail = ne; + } + else { + /* if 'e' is NULL here, we insert the new element first in the list */ + ne->next = e?e->next:list->head; + ne->prev = e; + if(!e) { + list->head->prev = ne; + list->head = ne; + } + else if(e->next) { + e->next->prev = ne; + } + else { + list->tail = ne; + } + if(e) + e->next = ne; + } + + ++list->size; +} + +/* + * @unittest: 1300 + */ +void +Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, + void *user) +{ + void *ptr; + if(e == NULL || list->size == 0) + return; + + if(e == list->head) { + list->head = e->next; + + if(list->head == NULL) + list->tail = NULL; + else + e->next->prev = NULL; + } + else { + if(!e->prev) + list->head = e->next; + else + e->prev->next = e->next; + + if(!e->next) + list->tail = e->prev; + else + e->next->prev = e->prev; + } + + ptr = e->ptr; + + e->ptr = NULL; + e->prev = NULL; + e->next = NULL; + + --list->size; + + /* call the dtor() last for when it actually frees the 'e' memory itself */ + if(list->dtor) + list->dtor(user, ptr); +} + +void +Curl_llist_destroy(struct curl_llist *list, void *user) +{ + if(list) { + while(list->size > 0) + Curl_llist_remove(list, list->tail, user); + } +} + +size_t +Curl_llist_count(struct curl_llist *list) +{ + return list->size; +} + +/* + * @unittest: 1300 + */ +void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, + struct curl_llist *to_list, + struct curl_llist_element *to_e) +{ + /* Remove element from list */ + if(e == NULL || list->size == 0) + return; + + if(e == list->head) { + list->head = e->next; + + if(list->head == NULL) + list->tail = NULL; + else + e->next->prev = NULL; + } + else { + e->prev->next = e->next; + if(!e->next) + list->tail = e->prev; + else + e->next->prev = e->prev; + } + + --list->size; + + /* Add element to to_list after to_e */ + if(to_list->size == 0) { + to_list->head = e; + to_list->head->prev = NULL; + to_list->head->next = NULL; + to_list->tail = e; + } + else { + e->next = to_e->next; + e->prev = to_e; + if(to_e->next) { + to_e->next->prev = e; + } + else { + to_list->tail = e; + } + to_e->next = e; + } + + ++to_list->size; +} diff --git a/libcurl/lib/llist.h b/libcurl/lib/llist.h new file mode 100644 index 0000000..b9d4c89 --- /dev/null +++ b/libcurl/lib/llist.h @@ -0,0 +1,53 @@ +#ifndef HEADER_CURL_LLIST_H +#define HEADER_CURL_LLIST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include + +typedef void (*curl_llist_dtor)(void *, void *); + +struct curl_llist_element { + void *ptr; + struct curl_llist_element *prev; + struct curl_llist_element *next; +}; + +struct curl_llist { + struct curl_llist_element *head; + struct curl_llist_element *tail; + curl_llist_dtor dtor; + size_t size; +}; + +void Curl_llist_init(struct curl_llist *, curl_llist_dtor); +void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *, + const void *, struct curl_llist_element *node); +void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, + void *); +size_t Curl_llist_count(struct curl_llist *); +void Curl_llist_destroy(struct curl_llist *, void *); +void Curl_llist_move(struct curl_llist *, struct curl_llist_element *, + struct curl_llist *, struct curl_llist_element *); + +#endif /* HEADER_CURL_LLIST_H */ diff --git a/libcurl/lib/makefile.amiga b/libcurl/lib/makefile.amiga new file mode 100644 index 0000000..673b147 --- /dev/null +++ b/libcurl/lib/makefile.amiga @@ -0,0 +1,21 @@ +# +# libcurl Makefile for AmigaOS ... +# + +# change the follow to where you have the AmiTCP SDK v4.3 includes: + +ATCPSDKI= /GG/netinclude + + +CC = m68k-amigaos-gcc +CFLAGS = -I$(ATCPSDKI) -m68020-60 -O2 -msoft-float -noixemul -g -I. -I../include -W -Wall + +include Makefile.inc +OBJS = $(CSOURCES:.c=.o) + +all: $(OBJS) + ar cru libcurl.a $(OBJS) + ranlib libcurl.a + +install: + $(INSTALL) -c ./libcurl.a /lib/libcurl.a diff --git a/libcurl/lib/makefile.dj b/libcurl/lib/makefile.dj new file mode 100644 index 0000000..941f8ce --- /dev/null +++ b/libcurl/lib/makefile.dj @@ -0,0 +1,71 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 2003 - 2008, Gisle Vanem . +# Copyright (C) 2003 - 2017, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +#*************************************************************************** + +# +# Adapted for djgpp2 / Watt-32 / DOS +# + +DEPEND_PREREQ = curl_config.h +VPATH = vtls vauth +TOPDIR = .. + +include ../packages/DOS/common.dj +include Makefile.inc + +CFLAGS += -DBUILDING_LIBCURL + +SOURCES = $(sort $(CSOURCES)) +OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.c=.o))) + +CURL_LIB = libcurl.a + +all: $(OBJ_DIR) curl_config.h $(CURL_LIB) + +$(CURL_LIB): $(OBJECTS) + ar rs $@ $? + +curl_config.h: config-dos.h + $(COPY) $^ $@ + +# clean generated files +# +genclean: + - $(DELETE) curl_config.h + +# clean object files and subdir +# +objclean: genclean + - $(DELETE) $(OBJ_DIR)$(DS)*.o + - $(RMDIR) $(OBJ_DIR) + +# clean without removing built library +# +clean: objclean + - $(DELETE) depend.dj + +# clean everything +# +realclean vclean: clean + - $(DELETE) $(CURL_LIB) + +-include depend.dj diff --git a/libcurl/lib/md4.c b/libcurl/lib/md4.c new file mode 100644 index 0000000..0b4ea9a --- /dev/null +++ b/libcurl/lib/md4.c @@ -0,0 +1,320 @@ +/* + * !checksrc! disable COPYRIGHT + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD4 Message-Digest Algorithm (RFC 1320). + * + * Homepage: + https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. In case + * this attempt to disclaim copyright and place the software in the public + * domain is deemed null and void, then the software is Copyright (c) 2001 + * Alexander Peslyak and it is hereby released to the general public under the + * following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#include "curl_setup.h" + +#ifdef USE_OPENSSL +#include +#endif +#ifdef USE_MBEDTLS +#include +#endif + +/* The NSS, OS/400, and when not included, OpenSSL and mbed TLS crypto + * libraries do not provide the MD4 hash algorithm, so we use this + * implementation of it */ +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ + (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \ + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) + +#include "curl_md4.h" +#include "warnless.h" + +#ifndef HAVE_OPENSSL + +#include + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD4_u32plus; + +typedef struct { + MD4_u32plus lo, hi; + MD4_u32plus a, b, c, d; + unsigned char buffer[64]; + MD4_u32plus block[16]; +} MD4_CTX; + +static void MD4_Init(MD4_CTX *ctx); +static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size); +static void MD4_Final(unsigned char *result, MD4_CTX *ctx); + +/* + * The basic MD4 functions. + * + * F and G are optimized compared to their RFC 1320 definitions, with the + * optimization for F borrowed from Colin Plumb's MD5 implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* + * The MD4 transformation for all three rounds. + */ +#define STEP(f, a, b, c, d, x, s) \ + (a) += f((b), (c), (d)) + (x); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD4_u32plus *)(void *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD4_u32plus)ptr[(n) * 4] | \ + ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD4_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(MD4_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD4_u32plus a, b, c, d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + MD4_u32plus saved_a, saved_b, saved_c, saved_d; + + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 3) + STEP(F, d, a, b, c, SET(1), 7) + STEP(F, c, d, a, b, SET(2), 11) + STEP(F, b, c, d, a, SET(3), 19) + STEP(F, a, b, c, d, SET(4), 3) + STEP(F, d, a, b, c, SET(5), 7) + STEP(F, c, d, a, b, SET(6), 11) + STEP(F, b, c, d, a, SET(7), 19) + STEP(F, a, b, c, d, SET(8), 3) + STEP(F, d, a, b, c, SET(9), 7) + STEP(F, c, d, a, b, SET(10), 11) + STEP(F, b, c, d, a, SET(11), 19) + STEP(F, a, b, c, d, SET(12), 3) + STEP(F, d, a, b, c, SET(13), 7) + STEP(F, c, d, a, b, SET(14), 11) + STEP(F, b, c, d, a, SET(15), 19) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while(size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +static void MD4_Init(MD4_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) +{ + MD4_u32plus saved_lo; + unsigned long used; + + saved_lo = ctx->lo; + ctx->lo = (saved_lo + size) & 0x1fffffff; + if(ctx->lo < saved_lo) + ctx->hi++; + ctx->hi += (MD4_u32plus)size >> 29; + + used = saved_lo & 0x3f; + + if(used) { + unsigned long available = 64 - used; + + if(size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if(size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +static void MD4_Final(unsigned char *result, MD4_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if(available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); + ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); + ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); + ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff); + ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); + ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); + ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); + ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); + + body(ctx, ctx->buffer, 64); + + result[0] = curlx_ultouc((ctx->a)&0xff); + result[1] = curlx_ultouc((ctx->a >> 8)&0xff); + result[2] = curlx_ultouc((ctx->a >> 16)&0xff); + result[3] = curlx_ultouc(ctx->a >> 24); + result[4] = curlx_ultouc((ctx->b)&0xff); + result[5] = curlx_ultouc((ctx->b >> 8)&0xff); + result[6] = curlx_ultouc((ctx->b >> 16)&0xff); + result[7] = curlx_ultouc(ctx->b >> 24); + result[8] = curlx_ultouc((ctx->c)&0xff); + result[9] = curlx_ultouc((ctx->c >> 8)&0xff); + result[10] = curlx_ultouc((ctx->c >> 16)&0xff); + result[11] = curlx_ultouc(ctx->c >> 24); + result[12] = curlx_ultouc((ctx->d)&0xff); + result[13] = curlx_ultouc((ctx->d >> 8)&0xff); + result[14] = curlx_ultouc((ctx->d >> 16)&0xff); + result[15] = curlx_ultouc(ctx->d >> 24); + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif + +void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len) +{ + MD4_CTX ctx; + MD4_Init(&ctx); + MD4_Update(&ctx, input, curlx_uztoui(len)); + MD4_Final(output, &ctx); +} + +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) || + (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */ diff --git a/libcurl/lib/md5.c b/libcurl/lib/md5.c new file mode 100644 index 0000000..2b81ca4 --- /dev/null +++ b/libcurl/lib/md5.c @@ -0,0 +1,568 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +#include + +#include "curl_md5.h" +#include "curl_hmac.h" +#include "warnless.h" + +#if defined(USE_GNUTLS_NETTLE) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct md5_ctx MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx) +{ + md5_init(ctx); +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + md5_update(ctx, inputLen, input); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + md5_digest(ctx, 16, digest); +} + +#elif defined(USE_GNUTLS) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef gcry_md_hd_t MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx) +{ + gcry_md_open(ctx, GCRY_MD_MD5, 0); +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + gcry_md_write(*ctx, input, inputLen); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + memcpy(digest, gcry_md_read(*ctx, 0), 16); + gcry_md_close(*ctx); +} + +#elif defined(USE_OPENSSL) && !defined(USE_AMISSL) +/* When OpenSSL is available we use the MD5-function from OpenSSL */ +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ + (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ + (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000)) + +/* For Apple operating systems: CommonCrypto has the functions we need. + These functions are available on Tiger and later, as well as iOS 2.0 + and later. If you're building for an older cat, well, sorry. + + Declaring the functions as static like this seems to be a bit more + reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */ +# include +# define MD5_CTX CC_MD5_CTX +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +static void MD5_Init(MD5_CTX *ctx) +{ + CC_MD5_Init(ctx); +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + CC_MD5_Update(ctx, input, inputLen); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + CC_MD5_Final(digest, ctx); +} + +#elif defined(WIN32) && !defined(CURL_WINDOWS_APP) + +#include +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct { + HCRYPTPROV hCryptProv; + HCRYPTHASH hHash; +} MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx) +{ + if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash); + } +} + +static void MD5_Update(MD5_CTX *ctx, + const unsigned char *input, + unsigned int inputLen) +{ + CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); +} + +static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + unsigned long length = 0; + CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0); + if(length == 16) + CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0); + if(ctx->hHash) + CryptDestroyHash(ctx->hHash); + if(ctx->hCryptProv) + CryptReleaseContext(ctx->hCryptProv, 0); +} + +#else +/* When no other crypto library is available we use this code segment */ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#include + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +static void MD5_Init(MD5_CTX *ctx); +static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +static void MD5_Final(unsigned char *result, MD5_CTX *ctx); + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)(void *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD5_u32plus a, b, c, d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while(size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +static void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used; + + saved_lo = ctx->lo; + ctx->lo = (saved_lo + size) & 0x1fffffff; + if(ctx->lo < saved_lo) + ctx->hi++; + ctx->hi += (MD5_u32plus)size >> 29; + + used = saved_lo & 0x3f; + + if(used) { + unsigned long available = 64 - used; + + if(size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if(size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +static void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if(available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); + ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); + ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); + ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24); + ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); + ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); + ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); + ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); + + body(ctx, ctx->buffer, 64); + + result[0] = curlx_ultouc((ctx->a)&0xff); + result[1] = curlx_ultouc((ctx->a >> 8)&0xff); + result[2] = curlx_ultouc((ctx->a >> 16)&0xff); + result[3] = curlx_ultouc(ctx->a >> 24); + result[4] = curlx_ultouc((ctx->b)&0xff); + result[5] = curlx_ultouc((ctx->b >> 8)&0xff); + result[6] = curlx_ultouc((ctx->b >> 16)&0xff); + result[7] = curlx_ultouc(ctx->b >> 24); + result[8] = curlx_ultouc((ctx->c)&0xff); + result[9] = curlx_ultouc((ctx->c >> 8)&0xff); + result[10] = curlx_ultouc((ctx->c >> 16)&0xff); + result[11] = curlx_ultouc(ctx->c >> 24); + result[12] = curlx_ultouc((ctx->d)&0xff); + result[13] = curlx_ultouc((ctx->d >> 8)&0xff); + result[14] = curlx_ultouc((ctx->d >> 16)&0xff); + result[15] = curlx_ultouc(ctx->d >> 24); + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif /* CRYPTO LIBS */ + +const HMAC_params Curl_HMAC_MD5[] = { + { + /* Hash initialization function. */ + CURLX_FUNCTION_CAST(HMAC_hinit_func, MD5_Init), + /* Hash update function. */ + CURLX_FUNCTION_CAST(HMAC_hupdate_func, MD5_Update), + /* Hash computation end function. */ + CURLX_FUNCTION_CAST(HMAC_hfinal_func, MD5_Final), + /* Size of hash context structure. */ + sizeof(MD5_CTX), + /* Maximum key length. */ + 64, + /* Result size. */ + 16 + } +}; + +const MD5_params Curl_DIGEST_MD5[] = { + { + /* Digest initialization function */ + CURLX_FUNCTION_CAST(Curl_MD5_init_func, MD5_Init), + /* Digest update function */ + CURLX_FUNCTION_CAST(Curl_MD5_update_func, MD5_Update), + /* Digest computation end function */ + CURLX_FUNCTION_CAST(Curl_MD5_final_func, MD5_Final), + /* Size of digest context struct */ + sizeof(MD5_CTX), + /* Result size */ + 16 + } +}; + +/* + * @unittest: 1601 + */ +void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */ + const unsigned char *input) +{ + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, input, curlx_uztoui(strlen((char *)input))); + MD5_Final(outbuffer, &ctx); +} + +MD5_context *Curl_MD5_init(const MD5_params *md5params) +{ + MD5_context *ctxt; + + /* Create MD5 context */ + ctxt = malloc(sizeof(*ctxt)); + + if(!ctxt) + return ctxt; + + ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize); + + if(!ctxt->md5_hashctx) { + free(ctxt); + return NULL; + } + + ctxt->md5_hash = md5params; + + (*md5params->md5_init_func)(ctxt->md5_hashctx); + + return ctxt; +} + +CURLcode Curl_MD5_update(MD5_context *context, + const unsigned char *data, + unsigned int len) +{ + (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len); + + return CURLE_OK; +} + +CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result) +{ + (*context->md5_hash->md5_final_func)(result, context->md5_hashctx); + + free(context->md5_hashctx); + free(context); + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libcurl/lib/memdebug.c b/libcurl/lib/memdebug.c new file mode 100644 index 0000000..ede6009 --- /dev/null +++ b/libcurl/lib/memdebug.c @@ -0,0 +1,503 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURLDEBUG + +#include + +#include "urldata.h" + +#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */ + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Until 2011-08-17 libcurl's Memory Tracking feature also performed + * automatic malloc and free filling operations using 0xA5 and 0x13 + * values. Our own preinitialization of dynamically allocated memory + * might be useful when not using third party memory debuggers, but + * on the other hand this would fool memory debuggers into thinking + * that all dynamically allocated memory is properly initialized. + * + * As a default setting, libcurl's Memory Tracking feature no longer + * performs preinitialization of dynamically allocated memory on its + * own. If you know what you are doing, and really want to retain old + * behavior, you can achieve this compiling with preprocessor symbols + * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate + * values. + */ + +#ifdef CURL_MT_MALLOC_FILL +# if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff) +# error "invalid CURL_MT_MALLOC_FILL or out of range" +# endif +#endif + +#ifdef CURL_MT_FREE_FILL +# if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff) +# error "invalid CURL_MT_FREE_FILL or out of range" +# endif +#endif + +#if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL) +# if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL) +# error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL" +# endif +#endif + +#ifdef CURL_MT_MALLOC_FILL +# define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len)) +#else +# define mt_malloc_fill(buf,len) Curl_nop_stmt +#endif + +#ifdef CURL_MT_FREE_FILL +# define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len)) +#else +# define mt_free_fill(buf,len) Curl_nop_stmt +#endif + +struct memdebug { + size_t size; + union { + curl_off_t o; + double d; + void *p; + } mem[1]; + /* I'm hoping this is the thing with the strictest alignment + * requirements. That also means we waste some space :-( */ +}; + +/* + * Note that these debug functions are very simple and they are meant to + * remain so. For advanced analysis, record a log file and write perl scripts + * to analyze them! + * + * Don't use these with multithreaded test programs! + */ + +FILE *curl_dbg_logfile = NULL; +static bool memlimit = FALSE; /* enable memory limit */ +static long memsize = 0; /* set number of mallocs allowed */ + +/* this sets the log file name */ +void curl_dbg_memdebug(const char *logname) +{ + if(!curl_dbg_logfile) { + if(logname && *logname) + curl_dbg_logfile = fopen(logname, FOPEN_WRITETEXT); + else + curl_dbg_logfile = stderr; +#ifdef MEMDEBUG_LOG_SYNC + /* Flush the log file after every line so the log isn't lost in a crash */ + if(curl_dbg_logfile) + setbuf(curl_dbg_logfile, (char *)NULL); +#endif + } +} + +/* This function sets the number of malloc() calls that should return + successfully! */ +void curl_dbg_memlimit(long limit) +{ + if(!memlimit) { + memlimit = TRUE; + memsize = limit; + } +} + +/* returns TRUE if this isn't allowed! */ +static bool countcheck(const char *func, int line, const char *source) +{ + /* if source is NULL, then the call is made internally and this check + should not be made */ + if(memlimit && source) { + if(!memsize) { + if(source) { + /* log to file */ + curl_dbg_log("LIMIT %s:%d %s reached memlimit\n", + source, line, func); + /* log to stderr also */ + fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", + source, line, func); + fflush(curl_dbg_logfile); /* because it might crash now */ + } + errno = ENOMEM; + return TRUE; /* RETURN ERROR! */ + } + else + memsize--; /* countdown */ + + + } + + return FALSE; /* allow this */ +} + +void *curl_dbg_malloc(size_t wantedsize, int line, const char *source) +{ + struct memdebug *mem; + size_t size; + + DEBUGASSERT(wantedsize != 0); + + if(countcheck("malloc", line, source)) + return NULL; + + /* alloc at least 64 bytes */ + size = sizeof(struct memdebug) + wantedsize; + + mem = (Curl_cmalloc)(size); + if(mem) { + /* fill memory with junk */ + mt_malloc_fill(mem->mem, wantedsize); + mem->size = wantedsize; + } + + if(source) + curl_dbg_log("MEM %s:%d malloc(%zu) = %p\n", + source, line, wantedsize, + mem ? (void *)mem->mem : (void *)0); + + return (mem ? mem->mem : NULL); +} + +void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size, + int line, const char *source) +{ + struct memdebug *mem; + size_t size, user_size; + + DEBUGASSERT(wanted_elements != 0); + DEBUGASSERT(wanted_size != 0); + + if(countcheck("calloc", line, source)) + return NULL; + + /* alloc at least 64 bytes */ + user_size = wanted_size * wanted_elements; + size = sizeof(struct memdebug) + user_size; + + mem = (Curl_ccalloc)(1, size); + if(mem) + mem->size = user_size; + + if(source) + curl_dbg_log("MEM %s:%d calloc(%zu,%zu) = %p\n", + source, line, wanted_elements, wanted_size, + mem ? (void *)mem->mem : (void *)0); + + return (mem ? mem->mem : NULL); +} + +char *curl_dbg_strdup(const char *str, int line, const char *source) +{ + char *mem; + size_t len; + + DEBUGASSERT(str != NULL); + + if(countcheck("strdup", line, source)) + return NULL; + + len = strlen(str) + 1; + + mem = curl_dbg_malloc(len, 0, NULL); /* NULL prevents logging */ + if(mem) + memcpy(mem, str, len); + + if(source) + curl_dbg_log("MEM %s:%d strdup(%p) (%zu) = %p\n", + source, line, (const void *)str, len, (const void *)mem); + + return mem; +} + +#if defined(WIN32) && defined(UNICODE) +wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source) +{ + wchar_t *mem; + size_t wsiz, bsiz; + + DEBUGASSERT(str != NULL); + + if(countcheck("wcsdup", line, source)) + return NULL; + + wsiz = wcslen(str) + 1; + bsiz = wsiz * sizeof(wchar_t); + + mem = curl_dbg_malloc(bsiz, 0, NULL); /* NULL prevents logging */ + if(mem) + memcpy(mem, str, bsiz); + + if(source) + curl_dbg_log("MEM %s:%d wcsdup(%p) (%zu) = %p\n", + source, line, (void *)str, bsiz, (void *)mem); + + return mem; +} +#endif + +/* We provide a realloc() that accepts a NULL as pointer, which then + performs a malloc(). In order to work with ares. */ +void *curl_dbg_realloc(void *ptr, size_t wantedsize, + int line, const char *source) +{ + struct memdebug *mem = NULL; + + size_t size = sizeof(struct memdebug) + wantedsize; + + DEBUGASSERT(wantedsize != 0); + + if(countcheck("realloc", line, source)) + return NULL; + +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:1684) + /* 1684: conversion from pointer to same-sized integral type */ +#endif + + if(ptr) + mem = (void *)((char *)ptr - offsetof(struct memdebug, mem)); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif + + mem = (Curl_crealloc)(mem, size); + if(source) + curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n", + source, line, (void *)ptr, wantedsize, + mem ? (void *)mem->mem : (void *)0); + + if(mem) { + mem->size = wantedsize; + return mem->mem; + } + + return NULL; +} + +void curl_dbg_free(void *ptr, int line, const char *source) +{ + if(ptr) { + struct memdebug *mem; + +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:1684) + /* 1684: conversion from pointer to same-sized integral type */ +#endif + + mem = (void *)((char *)ptr - offsetof(struct memdebug, mem)); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif + + /* destroy */ + mt_free_fill(mem->mem, mem->size); + + /* free for real */ + (Curl_cfree)(mem); + } + + if(source) + curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr); +} + +curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d socket() = %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d socket() = %ld\n" : + "FD %s:%d socket() = %zd\n"; + + curl_socket_t sockfd; + + if(countcheck("socket", line, source)) + return CURL_SOCKET_BAD; + + sockfd = socket(domain, type, protocol); + + if(source && (sockfd != CURL_SOCKET_BAD)) + curl_dbg_log(fmt, source, line, sockfd); + + return sockfd; +} + +SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line, + const char *source) +{ + SEND_TYPE_RETV rc; + if(countcheck("send", line, source)) + return -1; + rc = send(sockfd, buf, len, flags); + if(source) + curl_dbg_log("SEND %s:%d send(%lu) = %ld\n", + source, line, (unsigned long)len, (long)rc); + return rc; +} + +RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line, + const char *source) +{ + RECV_TYPE_RETV rc; + if(countcheck("recv", line, source)) + return -1; + rc = recv(sockfd, buf, len, flags); + if(source) + curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n", + source, line, (unsigned long)len, (long)rc); + return rc; +} + +#ifdef HAVE_SOCKETPAIR +int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d socketpair() = %d %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d socketpair() = %ld %ld\n" : + "FD %s:%d socketpair() = %zd %zd\n"; + + int res = socketpair(domain, type, protocol, socket_vector); + + if(source && (0 == res)) + curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]); + + return res; +} +#endif + +curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen, + int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d accept() = %d\n" : + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d accept() = %ld\n" : + "FD %s:%d accept() = %zd\n"; + + struct sockaddr *addr = (struct sockaddr *)saddr; + curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen; + + curl_socket_t sockfd = accept(s, addr, addrlen); + + if(source && (sockfd != CURL_SOCKET_BAD)) + curl_dbg_log(fmt, source, line, sockfd); + + return sockfd; +} + +/* separate function to allow libcurl to mark a "faked" close */ +void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source) +{ + const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? + "FD %s:%d sclose(%d)\n": + (sizeof(curl_socket_t) == sizeof(long)) ? + "FD %s:%d sclose(%ld)\n": + "FD %s:%d sclose(%zd)\n"; + + if(source) + curl_dbg_log(fmt, source, line, sockfd); +} + +/* this is our own defined way to close sockets on *ALL* platforms */ +int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source) +{ + int res = sclose(sockfd); + curl_dbg_mark_sclose(sockfd, line, source); + return res; +} + +FILE *curl_dbg_fopen(const char *file, const char *mode, + int line, const char *source) +{ + FILE *res = fopen(file, mode); + + if(source) + curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", + source, line, file, mode, (void *)res); + + return res; +} + +int curl_dbg_fclose(FILE *file, int line, const char *source) +{ + int res; + + DEBUGASSERT(file != NULL); + + if(source) + curl_dbg_log("FILE %s:%d fclose(%p)\n", + source, line, (void *)file); + + res = fclose(file); + + return res; +} + +#define LOGLINE_BUFSIZE 1024 + +/* this does the writing to the memory tracking log file */ +void curl_dbg_log(const char *format, ...) +{ + char *buf; + int nchars; + va_list ap; + + if(!curl_dbg_logfile) + return; + + buf = (Curl_cmalloc)(LOGLINE_BUFSIZE); + if(!buf) + return; + + va_start(ap, format); + nchars = mvsnprintf(buf, LOGLINE_BUFSIZE, format, ap); + va_end(ap); + + if(nchars > LOGLINE_BUFSIZE - 1) + nchars = LOGLINE_BUFSIZE - 1; + + if(nchars > 0) + fwrite(buf, 1, (size_t)nchars, curl_dbg_logfile); + + (Curl_cfree)(buf); +} + +#endif /* CURLDEBUG */ diff --git a/libcurl/lib/memdebug.h b/libcurl/lib/memdebug.h new file mode 100644 index 0000000..5236f60 --- /dev/null +++ b/libcurl/lib/memdebug.h @@ -0,0 +1,174 @@ +#ifndef HEADER_CURL_MEMDEBUG_H +#define HEADER_CURL_MEMDEBUG_H +#ifdef CURLDEBUG +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * CAUTION: this header is designed to work when included by the app-side + * as well as the library. Do not mix with library internals! + */ + +#define CURL_MT_LOGFNAME_BUFSIZE 512 + +extern FILE *curl_dbg_logfile; + +/* memory functions */ +CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source); +CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line, + const char *source); +CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line, + const char *source); +CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source); +CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src); +#if defined(WIN32) && defined(UNICODE) +CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, + const char *source); +#endif + +CURL_EXTERN void curl_dbg_memdebug(const char *logname); +CURL_EXTERN void curl_dbg_memlimit(long limit); +CURL_EXTERN void curl_dbg_log(const char *format, ...); + +/* file descriptor manipulators */ +CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source); +CURL_EXTERN void curl_dbg_mark_sclose(curl_socket_t sockfd, + int line, const char *source); +CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd, + int line, const char *source); +CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen, + int line, const char *source); +#ifdef HAVE_SOCKETPAIR +CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source); +#endif + +/* send/receive sockets */ +CURL_EXTERN SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, + SEND_TYPE_ARG4 flags, int line, + const char *source); +CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, + RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, + RECV_TYPE_ARG4 flags, int line, + const char *source); + +/* FILE functions */ +CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line, + const char *source); +CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); + +#ifndef MEMDEBUG_NODEFINES + +/* Set this symbol on the command-line, recompile all lib-sources */ +#undef strdup +#define strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +#define malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__) +#define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__) +#define realloc(ptr,size) curl_dbg_realloc(ptr, size, __LINE__, __FILE__) +#define free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__) +#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__) +#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__) + +#ifdef WIN32 +# ifdef UNICODE +# undef wcsdup +# define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# undef _wcsdup +# define _wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# undef _tcsdup +# define _tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# else +# undef _tcsdup +# define _tcsdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +# endif +#endif + +#undef socket +#define socket(domain,type,protocol)\ + curl_dbg_socket(domain, type, protocol, __LINE__, __FILE__) +#undef accept /* for those with accept as a macro */ +#define accept(sock,addr,len)\ + curl_dbg_accept(sock, addr, len, __LINE__, __FILE__) +#ifdef HAVE_SOCKETPAIR +#define socketpair(domain,type,protocol,socket_vector)\ + curl_dbg_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) +#endif + +#ifdef HAVE_GETADDRINFO +#if defined(getaddrinfo) && defined(__osf__) +/* OSF/1 and Tru64 have getaddrinfo as a define already, so we cannot define + our macro as for other platforms. Instead, we redefine the new name they + define getaddrinfo to become! */ +#define ogetaddrinfo(host,serv,hint,res) \ + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) +#else +#undef getaddrinfo +#define getaddrinfo(host,serv,hint,res) \ + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) +#endif +#endif /* HAVE_GETADDRINFO */ + +#ifdef HAVE_FREEADDRINFO +#undef freeaddrinfo +#define freeaddrinfo(data) \ + curl_dbg_freeaddrinfo(data, __LINE__, __FILE__) +#endif /* HAVE_FREEADDRINFO */ + +/* sclose is probably already defined, redefine it! */ +#undef sclose +#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__) + +#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__) + +#undef fopen +#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__) +#undef fdopen +#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__) +#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__) + +#endif /* MEMDEBUG_NODEFINES */ + +#endif /* CURLDEBUG */ + +/* +** Following section applies even when CURLDEBUG is not defined. +*/ + +#ifndef fake_sclose +#define fake_sclose(x) Curl_nop_stmt +#endif + +/* + * Curl_safefree defined as a macro to allow MemoryTracking feature + * to log free() calls at same location where Curl_safefree is used. + * This macro also assigns NULL to given pointer when free'd. + */ + +#define Curl_safefree(ptr) \ + do { free((ptr)); (ptr) = NULL;} WHILE_FALSE + +#endif /* HEADER_CURL_MEMDEBUG_H */ diff --git a/libcurl/lib/mime.c b/libcurl/lib/mime.c new file mode 100644 index 0000000..2135f72 --- /dev/null +++ b/libcurl/lib/mime.c @@ -0,0 +1,1904 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "mime.h" +#include "non-ascii.h" +#include "urldata.h" +#include "sendf.h" + +#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \ + !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP) + +#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) +#include +#endif + +#include "rand.h" +#include "slist.h" +#include "strcase.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef WIN32 +# ifndef R_OK +# define R_OK 4 +# endif +#endif + + +#define READ_ERROR ((size_t) -1) + +/* Encoders. */ +static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part); +static curl_off_t encoder_nop_size(curl_mimepart *part); +static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part); +static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part); +static curl_off_t encoder_base64_size(curl_mimepart *part); +static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part); +static curl_off_t encoder_qp_size(curl_mimepart *part); + +static const mime_encoder encoders[] = { + {"binary", encoder_nop_read, encoder_nop_size}, + {"8bit", encoder_nop_read, encoder_nop_size}, + {"7bit", encoder_7bit_read, encoder_nop_size}, + {"base64", encoder_base64_read, encoder_base64_size}, + {"quoted-printable", encoder_qp_read, encoder_qp_size}, + {ZERO_NULL, ZERO_NULL, ZERO_NULL} +}; + +/* Base64 encoding table */ +static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* Quoted-printable character class table. + * + * We cannot rely on ctype functions since quoted-printable input data + * is assumed to be ascii-compatible, even on non-ascii platforms. */ +#define QP_OK 1 /* Can be represented by itself. */ +#define QP_SP 2 /* Space or tab. */ +#define QP_CR 3 /* Carriage return. */ +#define QP_LF 4 /* Line-feed. */ +static const unsigned char qp_class[] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */ + 0, QP_SP, QP_LF, 0, 0, QP_CR, 0, 0, /* 08 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 17 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 18 - 1F */ + QP_SP, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 20 - 27 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 28 - 2F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 30 - 37 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0 , QP_OK, QP_OK, /* 38 - 3F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 40 - 47 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 48 - 4F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 50 - 57 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 58 - 5F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 60 - 67 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 68 - 6F */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 70 - 77 */ + QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0, /* 78 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */ +}; + + +/* Binary --> hexadecimal ASCII table. */ +static const char aschex[] = + "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x41\x42\x43\x44\x45\x46"; + + + +#ifndef __VMS +#define filesize(name, stat_data) (stat_data.st_size) +#define fopen_read fopen + +#else + +#include +/* + * get_vms_file_size does what it takes to get the real size of the file + * + * For fixed files, find out the size of the EOF block and adjust. + * + * For all others, have to read the entire file in, discarding the contents. + * Most posted text files will be small, and binary files like zlib archives + * and CD/DVD images should be either a STREAM_LF format or a fixed format. + * + */ +curl_off_t VmsRealFileSize(const char *name, + const struct_stat *stat_buf) +{ + char buffer[8192]; + curl_off_t count; + int ret_stat; + FILE * file; + + file = fopen(name, FOPEN_READTEXT); /* VMS */ + if(file == NULL) + return 0; + + count = 0; + ret_stat = 1; + while(ret_stat > 0) { + ret_stat = fread(buffer, 1, sizeof(buffer), file); + if(ret_stat != 0) + count += ret_stat; + } + fclose(file); + + return count; +} + +/* + * + * VmsSpecialSize checks to see if the stat st_size can be trusted and + * if not to call a routine to get the correct size. + * + */ +static curl_off_t VmsSpecialSize(const char *name, + const struct_stat *stat_buf) +{ + switch(stat_buf->st_fab_rfm) { + case FAB$C_VAR: + case FAB$C_VFC: + return VmsRealFileSize(name, stat_buf); + break; + default: + return stat_buf->st_size; + } +} + +#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data) + +/* + * vmsfopenread + * + * For upload to work as expected on VMS, different optional + * parameters must be added to the fopen command based on + * record format of the file. + * + */ +static FILE * vmsfopenread(const char *file, const char *mode) +{ + struct_stat statbuf; + int result; + + result = stat(file, &statbuf); + + switch(statbuf.st_fab_rfm) { + case FAB$C_VAR: + case FAB$C_VFC: + case FAB$C_STMCR: + return fopen(file, FOPEN_READTEXT); /* VMS */ + break; + default: + return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm"); + } +} + +#define fopen_read vmsfopenread +#endif + + +#ifndef HAVE_BASENAME +/* + (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 + Edition) + + The basename() function shall take the pathname pointed to by path and + return a pointer to the final component of the pathname, deleting any + trailing '/' characters. + + If the string pointed to by path consists entirely of the '/' character, + basename() shall return a pointer to the string "/". If the string pointed + to by path is exactly "//", it is implementation-defined whether '/' or "//" + is returned. + + If path is a null pointer or points to an empty string, basename() shall + return a pointer to the string ".". + + The basename() function may modify the string pointed to by path, and may + return a pointer to static storage that may then be overwritten by a + subsequent call to basename(). + + The basename() function need not be reentrant. A function that is not + required to be reentrant is not required to be thread-safe. + +*/ +static char *Curl_basename(char *path) +{ + /* Ignore all the details above for now and make a quick and simple + implementation here */ + char *s1; + char *s2; + + s1 = strrchr(path, '/'); + s2 = strrchr(path, '\\'); + + if(s1 && s2) { + path = (s1 > s2? s1 : s2) + 1; + } + else if(s1) + path = s1 + 1; + else if(s2) + path = s2 + 1; + + return path; +} + +#define basename(x) Curl_basename((x)) +#endif + + +/* Set readback state. */ +static void mimesetstate(mime_state *state, enum mimestate tok, void *ptr) +{ + state->state = tok; + state->ptr = ptr; + state->offset = 0; +} + + +/* Escape header string into allocated memory. */ +static char *escape_string(const char *src) +{ + size_t bytecount = 0; + size_t i; + char *dst; + + for(i = 0; src[i]; i++) + if(src[i] == '"' || src[i] == '\\') + bytecount++; + + bytecount += i; + dst = malloc(bytecount + 1); + if(!dst) + return NULL; + + for(i = 0; *src; src++) { + if(*src == '"' || *src == '\\') + dst[i++] = '\\'; + dst[i++] = *src; + } + + dst[i] = '\0'; + return dst; +} + +/* Check if header matches. */ +static char *match_header(struct curl_slist *hdr, const char *lbl, size_t len) +{ + char *value = NULL; + + if(strncasecompare(hdr->data, lbl, len) && hdr->data[len] == ':') + for(value = hdr->data + len + 1; *value == ' '; value++) + ; + return value; +} + +/* Get a header from an slist. */ +static char *search_header(struct curl_slist *hdrlist, const char *hdr) +{ + size_t len = strlen(hdr); + char *value = NULL; + + for(; !value && hdrlist; hdrlist = hdrlist->next) + value = match_header(hdrlist, hdr, len); + + return value; +} + +static char *strippath(const char *fullfile) +{ + char *filename; + char *base; + filename = strdup(fullfile); /* duplicate since basename() may ruin the + buffer it works on */ + if(!filename) + return NULL; + base = strdup(basename(filename)); + + free(filename); /* free temporary buffer */ + + return base; /* returns an allocated string or NULL ! */ +} + +/* Initialize data encoder state. */ +static void cleanup_encoder_state(mime_encoder_state *p) +{ + p->pos = 0; + p->bufbeg = 0; + p->bufend = 0; +} + + +/* Dummy encoder. This is used for 8bit and binary content encodings. */ +static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part) +{ + mime_encoder_state *st = &part->encstate; + size_t insize = st->bufend - st->bufbeg; + + (void) ateof; + + if(size > insize) + size = insize; + if(size) + memcpy(buffer, st->buf, size); + st->bufbeg += size; + return size; +} + +static curl_off_t encoder_nop_size(curl_mimepart *part) +{ + return part->datasize; +} + + +/* 7bit encoder: the encoder is just a data validity check. */ +static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part) +{ + mime_encoder_state *st = &part->encstate; + size_t cursize = st->bufend - st->bufbeg; + + (void) ateof; + + if(size > cursize) + size = cursize; + + for(cursize = 0; cursize < size; cursize++) { + *buffer = st->buf[st->bufbeg]; + if(*buffer++ & 0x80) + return cursize? cursize: READ_ERROR; + st->bufbeg++; + } + + return cursize; +} + + +/* Base64 content encoder. */ +static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part) +{ + mime_encoder_state *st = &part->encstate; + size_t cursize = 0; + int i; + char *ptr = buffer; + + while(st->bufbeg < st->bufend) { + /* Line full ? */ + if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) { + /* Yes, we need 2 characters for CRLF. */ + if(size < 2) + break; + *ptr++ = '\r'; + *ptr++ = '\n'; + st->pos = 0; + cursize += 2; + size -= 2; + } + + /* Be sure there is enough space and input data for a base64 group. */ + if(size < 4 || st->bufend - st->bufbeg < 3) + break; + + /* Encode three bytes as four characters. */ + i = st->buf[st->bufbeg++] & 0xFF; + i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF); + i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF); + *ptr++ = base64[(i >> 18) & 0x3F]; + *ptr++ = base64[(i >> 12) & 0x3F]; + *ptr++ = base64[(i >> 6) & 0x3F]; + *ptr++ = base64[i & 0x3F]; + cursize += 4; + st->pos += 4; + size -= 4; + } + + /* If at eof, we have to flush the buffered data. */ + if(ateof && size >= 4) { + /* Buffered data size can only be 0, 1 or 2. */ + ptr[2] = ptr[3] = '='; + i = 0; + switch(st->bufend - st->bufbeg) { + case 2: + i = (st->buf[st->bufbeg + 1] & 0xFF) << 8; + /* FALLTHROUGH */ + case 1: + i |= (st->buf[st->bufbeg] & 0xFF) << 16; + ptr[0] = base64[(i >> 18) & 0x3F]; + ptr[1] = base64[(i >> 12) & 0x3F]; + if(++st->bufbeg != st->bufend) { + ptr[2] = base64[(i >> 6) & 0x3F]; + st->bufbeg++; + } + cursize += 4; + st->pos += 4; + break; + } + } + +#ifdef CURL_DOES_CONVERSIONS + /* This is now textual data, Convert character codes. */ + if(part->easy && cursize) { + CURLcode result = Curl_convert_to_network(part->easy, buffer, cursize); + if(result) + return READ_ERROR; + } +#endif + + return cursize; +} + +static curl_off_t encoder_base64_size(curl_mimepart *part) +{ + curl_off_t size = part->datasize; + + if(size <= 0) + return size; /* Unknown size or no data. */ + + /* Compute base64 character count. */ + size = 4 * (1 + (size - 1) / 3); + + /* Effective character count must include CRLFs. */ + return size + 2 * ((size - 1) / MAX_ENCODED_LINE_LENGTH); +} + + +/* Quoted-printable lookahead. + * + * Check if a CRLF or end of data is in input buffer at current position + n. + * Return -1 if more data needed, 1 if CRLF or end of data, else 0. + */ +static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n) +{ + n += st->bufbeg; + if(n >= st->bufend && ateof) + return 1; + if(n + 2 > st->bufend) + return ateof? 0: -1; + if(qp_class[st->buf[n] & 0xFF] == QP_CR && + qp_class[st->buf[n + 1] & 0xFF] == QP_LF) + return 1; + return 0; +} + +/* Quoted-printable encoder. */ +static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, + curl_mimepart *part) +{ + mime_encoder_state *st = &part->encstate; + char *ptr = buffer; + size_t cursize = 0; + int softlinebreak; + char buf[4]; + + /* On all platforms, input is supposed to be ASCII compatible: for this + reason, we use hexadecimal ASCII codes in this function rather than + character constants that can be interpreted as non-ascii on some + platforms. Preserve ASCII encoding on output too. */ + while(st->bufbeg < st->bufend) { + size_t len = 1; + size_t consumed = 1; + int i = st->buf[st->bufbeg]; + buf[0] = (char) i; + buf[1] = aschex[(i >> 4) & 0xF]; + buf[2] = aschex[i & 0xF]; + + switch(qp_class[st->buf[st->bufbeg] & 0xFF]) { + case QP_OK: /* Not a special character. */ + break; + case QP_SP: /* Space or tab. */ + /* Spacing must be escaped if followed by CRLF. */ + switch(qp_lookahead_eol(st, ateof, 1)) { + case -1: /* More input data needed. */ + return cursize; + case 0: /* No encoding needed. */ + break; + default: /* CRLF after space or tab. */ + buf[0] = '\x3D'; /* '=' */ + len = 3; + break; + } + break; + case QP_CR: /* Carriage return. */ + /* If followed by a line-feed, output the CRLF pair. + Else escape it. */ + switch(qp_lookahead_eol(st, ateof, 0)) { + case -1: /* Need more data. */ + return cursize; + case 1: /* CRLF found. */ + buf[len++] = '\x0A'; /* Append '\n'. */ + consumed = 2; + break; + default: /* Not followed by LF: escape. */ + buf[0] = '\x3D'; /* '=' */ + len = 3; + break; + } + break; + default: /* Character must be escaped. */ + buf[0] = '\x3D'; /* '=' */ + len = 3; + break; + } + + /* Be sure the encoded character fits within maximum line length. */ + if(buf[len - 1] != '\x0A') { /* '\n' */ + softlinebreak = st->pos + len > MAX_ENCODED_LINE_LENGTH; + if(!softlinebreak && st->pos + len == MAX_ENCODED_LINE_LENGTH) { + /* We may use the current line only if end of data or followed by + a CRLF. */ + switch(qp_lookahead_eol(st, ateof, consumed)) { + case -1: /* Need more data. */ + return cursize; + break; + case 0: /* Not followed by a CRLF. */ + softlinebreak = 1; + break; + } + } + if(softlinebreak) { + strcpy(buf, "\x3D\x0D\x0A"); /* "=\r\n" */ + len = 3; + consumed = 0; + } + } + + /* If the output buffer would overflow, do not store. */ + if(len > size) + break; + + /* Append to output buffer. */ + memcpy(ptr, buf, len); + cursize += len; + ptr += len; + size -= len; + st->pos += len; + if(buf[len - 1] == '\x0A') /* '\n' */ + st->pos = 0; + st->bufbeg += consumed; + } + + return cursize; +} + +static curl_off_t encoder_qp_size(curl_mimepart *part) +{ + /* Determining the size can only be done by reading the data: unless the + data size is 0, we return it as unknown (-1). */ + return part->datasize? -1: 0; +} + + +/* In-memory data callbacks. */ +/* Argument is a pointer to the mime part. */ +static size_t mime_mem_read(char *buffer, size_t size, size_t nitems, + void *instream) +{ + curl_mimepart *part = (curl_mimepart *) instream; + size_t sz = (size_t) part->datasize - part->state.offset; + (void) size; /* Always 1.*/ + + if(sz > nitems) + sz = nitems; + + if(sz) + memcpy(buffer, (char *) &part->data[part->state.offset], sz); + + part->state.offset += sz; + return sz; +} + +static int mime_mem_seek(void *instream, curl_off_t offset, int whence) +{ + curl_mimepart *part = (curl_mimepart *) instream; + + switch(whence) { + case SEEK_CUR: + offset += part->state.offset; + break; + case SEEK_END: + offset += part->datasize; + break; + } + + if(offset < 0 || offset > part->datasize) + return CURL_SEEKFUNC_FAIL; + + part->state.offset = (size_t) offset; + return CURL_SEEKFUNC_OK; +} + +static void mime_mem_free(void *ptr) +{ + Curl_safefree(((curl_mimepart *) ptr)->data); +} + + +/* Named file callbacks. */ +/* Argument is a pointer to the mime part. */ +static int mime_open_file(curl_mimepart * part) +{ + /* Open a MIMEKIND_FILE part. */ + + if(part->fp) + return 0; + part->fp = fopen_read(part->data, "rb"); + return part->fp? 0: -1; +} + +static size_t mime_file_read(char *buffer, size_t size, size_t nitems, + void *instream) +{ + curl_mimepart *part = (curl_mimepart *) instream; + + if(mime_open_file(part)) + return READ_ERROR; + + return fread(buffer, size, nitems, part->fp); +} + +static int mime_file_seek(void *instream, curl_off_t offset, int whence) +{ + curl_mimepart *part = (curl_mimepart *) instream; + + if(whence == SEEK_SET && !offset && !part->fp) + return CURL_SEEKFUNC_OK; /* Not open: implicitly already at BOF. */ + + if(mime_open_file(part)) + return CURL_SEEKFUNC_FAIL; + + return fseek(part->fp, (long) offset, whence)? + CURL_SEEKFUNC_CANTSEEK: CURL_SEEKFUNC_OK; +} + +static void mime_file_free(void *ptr) +{ + curl_mimepart *part = (curl_mimepart *) ptr; + + if(part->fp) { + fclose(part->fp); + part->fp = NULL; + } + Curl_safefree(part->data); + part->data = NULL; +} + + +/* Subparts callbacks. */ +/* Argument is a pointer to the mime structure. */ + +/* Readback a byte string segment. */ +static size_t readback_bytes(mime_state *state, + char *buffer, size_t bufsize, + const char *bytes, size_t numbytes, + const char *trail) +{ + size_t sz; + + if(numbytes > state->offset) { + sz = numbytes - state->offset; + bytes += state->offset; + } + else { + size_t tsz = strlen(trail); + + sz = state->offset - numbytes; + if(sz >= tsz) + return 0; + bytes = trail + sz; + sz = tsz - sz; + } + + if(sz > bufsize) + sz = bufsize; + + memcpy(buffer, bytes, sz); + state->offset += sz; + return sz; +} + +/* Read a non-encoded part content. */ +static size_t read_part_content(curl_mimepart *part, + char *buffer, size_t bufsize) +{ + size_t sz = 0; + + if(part->readfunc) + sz = part->readfunc(buffer, 1, bufsize, part->arg); + return sz; +} + +/* Read and encode part content. */ +static size_t read_encoded_part_content(curl_mimepart *part, + char *buffer, size_t bufsize) +{ + mime_encoder_state *st = &part->encstate; + size_t cursize = 0; + size_t sz; + bool ateof = FALSE; + + while(bufsize) { + if(st->bufbeg < st->bufend || ateof) { + /* Encode buffered data. */ + sz = part->encoder->encodefunc(buffer, bufsize, ateof, part); + switch(sz) { + case 0: + if(ateof) + return cursize; + break; + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + case READ_ERROR: + return cursize? cursize: sz; + default: + cursize += sz; + buffer += sz; + bufsize -= sz; + continue; + } + } + + /* We need more data in input buffer. */ + if(st->bufbeg) { + size_t len = st->bufend - st->bufbeg; + + if(len) + memmove(st->buf, st->buf + st->bufbeg, len); + st->bufbeg = 0; + st->bufend = len; + } + if(st->bufend >= sizeof(st->buf)) + return cursize? cursize: READ_ERROR; /* Buffer full. */ + sz = read_part_content(part, st->buf + st->bufend, + sizeof(st->buf) - st->bufend); + switch(sz) { + case 0: + ateof = TRUE; + break; + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + case READ_ERROR: + return cursize? cursize: sz; + default: + st->bufend += sz; + break; + } + } + + return cursize; +} + +/* Readback a mime part. */ +static size_t readback_part(curl_mimepart *part, + char *buffer, size_t bufsize) +{ + size_t cursize = 0; +#ifdef CURL_DOES_CONVERSIONS + char *convbuf = buffer; +#endif + + /* Readback from part. */ + + while(bufsize) { + size_t sz = 0; + struct curl_slist *hdr = (struct curl_slist *) part->state.ptr; + switch(part->state.state) { + case MIMESTATE_BEGIN: + mimesetstate(&part->state, + (part->flags & MIME_BODY_ONLY)? + MIMESTATE_BODY: MIMESTATE_CURLHEADERS, + part->curlheaders); + break; + case MIMESTATE_USERHEADERS: + if(!hdr) { + mimesetstate(&part->state, MIMESTATE_EOH, NULL); + break; + } + if(match_header(hdr, "Content-Type", 12)) { + mimesetstate(&part->state, MIMESTATE_USERHEADERS, hdr->next); + break; + } + /* FALLTHROUGH */ + case MIMESTATE_CURLHEADERS: + if(!hdr) + mimesetstate(&part->state, MIMESTATE_USERHEADERS, part->userheaders); + else { + sz = readback_bytes(&part->state, buffer, bufsize, + hdr->data, strlen(hdr->data), "\r\n"); + if(!sz) + mimesetstate(&part->state, part->state.state, hdr->next); + } + break; + case MIMESTATE_EOH: + sz = readback_bytes(&part->state, buffer, bufsize, "\r\n", 2, ""); + if(!sz) + mimesetstate(&part->state, MIMESTATE_BODY, NULL); + break; + case MIMESTATE_BODY: +#ifdef CURL_DOES_CONVERSIONS + if(part->easy && convbuf < buffer) { + CURLcode result = Curl_convert_to_network(part->easy, convbuf, + buffer - convbuf); + if(result) + return READ_ERROR; + convbuf = buffer; + } +#endif + cleanup_encoder_state(&part->encstate); + mimesetstate(&part->state, MIMESTATE_CONTENT, NULL); + break; + case MIMESTATE_CONTENT: + if(part->encoder) + sz = read_encoded_part_content(part, buffer, bufsize); + else + sz = read_part_content(part, buffer, bufsize); + switch(sz) { + case 0: + mimesetstate(&part->state, MIMESTATE_END, NULL); + /* Try sparing open file descriptors. */ + if(part->kind == MIMEKIND_FILE && part->fp) { + fclose(part->fp); + part->fp = NULL; + } + /* FALLTHROUGH */ + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + case READ_ERROR: + return cursize? cursize: sz; + } + break; + case MIMESTATE_END: + return cursize; + default: + break; /* Other values not in part state. */ + } + + /* Bump buffer and counters according to read size. */ + cursize += sz; + buffer += sz; + bufsize -= sz; + } + +#ifdef CURL_DOES_CONVERSIONS + if(part->easy && convbuf < buffer && + part->state.state < MIMESTATE_BODY) { + CURLcode result = Curl_convert_to_network(part->easy, convbuf, + buffer - convbuf); + if(result) + return READ_ERROR; + } +#endif + + return cursize; +} + +/* Readback from mime. */ +static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, + void *instream) +{ + curl_mime *mime = (curl_mime *) instream; + size_t cursize = 0; +#ifdef CURL_DOES_CONVERSIONS + char *convbuf = buffer; +#endif + + (void) size; /* Always 1. */ + + while(nitems) { + size_t sz = 0; + curl_mimepart *part = mime->state.ptr; + switch(mime->state.state) { + case MIMESTATE_BEGIN: + case MIMESTATE_BODY: +#ifdef CURL_DOES_CONVERSIONS + convbuf = buffer; +#endif + mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart); + /* The first boundary always follows the header termination empty line, + so is always preceded by a CRLK. We can then spare 2 characters + by skipping the leading CRLF in boundary. */ + mime->state.offset += 2; + break; + case MIMESTATE_BOUNDARY1: + sz = readback_bytes(&mime->state, buffer, nitems, "\r\n--", 4, ""); + if(!sz) + mimesetstate(&mime->state, MIMESTATE_BOUNDARY2, part); + break; + case MIMESTATE_BOUNDARY2: + sz = readback_bytes(&mime->state, buffer, nitems, mime->boundary, + strlen(mime->boundary), part? "\r\n": "--\r\n"); + if(!sz) { +#ifdef CURL_DOES_CONVERSIONS + if(mime->easy && convbuf < buffer) { + CURLcode result = Curl_convert_to_network(mime->easy, convbuf, + buffer - convbuf); + if(result) + return READ_ERROR; + convbuf = buffer; + } +#endif + mimesetstate(&mime->state, MIMESTATE_CONTENT, part); + } + break; + case MIMESTATE_CONTENT: + if(!part) { + mimesetstate(&mime->state, MIMESTATE_END, NULL); + break; + } + sz = readback_part(part, buffer, nitems); + switch(sz) { + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: + case READ_ERROR: + return cursize? cursize: sz; + case 0: +#ifdef CURL_DOES_CONVERSIONS + convbuf = buffer; +#endif + mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, part->nextpart); + break; + } + break; + case MIMESTATE_END: + return cursize; + default: + break; /* other values not used in mime state. */ + } + + /* Bump buffer and counters according to read size. */ + cursize += sz; + buffer += sz; + nitems -= sz; + } + +#ifdef CURL_DOES_CONVERSIONS + if(mime->easy && convbuf < buffer && + mime->state.state <= MIMESTATE_CONTENT) { + CURLcode result = Curl_convert_to_network(mime->easy, convbuf, + buffer - convbuf); + if(result) + return READ_ERROR; + } +#endif + + return cursize; +} + +static int mime_part_rewind(curl_mimepart *part) +{ + int res = CURL_SEEKFUNC_OK; + enum mimestate targetstate = MIMESTATE_BEGIN; + + if(part->flags & MIME_BODY_ONLY) + targetstate = MIMESTATE_BODY; + cleanup_encoder_state(&part->encstate); + if(part->state.state > targetstate) { + res = CURL_SEEKFUNC_CANTSEEK; + if(part->seekfunc) { + res = part->seekfunc(part->arg, (curl_off_t) 0, SEEK_SET); + switch(res) { + case CURL_SEEKFUNC_OK: + case CURL_SEEKFUNC_FAIL: + case CURL_SEEKFUNC_CANTSEEK: + break; + case -1: /* For fseek() error. */ + res = CURL_SEEKFUNC_CANTSEEK; + break; + default: + res = CURL_SEEKFUNC_FAIL; + break; + } + } + } + + if(res == CURL_SEEKFUNC_OK) + mimesetstate(&part->state, targetstate, NULL); + + return res; +} + +static int mime_subparts_seek(void *instream, curl_off_t offset, int whence) +{ + curl_mime *mime = (curl_mime *) instream; + curl_mimepart *part; + int result = CURL_SEEKFUNC_OK; + + if(whence != SEEK_SET || offset) + return CURL_SEEKFUNC_CANTSEEK; /* Only support full rewind. */ + + if(mime->state.state == MIMESTATE_BEGIN) + return CURL_SEEKFUNC_OK; /* Already rewound. */ + + for(part = mime->firstpart; part; part = part->nextpart) { + int res = mime_part_rewind(part); + if(res != CURL_SEEKFUNC_OK) + result = res; + } + + if(result == CURL_SEEKFUNC_OK) + mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL); + + return result; +} + +/* Release part content. */ +static void cleanup_part_content(curl_mimepart *part) +{ + if(part->freefunc) + part->freefunc(part->arg); + + part->readfunc = NULL; + part->seekfunc = NULL; + part->freefunc = NULL; + part->arg = (void *) part; /* Defaults to part itself. */ + part->data = NULL; + part->fp = NULL; + part->datasize = (curl_off_t) 0; /* No size yet. */ + cleanup_encoder_state(&part->encstate); + part->kind = MIMEKIND_NONE; +} + +static void mime_subparts_free(void *ptr) +{ + curl_mime *mime = (curl_mime *) ptr; + + if(mime && mime->parent) { + mime->parent->freefunc = NULL; /* Be sure we won't be called again. */ + cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */ + } + curl_mime_free(mime); +} + +/* Do not free subparts: unbind them. This is used for the top level only. */ +static void mime_subparts_unbind(void *ptr) +{ + curl_mime *mime = (curl_mime *) ptr; + + if(mime && mime->parent) { + mime->parent->freefunc = NULL; /* Be sure we won't be called again. */ + cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */ + mime->parent = NULL; + } +} + + +void Curl_mime_cleanpart(curl_mimepart *part) +{ + cleanup_part_content(part); + curl_slist_free_all(part->curlheaders); + if(part->flags & MIME_USERHEADERS_OWNER) + curl_slist_free_all(part->userheaders); + Curl_safefree(part->mimetype); + Curl_safefree(part->name); + Curl_safefree(part->filename); + Curl_mime_initpart(part, part->easy); +} + +/* Recursively delete a mime handle and its parts. */ +void curl_mime_free(curl_mime *mime) +{ + curl_mimepart *part; + + if(mime) { + mime_subparts_unbind(mime); /* Be sure it's not referenced anymore. */ + while(mime->firstpart) { + part = mime->firstpart; + mime->firstpart = part->nextpart; + Curl_mime_cleanpart(part); + free(part); + } + free(mime); + } +} + +CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src) +{ + curl_mime *mime; + curl_mimepart *d; + const curl_mimepart *s; + CURLcode res = CURLE_OK; + + /* Duplicate content. */ + switch(src->kind) { + case MIMEKIND_NONE: + break; + case MIMEKIND_DATA: + res = curl_mime_data(dst, src->data, (size_t) src->datasize); + break; + case MIMEKIND_FILE: + res = curl_mime_filedata(dst, src->data); + /* Do not abort duplication if file is not readable. */ + if(res == CURLE_READ_ERROR) + res = CURLE_OK; + break; + case MIMEKIND_CALLBACK: + res = curl_mime_data_cb(dst, src->datasize, src->readfunc, + src->seekfunc, src->freefunc, src->arg); + break; + case MIMEKIND_MULTIPART: + /* No one knows about the cloned subparts, thus always attach ownership + to the part. */ + mime = curl_mime_init(dst->easy); + res = mime? curl_mime_subparts(dst, mime): CURLE_OUT_OF_MEMORY; + + /* Duplicate subparts. */ + for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) { + d = curl_mime_addpart(mime); + res = d? Curl_mime_duppart(d, s): CURLE_OUT_OF_MEMORY; + } + break; + default: /* Invalid kind: should not occur. */ + res = CURLE_BAD_FUNCTION_ARGUMENT; /* Internal error? */ + break; + } + + /* Duplicate headers. */ + if(!res && src->userheaders) { + struct curl_slist *hdrs = Curl_slist_duplicate(src->userheaders); + + if(!hdrs) + res = CURLE_OUT_OF_MEMORY; + else { + /* No one but this procedure knows about the new header list, + so always take ownership. */ + res = curl_mime_headers(dst, hdrs, TRUE); + if(res) + curl_slist_free_all(hdrs); + } + } + + /* Duplicate other fields. */ + if(dst != NULL) + dst->encoder = src->encoder; + else + res = CURLE_WRITE_ERROR; + if(!res) + res = curl_mime_type(dst, src->mimetype); + if(!res) + res = curl_mime_name(dst, src->name); + if(!res) + res = curl_mime_filename(dst, src->filename); + + /* If an error occurred, rollback. */ + if(res && dst) + Curl_mime_cleanpart(dst); + + return res; +} + +/* + * Mime build functions. + */ + +/* Create a mime handle. */ +curl_mime *curl_mime_init(struct Curl_easy *easy) +{ + curl_mime *mime; + + mime = (curl_mime *) malloc(sizeof(*mime)); + + if(mime) { + mime->easy = easy; + mime->parent = NULL; + mime->firstpart = NULL; + mime->lastpart = NULL; + + memset(mime->boundary, '-', 24); + if(Curl_rand_hex(easy, (unsigned char *) &mime->boundary[24], + MIME_RAND_BOUNDARY_CHARS + 1)) { + /* failed to get random separator, bail out */ + free(mime); + return NULL; + } + mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL); + } + + return mime; +} + +/* Initialize a mime part. */ +void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy) +{ + memset((char *) part, 0, sizeof(*part)); + part->easy = easy; + mimesetstate(&part->state, MIMESTATE_BEGIN, NULL); +} + +/* Create a mime part and append it to a mime handle's part list. */ +curl_mimepart *curl_mime_addpart(curl_mime *mime) +{ + curl_mimepart *part; + + if(!mime) + return NULL; + + part = (curl_mimepart *) malloc(sizeof(*part)); + + if(part) { + Curl_mime_initpart(part, mime->easy); + part->parent = mime; + + if(mime->lastpart) + mime->lastpart->nextpart = part; + else + mime->firstpart = part; + + mime->lastpart = part; + } + + return part; +} + +/* Set mime part name. */ +CURLcode curl_mime_name(curl_mimepart *part, const char *name) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + Curl_safefree(part->name); + part->name = NULL; + + if(name) { + part->name = strdup(name); + if(!part->name) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +/* Set mime part remote file name. */ +CURLcode curl_mime_filename(curl_mimepart *part, const char *filename) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + Curl_safefree(part->filename); + part->filename = NULL; + + if(filename) { + part->filename = strdup(filename); + if(!part->filename) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +/* Set mime part content from memory data. */ +CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + cleanup_part_content(part); + + if(data) { + if(datasize == CURL_ZERO_TERMINATED) + datasize = strlen(data); + + part->data = malloc(datasize + 1); + if(!part->data) + return CURLE_OUT_OF_MEMORY; + + part->datasize = datasize; + + if(datasize) + memcpy(part->data, data, datasize); + part->data[datasize] = '\0'; /* Set a nul terminator as sentinel. */ + + part->readfunc = mime_mem_read; + part->seekfunc = mime_mem_seek; + part->freefunc = mime_mem_free; + part->kind = MIMEKIND_DATA; + } + + return CURLE_OK; +} + +/* Set mime part content from named local file. */ +CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) +{ + CURLcode result = CURLE_OK; + + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + cleanup_part_content(part); + + if(filename) { + char *base; + struct_stat sbuf; + + if(stat(filename, &sbuf) || access(filename, R_OK)) + result = CURLE_READ_ERROR; + + part->data = strdup(filename); + if(!part->data) + result = CURLE_OUT_OF_MEMORY; + + part->datasize = -1; + if(!result && S_ISREG(sbuf.st_mode)) { + part->datasize = filesize(filename, sbuf); + part->seekfunc = mime_file_seek; + } + + part->readfunc = mime_file_read; + part->freefunc = mime_file_free; + part->kind = MIMEKIND_FILE; + + /* As a side effect, set the filename to the current file's base name. + It is possible to withdraw this by explicitly calling + curl_mime_filename() with a NULL filename argument after the current + call. */ + base = strippath(filename); + if(!base) + result = CURLE_OUT_OF_MEMORY; + else { + CURLcode res = curl_mime_filename(part, base); + + if(res) + result = res; + free(base); + } + } + return result; +} + +/* Set mime part type. */ +CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + Curl_safefree(part->mimetype); + part->mimetype = NULL; + + if(mimetype) { + part->mimetype = strdup(mimetype); + if(!part->mimetype) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +/* Set mime data transfer encoder. */ +CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + const mime_encoder *mep; + + if(!part) + return result; + + part->encoder = NULL; + + if(!encoding) + return CURLE_OK; /* Removing current encoder. */ + + for(mep = encoders; mep->name; mep++) + if(strcasecompare(encoding, mep->name)) { + part->encoder = mep; + result = CURLE_OK; + } + + return result; +} + +/* Set mime part headers. */ +CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, int take_ownership) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(part->flags & MIME_USERHEADERS_OWNER) { + if(part->userheaders != headers) /* Allow setting twice the same list. */ + curl_slist_free_all(part->userheaders); + part->flags &= ~MIME_USERHEADERS_OWNER; + } + part->userheaders = headers; + if(headers && take_ownership) + part->flags |= MIME_USERHEADERS_OWNER; + return CURLE_OK; +} + +/* Set mime part content from callback. */ +CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, void *arg) +{ + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + cleanup_part_content(part); + + if(readfunc) { + part->readfunc = readfunc; + part->seekfunc = seekfunc; + part->freefunc = freefunc; + part->arg = arg; + part->datasize = datasize; + part->kind = MIMEKIND_CALLBACK; + } + + return CURLE_OK; +} + +/* Set mime part content from subparts. */ +CURLcode Curl_mime_set_subparts(curl_mimepart *part, + curl_mime *subparts, int take_ownership) +{ + curl_mime *root; + + if(!part) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* Accept setting twice the same subparts. */ + if(part->kind == MIMEKIND_MULTIPART && part->arg == subparts) + return CURLE_OK; + + cleanup_part_content(part); + + if(subparts) { + /* Must belong to the same data handle. */ + if(part->easy && subparts->easy && part->easy != subparts->easy) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* Should not have been attached already. */ + if(subparts->parent) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* Should not be the part's root. */ + root = part->parent; + if(root) { + while(root->parent && root->parent->parent) + root = root->parent->parent; + if(subparts == root) { + if(part->easy) + failf(part->easy, "Can't add itself as a subpart!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + + subparts->parent = part; + part->readfunc = mime_subparts_read; + part->seekfunc = mime_subparts_seek; + part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind; + part->arg = subparts; + part->datasize = -1; + part->kind = MIMEKIND_MULTIPART; + } + + return CURLE_OK; +} + +CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) +{ + return Curl_mime_set_subparts(part, subparts, TRUE); +} + + +/* Readback from top mime. */ +/* Argument is the dummy top part. */ +size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream) +{ + curl_mimepart *part = (curl_mimepart *) instream; + + (void) size; /* Always 1. */ + return readback_part(part, buffer, nitems); +} + +/* Rewind mime stream. */ +CURLcode Curl_mime_rewind(curl_mimepart *part) +{ + return mime_part_rewind(part) == CURL_SEEKFUNC_OK? + CURLE_OK: CURLE_SEND_FAIL_REWIND; +} + +/* Compute header list size. */ +static size_t slist_size(struct curl_slist *s, + size_t overhead, const char *skip) +{ + size_t size = 0; + size_t skiplen = skip? strlen(skip): 0; + + for(; s; s = s->next) + if(!skip || !match_header(s, skip, skiplen)) + size += strlen(s->data) + overhead; + return size; +} + +/* Get/compute multipart size. */ +static curl_off_t multipart_size(curl_mime *mime) +{ + curl_off_t size; + size_t boundarysize; + curl_mimepart *part; + + if(!mime) + return 0; /* Not present -> empty. */ + + boundarysize = 4 + strlen(mime->boundary) + 2; + size = boundarysize; /* Final boundary - CRLF after headers. */ + + for(part = mime->firstpart; part; part = part->nextpart) { + curl_off_t sz = Curl_mime_size(part); + + if(sz < 0) + size = sz; + + if(size >= 0) + size += boundarysize + sz; + } + + return size; +} + +/* Get/compute mime size. */ +curl_off_t Curl_mime_size(curl_mimepart *part) +{ + curl_off_t size; + + if(part->kind == MIMEKIND_MULTIPART) + part->datasize = multipart_size(part->arg); + + size = part->datasize; + + if(part->encoder) + size = part->encoder->sizefunc(part); + + if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) { + /* Compute total part size. */ + size += slist_size(part->curlheaders, 2, NULL); + size += slist_size(part->userheaders, 2, "Content-Type"); + size += 2; /* CRLF after headers. */ + } + return size; +} + +/* Add a header. */ +/* VARARGS2 */ +CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...) +{ + struct curl_slist *hdr = NULL; + char *s = NULL; + va_list ap; + + va_start(ap, fmt); + s = curl_mvaprintf(fmt, ap); + va_end(ap); + + if(s) { + hdr = Curl_slist_append_nodup(*slp, s); + if(hdr) + *slp = hdr; + else + free(s); + } + + return hdr? CURLE_OK: CURLE_OUT_OF_MEMORY; +} + +/* Add a content type header. */ +static CURLcode add_content_type(struct curl_slist **slp, + const char *type, const char *boundary) +{ + return Curl_mime_add_header(slp, "Content-Type: %s%s%s", type, + boundary? "; boundary=": "", + boundary? boundary: ""); +} + +const char *Curl_mime_contenttype(const char *filename) +{ + /* + * If no content type was specified, we scan through a few well-known + * extensions and pick the first we match! + */ + struct ContentType { + const char *extension; + const char *type; + }; + static const struct ContentType ctts[] = { + {".gif", "image/gif"}, + {".jpg", "image/jpeg"}, + {".jpeg", "image/jpeg"}, + {".png", "image/png"}, + {".svg", "image/svg+xml"}, + {".txt", "text/plain"}, + {".htm", "text/html"}, + {".html", "text/html"}, + {".pdf", "application/pdf"}, + {".xml", "application/xml"} + }; + + if(filename) { + size_t len1 = strlen(filename); + const char *nameend = filename + len1; + unsigned int i; + + for(i = 0; i < sizeof(ctts) / sizeof(ctts[0]); i++) { + size_t len2 = strlen(ctts[i].extension); + + if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension)) + return ctts[i].type; + } + } + return NULL; +} + +CURLcode Curl_mime_prepare_headers(curl_mimepart *part, + const char *contenttype, + const char *disposition, + enum mimestrategy strategy) +{ + curl_mime *mime = NULL; + const char *boundary = NULL; + char *customct; + const char *cte = NULL; + CURLcode ret = CURLE_OK; + + /* Get rid of previously prepared headers. */ + curl_slist_free_all(part->curlheaders); + part->curlheaders = NULL; + + /* Be sure we won't access old headers later. */ + if(part->state.state == MIMESTATE_CURLHEADERS) + mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL); + + /* Check if content type is specified. */ + customct = part->mimetype; + if(!customct) + customct = search_header(part->userheaders, "Content-Type"); + if(customct) + contenttype = customct; + + /* If content type is not specified, try to determine it. */ + if(!contenttype) { + switch(part->kind) { + case MIMEKIND_MULTIPART: + contenttype = MULTIPART_CONTENTTYPE_DEFAULT; + break; + case MIMEKIND_FILE: + contenttype = Curl_mime_contenttype(part->filename); + if(!contenttype) + contenttype = Curl_mime_contenttype(part->data); + if(!contenttype && part->filename) + contenttype = FILE_CONTENTTYPE_DEFAULT; + break; + default: + contenttype = Curl_mime_contenttype(part->filename); + break; + } + } + + if(part->kind == MIMEKIND_MULTIPART) { + mime = (curl_mime *) part->arg; + if(mime) + boundary = mime->boundary; + } + else if(contenttype && !customct && + strcasecompare(contenttype, "text/plain")) + if(strategy == MIMESTRATEGY_MAIL || !part->filename) + contenttype = NULL; + + /* Issue content-disposition header only if not already set by caller. */ + if(!search_header(part->userheaders, "Content-Disposition")) { + if(!disposition) + if(part->filename || part->name || + (contenttype && !strncasecompare(contenttype, "multipart/", 10))) + disposition = DISPOSITION_DEFAULT; + if(disposition && curl_strequal(disposition, "attachment") && + !part->name && !part->filename) + disposition = NULL; + if(disposition) { + char *name = NULL; + char *filename = NULL; + + if(part->name) { + name = escape_string(part->name); + if(!name) + ret = CURLE_OUT_OF_MEMORY; + } + if(!ret && part->filename) { + filename = escape_string(part->filename); + if(!filename) + ret = CURLE_OUT_OF_MEMORY; + } + if(!ret) + ret = Curl_mime_add_header(&part->curlheaders, + "Content-Disposition: %s%s%s%s%s%s%s", + disposition, + name? "; name=\"": "", + name? name: "", + name? "\"": "", + filename? "; filename=\"": "", + filename? filename: "", + filename? "\"": ""); + Curl_safefree(name); + Curl_safefree(filename); + if(ret) + return ret; + } + } + + /* Issue Content-Type header. */ + if(contenttype) { + ret = add_content_type(&part->curlheaders, contenttype, boundary); + if(ret) + return ret; + } + + /* Content-Transfer-Encoding header. */ + if(!search_header(part->userheaders, "Content-Transfer-Encoding")) { + if(part->encoder) + cte = part->encoder->name; + else if(contenttype && strategy == MIMESTRATEGY_MAIL && + part->kind != MIMEKIND_MULTIPART) + cte = "8bit"; + if(cte) { + ret = Curl_mime_add_header(&part->curlheaders, + "Content-Transfer-Encoding: %s", cte); + if(ret) + return ret; + } + } + + /* If we were reading curl-generated headers, restart with new ones (this + should not occur). */ + if(part->state.state == MIMESTATE_CURLHEADERS) + mimesetstate(&part->state, MIMESTATE_CURLHEADERS, part->curlheaders); + + /* Process subparts. */ + if(part->kind == MIMEKIND_MULTIPART && mime) { + curl_mimepart *subpart; + + disposition = NULL; + if(strcasecompare(contenttype, "multipart/form-data")) + disposition = "form-data"; + for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) { + ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy); + if(ret) + return ret; + } + } + return ret; +} + +#else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */ + +/* Mime not compiled in: define stubs for externally-referenced functions. */ +curl_mime *curl_mime_init(CURL *easy) +{ + (void) easy; + return NULL; +} + +void curl_mime_free(curl_mime *mime) +{ + (void) mime; +} + +curl_mimepart *curl_mime_addpart(curl_mime *mime) +{ + (void) mime; + return NULL; +} + +CURLcode curl_mime_name(curl_mimepart *part, const char *name) +{ + (void) part; + (void) name; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_filename(curl_mimepart *part, const char *filename) +{ + (void) part; + (void) filename; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype) +{ + (void) part; + (void) mimetype; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding) +{ + (void) part; + (void) encoding; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize) +{ + (void) part; + (void) data; + (void) datasize; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) +{ + (void) part; + (void) filename; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg) +{ + (void) part; + (void) datasize; + (void) readfunc; + (void) seekfunc; + (void) freefunc; + (void) arg; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) +{ + (void) part; + (void) subparts; + return CURLE_NOT_BUILT_IN; +} + +CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, int take_ownership) +{ + (void) part; + (void) headers; + (void) take_ownership; + return CURLE_NOT_BUILT_IN; +} + +#endif /* if disabled */ diff --git a/libcurl/lib/mime.h b/libcurl/lib/mime.h new file mode 100644 index 0000000..4c9a5fb --- /dev/null +++ b/libcurl/lib/mime.h @@ -0,0 +1,164 @@ +#ifndef HEADER_CURL_MIME_H +#define HEADER_CURL_MIME_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#define MIME_RAND_BOUNDARY_CHARS 16 /* Nb. of random boundary chars. */ +#define MAX_ENCODED_LINE_LENGTH 76 /* Maximum encoded line length. */ +#define ENCODING_BUFFER_SIZE 256 /* Encoding temp buffers size. */ + +/* Part flags. */ +#define MIME_USERHEADERS_OWNER (1 << 0) +#define MIME_BODY_ONLY (1 << 1) + +#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream" +#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed" +#define DISPOSITION_DEFAULT "attachment" + +/* Part source kinds. */ +enum mimekind { + MIMEKIND_NONE = 0, /* Part not set. */ + MIMEKIND_DATA, /* Allocated mime data. */ + MIMEKIND_FILE, /* Data from file. */ + MIMEKIND_CALLBACK, /* Data from `read' callback. */ + MIMEKIND_MULTIPART, /* Data is a mime subpart. */ + MIMEKIND_LAST +}; + +/* Readback state tokens. */ +enum mimestate { + MIMESTATE_BEGIN, /* Readback has not yet started. */ + MIMESTATE_CURLHEADERS, /* In curl-generated headers. */ + MIMESTATE_USERHEADERS, /* In caller's supplied headers. */ + MIMESTATE_EOH, /* End of headers. */ + MIMESTATE_BODY, /* Placeholder. */ + MIMESTATE_BOUNDARY1, /* In boundary prefix. */ + MIMESTATE_BOUNDARY2, /* In boundary. */ + MIMESTATE_CONTENT, /* In content. */ + MIMESTATE_END, /* End of part reached. */ + MIMESTATE_LAST +}; + +/* Mime headers strategies. */ +enum mimestrategy { + MIMESTRATEGY_MAIL, /* Mime mail. */ + MIMESTRATEGY_FORM, /* HTTP post form. */ + MIMESTRATEGY_LAST +}; + +/* Content transfer encoder. */ +typedef struct { + const char * name; /* Encoding name. */ + size_t (*encodefunc)(char *buffer, size_t size, bool ateof, + curl_mimepart *part); /* Encoded read. */ + curl_off_t (*sizefunc)(curl_mimepart *part); /* Encoded size. */ +} mime_encoder; + +/* Content transfer encoder state. */ +typedef struct { + size_t pos; /* Position on output line. */ + size_t bufbeg; /* Next data index in input buffer. */ + size_t bufend; /* First unused byte index in input buffer. */ + char buf[ENCODING_BUFFER_SIZE]; /* Input buffer. */ +} mime_encoder_state; + +/* Mime readback state. */ +typedef struct { + enum mimestate state; /* Current state token. */ + void *ptr; /* State-dependent pointer. */ + size_t offset; /* State-dependent offset. */ +} mime_state; + +/* minimum buffer size for the boundary string */ +#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1) + +/* A mime multipart. */ +struct curl_mime_s { + struct Curl_easy *easy; /* The associated easy handle. */ + curl_mimepart *parent; /* Parent part. */ + curl_mimepart *firstpart; /* First part. */ + curl_mimepart *lastpart; /* Last part. */ + char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */ + mime_state state; /* Current readback state. */ +}; + +/* A mime part. */ +struct curl_mimepart_s { + struct Curl_easy *easy; /* The associated easy handle. */ + curl_mime *parent; /* Parent mime structure. */ + curl_mimepart *nextpart; /* Forward linked list. */ + enum mimekind kind; /* The part kind. */ + char *data; /* Memory data or file name. */ + curl_read_callback readfunc; /* Read function. */ + curl_seek_callback seekfunc; /* Seek function. */ + curl_free_callback freefunc; /* Argument free function. */ + void *arg; /* Argument to callback functions. */ + FILE *fp; /* File pointer. */ + struct curl_slist *curlheaders; /* Part headers. */ + struct curl_slist *userheaders; /* Part headers. */ + char *mimetype; /* Part mime type. */ + char *filename; /* Remote file name. */ + char *name; /* Data name. */ + curl_off_t datasize; /* Expected data size. */ + unsigned int flags; /* Flags. */ + mime_state state; /* Current readback state. */ + const mime_encoder *encoder; /* Content data encoder. */ + mime_encoder_state encstate; /* Data encoder state. */ +}; + +#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \ + !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP) + +/* Prototypes. */ +void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy); +void Curl_mime_cleanpart(curl_mimepart *part); +CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src); +CURLcode Curl_mime_set_subparts(curl_mimepart *part, + curl_mime *subparts, int take_ownership); +CURLcode Curl_mime_prepare_headers(curl_mimepart *part, + const char *contenttype, + const char *disposition, + enum mimestrategy strategy); +curl_off_t Curl_mime_size(curl_mimepart *part); +size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, + void *instream); +CURLcode Curl_mime_rewind(curl_mimepart *part); +CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...); +const char *Curl_mime_contenttype(const char *filename); + +#else +/* if disabled */ +#define Curl_mime_initpart(x,y) +#define Curl_mime_cleanpart(x) +#define Curl_mime_duppart(x,y) CURLE_OK /* Nothing to duplicate. Succeed */ +#define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN +#define Curl_mime_prepare_headers(a,b,c,d) CURLE_NOT_BUILT_IN +#define Curl_mime_size(x) (curl_off_t) -1 +#define Curl_mime_read NULL +#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_mime_add_header(x,y,...) CURLE_NOT_BUILT_IN +#endif + + +#endif /* HEADER_CURL_MIME_H */ diff --git a/libcurl/lib/mk-ca-bundle.pl b/libcurl/lib/mk-ca-bundle.pl new file mode 100644 index 0000000..33977f3 --- /dev/null +++ b/libcurl/lib/mk-ca-bundle.pl @@ -0,0 +1,558 @@ +#!/usr/bin/env perl +# *************************************************************************** +# * _ _ ____ _ +# * Project ___| | | | _ \| | +# * / __| | | | |_) | | +# * | (__| |_| | _ <| |___ +# * \___|\___/|_| \_\_____| +# * +# * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. +# * +# * This software is licensed as described in the file COPYING, which +# * you should have received as part of this distribution. The terms +# * are also available at https://curl.haxx.se/docs/copyright.html. +# * +# * You may opt to use, copy, modify, merge, publish, distribute and/or sell +# * copies of the Software, and permit persons to whom the Software is +# * furnished to do so, under the terms of the COPYING file. +# * +# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# * KIND, either express or implied. +# * +# *************************************************************************** +# This Perl script creates a fresh ca-bundle.crt file for use with libcurl. +# It downloads certdata.txt from Mozilla's source tree (see URL below), +# then parses certdata.txt and extracts CA Root Certificates into PEM format. +# These are then processed with the OpenSSL commandline tool to produce the +# final ca-bundle.crt file. +# The script is based on the parse-certs script written by Roland Krikava. +# This Perl script works on almost any platform since its only external +# dependency is the OpenSSL commandline tool for optional text listing. +# Hacked by Guenter Knauf. +# +use Encode; +use Getopt::Std; +use MIME::Base64; +use strict; +use warnings; +use vars qw($opt_b $opt_d $opt_f $opt_h $opt_i $opt_k $opt_l $opt_m $opt_n $opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w); +use List::Util; +use Text::Wrap; +my $MOD_SHA = "Digest::SHA"; +eval "require $MOD_SHA"; +if ($@) { + $MOD_SHA = "Digest::SHA::PurePerl"; + eval "require $MOD_SHA"; +} +eval "require LWP::UserAgent"; + +my %urls = ( + 'nss' => + 'https://hg.mozilla.org/projects/nss/raw-file/default/lib/ckfw/builtins/certdata.txt', + 'central' => + 'https://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', + 'beta' => + 'https://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', + 'release' => + 'https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', +); + +$opt_d = 'release'; + +# If the OpenSSL commandline is not in search path you can configure it here! +my $openssl = 'openssl'; + +my $version = '1.27'; + +$opt_w = 76; # default base64 encoded lines length + +# default cert types to include in the output (default is to include CAs which may issue SSL server certs) +my $default_mozilla_trust_purposes = "SERVER_AUTH"; +my $default_mozilla_trust_levels = "TRUSTED_DELEGATOR"; +$opt_p = $default_mozilla_trust_purposes . ":" . $default_mozilla_trust_levels; + +my @valid_mozilla_trust_purposes = ( + "DIGITAL_SIGNATURE", + "NON_REPUDIATION", + "KEY_ENCIPHERMENT", + "DATA_ENCIPHERMENT", + "KEY_AGREEMENT", + "KEY_CERT_SIGN", + "CRL_SIGN", + "SERVER_AUTH", + "CLIENT_AUTH", + "CODE_SIGNING", + "EMAIL_PROTECTION", + "IPSEC_END_SYSTEM", + "IPSEC_TUNNEL", + "IPSEC_USER", + "TIME_STAMPING", + "STEP_UP_APPROVED" +); + +my @valid_mozilla_trust_levels = ( + "TRUSTED_DELEGATOR", # CAs + "NOT_TRUSTED", # Don't trust these certs. + "MUST_VERIFY_TRUST", # This explicitly tells us that it ISN'T a CA but is otherwise ok. In other words, this should tell the app to ignore any other sources that claim this is a CA. + "TRUSTED" # This cert is trusted, but only for itself and not for delegates (i.e. it is not a CA). +); + +my $default_signature_algorithms = $opt_s = "MD5"; + +my @valid_signature_algorithms = ( + "MD5", + "SHA1", + "SHA256", + "SHA384", + "SHA512" +); + +$0 =~ s@.*(/|\\)@@; +$Getopt::Std::STANDARD_HELP_VERSION = 1; +getopts('bd:fhiklmnp:qs:tuvw:'); + +if(!defined($opt_d)) { + # to make plain "-d" use not cause warnings, and actually still work + $opt_d = 'release'; +} + +# Use predefined URL or else custom URL specified on command line. +my $url; +if(defined($urls{$opt_d})) { + $url = $urls{$opt_d}; + if(!$opt_k && $url !~ /^https:\/\//i) { + die "The URL for '$opt_d' is not HTTPS. Use -k to override (insecure).\n"; + } +} +else { + $url = $opt_d; +} + +my $curl = `curl -V`; + +if ($opt_i) { + print ("=" x 78 . "\n"); + print "Script Version : $version\n"; + print "Perl Version : $]\n"; + print "Operating System Name : $^O\n"; + print "Getopt::Std.pm Version : ${Getopt::Std::VERSION}\n"; + print "Encode::Encoding.pm Version : ${Encode::Encoding::VERSION}\n"; + print "MIME::Base64.pm Version : ${MIME::Base64::VERSION}\n"; + print "LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION}\n" if($LWP::UserAgent::VERSION); + print "LWP.pm Version : ${LWP::VERSION}\n" if($LWP::VERSION); + print "Digest::SHA.pm Version : ${Digest::SHA::VERSION}\n" if ($Digest::SHA::VERSION); + print "Digest::SHA::PurePerl.pm Version : ${Digest::SHA::PurePerl::VERSION}\n" if ($Digest::SHA::PurePerl::VERSION); + print ("=" x 78 . "\n"); +} + +sub warning_message() { + if ( $opt_d =~ m/^risk$/i ) { # Long Form Warning and Exit + print "Warning: Use of this script may pose some risk:\n"; + print "\n"; + print " 1) If you use HTTP URLs they are subject to a man in the middle attack\n"; + print " 2) Default to 'release', but more recent updates may be found in other trees\n"; + print " 3) certdata.txt file format may change, lag time to update this script\n"; + print " 4) Generally unwise to blindly trust CAs without manual review & verification\n"; + print " 5) Mozilla apps use additional security checks aren't represented in certdata\n"; + print " 6) Use of this script will make a security engineer grind his teeth and\n"; + print " swear at you. ;)\n"; + exit; + } else { # Short Form Warning + print "Warning: Use of this script may pose some risk, -d risk for more details.\n"; + } +} + +sub HELP_MESSAGE() { + print "Usage:\t${0} [-b] [-d] [-f] [-i] [-k] [-l] [-n] [-p] [-q] [-s] [-t] [-u] [-v] [-w] []\n"; + print "\t-b\tbackup an existing version of ca-bundle.crt\n"; + print "\t-d\tspecify Mozilla tree to pull certdata.txt or custom URL\n"; + print "\t\t Valid names are:\n"; + print "\t\t ", join( ", ", map { ( $_ =~ m/$opt_d/ ) ? "$_ (default)" : "$_" } sort keys %urls ), "\n"; + print "\t-f\tforce rebuild even if certdata.txt is current\n"; + print "\t-i\tprint version info about used modules\n"; + print "\t-k\tallow URLs other than HTTPS, enable HTTP fallback (insecure)\n"; + print "\t-l\tprint license info about certdata.txt\n"; + print "\t-m\tinclude meta data in output\n"; + print "\t-n\tno download of certdata.txt (to use existing)\n"; + print wrap("\t","\t\t", "-p\tlist of Mozilla trust purposes and levels for certificates to include in output. Takes the form of a comma separated list of purposes, a colon, and a comma separated list of levels. (default: $default_mozilla_trust_purposes:$default_mozilla_trust_levels)"), "\n"; + print "\t\t Valid purposes are:\n"; + print wrap("\t\t ","\t\t ", join( ", ", "ALL", @valid_mozilla_trust_purposes ) ), "\n"; + print "\t\t Valid levels are:\n"; + print wrap("\t\t ","\t\t ", join( ", ", "ALL", @valid_mozilla_trust_levels ) ), "\n"; + print "\t-q\tbe really quiet (no progress output at all)\n"; + print wrap("\t","\t\t", "-s\tcomma separated list of certificate signatures/hashes to output in plain text mode. (default: $default_signature_algorithms)\n"); + print "\t\t Valid signature algorithms are:\n"; + print wrap("\t\t ","\t\t ", join( ", ", "ALL", @valid_signature_algorithms ) ), "\n"; + print "\t-t\tinclude plain text listing of certificates\n"; + print "\t-u\tunlink (remove) certdata.txt after processing\n"; + print "\t-v\tbe verbose and print out processed CAs\n"; + print "\t-w \twrap base64 output lines after chars (default: ${opt_w})\n"; + exit; +} + +sub VERSION_MESSAGE() { + print "${0} version ${version} running Perl ${]} on ${^O}\n"; +} + +warning_message() unless ($opt_q || $url =~ m/^(ht|f)tps:/i ); +HELP_MESSAGE() if ($opt_h); + +sub report($@) { + my $output = shift; + + print STDERR $output . "\n" unless $opt_q; +} + +sub is_in_list($@) { + my $target = shift; + + return defined(List::Util::first { $target eq $_ } @_); +} + +# Parses $param_string as a case insensitive comma separated list with optional whitespace +# validates that only allowed parameters are supplied +sub parse_csv_param($$@) { + my $description = shift; + my $param_string = shift; + my @valid_values = @_; + + my @values = map { + s/^\s+//; # strip leading spaces + s/\s+$//; # strip trailing spaces + uc $_ # return the modified string as upper case + } split( ',', $param_string ); + + # Find all values which are not in the list of valid values or "ALL" + my @invalid = grep { !is_in_list($_,"ALL",@valid_values) } @values; + + if ( scalar(@invalid) > 0 ) { + # Tell the user which parameters were invalid and print the standard help message which will exit + print "Error: Invalid ", $description, scalar(@invalid) == 1 ? ": " : "s: ", join( ", ", map { "\"$_\"" } @invalid ), "\n"; + HELP_MESSAGE(); + } + + @values = @valid_values if ( is_in_list("ALL",@values) ); + + return @values; +} + +sub sha256 { + my $result; + if ($Digest::SHA::VERSION || $Digest::SHA::PurePerl::VERSION) { + open(FILE, $_[0]) or die "Can't open '$_[0]': $!"; + binmode(FILE); + $result = $MOD_SHA->new(256)->addfile(*FILE)->hexdigest; + close(FILE); + } else { + # Use OpenSSL command if Perl Digest::SHA modules not available + $result = `"$openssl" dgst -r -sha256 "$_[0]"`; + $result =~ s/^([0-9a-f]{64}) .+/$1/is; + } + return $result; +} + + +sub oldhash { + my $hash = ""; + open(C, "<$_[0]") || return 0; + while() { + chomp; + if($_ =~ /^\#\# SHA256: (.*)/) { + $hash = $1; + last; + } + } + close(C); + return $hash; +} + +if ( $opt_p !~ m/:/ ) { + print "Error: Mozilla trust identifier list must include both purposes and levels\n"; + HELP_MESSAGE(); +} + +(my $included_mozilla_trust_purposes_string, my $included_mozilla_trust_levels_string) = split( ':', $opt_p ); +my @included_mozilla_trust_purposes = parse_csv_param( "trust purpose", $included_mozilla_trust_purposes_string, @valid_mozilla_trust_purposes ); +my @included_mozilla_trust_levels = parse_csv_param( "trust level", $included_mozilla_trust_levels_string, @valid_mozilla_trust_levels ); + +my @included_signature_algorithms = parse_csv_param( "signature algorithm", $opt_s, @valid_signature_algorithms ); + +sub should_output_cert(%) { + my %trust_purposes_by_level = @_; + + foreach my $level (@included_mozilla_trust_levels) { + # for each level we want to output, see if any of our desired purposes are included + return 1 if ( defined( List::Util::first { is_in_list( $_, @included_mozilla_trust_purposes ) } @{$trust_purposes_by_level{$level}} ) ); + } + + return 0; +} + +my $crt = $ARGV[0] || 'ca-bundle.crt'; +(my $txt = $url) =~ s@(.*/|\?.*)@@g; + +my $stdout = $crt eq '-'; +my $resp; +my $fetched; + +my $oldhash = oldhash($crt); + +report "SHA256 of old file: $oldhash"; + +if(!$opt_n) { + report "Downloading $txt ..."; + + # If we have an HTTPS URL then use curl + if($url =~ /^https:\/\//i) { + if($curl) { + if($curl =~ /^Protocols:.* https( |$)/m) { + report "Get certdata with curl!"; + my $proto = !$opt_k ? "--proto =https" : ""; + my $quiet = $opt_q ? "-s" : ""; + my @out = `curl -w %{response_code} $proto $quiet -o "$txt" "$url"`; + if(!$? && @out && $out[0] == 200) { + $fetched = 1; + report "Downloaded $txt"; + } + else { + report "Failed downloading via HTTPS with curl"; + if(-e $txt && !unlink($txt)) { + report "Failed to remove '$txt': $!"; + } + } + } + else { + report "curl lacks https support"; + } + } + else { + report "curl not found"; + } + } + + # If nothing was fetched then use LWP + if(!$fetched) { + if($url =~ /^https:\/\//i) { + report "Falling back to HTTP"; + $url =~ s/^https:\/\//http:\/\//i; + } + if(!$opt_k) { + report "URLs other than HTTPS are disabled by default, to enable use -k"; + exit 1; + } + report "Get certdata with LWP!"; + if(!defined(${LWP::UserAgent::VERSION})) { + report "LWP is not available (LWP::UserAgent not found)"; + exit 1; + } + my $ua = new LWP::UserAgent(agent => "$0/$version"); + $ua->env_proxy(); + $resp = $ua->mirror($url, $txt); + if($resp && $resp->code eq '304') { + report "Not modified"; + exit 0 if -e $crt && !$opt_f; + } + else { + $fetched = 1; + report "Downloaded $txt"; + } + if(!$resp || $resp->code !~ /^(?:200|304)$/) { + report "Unable to download latest data: " + . ($resp? $resp->code . ' - ' . $resp->message : "LWP failed"); + exit 1 if -e $crt || ! -r $txt; + } + } +} + +my $filedate = $resp ? $resp->last_modified : (stat($txt))[9]; +my $datesrc = "as of"; +if(!$filedate) { + # mxr.mozilla.org gave us a time, hg.mozilla.org does not! + $filedate = time(); + $datesrc="downloaded on"; +} + +# get the hash from the download file +my $newhash= sha256($txt); + +if(!$opt_f && $oldhash eq $newhash) { + report "Downloaded file identical to previous run\'s source file. Exiting"; + if($opt_u && -e $txt && !unlink($txt)) { + report "Failed to remove $txt: $!\n"; + } + exit; +} + +report "SHA256 of new file: $newhash"; + +my $currentdate = scalar gmtime($filedate); + +my $format = $opt_t ? "plain text and " : ""; +if( $stdout ) { + open(CRT, '> -') or die "Couldn't open STDOUT: $!\n"; +} else { + open(CRT,">$crt.~") or die "Couldn't open $crt.~: $!\n"; +} +print CRT <) { + if (/\*\*\*\*\* BEGIN LICENSE BLOCK \*\*\*\*\*/) { + print CRT; + print if ($opt_l); + while () { + print CRT; + print if ($opt_l); + last if (/\*\*\*\*\* END LICENSE BLOCK \*\*\*\*\*/); + } + } + elsif(/^# (Issuer|Serial Number|Subject|Not Valid Before|Not Valid After |Fingerprint \(MD5\)|Fingerprint \(SHA1\)):/) { + push @precert, $_; + next; + } + elsif(/^#|^\s*$/) { + undef @precert; + next; + } + chomp; + + # this is a match for the start of a certificate + if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) { + $start_of_cert = 1 + } + if ($start_of_cert && /^CKA_LABEL UTF8 \"(.*)\"/) { + $caname = $1; + } + my %trust_purposes_by_level; + if ($start_of_cert && /^CKA_VALUE MULTILINE_OCTAL/) { + my $data; + while () { + last if (/^END/); + chomp; + my @octets = split(/\\/); + shift @octets; + for (@octets) { + $data .= chr(oct); + } + } + # scan forwards until the trust part + while () { + last if (/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/); + chomp; + } + # now scan the trust part to determine how we should trust this cert + while () { + last if (/^#/); + if (/^CKA_TRUST_([A-Z_]+)\s+CK_TRUST\s+CKT_NSS_([A-Z_]+)\s*$/) { + if ( !is_in_list($1,@valid_mozilla_trust_purposes) ) { + report "Warning: Unrecognized trust purpose for cert: $caname. Trust purpose: $1. Trust Level: $2"; + } elsif ( !is_in_list($2,@valid_mozilla_trust_levels) ) { + report "Warning: Unrecognized trust level for cert: $caname. Trust purpose: $1. Trust Level: $2"; + } else { + push @{$trust_purposes_by_level{$2}}, $1; + } + } + } + + if ( !should_output_cert(%trust_purposes_by_level) ) { + $skipnum ++; + report "Skipping: $caname" if ($opt_v); + } else { + my $encoded = MIME::Base64::encode_base64($data, ''); + $encoded =~ s/(.{1,${opt_w}})/$1\n/g; + my $pem = "-----BEGIN CERTIFICATE-----\n" + . $encoded + . "-----END CERTIFICATE-----\n"; + print CRT "\n$caname\n"; + print CRT @precert if($opt_m); + my $maxStringLength = length(decode('UTF-8', $caname, Encode::FB_CROAK | Encode::LEAVE_SRC)); + if ($opt_t) { + foreach my $key (keys %trust_purposes_by_level) { + my $string = $key . ": " . join(", ", @{$trust_purposes_by_level{$key}}); + $maxStringLength = List::Util::max( length($string), $maxStringLength ); + print CRT $string . "\n"; + } + } + print CRT ("=" x $maxStringLength . "\n"); + if (!$opt_t) { + print CRT $pem; + } else { + my $pipe = ""; + foreach my $hash (@included_signature_algorithms) { + $pipe = "|$openssl x509 -" . $hash . " -fingerprint -noout -inform PEM"; + if (!$stdout) { + $pipe .= " >> $crt.~"; + close(CRT) or die "Couldn't close $crt.~: $!"; + } + open(TMP, $pipe) or die "Couldn't open openssl pipe: $!"; + print TMP $pem; + close(TMP) or die "Couldn't close openssl pipe: $!"; + if (!$stdout) { + open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!"; + } + } + $pipe = "|$openssl x509 -text -inform PEM"; + if (!$stdout) { + $pipe .= " >> $crt.~"; + close(CRT) or die "Couldn't close $crt.~: $!"; + } + open(TMP, $pipe) or die "Couldn't open openssl pipe: $!"; + print TMP $pem; + close(TMP) or die "Couldn't close openssl pipe: $!"; + if (!$stdout) { + open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!"; + } + } + report "Parsing: $caname" if ($opt_v); + $certnum ++; + $start_of_cert = 0; + } + undef @precert; + } + +} +close(TXT) or die "Couldn't close $txt: $!\n"; +close(CRT) or die "Couldn't close $crt.~: $!\n"; +unless( $stdout ) { + if ($opt_b && -e $crt) { + my $bk = 1; + while (-e "$crt.~${bk}~") { + $bk++; + } + rename $crt, "$crt.~${bk}~" or die "Failed to create backup $crt.~$bk}~: $!\n"; + } elsif( -e $crt ) { + unlink( $crt ) or die "Failed to remove $crt: $!\n"; + } + rename "$crt.~", $crt or die "Failed to rename $crt.~ to $crt: $!\n"; +} +if($opt_u && -e $txt && !unlink($txt)) { + report "Failed to remove $txt: $!\n"; +} +report "Done ($certnum CA certs processed, $skipnum skipped)."; diff --git a/libcurl/lib/mk-ca-bundle.vbs b/libcurl/lib/mk-ca-bundle.vbs new file mode 100644 index 0000000..bd4e4a3 --- /dev/null +++ b/libcurl/lib/mk-ca-bundle.vbs @@ -0,0 +1,431 @@ +'*************************************************************************** +'* _ _ ____ _ +'* Project ___| | | | _ \| | +'* / __| | | | |_) | | +'* | (__| |_| | _ <| |___ +'* \___|\___/|_| \_\_____| +'* +'* Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. +'* +'* This software is licensed as described in the file COPYING, which +'* you should have received as part of this distribution. The terms +'* are also available at https://curl.haxx.se/docs/copyright.html. +'* +'* You may opt to use, copy, modify, merge, publish, distribute and/or sell +'* copies of the Software, and permit persons to whom the Software is +'* furnished to do so, under the terms of the COPYING file. +'* +'* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +'* KIND, either express or implied. +'* +'*************************************************************************** +'* Script to fetch certdata.txt from Mozilla.org site and create a +'* ca-bundle.crt for use with OpenSSL / libcurl / libcurl bindings +'* Requires WinHttp.WinHttpRequest.5.1 and ADODB.Stream which are part of +'* W2000 SP3 or later, WXP SP1 or later, W2003 Server SP1 or later. +'* Hacked by Guenter Knauf +'*************************************************************************** +Option Explicit +Const myVersion = "0.4.0" + +Const myUrl = "https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt" + +Const myOpenSSL = "openssl.exe" +Dim myUseOpenSSL +myUseOpenSSL = TRUE ' Flag: TRUE to use OpenSSL. If TRUE and is not + ' found then a warning is shown before continuing. + +Const myCdSavF = TRUE ' Flag: save downloaded data to file certdata.txt +Const myCaBakF = TRUE ' Flag: backup existing ca-bundle certificate +Const myAskLiF = TRUE ' Flag: display certdata.txt license agreement +Const myWrapLe = 76 ' Default length of base64 output lines + +' cert info code doesn't work properly with any recent openssl, leave disabled. +' Also: we want our certificate output by default to be as similar as possible +' to mk-ca-bundle.pl and setting this TRUE changes the base64 width to +' OpenSSL's built-in default width, which is not the same as mk-ca-bundle.pl. +Const myAskTiF = FALSE ' Flag: ask to include certificate text info + +' +'******************* Nothing to configure below! ******************* +' +Const adTypeBinary = 1 +Const adTypeText = 2 +Const adSaveCreateNotExist = 1 +Const adSaveCreateOverWrite = 2 +Dim objShell, objNetwork, objFSO, objHttp +Dim myBase, mySelf, myStream, myTmpFh, myCdData, myCdFile +Dim myCaFile, myTmpName, myBakNum, myOptTxt, i +Set objNetwork = WScript.CreateObject("WScript.Network") +Set objShell = WScript.CreateObject("WScript.Shell") +Set objFSO = WScript.CreateObject("Scripting.FileSystemObject") +Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest.5.1") +If objHttp Is Nothing Then Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest") +myBase = Left(WScript.ScriptFullName, InstrRev(WScript.ScriptFullName, "\")) +mySelf = Left(WScript.ScriptName, InstrRev(WScript.ScriptName, ".") - 1) & " " & myVersion + +myCdFile = Mid(myUrl, InstrRev(myUrl, "/") + 1) +myCaFile = "ca-bundle.crt" +myTmpName = InputBox("It will take a minute to download and parse the " & _ + "certificate data." & _ + vbLf & vbLf & _ + "Please enter the output filename:", mySelf, myCaFile) +If (myTmpName = "") Then + WScript.Quit 1 +End If +myCaFile = myTmpName +If (myCdFile = "") Then + MsgBox("URL does not contain filename!"), vbCritical, mySelf + WScript.Quit 1 +End If + +' Don't use OpenSSL if it's not present. +If (myUseOpenSSL = TRUE) Then + Dim errnum + + On Error Resume Next + Call objShell.Run("""" & myOpenSSL & """ version", 0, TRUE) + errnum = Err.Number + On Error GoTo 0 + + If Not (errnum = 0) Then + myUseOpenSSL = FALSE + MsgBox("OpenSSL was not found so the certificate bundle will not " & _ + "include the SHA256 hash of the raw certificate data file " & _ + "that was used to generate the certificates in the bundle. " & _ + vbLf & vbLf & _ + "This does not have any effect on the certificate output, " & _ + "so this script will continue." & _ + vbLf & vbLf & _ + "If you want to set a custom location for OpenSSL or disable " & _ + "this message then edit the variables at the start of the " & _ + "script."), vbInformation, mySelf + End If +End If + +If (myAskTiF = TRUE) And (myUseOpenSSL = TRUE) Then + If (6 = objShell.PopUp("Do you want to include text information about " & _ + "each certificate?" & vbLf & _ + "(Requires OpenSSL.exe in the current directory " & _ + "or search path)",, _ + mySelf, vbQuestion + vbYesNo + vbDefaultButton2)) Then + myOptTxt = TRUE + Else + myOptTxt = FALSE + End If +End If + +' Uncomment the line below to ignore SSL invalid cert errors +' objHttp.Option(4) = 256 + 512 + 4096 + 8192 +objHttp.SetTimeouts 0, 5000, 10000, 10000 +objHttp.Open "GET", myUrl, FALSE +objHttp.setRequestHeader "User-Agent", WScript.ScriptName & "/" & myVersion +objHttp.Send "" +If Not (objHttp.Status = 200) Then + MsgBox("Failed to download '" & myCdFile & "': " & objHttp.Status & " - " & objHttp.StatusText), vbCritical, mySelf + WScript.Quit 1 +End If +' Write received data to file if enabled +If (myCdSavF = TRUE) Then + Call SaveBinaryData(myCdFile, objHttp.ResponseBody) +End If +' Convert data from ResponseBody instead of using ResponseText because of UTF-8 +myCdData = ConvertBinaryToUTF8(objHttp.ResponseBody) +Set objHttp = Nothing +' Backup exitsing ca-bundle certificate file +If (myCaBakF = TRUE) Then + If objFSO.FileExists(myCaFile) Then + Dim myBakFile, b + b = 1 + myBakFile = myCaFile & ".~" & b & "~" + While objFSO.FileExists(myBakFile) + b = b + 1 + myBakFile = myCaFile & ".~" & b & "~" + Wend + Set myTmpFh = objFSO.GetFile(myCaFile) + myTmpFh.Move myBakFile + End If +End If + +' Process the received data +Dim myLines, myPattern, myInsideCert, myInsideLicense, myLicenseText, myNumCerts, myNumSkipped +Dim myLabel, myOctets, myData, myPem, myRev, myUntrusted, j +myNumSkipped = 0 +myNumCerts = 0 +myData = "" +myLines = Split(myCdData, vbLf, -1) +Set myStream = CreateObject("ADODB.Stream") +myStream.Open +myStream.Type = adTypeText +myStream.Charset = "utf-8" +myStream.WriteText "##" & vbLf & _ + "## Bundle of CA Root Certificates" & vbLf & _ + "##" & vbLf & _ + "## Certificate data from Mozilla as of: " & _ + ConvertDateToString(LocalDateToUTC(Now)) & " GMT" & vbLf & _ + "##" & vbLf & _ + "## This is a bundle of X.509 certificates of public Certificate Authorities" & vbLf & _ + "## (CA). These were automatically extracted from Mozilla's root certificates" & vbLf & _ + "## file (certdata.txt). This file can be found in the mozilla source tree:" & vbLf & _ + "## " & myUrl & vbLf & _ + "##" & vbLf & _ + "## It contains the certificates in PEM format and therefore" & vbLf & _ + "## can be directly used with curl / libcurl / php_curl, or with" & vbLf & _ + "## an Apache+mod_ssl webserver for SSL client authentication." & vbLf & _ + "## Just configure this file as the SSLCACertificateFile." & vbLf & _ + "##" & vbLf & _ + "## Conversion done with mk-ca-bundle.vbs version " & myVersion & "." & vbLf +If (myCdSavF = TRUE) And (myUseOpenSSL = TRUE) Then + myStream.WriteText "## SHA256: " & FileSHA256(myCdFile) & vbLf +End If +myStream.WriteText "##" & vbLf & vbLf + +myStream.WriteText vbLf +For i = 0 To UBound(myLines) + If InstrRev(myLines(i), "CKA_LABEL ") Then + myPattern = "^CKA_LABEL\s+[A-Z0-9]+\s+""(.+?)""" + myLabel = RegExprFirst(myPattern, myLines(i)) + End If + If (myInsideCert = TRUE) Then + If InstrRev(myLines(i), "END") Then + myInsideCert = FALSE + While (i < UBound(myLines)) And Not (myLines(i) = "#") + i = i + 1 + If InstrRev(myLines(i), "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR") Then + myUntrusted = FALSE + End If + Wend + If (myUntrusted = TRUE) Then + myNumSkipped = myNumSkipped + 1 + Else + myStream.WriteText myLabel & vbLf + myStream.WriteText String(Len(myLabel), "=") & vbLf + myPem = "-----BEGIN CERTIFICATE-----" & vbLf & _ + Base64Encode(myData) & vbLf & _ + "-----END CERTIFICATE-----" & vbLf + If (myOptTxt = FALSE) Then + myStream.WriteText myPem & vbLf + Else + Dim myCmd, myRval, myTmpIn, myTmpOut + myTmpIn = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName + myTmpOut = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName + Set myTmpFh = objFSO.OpenTextFile(myTmpIn, 2, TRUE) + myTmpFh.Write myPem + myTmpFh.Close + myCmd = """" & myOpenSSL & """ x509 -md5 -fingerprint -text " & _ + "-inform PEM -in " & myTmpIn & " -out " & myTmpOut + myRval = objShell.Run (myCmd, 0, TRUE) + objFSO.DeleteFile myTmpIn, TRUE + If Not (myRval = 0) Then + MsgBox("Failed to process PEM cert with OpenSSL commandline!"), vbCritical, mySelf + objFSO.DeleteFile myTmpOut, TRUE + WScript.Quit 3 + End If + Set myTmpFh = objFSO.OpenTextFile(myTmpOut, 1) + myStream.WriteText myTmpFh.ReadAll & vbLf + myTmpFh.Close + objFSO.DeleteFile myTmpOut, TRUE + End If + myNumCerts = myNumCerts + 1 + End If + Else + myOctets = Split(myLines(i), "\") + For j = 1 To UBound(myOctets) + myData = myData & Chr(CByte("&o" & myOctets(j))) + Next + End If + End If + If InstrRev(myLines(i), "CVS_ID ") Then + myPattern = "^CVS_ID\s+""(.+?)""" + myRev = RegExprFirst(myPattern, myLines(i)) + myStream.WriteText "# " & myRev & vbLf & vbLf + End If + If InstrRev(myLines(i), "CKA_VALUE MULTILINE_OCTAL") Then + myInsideCert = TRUE + myUntrusted = TRUE + myData = "" + End If + If InstrRev(myLines(i), "***** BEGIN LICENSE BLOCK *****") Then + myInsideLicense = TRUE + End If + If (myInsideLicense = TRUE) Then + myStream.WriteText myLines(i) & vbLf + myLicenseText = myLicenseText & Mid(myLines(i), 2) & vbLf + End If + If InstrRev(myLines(i), "***** END LICENSE BLOCK *****") Then + myInsideLicense = FALSE + If (myAskLiF = TRUE) Then + If Not (6 = objShell.PopUp(myLicenseText & vbLf & _ + "Do you agree to the license shown above (required to proceed) ?",, _ + mySelf, vbQuestion + vbYesNo + vbDefaultButton1)) Then + myStream.Close + objFSO.DeleteFile myCaFile, TRUE + WScript.Quit 2 + End If + End If + End If +Next + +' To stop the UTF-8 BOM from being written the stream has to be copied and +' then saved as binary. +Dim myCopy +Set myCopy = CreateObject("ADODB.Stream") +myCopy.Type = adTypeBinary +myCopy.Open +myStream.Position = 3 ' Skip UTF-8 BOM +myStream.CopyTo myCopy +myCopy.SaveToFile myCaFile, adSaveCreateOverWrite +myCopy.Close +myStream.Close +Set myCopy = Nothing +Set myStream = Nothing + +' Done +objShell.PopUp "Done (" & myNumCerts & " CA certs processed, " & myNumSkipped & _ + " untrusted skipped).", 20, mySelf, vbInformation +WScript.Quit 0 + +Function ConvertBinaryToUTF8(arrBytes) + Dim objStream + Set objStream = CreateObject("ADODB.Stream") + objStream.Open + objStream.Type = adTypeBinary + objStream.Write arrBytes + objStream.Position = 0 + objStream.Type = adTypeText + objStream.Charset = "utf-8" + ConvertBinaryToUTF8 = objStream.ReadText + Set objStream = Nothing +End Function + +Function SaveBinaryData(filename, data) + Dim objStream + Set objStream = CreateObject("ADODB.Stream") + objStream.Type = adTypeBinary + objStream.Open + objStream.Write data + objStream.SaveToFile filename, adSaveCreateOverWrite + objStream.Close + Set objStream = Nothing +End Function + +Function RegExprFirst(SearchPattern, TheString) + Dim objRegExp, Matches ' create variables. + Set objRegExp = New RegExp ' create a regular expression. + objRegExp.Pattern = SearchPattern ' sets the search pattern. + objRegExp.IgnoreCase = TRUE ' set to ignores case. + objRegExp.Global = TRUE ' set to global search. + Set Matches = objRegExp.Execute(TheString) ' do the search. + If (Matches.Count) Then + RegExprFirst = Matches(0).SubMatches(0) ' return first match. + Else + RegExprFirst = "" + End If + Set objRegExp = Nothing +End Function + +Function Base64Encode(inData) + Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + Dim cOut, sOut, lWrap, I + lWrap = Int(myWrapLe * 3 / 4) + + 'For each group of 3 bytes + For I = 1 To Len(inData) Step 3 + Dim nGroup, pOut, sGroup + + 'Create one long from this 3 bytes. + nGroup = &H10000 * Asc(Mid(inData, I, 1)) + _ + &H100 * MyASC(Mid(inData, I + 1, 1)) + _ + MyASC(Mid(inData, I + 2, 1)) + + 'Oct splits the long To 8 groups with 3 bits + nGroup = Oct(nGroup) + + 'Add leading zeros + nGroup = String(8 - Len(nGroup), "0") & nGroup + + 'Convert To base64 + pOut = Mid(Base64, CLng("&o" & Mid(nGroup, 1, 2)) + 1, 1) & _ + Mid(Base64, CLng("&o" & Mid(nGroup, 3, 2)) + 1, 1) & _ + Mid(Base64, CLng("&o" & Mid(nGroup, 5, 2)) + 1, 1) & _ + Mid(Base64, CLng("&o" & Mid(nGroup, 7, 2)) + 1, 1) + + 'Add the part To OutPut string + sOut = sOut + pOut + + 'Add a new line For Each myWrapLe chars In dest + If (I < Len(inData) - 2) Then + If (I + 2) Mod lWrap = 0 Then sOut = sOut & vbLf + End If + Next + Select Case Len(inData) Mod 3 + Case 1: '8 bit final + sOut = Left(sOut, Len(sOut) - 2) & "==" + Case 2: '16 bit final + sOut = Left(sOut, Len(sOut) - 1) & "=" + End Select + Base64Encode = sOut +End Function + +Function MyASC(OneChar) + If OneChar = "" Then MyASC = 0 Else MyASC = Asc(OneChar) +End Function + +' Return the date in the same format as perl to match mk-ca-bundle.pl output: +' Wed Sep 7 03:12:05 2016 +Function ConvertDateToString(input) + Dim output + output = WeekDayName(WeekDay(input), TRUE) & " " & _ + MonthName(Month(input), TRUE) & " " + If (Len(Day(input)) = 1) Then + output = output & " " + End If + output = output & _ + Day(input) & " " & _ + FormatDateTime(input, vbShortTime) & ":" + If (Len(Second(input)) = 1) Then + output = output & "0" + End If + output = output & _ + Second(input) & " " & _ + Year(input) + ConvertDateToString = output +End Function + +' Convert local Date to UTC. Microsoft says: +' Use Win32_ComputerSystem CurrentTimeZone property, because it automatically +' adjusts the Time Zone bias for daylight saving time; Win32_Time Zone Bias +' property does not. +' https://msdn.microsoft.com/en-us/library/windows/desktop/ms696015.aspx +Function LocalDateToUTC(localdate) + Dim item, offset + For Each item In GetObject("winmgmts:").InstancesOf("Win32_ComputerSystem") + offset = item.CurrentTimeZone ' the offset in minutes + Next + If (offset < 0) Then + LocalDateToUTC = DateAdd("n", ABS(offset), localdate) + Else + LocalDateToUTC = DateAdd("n", -ABS(offset), localdate) + End If + 'objShell.PopUp LocalDateToUTC +End Function + +Function FileSHA256(filename) + Dim cmd, rval, tmpOut, tmpFh + if (myUseOpenSSL = TRUE) Then + tmpOut = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName + cmd = """" & myOpenSSL & """ dgst -r -sha256 -out """ & tmpOut & """ """ & filename & """" + rval = objShell.Run(cmd, 0, TRUE) + If Not (rval = 0) Then + MsgBox("Failed to get sha256 of """ & filename & """ with OpenSSL commandline!"), vbCritical, mySelf + objFSO.DeleteFile tmpOut, TRUE + WScript.Quit 3 + End If + Set tmpFh = objFSO.OpenTextFile(tmpOut, 1) + FileSHA256 = RegExprFirst("^([0-9a-f]{64}) .+", tmpFh.ReadAll) + tmpFh.Close + objFSO.DeleteFile tmpOut, TRUE + Else + FileSHA256 = "" + End If +End Function diff --git a/libcurl/lib/mprintf.c b/libcurl/lib/mprintf.c new file mode 100644 index 0000000..e190936 --- /dev/null +++ b/libcurl/lib/mprintf.c @@ -0,0 +1,1173 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1999 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * + * Purpose: + * A merge of Bjorn Reese's format() function and Daniel's dsprintf() + * 1.0. A full blooded printf() clone with full support for $ + * everywhere (parameters, widths and precisions) including variabled + * sized parameters (like doubles, long longs, long doubles and even + * void * in 64-bit architectures). + * + * Current restrictions: + * - Max 128 parameters + * - No 'long double' support. + * + * If you ever want truly portable and good *printf() clones, the project that + * took on from here is named 'Trio' and you find more details on the trio web + * page at https://daniel.haxx.se/projects/trio/ + */ + +#include "curl_setup.h" +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * If SIZEOF_SIZE_T has not been defined, default to the size of long. + */ + +#ifdef HAVE_LONGLONG +# define LONG_LONG_TYPE long long +# define HAVE_LONG_LONG_TYPE +#else +# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define LONG_LONG_TYPE __int64 +# define HAVE_LONG_LONG_TYPE +# else +# undef LONG_LONG_TYPE +# undef HAVE_LONG_LONG_TYPE +# endif +#endif + +/* + * Non-ANSI integer extensions + */ + +#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \ + (defined(__WATCOMC__) && defined(__386__)) || \ + (defined(__POCC__) && defined(_MSC_VER)) || \ + (defined(_WIN32_WCE)) || \ + (defined(__MINGW32__)) || \ + (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)) +# define MP_HAVE_INT_EXTENSIONS +#endif + +/* + * Max integer data types that mprintf.c is capable + */ + +#ifdef HAVE_LONG_LONG_TYPE +# define mp_intmax_t LONG_LONG_TYPE +# define mp_uintmax_t unsigned LONG_LONG_TYPE +#else +# define mp_intmax_t long +# define mp_uintmax_t unsigned long +#endif + +#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should + fit negative DBL_MAX (317 letters) */ +#define MAX_PARAMETERS 128 /* lame static limit */ + +#ifdef __AMIGA__ +# undef FORMAT_INT +#endif + +/* Lower-case digits. */ +static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +/* Upper-case digits. */ +static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +#define OUTCHAR(x) \ + do{ \ + if(stream((unsigned char)(x), (FILE *)data) != -1) \ + done++; \ + else \ + return done; /* return immediately on failure */ \ + } WHILE_FALSE + +/* Data type to read from the arglist */ +typedef enum { + FORMAT_UNKNOWN = 0, + FORMAT_STRING, + FORMAT_PTR, + FORMAT_INT, + FORMAT_INTPTR, + FORMAT_LONG, + FORMAT_LONGLONG, + FORMAT_DOUBLE, + FORMAT_LONGDOUBLE, + FORMAT_WIDTH /* For internal use */ +} FormatType; + +/* conversion and display flags */ +enum { + FLAGS_NEW = 0, + FLAGS_SPACE = 1<<0, + FLAGS_SHOWSIGN = 1<<1, + FLAGS_LEFT = 1<<2, + FLAGS_ALT = 1<<3, + FLAGS_SHORT = 1<<4, + FLAGS_LONG = 1<<5, + FLAGS_LONGLONG = 1<<6, + FLAGS_LONGDOUBLE = 1<<7, + FLAGS_PAD_NIL = 1<<8, + FLAGS_UNSIGNED = 1<<9, + FLAGS_OCTAL = 1<<10, + FLAGS_HEX = 1<<11, + FLAGS_UPPER = 1<<12, + FLAGS_WIDTH = 1<<13, /* '*' or '*$' used */ + FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */ + FLAGS_PREC = 1<<15, /* precision was specified */ + FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */ + FLAGS_CHAR = 1<<17, /* %c story */ + FLAGS_FLOATE = 1<<18, /* %e or %E */ + FLAGS_FLOATG = 1<<19 /* %g or %G */ +}; + +typedef struct { + FormatType type; + int flags; + long width; /* width OR width parameter number */ + long precision; /* precision OR precision parameter number */ + union { + char *str; + void *ptr; + union { + mp_intmax_t as_signed; + mp_uintmax_t as_unsigned; + } num; + double dnum; + } data; +} va_stack_t; + +struct nsprintf { + char *buffer; + size_t length; + size_t max; +}; + +struct asprintf { + char *buffer; /* allocated buffer */ + size_t len; /* length of string */ + size_t alloc; /* length of alloc */ + int fail; /* (!= 0) if an alloc has failed and thus + the output is not the complete data */ +}; + +static long dprintf_DollarString(char *input, char **end) +{ + int number = 0; + while(ISDIGIT(*input)) { + number *= 10; + number += *input-'0'; + input++; + } + if(number && ('$'==*input++)) { + *end = input; + return number; + } + return 0; +} + +static bool dprintf_IsQualifierNoDollar(const char *fmt) +{ +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) { + return TRUE; + } +#endif + + switch(*fmt) { + case '-': case '+': case ' ': case '#': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'h': case 'l': case 'L': case 'z': case 'q': + case '*': case 'O': +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#endif + return TRUE; + + default: + return FALSE; + } +} + +/****************************************************************** + * + * Pass 1: + * Create an index with the type of each parameter entry and its + * value (may vary in size) + * + * Returns zero on success. + * + ******************************************************************/ + +static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, + va_list arglist) +{ + char *fmt = (char *)format; + int param_num = 0; + long this_param; + long width; + long precision; + int flags; + long max_param = 0; + long i; + + while(*fmt) { + if(*fmt++ == '%') { + if(*fmt == '%') { + fmt++; + continue; /* while */ + } + + flags = FLAGS_NEW; + + /* Handle the positional case (N$) */ + + param_num++; + + this_param = dprintf_DollarString(fmt, &fmt); + if(0 == this_param) + /* we got no positional, get the next counter */ + this_param = param_num; + + if(this_param > max_param) + max_param = this_param; + + /* + * The parameter with number 'i' should be used. Next, we need + * to get SIZE and TYPE of the parameter. Add the information + * to our array. + */ + + width = 0; + precision = 0; + + /* Handle the flags */ + + while(dprintf_IsQualifierNoDollar(fmt)) { +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3)) { + flags |= FLAGS_LONG; + fmt += 3; + } + else if(!strncmp(fmt, "I64", 3)) { + flags |= FLAGS_LONGLONG; + fmt += 3; + } + else +#endif + + switch(*fmt++) { + case ' ': + flags |= FLAGS_SPACE; + break; + case '+': + flags |= FLAGS_SHOWSIGN; + break; + case '-': + flags |= FLAGS_LEFT; + flags &= ~FLAGS_PAD_NIL; + break; + case '#': + flags |= FLAGS_ALT; + break; + case '.': + if('*' == *fmt) { + /* The precision is picked from a specified parameter */ + + flags |= FLAGS_PRECPARAM; + fmt++; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + precision = i; + else + precision = param_num; + + if(precision > max_param) + max_param = precision; + } + else { + flags |= FLAGS_PREC; + precision = strtol(fmt, &fmt, 10); + } + break; + case 'h': + flags |= FLAGS_SHORT; + break; +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; +#endif + case 'l': + if(flags & FLAGS_LONG) + flags |= FLAGS_LONGLONG; + else + flags |= FLAGS_LONG; + break; + case 'L': + flags |= FLAGS_LONGDOUBLE; + break; + case 'q': + flags |= FLAGS_LONGLONG; + break; + case 'z': + /* the code below generates a warning if -Wunreachable-code is + used */ +#if (SIZEOF_SIZE_T > SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case 'O': +#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case '0': + if(!(flags & FLAGS_LEFT)) + flags |= FLAGS_PAD_NIL; + /* FALLTHROUGH */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + flags |= FLAGS_WIDTH; + width = strtol(fmt-1, &fmt, 10); + break; + case '*': /* Special case */ + flags |= FLAGS_WIDTHPARAM; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + width = i; + else + width = param_num; + if(width > max_param) + max_param = width; + break; + default: + break; + } + } /* switch */ + + /* Handle the specifier */ + + i = this_param - 1; + + if((i < 0) || (i >= MAX_PARAMETERS)) + /* out of allowed range */ + return 1; + + switch (*fmt) { + case 'S': + flags |= FLAGS_ALT; + /* FALLTHROUGH */ + case 's': + vto[i].type = FORMAT_STRING; + break; + case 'n': + vto[i].type = FORMAT_INTPTR; + break; + case 'p': + vto[i].type = FORMAT_PTR; + break; + case 'd': case 'i': + vto[i].type = FORMAT_INT; + break; + case 'u': + vto[i].type = FORMAT_INT; + flags |= FLAGS_UNSIGNED; + break; + case 'o': + vto[i].type = FORMAT_INT; + flags |= FLAGS_OCTAL; + break; + case 'x': + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UNSIGNED; + break; + case 'X': + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED; + break; + case 'c': + vto[i].type = FORMAT_INT; + flags |= FLAGS_CHAR; + break; + case 'f': + vto[i].type = FORMAT_DOUBLE; + break; + case 'e': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE; + break; + case 'E': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE|FLAGS_UPPER; + break; + case 'g': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG; + break; + case 'G': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG|FLAGS_UPPER; + break; + default: + vto[i].type = FORMAT_UNKNOWN; + break; + } /* switch */ + + vto[i].flags = flags; + vto[i].width = width; + vto[i].precision = precision; + + if(flags & FLAGS_WIDTHPARAM) { + /* we have the width specified from a parameter, so we make that + parameter's info setup properly */ + long k = width - 1; + vto[i].width = k; + vto[k].type = FORMAT_WIDTH; + vto[k].flags = FLAGS_NEW; + /* can't use width or precision of width! */ + vto[k].width = 0; + vto[k].precision = 0; + } + if(flags & FLAGS_PRECPARAM) { + /* we have the precision specified from a parameter, so we make that + parameter's info setup properly */ + long k = precision - 1; + vto[i].precision = k; + vto[k].type = FORMAT_WIDTH; + vto[k].flags = FLAGS_NEW; + /* can't use width or precision of width! */ + vto[k].width = 0; + vto[k].precision = 0; + } + *endpos++ = fmt + 1; /* end of this sequence */ + } + } + + /* Read the arg list parameters into our data list */ + for(i = 0; i$ sequence */ + param = dprintf_DollarString(f, &f); + + if(!param) + param = param_num; + else + --param; + + param_num++; /* increase this always to allow "%2$s %1$s %s" and then the + third %s will pick the 3rd argument */ + + p = &vto[param]; + + /* pick up the specified width */ + if(p->flags & FLAGS_WIDTHPARAM) { + width = (long)vto[p->width].data.num.as_signed; + param_num++; /* since the width is extracted from a parameter, we + must skip that to get to the next one properly */ + if(width < 0) { + /* "A negative field width is taken as a '-' flag followed by a + positive field width." */ + width = -width; + p->flags |= FLAGS_LEFT; + p->flags &= ~FLAGS_PAD_NIL; + } + } + else + width = p->width; + + /* pick up the specified precision */ + if(p->flags & FLAGS_PRECPARAM) { + prec = (long)vto[p->precision].data.num.as_signed; + param_num++; /* since the precision is extracted from a parameter, we + must skip that to get to the next one properly */ + if(prec < 0) + /* "A negative precision is taken as if the precision were + omitted." */ + prec = -1; + } + else if(p->flags & FLAGS_PREC) + prec = p->precision; + else + prec = -1; + + is_alt = (p->flags & FLAGS_ALT) ? 1 : 0; + + switch(p->type) { + case FORMAT_INT: + num = p->data.num.as_unsigned; + if(p->flags & FLAGS_CHAR) { + /* Character. */ + if(!(p->flags & FLAGS_LEFT)) + while(--width > 0) + OUTCHAR(' '); + OUTCHAR((char) num); + if(p->flags & FLAGS_LEFT) + while(--width > 0) + OUTCHAR(' '); + break; + } + if(p->flags & FLAGS_OCTAL) { + /* Octal unsigned integer. */ + base = 8; + goto unsigned_number; + } + else if(p->flags & FLAGS_HEX) { + /* Hexadecimal unsigned integer. */ + + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + base = 16; + goto unsigned_number; + } + else if(p->flags & FLAGS_UNSIGNED) { + /* Decimal unsigned integer. */ + base = 10; + goto unsigned_number; + } + + /* Decimal integer. */ + base = 10; + + is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0; + if(is_neg) { + /* signed_num might fail to hold absolute negative minimum by 1 */ + signed_num = p->data.num.as_signed + (mp_intmax_t)1; + signed_num = -signed_num; + num = (mp_uintmax_t)signed_num; + num += (mp_uintmax_t)1; + } + + goto number; + + unsigned_number: + /* Unsigned number of base BASE. */ + is_neg = 0; + + number: + /* Number of base BASE. */ + + /* Supply a default precision if none was given. */ + if(prec == -1) + prec = 1; + + /* Put the number in WORK. */ + w = workend; + while(num > 0) { + *w-- = digits[num % base]; + num /= base; + } + width -= (long)(workend - w); + prec -= (long)(workend - w); + + if(is_alt && base == 8 && prec <= 0) { + *w-- = '0'; + --width; + } + + if(prec > 0) { + width -= prec; + while(prec-- > 0) + *w-- = '0'; + } + + if(is_alt && base == 16) + width -= 2; + + if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) + --width; + + if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR(' '); + + if(is_neg) + OUTCHAR('-'); + else if(p->flags & FLAGS_SHOWSIGN) + OUTCHAR('+'); + else if(p->flags & FLAGS_SPACE) + OUTCHAR(' '); + + if(is_alt && base == 16) { + OUTCHAR('0'); + if(p->flags & FLAGS_UPPER) + OUTCHAR('X'); + else + OUTCHAR('x'); + } + + if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR('0'); + + /* Write the number. */ + while(++w <= workend) { + OUTCHAR(*w); + } + + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + break; + + case FORMAT_STRING: + /* String. */ + { + static const char null[] = "(nil)"; + const char *str; + size_t len; + + str = (char *) p->data.str; + if(str == NULL) { + /* Write null[] if there's space. */ + if(prec == -1 || prec >= (long) sizeof(null) - 1) { + str = null; + len = sizeof(null) - 1; + /* Disable quotes around (nil) */ + p->flags &= (~FLAGS_ALT); + } + else { + str = ""; + len = 0; + } + } + else if(prec != -1) + len = (size_t)prec; + else + len = strlen(str); + + width -= (len > LONG_MAX) ? LONG_MAX : (long)len; + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + + if(!(p->flags&FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + + for(; len && *str; len--) + OUTCHAR(*str++); + if(p->flags&FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + } + break; + + case FORMAT_PTR: + /* Generic pointer. */ + { + void *ptr; + ptr = (void *) p->data.ptr; + if(ptr != NULL) { + /* If the pointer is not NULL, write it as a %#x spec. */ + base = 16; + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + is_alt = 1; + num = (size_t) ptr; + is_neg = 0; + goto number; + } + else { + /* Write "(nil)" for a nil pointer. */ + static const char strnil[] = "(nil)"; + const char *point; + + width -= (long)(sizeof(strnil) - 1); + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + for(point = strnil; *point != '\0'; ++point) + OUTCHAR(*point); + if(! (p->flags & FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + } + } + break; + + case FORMAT_DOUBLE: + { + char formatbuf[32]="%"; + char *fptr = &formatbuf[1]; + size_t left = sizeof(formatbuf)-strlen(formatbuf); + int len; + + width = -1; + if(p->flags & FLAGS_WIDTH) + width = p->width; + else if(p->flags & FLAGS_WIDTHPARAM) + width = (long)vto[p->width].data.num.as_signed; + + prec = -1; + if(p->flags & FLAGS_PREC) + prec = p->precision; + else if(p->flags & FLAGS_PRECPARAM) + prec = (long)vto[p->precision].data.num.as_signed; + + if(p->flags & FLAGS_LEFT) + *fptr++ = '-'; + if(p->flags & FLAGS_SHOWSIGN) + *fptr++ = '+'; + if(p->flags & FLAGS_SPACE) + *fptr++ = ' '; + if(p->flags & FLAGS_ALT) + *fptr++ = '#'; + + *fptr = 0; + + if(width >= 0) { + if(width >= (long)sizeof(work)) + width = sizeof(work)-1; + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, "%ld", width); + fptr += len; + left -= len; + } + if(prec >= 0) { + /* for each digit in the integer part, we can have one less + precision */ + size_t maxprec = sizeof(work) - 2; + double val = p->data.dnum; + while(val >= 10.0) { + val /= 10; + maxprec--; + } + + if(prec > (long)maxprec) + prec = (long)maxprec-1; + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, ".%ld", prec); + fptr += len; + } + if(p->flags & FLAGS_LONG) + *fptr++ = 'l'; + + if(p->flags & FLAGS_FLOATE) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e'); + else if(p->flags & FLAGS_FLOATG) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g'); + else + *fptr++ = 'f'; + + *fptr = 0; /* and a final zero termination */ + + /* NOTE NOTE NOTE!! Not all sprintf implementations return number of + output characters */ + (sprintf)(work, formatbuf, p->data.dnum); + DEBUGASSERT(strlen(work) <= sizeof(work)); + for(fptr = work; *fptr; fptr++) + OUTCHAR(*fptr); + } + break; + + case FORMAT_INTPTR: + /* Answer the count of characters written. */ +#ifdef HAVE_LONG_LONG_TYPE + if(p->flags & FLAGS_LONGLONG) + *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done; + else +#endif + if(p->flags & FLAGS_LONG) + *(long *) p->data.ptr = (long)done; + else if(!(p->flags & FLAGS_SHORT)) + *(int *) p->data.ptr = (int)done; + else + *(short *) p->data.ptr = (short)done; + break; + + default: + break; + } + f = *end++; /* goto end of %-code */ + + } + return done; +} + +/* fputc() look-alike */ +static int addbyter(int output, FILE *data) +{ + struct nsprintf *infop = (struct nsprintf *)data; + unsigned char outc = (unsigned char)output; + + if(infop->length < infop->max) { + /* only do this if we haven't reached max length yet */ + infop->buffer[0] = outc; /* store */ + infop->buffer++; /* increase pointer */ + infop->length++; /* we are now one byte larger */ + return outc; /* fputc() returns like this on success */ + } + return -1; +} + +int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, + va_list ap_save) +{ + int retcode; + struct nsprintf info; + + info.buffer = buffer; + info.length = 0; + info.max = maxlength; + + retcode = dprintf_formatf(&info, addbyter, format, ap_save); + if((retcode != -1) && info.max) { + /* we terminate this with a zero byte */ + if(info.max == info.length) + /* we're at maximum, scrap the last letter */ + info.buffer[-1] = 0; + else + info.buffer[0] = 0; + } + return retcode; +} + +int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save); + va_end(ap_save); + return retcode; +} + +/* fputc() look-alike */ +static int alloc_addbyter(int output, FILE *data) +{ + struct asprintf *infop = (struct asprintf *)data; + unsigned char outc = (unsigned char)output; + + if(!infop->buffer) { + infop->buffer = malloc(32); + if(!infop->buffer) { + infop->fail = 1; + return -1; /* fail */ + } + infop->alloc = 32; + infop->len = 0; + } + else if(infop->len + 1 >= infop->alloc) { + char *newptr = NULL; + size_t newsize = infop->alloc*2; + + /* detect wrap-around or other overflow problems */ + if(newsize > infop->alloc) + newptr = realloc(infop->buffer, newsize); + + if(!newptr) { + infop->fail = 1; + return -1; /* fail */ + } + infop->buffer = newptr; + infop->alloc = newsize; + } + + infop->buffer[ infop->len ] = outc; + + infop->len++; + + return outc; /* fputc() returns like this on success */ +} + +char *curl_maprintf(const char *format, ...) +{ + va_list ap_save; /* argument pointer */ + int retcode; + struct asprintf info; + + info.buffer = NULL; + info.len = 0; + info.alloc = 0; + info.fail = 0; + + va_start(ap_save, format); + retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); + va_end(ap_save); + if((-1 == retcode) || info.fail) { + if(info.alloc) + free(info.buffer); + return NULL; + } + if(info.alloc) { + info.buffer[info.len] = 0; /* we terminate this with a zero byte */ + return info.buffer; + } + return strdup(""); +} + +char *curl_mvaprintf(const char *format, va_list ap_save) +{ + int retcode; + struct asprintf info; + + info.buffer = NULL; + info.len = 0; + info.alloc = 0; + info.fail = 0; + + retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); + if((-1 == retcode) || info.fail) { + if(info.alloc) + free(info.buffer); + return NULL; + } + + if(info.alloc) { + info.buffer[info.len] = 0; /* we terminate this with a zero byte */ + return info.buffer; + } + return strdup(""); +} + +static int storebuffer(int output, FILE *data) +{ + char **buffer = (char **)data; + unsigned char outc = (unsigned char)output; + **buffer = outc; + (*buffer)++; + return outc; /* act like fputc() ! */ +} + +int curl_msprintf(char *buffer, const char *format, ...) +{ + va_list ap_save; /* argument pointer */ + int retcode; + va_start(ap_save, format); + retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); + va_end(ap_save); + *buffer = 0; /* we terminate this with a zero byte */ + return retcode; +} + +int curl_mprintf(const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + + retcode = dprintf_formatf(stdout, fputc, format, ap_save); + va_end(ap_save); + return retcode; +} + +int curl_mfprintf(FILE *whereto, const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + retcode = dprintf_formatf(whereto, fputc, format, ap_save); + va_end(ap_save); + return retcode; +} + +int curl_mvsprintf(char *buffer, const char *format, va_list ap_save) +{ + int retcode; + retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); + *buffer = 0; /* we terminate this with a zero byte */ + return retcode; +} + +int curl_mvprintf(const char *format, va_list ap_save) +{ + return dprintf_formatf(stdout, fputc, format, ap_save); +} + +int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save) +{ + return dprintf_formatf(whereto, fputc, format, ap_save); +} diff --git a/libcurl/lib/multi.c b/libcurl/lib/multi.c new file mode 100644 index 0000000..2b6b1bc --- /dev/null +++ b/libcurl/lib/multi.c @@ -0,0 +1,3076 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "transfer.h" +#include "url.h" +#include "connect.h" +#include "progress.h" +#include "easyif.h" +#include "share.h" +#include "psl.h" +#include "multiif.h" +#include "sendf.h" +#include "timeval.h" +#include "http.h" +#include "select.h" +#include "warnless.h" +#include "speedcheck.h" +#include "conncache.h" +#include "multihandle.h" +#include "sigpipe.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "http_proxy.h" +#include "http2.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97 + to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every + CURL handle takes 45-50 K memory, therefore this 3K are not significant. +*/ +#ifndef CURL_SOCKET_HASH_TABLE_SIZE +#define CURL_SOCKET_HASH_TABLE_SIZE 911 +#endif + +#ifndef CURL_CONNECTION_HASH_SIZE +#define CURL_CONNECTION_HASH_SIZE 97 +#endif + +#define CURL_MULTI_HANDLE 0x000bab1e + +#define GOOD_MULTI_HANDLE(x) \ + ((x) && (x)->type == CURL_MULTI_HANDLE) + +static CURLMcode singlesocket(struct Curl_multi *multi, + struct Curl_easy *data); +static CURLMcode add_next_timeout(struct curltime now, + struct Curl_multi *multi, + struct Curl_easy *d); +static CURLMcode multi_timeout(struct Curl_multi *multi, + long *timeout_ms); +static void process_pending_handles(struct Curl_multi *multi); +static void detach_connnection(struct Curl_easy *data); + +#ifdef DEBUGBUILD +static const char * const statename[]={ + "INIT", + "CONNECT_PEND", + "CONNECT", + "WAITRESOLVE", + "WAITCONNECT", + "WAITPROXYCONNECT", + "SENDPROTOCONNECT", + "PROTOCONNECT", + "DO", + "DOING", + "DO_MORE", + "DO_DONE", + "PERFORM", + "TOOFAST", + "DONE", + "COMPLETED", + "MSGSENT", +}; +#endif + +/* function pointer called once when switching TO a state */ +typedef void (*init_multistate_func)(struct Curl_easy *data); + +static void Curl_init_completed(struct Curl_easy *data) +{ + /* this is a completed transfer */ + + /* Important: reset the conn pointer so that we don't point to memory + that could be freed anytime */ + detach_connnection(data); + Curl_expire_clear(data); /* stop all timers */ +} + +/* always use this function to change state, to make debugging easier */ +static void mstate(struct Curl_easy *data, CURLMstate state +#ifdef DEBUGBUILD + , int lineno +#endif +) +{ + CURLMstate oldstate = data->mstate; + static const init_multistate_func finit[CURLM_STATE_LAST] = { + NULL, /* INIT */ + NULL, /* CONNECT_PEND */ + Curl_init_CONNECT, /* CONNECT */ + NULL, /* WAITRESOLVE */ + NULL, /* WAITCONNECT */ + NULL, /* WAITPROXYCONNECT */ + NULL, /* SENDPROTOCONNECT */ + NULL, /* PROTOCONNECT */ + Curl_connect_free, /* DO */ + NULL, /* DOING */ + NULL, /* DO_MORE */ + NULL, /* DO_DONE */ + NULL, /* PERFORM */ + NULL, /* TOOFAST */ + NULL, /* DONE */ + Curl_init_completed, /* COMPLETED */ + NULL /* MSGSENT */ + }; + +#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) lineno; +#endif + + if(oldstate == state) + /* don't bother when the new state is the same as the old state */ + return; + + data->mstate = state; + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + if(data->mstate >= CURLM_STATE_CONNECT_PEND && + data->mstate < CURLM_STATE_COMPLETED) { + long connection_id = -5000; + + if(data->conn) + connection_id = data->conn->connection_id; + + infof(data, + "STATE: %s => %s handle %p; line %d (connection #%ld)\n", + statename[oldstate], statename[data->mstate], + (void *)data, lineno, connection_id); + } +#endif + + if(state == CURLM_STATE_COMPLETED) + /* changing to COMPLETED means there's one less easy handle 'alive' */ + data->multi->num_alive--; + + /* if this state has an init-function, run it */ + if(finit[state]) + finit[state](data); +} + +#ifndef DEBUGBUILD +#define multistate(x,y) mstate(x,y) +#else +#define multistate(x,y) mstate(x,y, __LINE__) +#endif + +/* + * We add one of these structs to the sockhash for each socket + */ + +struct Curl_sh_entry { + struct curl_hash transfers; /* hash of transfers using this socket */ + unsigned int action; /* what combined action READ/WRITE this socket waits + for */ + void *socketp; /* settable by users with curl_multi_assign() */ + unsigned int users; /* number of transfers using this */ + unsigned int readers; /* this many transfers want to read */ + unsigned int writers; /* this many transfers want to write */ +}; +/* bits for 'action' having no bits means this socket is not expecting any + action */ +#define SH_READ 1 +#define SH_WRITE 2 + +/* look up a given socket in the socket hash, skip invalid sockets */ +static struct Curl_sh_entry *sh_getentry(struct curl_hash *sh, + curl_socket_t s) +{ + if(s != CURL_SOCKET_BAD) { + /* only look for proper sockets */ + return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t)); + } + return NULL; +} + +#define TRHASH_SIZE 13 +static size_t trhash(void *key, size_t key_length, size_t slots_num) +{ + size_t keyval = (size_t)*(struct Curl_easy **)key; + (void) key_length; + + return (keyval % slots_num); +} + +static size_t trhash_compare(void *k1, size_t k1_len, void *k2, size_t k2_len) +{ + (void)k1_len; + (void)k2_len; + + return *(struct Curl_easy **)k1 == *(struct Curl_easy **)k2; +} + +static void trhash_dtor(void *nada) +{ + (void)nada; +} + + +/* make sure this socket is present in the hash for this handle */ +static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh, + curl_socket_t s) +{ + struct Curl_sh_entry *there = sh_getentry(sh, s); + struct Curl_sh_entry *check; + + if(there) { + /* it is present, return fine */ + return there; + } + + /* not present, add it */ + check = calloc(1, sizeof(struct Curl_sh_entry)); + if(!check) + return NULL; /* major failure */ + + if(Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash, + trhash_compare, trhash_dtor)) { + free(check); + return NULL; + } + + /* make/add new hash entry */ + if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) { + free(check); + return NULL; /* major failure */ + } + + return check; /* things are good in sockhash land */ +} + + +/* delete the given socket + handle from the hash */ +static void sh_delentry(struct Curl_sh_entry *entry, + struct curl_hash *sh, curl_socket_t s) +{ + Curl_hash_destroy(&entry->transfers); + + /* We remove the hash entry. This will end up in a call to + sh_freeentry(). */ + Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t)); +} + +/* + * free a sockhash entry + */ +static void sh_freeentry(void *freethis) +{ + struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis; + + free(p); +} + +static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len) +{ + (void) k1_len; (void) k2_len; + + return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2)); +} + +static size_t hash_fd(void *key, size_t key_length, size_t slots_num) +{ + curl_socket_t fd = *((curl_socket_t *) key); + (void) key_length; + + return (fd % slots_num); +} + +/* + * sh_init() creates a new socket hash and returns the handle for it. + * + * Quote from README.multi_socket: + * + * "Some tests at 7000 and 9000 connections showed that the socket hash lookup + * is somewhat of a bottle neck. Its current implementation may be a bit too + * limiting. It simply has a fixed-size array, and on each entry in the array + * it has a linked list with entries. So the hash only checks which list to + * scan through. The code I had used so for used a list with merely 7 slots + * (as that is what the DNS hash uses) but with 7000 connections that would + * make an average of 1000 nodes in each list to run through. I upped that to + * 97 slots (I believe a prime is suitable) and noticed a significant speed + * increase. I need to reconsider the hash implementation or use a rather + * large default value like this. At 9000 connections I was still below 10us + * per call." + * + */ +static int sh_init(struct curl_hash *hash, int hashsize) +{ + return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare, + sh_freeentry); +} + +/* + * multi_addmsg() + * + * Called when a transfer is completed. Adds the given msg pointer to + * the list kept in the multi handle. + */ +static CURLMcode multi_addmsg(struct Curl_multi *multi, + struct Curl_message *msg) +{ + Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg, + &msg->list); + return CURLM_OK; +} + +struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ + int chashsize) /* connection hash */ +{ + struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi)); + + if(!multi) + return NULL; + + multi->type = CURL_MULTI_HANDLE; + + if(Curl_mk_dnscache(&multi->hostcache)) + goto error; + + if(sh_init(&multi->sockhash, hashsize)) + goto error; + + if(Curl_conncache_init(&multi->conn_cache, chashsize)) + goto error; + + Curl_llist_init(&multi->msglist, NULL); + Curl_llist_init(&multi->pending, NULL); + + multi->multiplexing = CURLPIPE_MULTIPLEX; + + /* -1 means it not set by user, use the default value */ + multi->maxconnects = -1; + return multi; + + error: + + Curl_hash_destroy(&multi->sockhash); + Curl_hash_destroy(&multi->hostcache); + Curl_conncache_destroy(&multi->conn_cache); + Curl_llist_destroy(&multi->msglist, NULL); + Curl_llist_destroy(&multi->pending, NULL); + + free(multi); + return NULL; +} + +struct Curl_multi *curl_multi_init(void) +{ + return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE, + CURL_CONNECTION_HASH_SIZE); +} + +CURLMcode curl_multi_add_handle(struct Curl_multi *multi, + struct Curl_easy *data) +{ + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + /* Verify that we got a somewhat good easy handle too */ + if(!GOOD_EASY_HANDLE(data)) + return CURLM_BAD_EASY_HANDLE; + + /* Prevent users from adding same easy handle more than once and prevent + adding to more than one multi stack */ + if(data->multi) + return CURLM_ADDED_ALREADY; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + /* Initialize timeout list for this handle */ + Curl_llist_init(&data->state.timeoutlist, NULL); + + /* + * No failure allowed in this function beyond this point. And no + * modification of easy nor multi handle allowed before this except for + * potential multi's connection cache growing which won't be undone in this + * function no matter what. + */ + if(data->set.errorbuffer) + data->set.errorbuffer[0] = 0; + + /* set the easy handle */ + multistate(data, CURLM_STATE_INIT); + + /* for multi interface connections, we share DNS cache automatically if the + easy handle's one is currently not set. */ + if(!data->dns.hostcache || + (data->dns.hostcachetype == HCACHE_NONE)) { + data->dns.hostcache = &multi->hostcache; + data->dns.hostcachetype = HCACHE_MULTI; + } + + /* Point to the shared or multi handle connection cache */ + if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT))) + data->state.conn_cache = &data->share->conn_cache; + else + data->state.conn_cache = &multi->conn_cache; + +#ifdef USE_LIBPSL + /* Do the same for PSL. */ + if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL))) + data->psl = &data->share->psl; + else + data->psl = &multi->psl; +#endif + + /* We add the new entry last in the list. */ + data->next = NULL; /* end of the line */ + if(multi->easyp) { + struct Curl_easy *last = multi->easylp; + last->next = data; + data->prev = last; + multi->easylp = data; /* the new last node */ + } + else { + /* first node, make prev NULL! */ + data->prev = NULL; + multi->easylp = multi->easyp = data; /* both first and last */ + } + + /* make the Curl_easy refer back to this multi handle */ + data->multi = multi; + + /* Set the timeout for this handle to expire really soon so that it will + be taken care of even when this handle is added in the midst of operation + when only the curl_multi_socket() API is used. During that flow, only + sockets that time-out or have actions will be dealt with. Since this + handle has no action yet, we make sure it times out to get things to + happen. */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + /* increase the node-counter */ + multi->num_easy++; + + /* increase the alive-counter */ + multi->num_alive++; + + /* A somewhat crude work-around for a little glitch in Curl_update_timer() + that happens if the lastcall time is set to the same time when the handle + is removed as when the next handle is added, as then the check in + Curl_update_timer() that prevents calling the application multiple times + with the same timer info will not trigger and then the new handle's + timeout will not be notified to the app. + + The work-around is thus simply to clear the 'lastcall' variable to force + Curl_update_timer() to always trigger a callback to the app when a new + easy handle is added */ + memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); + + /* The closure handle only ever has default timeouts set. To improve the + state somewhat we clone the timeouts from each added handle so that the + closure handle always has the same timeouts as the most recently added + easy handle. */ + data->state.conn_cache->closure_handle->set.timeout = data->set.timeout; + data->state.conn_cache->closure_handle->set.server_response_timeout = + data->set.server_response_timeout; + data->state.conn_cache->closure_handle->set.no_signal = + data->set.no_signal; + + Curl_update_timer(multi); + return CURLM_OK; +} + +#if 0 +/* Debug-function, used like this: + * + * Curl_hash_print(multi->sockhash, debug_print_sock_hash); + * + * Enable the hash print function first by editing hash.c + */ +static void debug_print_sock_hash(void *p) +{ + struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p; + + fprintf(stderr, " [easy %p/magic %x/socket %d]", + (void *)sh->data, sh->data->magic, (int)sh->socket); +} +#endif + +static CURLcode multi_done(struct Curl_easy *data, + CURLcode status, /* an error if this is called + after an error was detected */ + bool premature) +{ + CURLcode result; + struct connectdata *conn = data->conn; + unsigned int i; + + DEBUGF(infof(data, "multi_done\n")); + + if(data->state.done) + /* Stop if multi_done() has already been called */ + return CURLE_OK; + + /* Stop the resolver and free its own resources (but not dns_entry yet). */ + Curl_resolver_kill(conn); + + /* Cleanup possible redirect junk */ + Curl_safefree(data->req.newurl); + Curl_safefree(data->req.location); + + switch(status) { + case CURLE_ABORTED_BY_CALLBACK: + case CURLE_READ_ERROR: + case CURLE_WRITE_ERROR: + /* When we're aborted due to a callback return code it basically have to + be counted as premature as there is trouble ahead if we don't. We have + many callbacks and protocols work differently, we could potentially do + this more fine-grained in the future. */ + premature = TRUE; + default: + break; + } + + /* this calls the protocol-specific function pointer previously set */ + if(conn->handler->done) + result = conn->handler->done(conn, status, premature); + else + result = status; + + if(CURLE_ABORTED_BY_CALLBACK != result) { + /* avoid this if we already aborted by callback to avoid this calling + another callback */ + CURLcode rc = Curl_pgrsDone(conn); + if(!result && rc) + result = CURLE_ABORTED_BY_CALLBACK; + } + + process_pending_handles(data->multi); /* connection / multiplex */ + + detach_connnection(data); + if(CONN_INUSE(conn)) { + /* Stop if still used. */ + DEBUGF(infof(data, "Connection still in use %zu, " + "no more multi_done now!\n", + conn->easyq.size)); + return CURLE_OK; + } + + data->state.done = TRUE; /* called just now! */ + + if(conn->dns_entry) { + Curl_resolv_unlock(data, conn->dns_entry); /* done with this */ + conn->dns_entry = NULL; + } + Curl_hostcache_prune(data); + Curl_safefree(data->state.ulbuf); + + /* if the transfer was completed in a paused state there can be buffered + data left to free */ + for(i = 0; i < data->state.tempcount; i++) { + free(data->state.tempwrite[i].buf); + } + data->state.tempcount = 0; + + /* if data->set.reuse_forbid is TRUE, it means the libcurl client has + forced us to close this connection. This is ignored for requests taking + place in a NTLM/NEGOTIATE authentication handshake + + if conn->bits.close is TRUE, it means that the connection should be + closed in spite of all our efforts to be nice, due to protocol + restrictions in our or the server's end + + if premature is TRUE, it means this connection was said to be DONE before + the entire request operation is complete and thus we can't know in what + state it is for re-using, so we're forced to close it. In a perfect world + we can add code that keep track of if we really must close it here or not, + but currently we have no such detail knowledge. + */ + + if((data->set.reuse_forbid +#if defined(USE_NTLM) + && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 || + conn->proxy_ntlm_state == NTLMSTATE_TYPE2) +#endif +#if defined(USE_SPNEGO) + && !(conn->http_negotiate_state == GSS_AUTHRECV || + conn->proxy_negotiate_state == GSS_AUTHRECV) +#endif + ) || conn->bits.close + || (premature && !(conn->handler->flags & PROTOPT_STREAM))) { + CURLcode res2 = Curl_disconnect(data, conn, premature); + + /* If we had an error already, make sure we return that one. But + if we got a new error, return that. */ + if(!result && res2) + result = res2; + } + else { + char buffer[256]; + /* create string before returning the connection */ + msnprintf(buffer, sizeof(buffer), + "Connection #%ld to host %s left intact", + conn->connection_id, + conn->bits.socksproxy ? conn->socks_proxy.host.dispname : + conn->bits.httpproxy ? conn->http_proxy.host.dispname : + conn->bits.conn_to_host ? conn->conn_to_host.dispname : + conn->host.dispname); + + /* the connection is no longer in use by this transfer */ + if(Curl_conncache_return_conn(conn)) { + /* remember the most recently used connection */ + data->state.lastconnect = conn; + infof(data, "%s\n", buffer); + } + else + data->state.lastconnect = NULL; + } + + Curl_free_request_state(data); + return result; +} + +CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, + struct Curl_easy *data) +{ + struct Curl_easy *easy = data; + bool premature; + bool easy_owns_conn; + struct curl_llist_element *e; + + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + /* Verify that we got a somewhat good easy handle too */ + if(!GOOD_EASY_HANDLE(data)) + return CURLM_BAD_EASY_HANDLE; + + /* Prevent users from trying to remove same easy handle more than once */ + if(!data->multi) + return CURLM_OK; /* it is already removed so let's say it is fine! */ + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE; + easy_owns_conn = (data->conn && (data->conn->data == easy)) ? + TRUE : FALSE; + + /* If the 'state' is not INIT or COMPLETED, we might need to do something + nice to put the easy_handle in a good known state when this returns. */ + if(premature) { + /* this handle is "alive" so we need to count down the total number of + alive connections when this is removed */ + multi->num_alive--; + } + + if(data->conn && + data->mstate > CURLM_STATE_DO && + data->mstate < CURLM_STATE_COMPLETED) { + /* Set connection owner so that the DONE function closes it. We can + safely do this here since connection is killed. */ + data->conn->data = easy; + streamclose(data->conn, "Removed with partial response"); + easy_owns_conn = TRUE; + } + + /* The timer must be shut down before data->multi is set to NULL, + else the timenode will remain in the splay tree after + curl_easy_cleanup is called. */ + Curl_expire_clear(data); + + if(data->conn) { + + /* we must call multi_done() here (if we still own the connection) so that + we don't leave a half-baked one around */ + if(easy_owns_conn) { + + /* multi_done() clears the conn->data field to lose the association + between the easy handle and the connection + + Note that this ignores the return code simply because there's + nothing really useful to do with it anyway! */ + (void)multi_done(data, data->result, premature); + } + } + + if(data->connect_queue.ptr) + /* the handle was in the pending list waiting for an available connection, + so go ahead and remove it */ + Curl_llist_remove(&multi->pending, &data->connect_queue, NULL); + + if(data->dns.hostcachetype == HCACHE_MULTI) { + /* stop using the multi handle's DNS cache, *after* the possible + multi_done() call above */ + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + + Curl_wildcard_dtor(&data->wildcard); + + /* destroy the timeout list that is held in the easy handle, do this *after* + multi_done() as that may actually call Curl_expire that uses this */ + Curl_llist_destroy(&data->state.timeoutlist, NULL); + + /* as this was using a shared connection cache we clear the pointer to that + since we're not part of that multi handle anymore */ + data->state.conn_cache = NULL; + + /* change state without using multistate(), only to make singlesocket() do + what we want */ + data->mstate = CURLM_STATE_COMPLETED; + singlesocket(multi, easy); /* to let the application know what sockets that + vanish with this handle */ + + /* Remove the association between the connection and the handle */ + if(data->conn) { + data->conn->data = NULL; + detach_connnection(data); + } + +#ifdef USE_LIBPSL + /* Remove the PSL association. */ + if(data->psl == &multi->psl) + data->psl = NULL; +#endif + + data->multi = NULL; /* clear the association to this multi handle */ + + /* make sure there's no pending message in the queue sent from this easy + handle */ + + for(e = multi->msglist.head; e; e = e->next) { + struct Curl_message *msg = e->ptr; + + if(msg->extmsg.easy_handle == easy) { + Curl_llist_remove(&multi->msglist, e, NULL); + /* there can only be one from this specific handle */ + break; + } + } + + /* make the previous node point to our next */ + if(data->prev) + data->prev->next = data->next; + else + multi->easyp = data->next; /* point to first node */ + + /* make our next point to our previous node */ + if(data->next) + data->next->prev = data->prev; + else + multi->easylp = data->prev; /* point to last node */ + + /* NOTE NOTE NOTE + We do not touch the easy handle here! */ + multi->num_easy--; /* one less to care about now */ + + Curl_update_timer(multi); + return CURLM_OK; +} + +/* Return TRUE if the application asked for multiplexing */ +bool Curl_multiplex_wanted(const struct Curl_multi *multi) +{ + return (multi && (multi->multiplexing)); +} + +/* This is the only function that should clear data->conn. This will + occasionally be called with the pointer already cleared. */ +static void detach_connnection(struct Curl_easy *data) +{ + struct connectdata *conn = data->conn; + if(conn) + Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL); + data->conn = NULL; +} + +/* This is the only function that should assign data->conn */ +void Curl_attach_connnection(struct Curl_easy *data, + struct connectdata *conn) +{ + DEBUGASSERT(!data->conn); + DEBUGASSERT(conn); + data->conn = conn; + Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data, + &data->conn_queue); +} + +static int waitconnect_getsock(struct connectdata *conn, + curl_socket_t *sock, + int numsocks) +{ + int i; + int s = 0; + int rc = 0; + + if(!numsocks) + return GETSOCK_BLANK; + +#ifdef USE_SSL + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + return Curl_ssl_getsock(conn, sock, numsocks); +#endif + + for(i = 0; i<2; i++) { + if(conn->tempsock[i] != CURL_SOCKET_BAD) { + sock[s] = conn->tempsock[i]; + rc |= GETSOCK_WRITESOCK(s++); + } + } + + return rc; +} + +static int waitproxyconnect_getsock(struct connectdata *conn, + curl_socket_t *sock, + int numsocks) +{ + if(!numsocks) + return GETSOCK_BLANK; + + sock[0] = conn->sock[FIRSTSOCKET]; + + /* when we've sent a CONNECT to a proxy, we should rather wait for the + socket to become readable to be able to get the response headers */ + if(conn->connect_state) + return GETSOCK_READSOCK(0); + + return GETSOCK_WRITESOCK(0); +} + +static int domore_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn && conn->handler->domore_getsock) + return conn->handler->domore_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} + +/* returns bitmapped flags for this handle and its sockets */ +static int multi_getsock(struct Curl_easy *data, + curl_socket_t *socks, /* points to numsocks number + of sockets */ + int numsocks) +{ + /* The no connection case can happen when this is called from + curl_multi_remove_handle() => singlesocket() => multi_getsock(). + */ + if(!data->conn) + return 0; + + if(data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_COMPLETED) { + /* Set up ownership correctly */ + data->conn->data = data; + } + + switch(data->mstate) { + default: +#if 0 /* switch back on these cases to get the compiler to check for all enums + to be present */ + case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */ + case CURLM_STATE_COMPLETED: + case CURLM_STATE_MSGSENT: + case CURLM_STATE_INIT: + case CURLM_STATE_CONNECT: + case CURLM_STATE_WAITDO: + case CURLM_STATE_DONE: + case CURLM_STATE_LAST: + /* this will get called with CURLM_STATE_COMPLETED when a handle is + removed */ +#endif + return 0; + + case CURLM_STATE_WAITRESOLVE: + return Curl_resolv_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_PROTOCONNECT: + case CURLM_STATE_SENDPROTOCONNECT: + return Curl_protocol_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_DO: + case CURLM_STATE_DOING: + return Curl_doing_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_WAITPROXYCONNECT: + return waitproxyconnect_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_WAITCONNECT: + return waitconnect_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_DO_MORE: + return domore_getsock(data->conn, socks, numsocks); + + case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch + to waiting for the same as the *PERFORM + states */ + case CURLM_STATE_PERFORM: + return Curl_single_getsock(data->conn, socks, numsocks); + } + +} + +CURLMcode curl_multi_fdset(struct Curl_multi *multi, + fd_set *read_fd_set, fd_set *write_fd_set, + fd_set *exc_fd_set, int *max_fd) +{ + /* Scan through all the easy handles to get the file descriptors set. + Some easy handles may not have connected to the remote host yet, + and then we must make sure that is done. */ + struct Curl_easy *data; + int this_max_fd = -1; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int i; + (void)exc_fd_set; /* not used */ + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + data = multi->easyp; + while(data) { + int bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) { + FD_SET(sockbunch[i], read_fd_set); + s = sockbunch[i]; + } + if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) { + FD_SET(sockbunch[i], write_fd_set); + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) + /* this socket is unused, break out of loop */ + break; + if((int)s > this_max_fd) + this_max_fd = (int)s; + } + + data = data->next; /* check next handle */ + } + + *max_fd = this_max_fd; + + return CURLM_OK; +} + +#define NUM_POLLS_ON_STACK 10 + +CURLMcode Curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret, + bool *gotsocket) /* if any socket was checked */ +{ + struct Curl_easy *data; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int bitmap; + unsigned int i; + unsigned int nfds = 0; + unsigned int curlfds; + bool ufds_malloc = FALSE; + long timeout_internal; + int retcode = 0; + struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; + struct pollfd *ufds = &a_few_on_stack[0]; + + if(gotsocket) + *gotsocket = FALSE; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + /* Count up how many fds we have from the multi handle */ + data = multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if(bitmap & GETSOCK_READSOCK(i)) { + ++nfds; + s = sockbunch[i]; + } + if(bitmap & GETSOCK_WRITESOCK(i)) { + ++nfds; + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) { + break; + } + } + + data = data->next; /* check next handle */ + } + + /* If the internally desired timeout is actually shorter than requested from + the outside, then use the shorter time! But only if the internal timer + is actually larger than -1! */ + (void)multi_timeout(multi, &timeout_internal); + if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms)) + timeout_ms = (int)timeout_internal; + + curlfds = nfds; /* number of internal file descriptors */ + nfds += extra_nfds; /* add the externally provided ones */ + + if(nfds > NUM_POLLS_ON_STACK) { + /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes + big, so at 2^29 sockets this value might wrap. When a process gets + the capability to actually handle over 500 million sockets this + calculation needs a integer overflow check. */ + ufds = malloc(nfds * sizeof(struct pollfd)); + if(!ufds) + return CURLM_OUT_OF_MEMORY; + ufds_malloc = TRUE; + } + nfds = 0; + + /* only do the second loop if we found descriptors in the first stage run + above */ + + if(curlfds) { + /* Add the curl handles to our pollfds first */ + data = multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE); + + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { + curl_socket_t s = CURL_SOCKET_BAD; + + if(bitmap & GETSOCK_READSOCK(i)) { + ufds[nfds].fd = sockbunch[i]; + ufds[nfds].events = POLLIN; + ++nfds; + s = sockbunch[i]; + } + if(bitmap & GETSOCK_WRITESOCK(i)) { + ufds[nfds].fd = sockbunch[i]; + ufds[nfds].events = POLLOUT; + ++nfds; + s = sockbunch[i]; + } + if(s == CURL_SOCKET_BAD) { + break; + } + } + + data = data->next; /* check next handle */ + } + } + + /* Add external file descriptions from poll-like struct curl_waitfd */ + for(i = 0; i < extra_nfds; i++) { + ufds[nfds].fd = extra_fds[i].fd; + ufds[nfds].events = 0; + if(extra_fds[i].events & CURL_WAIT_POLLIN) + ufds[nfds].events |= POLLIN; + if(extra_fds[i].events & CURL_WAIT_POLLPRI) + ufds[nfds].events |= POLLPRI; + if(extra_fds[i].events & CURL_WAIT_POLLOUT) + ufds[nfds].events |= POLLOUT; + ++nfds; + } + + if(nfds) { + int pollrc; + /* wait... */ + pollrc = Curl_poll(ufds, nfds, timeout_ms); + + if(pollrc > 0) { + retcode = pollrc; + /* copy revents results from the poll to the curl_multi_wait poll + struct, the bit values of the actual underlying poll() implementation + may not be the same as the ones in the public libcurl API! */ + for(i = 0; i < extra_nfds; i++) { + unsigned short mask = 0; + unsigned r = ufds[curlfds + i].revents; + + if(r & POLLIN) + mask |= CURL_WAIT_POLLIN; + if(r & POLLOUT) + mask |= CURL_WAIT_POLLOUT; + if(r & POLLPRI) + mask |= CURL_WAIT_POLLPRI; + + extra_fds[i].revents = mask; + } + } + } + + if(ufds_malloc) + free(ufds); + if(ret) + *ret = retcode; + if(gotsocket && (extra_fds || curlfds)) + /* if any socket was checked */ + *gotsocket = TRUE; + + return CURLM_OK; +} + +CURLMcode curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret) +{ + return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, NULL); +} + +/* + * multi_ischanged() is called + * + * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND + * => CONNECT action. + * + * Set 'clear' to TRUE to have it also clear the state variable. + */ +static bool multi_ischanged(struct Curl_multi *multi, bool clear) +{ + bool retval = multi->recheckstate; + if(clear) + multi->recheckstate = FALSE; + return retval; +} + +CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, + struct Curl_easy *data, + struct connectdata *conn) +{ + CURLMcode rc; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + rc = curl_multi_add_handle(multi, data); + if(!rc) { + struct SingleRequest *k = &data->req; + + /* pass in NULL for 'conn' here since we don't want to init the + connection, only this transfer */ + Curl_init_do(data, NULL); + + /* take this handle to the perform state right away */ + multistate(data, CURLM_STATE_PERFORM); + Curl_attach_connnection(data, conn); + k->keepon |= KEEP_RECV; /* setup to receive! */ + } + return rc; +} + +/* + * do_complete is called when the DO actions are complete. + * + * We init chunking and trailer bits to their default values here immediately + * before receiving any header data for the current request. + */ +static void do_complete(struct connectdata *conn) +{ + conn->data->req.chunk = FALSE; + Curl_pgrsTime(conn->data, TIMER_PRETRANSFER); +} + +static CURLcode multi_do(struct Curl_easy *data, bool *done) +{ + CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->handler); + + if(conn->handler->do_it) { + /* generic protocol-specific function pointer set in curl_connect() */ + result = conn->handler->do_it(conn, done); + + if(!result && *done) + /* do_complete must be called after the protocol-specific DO function */ + do_complete(conn); + } + return result; +} + +/* + * multi_do_more() is called during the DO_MORE multi state. It is basically a + * second stage DO state which (wrongly) was introduced to support FTP's + * second connection. + * + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to + * DOING state there's more work to do! + */ + +static CURLcode multi_do_more(struct connectdata *conn, int *complete) +{ + CURLcode result = CURLE_OK; + + *complete = 0; + + if(conn->handler->do_more) + result = conn->handler->do_more(conn, complete); + + if(!result && (*complete == 1)) + /* do_complete must be called after the protocol-specific DO function */ + do_complete(conn); + + return result; +} + +static CURLMcode multi_runsingle(struct Curl_multi *multi, + struct curltime now, + struct Curl_easy *data) +{ + struct Curl_message *msg = NULL; + bool connected; + bool async; + bool protocol_connect = FALSE; + bool dophase_done = FALSE; + bool done = FALSE; + CURLMcode rc; + CURLcode result = CURLE_OK; + timediff_t timeout_ms; + timediff_t recv_timeout_ms; + timediff_t send_timeout_ms; + int control; + + if(!GOOD_EASY_HANDLE(data)) + return CURLM_BAD_EASY_HANDLE; + + do { + /* A "stream" here is a logical stream if the protocol can handle that + (HTTP/2), or the full connection for older protocols */ + bool stream_error = FALSE; + rc = CURLM_OK; + + DEBUGASSERT((data->mstate <= CURLM_STATE_CONNECT) || + (data->mstate >= CURLM_STATE_DONE) || + data->conn); + if(!data->conn && + data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_DONE) { + /* In all these states, the code will blindly access 'data->conn' + so this is precaution that it isn't NULL. And it silences static + analyzers. */ + failf(data, "In state %d with no conn, bail out!\n", data->mstate); + return CURLM_INTERNAL_ERROR; + } + + if(multi_ischanged(multi, TRUE)) { + DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n")); + process_pending_handles(multi); /* multiplexed */ + } + + if(data->conn && data->mstate > CURLM_STATE_CONNECT && + data->mstate < CURLM_STATE_COMPLETED) { + /* Make sure we set the connection's current owner */ + data->conn->data = data; + } + + if(data->conn && + (data->mstate >= CURLM_STATE_CONNECT) && + (data->mstate < CURLM_STATE_COMPLETED)) { + /* we need to wait for the connect state as only then is the start time + stored, but we must not check already completed handles */ + timeout_ms = Curl_timeleft(data, &now, + (data->mstate <= CURLM_STATE_DO)? + TRUE:FALSE); + + if(timeout_ms < 0) { + /* Handle timed out */ + if(data->mstate == CURLM_STATE_WAITRESOLVE) + failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds", + Curl_timediff(now, data->progress.t_startsingle)); + else if(data->mstate == CURLM_STATE_WAITCONNECT) + failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds", + Curl_timediff(now, data->progress.t_startsingle)); + else { + struct SingleRequest *k = &data->req; + if(k->size != -1) { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_timediff(now, data->progress.t_startsingle), + k->bytecount, k->size); + } + else { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T + " bytes received", + Curl_timediff(now, data->progress.t_startsingle), + k->bytecount); + } + } + + /* Force connection closed if the connection has indeed been used */ + if(data->mstate > CURLM_STATE_DO) { + streamclose(data->conn, "Disconnected with pending data"); + stream_error = TRUE; + } + result = CURLE_OPERATION_TIMEDOUT; + (void)multi_done(data, result, TRUE); + /* Skip the statemachine and go directly to error handling section. */ + goto statemachine_end; + } + } + + switch(data->mstate) { + case CURLM_STATE_INIT: + /* init this transfer. */ + result = Curl_pretransfer(data); + + if(!result) { + /* after init, go CONNECT */ + multistate(data, CURLM_STATE_CONNECT); + Curl_pgrsTime(data, TIMER_STARTOP); + rc = CURLM_CALL_MULTI_PERFORM; + } + break; + + case CURLM_STATE_CONNECT_PEND: + /* We will stay here until there is a connection available. Then + we try again in the CURLM_STATE_CONNECT state. */ + break; + + case CURLM_STATE_CONNECT: + /* Connect. We want to get a connection identifier filled in. */ + Curl_pgrsTime(data, TIMER_STARTSINGLE); + if(data->set.timeout) + Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT); + + if(data->set.connecttimeout) + Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT); + + result = Curl_connect(data, &async, &protocol_connect); + if(CURLE_NO_CONNECTION_AVAILABLE == result) { + /* There was no connection available. We will go to the pending + state and wait for an available connection. */ + multistate(data, CURLM_STATE_CONNECT_PEND); + + /* add this handle to the list of connect-pending handles */ + Curl_llist_insert_next(&multi->pending, multi->pending.tail, data, + &data->connect_queue); + result = CURLE_OK; + break; + } + else if(data->state.previouslypending) { + /* this transfer comes from the pending queue so try move another */ + infof(data, "Transfer was pending, now try another\n"); + process_pending_handles(data->multi); + } + + if(!result) { + if(async) + /* We're now waiting for an asynchronous name lookup */ + multistate(data, CURLM_STATE_WAITRESOLVE); + else { + /* after the connect has been sent off, go WAITCONNECT unless the + protocol connect is already done and we can go directly to + WAITDO or DO! */ + rc = CURLM_CALL_MULTI_PERFORM; + + if(protocol_connect) + multistate(data, CURLM_STATE_DO); + else { +#ifndef CURL_DISABLE_HTTP + if(Curl_connect_ongoing(data->conn)) + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + else +#endif + multistate(data, CURLM_STATE_WAITCONNECT); + } + } + } + break; + + case CURLM_STATE_WAITRESOLVE: + /* awaiting an asynch name resolve to complete */ + { + struct Curl_dns_entry *dns = NULL; + struct connectdata *conn = data->conn; + const char *hostname; + + DEBUGASSERT(conn); + if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; + else if(conn->bits.conn_to_host) + hostname = conn->conn_to_host.name; + else + hostname = conn->host.name; + + /* check if we have the name resolved by now */ + dns = Curl_fetch_addr(conn, hostname, (int)conn->port); + + if(dns) { +#ifdef CURLRES_ASYNCH + conn->async.dns = dns; + conn->async.done = TRUE; +#endif + result = CURLE_OK; + infof(data, "Hostname '%s' was found in DNS cache\n", hostname); + } + + if(!dns) + result = Curl_resolv_check(data->conn, &dns); + + /* Update sockets here, because the socket(s) may have been + closed and the application thus needs to be told, even if it + is likely that the same socket(s) will again be used further + down. If the name has not yet been resolved, it is likely + that new sockets have been opened in an attempt to contact + another resolver. */ + singlesocket(multi, data); + + if(dns) { + /* Perform the next step in the connection phase, and then move on + to the WAITCONNECT state */ + result = Curl_once_resolved(data->conn, &protocol_connect); + + if(result) + /* if Curl_once_resolved() returns failure, the connection struct + is already freed and gone */ + data->conn = NULL; /* no more connection */ + else { + /* call again please so that we get the next socket setup */ + rc = CURLM_CALL_MULTI_PERFORM; + if(protocol_connect) + multistate(data, CURLM_STATE_DO); + else { +#ifndef CURL_DISABLE_HTTP + if(Curl_connect_ongoing(data->conn)) + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + else +#endif + multistate(data, CURLM_STATE_WAITCONNECT); + } + } + } + + if(result) { + /* failure detected */ + stream_error = TRUE; + break; + } + } + break; + +#ifndef CURL_DISABLE_HTTP + case CURLM_STATE_WAITPROXYCONNECT: + /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ + DEBUGASSERT(data->conn); + result = Curl_http_connect(data->conn, &protocol_connect); + + if(data->conn->bits.proxy_connect_closed) { + rc = CURLM_CALL_MULTI_PERFORM; + /* connect back to proxy again */ + result = CURLE_OK; + multi_done(data, CURLE_OK, FALSE); + multistate(data, CURLM_STATE_CONNECT); + } + else if(!result) { + if((data->conn->http_proxy.proxytype != CURLPROXY_HTTPS || + data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) && + Curl_connect_complete(data->conn)) { + rc = CURLM_CALL_MULTI_PERFORM; + /* initiate protocol connect phase */ + multistate(data, CURLM_STATE_SENDPROTOCONNECT); + } + } + else if(result) + stream_error = TRUE; + break; +#endif + + case CURLM_STATE_WAITCONNECT: + /* awaiting a completion of an asynch TCP connect */ + DEBUGASSERT(data->conn); + result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected); + if(connected && !result) { +#ifndef CURL_DISABLE_HTTP + if((data->conn->http_proxy.proxytype == CURLPROXY_HTTPS && + !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) || + Curl_connect_ongoing(data->conn)) { + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + break; + } +#endif + rc = CURLM_CALL_MULTI_PERFORM; + multistate(data, data->conn->bits.tunnel_proxy? + CURLM_STATE_WAITPROXYCONNECT: + CURLM_STATE_SENDPROTOCONNECT); + } + else if(result) { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, TRUE); + stream_error = TRUE; + break; + } + break; + + case CURLM_STATE_SENDPROTOCONNECT: + result = Curl_protocol_connect(data->conn, &protocol_connect); + if(!result && !protocol_connect) + /* switch to waiting state */ + multistate(data, CURLM_STATE_PROTOCONNECT); + else if(!result) { + /* protocol connect has completed, go WAITDO or DO */ + multistate(data, CURLM_STATE_DO); + rc = CURLM_CALL_MULTI_PERFORM; + } + else if(result) { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, TRUE); + stream_error = TRUE; + } + break; + + case CURLM_STATE_PROTOCONNECT: + /* protocol-specific connect phase */ + result = Curl_protocol_connecting(data->conn, &protocol_connect); + if(!result && protocol_connect) { + /* after the connect has completed, go WAITDO or DO */ + multistate(data, CURLM_STATE_DO); + rc = CURLM_CALL_MULTI_PERFORM; + } + else if(result) { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, TRUE); + stream_error = TRUE; + } + break; + + case CURLM_STATE_DO: + if(data->set.connect_only) { + /* keep connection open for application to use the socket */ + connkeep(data->conn, "CONNECT_ONLY"); + multistate(data, CURLM_STATE_DONE); + result = CURLE_OK; + rc = CURLM_CALL_MULTI_PERFORM; + } + else { + /* Perform the protocol's DO action */ + result = multi_do(data, &dophase_done); + + /* When multi_do() returns failure, data->conn might be NULL! */ + + if(!result) { + if(!dophase_done) { +#ifndef CURL_DISABLE_FTP + /* some steps needed for wildcard matching */ + if(data->state.wildcardmatch) { + struct WildcardData *wc = &data->wildcard; + if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) { + /* skip some states if it is important */ + multi_done(data, CURLE_OK, FALSE); + multistate(data, CURLM_STATE_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + break; + } + } +#endif + /* DO was not completed in one function call, we must continue + DOING... */ + multistate(data, CURLM_STATE_DOING); + rc = CURLM_OK; + } + + /* after DO, go DO_DONE... or DO_MORE */ + else if(data->conn->bits.do_more) { + /* we're supposed to do more, but we need to sit down, relax + and wait a little while first */ + multistate(data, CURLM_STATE_DO_MORE); + rc = CURLM_OK; + } + else { + /* we're done with the DO, now DO_DONE */ + multistate(data, CURLM_STATE_DO_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + else if((CURLE_SEND_ERROR == result) && + data->conn->bits.reuse) { + /* + * In this situation, a connection that we were trying to use + * may have unexpectedly died. If possible, send the connection + * back to the CONNECT phase so we can try again. + */ + char *newurl = NULL; + followtype follow = FOLLOW_NONE; + CURLcode drc; + + drc = Curl_retry_request(data->conn, &newurl); + if(drc) { + /* a failure here pretty much implies an out of memory */ + result = drc; + stream_error = TRUE; + } + + Curl_posttransfer(data); + drc = multi_done(data, result, FALSE); + + /* When set to retry the connection, we must to go back to + * the CONNECT state */ + if(newurl) { + if(!drc || (drc == CURLE_SEND_ERROR)) { + follow = FOLLOW_RETRY; + drc = Curl_follow(data, newurl, follow); + if(!drc) { + multistate(data, CURLM_STATE_CONNECT); + rc = CURLM_CALL_MULTI_PERFORM; + result = CURLE_OK; + } + else { + /* Follow failed */ + result = drc; + } + } + else { + /* done didn't return OK or SEND_ERROR */ + result = drc; + } + } + else { + /* Have error handler disconnect conn if we can't retry */ + stream_error = TRUE; + } + free(newurl); + } + else { + /* failure detected */ + Curl_posttransfer(data); + if(data->conn) + multi_done(data, result, FALSE); + stream_error = TRUE; + } + } + break; + + case CURLM_STATE_DOING: + /* we continue DOING until the DO phase is complete */ + DEBUGASSERT(data->conn); + result = Curl_protocol_doing(data->conn, + &dophase_done); + if(!result) { + if(dophase_done) { + /* after DO, go DO_DONE or DO_MORE */ + multistate(data, data->conn->bits.do_more? + CURLM_STATE_DO_MORE: + CURLM_STATE_DO_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } /* dophase_done */ + } + else { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, FALSE); + stream_error = TRUE; + } + break; + + case CURLM_STATE_DO_MORE: + /* + * When we are connected, DO MORE and then go DO_DONE + */ + DEBUGASSERT(data->conn); + result = multi_do_more(data->conn, &control); + + if(!result) { + if(control) { + /* if positive, advance to DO_DONE + if negative, go back to DOING */ + multistate(data, control == 1? + CURLM_STATE_DO_DONE: + CURLM_STATE_DOING); + rc = CURLM_CALL_MULTI_PERFORM; + } + else + /* stay in DO_MORE */ + rc = CURLM_OK; + } + else { + /* failure detected */ + Curl_posttransfer(data); + multi_done(data, result, FALSE); + stream_error = TRUE; + } + break; + + case CURLM_STATE_DO_DONE: + DEBUGASSERT(data->conn); + if(data->conn->bits.multiplex) + /* Check if we can move pending requests to send pipe */ + process_pending_handles(multi); /* multiplexed */ + + /* Only perform the transfer if there's a good socket to work with. + Having both BAD is a signal to skip immediately to DONE */ + if((data->conn->sockfd != CURL_SOCKET_BAD) || + (data->conn->writesockfd != CURL_SOCKET_BAD)) + multistate(data, CURLM_STATE_PERFORM); + else { +#ifndef CURL_DISABLE_FTP + if(data->state.wildcardmatch && + ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) { + data->wildcard.state = CURLWC_DONE; + } +#endif + multistate(data, CURLM_STATE_DONE); + } + rc = CURLM_CALL_MULTI_PERFORM; + break; + + case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */ + DEBUGASSERT(data->conn); + /* if both rates are within spec, resume transfer */ + if(Curl_pgrsUpdate(data->conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, now); + + if(!result) { + send_timeout_ms = 0; + if(data->set.max_send_speed > 0) + send_timeout_ms = + Curl_pgrsLimitWaitTime(data->progress.uploaded, + data->progress.ul_limit_size, + data->set.max_send_speed, + data->progress.ul_limit_start, + now); + + recv_timeout_ms = 0; + if(data->set.max_recv_speed > 0) + recv_timeout_ms = + Curl_pgrsLimitWaitTime(data->progress.downloaded, + data->progress.dl_limit_size, + data->set.max_recv_speed, + data->progress.dl_limit_start, + now); + + if(!send_timeout_ms && !recv_timeout_ms) { + multistate(data, CURLM_STATE_PERFORM); + Curl_ratelimit(data, now); + } + else if(send_timeout_ms >= recv_timeout_ms) + Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); + else + Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST); + } + break; + + case CURLM_STATE_PERFORM: + { + char *newurl = NULL; + bool retry = FALSE; + bool comeback = FALSE; + + /* check if over send speed */ + send_timeout_ms = 0; + if(data->set.max_send_speed > 0) + send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded, + data->progress.ul_limit_size, + data->set.max_send_speed, + data->progress.ul_limit_start, + now); + + /* check if over recv speed */ + recv_timeout_ms = 0; + if(data->set.max_recv_speed > 0) + recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded, + data->progress.dl_limit_size, + data->set.max_recv_speed, + data->progress.dl_limit_start, + now); + + if(send_timeout_ms || recv_timeout_ms) { + Curl_ratelimit(data, now); + multistate(data, CURLM_STATE_TOOFAST); + if(send_timeout_ms >= recv_timeout_ms) + Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); + else + Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST); + break; + } + + /* read/write data if it is ready to do so */ + result = Curl_readwrite(data->conn, data, &done, &comeback); + + if(done || (result == CURLE_RECV_ERROR)) { + /* If CURLE_RECV_ERROR happens early enough, we assume it was a race + * condition and the server closed the re-used connection exactly when + * we wanted to use it, so figure out if that is indeed the case. + */ + CURLcode ret = Curl_retry_request(data->conn, &newurl); + if(!ret) + retry = (newurl)?TRUE:FALSE; + else if(!result) + result = ret; + + if(retry) { + /* if we are to retry, set the result to OK and consider the + request as done */ + result = CURLE_OK; + done = TRUE; + } + } + else if((CURLE_HTTP2_STREAM == result) && + Curl_h2_http_1_1_error(data->conn)) { + CURLcode ret = Curl_retry_request(data->conn, &newurl); + + if(!ret) { + infof(data, "Downgrades to HTTP/1.1!\n"); + data->set.httpversion = CURL_HTTP_VERSION_1_1; + /* clear the error message bit too as we ignore the one we got */ + data->state.errorbuf = FALSE; + if(!newurl) + /* typically for HTTP_1_1_REQUIRED error on first flight */ + newurl = strdup(data->change.url); + /* if we are to retry, set the result to OK and consider the request + as done */ + retry = TRUE; + result = CURLE_OK; + done = TRUE; + } + else + result = ret; + } + + if(result) { + /* + * The transfer phase returned error, we mark the connection to get + * closed to prevent being re-used. This is because we can't possibly + * know if the connection is in a good shape or not now. Unless it is + * a protocol which uses two "channels" like FTP, as then the error + * happened in the data connection. + */ + + if(!(data->conn->handler->flags & PROTOPT_DUAL) && + result != CURLE_HTTP2_STREAM) + streamclose(data->conn, "Transfer returned error"); + + Curl_posttransfer(data); + multi_done(data, result, TRUE); + } + else if(done) { + followtype follow = FOLLOW_NONE; + + /* call this even if the readwrite function returned error */ + Curl_posttransfer(data); + + /* When we follow redirects or is set to retry the connection, we must + to go back to the CONNECT state */ + if(data->req.newurl || retry) { + if(!retry) { + /* if the URL is a follow-location and not just a retried request + then figure out the URL here */ + free(newurl); + newurl = data->req.newurl; + data->req.newurl = NULL; + follow = FOLLOW_REDIR; + } + else + follow = FOLLOW_RETRY; + (void)multi_done(data, CURLE_OK, FALSE); + /* multi_done() might return CURLE_GOT_NOTHING */ + result = Curl_follow(data, newurl, follow); + if(!result) { + multistate(data, CURLM_STATE_CONNECT); + rc = CURLM_CALL_MULTI_PERFORM; + } + free(newurl); + } + else { + /* after the transfer is done, go DONE */ + + /* but first check to see if we got a location info even though we're + not following redirects */ + if(data->req.location) { + free(newurl); + newurl = data->req.location; + data->req.location = NULL; + result = Curl_follow(data, newurl, FOLLOW_FAKE); + free(newurl); + if(result) { + stream_error = TRUE; + result = multi_done(data, result, TRUE); + } + } + + if(!result) { + multistate(data, CURLM_STATE_DONE); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + } + else if(comeback) + rc = CURLM_CALL_MULTI_PERFORM; + break; + } + + case CURLM_STATE_DONE: + /* this state is highly transient, so run another loop after this */ + rc = CURLM_CALL_MULTI_PERFORM; + + if(data->conn) { + CURLcode res; + + if(data->conn->bits.multiplex) + /* Check if we can move pending requests to connection */ + process_pending_handles(multi); /* multiplexing */ + + /* post-transfer command */ + res = multi_done(data, result, FALSE); + + /* allow a previously set error code take precedence */ + if(!result) + result = res; + + /* + * If there are other handles on the connection, multi_done won't set + * conn to NULL. In such a case, curl_multi_remove_handle() can + * access free'd data, if the connection is free'd and the handle + * removed before we perform the processing in CURLM_STATE_COMPLETED + */ + if(data->conn) + detach_connnection(data); + } + +#ifndef CURL_DISABLE_FTP + if(data->state.wildcardmatch) { + if(data->wildcard.state != CURLWC_DONE) { + /* if a wildcard is set and we are not ending -> lets start again + with CURLM_STATE_INIT */ + multistate(data, CURLM_STATE_INIT); + break; + } + } +#endif + /* after we have DONE what we're supposed to do, go COMPLETED, and + it doesn't matter what the multi_done() returned! */ + multistate(data, CURLM_STATE_COMPLETED); + break; + + case CURLM_STATE_COMPLETED: + break; + + case CURLM_STATE_MSGSENT: + data->result = result; + return CURLM_OK; /* do nothing */ + + default: + return CURLM_INTERNAL_ERROR; + } + statemachine_end: + + if(data->mstate < CURLM_STATE_COMPLETED) { + if(result) { + /* + * If an error was returned, and we aren't in completed state now, + * then we go to completed and consider this transfer aborted. + */ + + /* NOTE: no attempt to disconnect connections must be made + in the case blocks above - cleanup happens only here */ + + /* Check if we can move pending requests to send pipe */ + process_pending_handles(multi); /* connection */ + + if(data->conn) { + if(stream_error) { + /* Don't attempt to send data over a connection that timed out */ + bool dead_connection = result == CURLE_OPERATION_TIMEDOUT; + /* disconnect properly */ + Curl_disconnect(data, data->conn, dead_connection); + + /* This is where we make sure that the conn pointer is reset. + We don't have to do this in every case block above where a + failure is detected */ + detach_connnection(data); + } + } + else if(data->mstate == CURLM_STATE_CONNECT) { + /* Curl_connect() failed */ + (void)Curl_posttransfer(data); + } + + multistate(data, CURLM_STATE_COMPLETED); + rc = CURLM_CALL_MULTI_PERFORM; + } + /* if there's still a connection to use, call the progress function */ + else if(data->conn && Curl_pgrsUpdate(data->conn)) { + /* aborted due to progress callback return code must close the + connection */ + result = CURLE_ABORTED_BY_CALLBACK; + streamclose(data->conn, "Aborted by callback"); + + /* if not yet in DONE state, go there, otherwise COMPLETED */ + multistate(data, (data->mstate < CURLM_STATE_DONE)? + CURLM_STATE_DONE: CURLM_STATE_COMPLETED); + rc = CURLM_CALL_MULTI_PERFORM; + } + } + + if(CURLM_STATE_COMPLETED == data->mstate) { + if(data->set.fmultidone) { + /* signal via callback instead */ + data->set.fmultidone(data, result); + } + else { + /* now fill in the Curl_message with this info */ + msg = &data->msg; + + msg->extmsg.msg = CURLMSG_DONE; + msg->extmsg.easy_handle = data; + msg->extmsg.data.result = result; + + rc = multi_addmsg(multi, msg); + DEBUGASSERT(!data->conn); + } + multistate(data, CURLM_STATE_MSGSENT); + } + } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE)); + + data->result = result; + return rc; +} + + +CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) +{ + struct Curl_easy *data; + CURLMcode returncode = CURLM_OK; + struct Curl_tree *t; + struct curltime now = Curl_now(); + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + data = multi->easyp; + while(data) { + CURLMcode result; + SIGPIPE_VARIABLE(pipe_st); + + sigpipe_ignore(data, &pipe_st); + result = multi_runsingle(multi, now, data); + sigpipe_restore(&pipe_st); + + if(result) + returncode = result; + + data = data->next; /* operate on next handle */ + } + + /* + * Simply remove all expired timers from the splay since handles are dealt + * with unconditionally by this function and curl_multi_timeout() requires + * that already passed/handled expire times are removed from the splay. + * + * It is important that the 'now' value is set at the entry of this function + * and not for the current time as it may have ticked a little while since + * then and then we risk this loop to remove timers that actually have not + * been handled! + */ + do { + multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); + if(t) + /* the removed may have another timeout in queue */ + (void)add_next_timeout(now, multi, t->payload); + + } while(t); + + *running_handles = multi->num_alive; + + if(CURLM_OK >= returncode) + Curl_update_timer(multi); + + return returncode; +} + +CURLMcode curl_multi_cleanup(struct Curl_multi *multi) +{ + struct Curl_easy *data; + struct Curl_easy *nextdata; + + if(GOOD_MULTI_HANDLE(multi)) { + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + multi->type = 0; /* not good anymore */ + + /* Firsrt remove all remaining easy handles */ + data = multi->easyp; + while(data) { + nextdata = data->next; + if(!data->state.done && data->conn) + /* if DONE was never called for this handle */ + (void)multi_done(data, CURLE_OK, TRUE); + if(data->dns.hostcachetype == HCACHE_MULTI) { + /* clear out the usage of the shared DNS cache */ + Curl_hostcache_clean(data, data->dns.hostcache); + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + + /* Clear the pointer to the connection cache */ + data->state.conn_cache = NULL; + data->multi = NULL; /* clear the association */ + +#ifdef USE_LIBPSL + if(data->psl == &multi->psl) + data->psl = NULL; +#endif + + data = nextdata; + } + + /* Close all the connections in the connection cache */ + Curl_conncache_close_all_connections(&multi->conn_cache); + + Curl_hash_destroy(&multi->sockhash); + Curl_conncache_destroy(&multi->conn_cache); + Curl_llist_destroy(&multi->msglist, NULL); + Curl_llist_destroy(&multi->pending, NULL); + + Curl_hash_destroy(&multi->hostcache); + Curl_psl_destroy(&multi->psl); + free(multi); + + return CURLM_OK; + } + return CURLM_BAD_HANDLE; +} + +/* + * curl_multi_info_read() + * + * This function is the primary way for a multi/multi_socket application to + * figure out if a transfer has ended. We MUST make this function as fast as + * possible as it will be polled frequently and we MUST NOT scan any lists in + * here to figure out things. We must scale fine to thousands of handles and + * beyond. The current design is fully O(1). + */ + +CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue) +{ + struct Curl_message *msg; + + *msgs_in_queue = 0; /* default to none */ + + if(GOOD_MULTI_HANDLE(multi) && + !multi->in_callback && + Curl_llist_count(&multi->msglist)) { + /* there is one or more messages in the list */ + struct curl_llist_element *e; + + /* extract the head of the list to return */ + e = multi->msglist.head; + + msg = e->ptr; + + /* remove the extracted entry */ + Curl_llist_remove(&multi->msglist, e, NULL); + + *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist)); + + return &msg->extmsg; + } + return NULL; +} + +/* + * singlesocket() checks what sockets we deal with and their "action state" + * and if we have a different state in any of those sockets from last time we + * call the callback accordingly. + */ +static CURLMcode singlesocket(struct Curl_multi *multi, + struct Curl_easy *data) +{ + curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; + int i; + struct Curl_sh_entry *entry; + curl_socket_t s; + int num; + unsigned int curraction; + int actions[MAX_SOCKSPEREASYHANDLE]; + + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) + socks[i] = CURL_SOCKET_BAD; + + /* Fill in the 'current' struct with the state as it is now: what sockets to + supervise and for what actions */ + curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE); + + /* We have 0 .. N sockets already and we get to know about the 0 .. M + sockets we should have from now on. Detect the differences, remove no + longer supervised ones and add new ones */ + + /* walk over the sockets we got right now */ + for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) && + (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))); + i++) { + unsigned int action = CURL_POLL_NONE; + unsigned int prevaction = 0; + unsigned int comboaction; + bool sincebefore = FALSE; + + s = socks[i]; + + /* get it from the hash */ + entry = sh_getentry(&multi->sockhash, s); + + if(curraction & GETSOCK_READSOCK(i)) + action |= CURL_POLL_IN; + if(curraction & GETSOCK_WRITESOCK(i)) + action |= CURL_POLL_OUT; + + actions[i] = action; + if(entry) { + /* check if new for this transfer */ + int j; + for(j = 0; j< data->numsocks; j++) { + if(s == data->sockets[j]) { + prevaction = data->actions[j]; + sincebefore = TRUE; + break; + } + } + } + else { + /* this is a socket we didn't have before, add it to the hash! */ + entry = sh_addentry(&multi->sockhash, s); + if(!entry) + /* fatal */ + return CURLM_OUT_OF_MEMORY; + } + if(sincebefore && (prevaction != action)) { + /* Socket was used already, but different action now */ + if(prevaction & CURL_POLL_IN) + entry->readers--; + if(prevaction & CURL_POLL_OUT) + entry->writers--; + if(action & CURL_POLL_IN) + entry->readers++; + if(action & CURL_POLL_OUT) + entry->writers++; + } + else if(!sincebefore) { + /* a new user */ + entry->users++; + if(action & CURL_POLL_IN) + entry->readers++; + if(action & CURL_POLL_OUT) + entry->writers++; + + /* add 'data' to the transfer hash on this socket! */ + if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */ + sizeof(struct Curl_easy *), data)) + return CURLM_OUT_OF_MEMORY; + } + + comboaction = (entry->writers? CURL_POLL_OUT : 0) | + (entry->readers ? CURL_POLL_IN : 0); + + /* socket existed before and has the same action set as before */ + if(sincebefore && (entry->action == comboaction)) + /* same, continue */ + continue; + + if(multi->socket_cb) + multi->socket_cb(data, s, comboaction, multi->socket_userp, + entry->socketp); + + entry->action = comboaction; /* store the current action state */ + } + + num = i; /* number of sockets */ + + /* when we've walked over all the sockets we should have right now, we must + make sure to detect sockets that are removed */ + for(i = 0; i< data->numsocks; i++) { + int j; + bool stillused = FALSE; + s = data->sockets[i]; + for(j = 0; j < num; j++) { + if(s == socks[j]) { + /* this is still supervised */ + stillused = TRUE; + break; + } + } + if(stillused) + continue; + + entry = sh_getentry(&multi->sockhash, s); + /* if this is NULL here, the socket has been closed and notified so + already by Curl_multi_closed() */ + if(entry) { + int oldactions = data->actions[i]; + /* this socket has been removed. Decrease user count */ + entry->users--; + if(oldactions & CURL_POLL_OUT) + entry->writers--; + if(oldactions & CURL_POLL_IN) + entry->readers--; + if(!entry->users) { + if(multi->socket_cb) + multi->socket_cb(data, s, CURL_POLL_REMOVE, + multi->socket_userp, + entry->socketp); + sh_delentry(entry, &multi->sockhash, s); + } + else { + /* still users, but remove this handle as a user of this socket */ + if(Curl_hash_delete(&entry->transfers, (char *)&data, + sizeof(struct Curl_easy *))) { + DEBUGASSERT(NULL); + } + } + } + } /* for loop over numsocks */ + + memcpy(data->sockets, socks, num*sizeof(curl_socket_t)); + memcpy(data->actions, actions, num*sizeof(int)); + data->numsocks = num; + return CURLM_OK; +} + +void Curl_updatesocket(struct Curl_easy *data) +{ + singlesocket(data->multi, data); +} + + +/* + * Curl_multi_closed() + * + * Used by the connect code to tell the multi_socket code that one of the + * sockets we were using is about to be closed. This function will then + * remove it from the sockethash for this handle to make the multi_socket API + * behave properly, especially for the case when libcurl will create another + * socket again and it gets the same file descriptor number. + */ + +void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s) +{ + if(data) { + /* if there's still an easy handle associated with this connection */ + struct Curl_multi *multi = data->multi; + if(multi) { + /* this is set if this connection is part of a handle that is added to + a multi handle, and only then this is necessary */ + struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s); + + if(entry) { + if(multi->socket_cb) + multi->socket_cb(data, s, CURL_POLL_REMOVE, + multi->socket_userp, + entry->socketp); + + /* now remove it from the socket hash */ + sh_delentry(entry, &multi->sockhash, s); + } + } + } +} + +/* + * add_next_timeout() + * + * Each Curl_easy has a list of timeouts. The add_next_timeout() is called + * when it has just been removed from the splay tree because the timeout has + * expired. This function is then to advance in the list to pick the next + * timeout to use (skip the already expired ones) and add this node back to + * the splay tree again. + * + * The splay tree only has each sessionhandle as a single node and the nearest + * timeout is used to sort it on. + */ +static CURLMcode add_next_timeout(struct curltime now, + struct Curl_multi *multi, + struct Curl_easy *d) +{ + struct curltime *tv = &d->state.expiretime; + struct curl_llist *list = &d->state.timeoutlist; + struct curl_llist_element *e; + struct time_node *node = NULL; + + /* move over the timeout list for this specific handle and remove all + timeouts that are now passed tense and store the next pending + timeout in *tv */ + for(e = list->head; e;) { + struct curl_llist_element *n = e->next; + timediff_t diff; + node = (struct time_node *)e->ptr; + diff = Curl_timediff(node->time, now); + if(diff <= 0) + /* remove outdated entry */ + Curl_llist_remove(list, e, NULL); + else + /* the list is sorted so get out on the first mismatch */ + break; + e = n; + } + e = list->head; + if(!e) { + /* clear the expire times within the handles that we remove from the + splay tree */ + tv->tv_sec = 0; + tv->tv_usec = 0; + } + else { + /* copy the first entry to 'tv' */ + memcpy(tv, &node->time, sizeof(*tv)); + + /* Insert this node again into the splay. Keep the timer in the list in + case we need to recompute future timers. */ + multi->timetree = Curl_splayinsert(*tv, multi->timetree, + &d->state.timenode); + } + return CURLM_OK; +} + +static CURLMcode multi_socket(struct Curl_multi *multi, + bool checkall, + curl_socket_t s, + int ev_bitmask, + int *running_handles) +{ + CURLMcode result = CURLM_OK; + struct Curl_easy *data = NULL; + struct Curl_tree *t; + struct curltime now = Curl_now(); + + if(checkall) { + /* *perform() deals with running_handles on its own */ + result = curl_multi_perform(multi, running_handles); + + /* walk through each easy handle and do the socket state change magic + and callbacks */ + if(result != CURLM_BAD_HANDLE) { + data = multi->easyp; + while(data && !result) { + result = singlesocket(multi, data); + data = data->next; + } + } + + /* or should we fall-through and do the timer-based stuff? */ + return result; + } + if(s != CURL_SOCKET_TIMEOUT) { + struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s); + + if(!entry) + /* Unmatched socket, we can't act on it but we ignore this fact. In + real-world tests it has been proved that libevent can in fact give + the application actions even though the socket was just previously + asked to get removed, so thus we better survive stray socket actions + and just move on. */ + ; + else { + struct curl_hash_iterator iter; + struct curl_hash_element *he; + + /* the socket can be shared by many transfers, iterate */ + Curl_hash_start_iterate(&entry->transfers, &iter); + for(he = Curl_hash_next_element(&iter); he; + he = Curl_hash_next_element(&iter)) { + data = (struct Curl_easy *)he->ptr; + DEBUGASSERT(data); + DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER); + + if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK)) + /* set socket event bitmask if they're not locked */ + data->conn->cselect_bits = ev_bitmask; + + Curl_expire(data, 0, EXPIRE_RUN_NOW); + } + + /* Now we fall-through and do the timer-based stuff, since we don't want + to force the user to have to deal with timeouts as long as at least + one connection in fact has traffic. */ + + data = NULL; /* set data to NULL again to avoid calling + multi_runsingle() in case there's no need to */ + now = Curl_now(); /* get a newer time since the multi_runsingle() loop + may have taken some time */ + } + } + else { + /* Asked to run due to time-out. Clear the 'lastcall' variable to force + Curl_update_timer() to trigger a callback to the app again even if the + same timeout is still the one to run after this call. That handles the + case when the application asks libcurl to run the timeout + prematurely. */ + memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); + } + + /* + * The loop following here will go on as long as there are expire-times left + * to process in the splay and 'data' will be re-assigned for every expired + * handle we deal with. + */ + do { + /* the first loop lap 'data' can be NULL */ + if(data) { + SIGPIPE_VARIABLE(pipe_st); + + sigpipe_ignore(data, &pipe_st); + result = multi_runsingle(multi, now, data); + sigpipe_restore(&pipe_st); + + if(CURLM_OK >= result) { + /* get the socket(s) and check if the state has been changed since + last */ + result = singlesocket(multi, data); + if(result) + return result; + } + } + + /* Check if there's one (more) expired timer to deal with! This function + extracts a matching node if there is one */ + + multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); + if(t) { + data = t->payload; /* assign this for next loop */ + (void)add_next_timeout(now, multi, t->payload); + } + + } while(t); + + *running_handles = multi->num_alive; + return result; +} + +#undef curl_multi_setopt +CURLMcode curl_multi_setopt(struct Curl_multi *multi, + CURLMoption option, ...) +{ + CURLMcode res = CURLM_OK; + va_list param; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + va_start(param, option); + + switch(option) { + case CURLMOPT_SOCKETFUNCTION: + multi->socket_cb = va_arg(param, curl_socket_callback); + break; + case CURLMOPT_SOCKETDATA: + multi->socket_userp = va_arg(param, void *); + break; + case CURLMOPT_PUSHFUNCTION: + multi->push_cb = va_arg(param, curl_push_callback); + break; + case CURLMOPT_PUSHDATA: + multi->push_userp = va_arg(param, void *); + break; + case CURLMOPT_PIPELINING: + multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX; + break; + case CURLMOPT_TIMERFUNCTION: + multi->timer_cb = va_arg(param, curl_multi_timer_callback); + break; + case CURLMOPT_TIMERDATA: + multi->timer_userp = va_arg(param, void *); + break; + case CURLMOPT_MAXCONNECTS: + multi->maxconnects = va_arg(param, long); + break; + case CURLMOPT_MAX_HOST_CONNECTIONS: + multi->max_host_connections = va_arg(param, long); + break; + case CURLMOPT_MAX_TOTAL_CONNECTIONS: + multi->max_total_connections = va_arg(param, long); + break; + /* options formerly used for pipelining */ + case CURLMOPT_MAX_PIPELINE_LENGTH: + break; + case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE: + break; + case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE: + break; + case CURLMOPT_PIPELINING_SITE_BL: + break; + case CURLMOPT_PIPELINING_SERVER_BL: + break; + default: + res = CURLM_UNKNOWN_OPTION; + break; + } + va_end(param); + return res; +} + +/* we define curl_multi_socket() in the public multi.h header */ +#undef curl_multi_socket + +CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s, + int *running_handles) +{ + CURLMcode result; + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + result = multi_socket(multi, FALSE, s, 0, running_handles); + if(CURLM_OK >= result) + Curl_update_timer(multi); + return result; +} + +CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s, + int ev_bitmask, int *running_handles) +{ + CURLMcode result; + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles); + if(CURLM_OK >= result) + Curl_update_timer(multi); + return result; +} + +CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles) + +{ + CURLMcode result; + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles); + if(CURLM_OK >= result) + Curl_update_timer(multi); + return result; +} + +static CURLMcode multi_timeout(struct Curl_multi *multi, + long *timeout_ms) +{ + static struct curltime tv_zero = {0, 0}; + + if(multi->timetree) { + /* we have a tree of expire times */ + struct curltime now = Curl_now(); + + /* splay the lowest to the bottom */ + multi->timetree = Curl_splay(tv_zero, multi->timetree); + + if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) { + /* some time left before expiration */ + timediff_t diff = Curl_timediff(multi->timetree->key, now); + if(diff <= 0) + /* + * Since we only provide millisecond resolution on the returned value + * and the diff might be less than one millisecond here, we don't + * return zero as that may cause short bursts of busyloops on fast + * processors while the diff is still present but less than one + * millisecond! instead we return 1 until the time is ripe. + */ + *timeout_ms = 1; + else + /* this should be safe even on 64 bit archs, as we don't use that + overly long timeouts */ + *timeout_ms = (long)diff; + } + else + /* 0 means immediately */ + *timeout_ms = 0; + } + else + *timeout_ms = -1; + + return CURLM_OK; +} + +CURLMcode curl_multi_timeout(struct Curl_multi *multi, + long *timeout_ms) +{ + /* First, make some basic checks that the CURLM handle is a good handle */ + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + return multi_timeout(multi, timeout_ms); +} + +/* + * Tell the application it should update its timers, if it subscribes to the + * update timer callback. + */ +void Curl_update_timer(struct Curl_multi *multi) +{ + long timeout_ms; + + if(!multi->timer_cb) + return; + if(multi_timeout(multi, &timeout_ms)) { + return; + } + if(timeout_ms < 0) { + static const struct curltime none = {0, 0}; + if(Curl_splaycomparekeys(none, multi->timer_lastcall)) { + multi->timer_lastcall = none; + /* there's no timeout now but there was one previously, tell the app to + disable it */ + multi->timer_cb(multi, -1, multi->timer_userp); + return; + } + return; + } + + /* When multi_timeout() is done, multi->timetree points to the node with the + * timeout we got the (relative) time-out time for. We can thus easily check + * if this is the same (fixed) time as we got in a previous call and then + * avoid calling the callback again. */ + if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0) + return; + + multi->timer_lastcall = multi->timetree->key; + + multi->timer_cb(multi, timeout_ms, multi->timer_userp); +} + +/* + * multi_deltimeout() + * + * Remove a given timestamp from the list of timeouts. + */ +static void +multi_deltimeout(struct Curl_easy *data, expire_id eid) +{ + struct curl_llist_element *e; + struct curl_llist *timeoutlist = &data->state.timeoutlist; + /* find and remove the specific node from the list */ + for(e = timeoutlist->head; e; e = e->next) { + struct time_node *n = (struct time_node *)e->ptr; + if(n->eid == eid) { + Curl_llist_remove(timeoutlist, e, NULL); + return; + } + } +} + +/* + * multi_addtimeout() + * + * Add a timestamp to the list of timeouts. Keep the list sorted so that head + * of list is always the timeout nearest in time. + * + */ +static CURLMcode +multi_addtimeout(struct Curl_easy *data, + struct curltime *stamp, + expire_id eid) +{ + struct curl_llist_element *e; + struct time_node *node; + struct curl_llist_element *prev = NULL; + size_t n; + struct curl_llist *timeoutlist = &data->state.timeoutlist; + + node = &data->state.expires[eid]; + + /* copy the timestamp and id */ + memcpy(&node->time, stamp, sizeof(*stamp)); + node->eid = eid; /* also marks it as in use */ + + n = Curl_llist_count(timeoutlist); + if(n) { + /* find the correct spot in the list */ + for(e = timeoutlist->head; e; e = e->next) { + struct time_node *check = (struct time_node *)e->ptr; + timediff_t diff = Curl_timediff(check->time, node->time); + if(diff > 0) + break; + prev = e; + } + + } + /* else + this is the first timeout on the list */ + + Curl_llist_insert_next(timeoutlist, prev, node, &node->list); + return CURLM_OK; +} + +/* + * Curl_expire() + * + * given a number of milliseconds from now to use to set the 'act before + * this'-time for the transfer, to be extracted by curl_multi_timeout() + * + * The timeout will be added to a queue of timeouts if it defines a moment in + * time that is later than the current head of queue. + * + * Expire replaces a former timeout using the same id if already set. + */ +void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id) +{ + struct Curl_multi *multi = data->multi; + struct curltime *nowp = &data->state.expiretime; + struct curltime set; + + /* this is only interesting while there is still an associated multi struct + remaining! */ + if(!multi) + return; + + DEBUGASSERT(id < EXPIRE_LAST); + + set = Curl_now(); + set.tv_sec += milli/1000; + set.tv_usec += (unsigned int)(milli%1000)*1000; + + if(set.tv_usec >= 1000000) { + set.tv_sec++; + set.tv_usec -= 1000000; + } + + /* Remove any timer with the same id just in case. */ + multi_deltimeout(data, id); + + /* Add it to the timer list. It must stay in the list until it has expired + in case we need to recompute the minimum timer later. */ + multi_addtimeout(data, &set, id); + + if(nowp->tv_sec || nowp->tv_usec) { + /* This means that the struct is added as a node in the splay tree. + Compare if the new time is earlier, and only remove-old/add-new if it + is. */ + timediff_t diff = Curl_timediff(set, *nowp); + int rc; + + if(diff > 0) { + /* The current splay tree entry is sooner than this new expiry time. + We don't need to update our splay tree entry. */ + return; + } + + /* Since this is an updated time, we must remove the previous entry from + the splay tree first and then re-add the new value */ + rc = Curl_splayremovebyaddr(multi->timetree, + &data->state.timenode, + &multi->timetree); + if(rc) + infof(data, "Internal error removing splay node = %d\n", rc); + } + + /* Indicate that we are in the splay tree and insert the new timer expiry + value since it is our local minimum. */ + *nowp = set; + data->state.timenode.payload = data; + multi->timetree = Curl_splayinsert(*nowp, multi->timetree, + &data->state.timenode); +} + +/* + * Curl_expire_done() + * + * Removes the expire timer. Marks it as done. + * + */ +void Curl_expire_done(struct Curl_easy *data, expire_id id) +{ + /* remove the timer, if there */ + multi_deltimeout(data, id); +} + +/* + * Curl_expire_clear() + * + * Clear ALL timeout values for this handle. + */ +void Curl_expire_clear(struct Curl_easy *data) +{ + struct Curl_multi *multi = data->multi; + struct curltime *nowp = &data->state.expiretime; + + /* this is only interesting while there is still an associated multi struct + remaining! */ + if(!multi) + return; + + if(nowp->tv_sec || nowp->tv_usec) { + /* Since this is an cleared time, we must remove the previous entry from + the splay tree */ + struct curl_llist *list = &data->state.timeoutlist; + int rc; + + rc = Curl_splayremovebyaddr(multi->timetree, + &data->state.timenode, + &multi->timetree); + if(rc) + infof(data, "Internal error clearing splay node = %d\n", rc); + + /* flush the timeout list too */ + while(list->size > 0) { + Curl_llist_remove(list, list->tail, NULL); + } + +#ifdef DEBUGBUILD + infof(data, "Expire cleared (transfer %p)\n", data); +#endif + nowp->tv_sec = 0; + nowp->tv_usec = 0; + } +} + + + + +CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s, + void *hashp) +{ + struct Curl_sh_entry *there = NULL; + + if(multi->in_callback) + return CURLM_RECURSIVE_API_CALL; + + there = sh_getentry(&multi->sockhash, s); + + if(!there) + return CURLM_BAD_SOCKET; + + there->socketp = hashp; + + return CURLM_OK; +} + +size_t Curl_multi_max_host_connections(struct Curl_multi *multi) +{ + return multi ? multi->max_host_connections : 0; +} + +size_t Curl_multi_max_total_connections(struct Curl_multi *multi) +{ + return multi ? multi->max_total_connections : 0; +} + +/* + * When information about a connection has appeared, call this! + */ + +void Curl_multiuse_state(struct connectdata *conn, + int bundlestate) /* use BUNDLE_* defines */ +{ + DEBUGASSERT(conn); + DEBUGASSERT(conn->bundle); + DEBUGASSERT(conn->data); + DEBUGASSERT(conn->data->multi); + + conn->bundle->multiuse = bundlestate; + process_pending_handles(conn->data->multi); +} + +static void process_pending_handles(struct Curl_multi *multi) +{ + struct curl_llist_element *e = multi->pending.head; + if(e) { + struct Curl_easy *data = e->ptr; + + DEBUGASSERT(data->mstate == CURLM_STATE_CONNECT_PEND); + + multistate(data, CURLM_STATE_CONNECT); + + /* Remove this node from the list */ + Curl_llist_remove(&multi->pending, e, NULL); + + /* Make sure that the handle will be processed soonish. */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + /* mark this as having been in the pending queue */ + data->state.previouslypending = TRUE; + } +} + +void Curl_set_in_callback(struct Curl_easy *data, bool value) +{ + /* might get called when there is no data pointer! */ + if(data) { + if(data->multi_easy) + data->multi_easy->in_callback = value; + else if(data->multi) + data->multi->in_callback = value; + } +} + +bool Curl_is_in_callback(struct Curl_easy *easy) +{ + return ((easy->multi && easy->multi->in_callback) || + (easy->multi_easy && easy->multi_easy->in_callback)); +} + +#ifdef DEBUGBUILD +void Curl_multi_dump(struct Curl_multi *multi) +{ + struct Curl_easy *data; + int i; + fprintf(stderr, "* Multi status: %d handles, %d alive\n", + multi->num_easy, multi->num_alive); + for(data = multi->easyp; data; data = data->next) { + if(data->mstate < CURLM_STATE_COMPLETED) { + /* only display handles that are not completed */ + fprintf(stderr, "handle %p, state %s, %d sockets\n", + (void *)data, + statename[data->mstate], data->numsocks); + for(i = 0; i < data->numsocks; i++) { + curl_socket_t s = data->sockets[i]; + struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s); + + fprintf(stderr, "%d ", (int)s); + if(!entry) { + fprintf(stderr, "INTERNAL CONFUSION\n"); + continue; + } + fprintf(stderr, "[%s %s] ", + (entry->action&CURL_POLL_IN)?"RECVING":"", + (entry->action&CURL_POLL_OUT)?"SENDING":""); + } + if(data->numsocks) + fprintf(stderr, "\n"); + } + } +} +#endif diff --git a/libcurl/lib/multihandle.h b/libcurl/lib/multihandle.h new file mode 100644 index 0000000..279379a --- /dev/null +++ b/libcurl/lib/multihandle.h @@ -0,0 +1,138 @@ +#ifndef HEADER_CURL_MULTIHANDLE_H +#define HEADER_CURL_MULTIHANDLE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "conncache.h" +#include "psl.h" + +struct Curl_message { + struct curl_llist_element list; + /* the 'CURLMsg' is the part that is visible to the external user */ + struct CURLMsg extmsg; +}; + +/* NOTE: if you add a state here, add the name to the statename[] array as + well! +*/ +typedef enum { + CURLM_STATE_INIT, /* 0 - start in this state */ + CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */ + CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */ + CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */ + CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */ + CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization + to complete and/or proxy CONNECT to + finalize */ + CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */ + CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect + phase */ + CURLM_STATE_DO, /* 8 - start send off the request (part 1) */ + CURLM_STATE_DOING, /* 9 - sending off the request (part 1) */ + CURLM_STATE_DO_MORE, /* 10 - send off the request (part 2) */ + CURLM_STATE_DO_DONE, /* 11 - done sending off request */ + CURLM_STATE_PERFORM, /* 12 - transfer data */ + CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */ + CURLM_STATE_DONE, /* 14 - post data transfer operation */ + CURLM_STATE_COMPLETED, /* 15 - operation complete */ + CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */ + CURLM_STATE_LAST /* 17 - not a true state, never use this */ +} CURLMstate; + +/* we support N sockets per easy handle. Set the corresponding bit to what + action we should wait for */ +#define MAX_SOCKSPEREASYHANDLE 5 +#define GETSOCK_READABLE (0x00ff) +#define GETSOCK_WRITABLE (0xff00) + +#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX) + +/* This is the struct known as CURLM on the outside */ +struct Curl_multi { + /* First a simple identifier to easier detect if a user mix up + this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */ + long type; + + /* We have a doubly-linked circular list with easy handles */ + struct Curl_easy *easyp; + struct Curl_easy *easylp; /* last node */ + + int num_easy; /* amount of entries in the linked list above. */ + int num_alive; /* amount of easy handles that are added but have not yet + reached COMPLETE state */ + + struct curl_llist msglist; /* a list of messages from completed transfers */ + + struct curl_llist pending; /* Curl_easys that are in the + CURLM_STATE_CONNECT_PEND state */ + + /* callback function and user data pointer for the *socket() API */ + curl_socket_callback socket_cb; + void *socket_userp; + + /* callback function and user data pointer for server push */ + curl_push_callback push_cb; + void *push_userp; + + /* Hostname cache */ + struct curl_hash hostcache; + +#ifdef USE_LIBPSL + /* PSL cache. */ + struct PslCache psl; +#endif + + /* timetree points to the splay-tree of time nodes to figure out expire + times of all currently set timers */ + struct Curl_tree *timetree; + + /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note + the pluralis form, there can be more than one easy handle waiting on the + same actual socket) */ + struct curl_hash sockhash; + + /* multiplexing wanted */ + bool multiplexing; + + bool recheckstate; /* see Curl_multi_connchanged */ + + /* Shared connection cache (bundles)*/ + struct conncache conn_cache; + + long maxconnects; /* if >0, a fixed limit of the maximum number of entries + we're allowed to grow the connection cache to */ + + long max_host_connections; /* if >0, a fixed limit of the maximum number + of connections per host */ + + long max_total_connections; /* if >0, a fixed limit of the maximum number + of connections in total */ + + /* timer callback and user data pointer for the *socket() API */ + curl_multi_timer_callback timer_cb; + void *timer_userp; + struct curltime timer_lastcall; /* the fixed time for the timeout for the + previous callback */ + bool in_callback; /* true while executing a callback */ +}; + +#endif /* HEADER_CURL_MULTIHANDLE_H */ diff --git a/libcurl/lib/multiif.h b/libcurl/lib/multiif.h new file mode 100644 index 0000000..a644558 --- /dev/null +++ b/libcurl/lib/multiif.h @@ -0,0 +1,99 @@ +#ifndef HEADER_CURL_MULTIIF_H +#define HEADER_CURL_MULTIIF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by multi.c + */ + +void Curl_updatesocket(struct Curl_easy *data); +void Curl_expire(struct Curl_easy *data, time_t milli, expire_id); +void Curl_expire_clear(struct Curl_easy *data); +void Curl_expire_done(struct Curl_easy *data, expire_id id); +void Curl_update_timer(struct Curl_multi *multi); +void Curl_attach_connnection(struct Curl_easy *data, + struct connectdata *conn); +bool Curl_multiplex_wanted(const struct Curl_multi *multi); +void Curl_set_in_callback(struct Curl_easy *data, bool value); +bool Curl_is_in_callback(struct Curl_easy *easy); + +/* Internal version of curl_multi_init() accepts size parameters for the + socket and connection hashes */ +struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize); + +/* the write bits start at bit 16 for the *getsock() bitmap */ +#define GETSOCK_WRITEBITSTART 16 + +#define GETSOCK_BLANK 0 /* no bits set */ + +/* set the bit for the given sock number to make the bitmap for writable */ +#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x))) + +/* set the bit for the given sock number to make the bitmap for readable */ +#define GETSOCK_READSOCK(x) (1 << (x)) + +#ifdef DEBUGBUILD + /* + * Curl_multi_dump is not a stable public function, this is only meant to + * allow easier tracking of the internal handle's state and what sockets + * they use. Only for research and development DEBUGBUILD enabled builds. + */ +void Curl_multi_dump(struct Curl_multi *multi); +#endif + +/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */ +size_t Curl_multi_max_host_connections(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */ +size_t Curl_multi_max_total_connections(struct Curl_multi *multi); + +void Curl_multiuse_state(struct connectdata *conn, + int bundlestate); /* use BUNDLE_* defines */ + +/* + * Curl_multi_closed() + * + * Used by the connect code to tell the multi_socket code that one of the + * sockets we were using is about to be closed. This function will then + * remove it from the sockethash for this handle to make the multi_socket API + * behave properly, especially for the case when libcurl will create another + * socket again and it gets the same file descriptor number. + */ + +void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s); + +/* + * Add a handle and move it into PERFORM state at once. For pushed streams. + */ +CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, + struct Curl_easy *data, + struct connectdata *conn); + +CURLMcode Curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret, + bool *gotsocket); /* if any socket was checked */ + +#endif /* HEADER_CURL_MULTIIF_H */ diff --git a/libcurl/lib/netrc.c b/libcurl/lib/netrc.c new file mode 100644 index 0000000..f41636e --- /dev/null +++ b/libcurl/lib/netrc.c @@ -0,0 +1,245 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#ifndef CURL_DISABLE_NETRC + +#ifdef HAVE_PWD_H +#include +#endif + +#include +#include "netrc.h" +#include "strtok.h" +#include "strcase.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Get user and password from .netrc when given a machine name */ + +enum host_lookup_state { + NOTHING, + HOSTFOUND, /* the 'machine' keyword was found */ + HOSTVALID /* this is "our" machine! */ +}; + +/* + * @unittest: 1304 + * + * *loginp and *passwordp MUST be allocated if they aren't NULL when passed + * in. + */ +int Curl_parsenetrc(const char *host, + char **loginp, + char **passwordp, + bool *login_changed, + bool *password_changed, + char *netrcfile) +{ + FILE *file; + int retcode = 1; + char *login = *loginp; + char *password = *passwordp; + bool specific_login = (login && *login != 0); + bool login_alloc = FALSE; + bool password_alloc = FALSE; + bool netrc_alloc = FALSE; + enum host_lookup_state state = NOTHING; + + char state_login = 0; /* Found a login keyword */ + char state_password = 0; /* Found a password keyword */ + int state_our_login = FALSE; /* With specific_login, found *our* login + name */ + +#define NETRC DOT_CHAR "netrc" + + if(!netrcfile) { + bool home_alloc = FALSE; + char *home = curl_getenv("HOME"); /* portable environment reader */ + if(home) { + home_alloc = TRUE; +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + } + else { + struct passwd pw, *pw_res; + char pwbuf[1024]; + if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) + && pw_res) { + home = strdup(pw.pw_dir); + if(!home) + return -1; + home_alloc = TRUE; + } +#elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID) + } + else { + struct passwd *pw; + pw = getpwuid(geteuid()); + if(pw) { + home = pw->pw_dir; + } +#endif + } + + if(!home) + return retcode; /* no home directory found (or possibly out of memory) */ + + netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC); + if(home_alloc) + free(home); + if(!netrcfile) { + return -1; + } + netrc_alloc = TRUE; + } + + file = fopen(netrcfile, FOPEN_READTEXT); + if(netrc_alloc) + free(netrcfile); + if(file) { + char *tok; + char *tok_buf; + bool done = FALSE; + char netrcbuffer[4096]; + int netrcbuffsize = (int)sizeof(netrcbuffer); + + while(!done && fgets(netrcbuffer, netrcbuffsize, file)) { + tok = strtok_r(netrcbuffer, " \t\n", &tok_buf); + if(tok && *tok == '#') + /* treat an initial hash as a comment line */ + continue; + while(!done && tok) { + + if((login && *login) && (password && *password)) { + done = TRUE; + break; + } + + switch(state) { + case NOTHING: + if(strcasecompare("machine", tok)) { + /* the next tok is the machine name, this is in itself the + delimiter that starts the stuff entered for this machine, + after this we need to search for 'login' and + 'password'. */ + state = HOSTFOUND; + } + else if(strcasecompare("default", tok)) { + state = HOSTVALID; + retcode = 0; /* we did find our host */ + } + break; + case HOSTFOUND: + if(strcasecompare(host, tok)) { + /* and yes, this is our host! */ + state = HOSTVALID; + retcode = 0; /* we did find our host */ + } + else + /* not our host */ + state = NOTHING; + break; + case HOSTVALID: + /* we are now parsing sub-keywords concerning "our" host */ + if(state_login) { + if(specific_login) { + state_our_login = strcasecompare(login, tok); + } + else if(!login || strcmp(login, tok)) { + if(login_alloc) { + free(login); + login_alloc = FALSE; + } + login = strdup(tok); + if(!login) { + retcode = -1; /* allocation failed */ + goto out; + } + login_alloc = TRUE; + } + state_login = 0; + } + else if(state_password) { + if((state_our_login || !specific_login) + && (!password || strcmp(password, tok))) { + if(password_alloc) { + free(password); + password_alloc = FALSE; + } + password = strdup(tok); + if(!password) { + retcode = -1; /* allocation failed */ + goto out; + } + password_alloc = TRUE; + } + state_password = 0; + } + else if(strcasecompare("login", tok)) + state_login = 1; + else if(strcasecompare("password", tok)) + state_password = 1; + else if(strcasecompare("machine", tok)) { + /* ok, there's machine here go => */ + state = HOSTFOUND; + state_our_login = FALSE; + } + break; + } /* switch (state) */ + + tok = strtok_r(NULL, " \t\n", &tok_buf); + } /* while(tok) */ + } /* while fgets() */ + + out: + if(!retcode) { + *login_changed = FALSE; + *password_changed = FALSE; + if(login_alloc) { + if(*loginp) + free(*loginp); + *loginp = login; + *login_changed = TRUE; + } + if(password_alloc) { + if(*passwordp) + free(*passwordp); + *passwordp = password; + *password_changed = TRUE; + } + } + else { + if(login_alloc) + free(login); + if(password_alloc) + free(password); + } + fclose(file); + } + + return retcode; +} + +#endif diff --git a/libcurl/lib/netrc.h b/libcurl/lib/netrc.h new file mode 100644 index 0000000..7f56c4b --- /dev/null +++ b/libcurl/lib/netrc.h @@ -0,0 +1,45 @@ +#ifndef HEADER_CURL_NETRC_H +#define HEADER_CURL_NETRC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#ifndef CURL_DISABLE_NETRC + +/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */ +int Curl_parsenetrc(const char *host, + char **loginp, + char **passwordp, + bool *login_changed, + bool *password_changed, + char *filename); + /* Assume: (*passwordp)[0]=0, host[0] != 0. + * If (*loginp)[0] = 0, search for login and password within a machine + * section in the netrc. + * If (*loginp)[0] != 0, search for password within machine and login. + */ +#else +/* disabled */ +#define Curl_parsenetrc(a,b,c,d,e,f) 1 +#endif + +#endif /* HEADER_CURL_NETRC_H */ diff --git a/libcurl/lib/non-ascii.c b/libcurl/lib/non-ascii.c new file mode 100644 index 0000000..42beaec --- /dev/null +++ b/libcurl/lib/non-ascii.c @@ -0,0 +1,332 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +#include + +#include "non-ascii.h" +#include "formdata.h" +#include "sendf.h" +#include "urldata.h" +#include "multiif.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifdef HAVE_ICONV +#include +/* set default codesets for iconv */ +#ifndef CURL_ICONV_CODESET_OF_NETWORK +#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1" +#endif +#ifndef CURL_ICONV_CODESET_FOR_UTF8 +#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8" +#endif +#define ICONV_ERROR (size_t)-1 +#endif /* HAVE_ICONV */ + +/* + * Curl_convert_clone() returns a malloced copy of the source string (if + * returning CURLE_OK), with the data converted to network format. + */ +CURLcode Curl_convert_clone(struct Curl_easy *data, + const char *indata, + size_t insize, + char **outbuf) +{ + char *convbuf; + CURLcode result; + + convbuf = malloc(insize); + if(!convbuf) + return CURLE_OUT_OF_MEMORY; + + memcpy(convbuf, indata, insize); + result = Curl_convert_to_network(data, convbuf, insize); + if(result) { + free(convbuf); + return result; + } + + *outbuf = convbuf; /* return the converted buffer */ + + return CURLE_OK; +} + +/* + * Curl_convert_to_network() is an internal function for performing ASCII + * conversions on non-ASCII platforms. It converts the buffer _in place_. + */ +CURLcode Curl_convert_to_network(struct Curl_easy *data, + char *buffer, size_t length) +{ + if(data && data->set.convtonetwork) { + /* use translation callback */ + CURLcode result; + Curl_set_in_callback(data, true); + result = data->set.convtonetwork(buffer, length); + Curl_set_in_callback(data, false); + if(result) { + failf(data, + "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + iconv_t tmpcd = (iconv_t) -1; + iconv_t *cd = &tmpcd; + char *input_ptr, *output_ptr; + size_t in_bytes, out_bytes, rc; + + /* open an iconv conversion descriptor if necessary */ + if(data) + cd = &data->outbound_cd; + if(*cd == (iconv_t)-1) { + *cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST); + if(*cd == (iconv_t)-1) { + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST, + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(*cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if(!data) + iconv_close(tmpcd); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + failf(data, + "The Curl_convert_to_network iconv call failed with errno %i: %s", + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } +#else + failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Curl_convert_from_network() is an internal function for performing ASCII + * conversions on non-ASCII platforms. It converts the buffer _in place_. + */ +CURLcode Curl_convert_from_network(struct Curl_easy *data, + char *buffer, size_t length) +{ + if(data && data->set.convfromnetwork) { + /* use translation callback */ + CURLcode result; + Curl_set_in_callback(data, true); + result = data->set.convfromnetwork(buffer, length); + Curl_set_in_callback(data, false); + if(result) { + failf(data, + "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + iconv_t tmpcd = (iconv_t) -1; + iconv_t *cd = &tmpcd; + char *input_ptr, *output_ptr; + size_t in_bytes, out_bytes, rc; + + /* open an iconv conversion descriptor if necessary */ + if(data) + cd = &data->inbound_cd; + if(*cd == (iconv_t)-1) { + *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK); + if(*cd == (iconv_t)-1) { + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK, + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(*cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if(!data) + iconv_close(tmpcd); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + failf(data, + "Curl_convert_from_network iconv call failed with errno %i: %s", + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } +#else + failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Curl_convert_from_utf8() is an internal function for performing UTF-8 + * conversions on non-ASCII platforms. + */ +CURLcode Curl_convert_from_utf8(struct Curl_easy *data, + char *buffer, size_t length) +{ + if(data && data->set.convfromutf8) { + /* use translation callback */ + CURLcode result; + Curl_set_in_callback(data, true); + result = data->set.convfromutf8(buffer, length); + Curl_set_in_callback(data, false); + if(result) { + failf(data, + "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s", + (int)result, curl_easy_strerror(result)); + } + + return result; + } + else { +#ifdef HAVE_ICONV + /* do the translation ourselves */ + iconv_t tmpcd = (iconv_t) -1; + iconv_t *cd = &tmpcd; + char *input_ptr; + char *output_ptr; + size_t in_bytes, out_bytes, rc; + + /* open an iconv conversion descriptor if necessary */ + if(data) + cd = &data->utf8_cd; + if(*cd == (iconv_t)-1) { + *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8); + if(*cd == (iconv_t)-1) { + failf(data, + "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", + CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8, + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(*cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if(!data) + iconv_close(tmpcd); + if((rc == ICONV_ERROR) || (in_bytes != 0)) { + failf(data, + "The Curl_convert_from_utf8 iconv call failed with errno %i: %s", + errno, strerror(errno)); + return CURLE_CONV_FAILED; + } + if(output_ptr < input_ptr) { + /* null terminate the now shorter output string */ + *output_ptr = 0x00; + } +#else + failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required"); + return CURLE_CONV_REQD; +#endif /* HAVE_ICONV */ + } + + return CURLE_OK; +} + +/* + * Init conversion stuff for a Curl_easy + */ +void Curl_convert_init(struct Curl_easy *data) +{ +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) + /* conversion descriptors for iconv calls */ + data->outbound_cd = (iconv_t)-1; + data->inbound_cd = (iconv_t)-1; + data->utf8_cd = (iconv_t)-1; +#else + (void)data; +#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ +} + +/* + * Setup conversion stuff for a Curl_easy + */ +void Curl_convert_setup(struct Curl_easy *data) +{ + data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK); + data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST); + data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_FOR_UTF8); +} + +/* + * Close conversion stuff for a Curl_easy + */ + +void Curl_convert_close(struct Curl_easy *data) +{ +#ifdef HAVE_ICONV + /* close iconv conversion descriptors */ + if(data->inbound_cd != (iconv_t)-1) { + iconv_close(data->inbound_cd); + } + if(data->outbound_cd != (iconv_t)-1) { + iconv_close(data->outbound_cd); + } + if(data->utf8_cd != (iconv_t)-1) { + iconv_close(data->utf8_cd); + } +#else + (void)data; +#endif /* HAVE_ICONV */ +} + +#endif /* CURL_DOES_CONVERSIONS */ diff --git a/libcurl/lib/non-ascii.h b/libcurl/lib/non-ascii.h new file mode 100644 index 0000000..5fb5771 --- /dev/null +++ b/libcurl/lib/non-ascii.h @@ -0,0 +1,61 @@ +#ifndef HEADER_CURL_NON_ASCII_H +#define HEADER_CURL_NON_ASCII_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +#include "urldata.h" + +/* + * Curl_convert_clone() returns a malloced copy of the source string (if + * returning CURLE_OK), with the data converted to network format. + * + * If no conversion was needed *outbuf may be NULL. + */ +CURLcode Curl_convert_clone(struct Curl_easy *data, + const char *indata, + size_t insize, + char **outbuf); + +void Curl_convert_init(struct Curl_easy *data); +void Curl_convert_setup(struct Curl_easy *data); +void Curl_convert_close(struct Curl_easy *data); + +CURLcode Curl_convert_to_network(struct Curl_easy *data, + char *buffer, size_t length); +CURLcode Curl_convert_from_network(struct Curl_easy *data, + char *buffer, size_t length); +CURLcode Curl_convert_from_utf8(struct Curl_easy *data, + char *buffer, size_t length); +#else +#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK) +#define Curl_convert_init(x) Curl_nop_stmt +#define Curl_convert_setup(x) Curl_nop_stmt +#define Curl_convert_close(x) Curl_nop_stmt +#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK) +#endif + +#endif /* HEADER_CURL_NON_ASCII_H */ diff --git a/libcurl/lib/nonblock.c b/libcurl/lib/nonblock.c new file mode 100644 index 0000000..4d105c1 --- /dev/null +++ b/libcurl/lib/nonblock.c @@ -0,0 +1,91 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#include "nonblock.h" + +/* + * curlx_nonblock() set the given socket to either blocking or non-blocking + * mode based on the 'nonblock' boolean argument. This function is highly + * portable. + */ +int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ + int nonblock /* TRUE or FALSE */) +{ +#if defined(USE_BLOCKING_SOCKETS) + (void)sockfd; + (void)nonblock; + return 0; /* returns success */ + +#elif defined(HAVE_FCNTL_O_NONBLOCK) + + /* most recent unix versions */ + int flags; + flags = sfcntl(sockfd, F_GETFL, 0); + if(nonblock) + return sfcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); + +#elif defined(HAVE_IOCTL_FIONBIO) + + /* older unix versions */ + int flags = nonblock ? 1 : 0; + return ioctl(sockfd, FIONBIO, &flags); + +#elif defined(HAVE_IOCTLSOCKET_FIONBIO) + + /* Windows */ + unsigned long flags = nonblock ? 1UL : 0UL; + return ioctlsocket(sockfd, FIONBIO, &flags); + +#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) + + /* Amiga */ + long flags = nonblock ? 1L : 0L; + return IoctlSocket(sockfd, FIONBIO, (char *)&flags); + +#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) + + /* BeOS */ + long b = nonblock ? 1L : 0L; + return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); + +#else +# error "no non-blocking method was found/used/set" +#endif +} diff --git a/libcurl/lib/nonblock.h b/libcurl/lib/nonblock.h new file mode 100644 index 0000000..eb18ea1 --- /dev/null +++ b/libcurl/lib/nonblock.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_NONBLOCK_H +#define HEADER_CURL_NONBLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include /* for curl_socket_t */ + +int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ + int nonblock /* TRUE or FALSE */); + +#endif /* HEADER_CURL_NONBLOCK_H */ diff --git a/libcurl/lib/nwlib.c b/libcurl/lib/nwlib.c new file mode 100644 index 0000000..7bf5f51 --- /dev/null +++ b/libcurl/lib/nwlib.c @@ -0,0 +1,328 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef NETWARE /* Novell NetWare */ + +#ifdef __NOVELL_LIBC__ +/* For native LibC-based NLM we need to register as a real lib. */ +#include +#include +#include +#include +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +typedef struct +{ + int _errno; + void *twentybytes; +} libthreaddata_t; + +typedef struct +{ + int x; + int y; + int z; + void *tenbytes; + NXKey_t perthreadkey; /* if -1, no key obtained... */ + NXMutex_t *lock; +} libdata_t; + +int gLibId = -1; +void *gLibHandle = (void *) NULL; +rtag_t gAllocTag = (rtag_t) NULL; +NXMutex_t *gLibLock = (NXMutex_t *) NULL; + +/* internal library function prototypes... */ +int DisposeLibraryData(void *); +void DisposeThreadData(void *); +int GetOrSetUpData(int id, libdata_t **data, libthreaddata_t **threaddata); + + +int _NonAppStart(void *NLMHandle, + void *errorScreen, + const char *cmdLine, + const char *loadDirPath, + size_t uninitializedDataLength, + void *NLMFileHandle, + int (*readRoutineP)(int conn, + void *fileHandle, size_t offset, + size_t nbytes, + size_t *bytesRead, + void *buffer), + size_t customDataOffset, + size_t customDataSize, + int messageCount, + const char **messages) +{ + NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0); + +#ifndef __GNUC__ +#pragma unused(cmdLine) +#pragma unused(loadDirPath) +#pragma unused(uninitializedDataLength) +#pragma unused(NLMFileHandle) +#pragma unused(readRoutineP) +#pragma unused(customDataOffset) +#pragma unused(customDataSize) +#pragma unused(messageCount) +#pragma unused(messages) +#endif + + /* + * Here we process our command line, post errors (to the error screen), + * perform initializations and anything else we need to do before being able + * to accept calls into us. If we succeed, we return non-zero and the NetWare + * Loader will leave us up, otherwise we fail to load and get dumped. + */ + gAllocTag = AllocateResourceTag(NLMHandle, + " memory allocations", + AllocSignature); + + if(!gAllocTag) { + OutputToScreen(errorScreen, "Unable to allocate resource tag for " + "library memory allocations.\n"); + return -1; + } + + gLibId = register_library(DisposeLibraryData); + + if(gLibId < -1) { + OutputToScreen(errorScreen, "Unable to register library with kernel.\n"); + return -1; + } + + gLibHandle = NLMHandle; + + gLibLock = NXMutexAlloc(0, 0, &liblock); + + if(!gLibLock) { + OutputToScreen(errorScreen, "Unable to allocate library data lock.\n"); + return -1; + } + + return 0; +} + +/* + * Here we clean up any resources we allocated. Resource tags is a big part + * of what we created, but NetWare doesn't ask us to free those. + */ +void _NonAppStop(void) +{ + (void) unregister_library(gLibId); + NXMutexFree(gLibLock); +} + +/* + * This function cannot be the first in the file for if the file is linked + * first, then the check-unload function's offset will be nlmname.nlm+0 + * which is how to tell that there isn't one. When the check function is + * first in the linked objects, it is ambiguous. For this reason, we will + * put it inside this file after the stop function. + * + * Here we check to see if it's alright to ourselves to be unloaded. If not, + * we return a non-zero value. Right now, there isn't any reason not to allow + * it. + */ +int _NonAppCheckUnload(void) +{ + return 0; +} + +int GetOrSetUpData(int id, libdata_t **appData, + libthreaddata_t **threadData) +{ + int err; + libdata_t *app_data; + libthreaddata_t *thread_data; + NXKey_t key; + NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0); + + err = 0; + thread_data = (libthreaddata_t *) NULL; + + /* + * Attempt to get our data for the application calling us. This is where we + * store whatever application-specific information we need to carry in + * support of calling applications. + */ + app_data = (libdata_t *) get_app_data(id); + + if(!app_data) { + /* + * This application hasn't called us before; set up application AND + * per-thread data. Of course, just in case a thread from this same + * application is calling us simultaneously, we better lock our application + * data-creation mutex. We also need to recheck for data after we acquire + * the lock because WE might be that other thread that was too late to + * create the data and the first thread in will have created it. + */ + NXLock(gLibLock); + + app_data = (libdata_t *) get_app_data(id); + if(!app_data) { + app_data = calloc(1, sizeof(libdata_t)); + + if(app_data) { + app_data->tenbytes = malloc(10); + app_data->lock = NXMutexAlloc(0, 0, &liblock); + + if(!app_data->tenbytes || !app_data->lock) { + if(app_data->lock) + NXMutexFree(app_data->lock); + free(app_data->tenbytes); + free(app_data); + app_data = (libdata_t *) NULL; + err = ENOMEM; + } + + if(app_data) { + /* + * Here we burn in the application data that we were trying to get + * by calling get_app_data(). Next time we call the first function, + * we'll get this data we're just now setting. We also go on here to + * establish the per-thread data for the calling thread, something + * we'll have to do on each application thread the first time + * it calls us. + */ + err = set_app_data(gLibId, app_data); + + if(err) { + if(app_data->lock) + NXMutexFree(app_data->lock); + free(app_data->tenbytes); + free(app_data); + app_data = (libdata_t *) NULL; + err = ENOMEM; + } + else { + /* create key for thread-specific data... */ + err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key); + + if(err) /* (no more keys left?) */ + key = -1; + + app_data->perthreadkey = key; + } + } + } + } + + NXUnlock(gLibLock); + } + + if(app_data) { + key = app_data->perthreadkey; + + if(key != -1 /* couldn't create a key? no thread data */ + && !(err = NXKeyGetValue(key, (void **) &thread_data)) + && !thread_data) { + /* + * Allocate the per-thread data for the calling thread. Regardless of + * whether there was already application data or not, this may be the + * first call by a new thread. The fact that we allocation 20 bytes on + * a pointer is not very important, this just helps to demonstrate that + * we can have arbitrarily complex per-thread data. + */ + thread_data = malloc(sizeof(libthreaddata_t)); + + if(thread_data) { + thread_data->_errno = 0; + thread_data->twentybytes = malloc(20); + + if(!thread_data->twentybytes) { + free(thread_data); + thread_data = (libthreaddata_t *) NULL; + err = ENOMEM; + } + + err = NXKeySetValue(key, thread_data); + if(err) { + free(thread_data->twentybytes); + free(thread_data); + thread_data = (libthreaddata_t *) NULL; + } + } + } + } + + if(appData) + *appData = app_data; + + if(threadData) + *threadData = thread_data; + + return err; +} + +int DisposeLibraryData(void *data) +{ + if(data) { + void *tenbytes = ((libdata_t *) data)->tenbytes; + + free(tenbytes); + free(data); + } + + return 0; +} + +void DisposeThreadData(void *data) +{ + if(data) { + void *twentybytes = ((libthreaddata_t *) data)->twentybytes; + + free(twentybytes); + free(data); + } +} + +#else /* __NOVELL_LIBC__ */ +/* For native CLib-based NLM seems we can do a bit more simple. */ +#include + +int main(void) +{ + /* initialize any globals here... */ + + /* do this if any global initializing was done + SynchronizeStart(); + */ + ExitThread(TSR_THREAD, 0); + return 0; +} + +#endif /* __NOVELL_LIBC__ */ + +#else /* NETWARE */ + +#ifdef __POCC__ +# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */ +#endif + +#endif /* NETWARE */ diff --git a/libcurl/lib/nwos.c b/libcurl/lib/nwos.c new file mode 100644 index 0000000..c6c22cc --- /dev/null +++ b/libcurl/lib/nwos.c @@ -0,0 +1,88 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef NETWARE /* Novell NetWare */ + +#ifdef __NOVELL_LIBC__ +/* For native LibC-based NLM we need to do nothing. */ +int netware_init(void) +{ + return 0; +} + +#else /* __NOVELL_LIBC__ */ + +/* For native CLib-based NLM we need to initialize the LONG namespace. */ +#include +#include +#include +/* Make the CLIB Ctx stuff link */ +#include +NETDB_DEFINE_CONTEXT +/* Make the CLIB Inet stuff link */ +#include +#include +NETINET_DEFINE_CONTEXT + +int netware_init(void) +{ + int rc = 0; + unsigned int myHandle = GetNLMHandle(); + /* import UnAugmentAsterisk dynamically for NW4.x compatibility */ + void (*pUnAugmentAsterisk)(int) = (void(*)(int)) + ImportSymbol(myHandle, "UnAugmentAsterisk"); + /* import UseAccurateCaseForPaths dynamically for NW3.x compatibility */ + void (*pUseAccurateCaseForPaths)(int) = (void(*)(int)) + ImportSymbol(myHandle, "UseAccurateCaseForPaths"); + if(pUnAugmentAsterisk) + pUnAugmentAsterisk(1); + if(pUseAccurateCaseForPaths) + pUseAccurateCaseForPaths(1); + UnimportSymbol(myHandle, "UnAugmentAsterisk"); + UnimportSymbol(myHandle, "UseAccurateCaseForPaths"); + /* set long name space */ + if((SetCurrentNameSpace(4) == 255)) { + rc = 1; + } + if((SetTargetNameSpace(4) == 255)) { + rc = rc + 2; + } + return rc; +} + +/* dummy function to satisfy newer prelude */ +int __init_environment(void) +{ + return 0; +} + +/* dummy function to satisfy newer prelude */ +int __deinit_environment(void) +{ + return 0; +} + +#endif /* __NOVELL_LIBC__ */ + +#endif /* NETWARE */ diff --git a/libcurl/lib/objnames-test08.sh b/libcurl/lib/objnames-test08.sh new file mode 100644 index 0000000..4859757 --- /dev/null +++ b/libcurl/lib/objnames-test08.sh @@ -0,0 +1,217 @@ +#!/bin/sh +# *************************************************************************** +# * _ _ ____ _ +# * Project ___| | | | _ \| | +# * / __| | | | |_) | | +# * | (__| |_| | _ <| |___ +# * \___|\___/|_| \_\_____| +# * +# * Copyright (C) 2013, Daniel Stenberg, , et al. +# * +# * This software is licensed as described in the file COPYING, which +# * you should have received as part of this distribution. The terms +# * are also available at https://curl.haxx.se/docs/copyright.html. +# * +# * You may opt to use, copy, modify, merge, publish, distribute and/or sell +# * copies of the Software, and permit persons to whom the Software is +# * furnished to do so, under the terms of the COPYING file. +# * +# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# * KIND, either express or implied. +# * +# *************************************************************************** + +# +# This Bourne shell script file is used by test case 1222 to do +# unit testing of curl_8char_object_name() shell function which +# is defined in file objnames.inc and sourced by this file and +# any other shell script that may use it. +# + +# +# argument validation +# + +if test $# -eq 1; then + : +else + echo "Usage: ${0} srcdir" + exit 1 +fi + +if test -f "${1}/runtests.pl"; then + : +else + echo "${0}: Wrong srcdir" + exit 1 +fi + +srcdir=${1} + +if test -f "$srcdir/../lib/objnames.inc"; then + : +else + echo "$0: Missing objnames.inc" + exit 1 +fi + +# +# Some variables +# + +logdir=log +tstnum=1222 + +list_c=$logdir/${tstnum}_list_c +list_obj=$logdir/${tstnum}_list_obj +list_obj_c=$logdir/${tstnum}_list_obj_c +list_obj_uniq=$logdir/${tstnum}_list_obj_uniq + + +# +# Source curl_8char_object_name() function definition +# + +. $srcdir/../lib/objnames.inc + +# +# Some curl_8char_object_name() unit tests +# + +echo 'Testing curl_8char_object_name...' +echo "" + +argstr=123__678__ABC__FGH__KLM__PQRSTUV +expect=16AFKPQR +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123__678__ABC__FGH__KLM__PQ.S.UV +expect=16AFKPQ +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123__678__ABC..FGH..KLM..PQRSTUV +expect=16ABC +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123__678_.ABC._FGH__KLM__PQRSTUV +expect=16 +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123.567.90ABCDEFGHIJKLMNOPQRSTUV +expect=123 +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=1234567.90A.CDEFGHIJKLMNOPQRSTUV +expect=1234567 +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=1234567890.BCD.FGHIJKLMNOPQRSTUV +expect=12345678 +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=12=45-78+0AB.DE.GHIJKLMNOPQRSTUV +expect=1470AB +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=1234567890ABCDEFGHIJKLMNOPQRSTUV +expect=12345678 +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123_567_90A_CDE_GHIJKLMNOPQRSTUV +expect=159CGHIJ +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123_567_90A_CDEFGHIJKLMNOPQRSTUV +expect=159CDEFG +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123_567_90ABCDEFGHIJKLMNOPQRSTUV +expect=1590ABCD +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123_567890ABCDEFGHIJKLMNOPQRSTUV +expect=1567890A +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=1234567890ABCDEFGHIJKLMNOPQRSTUV +expect=12345678 +outstr=`curl_8char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +# +# Verify that generated object name is distinct for +# all *.c source files in lib and src subdirectories. +# + +ls $srcdir/../lib/*.c > $list_c +ls $srcdir/../src/*.c >> $list_c + +rm -f $list_obj + +for c_fname in `cat $list_c`; do + obj_name=`curl_8char_object_name $c_fname` + echo "$obj_name" >> $list_obj +done + +sort -u $list_obj > $list_obj_uniq + +cnt_c=`cat $list_c | wc -l` +cnt_u=`cat $list_obj_uniq | wc -l` + +echo "" +echo "" +echo "" +if test $cnt_c -eq $cnt_u; then + echo "8-characters-or-less generated object names are unique." + obj_name_clash="no" +else + echo "8-characters-or-less generated object names are clashing..." + obj_name_clash="yes" +fi + +if test $obj_name_clash = "yes"; then + # + # Show clashing object names and respective source file names + # + echo "" + paste $list_obj $list_c | sort > $list_obj_c + prev_match="no" + prev_line="unknown" + prev_obj_name="unknown" + while read this_line; do + obj_name=`echo "$this_line" | cut -f1` + if test "x$obj_name" = "x$prev_obj_name"; then + if test "x$prev_match" != "xyes"; then + echo "$prev_line" + echo "$this_line" + prev_match="yes" + else + echo "$this_line" + fi + else + prev_match="no" + fi + prev_line=$this_line + prev_obj_name=$obj_name + done < $list_obj_c +fi + +rm -f $list_c +rm -f $list_obj +rm -f $list_obj_c +rm -f $list_obj_uniq + +# end of objnames-test.sh diff --git a/libcurl/lib/objnames-test10.sh b/libcurl/lib/objnames-test10.sh new file mode 100644 index 0000000..62184b8 --- /dev/null +++ b/libcurl/lib/objnames-test10.sh @@ -0,0 +1,217 @@ +#!/bin/sh +# *************************************************************************** +# * _ _ ____ _ +# * Project ___| | | | _ \| | +# * / __| | | | |_) | | +# * | (__| |_| | _ <| |___ +# * \___|\___/|_| \_\_____| +# * +# * Copyright (C) 2013, Daniel Stenberg, , et al. +# * +# * This software is licensed as described in the file COPYING, which +# * you should have received as part of this distribution. The terms +# * are also available at https://curl.haxx.se/docs/copyright.html. +# * +# * You may opt to use, copy, modify, merge, publish, distribute and/or sell +# * copies of the Software, and permit persons to whom the Software is +# * furnished to do so, under the terms of the COPYING file. +# * +# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# * KIND, either express or implied. +# * +# *************************************************************************** + +# +# This Bourne shell script file is used by test case 1221 to do +# unit testing of curl_10char_object_name() shell function which +# is defined in file objnames.inc and sourced by this file and +# any other shell script that may use it. +# + +# +# argument validation +# + +if test $# -eq 1; then + : +else + echo "Usage: ${0} srcdir" + exit 1 +fi + +if test -f "${1}/runtests.pl"; then + : +else + echo "${0}: Wrong srcdir" + exit 1 +fi + +srcdir=${1} + +if test -f "$srcdir/../lib/objnames.inc"; then + : +else + echo "$0: Missing objnames.inc" + exit 1 +fi + +# +# Some variables +# + +logdir=log +tstnum=1221 + +list_c=$logdir/${tstnum}_list_c +list_obj=$logdir/${tstnum}_list_obj +list_obj_c=$logdir/${tstnum}_list_obj_c +list_obj_uniq=$logdir/${tstnum}_list_obj_uniq + + +# +# Source curl_10char_object_name() function definition +# + +. $srcdir/../lib/objnames.inc + +# +# Some curl_10char_object_name() unit tests +# + +echo 'Testing curl_10char_object_name...' +echo "" + +argstr=123__678__ABC__FGH__KLM__PQRSTUV +expect=16AFKPQRST +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123__678__ABC__FGH__KLM__PQ.S.UV +expect=16AFKPQ +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123__678__ABC..FGH..KLM..PQRSTUV +expect=16ABC +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123__678_.ABC._FGH__KLM__PQRSTUV +expect=16 +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123.567.90ABCDEFGHIJKLMNOPQRSTUV +expect=123 +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=1234567.90A.CDEFGHIJKLMNOPQRSTUV +expect=1234567 +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=1234567890.BCD.FGHIJKLMNOPQRSTUV +expect=1234567890 +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=12=45-78+0AB.DE.GHIJKLMNOPQRSTUV +expect=1470AB +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=1234567890ABCDEFGHIJKLMNOPQRSTUV +expect=1234567890 +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123_567_90A_CDE_GHIJKLMNOPQRSTUV +expect=159CGHIJKL +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123_567_90A_CDEFGHIJKLMNOPQRSTUV +expect=159CDEFGHI +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123_567_90ABCDEFGHIJKLMNOPQRSTUV +expect=1590ABCDEF +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=123_567890ABCDEFGHIJKLMNOPQRSTUV +expect=1567890ABC +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +argstr=1234567890ABCDEFGHIJKLMNOPQRSTUV +expect=1234567890 +outstr=`curl_10char_object_name $argstr` +echo "result: $outstr expected: $expect input: $argstr" + +# +# Verify that generated object name is distinct for +# all *.c source files in lib and src subdirectories. +# + +ls $srcdir/../lib/*.c > $list_c +ls $srcdir/../src/*.c >> $list_c + +rm -f $list_obj + +for c_fname in `cat $list_c`; do + obj_name=`curl_10char_object_name $c_fname` + echo "$obj_name" >> $list_obj +done + +sort -u $list_obj > $list_obj_uniq + +cnt_c=`cat $list_c | wc -l` +cnt_u=`cat $list_obj_uniq | wc -l` + +echo "" +echo "" +echo "" +if test $cnt_c -eq $cnt_u; then + echo "10-characters-or-less generated object names are unique." + obj_name_clash="no" +else + echo "10-characters-or-less generated object names are clashing..." + obj_name_clash="yes" +fi + +if test $obj_name_clash = "yes"; then + # + # Show clashing object names and respective source file names + # + echo "" + paste $list_obj $list_c | sort > $list_obj_c + prev_match="no" + prev_line="unknown" + prev_obj_name="unknown" + while read this_line; do + obj_name=`echo "$this_line" | cut -f1` + if test "x$obj_name" = "x$prev_obj_name"; then + if test "x$prev_match" != "xyes"; then + echo "$prev_line" + echo "$this_line" + prev_match="yes" + else + echo "$this_line" + fi + else + prev_match="no" + fi + prev_line=$this_line + prev_obj_name=$obj_name + done < $list_obj_c +fi + +rm -f $list_c +rm -f $list_obj +rm -f $list_obj_c +rm -f $list_obj_uniq + +# end of objnames-test10.sh diff --git a/libcurl/lib/objnames.inc b/libcurl/lib/objnames.inc new file mode 100644 index 0000000..6a5b2a8 --- /dev/null +++ b/libcurl/lib/objnames.inc @@ -0,0 +1,107 @@ +# *************************************************************************** +# * _ _ ____ _ +# * Project ___| | | | _ \| | +# * / __| | | | |_) | | +# * | (__| |_| | _ <| |___ +# * \___|\___/|_| \_\_____| +# * +# * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. +# * +# * This software is licensed as described in the file COPYING, which +# * you should have received as part of this distribution. The terms +# * are also available at https://curl.haxx.se/docs/copyright.html. +# * +# * You may opt to use, copy, modify, merge, publish, distribute and/or sell +# * copies of the Software, and permit persons to whom the Software is +# * furnished to do so, under the terms of the COPYING file. +# * +# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# * KIND, either express or implied. +# * +# *************************************************************************** + +# +# This file is sourced from curl/packages/OS400/initscript.sh and +# other Bourne shell scripts. Keep it as portable as possible. +# + +# +# curl_10char_object_name +# +# This shell function accepts a single string argument with unspecified +# length representing a (*.c) source file name and returns a string which +# is a transformation of given argument. +# +# The intended purpose of this function is to transliterate a (*.c) source +# file name that may be longer than 10 characters, or not, into a string +# with at most 10 characters which may be used as an OS/400 object name. +# +# This function might not be universally useful, nor we care about it. +# +# It is intended to be used with libcurl's (*.c) source file names, so +# dependency on libcurl's source file naming scheme is acceptable and +# good enough for its intended use. Specifically it makes use of the fact +# that libcurl's (*.c) source file names which may be longer than 10 chars +# are conformed with underscore '_' separated substrings, or separated by +# other character which does not belong to the [0-9], [a-z] or [A-Z] sets. +# +# This allows repeatable and automatic short object name generation with +# no need for a hardcoded mapping table. +# +# Transformation is done in the following way: +# +# 1) Leading directory components are removed. +# 2) Leftmost dot character and any other char following it are removed. +# 3) Lowercase characters are transliterated to uppercase. +# 4) Characters not in [A-Z] or [0-9] are transliterated to underscore '_'. +# 5) Every sequence of one or more underscores is replaced with a single one. +# 6) Five leftmost substrings which end in an underscore character are +# replaced by the first character of each substring, while retaining +# the rest of the string. +# 7) Finally the result is truncated to 10 characters. +# +# Resulting object name may be shorter than 10 characters. +# +# Test case 1221 does unit testng of this function and also verifies +# that it is possible to generate distinct short object names for all +# curl and libcurl *.c source file names. +# + +curl_10char_object_name() { + echo "${1}" | \ + sed -e 's:.*/::' \ + -e 's:[.].*::' \ + -e 'y:abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:' \ + -e 's:[^ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_]:_:g' \ + -e 's:__*:_:g' \ + -e 's:\([^_]\)[^_]*_\(.*\):\1\2:' \ + -e 's:\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3:' \ + -e 's:\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4:' \ + -e 's:\([^_]\)\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4\5:' \ + -e 's:\([^_]\)\([^_]\)\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4\5\6:' \ + -e 's:^\(..........\).*:\1:' +} + +# +# curl_8char_object_name +# +# Same as curl_10char_object_name() description and details above, except +# that object name is limited to 8 charcters maximum. +# + +curl_8char_object_name() { + echo "${1}" | \ + sed -e 's:.*/::' \ + -e 's:[.].*::' \ + -e 'y:abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:' \ + -e 's:[^ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_]:_:g' \ + -e 's:__*:_:g' \ + -e 's:\([^_]\)[^_]*_\(.*\):\1\2:' \ + -e 's:\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3:' \ + -e 's:\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4:' \ + -e 's:\([^_]\)\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4\5:' \ + -e 's:\([^_]\)\([^_]\)\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4\5\6:' \ + -e 's:^\(........\).*:\1:' +} + +# end of objectname.inc diff --git a/libcurl/lib/openldap.c b/libcurl/lib/openldap.c new file mode 100644 index 0000000..eeab2c7 --- /dev/null +++ b/libcurl/lib/openldap.c @@ -0,0 +1,758 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Howard Chu, + * Copyright (C) 2011 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP) + +/* + * Notice that USE_OPENLDAP is only a source code selection switch. When + * libcurl is built with USE_OPENLDAP defined the libcurl source code that + * gets compiled is the code from openldap.c, otherwise the code that gets + * compiled is the code from ldap.c. + * + * When USE_OPENLDAP is defined a recent version of the OpenLDAP library + * might be required for compilation and runtime. In order to use ancient + * OpenLDAP library versions, USE_OPENLDAP shall not be defined. + */ + +#include + +#include "urldata.h" +#include +#include "sendf.h" +#include "vtls/vtls.h" +#include "transfer.h" +#include "curl_ldap.h" +#include "curl_base64.h" +#include "connect.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Uncommenting this will enable the built-in debug logging of the openldap + * library. The debug log level can be set using the CURL_OPENLDAP_TRACE + * environment variable. The debug output is written to stderr. + * + * The library supports the following debug flags: + * LDAP_DEBUG_NONE 0x0000 + * LDAP_DEBUG_TRACE 0x0001 + * LDAP_DEBUG_CONSTRUCT 0x0002 + * LDAP_DEBUG_DESTROY 0x0004 + * LDAP_DEBUG_PARAMETER 0x0008 + * LDAP_DEBUG_ANY 0xffff + * + * For example, use CURL_OPENLDAP_TRACE=0 for no debug, + * CURL_OPENLDAP_TRACE=2 for LDAP_DEBUG_CONSTRUCT messages only, + * CURL_OPENLDAP_TRACE=65535 for all debug message levels. + */ +/* #define CURL_OPENLDAP_DEBUG */ + +#ifndef _LDAP_PVT_H +extern int ldap_pvt_url_scheme2proto(const char *); +extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, + LDAP **ld); +#endif + +static CURLcode ldap_setup_connection(struct connectdata *conn); +static CURLcode ldap_do(struct connectdata *conn, bool *done); +static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); +static CURLcode ldap_connect(struct connectdata *conn, bool *done); +static CURLcode ldap_connecting(struct connectdata *conn, bool *done); +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead); + +static Curl_recv ldap_recv; + +/* + * LDAP protocol handler. + */ + +const struct Curl_handler Curl_handler_ldap = { + "LDAP", /* scheme */ + ldap_setup_connection, /* setup_connection */ + ldap_do, /* do_it */ + ldap_done, /* done */ + ZERO_NULL, /* do_more */ + ldap_connect, /* connect_it */ + ldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * LDAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ldaps = { + "LDAPS", /* scheme */ + ldap_setup_connection, /* setup_connection */ + ldap_do, /* do_it */ + ldap_done, /* done */ + ZERO_NULL, /* do_more */ + ldap_connect, /* connect_it */ + ldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAP, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + +static const char *url_errs[] = { + "success", + "out of memory", + "bad parameter", + "unrecognized scheme", + "unbalanced delimiter", + "bad URL", + "bad host or port", + "bad or missing attributes", + "bad or missing scope", + "bad or missing filter", + "bad or missing extensions" +}; + +typedef struct ldapconninfo { + LDAP *ld; + Curl_recv *recv; /* for stacking SSL handler */ + Curl_send *send; + int proto; + int msgid; + bool ssldone; + bool sslinst; + bool didbind; +} ldapconninfo; + +typedef struct ldapreqinfo { + int msgid; + int nument; +} ldapreqinfo; + +static CURLcode ldap_setup_connection(struct connectdata *conn) +{ + ldapconninfo *li; + LDAPURLDesc *lud; + struct Curl_easy *data = conn->data; + int rc, proto; + CURLcode status; + + rc = ldap_url_parse(data->change.url, &lud); + if(rc != LDAP_URL_SUCCESS) { + const char *msg = "url parsing problem"; + status = CURLE_URL_MALFORMAT; + if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if(rc == LDAP_URL_ERR_MEM) + status = CURLE_OUT_OF_MEMORY; + msg = url_errs[rc]; + } + failf(conn->data, "LDAP local: %s", msg); + return status; + } + proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); + ldap_free_urldesc(lud); + + li = calloc(1, sizeof(ldapconninfo)); + if(!li) + return CURLE_OUT_OF_MEMORY; + li->proto = proto; + conn->proto.generic = li; + connkeep(conn, "OpenLDAP default"); + return CURLE_OK; +} + +#ifdef USE_SSL +static Sockbuf_IO ldapsb_tls; +#endif + +static CURLcode ldap_connect(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + struct Curl_easy *data = conn->data; + int rc, proto = LDAP_VERSION3; + char hosturl[1024]; + char *ptr; + + (void)done; + + strcpy(hosturl, "ldap"); + ptr = hosturl + 4; + if(conn->handler->flags & PROTOPT_SSL) + *ptr++ = 's'; + msnprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", + conn->host.name, conn->remote_port); + +#ifdef CURL_OPENLDAP_DEBUG + static int do_trace = 0; + const char *env = getenv("CURL_OPENLDAP_TRACE"); + do_trace = (env && strtol(env, NULL, 10) > 0); + if(do_trace) { + ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace); + } +#endif + + rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); + if(rc) { + failf(data, "LDAP local: Cannot connect to %s, %s", + hosturl, ldap_err2string(rc)); + return CURLE_COULDNT_CONNECT; + } + + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + +#ifdef USE_SSL + if(conn->handler->flags & PROTOPT_SSL) { + CURLcode result; + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); + if(result) + return result; + } +#endif + + return CURLE_OK; +} + +static CURLcode ldap_connecting(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + struct Curl_easy *data = conn->data; + LDAPMessage *msg = NULL; + struct timeval tv = {0, 1}, *tvp; + int rc, err; + char *info = NULL; + +#ifdef USE_SSL + if(conn->handler->flags & PROTOPT_SSL) { + /* Is the SSL handshake complete yet? */ + if(!li->ssldone) { + CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + &li->ssldone); + if(result || !li->ssldone) + return result; + } + + /* Have we installed the libcurl SSL handlers into the sockbuf yet? */ + if(!li->sslinst) { + Sockbuf *sb; + ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); + ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn); + li->sslinst = TRUE; + li->recv = conn->recv[FIRSTSOCKET]; + li->send = conn->send[FIRSTSOCKET]; + } + } +#endif + + tvp = &tv; + + retry: + if(!li->didbind) { + char *binddn; + struct berval passwd; + + if(conn->bits.user_passwd) { + binddn = conn->user; + passwd.bv_val = conn->passwd; + passwd.bv_len = strlen(passwd.bv_val); + } + else { + binddn = NULL; + passwd.bv_val = NULL; + passwd.bv_len = 0; + } + rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd, + NULL, NULL, &li->msgid); + if(rc) + return CURLE_LDAP_CANNOT_BIND; + li->didbind = TRUE; + if(tvp) + return CURLE_OK; + } + + rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &msg); + if(rc < 0) { + failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc)); + return CURLE_LDAP_CANNOT_BIND; + } + if(rc == 0) { + /* timed out */ + return CURLE_OK; + } + + rc = ldap_parse_result(li->ld, msg, &err, NULL, &info, NULL, NULL, 1); + if(rc) { + failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc)); + return CURLE_LDAP_CANNOT_BIND; + } + + /* Try to fallback to LDAPv2? */ + if(err == LDAP_PROTOCOL_ERROR) { + int proto; + ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + if(proto == LDAP_VERSION3) { + if(info) { + ldap_memfree(info); + info = NULL; + } + proto = LDAP_VERSION2; + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + li->didbind = FALSE; + goto retry; + } + } + + if(err) { + failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc), + info ? info : ""); + if(info) + ldap_memfree(info); + return CURLE_LOGIN_DENIED; + } + + if(info) + ldap_memfree(info); + conn->recv[FIRSTSOCKET] = ldap_recv; + *done = TRUE; + + return CURLE_OK; +} + +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) +{ + ldapconninfo *li = conn->proto.generic; + (void) dead_connection; + + if(li) { + if(li->ld) { + ldap_unbind_ext(li->ld, NULL, NULL); + li->ld = NULL; + } + conn->proto.generic = NULL; + free(li); + } + return CURLE_OK; +} + +static CURLcode ldap_do(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + ldapreqinfo *lr; + CURLcode status = CURLE_OK; + int rc = 0; + LDAPURLDesc *ludp = NULL; + int msgid; + struct Curl_easy *data = conn->data; + + connkeep(conn, "OpenLDAP do"); + + infof(data, "LDAP local: %s\n", data->change.url); + + rc = ldap_url_parse(data->change.url, &ludp); + if(rc != LDAP_URL_SUCCESS) { + const char *msg = "url parsing problem"; + status = CURLE_URL_MALFORMAT; + if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if(rc == LDAP_URL_ERR_MEM) + status = CURLE_OUT_OF_MEMORY; + msg = url_errs[rc]; + } + failf(conn->data, "LDAP local: %s", msg); + return status; + } + + rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope, + ludp->lud_filter, ludp->lud_attrs, 0, + NULL, NULL, NULL, 0, &msgid); + ldap_free_urldesc(ludp); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); + return CURLE_LDAP_SEARCH_FAILED; + } + lr = calloc(1, sizeof(ldapreqinfo)); + if(!lr) + return CURLE_OUT_OF_MEMORY; + lr->msgid = msgid; + data->req.protop = lr; + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + *done = TRUE; + return CURLE_OK; +} + +static CURLcode ldap_done(struct connectdata *conn, CURLcode res, + bool premature) +{ + ldapreqinfo *lr = conn->data->req.protop; + + (void)res; + (void)premature; + + if(lr) { + /* if there was a search in progress, abandon it */ + if(lr->msgid) { + ldapconninfo *li = conn->proto.generic; + ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); + lr->msgid = 0; + } + conn->data->req.protop = NULL; + free(lr); + } + + return CURLE_OK; +} + +static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, + size_t len, CURLcode *err) +{ + ldapconninfo *li = conn->proto.generic; + struct Curl_easy *data = conn->data; + ldapreqinfo *lr = data->req.protop; + int rc, ret; + LDAPMessage *msg = NULL; + LDAPMessage *ent; + BerElement *ber = NULL; + struct timeval tv = {0, 1}; + + (void)len; + (void)buf; + (void)sockindex; + + rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg); + if(rc < 0) { + failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); + *err = CURLE_RECV_ERROR; + return -1; + } + + *err = CURLE_AGAIN; + ret = -1; + + /* timed out */ + if(!msg) + return ret; + + for(ent = ldap_first_message(li->ld, msg); ent; + ent = ldap_next_message(li->ld, ent)) { + struct berval bv, *bvals; + int binary = 0, msgtype; + CURLcode writeerr; + + msgtype = ldap_msgtype(ent); + if(msgtype == LDAP_RES_SEARCH_RESULT) { + int code; + char *info = NULL; + rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); + if(rc) { + failf(data, "LDAP local: search ldap_parse_result %s", + ldap_err2string(rc)); + *err = CURLE_LDAP_SEARCH_FAILED; + } + else if(code && code != LDAP_SIZELIMIT_EXCEEDED) { + failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), + info ? info : ""); + *err = CURLE_LDAP_SEARCH_FAILED; + } + else { + /* successful */ + if(code == LDAP_SIZELIMIT_EXCEEDED) + infof(data, "There are more than %d entries\n", lr->nument); + data->req.size = data->req.bytecount; + *err = CURLE_OK; + ret = 0; + } + lr->msgid = 0; + ldap_memfree(info); + break; + } + else if(msgtype != LDAP_RES_SEARCH_ENTRY) + continue; + + lr->nument++; + rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); + if(rc < 0) { + *err = CURLE_RECV_ERROR; + return -1; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount += bv.bv_len + 5; + + for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) { + int i; + + if(bv.bv_val == NULL) + break; + + if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) + binary = 1; + else + binary = 0; + + if(bvals == NULL) { + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); + if(writeerr) { + *err = writeerr; + return -1; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount += bv.bv_len + 3; + continue; + } + + for(i = 0; bvals[i].bv_val != NULL; i++) { + int binval = 0; + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount += bv.bv_len + 2; + + if(!binary) { + /* check for leading or trailing whitespace */ + if(ISSPACE(bvals[i].bv_val[0]) || + ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) + binval = 1; + else { + /* check for unprintable characters */ + unsigned int j; + for(j = 0; jreq.bytecount += 2; + if(val_b64_sz > 0) { + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, + val_b64_sz); + if(writeerr) { + *err = writeerr; + return -1; + } + free(val_b64); + data->req.bytecount += val_b64_sz; + } + } + else { + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); + if(writeerr) { + *err = writeerr; + return -1; + } + + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, + bvals[i].bv_len); + if(writeerr) { + *err = writeerr; + return -1; + } + + data->req.bytecount += bvals[i].bv_len + 1; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(writeerr) { + *err = writeerr; + return -1; + } + + data->req.bytecount++; + } + ber_memfree(bvals); + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount++; + } + writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + if(writeerr) { + *err = writeerr; + return -1; + } + data->req.bytecount++; + ber_free(ber, 0); + } + ldap_msgfree(msg); + return ret; +} + +#ifdef USE_SSL +static int +ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) +{ + sbiod->sbiod_pvt = arg; + return 0; +} + +static int +ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod) +{ + sbiod->sbiod_pvt = NULL; + return 0; +} + +/* We don't need to do anything because libcurl does it already */ +static int +ldapsb_tls_close(Sockbuf_IO_Desc *sbiod) +{ + (void)sbiod; + return 0; +} + +static int +ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) +{ + (void)arg; + if(opt == LBER_SB_OPT_DATA_READY) { + struct connectdata *conn = sbiod->sbiod_pvt; + return Curl_ssl_data_pending(conn, FIRSTSOCKET); + } + return 0; +} + +static ber_slen_t +ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct connectdata *conn = sbiod->sbiod_pvt; + ldapconninfo *li = conn->proto.generic; + ber_slen_t ret; + CURLcode err = CURLE_RECV_ERROR; + + ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err); + if(ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + return ret; +} + +static ber_slen_t +ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct connectdata *conn = sbiod->sbiod_pvt; + ldapconninfo *li = conn->proto.generic; + ber_slen_t ret; + CURLcode err = CURLE_SEND_ERROR; + + ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err); + if(ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + return ret; +} + +static Sockbuf_IO ldapsb_tls = +{ + ldapsb_tls_setup, + ldapsb_tls_remove, + ldapsb_tls_ctrl, + ldapsb_tls_read, + ldapsb_tls_write, + ldapsb_tls_close +}; +#endif /* USE_SSL */ + +#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ diff --git a/libcurl/lib/parsedate.c b/libcurl/lib/parsedate.c new file mode 100644 index 0000000..7ae5eb8 --- /dev/null +++ b/libcurl/lib/parsedate.c @@ -0,0 +1,607 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + A brief summary of the date string formats this parser groks: + + RFC 2616 3.3.1 + + Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 + Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + + we support dates without week day name: + + 06 Nov 1994 08:49:37 GMT + 06-Nov-94 08:49:37 GMT + Nov 6 08:49:37 1994 + + without the time zone: + + 06 Nov 1994 08:49:37 + 06-Nov-94 08:49:37 + + weird order: + + 1994 Nov 6 08:49:37 (GNU date fails) + GMT 08:49:37 06-Nov-94 Sunday + 94 6 Nov 08:49:37 (GNU date fails) + + time left out: + + 1994 Nov 6 + 06-Nov-94 + Sun Nov 6 94 + + unusual separators: + + 1994.Nov.6 + Sun/Nov/6/94/GMT + + commonly used time zone names: + + Sun, 06 Nov 1994 08:49:37 CET + 06 Nov 1994 08:49:37 EST + + time zones specified using RFC822 style: + + Sun, 12 Sep 2004 15:05:58 -0700 + Sat, 11 Sep 2004 21:32:11 +0200 + + compact numerical date strings: + + 20040912 15:05:58 -0700 + 20040911 +0200 + +*/ + +#include "curl_setup.h" + +#include + +#include +#include "strcase.h" +#include "warnless.h" +#include "parsedate.h" + +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output); + +#define PARSEDATE_OK 0 +#define PARSEDATE_FAIL -1 +#define PARSEDATE_LATER 1 +#define PARSEDATE_SOONER 2 + +#ifndef CURL_DISABLE_PARSEDATE + +const char * const Curl_wkday[] = +{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; +static const char * const weekday[] = +{ "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; +const char * const Curl_month[]= +{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +struct tzinfo { + char name[5]; + int offset; /* +/- in minutes */ +}; + +/* Here's a bunch of frequently used time zone names. These were supported + by the old getdate parser. */ +#define tDAYZONE -60 /* offset for daylight savings time */ +static const struct tzinfo tz[]= { + {"GMT", 0}, /* Greenwich Mean */ + {"UT", 0}, /* Universal Time */ + {"UTC", 0}, /* Universal (Coordinated) */ + {"WET", 0}, /* Western European */ + {"BST", 0 tDAYZONE}, /* British Summer */ + {"WAT", 60}, /* West Africa */ + {"AST", 240}, /* Atlantic Standard */ + {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */ + {"EST", 300}, /* Eastern Standard */ + {"EDT", 300 tDAYZONE}, /* Eastern Daylight */ + {"CST", 360}, /* Central Standard */ + {"CDT", 360 tDAYZONE}, /* Central Daylight */ + {"MST", 420}, /* Mountain Standard */ + {"MDT", 420 tDAYZONE}, /* Mountain Daylight */ + {"PST", 480}, /* Pacific Standard */ + {"PDT", 480 tDAYZONE}, /* Pacific Daylight */ + {"YST", 540}, /* Yukon Standard */ + {"YDT", 540 tDAYZONE}, /* Yukon Daylight */ + {"HST", 600}, /* Hawaii Standard */ + {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */ + {"CAT", 600}, /* Central Alaska */ + {"AHST", 600}, /* Alaska-Hawaii Standard */ + {"NT", 660}, /* Nome */ + {"IDLW", 720}, /* International Date Line West */ + {"CET", -60}, /* Central European */ + {"MET", -60}, /* Middle European */ + {"MEWT", -60}, /* Middle European Winter */ + {"MEST", -60 tDAYZONE}, /* Middle European Summer */ + {"CEST", -60 tDAYZONE}, /* Central European Summer */ + {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ + {"FWT", -60}, /* French Winter */ + {"FST", -60 tDAYZONE}, /* French Summer */ + {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ + {"WAST", -420}, /* West Australian Standard */ + {"WADT", -420 tDAYZONE}, /* West Australian Daylight */ + {"CCT", -480}, /* China Coast, USSR Zone 7 */ + {"JST", -540}, /* Japan Standard, USSR Zone 8 */ + {"EAST", -600}, /* Eastern Australian Standard */ + {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */ + {"GST", -600}, /* Guam Standard, USSR Zone 9 */ + {"NZT", -720}, /* New Zealand */ + {"NZST", -720}, /* New Zealand Standard */ + {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ + {"IDLE", -720}, /* International Date Line East */ + /* Next up: Military timezone names. RFC822 allowed these, but (as noted in + RFC 1123) had their signs wrong. Here we use the correct signs to match + actual military usage. + */ + {"A", 1 * 60}, /* Alpha */ + {"B", 2 * 60}, /* Bravo */ + {"C", 3 * 60}, /* Charlie */ + {"D", 4 * 60}, /* Delta */ + {"E", 5 * 60}, /* Echo */ + {"F", 6 * 60}, /* Foxtrot */ + {"G", 7 * 60}, /* Golf */ + {"H", 8 * 60}, /* Hotel */ + {"I", 9 * 60}, /* India */ + /* "J", Juliet is not used as a timezone, to indicate the observer's local + time */ + {"K", 10 * 60}, /* Kilo */ + {"L", 11 * 60}, /* Lima */ + {"M", 12 * 60}, /* Mike */ + {"N", -1 * 60}, /* November */ + {"O", -2 * 60}, /* Oscar */ + {"P", -3 * 60}, /* Papa */ + {"Q", -4 * 60}, /* Quebec */ + {"R", -5 * 60}, /* Romeo */ + {"S", -6 * 60}, /* Sierra */ + {"T", -7 * 60}, /* Tango */ + {"U", -8 * 60}, /* Uniform */ + {"V", -9 * 60}, /* Victor */ + {"W", -10 * 60}, /* Whiskey */ + {"X", -11 * 60}, /* X-ray */ + {"Y", -12 * 60}, /* Yankee */ + {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */ +}; + +/* returns: + -1 no day + 0 monday - 6 sunday +*/ + +static int checkday(const char *check, size_t len) +{ + int i; + const char * const *what; + bool found = FALSE; + if(len > 3) + what = &weekday[0]; + else + what = &Curl_wkday[0]; + for(i = 0; i<7; i++) { + if(strcasecompare(check, what[0])) { + found = TRUE; + break; + } + what++; + } + return found?i:-1; +} + +static int checkmonth(const char *check) +{ + int i; + const char * const *what; + bool found = FALSE; + + what = &Curl_month[0]; + for(i = 0; i<12; i++) { + if(strcasecompare(check, what[0])) { + found = TRUE; + break; + } + what++; + } + return found?i:-1; /* return the offset or -1, no real offset is -1 */ +} + +/* return the time zone offset between GMT and the input one, in number + of seconds or -1 if the timezone wasn't found/legal */ + +static int checktz(const char *check) +{ + unsigned int i; + const struct tzinfo *what; + bool found = FALSE; + + what = tz; + for(i = 0; i< sizeof(tz)/sizeof(tz[0]); i++) { + if(strcasecompare(check, what->name)) { + found = TRUE; + break; + } + what++; + } + return found?what->offset*60:-1; +} + +static void skip(const char **date) +{ + /* skip everything that aren't letters or digits */ + while(**date && !ISALNUM(**date)) + (*date)++; +} + +enum assume { + DATE_MDAY, + DATE_YEAR, + DATE_TIME +}; + +/* this is a clone of 'struct tm' but with all fields we don't need or use + cut out */ +struct my_tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; /* full year */ +}; + +/* struct tm to time since epoch in GMT time zone. + * This is similar to the standard mktime function but for GMT only, and + * doesn't suffer from the various bugs and portability problems that + * some systems' implementations have. + * + * Returns 0 on success, otherwise non-zero. + */ +static void my_timegm(struct my_tm *tm, time_t *t) +{ + static const int month_days_cumulative [12] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + int month, year, leap_days; + + year = tm->tm_year; + month = tm->tm_mon; + if(month < 0) { + year += (11 - month) / 12; + month = 11 - (11 - month) % 12; + } + else if(month >= 12) { + year -= month / 12; + month = month % 12; + } + + leap_days = year - (tm->tm_mon <= 1); + leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) + - (1969 / 4) + (1969 / 100) - (1969 / 400)); + + *t = ((((time_t) (year - 1970) * 365 + + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24 + + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec; +} + +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output) +{ + time_t t = 0; + int wdaynum = -1; /* day of the week number, 0-6 (mon-sun) */ + int monnum = -1; /* month of the year number, 0-11 */ + int mdaynum = -1; /* day of month, 1 - 31 */ + int hournum = -1; + int minnum = -1; + int secnum = -1; + int yearnum = -1; + int tzoff = -1; + struct my_tm tm; + enum assume dignext = DATE_MDAY; + const char *indate = date; /* save the original pointer */ + int part = 0; /* max 6 parts */ + + while(*date && (part < 6)) { + bool found = FALSE; + + skip(&date); + + if(ISALPHA(*date)) { + /* a name coming up */ + char buf[32]=""; + size_t len; + if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz]", buf)) + len = strlen(buf); + else + len = 0; + + if(wdaynum == -1) { + wdaynum = checkday(buf, len); + if(wdaynum != -1) + found = TRUE; + } + if(!found && (monnum == -1)) { + monnum = checkmonth(buf); + if(monnum != -1) + found = TRUE; + } + + if(!found && (tzoff == -1)) { + /* this just must be a time zone string */ + tzoff = checktz(buf); + if(tzoff != -1) + found = TRUE; + } + + if(!found) + return PARSEDATE_FAIL; /* bad string */ + + date += len; + } + else if(ISDIGIT(*date)) { + /* a digit */ + int val; + char *end; + int len = 0; + if((secnum == -1) && + (3 == sscanf(date, "%02d:%02d:%02d%n", + &hournum, &minnum, &secnum, &len))) { + /* time stamp! */ + date += len; + } + else if((secnum == -1) && + (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) { + /* time stamp without seconds */ + date += len; + secnum = 0; + } + else { + long lval; + int error; + int old_errno; + + old_errno = errno; + errno = 0; + lval = strtol(date, &end, 10); + error = errno; + if(errno != old_errno) + errno = old_errno; + + if(error) + return PARSEDATE_FAIL; + +#if LONG_MAX != INT_MAX + if((lval > (long)INT_MAX) || (lval < (long)INT_MIN)) + return PARSEDATE_FAIL; +#endif + + val = curlx_sltosi(lval); + + if((tzoff == -1) && + ((end - date) == 4) && + (val <= 1400) && + (indate< date) && + ((date[-1] == '+' || date[-1] == '-'))) { + /* four digits and a value less than or equal to 1400 (to take into + account all sorts of funny time zone diffs) and it is preceded + with a plus or minus. This is a time zone indication. 1400 is + picked since +1300 is frequently used and +1400 is mentioned as + an edge number in the document "ISO C 200X Proposal: Timezone + Functions" at http://david.tribble.com/text/c0xtimezone.html If + anyone has a more authoritative source for the exact maximum time + zone offsets, please speak up! */ + found = TRUE; + tzoff = (val/100 * 60 + val%100)*60; + + /* the + and - prefix indicates the local time compared to GMT, + this we need their reversed math to get what we want */ + tzoff = date[-1]=='+'?-tzoff:tzoff; + } + + if(((end - date) == 8) && + (yearnum == -1) && + (monnum == -1) && + (mdaynum == -1)) { + /* 8 digits, no year, month or day yet. This is YYYYMMDD */ + found = TRUE; + yearnum = val/10000; + monnum = (val%10000)/100-1; /* month is 0 - 11 */ + mdaynum = val%100; + } + + if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { + if((val > 0) && (val<32)) { + mdaynum = val; + found = TRUE; + } + dignext = DATE_YEAR; + } + + if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { + yearnum = val; + found = TRUE; + if(yearnum < 100) { + if(yearnum > 70) + yearnum += 1900; + else + yearnum += 2000; + } + if(mdaynum == -1) + dignext = DATE_MDAY; + } + + if(!found) + return PARSEDATE_FAIL; + + date = end; + } + } + + part++; + } + + if(-1 == secnum) + secnum = minnum = hournum = 0; /* no time, make it zero */ + + if((-1 == mdaynum) || + (-1 == monnum) || + (-1 == yearnum)) + /* lacks vital info, fail */ + return PARSEDATE_FAIL; + +#ifdef HAVE_TIME_T_UNSIGNED + if(yearnum < 1970) { + /* only positive numbers cannot return earlier */ + *output = TIME_T_MIN; + return PARSEDATE_SOONER; + } +#endif + +#if (SIZEOF_TIME_T < 5) + +#ifdef HAVE_TIME_T_UNSIGNED + /* an unsigned 32 bit time_t can only hold dates to 2106 */ + if(yearnum > 2105) { + *output = TIME_T_MAX; + return PARSEDATE_LATER; + } +#else + /* a signed 32 bit time_t can only hold dates to the beginning of 2038 */ + if(yearnum > 2037) { + *output = TIME_T_MAX; + return PARSEDATE_LATER; + } + if(yearnum < 1903) { + *output = TIME_T_MIN; + return PARSEDATE_SOONER; + } +#endif + +#else + /* The Gregorian calendar was introduced 1582 */ + if(yearnum < 1583) + return PARSEDATE_FAIL; +#endif + + if((mdaynum > 31) || (monnum > 11) || + (hournum > 23) || (minnum > 59) || (secnum > 60)) + return PARSEDATE_FAIL; /* clearly an illegal date */ + + tm.tm_sec = secnum; + tm.tm_min = minnum; + tm.tm_hour = hournum; + tm.tm_mday = mdaynum; + tm.tm_mon = monnum; + tm.tm_year = yearnum; + + /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on + architectures that feature 64 bit 'long' but ultimately time_t is the + correct data type to use. + */ + my_timegm(&tm, &t); + + /* Add the time zone diff between local time zone and GMT. */ + if(tzoff == -1) + tzoff = 0; + + if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) { + *output = TIME_T_MAX; + return PARSEDATE_LATER; /* time_t overflow */ + } + + t += tzoff; + + *output = t; + + return PARSEDATE_OK; +} +#else +/* disabled */ +static int parsedate(const char *date, time_t *output) +{ + (void)date; + *output = 0; + return PARSEDATE_OK; /* a lie */ +} +#endif + +time_t curl_getdate(const char *p, const time_t *now) +{ + time_t parsed = -1; + int rc = parsedate(p, &parsed); + (void)now; /* legacy argument from the past that we ignore */ + + if(rc == PARSEDATE_OK) { + if(parsed == -1) + /* avoid returning -1 for a working scenario */ + parsed++; + return parsed; + } + /* everything else is fail */ + return -1; +} + +/* + * Curl_gmtime() is a gmtime() replacement for portability. Do not use the + * gmtime_r() or gmtime() functions anywhere else but here. + * + */ + +CURLcode Curl_gmtime(time_t intime, struct tm *store) +{ + const struct tm *tm; +#ifdef HAVE_GMTIME_R + /* thread-safe version */ + tm = (struct tm *)gmtime_r(&intime, store); +#else + tm = gmtime(&intime); + if(tm) + *store = *tm; /* copy the pointed struct to the local copy */ +#endif + + if(!tm) + return CURLE_BAD_FUNCTION_ARGUMENT; + return CURLE_OK; +} diff --git a/libcurl/lib/parsedate.h b/libcurl/lib/parsedate.h new file mode 100644 index 0000000..8dc3b90 --- /dev/null +++ b/libcurl/lib/parsedate.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_PARSEDATE_H +#define HEADER_CURL_PARSEDATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +extern const char * const Curl_wkday[7]; +extern const char * const Curl_month[12]; + +CURLcode Curl_gmtime(time_t intime, struct tm *store); + +#endif /* HEADER_CURL_PARSEDATE_H */ diff --git a/libcurl/lib/pingpong.c b/libcurl/lib/pingpong.c new file mode 100644 index 0000000..e9568ee --- /dev/null +++ b/libcurl/lib/pingpong.c @@ -0,0 +1,522 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * 'pingpong' is for generic back-and-forth support functions used by FTP, + * IMAP, POP3, SMTP and whatever more that likes them. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "progress.h" +#include "speedcheck.h" +#include "pingpong.h" +#include "multiif.h" +#include "non-ascii.h" +#include "vtls/vtls.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef USE_PINGPONG + +/* Returns timeout in ms. 0 or negative number means the timeout has already + triggered */ +time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting) +{ + struct connectdata *conn = pp->conn; + struct Curl_easy *data = conn->data; + time_t timeout_ms; /* in milliseconds */ + long response_time = (data->set.server_response_timeout)? + data->set.server_response_timeout: pp->response_time; + + /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine + remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is + supposed to govern the response for any given server response, not for + the time from connect to the given server response. */ + + /* Without a requested timeout, we only wait 'response_time' seconds for the + full response to arrive before we bail out */ + timeout_ms = response_time - + Curl_timediff(Curl_now(), pp->response); /* spent time */ + + if(data->set.timeout && !disconnecting) { + /* if timeout is requested, find out how much remaining time we have */ + time_t timeout2_ms = data->set.timeout - /* timeout time */ + Curl_timediff(Curl_now(), conn->now); /* spent time */ + + /* pick the lowest number */ + timeout_ms = CURLMIN(timeout_ms, timeout2_ms); + } + + return timeout_ms; +} + +/* + * Curl_pp_statemach() + */ +CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, + bool disconnecting) +{ + struct connectdata *conn = pp->conn; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int rc; + time_t interval_ms; + time_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting); + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + + if(timeout_ms <= 0) { + failf(data, "server response timeout"); + return CURLE_OPERATION_TIMEDOUT; /* already too little time */ + } + + if(block) { + interval_ms = 1000; /* use 1 second timeout intervals */ + if(timeout_ms < interval_ms) + interval_ms = timeout_ms; + } + else + interval_ms = 0; /* immediate */ + + if(Curl_ssl_data_pending(conn, FIRSTSOCKET)) + rc = 1; + else if(Curl_pp_moredata(pp)) + /* We are receiving and there is data in the cache so just read it */ + rc = 1; + else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET)) + /* We are receiving and there is data ready in the SSL library */ + rc = 1; + else + rc = Curl_socket_check(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ + CURL_SOCKET_BAD, + pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ + interval_ms); + + if(block) { + /* if we didn't wait, we don't have to spend time on this now */ + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, Curl_now()); + + if(result) + return result; + } + + if(rc == -1) { + failf(data, "select/poll error"); + result = CURLE_OUT_OF_MEMORY; + } + else if(rc) + result = pp->statemach_act(conn); + + return result; +} + +/* initialize stuff to prepare for reading a fresh new response */ +void Curl_pp_init(struct pingpong *pp) +{ + struct connectdata *conn = pp->conn; + pp->nread_resp = 0; + pp->linestart_resp = conn->data->state.buffer; + pp->pending_resp = TRUE; + pp->response = Curl_now(); /* start response time-out now! */ +} + + + +/*********************************************************************** + * + * Curl_pp_vsendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_vsendf(struct pingpong *pp, + const char *fmt, + va_list args) +{ + ssize_t bytes_written; + size_t write_len; + char *fmt_crlf; + char *s; + CURLcode result; + struct connectdata *conn = pp->conn; + struct Curl_easy *data; + +#ifdef HAVE_GSSAPI + enum protection_level data_sec; +#endif + + DEBUGASSERT(pp->sendleft == 0); + DEBUGASSERT(pp->sendsize == 0); + DEBUGASSERT(pp->sendthis == NULL); + + if(!conn) + /* can't send without a connection! */ + return CURLE_SEND_ERROR; + + data = conn->data; + + fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */ + if(!fmt_crlf) + return CURLE_OUT_OF_MEMORY; + + s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */ + free(fmt_crlf); + if(!s) + return CURLE_OUT_OF_MEMORY; + + bytes_written = 0; + write_len = strlen(s); + + Curl_pp_init(pp); + + result = Curl_convert_to_network(data, s, write_len); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) { + free(s); + return result; + } + +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CMD; +#endif + result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, + &bytes_written); +#ifdef HAVE_GSSAPI + data_sec = conn->data_prot; + DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); + conn->data_prot = data_sec; +#endif + + if(result) { + free(s); + return result; + } + + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written); + + if(bytes_written != (ssize_t)write_len) { + /* the whole chunk was not sent, keep it around and adjust sizes */ + pp->sendthis = s; + pp->sendsize = write_len; + pp->sendleft = write_len - bytes_written; + } + else { + free(s); + pp->sendthis = NULL; + pp->sendleft = pp->sendsize = 0; + pp->response = Curl_now(); + } + + return CURLE_OK; +} + + +/*********************************************************************** + * + * Curl_pp_sendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_sendf(struct pingpong *pp, + const char *fmt, ...) +{ + CURLcode result; + va_list ap; + va_start(ap, fmt); + + result = Curl_pp_vsendf(pp, fmt, ap); + + va_end(ap); + + return result; +} + +/* + * Curl_pp_readresp() + * + * Reads a piece of a server response. + */ +CURLcode Curl_pp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *code, /* return the server code if done */ + size_t *size) /* size of the response */ +{ + ssize_t perline; /* count bytes per line */ + bool keepon = TRUE; + ssize_t gotbytes; + char *ptr; + struct connectdata *conn = pp->conn; + struct Curl_easy *data = conn->data; + char * const buf = data->state.buffer; + CURLcode result = CURLE_OK; + + *code = 0; /* 0 for errors or not done */ + *size = 0; + + ptr = buf + pp->nread_resp; + + /* number of bytes in the current line, so far */ + perline = (ssize_t)(ptr-pp->linestart_resp); + + while((pp->nread_resp < (size_t)data->set.buffer_size) && + (keepon && !result)) { + + if(pp->cache) { + /* we had data in the "cache", copy that instead of doing an actual + * read + * + * pp->cache_size is cast to ssize_t here. This should be safe, because + * it would have been populated with something of size int to begin + * with, even though its datatype may be larger than an int. + */ + if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) { + failf(data, "cached response data too big to handle"); + return CURLE_RECV_ERROR; + } + memcpy(ptr, pp->cache, pp->cache_size); + gotbytes = (ssize_t)pp->cache_size; + free(pp->cache); /* free the cache */ + pp->cache = NULL; /* clear the pointer */ + pp->cache_size = 0; /* zero the size just in case */ + } + else { +#ifdef HAVE_GSSAPI + enum protection_level prot = conn->data_prot; + conn->data_prot = PROT_CLEAR; +#endif + DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <= + (buf + data->set.buffer_size + 1)); + result = Curl_read(conn, sockfd, ptr, + data->set.buffer_size - pp->nread_resp, + &gotbytes); +#ifdef HAVE_GSSAPI + DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST); + conn->data_prot = prot; +#endif + if(result == CURLE_AGAIN) + return CURLE_OK; /* return */ + + if(!result && (gotbytes > 0)) + /* convert from the network encoding */ + result = Curl_convert_from_network(data, ptr, gotbytes); + /* Curl_convert_from_network calls failf if unsuccessful */ + + if(result) + /* Set outer result variable to this error. */ + keepon = FALSE; + } + + if(!keepon) + ; + else if(gotbytes <= 0) { + keepon = FALSE; + result = CURLE_RECV_ERROR; + failf(data, "response reading failed"); + } + else { + /* we got a whole chunk of data, which can be anything from one + * byte to a set of lines and possible just a piece of the last + * line */ + ssize_t i; + ssize_t clipamount = 0; + bool restart = FALSE; + + data->req.headerbytecount += (long)gotbytes; + + pp->nread_resp += gotbytes; + for(i = 0; i < gotbytes; ptr++, i++) { + perline++; + if(*ptr == '\n') { + /* a newline is CRLF in pp-talk, so the CR is ignored as + the line isn't really terminated until the LF comes */ + + /* output debug output if that is requested */ +#ifdef HAVE_GSSAPI + if(!conn->sec_complete) +#endif + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + pp->linestart_resp, (size_t)perline); + + /* + * We pass all response-lines to the callback function registered + * for "headers". The response lines can be seen as a kind of + * headers. + */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + pp->linestart_resp, perline); + if(result) + return result; + + if(pp->endofresp(conn, pp->linestart_resp, perline, code)) { + /* This is the end of the last line, copy the last line to the + start of the buffer and zero terminate, for old times sake */ + size_t n = ptr - pp->linestart_resp; + memmove(buf, pp->linestart_resp, n); + buf[n] = 0; /* zero terminate */ + keepon = FALSE; + pp->linestart_resp = ptr + 1; /* advance pointer */ + i++; /* skip this before getting out */ + + *size = pp->nread_resp; /* size of the response */ + pp->nread_resp = 0; /* restart */ + break; + } + perline = 0; /* line starts over here */ + pp->linestart_resp = ptr + 1; + } + } + + if(!keepon && (i != gotbytes)) { + /* We found the end of the response lines, but we didn't parse the + full chunk of data we have read from the server. We therefore need + to store the rest of the data to be checked on the next invoke as + it may actually contain another end of response already! */ + clipamount = gotbytes - i; + restart = TRUE; + DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing " + "server response left\n", + (int)clipamount)); + } + else if(keepon) { + + if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) { + /* We got an excessive line without newlines and we need to deal + with it. We keep the first bytes of the line then we throw + away the rest. */ + infof(data, "Excessive server response line length received, " + "%zd bytes. Stripping\n", gotbytes); + restart = TRUE; + + /* we keep 40 bytes since all our pingpong protocols are only + interested in the first piece */ + clipamount = 40; + } + else if(pp->nread_resp > (size_t)data->set.buffer_size/2) { + /* We got a large chunk of data and there's potentially still + trailing data to take care of, so we put any such part in the + "cache", clear the buffer to make space and restart. */ + clipamount = perline; + restart = TRUE; + } + } + else if(i == gotbytes) + restart = TRUE; + + if(clipamount) { + pp->cache_size = clipamount; + pp->cache = malloc(pp->cache_size); + if(pp->cache) + memcpy(pp->cache, pp->linestart_resp, pp->cache_size); + else + return CURLE_OUT_OF_MEMORY; + } + if(restart) { + /* now reset a few variables to start over nicely from the start of + the big buffer */ + pp->nread_resp = 0; /* start over from scratch in the buffer */ + ptr = pp->linestart_resp = buf; + perline = 0; + } + + } /* there was data */ + + } /* while there's buffer left and loop is requested */ + + pp->pending_resp = FALSE; + + return result; +} + +int Curl_pp_getsock(struct pingpong *pp, + curl_socket_t *socks, + int numsocks) +{ + struct connectdata *conn = pp->conn; + + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + + if(pp->sendleft) { + /* write mode */ + return GETSOCK_WRITESOCK(0); + } + + /* read mode */ + return GETSOCK_READSOCK(0); +} + +CURLcode Curl_pp_flushsend(struct pingpong *pp) +{ + /* we have a piece of a command still left to send */ + struct connectdata *conn = pp->conn; + ssize_t written; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize - + pp->sendleft, pp->sendleft, &written); + if(result) + return result; + + if(written != (ssize_t)pp->sendleft) { + /* only a fraction was sent */ + pp->sendleft -= written; + } + else { + free(pp->sendthis); + pp->sendthis = NULL; + pp->sendleft = pp->sendsize = 0; + pp->response = Curl_now(); + } + return CURLE_OK; +} + +CURLcode Curl_pp_disconnect(struct pingpong *pp) +{ + free(pp->cache); + pp->cache = NULL; + return CURLE_OK; +} + +bool Curl_pp_moredata(struct pingpong *pp) +{ + return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ? + TRUE : FALSE; +} + +#endif diff --git a/libcurl/lib/pingpong.h b/libcurl/lib/pingpong.h new file mode 100644 index 0000000..dbe1f8d --- /dev/null +++ b/libcurl/lib/pingpong.h @@ -0,0 +1,151 @@ +#ifndef HEADER_CURL_PINGPONG_H +#define HEADER_CURL_PINGPONG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \ + !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP) +#define USE_PINGPONG +#endif + +/* forward-declaration, this is defined in urldata.h */ +struct connectdata; + +typedef enum { + FTPTRANSFER_BODY, /* yes do transfer a body */ + FTPTRANSFER_INFO, /* do still go through to get info/headers */ + FTPTRANSFER_NONE, /* don't get anything and don't get info */ + FTPTRANSFER_LAST /* end of list marker, never used */ +} curl_pp_transfer; + +/* + * 'pingpong' is the generic struct used for protocols doing server<->client + * conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc. + * + * It holds response cache and non-blocking sending data. + */ +struct pingpong { + char *cache; /* data cache between getresponse()-calls */ + size_t cache_size; /* size of cache in bytes */ + size_t nread_resp; /* number of bytes currently read of a server response */ + char *linestart_resp; /* line start pointer for the server response + reader function */ + bool pending_resp; /* set TRUE when a server response is pending or in + progress, and is cleared once the last response is + read */ + char *sendthis; /* allocated pointer to a buffer that is to be sent to the + server */ + size_t sendleft; /* number of bytes left to send from the sendthis buffer */ + size_t sendsize; /* total size of the sendthis buffer */ + struct curltime response; /* set to Curl_now() when a command has been sent + off, used to time-out response reading */ + long response_time; /* When no timeout is given, this is the amount of + milliseconds we await for a server response. */ + + struct connectdata *conn; /* points to the connectdata struct that this + belongs to */ + + /* Function pointers the protocols MUST implement and provide for the + pingpong layer to function */ + + CURLcode (*statemach_act)(struct connectdata *conn); + + bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len, + int *code); +}; + +/* + * Curl_pp_statemach() + * + * called repeatedly until done. Set 'wait' to make it wait a while on the + * socket if there's no traffic. + */ +CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, + bool disconnecting); + +/* initialize stuff to prepare for reading a fresh new response */ +void Curl_pp_init(struct pingpong *pp); + +/* Returns timeout in ms. 0 or negative number means the timeout has already + triggered */ +time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting); + + +/*********************************************************************** + * + * Curl_pp_sendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_sendf(struct pingpong *pp, + const char *fmt, ...); + +/*********************************************************************** + * + * Curl_pp_vsendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_vsendf(struct pingpong *pp, + const char *fmt, + va_list args); + +/* + * Curl_pp_readresp() + * + * Reads a piece of a server response. + */ +CURLcode Curl_pp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *code, /* return the server code if done */ + size_t *size); /* size of the response */ + + +CURLcode Curl_pp_flushsend(struct pingpong *pp); + +/* call this when a pingpong connection is disconnected */ +CURLcode Curl_pp_disconnect(struct pingpong *pp); + +int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks, + int numsocks); + + +/*********************************************************************** + * + * Curl_pp_moredata() + * + * Returns whether there are still more data in the cache and so a call + * to Curl_pp_readresp() will not block. + */ +bool Curl_pp_moredata(struct pingpong *pp); + +#endif /* HEADER_CURL_PINGPONG_H */ diff --git a/libcurl/lib/pipeline.c b/libcurl/lib/pipeline.c new file mode 100644 index 0000000..4d41b04 --- /dev/null +++ b/libcurl/lib/pipeline.c @@ -0,0 +1,403 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013, Linus Nielsen Feltzing, + * Copyright (C) 2013 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "multiif.h" +#include "pipeline.h" +#include "sendf.h" +#include "strcase.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +struct site_blacklist_entry { + struct curl_llist_element list; + unsigned short port; + char hostname[1]; +}; + +static void site_blacklist_llist_dtor(void *user, void *element) +{ + struct site_blacklist_entry *entry = element; + (void)user; + free(entry); +} + +static void server_blacklist_llist_dtor(void *user, void *element) +{ + (void)user; + free(element); +} + +bool Curl_pipeline_penalized(struct Curl_easy *data, + struct connectdata *conn) +{ + if(data) { + bool penalized = FALSE; + curl_off_t penalty_size = + Curl_multi_content_length_penalty_size(data->multi); + curl_off_t chunk_penalty_size = + Curl_multi_chunk_length_penalty_size(data->multi); + curl_off_t recv_size = -2; /* Make it easy to spot in the log */ + + /* Find the head of the recv pipe, if any */ + if(conn->recv_pipe.head) { + struct Curl_easy *recv_handle = conn->recv_pipe.head->ptr; + + recv_size = recv_handle->req.size; + + if(penalty_size > 0 && recv_size > penalty_size) + penalized = TRUE; + } + + if(chunk_penalty_size > 0 && + (curl_off_t)conn->chunk.datasize > chunk_penalty_size) + penalized = TRUE; + + infof(data, "Conn: %ld (%p) Receive pipe weight: (%" + CURL_FORMAT_CURL_OFF_T "/%zu), penalized: %s\n", + conn->connection_id, (void *)conn, recv_size, + conn->chunk.datasize, penalized?"TRUE":"FALSE"); + return penalized; + } + return FALSE; +} + +static CURLcode addHandleToPipeline(struct Curl_easy *data, + struct curl_llist *pipeline) +{ + Curl_llist_insert_next(pipeline, pipeline->tail, data, + &data->pipeline_queue); + return CURLE_OK; +} + + +CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle, + struct connectdata *conn) +{ + struct curl_llist_element *sendhead = conn->send_pipe.head; + struct curl_llist *pipeline; + CURLcode result; + + pipeline = &conn->send_pipe; + + result = addHandleToPipeline(handle, pipeline); + + if(pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head) { + /* this is a new one as head, expire it */ + Curl_pipeline_leave_write(conn); /* not in use yet */ + Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW); + } + +#if 0 /* enable for pipeline debugging */ + print_pipeline(conn); +#endif + + return result; +} + +/* Move this transfer from the sending list to the receiving list. + + Pay special attention to the new sending list "leader" as it needs to get + checked to update what sockets it acts on. + +*/ +void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle, + struct connectdata *conn) +{ + struct curl_llist_element *curr; + + curr = conn->send_pipe.head; + while(curr) { + if(curr->ptr == handle) { + Curl_llist_move(&conn->send_pipe, curr, + &conn->recv_pipe, conn->recv_pipe.tail); + + if(conn->send_pipe.head) { + /* Since there's a new easy handle at the start of the send pipeline, + set its timeout value to 1ms to make it trigger instantly */ + Curl_pipeline_leave_write(conn); /* not used now */ +#ifdef DEBUGBUILD + infof(conn->data, "%p is at send pipe head B!\n", + (void *)conn->send_pipe.head->ptr); +#endif + Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW); + } + + /* The receiver's list is not really interesting here since either this + handle is now first in the list and we'll deal with it soon, or + another handle is already first and thus is already taken care of */ + + break; /* we're done! */ + } + curr = curr->next; + } +} + +bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle, + struct connectdata *conn) +{ + if(handle->multi) { + struct curl_llist *blacklist = + Curl_multi_pipelining_site_bl(handle->multi); + + if(blacklist) { + struct curl_llist_element *curr; + + curr = blacklist->head; + while(curr) { + struct site_blacklist_entry *site; + + site = curr->ptr; + if(strcasecompare(site->hostname, conn->host.name) && + site->port == conn->remote_port) { + infof(handle, "Site %s:%d is pipeline blacklisted\n", + conn->host.name, conn->remote_port); + return TRUE; + } + curr = curr->next; + } + } + } + return FALSE; +} + +CURLMcode Curl_pipeline_set_site_blacklist(char **sites, + struct curl_llist *list) +{ + /* Free the old list */ + if(list->size) + Curl_llist_destroy(list, NULL); + + if(sites) { + Curl_llist_init(list, (curl_llist_dtor) site_blacklist_llist_dtor); + + /* Parse the URLs and populate the list */ + while(*sites) { + char *port; + struct site_blacklist_entry *entry; + + entry = malloc(sizeof(struct site_blacklist_entry) + strlen(*sites)); + if(!entry) { + Curl_llist_destroy(list, NULL); + return CURLM_OUT_OF_MEMORY; + } + strcpy(entry->hostname, *sites); + + port = strchr(entry->hostname, ':'); + if(port) { + *port = '\0'; + port++; + entry->port = (unsigned short)strtol(port, NULL, 10); + } + else { + /* Default port number for HTTP */ + entry->port = 80; + } + + Curl_llist_insert_next(list, list->tail, entry, &entry->list); + sites++; + } + } + + return CURLM_OK; +} + +struct blacklist_node { + struct curl_llist_element list; + char server_name[1]; +}; + +bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle, + char *server_name) +{ + if(handle->multi && server_name) { + struct curl_llist *list = + Curl_multi_pipelining_server_bl(handle->multi); + + struct curl_llist_element *e = list->head; + while(e) { + struct blacklist_node *bl = (struct blacklist_node *)e; + if(strncasecompare(bl->server_name, server_name, + strlen(bl->server_name))) { + infof(handle, "Server %s is blacklisted\n", server_name); + return TRUE; + } + e = e->next; + } + + DEBUGF(infof(handle, "Server %s is not blacklisted\n", server_name)); + } + return FALSE; +} + +CURLMcode Curl_pipeline_set_server_blacklist(char **servers, + struct curl_llist *list) +{ + /* Free the old list */ + if(list->size) + Curl_llist_destroy(list, NULL); + + if(servers) { + Curl_llist_init(list, (curl_llist_dtor) server_blacklist_llist_dtor); + + /* Parse the URLs and populate the list */ + while(*servers) { + struct blacklist_node *n; + size_t len = strlen(*servers); + + n = malloc(sizeof(struct blacklist_node) + len); + if(!n) { + Curl_llist_destroy(list, NULL); + return CURLM_OUT_OF_MEMORY; + } + strcpy(n->server_name, *servers); + + Curl_llist_insert_next(list, list->tail, n, &n->list); + servers++; + } + } + + + return CURLM_OK; +} + +static bool pipe_head(struct Curl_easy *data, + struct curl_llist *pipeline) +{ + if(pipeline) { + struct curl_llist_element *curr = pipeline->head; + if(curr) + return (curr->ptr == data) ? TRUE : FALSE; + } + return FALSE; +} + +/* returns TRUE if the given handle is head of the recv pipe */ +bool Curl_recvpipe_head(struct Curl_easy *data, + struct connectdata *conn) +{ + return pipe_head(data, &conn->recv_pipe); +} + +/* returns TRUE if the given handle is head of the send pipe */ +bool Curl_sendpipe_head(struct Curl_easy *data, + struct connectdata *conn) +{ + return pipe_head(data, &conn->send_pipe); +} + + +/* + * Check if the write channel is available and this handle as at the head, + * then grab the channel and return TRUE. + * + * If not available, return FALSE. + */ + +bool Curl_pipeline_checkget_write(struct Curl_easy *data, + struct connectdata *conn) +{ + if(conn->bits.multiplex) + /* when multiplexing, we can use it at once */ + return TRUE; + + if(!conn->writechannel_inuse && Curl_sendpipe_head(data, conn)) { + /* Grab the channel */ + conn->writechannel_inuse = TRUE; + return TRUE; + } + return FALSE; +} + + +/* + * Check if the read channel is available and this handle as at the head, then + * grab the channel and return TRUE. + * + * If not available, return FALSE. + */ + +bool Curl_pipeline_checkget_read(struct Curl_easy *data, + struct connectdata *conn) +{ + if(conn->bits.multiplex) + /* when multiplexing, we can use it at once */ + return TRUE; + + if(!conn->readchannel_inuse && Curl_recvpipe_head(data, conn)) { + /* Grab the channel */ + conn->readchannel_inuse = TRUE; + return TRUE; + } + return FALSE; +} + +/* + * The current user of the pipeline write channel gives it up. + */ +void Curl_pipeline_leave_write(struct connectdata *conn) +{ + conn->writechannel_inuse = FALSE; +} + +/* + * The current user of the pipeline read channel gives it up. + */ +void Curl_pipeline_leave_read(struct connectdata *conn) +{ + conn->readchannel_inuse = FALSE; +} + + +#if 0 +void print_pipeline(struct connectdata *conn) +{ + struct curl_llist_element *curr; + struct connectbundle *cb_ptr; + struct Curl_easy *data = conn->data; + + cb_ptr = conn->bundle; + + if(cb_ptr) { + curr = cb_ptr->conn_list->head; + while(curr) { + conn = curr->ptr; + infof(data, "- Conn %ld (%p) send_pipe: %zu, recv_pipe: %zu\n", + conn->connection_id, + (void *)conn, + conn->send_pipe->size, + conn->recv_pipe->size); + curr = curr->next; + } + } +} + +#endif diff --git a/libcurl/lib/pipeline.h b/libcurl/lib/pipeline.h new file mode 100644 index 0000000..413ba31 --- /dev/null +++ b/libcurl/lib/pipeline.h @@ -0,0 +1,56 @@ +#ifndef HEADER_CURL_PIPELINE_H +#define HEADER_CURL_PIPELINE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle, + struct connectdata *conn); +void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle, + struct connectdata *conn); +bool Curl_pipeline_penalized(struct Curl_easy *data, + struct connectdata *conn); + +bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle, + struct connectdata *conn); + +CURLMcode Curl_pipeline_set_site_blacklist(char **sites, + struct curl_llist *list_ptr); + +bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle, + char *server_name); + +CURLMcode Curl_pipeline_set_server_blacklist(char **servers, + struct curl_llist *list_ptr); + +bool Curl_pipeline_checkget_write(struct Curl_easy *data, + struct connectdata *conn); +bool Curl_pipeline_checkget_read(struct Curl_easy *data, + struct connectdata *conn); +void Curl_pipeline_leave_write(struct connectdata *conn); +void Curl_pipeline_leave_read(struct connectdata *conn); +bool Curl_recvpipe_head(struct Curl_easy *data, + struct connectdata *conn); +bool Curl_sendpipe_head(struct Curl_easy *data, + struct connectdata *conn); + +#endif /* HEADER_CURL_PIPELINE_H */ diff --git a/libcurl/lib/pop3.c b/libcurl/lib/pop3.c new file mode 100644 index 0000000..a681d52 --- /dev/null +++ b/libcurl/lib/pop3.c @@ -0,0 +1,1546 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC1734 POP3 Authentication + * RFC1939 POP3 protocol + * RFC2195 CRAM-MD5 authentication + * RFC2384 POP URL Scheme + * RFC2449 POP3 Extension Mechanism + * RFC2595 Using TLS with IMAP, POP3 and ACAP + * RFC2831 DIGEST-MD5 authentication + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC5034 POP3 SASL Authentication Mechanism + * RFC6749 OAuth 2.0 Authorization Framework + * RFC8314 Use of TLS for Email Submission and Access + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_POP3 + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "pop3.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "curl_sasl.h" +#include "curl_md5.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode pop3_do(struct connectdata *conn, bool *done); +static CURLcode pop3_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode pop3_connect(struct connectdata *conn, bool *done); +static CURLcode pop3_disconnect(struct connectdata *conn, bool dead); +static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done); +static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode pop3_setup_connection(struct connectdata *conn); +static CURLcode pop3_parse_url_options(struct connectdata *conn); +static CURLcode pop3_parse_url_path(struct connectdata *conn); +static CURLcode pop3_parse_custom_request(struct connectdata *conn); +static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, + const char *initresp); +static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp); +static void pop3_get_message(char *buffer, char **outptr); + +/* + * POP3 protocol handler. + */ + +const struct Curl_handler Curl_handler_pop3 = { + "POP3", /* scheme */ + pop3_setup_connection, /* setup_connection */ + pop3_do, /* do_it */ + pop3_done, /* done */ + ZERO_NULL, /* do_more */ + pop3_connect, /* connect_it */ + pop3_multi_statemach, /* connecting */ + pop3_doing, /* doing */ + pop3_getsock, /* proto_getsock */ + pop3_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + pop3_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_POP3, /* defport */ + CURLPROTO_POP3, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ + PROTOPT_URLOPTIONS +}; + +#ifdef USE_SSL +/* + * POP3S protocol handler. + */ + +const struct Curl_handler Curl_handler_pop3s = { + "POP3S", /* scheme */ + pop3_setup_connection, /* setup_connection */ + pop3_do, /* do_it */ + pop3_done, /* done */ + ZERO_NULL, /* do_more */ + pop3_connect, /* connect_it */ + pop3_multi_statemach, /* connecting */ + pop3_doing, /* doing */ + pop3_getsock, /* proto_getsock */ + pop3_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + pop3_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_POP3S, /* defport */ + CURLPROTO_POP3S, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL + | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */ +}; +#endif + +/* SASL parameters for the pop3 protocol */ +static const struct SASLproto saslpop3 = { + "pop", /* The service name */ + '*', /* Code received when continuation is expected */ + '+', /* Code to receive upon authentication success */ + 255 - 8, /* Maximum initial response length (no max) */ + pop3_perform_auth, /* Send authentication command */ + pop3_continue_auth, /* Send authentication continuation */ + pop3_get_message /* Get SASL response message */ +}; + +#ifdef USE_SSL +static void pop3_to_pop3s(struct connectdata *conn) +{ + /* Change the connection handler */ + conn->handler = &Curl_handler_pop3s; + + /* Set the connection's upgraded to TLS flag */ + conn->tls_upgraded = TRUE; +} +#else +#define pop3_to_pop3s(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * pop3_endofresp() + * + * Checks for an ending POP3 status code at the start of the given string, but + * also detects the APOP timestamp from the server greeting and various + * capabilities from the CAPA response including the supported authentication + * types and allowed SASL mechanisms. + */ +static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* Do we have an error response? */ + if(len >= 4 && !memcmp("-ERR", line, 4)) { + *resp = '-'; + + return TRUE; + } + + /* Are we processing CAPA command responses? */ + if(pop3c->state == POP3_CAPA) { + /* Do we have the terminating line? */ + if(len >= 1 && line[0] == '.') + /* Treat the response as a success */ + *resp = '+'; + else + /* Treat the response as an untagged continuation */ + *resp = '*'; + + return TRUE; + } + + /* Do we have a success response? */ + if(len >= 3 && !memcmp("+OK", line, 3)) { + *resp = '+'; + + return TRUE; + } + + /* Do we have a continuation response? */ + if(len >= 1 && line[0] == '+') { + *resp = '*'; + + return TRUE; + } + + return FALSE; /* Nothing for us */ +} + +/*********************************************************************** + * + * pop3_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void pop3_get_message(char *buffer, char **outptr) +{ + size_t len = strlen(buffer); + char *message = NULL; + + if(len > 2) { + /* Find the start of the message */ + len -= 2; + for(message = buffer + 2; *message == ' ' || *message == '\t'; + message++, len--) + ; + + /* Find the end of the message */ + for(; len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + } + else + /* junk input => zero length output */ + message = &buffer[len]; + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change POP3 state! + */ +static void state(struct connectdata *conn, pop3state newstate) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "STOP", + "SERVERGREET", + "CAPA", + "STARTTLS", + "UPGRADETLS", + "AUTH", + "APOP", + "USER", + "PASS", + "COMMAND", + "QUIT", + /* LAST */ + }; + + if(pop3c->state != newstate) + infof(conn->data, "POP3 %p state change from %s to %s\n", + (void *)pop3c, names[pop3c->state], names[newstate]); +#endif + + pop3c->state = newstate; +} + +/*********************************************************************** + * + * pop3_perform_capa() + * + * Sends the CAPA command in order to obtain a list of server side supported + * capabilities. + */ +static CURLcode pop3_perform_capa(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + pop3c->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */ + pop3c->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */ + pop3c->tls_supported = FALSE; /* Clear the TLS capability */ + + /* Send the CAPA command */ + result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA"); + + if(!result) + state(conn, POP3_CAPA); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_starttls() + * + * Sends the STLS command to start the upgrade to TLS. + */ +static CURLcode pop3_perform_starttls(struct connectdata *conn) +{ + /* Send the STLS command */ + CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS"); + + if(!result) + state(conn, POP3_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn) +{ + /* Start the SSL connection */ + struct pop3_conn *pop3c = &conn->proto.pop3c; + CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + &pop3c->ssldone); + + if(!result) { + if(pop3c->state != POP3_UPGRADETLS) + state(conn, POP3_UPGRADETLS); + + if(pop3c->ssldone) { + pop3_to_pop3s(conn); + result = pop3_perform_capa(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * pop3_perform_user() + * + * Sends a clear text USER command to authenticate with. + */ +static CURLcode pop3_perform_user(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, POP3_STOP); + + return result; + } + + /* Send the USER command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s", + conn->user ? conn->user : ""); + if(!result) + state(conn, POP3_USER); + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +/*********************************************************************** + * + * pop3_perform_apop() + * + * Sends an APOP command to authenticate with. + */ +static CURLcode pop3_perform_apop(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + size_t i; + MD5_context *ctxt; + unsigned char digest[MD5_DIGEST_LEN]; + char secret[2 * MD5_DIGEST_LEN + 1]; + + /* Check we have a username and password to authenticate with and end the + connect phase if we don't */ + if(!conn->bits.user_passwd) { + state(conn, POP3_STOP); + + return result; + } + + /* Create the digest */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp, + curlx_uztoui(strlen(pop3c->apoptimestamp))); + + Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd, + curlx_uztoui(strlen(conn->passwd))); + + /* Finalise the digest */ + Curl_MD5_final(ctxt, digest); + + /* Convert the calculated 16 octet digest into a 32 byte hex string */ + for(i = 0; i < MD5_DIGEST_LEN; i++) + msnprintf(&secret[2 * i], 3, "%02x", digest[i]); + + result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret); + + if(!result) + state(conn, POP3_APOP); + + return result; +} +#endif + +/*********************************************************************** + * + * pop3_perform_auth() + * + * Sends an AUTH command allowing the client to login with the given SASL + * authentication mechanism. + */ +static CURLcode pop3_perform_auth(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + if(initresp) { /* AUTH ... */ + /* Send the AUTH command with the initial response */ + result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp); + } + else { + /* Send the AUTH command */ + result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * pop3_continue_auth() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode pop3_continue_auth(struct connectdata *conn, + const char *resp) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + return Curl_pp_sendf(&pop3c->pp, "%s", resp); +} + +/*********************************************************************** + * + * pop3_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism, falling back to APOP and clear text should a + * common mechanism not be available between the client and server. + */ +static CURLcode pop3_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + saslprogress progress = SASL_IDLE; + + /* Check we have enough data to authenticate with and end the + connect phase if we don't */ + if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) { + state(conn, POP3_STOP); + return result; + } + + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) { + /* Calculate the SASL login details */ + result = Curl_sasl_start(&pop3c->sasl, conn, FALSE, &progress); + + if(!result) + if(progress == SASL_INPROGRESS) + state(conn, POP3_AUTH); + } + + if(!result && progress == SASL_IDLE) { +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) + /* Perform APOP authentication */ + result = pop3_perform_apop(conn); + else +#endif + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) + /* Perform clear text authentication */ + result = pop3_perform_user(conn); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * pop3_perform_command() + * + * Sends a POP3 based command. + */ +static CURLcode pop3_perform_command(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *command = NULL; + + /* Calculate the default command */ + if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) { + command = "LIST"; + + if(pop3->id[0] != '\0') + /* Message specific LIST so skip the BODY transfer */ + pop3->transfer = FTPTRANSFER_INFO; + } + else + command = "RETR"; + + /* Send the command */ + if(pop3->id[0] != '\0') + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s", + (pop3->custom && pop3->custom[0] != '\0' ? + pop3->custom : command), pop3->id); + else + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", + (pop3->custom && pop3->custom[0] != '\0' ? + pop3->custom : command)); + + if(!result) + state(conn, POP3_COMMAND); + + return result; +} + +/*********************************************************************** + * + * pop3_perform_quit() + * + * Performs the quit action prior to sclose() be called. + */ +static CURLcode pop3_perform_quit(struct connectdata *conn) +{ + /* Send the QUIT command */ + CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT"); + + if(!result) + state(conn, POP3_QUIT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode pop3_state_servergreet_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Got unexpected pop3-server response"); + result = CURLE_WEIRD_SERVER_REPLY; + } + else { + /* Does the server support APOP authentication? */ + if(len >= 4 && line[len - 2] == '>') { + /* Look for the APOP timestamp */ + size_t i; + for(i = 3; i < len - 2; ++i) { + if(line[i] == '<') { + /* Calculate the length of the timestamp */ + size_t timestamplen = len - 1 - i; + char *at; + if(!timestamplen) + break; + + /* Allocate some memory for the timestamp */ + pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1); + + if(!pop3c->apoptimestamp) + break; + + /* Copy the timestamp */ + memcpy(pop3c->apoptimestamp, line + i, timestamplen); + pop3c->apoptimestamp[timestamplen] = '\0'; + + /* If the timestamp does not contain '@' it is not (as required by + RFC-1939) conformant to the RFC-822 message id syntax, and we + therefore do not use APOP authentication. */ + at = strchr(pop3c->apoptimestamp, '@'); + if(!at) + Curl_safefree(pop3c->apoptimestamp); + else + /* Store the APOP capability */ + pop3c->authtypes |= POP3_TYPE_APOP; + break; + } + } + } + + result = pop3_perform_capa(conn); + } + + return result; +} + +/* For CAPA responses */ +static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + /* Do we have a untagged continuation response? */ + if(pop3code == '*') { + /* Does the server support the STLS capability? */ + if(len >= 4 && !memcmp(line, "STLS", 4)) + pop3c->tls_supported = TRUE; + + /* Does the server support clear text authentication? */ + else if(len >= 4 && !memcmp(line, "USER", 4)) + pop3c->authtypes |= POP3_TYPE_CLEARTEXT; + + /* Does the server support SASL based authentication? */ + else if(len >= 5 && !memcmp(line, "SASL ", 5)) { + pop3c->authtypes |= POP3_TYPE_SASL; + + /* Advance past the SASL keyword */ + line += 5; + len -= 5; + + /* Loop through the data line */ + for(;;) { + size_t llen; + size_t wordlen; + unsigned int mechbit; + + while(len && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + len--; + } + + if(!len) + break; + + /* Extract the word */ + for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Test the word for a matching authentication mechanism */ + mechbit = Curl_sasl_decode_mech(line, wordlen, &llen); + if(mechbit && llen == wordlen) + pop3c->sasl.authmechs |= mechbit; + + line += wordlen; + len -= wordlen; + } + } + } + else if(pop3code == '+') { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(pop3c->tls_supported) + /* Switch to TLS connection now */ + result = pop3_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = pop3_perform_authentication(conn); + else { + failf(data, "STLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = pop3_perform_authentication(conn); + } + else { + /* Clear text is supported when CAPA isn't recognised */ + pop3c->authtypes |= POP3_TYPE_CLEARTEXT; + + result = pop3_perform_authentication(conn); + } + + return result; +} + +/* For STARTTLS responses */ +static CURLcode pop3_state_starttls_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied"); + result = CURLE_USE_SSL_FAILED; + } + else + result = pop3_perform_authentication(conn); + } + else + result = pop3_perform_upgrade_tls(conn); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode pop3_state_auth_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct pop3_conn *pop3c = &conn->proto.pop3c; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&pop3c->sasl, conn, pop3code, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, POP3_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP) + /* Perform APOP authentication */ + result = pop3_perform_apop(conn); + else +#endif + if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT) + /* Perform clear text authentication */ + result = pop3_perform_user(conn); + else { + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + } + break; + default: + break; + } + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +/* For APOP responses */ +static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Authentication failed: %d", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, POP3_STOP); + + return result; +} +#endif + +/* For USER responses */ +static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied. %c", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* Send the PASS command */ + result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s", + conn->passwd ? conn->passwd : ""); + if(!result) + state(conn, POP3_PASS); + + return result; +} + +/* For PASS responses */ +static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + failf(data, "Access denied. %c", pop3code); + result = CURLE_LOGIN_DENIED; + } + else + /* End of connect phase */ + state(conn, POP3_STOP); + + return result; +} + +/* For command responses */ +static CURLcode pop3_state_command_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + + (void)instate; /* no use for this yet */ + + if(pop3code != '+') { + state(conn, POP3_STOP); + return CURLE_RECV_ERROR; + } + + /* This 'OK' line ends with a CR LF pair which is the two first bytes of the + EOB string so count this is two matching bytes. This is necessary to make + the code detect the EOB if the only data than comes now is %2e CR LF like + when there is no body to return. */ + pop3c->eob = 2; + + /* But since this initial CR LF pair is not part of the actual body, we set + the strip counter here so that these bytes won't be delivered. */ + pop3c->strip = 2; + + if(pop3->transfer == FTPTRANSFER_BODY) { + /* POP3 download */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + + if(pp->cache) { + /* The header "cache" contains a bunch of data that is actually body + content so send it as such. Note that there may even be additional + "headers" after the body */ + + if(!data->set.opt_no_body) { + result = Curl_pop3_write(conn, pp->cache, pp->cache_size); + if(result) + return result; + } + + /* Free the cache */ + Curl_safefree(pp->cache); + + /* Reset the cache size */ + pp->cache_size = 0; + } + } + + /* End of DO phase */ + state(conn, POP3_STOP); + + return result; +} + +static CURLcode pop3_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int pop3code; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */ + if(pop3c->state == POP3_UPGRADETLS) + return pop3_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &pop3code, &nread); + if(result) + return result; + + if(!pop3code) + break; + + /* We have now received a full POP3 server response */ + switch(pop3c->state) { + case POP3_SERVERGREET: + result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state); + break; + + case POP3_CAPA: + result = pop3_state_capa_resp(conn, pop3code, pop3c->state); + break; + + case POP3_STARTTLS: + result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); + break; + + case POP3_AUTH: + result = pop3_state_auth_resp(conn, pop3code, pop3c->state); + break; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + case POP3_APOP: + result = pop3_state_apop_resp(conn, pop3code, pop3c->state); + break; +#endif + + case POP3_USER: + result = pop3_state_user_resp(conn, pop3code, pop3c->state); + break; + + case POP3_PASS: + result = pop3_state_pass_resp(conn, pop3code, pop3c->state); + break; + + case POP3_COMMAND: + result = pop3_state_command_resp(conn, pop3code, pop3c->state); + break; + + case POP3_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, POP3_STOP); + break; + } + } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone); + if(result || !pop3c->ssldone) + return result; + } + + result = Curl_pp_statemach(&pop3c->pp, FALSE, FALSE); + *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode pop3_block_statemach(struct connectdata *conn, + bool disconnecting) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + + while(pop3c->state != POP3_STOP && !result) + result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting); + + return result; +} + +/* Allocate and initialize the POP3 struct for the current Curl_easy if + required */ +static CURLcode pop3_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3; + + pop3 = data->req.protop = calloc(sizeof(struct POP3), 1); + if(!pop3) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the POP3 "protocol connect" and "doing" phases only */ +static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.pop3c.pp, socks, numsocks); +} + +/*********************************************************************** + * + * pop3_connect() + * + * This function should do everything that is to be considered a part of the + * connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + */ +static CURLcode pop3_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + struct pingpong *pp = &pop3c->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in POP3 */ + connkeep(conn, "POP3 default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = pop3_statemach_act; + pp->endofresp = pop3_endofresp; + pp->conn = conn; + + /* Set the default preferred authentication type and mechanism */ + pop3c->preftype = POP3_TYPE_ANY; + Curl_sasl_init(&pop3c->sasl, &saslpop3); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = pop3_parse_url_options(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, POP3_SERVERGREET); + + result = pop3_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * pop3_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode pop3_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + + (void)premature; + + if(!pop3) + return CURLE_OK; + + if(status) { + connclose(conn, "POP3 done with bad status"); + result = status; /* use the already set error code */ + } + + /* Cleanup our per-request based variables */ + Curl_safefree(pop3->id); + Curl_safefree(pop3->custom); + + /* Clear the transfer mode for the next request */ + pop3->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * pop3_perform() + * + * This is the actual DO function for POP3. Get a message/listing according to + * the options previously setup. + */ +static CURLcode pop3_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is POP3 and no proxy */ + CURLcode result = CURLE_OK; + struct POP3 *pop3 = conn->data->req.protop; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* Requested no body means no transfer */ + pop3->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Start the first command in the DO phase */ + result = pop3_perform_command(conn); + if(result) + return result; + + /* Run the state-machine */ + result = pop3_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * pop3_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (pop3_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode pop3_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the URL path */ + result = pop3_parse_url_path(conn); + if(result) + return result; + + /* Parse the custom request */ + result = pop3_parse_custom_request(conn); + if(result) + return result; + + result = pop3_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * pop3_disconnect() + * + * Disconnect from an POP3 server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct pop3_conn *pop3c = &conn->proto.pop3c; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The POP3 session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart) + if(!pop3_perform_quit(conn)) + (void)pop3_block_statemach(conn, TRUE); /* ignore errors on QUIT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&pop3c->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, pop3c->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(pop3c->apoptimestamp); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected) +{ + (void)conn; + (void)connected; + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = pop3_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = pop3_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * pop3_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode pop3_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct Curl_easy *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = pop3_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = pop3_dophase_done(conn, connected); + + return result; +} + +static CURLcode pop3_setup_connection(struct connectdata *conn) +{ + /* Initialise the POP3 layer */ + CURLcode result = pop3_init(conn); + if(result) + return result; + + /* Clear the TLS upgraded flag */ + conn->tls_upgraded = FALSE; + + return CURLE_OK; +} + +/*********************************************************************** + * + * pop3_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode pop3_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct pop3_conn *pop3c = &conn->proto.pop3c; + const char *ptr = conn->options; + + pop3c->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strncasecompare(key, "AUTH=", 5)) { + result = Curl_sasl_parse_url_auth_option(&pop3c->sasl, + value, ptr - value); + + if(result && strncasecompare(value, "+APOP", ptr - value)) { + pop3c->preftype = POP3_TYPE_APOP; + pop3c->sasl.prefmech = SASL_AUTH_NONE; + result = CURLE_OK; + } + } + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + if(pop3c->preftype != POP3_TYPE_APOP) + switch(pop3c->sasl.prefmech) { + case SASL_AUTH_NONE: + pop3c->preftype = POP3_TYPE_NONE; + break; + case SASL_AUTH_DEFAULT: + pop3c->preftype = POP3_TYPE_ANY; + break; + default: + pop3c->preftype = POP3_TYPE_SASL; + break; + } + + return result; +} + +/*********************************************************************** + * + * pop3_parse_url_path() + * + * Parse the URL path into separate path components. + */ +static CURLcode pop3_parse_url_path(struct connectdata *conn) +{ + /* The POP3 struct is already initialised in pop3_connect() */ + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *path = &data->state.up.path[1]; /* skip leading path */ + + /* URL decode the path for the message ID */ + return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE); +} + +/*********************************************************************** + * + * pop3_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode pop3_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct POP3 *pop3 = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + /* URL decode the custom request */ + if(custom) + result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE); + + return result; +} + +/*********************************************************************** + * + * Curl_pop3_write() + * + * This function scans the body after the end-of-body and writes everything + * until the end is found. + */ +CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) +{ + /* This code could be made into a special function in the handler struct */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; + + struct pop3_conn *pop3c = &conn->proto.pop3c; + bool strip_dot = FALSE; + size_t last = 0; + size_t i; + + /* Search through the buffer looking for the end-of-body marker which is + 5 bytes (0d 0a 2e 0d 0a). Note that a line starting with a dot matches + the eob so the server will have prefixed it with an extra dot which we + need to strip out. Additionally the marker could of course be spread out + over 5 different data chunks. */ + for(i = 0; i < nread; i++) { + size_t prev = pop3c->eob; + + switch(str[i]) { + case 0x0d: + if(pop3c->eob == 0) { + pop3c->eob++; + + if(i) { + /* Write out the body part that didn't match */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], + i - last); + + if(result) + return result; + + last = i; + } + } + else if(pop3c->eob == 3) + pop3c->eob++; + else + /* If the character match wasn't at position 0 or 3 then restart the + pattern matching */ + pop3c->eob = 1; + break; + + case 0x0a: + if(pop3c->eob == 1 || pop3c->eob == 4) + pop3c->eob++; + else + /* If the character match wasn't at position 1 or 4 then start the + search again */ + pop3c->eob = 0; + break; + + case 0x2e: + if(pop3c->eob == 2) + pop3c->eob++; + else if(pop3c->eob == 3) { + /* We have an extra dot after the CRLF which we need to strip off */ + strip_dot = TRUE; + pop3c->eob = 0; + } + else + /* If the character match wasn't at position 2 then start the search + again */ + pop3c->eob = 0; + break; + + default: + pop3c->eob = 0; + break; + } + + /* Did we have a partial match which has subsequently failed? */ + if(prev && prev >= pop3c->eob) { + /* Strip can only be non-zero for the very first mismatch after CRLF + and then both prev and strip are equal and nothing will be output + below */ + while(prev && pop3c->strip) { + prev--; + pop3c->strip--; + } + + if(prev) { + /* If the partial match was the CRLF and dot then only write the CRLF + as the server would have inserted the dot */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, + strip_dot ? prev - 1 : prev); + + if(result) + return result; + + last = i; + strip_dot = FALSE; + } + } + } + + if(pop3c->eob == POP3_EOB_LEN) { + /* We have a full match so the transfer is done, however we must transfer + the CRLF at the start of the EOB as this is considered to be part of the + message as per RFC-1939, sect. 3 */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2); + + k->keepon &= ~KEEP_RECV; + pop3c->eob = 0; + + return result; + } + + if(pop3c->eob) + /* While EOB is matching nothing should be output */ + return CURLE_OK; + + if(nread - last) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last], + nread - last); + } + + return result; +} + +#endif /* CURL_DISABLE_POP3 */ diff --git a/libcurl/lib/pop3.h b/libcurl/lib/pop3.h new file mode 100644 index 0000000..a8e697c --- /dev/null +++ b/libcurl/lib/pop3.h @@ -0,0 +1,95 @@ +#ifndef HEADER_CURL_POP3_H +#define HEADER_CURL_POP3_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * POP3 unique setup + ***************************************************************************/ +typedef enum { + POP3_STOP, /* do nothing state, stops the state machine */ + POP3_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + POP3_CAPA, + POP3_STARTTLS, + POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + POP3_AUTH, + POP3_APOP, + POP3_USER, + POP3_PASS, + POP3_COMMAND, + POP3_QUIT, + POP3_LAST /* never used */ +} pop3state; + +/* This POP3 struct is used in the Curl_easy. All POP3 data that is + connection-oriented must be in pop3_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct POP3 { + curl_pp_transfer transfer; + char *id; /* Message ID */ + char *custom; /* Custom Request */ +}; + +/* pop3_conn is used for struct connection-oriented data in the connectdata + struct */ +struct pop3_conn { + struct pingpong pp; + pop3state state; /* Always use pop3.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + size_t eob; /* Number of bytes of the EOB (End Of Body) that + have been received so far */ + size_t strip; /* Number of bytes from the start to ignore as + non-body */ + struct SASL sasl; /* SASL-related storage */ + unsigned int authtypes; /* Accepted authentication types */ + unsigned int preftype; /* Preferred authentication type */ + char *apoptimestamp; /* APOP timestamp from the server greeting */ + bool tls_supported; /* StartTLS capability supported by server */ +}; + +extern const struct Curl_handler Curl_handler_pop3; +extern const struct Curl_handler Curl_handler_pop3s; + +/* Authentication type flags */ +#define POP3_TYPE_CLEARTEXT (1 << 0) +#define POP3_TYPE_APOP (1 << 1) +#define POP3_TYPE_SASL (1 << 2) + +/* Authentication type values */ +#define POP3_TYPE_NONE 0 +#define POP3_TYPE_ANY ~0U + +/* This is the 5-bytes End-Of-Body marker for POP3 */ +#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" +#define POP3_EOB_LEN 5 + +/* This function scans the body after the end-of-body and writes everything + * until the end is found */ +CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread); + +#endif /* HEADER_CURL_POP3_H */ diff --git a/libcurl/lib/progress.c b/libcurl/lib/progress.c new file mode 100644 index 0000000..9f953ef --- /dev/null +++ b/libcurl/lib/progress.c @@ -0,0 +1,618 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "sendf.h" +#include "multiif.h" +#include "progress.h" +#include "curl_printf.h" + +/* check rate limits within this many recent milliseconds, at minimum. */ +#define MIN_RATE_LIMIT_PERIOD 3000 + +#ifndef CURL_DISABLE_PROGRESS_METER +/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero + byte) */ +static void time2str(char *r, curl_off_t seconds) +{ + curl_off_t h; + if(seconds <= 0) { + strcpy(r, "--:--:--"); + return; + } + h = seconds / CURL_OFF_T_C(3600); + if(h <= CURL_OFF_T_C(99)) { + curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60); + curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60)); + msnprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T + ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s); + } + else { + /* this equals to more than 99 hours, switch to a more suitable output + format to fit within the limits. */ + curl_off_t d = seconds / CURL_OFF_T_C(86400); + h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600); + if(d <= CURL_OFF_T_C(999)) + msnprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T + "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h); + else + msnprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d); + } +} + +/* The point of this function would be to return a string of the input data, + but never longer than 5 columns (+ one zero byte). + Add suffix k, M, G when suitable... */ +static char *max5data(curl_off_t bytes, char *max5) +{ +#define ONE_KILOBYTE CURL_OFF_T_C(1024) +#define ONE_MEGABYTE (CURL_OFF_T_C(1024) * ONE_KILOBYTE) +#define ONE_GIGABYTE (CURL_OFF_T_C(1024) * ONE_MEGABYTE) +#define ONE_TERABYTE (CURL_OFF_T_C(1024) * ONE_GIGABYTE) +#define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE) + + if(bytes < CURL_OFF_T_C(100000)) + msnprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE) + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE); + + else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE) + /* 'XX.XM' is good as long as we're less than 100 megs */ + msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0" + CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE, + (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) ); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) + + else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE) + /* 'XXXXM' is good until we're at 10000MB or above */ + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE); + + else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE) + /* 10000 MB - 100 GB, we show it as XX.XG */ + msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0" + CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE, + (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) ); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE) + /* up to 10000GB, display without decimal: XXXXG */ + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE); + + else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE) + /* up to 10000TB, display without decimal: XXXXT */ + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE); + + else + /* up to 10000PB, display without decimal: XXXXP */ + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE); + + /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number + can hold, but our data type is signed so 8192PB will be the maximum. */ + +#else + + else + msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE); + +#endif + + return max5; +} +#endif + +/* + + New proposed interface, 9th of February 2000: + + pgrsStartNow() - sets start time + pgrsSetDownloadSize(x) - known expected download size + pgrsSetUploadSize(x) - known expected upload size + pgrsSetDownloadCounter() - amount of data currently downloaded + pgrsSetUploadCounter() - amount of data currently uploaded + pgrsUpdate() - show progress + pgrsDone() - transfer complete + +*/ + +int Curl_pgrsDone(struct connectdata *conn) +{ + int rc; + struct Curl_easy *data = conn->data; + data->progress.lastshow = 0; + rc = Curl_pgrsUpdate(conn); /* the final (forced) update */ + if(rc) + return rc; + + if(!(data->progress.flags & PGRS_HIDE) && + !data->progress.callback) + /* only output if we don't use a progress callback and we're not + * hidden */ + fprintf(data->set.err, "\n"); + + data->progress.speeder_c = 0; /* reset the progress meter display */ + return 0; +} + +/* reset the known transfer sizes */ +void Curl_pgrsResetTransferSizes(struct Curl_easy *data) +{ + Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsSetUploadSize(data, -1); +} + +/* + * @unittest: 1399 + */ +void Curl_pgrsTime(struct Curl_easy *data, timerid timer) +{ + struct curltime now = Curl_now(); + time_t *delta = NULL; + + switch(timer) { + default: + case TIMER_NONE: + /* mistake filter */ + break; + case TIMER_STARTOP: + /* This is set at the start of a transfer */ + data->progress.t_startop = now; + break; + case TIMER_STARTSINGLE: + /* This is set at the start of each single fetch */ + data->progress.t_startsingle = now; + data->progress.is_t_startransfer_set = false; + break; + case TIMER_STARTACCEPT: + data->progress.t_acceptdata = now; + break; + case TIMER_NAMELOOKUP: + delta = &data->progress.t_nslookup; + break; + case TIMER_CONNECT: + delta = &data->progress.t_connect; + break; + case TIMER_APPCONNECT: + delta = &data->progress.t_appconnect; + break; + case TIMER_PRETRANSFER: + delta = &data->progress.t_pretransfer; + break; + case TIMER_STARTTRANSFER: + delta = &data->progress.t_starttransfer; + /* prevent updating t_starttransfer unless: + * 1) this is the first time we're setting t_starttransfer + * 2) a redirect has occurred since the last time t_starttransfer was set + * This prevents repeated invocations of the function from incorrectly + * changing the t_starttransfer time. + */ + if(data->progress.is_t_startransfer_set) { + return; + } + else { + data->progress.is_t_startransfer_set = true; + break; + } + case TIMER_POSTRANSFER: + /* this is the normal end-of-transfer thing */ + break; + case TIMER_REDIRECT: + data->progress.t_redirect = Curl_timediff_us(now, data->progress.start); + break; + } + if(delta) { + timediff_t us = Curl_timediff_us(now, data->progress.t_startsingle); + if(us < 1) + us = 1; /* make sure at least one microsecond passed */ + *delta += us; + } +} + +void Curl_pgrsStartNow(struct Curl_easy *data) +{ + data->progress.speeder_c = 0; /* reset the progress meter display */ + data->progress.start = Curl_now(); + data->progress.is_t_startransfer_set = false; + data->progress.ul_limit_start.tv_sec = 0; + data->progress.ul_limit_start.tv_usec = 0; + data->progress.dl_limit_start.tv_sec = 0; + data->progress.dl_limit_start.tv_usec = 0; + /* clear all bits except HIDE and HEADERS_OUT */ + data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT; + Curl_ratelimit(data, data->progress.start); +} + +/* + * This is used to handle speed limits, calculating how many milliseconds to + * wait until we're back under the speed limit, if needed. + * + * The way it works is by having a "starting point" (time & amount of data + * transferred by then) used in the speed computation, to be used instead of + * the start of the transfer. This starting point is regularly moved as + * transfer goes on, to keep getting accurate values (instead of average over + * the entire transfer). + * + * This function takes the current amount of data transferred, the amount at + * the starting point, the limit (in bytes/s), the time of the starting point + * and the current time. + * + * Returns 0 if no waiting is needed or when no waiting is needed but the + * starting point should be reset (to current); or the number of milliseconds + * to wait to get back under the speed limit. + */ +timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, + curl_off_t startsize, + curl_off_t limit, + struct curltime start, + struct curltime now) +{ + curl_off_t size = cursize - startsize; + time_t minimum; + time_t actual; + + if(!limit || !size) + return 0; + + /* + * 'minimum' is the number of milliseconds 'size' should take to download to + * stay below 'limit'. + */ + if(size < CURL_OFF_T_MAX/1000) + minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit); + else { + minimum = (time_t) (size / limit); + if(minimum < TIME_T_MAX/1000) + minimum *= 1000; + else + minimum = TIME_T_MAX; + } + + /* + * 'actual' is the time in milliseconds it took to actually download the + * last 'size' bytes. + */ + actual = Curl_timediff(now, start); + if(actual < minimum) { + /* if it downloaded the data faster than the limit, make it wait the + difference */ + return (minimum - actual); + } + + return 0; +} + +/* + * Set the number of downloaded bytes so far. + */ +void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size) +{ + data->progress.downloaded = size; +} + +/* + * Update the timestamp and sizestamp to use for rate limit calculations. + */ +void Curl_ratelimit(struct Curl_easy *data, struct curltime now) +{ + /* don't set a new stamp unless the time since last update is long enough */ + if(data->set.max_recv_speed > 0) { + if(Curl_timediff(now, data->progress.dl_limit_start) >= + MIN_RATE_LIMIT_PERIOD) { + data->progress.dl_limit_start = now; + data->progress.dl_limit_size = data->progress.downloaded; + } + } + if(data->set.max_send_speed > 0) { + if(Curl_timediff(now, data->progress.ul_limit_start) >= + MIN_RATE_LIMIT_PERIOD) { + data->progress.ul_limit_start = now; + data->progress.ul_limit_size = data->progress.uploaded; + } + } +} + +/* + * Set the number of uploaded bytes so far. + */ +void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size) +{ + data->progress.uploaded = size; +} + +void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size) +{ + if(size >= 0) { + data->progress.size_dl = size; + data->progress.flags |= PGRS_DL_SIZE_KNOWN; + } + else { + data->progress.size_dl = 0; + data->progress.flags &= ~PGRS_DL_SIZE_KNOWN; + } +} + +void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size) +{ + if(size >= 0) { + data->progress.size_ul = size; + data->progress.flags |= PGRS_UL_SIZE_KNOWN; + } + else { + data->progress.size_ul = 0; + data->progress.flags &= ~PGRS_UL_SIZE_KNOWN; + } +} + +/* returns TRUE if it's time to show the progress meter */ +static bool progress_calc(struct connectdata *conn, struct curltime now) +{ + curl_off_t timespent; + curl_off_t timespent_ms; /* milliseconds */ + struct Curl_easy *data = conn->data; + curl_off_t dl = data->progress.downloaded; + curl_off_t ul = data->progress.uploaded; + bool timetoshow = FALSE; + + /* The time spent so far (from the start) */ + data->progress.timespent = Curl_timediff_us(now, data->progress.start); + timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */ + timespent_ms = (curl_off_t)data->progress.timespent/1000; /* ms */ + + /* The average download speed this far */ + if(dl < CURL_OFF_T_MAX/1000) + data->progress.dlspeed = (dl * 1000 / (timespent_ms>0?timespent_ms:1)); + else + data->progress.dlspeed = (dl / (timespent>0?timespent:1)); + + /* The average upload speed this far */ + if(ul < CURL_OFF_T_MAX/1000) + data->progress.ulspeed = (ul * 1000 / (timespent_ms>0?timespent_ms:1)); + else + data->progress.ulspeed = (ul / (timespent>0?timespent:1)); + + /* Calculations done at most once a second, unless end is reached */ + if(data->progress.lastshow != now.tv_sec) { + int countindex; /* amount of seconds stored in the speeder array */ + int nowindex = data->progress.speeder_c% CURR_TIME; + data->progress.lastshow = now.tv_sec; + timetoshow = TRUE; + + /* Let's do the "current speed" thing, with the dl + ul speeds + combined. Store the speed at entry 'nowindex'. */ + data->progress.speeder[ nowindex ] = + data->progress.downloaded + data->progress.uploaded; + + /* remember the exact time for this moment */ + data->progress.speeder_time [ nowindex ] = now; + + /* advance our speeder_c counter, which is increased every time we get + here and we expect it to never wrap as 2^32 is a lot of seconds! */ + data->progress.speeder_c++; + + /* figure out how many index entries of data we have stored in our speeder + array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of + transfer. Imagine, after one second we have filled in two entries, + after two seconds we've filled in three entries etc. */ + countindex = ((data->progress.speeder_c >= CURR_TIME)? + CURR_TIME:data->progress.speeder_c) - 1; + + /* first of all, we don't do this if there's no counted seconds yet */ + if(countindex) { + int checkindex; + timediff_t span_ms; + + /* Get the index position to compare with the 'nowindex' position. + Get the oldest entry possible. While we have less than CURR_TIME + entries, the first entry will remain the oldest. */ + checkindex = (data->progress.speeder_c >= CURR_TIME)? + data->progress.speeder_c%CURR_TIME:0; + + /* Figure out the exact time for the time span */ + span_ms = Curl_timediff(now, data->progress.speeder_time[checkindex]); + if(0 == span_ms) + span_ms = 1; /* at least one millisecond MUST have passed */ + + /* Calculate the average speed the last 'span_ms' milliseconds */ + { + curl_off_t amount = data->progress.speeder[nowindex]- + data->progress.speeder[checkindex]; + + if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */) + /* the 'amount' value is bigger than would fit in 32 bits if + multiplied with 1000, so we use the double math for this */ + data->progress.current_speed = (curl_off_t) + ((double)amount/((double)span_ms/1000.0)); + else + /* the 'amount' value is small enough to fit within 32 bits even + when multiplied with 1000 */ + data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms; + } + } + else + /* the first second we use the average */ + data->progress.current_speed = + data->progress.ulspeed + data->progress.dlspeed; + + } /* Calculations end */ + return timetoshow; +} + +#ifndef CURL_DISABLE_PROGRESS_METER +static void progress_meter(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + char max5[6][10]; + curl_off_t dlpercen = 0; + curl_off_t ulpercen = 0; + curl_off_t total_percen = 0; + curl_off_t total_transfer; + curl_off_t total_expected_transfer; + char time_left[10]; + char time_total[10]; + char time_spent[10]; + curl_off_t ulestimate = 0; + curl_off_t dlestimate = 0; + curl_off_t total_estimate; + curl_off_t timespent = + (curl_off_t)data->progress.timespent/1000000; /* seconds */ + + if(!(data->progress.flags & PGRS_HEADERS_OUT)) { + if(data->state.resume_from) { + fprintf(data->set.err, + "** Resuming transfer from byte position %" + CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); + } + fprintf(data->set.err, + " %% Total %% Received %% Xferd Average Speed " + "Time Time Time Current\n" + " Dload Upload " + "Total Spent Left Speed\n"); + data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */ + } + + /* Figure out the estimated time of arrival for the upload */ + if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && + (data->progress.ulspeed > CURL_OFF_T_C(0))) { + ulestimate = data->progress.size_ul / data->progress.ulspeed; + + if(data->progress.size_ul > CURL_OFF_T_C(10000)) + ulpercen = data->progress.uploaded / + (data->progress.size_ul/CURL_OFF_T_C(100)); + else if(data->progress.size_ul > CURL_OFF_T_C(0)) + ulpercen = (data->progress.uploaded*100) / + data->progress.size_ul; + } + + /* ... and the download */ + if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && + (data->progress.dlspeed > CURL_OFF_T_C(0))) { + dlestimate = data->progress.size_dl / data->progress.dlspeed; + + if(data->progress.size_dl > CURL_OFF_T_C(10000)) + dlpercen = data->progress.downloaded / + (data->progress.size_dl/CURL_OFF_T_C(100)); + else if(data->progress.size_dl > CURL_OFF_T_C(0)) + dlpercen = (data->progress.downloaded*100) / + data->progress.size_dl; + } + + /* Now figure out which of them is slower and use that one for the + total estimate! */ + total_estimate = ulestimate>dlestimate?ulestimate:dlestimate; + + /* create the three time strings */ + time2str(time_left, total_estimate > 0?(total_estimate - timespent):0); + time2str(time_total, total_estimate); + time2str(time_spent, timespent); + + /* Get the total amount of data expected to get transferred */ + total_expected_transfer = + ((data->progress.flags & PGRS_UL_SIZE_KNOWN)? + data->progress.size_ul:data->progress.uploaded)+ + ((data->progress.flags & PGRS_DL_SIZE_KNOWN)? + data->progress.size_dl:data->progress.downloaded); + + /* We have transferred this much so far */ + total_transfer = data->progress.downloaded + data->progress.uploaded; + + /* Get the percentage of data transferred so far */ + if(total_expected_transfer > CURL_OFF_T_C(10000)) + total_percen = total_transfer / + (total_expected_transfer/CURL_OFF_T_C(100)); + else if(total_expected_transfer > CURL_OFF_T_C(0)) + total_percen = (total_transfer*100) / total_expected_transfer; + + fprintf(data->set.err, + "\r" + "%3" CURL_FORMAT_CURL_OFF_T " %s " + "%3" CURL_FORMAT_CURL_OFF_T " %s " + "%3" CURL_FORMAT_CURL_OFF_T " %s %s %s %s %s %s %s", + total_percen, /* 3 letters */ /* total % */ + max5data(total_expected_transfer, max5[2]), /* total size */ + dlpercen, /* 3 letters */ /* rcvd % */ + max5data(data->progress.downloaded, max5[0]), /* rcvd size */ + ulpercen, /* 3 letters */ /* xfer % */ + max5data(data->progress.uploaded, max5[1]), /* xfer size */ + max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */ + max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */ + time_total, /* 8 letters */ /* total time */ + time_spent, /* 8 letters */ /* time spent */ + time_left, /* 8 letters */ /* time left */ + max5data(data->progress.current_speed, max5[5]) + ); + + /* we flush the output stream to make it appear as soon as possible */ + fflush(data->set.err); +} +#else + /* progress bar disabled */ +#define progress_meter(x) Curl_nop_stmt +#endif + + +/* + * Curl_pgrsUpdate() returns 0 for success or the value returned by the + * progress callback! + */ +int Curl_pgrsUpdate(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct curltime now = Curl_now(); /* what time is it */ + bool showprogress = progress_calc(conn, now); + if(!(data->progress.flags & PGRS_HIDE)) { + if(data->set.fxferinfo) { + int result; + /* There's a callback set, call that */ + Curl_set_in_callback(data, true); + result = data->set.fxferinfo(data->set.progress_client, + data->progress.size_dl, + data->progress.downloaded, + data->progress.size_ul, + data->progress.uploaded); + Curl_set_in_callback(data, false); + if(result) + failf(data, "Callback aborted"); + return result; + } + if(data->set.fprogress) { + int result; + /* The older deprecated callback is set, call that */ + Curl_set_in_callback(data, true); + result = data->set.fprogress(data->set.progress_client, + (double)data->progress.size_dl, + (double)data->progress.downloaded, + (double)data->progress.size_ul, + (double)data->progress.uploaded); + Curl_set_in_callback(data, false); + if(result) + failf(data, "Callback aborted"); + return result; + } + + if(showprogress) + progress_meter(conn); + } + + return 0; +} diff --git a/libcurl/lib/progress.h b/libcurl/lib/progress.h new file mode 100644 index 0000000..3515ac6 --- /dev/null +++ b/libcurl/lib/progress.h @@ -0,0 +1,64 @@ +#ifndef HEADER_CURL_PROGRESS_H +#define HEADER_CURL_PROGRESS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "timeval.h" + + +typedef enum { + TIMER_NONE, + TIMER_STARTOP, + TIMER_STARTSINGLE, + TIMER_NAMELOOKUP, + TIMER_CONNECT, + TIMER_APPCONNECT, + TIMER_PRETRANSFER, + TIMER_STARTTRANSFER, + TIMER_POSTRANSFER, + TIMER_STARTACCEPT, + TIMER_REDIRECT, + TIMER_LAST /* must be last */ +} timerid; + +int Curl_pgrsDone(struct connectdata *); +void Curl_pgrsStartNow(struct Curl_easy *data); +void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size); +void Curl_ratelimit(struct Curl_easy *data, struct curltime now); +int Curl_pgrsUpdate(struct connectdata *); +void Curl_pgrsResetTransferSizes(struct Curl_easy *data); +void Curl_pgrsTime(struct Curl_easy *data, timerid timer); +timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, + curl_off_t startsize, + curl_off_t limit, + struct curltime start, + struct curltime now); + +#define PGRS_HIDE (1<<4) +#define PGRS_UL_SIZE_KNOWN (1<<5) +#define PGRS_DL_SIZE_KNOWN (1<<6) +#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */ + +#endif /* HEADER_CURL_PROGRESS_H */ diff --git a/libcurl/lib/psl.c b/libcurl/lib/psl.c new file mode 100644 index 0000000..568baff --- /dev/null +++ b/libcurl/lib/psl.c @@ -0,0 +1,111 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifdef USE_LIBPSL + +#include "psl.h" +#include "share.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +void Curl_psl_destroy(struct PslCache *pslcache) +{ + if(pslcache->psl) { + if(pslcache->dynamic) + psl_free((psl_ctx_t *) pslcache->psl); + pslcache->psl = NULL; + pslcache->dynamic = FALSE; + } +} + +static time_t now_seconds(void) +{ + struct curltime now = Curl_now(); + + return now.tv_sec; +} + +const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy) +{ + struct PslCache *pslcache = easy->psl; + const psl_ctx_t *psl; + time_t now; + + if(!pslcache) + return NULL; + + Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED); + now = now_seconds(); + if(!pslcache->psl || pslcache->expires <= now) { + /* Let a chance to other threads to do the job: avoids deadlock. */ + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); + + /* Update cache: this needs an exclusive lock. */ + Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SINGLE); + + /* Recheck in case another thread did the job. */ + now = now_seconds(); + if(!pslcache->psl || pslcache->expires <= now) { + bool dynamic = FALSE; + time_t expires = TIME_T_MAX; + +#if defined(PSL_VERSION_NUMBER) && PSL_VERSION_NUMBER >= 0x001000 + psl = psl_latest(NULL); + dynamic = psl != NULL; + /* Take care of possible time computation overflow. */ + expires = now < TIME_T_MAX - PSL_TTL? now + PSL_TTL: TIME_T_MAX; + + /* Only get the built-in PSL if we do not already have the "latest". */ + if(!psl && !pslcache->dynamic) +#endif + + psl = psl_builtin(); + + if(psl) { + Curl_psl_destroy(pslcache); + pslcache->psl = psl; + pslcache->dynamic = dynamic; + pslcache->expires = expires; + } + } + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); /* Release exclusive lock. */ + Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED); + } + psl = pslcache->psl; + if(!psl) + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); + return psl; +} + +void Curl_psl_release(struct Curl_easy *easy) +{ + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); +} + +#endif /* USE_LIBPSL */ diff --git a/libcurl/lib/psl.h b/libcurl/lib/psl.h new file mode 100644 index 0000000..e9f99d0 --- /dev/null +++ b/libcurl/lib/psl.h @@ -0,0 +1,47 @@ +#ifndef HEADER_PSL_H +#define HEADER_PSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_LIBPSL +#include + +#define PSL_TTL (72 * 3600) /* PSL time to live before a refresh. */ + +struct PslCache { + const psl_ctx_t *psl; /* The PSL. */ + time_t expires; /* Time this PSL life expires. */ + bool dynamic; /* PSL should be released when no longer needed. */ +}; + +const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy); +void Curl_psl_release(struct Curl_easy *easy); +void Curl_psl_destroy(struct PslCache *pslcache); + +#else + +#define Curl_psl_use(easy) NULL +#define Curl_psl_release(easy) +#define Curl_psl_destroy(pslcache) + +#endif /* USE_LIBPSL */ +#endif /* HEADER_PSL_H */ diff --git a/libcurl/lib/rand.c b/libcurl/lib/rand.c new file mode 100644 index 0000000..c415048 --- /dev/null +++ b/libcurl/lib/rand.c @@ -0,0 +1,186 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include "vtls/vtls.h" +#include "sendf.h" +#include "rand.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) +{ + unsigned int r; + CURLcode result = CURLE_OK; + static unsigned int randseed; + static bool seeded = FALSE; + +#ifdef CURLDEBUG + char *force_entropy = getenv("CURL_ENTROPY"); + if(force_entropy) { + if(!seeded) { + unsigned int seed = 0; + size_t elen = strlen(force_entropy); + size_t clen = sizeof(seed); + size_t min = elen < clen ? elen : clen; + memcpy((char *)&seed, force_entropy, min); + randseed = ntohl(seed); + seeded = TRUE; + } + else + randseed++; + *rnd = randseed; + return CURLE_OK; + } +#endif + + /* data may be NULL! */ + result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd)); + if(result != CURLE_NOT_BUILT_IN) + /* only if there is no random function in the TLS backend do the non crypto + version, otherwise return result */ + return result; + + /* ---- non-cryptographic version following ---- */ + +#ifdef RANDOM_FILE + if(!seeded) { + /* if there's a random file to read a seed from, use it */ + int fd = open(RANDOM_FILE, O_RDONLY); + if(fd > -1) { + /* read random data into the randseed variable */ + ssize_t nread = read(fd, &randseed, sizeof(randseed)); + if(nread == sizeof(randseed)) + seeded = TRUE; + close(fd); + } + } +#endif + + if(!seeded) { + struct curltime now = Curl_now(); + infof(data, "WARNING: Using weak random seed\n"); + randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + seeded = TRUE; + } + + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + *rnd = (r << 16) | ((r >> 16) & 0xFFFF); + return CURLE_OK; +} + +/* + * Curl_rand() stores 'num' number of random unsigned integers in the buffer + * 'rndptr' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit or mbedTLS), this function will use "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ + +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + + DEBUGASSERT(num > 0); + + while(num) { + unsigned int r; + size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int); + + result = randit(data, &r); + if(result) + return result; + + while(left) { + *rnd++ = (unsigned char)(r & 0xFF); + r >>= 8; + --num; + --left; + } + } + + return result; +} + +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ + +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + const char *hex = "0123456789abcdef"; + unsigned char buffer[128]; + unsigned char *bufp = buffer; + DEBUGASSERT(num > 1); + +#ifdef __clang_analyzer__ + /* This silences a scan-build warning about accessing this buffer with + uninitialized memory. */ + memset(buffer, 0, sizeof(buffer)); +#endif + + if((num/2 >= sizeof(buffer)) || !(num&1)) + /* make sure it fits in the local buffer and that it is an odd number! */ + return CURLE_BAD_FUNCTION_ARGUMENT; + + num--; /* save one for zero termination */ + + result = Curl_rand(data, buffer, num/2); + if(result) + return result; + + while(num) { + /* clang-tidy warns on this line without this comment: */ + /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */ + *rnd++ = hex[(*bufp & 0xF0)>>4]; + *rnd++ = hex[*bufp & 0x0F]; + bufp++; + num -= 2; + } + *rnd = 0; + + return result; +} diff --git a/libcurl/lib/rand.h b/libcurl/lib/rand.h new file mode 100644 index 0000000..3c8e2b8 --- /dev/null +++ b/libcurl/lib/rand.h @@ -0,0 +1,49 @@ +#ifndef HEADER_CURL_RAND_H +#define HEADER_CURL_RAND_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Curl_rand() stores 'num' number of random unsigned characters in the buffer + * 'rnd' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit or mbedTLS), this function will use "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num); + +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num); + +#endif /* HEADER_CURL_RAND_H */ diff --git a/libcurl/lib/rtsp.c b/libcurl/lib/rtsp.c new file mode 100644 index 0000000..25e194a --- /dev/null +++ b/libcurl/lib/rtsp.c @@ -0,0 +1,827 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_RTSP + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "multiif.h" +#include "http.h" +#include "url.h" +#include "progress.h" +#include "rtsp.h" +#include "strcase.h" +#include "select.h" +#include "connect.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define RTP_PKT_CHANNEL(p) ((int)((unsigned char)((p)[1]))) + +#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \ + ((int)((unsigned char)((p)[3])))) + +/* protocol-specific functions set up to be called by the main engine */ +static CURLcode rtsp_do(struct connectdata *conn, bool *done); +static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature); +static CURLcode rtsp_connect(struct connectdata *conn, bool *done); +static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead); + +static int rtsp_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + +/* + * Parse and write out any available RTP data. + * + * nread: amount of data left after k->str. will be modified if RTP + * data is parsed and k->str is moved up + * readmore: whether or not the RTP parser needs more data right away + */ +static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *readmore); + +static CURLcode rtsp_setup_connection(struct connectdata *conn); +static unsigned int rtsp_conncheck(struct connectdata *check, + unsigned int checks_to_perform); + +/* this returns the socket to wait for in the DO and DOING state for the multi + interface and then we're always _sending_ a request and thus we wait for + the single socket to become writable only */ +static int rtsp_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + /* write mode */ + (void)numsocks; /* unused, we trust it to be at least 1 */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); +} + +static +CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len); + + +/* + * RTSP handler interface. + */ +const struct Curl_handler Curl_handler_rtsp = { + "RTSP", /* scheme */ + rtsp_setup_connection, /* setup_connection */ + rtsp_do, /* do_it */ + rtsp_done, /* done */ + ZERO_NULL, /* do_more */ + rtsp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + rtsp_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + rtsp_disconnect, /* disconnect */ + rtsp_rtp_readwrite, /* readwrite */ + rtsp_conncheck, /* connection_check */ + PORT_RTSP, /* defport */ + CURLPROTO_RTSP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + + +static CURLcode rtsp_setup_connection(struct connectdata *conn) +{ + struct RTSP *rtsp; + + conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP)); + if(!rtsp) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + + +/* + * The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not + * want to block the application forever while receiving a stream. Therefore, + * we cannot assume that an RTSP socket is dead just because it is readable. + * + * Instead, if it is readable, run Curl_connalive() to peek at the socket + * and distinguish between closed and data. + */ +static bool rtsp_connisdead(struct connectdata *check) +{ + int sval; + bool ret_val = TRUE; + + sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0); + if(sval == 0) { + /* timeout */ + ret_val = FALSE; + } + else if(sval & CURL_CSELECT_ERR) { + /* socket is in an error state */ + ret_val = TRUE; + } + else if(sval & CURL_CSELECT_IN) { + /* readable with no error. could still be closed */ + ret_val = !Curl_connalive(check); + } + + return ret_val; +} + +/* + * Function to check on various aspects of a connection. + */ +static unsigned int rtsp_conncheck(struct connectdata *check, + unsigned int checks_to_perform) +{ + unsigned int ret_val = CONNRESULT_NONE; + + if(checks_to_perform & CONNCHECK_ISDEAD) { + if(rtsp_connisdead(check)) + ret_val |= CONNRESULT_DEAD; + } + + return ret_val; +} + + +static CURLcode rtsp_connect(struct connectdata *conn, bool *done) +{ + CURLcode httpStatus; + struct Curl_easy *data = conn->data; + + httpStatus = Curl_http_connect(conn, done); + + /* Initialize the CSeq if not already done */ + if(data->state.rtsp_next_client_CSeq == 0) + data->state.rtsp_next_client_CSeq = 1; + if(data->state.rtsp_next_server_CSeq == 0) + data->state.rtsp_next_server_CSeq = 1; + + conn->proto.rtspc.rtp_channel = -1; + + return httpStatus; +} + +static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead) +{ + (void) dead; + Curl_safefree(conn->proto.rtspc.rtp_buf); + return CURLE_OK; +} + + +static CURLcode rtsp_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct Curl_easy *data = conn->data; + struct RTSP *rtsp = data->req.protop; + CURLcode httpStatus; + + /* Bypass HTTP empty-reply checks on receive */ + if(data->set.rtspreq == RTSPREQ_RECEIVE) + premature = TRUE; + + httpStatus = Curl_http_done(conn, status, premature); + + if(rtsp) { + /* Check the sequence numbers */ + long CSeq_sent = rtsp->CSeq_sent; + long CSeq_recv = rtsp->CSeq_recv; + if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) { + failf(data, + "The CSeq of this request %ld did not match the response %ld", + CSeq_sent, CSeq_recv); + return CURLE_RTSP_CSEQ_ERROR; + } + if(data->set.rtspreq == RTSPREQ_RECEIVE && + (conn->proto.rtspc.rtp_channel == -1)) { + infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv); + } + } + + return httpStatus; +} + +static CURLcode rtsp_do(struct connectdata *conn, bool *done) +{ + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + Curl_RtspReq rtspreq = data->set.rtspreq; + struct RTSP *rtsp = data->req.protop; + Curl_send_buffer *req_buffer; + curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */ + curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */ + + const char *p_request = NULL; + const char *p_session_id = NULL; + const char *p_accept = NULL; + const char *p_accept_encoding = NULL; + const char *p_range = NULL; + const char *p_referrer = NULL; + const char *p_stream_uri = NULL; + const char *p_transport = NULL; + const char *p_uagent = NULL; + const char *p_proxyuserpwd = NULL; + const char *p_userpwd = NULL; + + *done = TRUE; + + rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq; + rtsp->CSeq_recv = 0; + + /* Setup the 'p_request' pointer to the proper p_request string + * Since all RTSP requests are included here, there is no need to + * support custom requests like HTTP. + **/ + data->set.opt_no_body = TRUE; /* most requests don't contain a body */ + switch(rtspreq) { + default: + failf(data, "Got invalid RTSP request"); + return CURLE_BAD_FUNCTION_ARGUMENT; + case RTSPREQ_OPTIONS: + p_request = "OPTIONS"; + break; + case RTSPREQ_DESCRIBE: + p_request = "DESCRIBE"; + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_ANNOUNCE: + p_request = "ANNOUNCE"; + break; + case RTSPREQ_SETUP: + p_request = "SETUP"; + break; + case RTSPREQ_PLAY: + p_request = "PLAY"; + break; + case RTSPREQ_PAUSE: + p_request = "PAUSE"; + break; + case RTSPREQ_TEARDOWN: + p_request = "TEARDOWN"; + break; + case RTSPREQ_GET_PARAMETER: + /* GET_PARAMETER's no_body status is determined later */ + p_request = "GET_PARAMETER"; + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_SET_PARAMETER: + p_request = "SET_PARAMETER"; + break; + case RTSPREQ_RECORD: + p_request = "RECORD"; + break; + case RTSPREQ_RECEIVE: + p_request = ""; + /* Treat interleaved RTP as body*/ + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_LAST: + failf(data, "Got invalid RTSP request: RTSPREQ_LAST"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + if(rtspreq == RTSPREQ_RECEIVE) { + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); + + return result; + } + + p_session_id = data->set.str[STRING_RTSP_SESSION_ID]; + if(!p_session_id && + (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) { + failf(data, "Refusing to issue an RTSP request [%s] without a session ID.", + p_request); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + /* Stream URI. Default to server '*' if not specified */ + if(data->set.str[STRING_RTSP_STREAM_URI]) { + p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI]; + } + else { + p_stream_uri = "*"; + } + + /* Transport Header for SETUP requests */ + p_transport = Curl_checkheaders(conn, "Transport"); + if(rtspreq == RTSPREQ_SETUP && !p_transport) { + /* New Transport: setting? */ + if(data->set.str[STRING_RTSP_TRANSPORT]) { + Curl_safefree(conn->allocptr.rtsp_transport); + + conn->allocptr.rtsp_transport = + aprintf("Transport: %s\r\n", + data->set.str[STRING_RTSP_TRANSPORT]); + if(!conn->allocptr.rtsp_transport) + return CURLE_OUT_OF_MEMORY; + } + else { + failf(data, + "Refusing to issue an RTSP SETUP without a Transport: header."); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + p_transport = conn->allocptr.rtsp_transport; + } + + /* Accept Headers for DESCRIBE requests */ + if(rtspreq == RTSPREQ_DESCRIBE) { + /* Accept Header */ + p_accept = Curl_checkheaders(conn, "Accept")? + NULL:"Accept: application/sdp\r\n"; + + /* Accept-Encoding header */ + if(!Curl_checkheaders(conn, "Accept-Encoding") && + data->set.str[STRING_ENCODING]) { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = + aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); + + if(!conn->allocptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; + + p_accept_encoding = conn->allocptr.accept_encoding; + } + } + + /* The User-Agent string might have been allocated in url.c already, because + it might have been used in the proxy connect, but if we have got a header + with the user-agent string specified, we erase the previously made string + here. */ + if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) { + Curl_safefree(conn->allocptr.uagent); + conn->allocptr.uagent = NULL; + } + else if(!Curl_checkheaders(conn, "User-Agent") && + data->set.str[STRING_USERAGENT]) { + p_uagent = conn->allocptr.uagent; + } + + /* setup the authentication headers */ + result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE); + if(result) + return result; + + p_proxyuserpwd = conn->allocptr.proxyuserpwd; + p_userpwd = conn->allocptr.userpwd; + + /* Referrer */ + Curl_safefree(conn->allocptr.ref); + if(data->change.referer && !Curl_checkheaders(conn, "Referer")) + conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + else + conn->allocptr.ref = NULL; + + p_referrer = conn->allocptr.ref; + + /* + * Range Header + * Only applies to PLAY, PAUSE, RECORD + * + * Go ahead and use the Range stuff supplied for HTTP + */ + if(data->state.use_range && + (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) { + + /* Check to see if there is a range set in the custom headers */ + if(!Curl_checkheaders(conn, "Range") && data->state.range) { + Curl_safefree(conn->allocptr.rangeline); + conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range); + p_range = conn->allocptr.rangeline; + } + } + + /* + * Sanity check the custom headers + */ + if(Curl_checkheaders(conn, "CSeq")) { + failf(data, "CSeq cannot be set as a custom header."); + return CURLE_RTSP_CSEQ_ERROR; + } + if(Curl_checkheaders(conn, "Session")) { + failf(data, "Session ID cannot be set as a custom header."); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + /* Initialize a dynamic send buffer */ + req_buffer = Curl_add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + + result = + Curl_add_bufferf(&req_buffer, + "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */ + "CSeq: %ld\r\n", /* CSeq */ + p_request, p_stream_uri, rtsp->CSeq_sent); + if(result) + return result; + + /* + * Rather than do a normal alloc line, keep the session_id unformatted + * to make comparison easier + */ + if(p_session_id) { + result = Curl_add_bufferf(&req_buffer, "Session: %s\r\n", p_session_id); + if(result) + return result; + } + + /* + * Shared HTTP-like options + */ + result = Curl_add_bufferf(&req_buffer, + "%s" /* transport */ + "%s" /* accept */ + "%s" /* accept-encoding */ + "%s" /* range */ + "%s" /* referrer */ + "%s" /* user-agent */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + , + p_transport ? p_transport : "", + p_accept ? p_accept : "", + p_accept_encoding ? p_accept_encoding : "", + p_range ? p_range : "", + p_referrer ? p_referrer : "", + p_uagent ? p_uagent : "", + p_proxyuserpwd ? p_proxyuserpwd : "", + p_userpwd ? p_userpwd : ""); + + /* + * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM + * with basic and digest, it will be freed anyway by the next request + */ + Curl_safefree(conn->allocptr.userpwd); + conn->allocptr.userpwd = NULL; + + if(result) + return result; + + if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) { + result = Curl_add_timecondition(conn, req_buffer); + if(result) + return result; + } + + result = Curl_add_custom_headers(conn, FALSE, req_buffer); + if(result) + return result; + + if(rtspreq == RTSPREQ_ANNOUNCE || + rtspreq == RTSPREQ_SET_PARAMETER || + rtspreq == RTSPREQ_GET_PARAMETER) { + + if(data->set.upload) { + putsize = data->state.infilesize; + data->set.httpreq = HTTPREQ_PUT; + + } + else { + postsize = (data->state.infilesize != -1)? + data->state.infilesize: + (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); + data->set.httpreq = HTTPREQ_POST; + } + + if(putsize > 0 || postsize > 0) { + /* As stated in the http comments, it is probably not wise to + * actually set a custom Content-Length in the headers */ + if(!Curl_checkheaders(conn, "Content-Length")) { + result = + Curl_add_bufferf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", + (data->set.upload ? putsize : postsize)); + if(result) + return result; + } + + if(rtspreq == RTSPREQ_SET_PARAMETER || + rtspreq == RTSPREQ_GET_PARAMETER) { + if(!Curl_checkheaders(conn, "Content-Type")) { + result = Curl_add_bufferf(&req_buffer, + "Content-Type: text/parameters\r\n"); + if(result) + return result; + } + } + + if(rtspreq == RTSPREQ_ANNOUNCE) { + if(!Curl_checkheaders(conn, "Content-Type")) { + result = Curl_add_bufferf(&req_buffer, + "Content-Type: application/sdp\r\n"); + if(result) + return result; + } + } + + data->state.expect100header = FALSE; /* RTSP posts are simple/small */ + } + else if(rtspreq == RTSPREQ_GET_PARAMETER) { + /* Check for an empty GET_PARAMETER (heartbeat) request */ + data->set.httpreq = HTTPREQ_HEAD; + data->set.opt_no_body = TRUE; + } + } + + /* RTSP never allows chunked transfer */ + data->req.forbidchunk = TRUE; + /* Finish the request buffer */ + result = Curl_add_buffer(&req_buffer, "\r\n", 2); + if(result) + return result; + + if(postsize > 0) { + result = Curl_add_buffer(&req_buffer, data->set.postfields, + (size_t)postsize); + if(result) + return result; + } + + /* issue the request */ + result = Curl_add_buffer_send(&req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) { + failf(data, "Failed sending RTSP request"); + return result; + } + + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1); + + /* Increment the CSeq on success */ + data->state.rtsp_next_client_CSeq++; + + if(data->req.writebytecount) { + /* if a request-body has been sent off, we make sure this progress is + noted properly */ + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + } + + return result; +} + + +static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *readmore) { + struct SingleRequest *k = &data->req; + struct rtsp_conn *rtspc = &(conn->proto.rtspc); + + char *rtp; /* moving pointer to rtp data */ + ssize_t rtp_dataleft; /* how much data left to parse in this round */ + char *scratch; + CURLcode result; + + if(rtspc->rtp_buf) { + /* There was some leftover data the last time. Merge buffers */ + char *newptr = Curl_saferealloc(rtspc->rtp_buf, + rtspc->rtp_bufsize + *nread); + if(!newptr) { + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return CURLE_OUT_OF_MEMORY; + } + rtspc->rtp_buf = newptr; + memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread); + rtspc->rtp_bufsize += *nread; + rtp = rtspc->rtp_buf; + rtp_dataleft = rtspc->rtp_bufsize; + } + else { + /* Just parse the request buffer directly */ + rtp = k->str; + rtp_dataleft = *nread; + } + + while((rtp_dataleft > 0) && + (rtp[0] == '$')) { + if(rtp_dataleft > 4) { + int rtp_length; + + /* Parse the header */ + /* The channel identifier immediately follows and is 1 byte */ + rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp); + + /* The length is two bytes */ + rtp_length = RTP_PKT_LENGTH(rtp); + + if(rtp_dataleft < rtp_length + 4) { + /* Need more - incomplete payload*/ + *readmore = TRUE; + break; + } + /* We have the full RTP interleaved packet + * Write out the header including the leading '$' */ + DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n", + rtspc->rtp_channel, rtp_length)); + result = rtp_client_write(conn, &rtp[0], rtp_length + 4); + if(result) { + failf(data, "Got an error writing an RTP packet"); + *readmore = FALSE; + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return result; + } + + /* Move forward in the buffer */ + rtp_dataleft -= rtp_length + 4; + rtp += rtp_length + 4; + + if(data->set.rtspreq == RTSPREQ_RECEIVE) { + /* If we are in a passive receive, give control back + * to the app as often as we can. + */ + k->keepon &= ~KEEP_RECV; + } + } + else { + /* Need more - incomplete header */ + *readmore = TRUE; + break; + } + } + + if(rtp_dataleft != 0 && rtp[0] == '$') { + DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft, + *readmore ? "(READMORE)" : "")); + + /* Store the incomplete RTP packet for a "rewind" */ + scratch = malloc(rtp_dataleft); + if(!scratch) { + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return CURLE_OUT_OF_MEMORY; + } + memcpy(scratch, rtp, rtp_dataleft); + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = scratch; + rtspc->rtp_bufsize = rtp_dataleft; + + /* As far as the transfer is concerned, this data is consumed */ + *nread = 0; + return CURLE_OK; + } + /* Fix up k->str to point just after the last RTP packet */ + k->str += *nread - rtp_dataleft; + + /* either all of the data has been read or... + * rtp now points at the next byte to parse + */ + if(rtp_dataleft > 0) + DEBUGASSERT(k->str[0] == rtp[0]); + + DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */ + + *nread = rtp_dataleft; + + /* If we get here, we have finished with the leftover/merge buffer */ + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + + return CURLE_OK; +} + +static +CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) +{ + struct Curl_easy *data = conn->data; + size_t wrote; + curl_write_callback writeit; + void *user_ptr; + + if(len == 0) { + failf(data, "Cannot write a 0 size RTP packet."); + return CURLE_WRITE_ERROR; + } + + /* If the user has configured CURLOPT_INTERLEAVEFUNCTION then use that + function and any configured CURLOPT_INTERLEAVEDATA to write out the RTP + data. Otherwise, use the CURLOPT_WRITEFUNCTION with the CURLOPT_WRITEDATA + pointer to write out the RTP data. */ + if(data->set.fwrite_rtp) { + writeit = data->set.fwrite_rtp; + user_ptr = data->set.rtp_out; + } + else { + writeit = data->set.fwrite_func; + user_ptr = data->set.out; + } + + Curl_set_in_callback(data, true); + wrote = writeit(ptr, 1, len, user_ptr); + Curl_set_in_callback(data, false); + + if(CURL_WRITEFUNC_PAUSE == wrote) { + failf(data, "Cannot pause RTP"); + return CURLE_WRITE_ERROR; + } + + if(wrote != len) { + failf(data, "Failed writing RTP data"); + return CURLE_WRITE_ERROR; + } + + return CURLE_OK; +} + +CURLcode Curl_rtsp_parseheader(struct connectdata *conn, + char *header) +{ + struct Curl_easy *data = conn->data; + long CSeq = 0; + + if(checkprefix("CSeq:", header)) { + /* Store the received CSeq. Match is verified in rtsp_done */ + int nc = sscanf(&header[4], ": %ld", &CSeq); + if(nc == 1) { + struct RTSP *rtsp = data->req.protop; + rtsp->CSeq_recv = CSeq; /* mark the request */ + data->state.rtsp_CSeq_recv = CSeq; /* update the handle */ + } + else { + failf(data, "Unable to read the CSeq header: [%s]", header); + return CURLE_RTSP_CSEQ_ERROR; + } + } + else if(checkprefix("Session:", header)) { + char *start; + + /* Find the first non-space letter */ + start = header + 8; + while(*start && ISSPACE(*start)) + start++; + + if(!*start) { + failf(data, "Got a blank Session ID"); + } + else if(data->set.str[STRING_RTSP_SESSION_ID]) { + /* If the Session ID is set, then compare */ + if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], + strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) { + failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]", + start, data->set.str[STRING_RTSP_SESSION_ID]); + return CURLE_RTSP_SESSION_ERROR; + } + } + else { + /* If the Session ID is not set, and we find it in a response, then set + * it. + * + * Allow any non whitespace content, up to the field separator or end of + * line. RFC 2326 isn't 100% clear on the session ID and for example + * gstreamer does url-encoded session ID's not covered by the standard. + */ + char *end = start; + while(*end && *end != ';' && !ISSPACE(*end)) + end++; + + /* Copy the id substring into a new buffer */ + data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1); + if(data->set.str[STRING_RTSP_SESSION_ID] == NULL) + return CURLE_OUT_OF_MEMORY; + memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start); + (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0'; + } + } + return CURLE_OK; +} + +#endif /* CURL_DISABLE_RTSP */ diff --git a/libcurl/lib/rtsp.h b/libcurl/lib/rtsp.h new file mode 100644 index 0000000..2f9cc32 --- /dev/null +++ b/libcurl/lib/rtsp.h @@ -0,0 +1,66 @@ +#ifndef HEADER_CURL_RTSP_H +#define HEADER_CURL_RTSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_RTSP + +extern const struct Curl_handler Curl_handler_rtsp; + +CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header); + +#else +/* disabled */ +#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN + +#endif /* CURL_DISABLE_RTSP */ + +/* + * RTSP Connection data + * + * Currently, only used for tracking incomplete RTP data reads + */ +struct rtsp_conn { + char *rtp_buf; + ssize_t rtp_bufsize; + int rtp_channel; +}; + +/**************************************************************************** + * RTSP unique setup + ***************************************************************************/ +struct RTSP { + /* + * http_wrapper MUST be the first element of this structure for the wrap + * logic to work. In this way, we get a cheap polymorphism because + * &(data->state.proto.rtsp) == &(data->state.proto.http) per the C spec + * + * HTTP functions can safely treat this as an HTTP struct, but RTSP aware + * functions can also index into the later elements. + */ + struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */ + + long CSeq_sent; /* CSeq of this request */ + long CSeq_recv; /* CSeq received */ +}; + + +#endif /* HEADER_CURL_RTSP_H */ diff --git a/libcurl/lib/security.c b/libcurl/lib/security.c new file mode 100644 index 0000000..550ea2d --- /dev/null +++ b/libcurl/lib/security.c @@ -0,0 +1,581 @@ +/* This source code was modified by Martin Hedenfalk for + * use in Curl. His latest changes were done 2000-09-18. + * + * It has since been patched and modified a lot by Daniel Stenberg + * to make it better applied to curl conditions, and to make + * it not use globals, pollute name space and more. This source code awaits a + * rewrite to work around the paragraph 2 in the BSD licenses as explained + * below. + * + * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * + * Copyright (C) 2001 - 2019, Daniel Stenberg, , et al. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP +#ifdef HAVE_GSSAPI + +#ifdef HAVE_NETDB_H +#include +#endif + +#include + +#include "urldata.h" +#include "curl_base64.h" +#include "curl_memory.h" +#include "curl_sec.h" +#include "ftp.h" +#include "sendf.h" +#include "strcase.h" +#include "warnless.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static const struct { + enum protection_level level; + const char *name; +} level_names[] = { + { PROT_CLEAR, "clear" }, + { PROT_SAFE, "safe" }, + { PROT_CONFIDENTIAL, "confidential" }, + { PROT_PRIVATE, "private" } +}; + +static enum protection_level +name_to_level(const char *name) +{ + int i; + for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++) + if(checkprefix(name, level_names[i].name)) + return level_names[i].level; + return PROT_NONE; +} + +/* Convert a protocol |level| to its char representation. + We take an int to catch programming mistakes. */ +static char level_to_char(int level) +{ + switch(level) { + case PROT_CLEAR: + return 'C'; + case PROT_SAFE: + return 'S'; + case PROT_CONFIDENTIAL: + return 'E'; + case PROT_PRIVATE: + return 'P'; + case PROT_CMD: + /* Fall through */ + default: + /* Those 2 cases should not be reached! */ + break; + } + DEBUGASSERT(0); + /* Default to the most secure alternative. */ + return 'P'; +} + +/* Send an FTP command defined by |message| and the optional arguments. The + function returns the ftp_code. If an error occurs, -1 is returned. */ +static int ftp_send_command(struct connectdata *conn, const char *message, ...) +{ + int ftp_code; + ssize_t nread = 0; + va_list args; + char print_buffer[50]; + + va_start(args, message); + mvsnprintf(print_buffer, sizeof(print_buffer), message, args); + va_end(args); + + if(Curl_ftpsend(conn, print_buffer)) { + ftp_code = -1; + } + else { + if(Curl_GetFTPResponse(&nread, conn, &ftp_code)) + ftp_code = -1; + } + + (void)nread; /* Unused */ + return ftp_code; +} + +/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode + saying whether an error occurred or CURLE_OK if |len| was read. */ +static CURLcode +socket_read(curl_socket_t fd, void *to, size_t len) +{ + char *to_p = to; + CURLcode result; + ssize_t nread = 0; + + while(len > 0) { + result = Curl_read_plain(fd, to_p, len, &nread); + if(!result) { + len -= nread; + to_p += nread; + } + else { + if(result == CURLE_AGAIN) + continue; + return result; + } + } + return CURLE_OK; +} + + +/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a + CURLcode saying whether an error occurred or CURLE_OK if |len| was + written. */ +static CURLcode +socket_write(struct connectdata *conn, curl_socket_t fd, const void *to, + size_t len) +{ + const char *to_p = to; + CURLcode result; + ssize_t written; + + while(len > 0) { + result = Curl_write_plain(conn, fd, to_p, len, &written); + if(!result) { + len -= written; + to_p += written; + } + else { + if(result == CURLE_AGAIN) + continue; + return result; + } + } + return CURLE_OK; +} + +static CURLcode read_data(struct connectdata *conn, + curl_socket_t fd, + struct krb5buffer *buf) +{ + int len; + void *tmp = NULL; + CURLcode result; + + result = socket_read(fd, &len, sizeof(len)); + if(result) + return result; + + if(len) { + /* only realloc if there was a length */ + len = ntohl(len); + tmp = Curl_saferealloc(buf->data, len); + } + if(tmp == NULL) + return CURLE_OUT_OF_MEMORY; + + buf->data = tmp; + result = socket_read(fd, buf->data, len); + if(result) + return result; + buf->size = conn->mech->decode(conn->app_data, buf->data, len, + conn->data_prot, conn); + buf->index = 0; + return CURLE_OK; +} + +static size_t +buffer_read(struct krb5buffer *buf, void *data, size_t len) +{ + if(buf->size - buf->index < len) + len = buf->size - buf->index; + memcpy(data, (char *)buf->data + buf->index, len); + buf->index += len; + return len; +} + +/* Matches Curl_recv signature */ +static ssize_t sec_recv(struct connectdata *conn, int sockindex, + char *buffer, size_t len, CURLcode *err) +{ + size_t bytes_read; + size_t total_read = 0; + curl_socket_t fd = conn->sock[sockindex]; + + *err = CURLE_OK; + + /* Handle clear text response. */ + if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) + return read(fd, buffer, len); + + if(conn->in_buffer.eof_flag) { + conn->in_buffer.eof_flag = 0; + return 0; + } + + bytes_read = buffer_read(&conn->in_buffer, buffer, len); + len -= bytes_read; + total_read += bytes_read; + buffer += bytes_read; + + while(len > 0) { + if(read_data(conn, fd, &conn->in_buffer)) + return -1; + if(conn->in_buffer.size == 0) { + if(bytes_read > 0) + conn->in_buffer.eof_flag = 1; + return bytes_read; + } + bytes_read = buffer_read(&conn->in_buffer, buffer, len); + len -= bytes_read; + total_read += bytes_read; + buffer += bytes_read; + } + return total_read; +} + +/* Send |length| bytes from |from| to the |fd| socket taking care of encoding + and negotiating with the server. |from| can be NULL. */ +static void do_sec_send(struct connectdata *conn, curl_socket_t fd, + const char *from, int length) +{ + int bytes, htonl_bytes; /* 32-bit integers for htonl */ + char *buffer = NULL; + char *cmd_buffer; + size_t cmd_size = 0; + CURLcode error; + enum protection_level prot_level = conn->data_prot; + bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE; + + DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST); + + if(iscmd) { + if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5)) + prot_level = PROT_PRIVATE; + else + prot_level = conn->command_prot; + } + bytes = conn->mech->encode(conn->app_data, from, length, prot_level, + (void **)&buffer); + if(!buffer || bytes <= 0) + return; /* error */ + + if(iscmd) { + error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes), + &cmd_buffer, &cmd_size); + if(error) { + free(buffer); + return; /* error */ + } + if(cmd_size > 0) { + static const char *enc = "ENC "; + static const char *mic = "MIC "; + if(prot_level == PROT_PRIVATE) + socket_write(conn, fd, enc, 4); + else + socket_write(conn, fd, mic, 4); + + socket_write(conn, fd, cmd_buffer, cmd_size); + socket_write(conn, fd, "\r\n", 2); + infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic, + cmd_buffer); + free(cmd_buffer); + } + } + else { + htonl_bytes = htonl(bytes); + socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes)); + socket_write(conn, fd, buffer, curlx_sitouz(bytes)); + } + free(buffer); +} + +static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd, + const char *buffer, size_t length) +{ + ssize_t tx = 0, len = conn->buffer_size; + + len -= conn->mech->overhead(conn->app_data, conn->data_prot, + curlx_sztosi(len)); + if(len <= 0) + len = length; + while(length) { + if(length < (size_t)len) + len = length; + + do_sec_send(conn, fd, buffer, curlx_sztosi(len)); + length -= len; + buffer += len; + tx += len; + } + return tx; +} + +/* Matches Curl_send signature */ +static ssize_t sec_send(struct connectdata *conn, int sockindex, + const void *buffer, size_t len, CURLcode *err) +{ + curl_socket_t fd = conn->sock[sockindex]; + *err = CURLE_OK; + return sec_write(conn, fd, buffer, len); +} + +int Curl_sec_read_msg(struct connectdata *conn, char *buffer, + enum protection_level level) +{ + /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an + int */ + int decoded_len; + char *buf; + int ret_code = 0; + size_t decoded_sz = 0; + CURLcode error; + + if(!conn->mech) + /* not inititalized, return error */ + return -1; + + DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); + + error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz); + if(error || decoded_sz == 0) + return -1; + + if(decoded_sz > (size_t)INT_MAX) { + free(buf); + return -1; + } + decoded_len = curlx_uztosi(decoded_sz); + + decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len, + level, conn); + if(decoded_len <= 0) { + free(buf); + return -1; + } + + if(conn->data->set.verbose) { + buf[decoded_len] = '\n'; + Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1); + } + + buf[decoded_len] = '\0'; + if(decoded_len <= 3) + /* suspiciously short */ + return 0; + + if(buf[3] != '-') + /* safe to ignore return code */ + (void)sscanf(buf, "%d", &ret_code); + + if(buf[decoded_len - 1] == '\n') + buf[decoded_len - 1] = '\0'; + strcpy(buffer, buf); + free(buf); + return ret_code; +} + +static int sec_set_protection_level(struct connectdata *conn) +{ + int code; + enum protection_level level = conn->request_data_prot; + + DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); + + if(!conn->sec_complete) { + infof(conn->data, "Trying to change the protection level after the" + " completion of the data exchange.\n"); + return -1; + } + + /* Bail out if we try to set up the same level */ + if(conn->data_prot == level) + return 0; + + if(level) { + char *pbsz; + static unsigned int buffer_size = 1 << 20; /* 1048576 */ + + code = ftp_send_command(conn, "PBSZ %u", buffer_size); + if(code < 0) + return -1; + + if(code/100 != 2) { + failf(conn->data, "Failed to set the protection's buffer size."); + return -1; + } + conn->buffer_size = buffer_size; + + pbsz = strstr(conn->data->state.buffer, "PBSZ="); + if(pbsz) { + /* ignore return code, use default value if it fails */ + (void)sscanf(pbsz, "PBSZ=%u", &buffer_size); + if(buffer_size < conn->buffer_size) + conn->buffer_size = buffer_size; + } + } + + /* Now try to negiociate the protection level. */ + code = ftp_send_command(conn, "PROT %c", level_to_char(level)); + + if(code < 0) + return -1; + + if(code/100 != 2) { + failf(conn->data, "Failed to set the protection level."); + return -1; + } + + conn->data_prot = level; + if(level == PROT_PRIVATE) + conn->command_prot = level; + + return 0; +} + +int +Curl_sec_request_prot(struct connectdata *conn, const char *level) +{ + enum protection_level l = name_to_level(level); + if(l == PROT_NONE) + return -1; + DEBUGASSERT(l > PROT_NONE && l < PROT_LAST); + conn->request_data_prot = l; + return 0; +} + +static CURLcode choose_mech(struct connectdata *conn) +{ + int ret; + struct Curl_easy *data = conn->data; + void *tmp_allocation; + const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech; + + tmp_allocation = realloc(conn->app_data, mech->size); + if(tmp_allocation == NULL) { + failf(data, "Failed realloc of size %zu", mech->size); + mech = NULL; + return CURLE_OUT_OF_MEMORY; + } + conn->app_data = tmp_allocation; + + if(mech->init) { + ret = mech->init(conn->app_data); + if(ret) { + infof(data, "Failed initialization for %s. Skipping it.\n", + mech->name); + return CURLE_FAILED_INIT; + } + } + + infof(data, "Trying mechanism %s...\n", mech->name); + ret = ftp_send_command(conn, "AUTH %s", mech->name); + if(ret < 0) + return CURLE_COULDNT_CONNECT; + + if(ret/100 != 3) { + switch(ret) { + case 504: + infof(data, "Mechanism %s is not supported by the server (server " + "returned ftp code: 504).\n", mech->name); + break; + case 534: + infof(data, "Mechanism %s was rejected by the server (server returned " + "ftp code: 534).\n", mech->name); + break; + default: + if(ret/100 == 5) { + infof(data, "server does not support the security extensions\n"); + return CURLE_USE_SSL_FAILED; + } + break; + } + return CURLE_LOGIN_DENIED; + } + + /* Authenticate */ + ret = mech->auth(conn->app_data, conn); + + if(ret != AUTH_CONTINUE) { + if(ret != AUTH_OK) { + /* Mechanism has dumped the error to stderr, don't error here. */ + return -1; + } + DEBUGASSERT(ret == AUTH_OK); + + conn->mech = mech; + conn->sec_complete = 1; + conn->recv[FIRSTSOCKET] = sec_recv; + conn->send[FIRSTSOCKET] = sec_send; + conn->recv[SECONDARYSOCKET] = sec_recv; + conn->send[SECONDARYSOCKET] = sec_send; + conn->command_prot = PROT_SAFE; + /* Set the requested protection level */ + /* BLOCKING */ + (void)sec_set_protection_level(conn); + } + + return CURLE_OK; +} + +CURLcode +Curl_sec_login(struct connectdata *conn) +{ + return choose_mech(conn); +} + + +void +Curl_sec_end(struct connectdata *conn) +{ + if(conn->mech != NULL && conn->mech->end) + conn->mech->end(conn->app_data); + free(conn->app_data); + conn->app_data = NULL; + if(conn->in_buffer.data) { + free(conn->in_buffer.data); + conn->in_buffer.data = NULL; + conn->in_buffer.size = 0; + conn->in_buffer.index = 0; + conn->in_buffer.eof_flag = 0; + } + conn->sec_complete = 0; + conn->data_prot = PROT_CLEAR; + conn->mech = NULL; +} + +#endif /* HAVE_GSSAPI */ + +#endif /* CURL_DISABLE_FTP */ diff --git a/libcurl/lib/select.c b/libcurl/lib/select.c new file mode 100644 index 0000000..8cd9eb2 --- /dev/null +++ b/libcurl/lib/select.c @@ -0,0 +1,585 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) +#error "We can't compile without select() or poll() support." +#endif + +#if defined(__BEOS__) && !defined(__HAIKU__) +/* BeOS has FD_SET defined in socket.h */ +#include +#endif + +#ifdef MSDOS +#include /* delay() */ +#endif + +#ifdef __VXWORKS__ +#include /* bzero() in FD_SET */ +#endif + +#include + +#include "urldata.h" +#include "connect.h" +#include "select.h" +#include "warnless.h" + +/* Convenience local macros */ +#define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv) + +int Curl_ack_eintr = 0; +#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR) + +/* + * Internal function used for waiting a specific amount of ms + * in Curl_socket_check() and Curl_poll() when no file descriptor + * is provided to wait on, just being used to delay execution. + * WinSock select() and poll() timeout mechanisms need a valid + * socket descriptor in a not null file descriptor set to work. + * Waiting indefinitely with this function is not allowed, a + * zero or negative timeout value will return immediately. + * Timeout resolution, accuracy, as well as maximum supported + * value is system dependent, neither factor is a citical issue + * for the intended use of this function in the library. + * + * Return values: + * -1 = system call error, invalid timeout value, or interrupted + * 0 = specified timeout has elapsed + */ +int Curl_wait_ms(int timeout_ms) +{ +#if !defined(MSDOS) && !defined(USE_WINSOCK) +#ifndef HAVE_POLL_FINE + struct timeval pending_tv; +#endif + struct curltime initial_tv; + int pending_ms; +#endif + int r = 0; + + if(!timeout_ms) + return 0; + if(timeout_ms < 0) { + SET_SOCKERRNO(EINVAL); + return -1; + } +#if defined(MSDOS) + delay(timeout_ms); +#elif defined(USE_WINSOCK) + Sleep(timeout_ms); +#else + pending_ms = timeout_ms; + initial_tv = Curl_now(); + do { + int error; +#if defined(HAVE_POLL_FINE) + r = poll(NULL, 0, pending_ms); +#else + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + r = select(0, NULL, NULL, NULL, &pending_tv); +#endif /* HAVE_POLL_FINE */ + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + pending_ms = timeout_ms - ELAPSED_MS(); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } while(r == -1); +#endif /* USE_WINSOCK */ + if(r) + r = -1; + return r; +} + +/* + * Wait for read or write events on a set of file descriptors. It uses poll() + * when a fine poll() is available, in order to avoid limits with FD_SETSIZE, + * otherwise select() is used. An error is returned if select() is being used + * and a file descriptor is too large for FD_SETSIZE. + * + * A negative timeout value makes this function wait indefinitely, + * unless no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE + * 0 = timeout + * [bitmask] = action as described below + * + * CURL_CSELECT_IN - first socket is readable + * CURL_CSELECT_IN2 - second socket is readable + * CURL_CSELECT_OUT - write socket is writable + * CURL_CSELECT_ERR - an error condition occurred + */ +int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ + curl_socket_t readfd1, + curl_socket_t writefd, /* socket to write to */ + time_t timeout_ms) /* milliseconds to wait */ +{ +#ifdef HAVE_POLL_FINE + struct pollfd pfd[3]; + int num; +#else + struct timeval pending_tv; + struct timeval *ptimeout; + fd_set fds_read; + fd_set fds_write; + fd_set fds_err; + curl_socket_t maxfd; +#endif + struct curltime initial_tv = {0, 0}; + int pending_ms = 0; + int r; + int ret; + +#if SIZEOF_TIME_T != SIZEOF_INT + /* wrap-around precaution */ + if(timeout_ms >= INT_MAX) + timeout_ms = INT_MAX; +#endif + + if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && + (writefd == CURL_SOCKET_BAD)) { + /* no sockets, just wait */ + r = Curl_wait_ms((int)timeout_ms); + return r; + } + + /* Avoid initial timestamp, avoid Curl_now() call, when elapsed + time in this function does not need to be measured. This happens + when function is called with a zero timeout or a negative timeout + value indicating a blocking call should be performed. */ + + if(timeout_ms > 0) { + pending_ms = (int)timeout_ms; + initial_tv = Curl_now(); + } + +#ifdef HAVE_POLL_FINE + + num = 0; + if(readfd0 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd0; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd1; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(writefd != CURL_SOCKET_BAD) { + pfd[num].fd = writefd; + pfd[num].events = POLLWRNORM|POLLOUT; + pfd[num].revents = 0; + num++; + } + + do { + int error; + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(pfd, num, pending_ms); + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + ret = 0; + num = 0; + if(readfd0 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN2; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } + if(writefd != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLWRNORM|POLLOUT)) + ret |= CURL_CSELECT_OUT; + if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + } + + return ret; + +#else /* HAVE_POLL_FINE */ + + FD_ZERO(&fds_err); + maxfd = (curl_socket_t)-1; + + FD_ZERO(&fds_read); + if(readfd0 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd0); + FD_SET(readfd0, &fds_read); + FD_SET(readfd0, &fds_err); + maxfd = readfd0; + } + if(readfd1 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd1); + FD_SET(readfd1, &fds_read); + FD_SET(readfd1, &fds_err); + if(readfd1 > maxfd) + maxfd = readfd1; + } + + FD_ZERO(&fds_write); + if(writefd != CURL_SOCKET_BAD) { + VERIFY_SOCK(writefd); + FD_SET(writefd, &fds_write); + FD_SET(writefd, &fds_err); + if(writefd > maxfd) + maxfd = writefd; + } + + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; + + do { + int error; + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } + + /* WinSock select() must not be called with an fd_set that contains zero + fd flags, or it will return WSAEINVAL. But, it also can't be called + with no fd_sets at all! From the documentation: + + Any two of the parameters, readfds, writefds, or exceptfds, can be + given as null. At least one must be non-null, and any non-null + descriptor set must contain at least one handle to a socket. + + We know that we have at least one bit set in at least two fd_sets in + this case, but we may have no bits set in either fds_read or fd_write, + so check for that and handle it. Luckily, with WinSock, we can _also_ + ask how many bits are set on an fd_set. + + It is unclear why WinSock doesn't just handle this for us instead of + calling this an error. + + Note also that WinSock ignores the first argument, so we don't worry + about the fact that maxfd is computed incorrectly with WinSock (since + curl_socket_t is unsigned in such cases and thus -1 is the largest + value). + */ +#ifdef USE_WINSOCK + r = select((int)maxfd + 1, + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + &fds_err, ptimeout); +#else + r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); +#endif + + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + ret = 0; + if(readfd0 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd0, &fds_read)) + ret |= CURL_CSELECT_IN; + if(FD_ISSET(readfd0, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd1, &fds_read)) + ret |= CURL_CSELECT_IN2; + if(FD_ISSET(readfd1, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(writefd != CURL_SOCKET_BAD) { + if(FD_ISSET(writefd, &fds_write)) + ret |= CURL_CSELECT_OUT; + if(FD_ISSET(writefd, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + + return ret; + +#endif /* HAVE_POLL_FINE */ + +} + +/* + * This is a wrapper around poll(). If poll() does not exist, then + * select() is used instead. An error is returned if select() is + * being used and a file descriptor is too large for FD_SETSIZE. + * A negative timeout value makes this function wait indefinitely, + * unless no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE + * 0 = timeout + * N = number of structures with non zero revent fields + */ +int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) +{ +#ifndef HAVE_POLL_FINE + struct timeval pending_tv; + struct timeval *ptimeout; + fd_set fds_read; + fd_set fds_write; + fd_set fds_err; + curl_socket_t maxfd; +#endif + struct curltime initial_tv = {0, 0}; + bool fds_none = TRUE; + unsigned int i; + int pending_ms = 0; + int r; + + if(ufds) { + for(i = 0; i < nfds; i++) { + if(ufds[i].fd != CURL_SOCKET_BAD) { + fds_none = FALSE; + break; + } + } + } + if(fds_none) { + r = Curl_wait_ms(timeout_ms); + return r; + } + + /* Avoid initial timestamp, avoid Curl_now() call, when elapsed + time in this function does not need to be measured. This happens + when function is called with a zero timeout or a negative timeout + value indicating a blocking call should be performed. */ + + if(timeout_ms > 0) { + pending_ms = timeout_ms; + initial_tv = Curl_now(); + } + +#ifdef HAVE_POLL_FINE + + do { + int error; + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(ufds, nfds, pending_ms); + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + for(i = 0; i < nfds; i++) { + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + if(ufds[i].revents & POLLHUP) + ufds[i].revents |= POLLIN; + if(ufds[i].revents & POLLERR) + ufds[i].revents |= (POLLIN|POLLOUT); + } + +#else /* HAVE_POLL_FINE */ + + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + FD_ZERO(&fds_err); + maxfd = (curl_socket_t)-1; + + for(i = 0; i < nfds; i++) { + ufds[i].revents = 0; + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + VERIFY_SOCK(ufds[i].fd); + if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI| + POLLRDNORM|POLLWRNORM|POLLRDBAND)) { + if(ufds[i].fd > maxfd) + maxfd = ufds[i].fd; + if(ufds[i].events & (POLLRDNORM|POLLIN)) + FD_SET(ufds[i].fd, &fds_read); + if(ufds[i].events & (POLLWRNORM|POLLOUT)) + FD_SET(ufds[i].fd, &fds_write); + if(ufds[i].events & (POLLRDBAND|POLLPRI)) + FD_SET(ufds[i].fd, &fds_err); + } + } + +#ifdef USE_WINSOCK + /* WinSock select() can't handle zero events. See the comment about this in + Curl_check_socket(). */ + if(fds_read.fd_count == 0 && fds_write.fd_count == 0 + && fds_err.fd_count == 0) { + r = Curl_wait_ms(timeout_ms); + return r; + } +#endif + + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; + + do { + int error; + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } + +#ifdef USE_WINSOCK + r = select((int)maxfd + 1, + /* WinSock select() can't handle fd_sets with zero bits set, so + don't give it such arguments. See the comment about this in + Curl_check_socket(). + */ + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + fds_err.fd_count ? &fds_err : NULL, ptimeout); +#else + r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); +#endif + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = timeout_ms - ELAPSED_MS(); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + r = 0; + for(i = 0; i < nfds; i++) { + ufds[i].revents = 0; + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + if(FD_ISSET(ufds[i].fd, &fds_read)) + ufds[i].revents |= POLLIN; + if(FD_ISSET(ufds[i].fd, &fds_write)) + ufds[i].revents |= POLLOUT; + if(FD_ISSET(ufds[i].fd, &fds_err)) + ufds[i].revents |= POLLPRI; + if(ufds[i].revents != 0) + r++; + } + +#endif /* HAVE_POLL_FINE */ + + return r; +} + +#ifdef TPF +/* + * This is a replacement for select() on the TPF platform. + * It is used whenever libcurl calls select(). + * The call below to tpf_process_signals() is required because + * TPF's select calls are not signal interruptible. + * + * Return values are the same as select's. + */ +int tpf_select_libcurl(int maxfds, fd_set *reads, fd_set *writes, + fd_set *excepts, struct timeval *tv) +{ + int rc; + + rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv); + tpf_process_signals(); + return rc; +} +#endif /* TPF */ diff --git a/libcurl/lib/select.h b/libcurl/lib/select.h new file mode 100644 index 0000000..9a1ba45 --- /dev/null +++ b/libcurl/lib/select.h @@ -0,0 +1,115 @@ +#ifndef HEADER_CURL_SELECT_H +#define HEADER_CURL_SELECT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_POLL_H +#include +#elif defined(HAVE_SYS_POLL_H) +#include +#endif + +/* + * Definition of pollfd struct and constants for platforms lacking them. + */ + +#if !defined(HAVE_STRUCT_POLLFD) && \ + !defined(HAVE_SYS_POLL_H) && \ + !defined(HAVE_POLL_H) && \ + !defined(POLLIN) + +#define POLLIN 0x01 +#define POLLPRI 0x02 +#define POLLOUT 0x04 +#define POLLERR 0x08 +#define POLLHUP 0x10 +#define POLLNVAL 0x20 + +struct pollfd +{ + curl_socket_t fd; + short events; + short revents; +}; + +#endif + +#ifndef POLLRDNORM +#define POLLRDNORM POLLIN +#endif + +#ifndef POLLWRNORM +#define POLLWRNORM POLLOUT +#endif + +#ifndef POLLRDBAND +#define POLLRDBAND POLLPRI +#endif + +/* there are three CSELECT defines that are defined in the public header that + are exposed to users, but this *IN2 bit is only ever used internally and + therefore defined here */ +#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1) + +int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, + curl_socket_t writefd, + time_t timeout_ms); + +#define SOCKET_READABLE(x,z) \ + Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z) +#define SOCKET_WRITABLE(x,z) \ + Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z) + +int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); + +/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set, + * EINTR condition is honored and function might exit early without + * awaiting full timeout. Otherwise EINTR will be ignored and full + * timeout will elapse. */ +extern int Curl_ack_eintr; + +int Curl_wait_ms(int timeout_ms); + +#ifdef TPF +int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, + fd_set* excepts, struct timeval* tv); +#endif + +/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which + unfortunately makes it impossible for us to easily check if they're valid +*/ +#if defined(USE_WINSOCK) || defined(TPF) +#define VALID_SOCK(x) 1 +#define VERIFY_SOCK(x) Curl_nop_stmt +#else +#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) +#define VERIFY_SOCK(x) do { \ + if(!VALID_SOCK(x)) { \ + SET_SOCKERRNO(EINVAL); \ + return -1; \ + } \ +} WHILE_FALSE +#endif + +#endif /* HEADER_CURL_SELECT_H */ diff --git a/libcurl/lib/sendf.c b/libcurl/lib/sendf.c new file mode 100644 index 0000000..5913ea4 --- /dev/null +++ b/libcurl/lib/sendf.c @@ -0,0 +1,821 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_LINUX_TCP_H +#include +#endif + +#include + +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "vtls/vtls.h" +#include "ssh.h" +#include "easyif.h" +#include "multiif.h" +#include "non-ascii.h" +#include "strerror.h" +#include "select.h" +#include "strdup.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifdef CURL_DO_LINEEND_CONV +/* + * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF + * (\n), with special processing for CRLF sequences that are split between two + * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new + * size of the data is returned. + */ +static size_t convert_lineends(struct Curl_easy *data, + char *startPtr, size_t size) +{ + char *inPtr, *outPtr; + + /* sanity check */ + if((startPtr == NULL) || (size < 1)) { + return size; + } + + if(data->state.prev_block_had_trailing_cr) { + /* The previous block of incoming data + had a trailing CR, which was turned into a LF. */ + if(*startPtr == '\n') { + /* This block of incoming data starts with the + previous block's LF so get rid of it */ + memmove(startPtr, startPtr + 1, size-1); + size--; + /* and it wasn't a bare CR but a CRLF conversion instead */ + data->state.crlf_conversions++; + } + data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */ + } + + /* find 1st CR, if any */ + inPtr = outPtr = memchr(startPtr, '\r', size); + if(inPtr) { + /* at least one CR, now look for CRLF */ + while(inPtr < (startPtr + size-1)) { + /* note that it's size-1, so we'll never look past the last byte */ + if(memcmp(inPtr, "\r\n", 2) == 0) { + /* CRLF found, bump past the CR and copy the NL */ + inPtr++; + *outPtr = *inPtr; + /* keep track of how many CRLFs we converted */ + data->state.crlf_conversions++; + } + else { + if(*inPtr == '\r') { + /* lone CR, move LF instead */ + *outPtr = '\n'; + } + else { + /* not a CRLF nor a CR, just copy whatever it is */ + *outPtr = *inPtr; + } + } + outPtr++; + inPtr++; + } /* end of while loop */ + + if(inPtr < startPtr + size) { + /* handle last byte */ + if(*inPtr == '\r') { + /* deal with a CR at the end of the buffer */ + *outPtr = '\n'; /* copy a NL instead */ + /* note that a CRLF might be split across two blocks */ + data->state.prev_block_had_trailing_cr = TRUE; + } + else { + /* copy last byte */ + *outPtr = *inPtr; + } + outPtr++; + } + if(outPtr < startPtr + size) + /* tidy up by null terminating the now shorter data */ + *outPtr = '\0'; + + return (outPtr - startPtr); + } + return size; +} +#endif /* CURL_DO_LINEEND_CONV */ + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) +{ + struct postponed_data * const psnd = &(conn->postponed[sockindex]); + return psnd->buffer && psnd->allocated_size && + psnd->recv_size > psnd->recv_processed; +} + +static void pre_receive_plain(struct connectdata *conn, int num) +{ + const curl_socket_t sockfd = conn->sock[num]; + struct postponed_data * const psnd = &(conn->postponed[num]); + size_t bytestorecv = psnd->allocated_size - psnd->recv_size; + /* WinSock will destroy unread received data if send() is + failed. + To avoid lossage of received data, recv() must be + performed before every send() if any incoming data is + available. However, skip this, if buffer is already full. */ + if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 && + conn->recv[num] == Curl_recv_plain && + (!psnd->buffer || bytestorecv)) { + const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD, + CURL_SOCKET_BAD, 0); + if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) { + /* Have some incoming data */ + if(!psnd->buffer) { + /* Use buffer double default size for intermediate buffer */ + psnd->allocated_size = 2 * conn->data->set.buffer_size; + psnd->buffer = malloc(psnd->allocated_size); + psnd->recv_size = 0; + psnd->recv_processed = 0; +#ifdef DEBUGBUILD + psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */ +#endif /* DEBUGBUILD */ + bytestorecv = psnd->allocated_size; + } + if(psnd->buffer) { + ssize_t recvedbytes; + DEBUGASSERT(psnd->bindsock == sockfd); + recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size, + bytestorecv); + if(recvedbytes > 0) + psnd->recv_size += recvedbytes; + } + else + psnd->allocated_size = 0; + } + } +} + +static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf, + size_t len) +{ + struct postponed_data * const psnd = &(conn->postponed[num]); + size_t copysize; + if(!psnd->buffer) + return 0; + + DEBUGASSERT(psnd->allocated_size > 0); + DEBUGASSERT(psnd->recv_size <= psnd->allocated_size); + DEBUGASSERT(psnd->recv_processed <= psnd->recv_size); + /* Check and process data that already received and storied in internal + intermediate buffer */ + if(psnd->recv_size > psnd->recv_processed) { + DEBUGASSERT(psnd->bindsock == conn->sock[num]); + copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed); + memcpy(buf, psnd->buffer + psnd->recv_processed, copysize); + psnd->recv_processed += copysize; + } + else + copysize = 0; /* buffer was allocated, but nothing was received */ + + /* Free intermediate buffer if it has no unprocessed data */ + if(psnd->recv_processed == psnd->recv_size) { + free(psnd->buffer); + psnd->buffer = NULL; + psnd->allocated_size = 0; + psnd->recv_size = 0; + psnd->recv_processed = 0; +#ifdef DEBUGBUILD + psnd->bindsock = CURL_SOCKET_BAD; +#endif /* DEBUGBUILD */ + } + return (ssize_t)copysize; +} +#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ +/* Use "do-nothing" macros instead of functions when workaround not used */ +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) +{ + (void)conn; + (void)sockindex; + return false; +} +#define pre_receive_plain(c,n) do {} WHILE_FALSE +#define get_pre_recved(c,n,b,l) 0 +#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ + +/* Curl_infof() is for info message along the way */ + +void Curl_infof(struct Curl_easy *data, const char *fmt, ...) +{ + if(data && data->set.verbose) { + va_list ap; + size_t len; + char print_buffer[2048 + 1]; + va_start(ap, fmt); + len = mvsnprintf(print_buffer, sizeof(print_buffer), fmt, ap); + /* + * Indicate truncation of the input by replacing the last 3 characters + * with "...", and transfer the newline over in case the format had one. + */ + if(len >= sizeof(print_buffer)) { + len = strlen(fmt); + if(fmt[--len] == '\n') + msnprintf(print_buffer + (sizeof(print_buffer) - 5), 5, "...\n"); + else + msnprintf(print_buffer + (sizeof(print_buffer) - 4), 4, "..."); + } + va_end(ap); + len = strlen(print_buffer); + Curl_debug(data, CURLINFO_TEXT, print_buffer, len); + } +} + +/* Curl_failf() is for messages stating why we failed. + * The message SHALL NOT include any LF or CR. + */ + +void Curl_failf(struct Curl_easy *data, const char *fmt, ...) +{ + if(data->set.verbose || data->set.errorbuffer) { + va_list ap; + size_t len; + char error[CURL_ERROR_SIZE + 2]; + va_start(ap, fmt); + mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); + len = strlen(error); + + if(data->set.errorbuffer && !data->state.errorbuf) { + strcpy(data->set.errorbuffer, error); + data->state.errorbuf = TRUE; /* wrote error string */ + } + if(data->set.verbose) { + error[len] = '\n'; + error[++len] = '\0'; + Curl_debug(data, CURLINFO_TEXT, error, len); + } + va_end(ap); + } +} + +/* Curl_sendf() sends formatted data to the server */ +CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, + const char *fmt, ...) +{ + struct Curl_easy *data = conn->data; + ssize_t bytes_written; + size_t write_len; + CURLcode result = CURLE_OK; + char *s; + char *sptr; + va_list ap; + va_start(ap, fmt); + s = vaprintf(fmt, ap); /* returns an allocated string */ + va_end(ap); + if(!s) + return CURLE_OUT_OF_MEMORY; /* failure */ + + bytes_written = 0; + write_len = strlen(s); + sptr = s; + + for(;;) { + /* Write the buffer to the socket */ + result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); + + if(result) + break; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written); + + if((size_t)bytes_written != write_len) { + /* if not all was written at once, we must advance the pointer, decrease + the size left and try again! */ + write_len -= bytes_written; + sptr += bytes_written; + } + else + break; + } + + free(s); /* free the output string */ + + return result; +} + +/* + * Curl_write() is an internal write function that sends data to the + * server. Works with plain sockets, SCP, SSL or kerberos. + * + * If the write would block (CURLE_AGAIN), we return CURLE_OK and + * (*written == 0). Otherwise we return regular CURLcode value. + */ +CURLcode Curl_write(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, + size_t len, + ssize_t *written) +{ + ssize_t bytes_written; + CURLcode result = CURLE_OK; + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + bytes_written = conn->send[num](conn, num, mem, len, &result); + + *written = bytes_written; + if(bytes_written >= 0) + /* we completely ignore the curlcode value when subzero is not returned */ + return CURLE_OK; + + /* handle CURLE_AGAIN or a send failure */ + switch(result) { + case CURLE_AGAIN: + *written = 0; + return CURLE_OK; + + case CURLE_OK: + /* general send failure */ + return CURLE_SEND_ERROR; + + default: + /* we got a specific curlcode, forward it */ + return result; + } +} + +ssize_t Curl_send_plain(struct connectdata *conn, int num, + const void *mem, size_t len, CURLcode *code) +{ + curl_socket_t sockfd = conn->sock[num]; + ssize_t bytes_written; + /* WinSock will destroy unread received data if send() is + failed. + To avoid lossage of received data, recv() must be + performed before every send() if any incoming data is + available. */ + pre_receive_plain(conn, num); + +#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */ + if(conn->bits.tcp_fastopen) { + bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN, + conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen); + conn->bits.tcp_fastopen = FALSE; + } + else +#endif + bytes_written = swrite(sockfd, mem, len); + + *code = CURLE_OK; + if(-1 == bytes_written) { + int err = SOCKERRNO; + + if( +#ifdef WSAEWOULDBLOCK + /* This is how Windows does it */ + (WSAEWOULDBLOCK == err) +#else + /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned + due to its inability to send off data without blocking. We therefore + treat both error codes the same here */ + (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) || + (EINPROGRESS == err) +#endif + ) { + /* this is just a case of EWOULDBLOCK */ + bytes_written = 0; + *code = CURLE_AGAIN; + } + else { + char buffer[STRERROR_LEN]; + failf(conn->data, "Send failure: %s", + Curl_strerror(err, buffer, sizeof(buffer))); + conn->data->state.os_errno = err; + *code = CURLE_SEND_ERROR; + } + } + return bytes_written; +} + +/* + * Curl_write_plain() is an internal write function that sends data to the + * server using plain sockets only. Otherwise meant to have the exact same + * proto as Curl_write() + */ +CURLcode Curl_write_plain(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, + size_t len, + ssize_t *written) +{ + ssize_t bytes_written; + CURLcode result; + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + bytes_written = Curl_send_plain(conn, num, mem, len, &result); + + *written = bytes_written; + + return result; +} + +ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, + size_t len, CURLcode *code) +{ + curl_socket_t sockfd = conn->sock[num]; + ssize_t nread; + /* Check and return data that already received and storied in internal + intermediate buffer */ + nread = get_pre_recved(conn, num, buf, len); + if(nread > 0) { + *code = CURLE_OK; + return nread; + } + + nread = sread(sockfd, buf, len); + + *code = CURLE_OK; + if(-1 == nread) { + int err = SOCKERRNO; + + if( +#ifdef WSAEWOULDBLOCK + /* This is how Windows does it */ + (WSAEWOULDBLOCK == err) +#else + /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned + due to its inability to send off data without blocking. We therefore + treat both error codes the same here */ + (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) +#endif + ) { + /* this is just a case of EWOULDBLOCK */ + *code = CURLE_AGAIN; + } + else { + char buffer[STRERROR_LEN]; + failf(conn->data, "Recv failure: %s", + Curl_strerror(err, buffer, sizeof(buffer))); + conn->data->state.os_errno = err; + *code = CURLE_RECV_ERROR; + } + } + return nread; +} + +static CURLcode pausewrite(struct Curl_easy *data, + int type, /* what type of data */ + const char *ptr, + size_t len) +{ + /* signalled to pause sending on this connection, but since we have data + we want to send we need to dup it to save a copy for when the sending + is again enabled */ + struct SingleRequest *k = &data->req; + struct UrlState *s = &data->state; + char *dupl; + unsigned int i; + bool newtype = TRUE; + + if(s->tempcount) { + for(i = 0; i< s->tempcount; i++) { + if(s->tempwrite[i].type == type) { + /* data for this type exists */ + newtype = FALSE; + break; + } + } + DEBUGASSERT(i < 3); + } + else + i = 0; + + if(!newtype) { + /* append new data to old data */ + + /* figure out the new size of the data to save */ + size_t newlen = len + s->tempwrite[i].len; + /* allocate the new memory area */ + char *newptr = realloc(s->tempwrite[i].buf, newlen); + if(!newptr) + return CURLE_OUT_OF_MEMORY; + /* copy the new data to the end of the new area */ + memcpy(newptr + s->tempwrite[i].len, ptr, len); + + /* update the pointer and the size */ + s->tempwrite[i].buf = newptr; + s->tempwrite[i].len = newlen; + } + else { + dupl = Curl_memdup(ptr, len); + if(!dupl) + return CURLE_OUT_OF_MEMORY; + + /* store this information in the state struct for later use */ + s->tempwrite[i].buf = dupl; + s->tempwrite[i].len = len; + s->tempwrite[i].type = type; + + if(newtype) + s->tempcount++; + } + + /* mark the connection as RECV paused */ + k->keepon |= KEEP_RECV_PAUSE; + + DEBUGF(infof(data, "Paused %zu bytes in buffer for type %02x\n", + len, type)); + + return CURLE_OK; +} + + +/* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via + * client write callback(s) and takes care of pause requests from the + * callbacks. + */ +static CURLcode chop_write(struct connectdata *conn, + int type, + char *optr, + size_t olen) +{ + struct Curl_easy *data = conn->data; + curl_write_callback writeheader = NULL; + curl_write_callback writebody = NULL; + char *ptr = optr; + size_t len = olen; + + if(!len) + return CURLE_OK; + + /* If reading is paused, append this data to the already held data for this + type. */ + if(data->req.keepon & KEEP_RECV_PAUSE) + return pausewrite(data, type, ptr, len); + + /* Determine the callback(s) to use. */ + if(type & CLIENTWRITE_BODY) + writebody = data->set.fwrite_func; + if((type & CLIENTWRITE_HEADER) && + (data->set.fwrite_header || data->set.writeheader)) { + /* + * Write headers to the same callback or to the especially setup + * header callback function (added after version 7.7.1). + */ + writeheader = + data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; + } + + /* Chop data, write chunks. */ + while(len) { + size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE; + + if(writebody) { + size_t wrote; + Curl_set_in_callback(data, true); + wrote = writebody(ptr, 1, chunklen, data->set.out); + Curl_set_in_callback(data, false); + + if(CURL_WRITEFUNC_PAUSE == wrote) { + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* Protocols that work without network cannot be paused. This is + actually only FILE:// just now, and it can't pause since the + transfer isn't done using the "normal" procedure. */ + failf(data, "Write callback asked for PAUSE when not supported!"); + return CURLE_WRITE_ERROR; + } + return pausewrite(data, type, ptr, len); + } + if(wrote != chunklen) { + failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen); + return CURLE_WRITE_ERROR; + } + } + + ptr += chunklen; + len -= chunklen; + } + + if(writeheader) { + size_t wrote; + ptr = optr; + len = olen; + Curl_set_in_callback(data, true); + wrote = writeheader(ptr, 1, len, data->set.writeheader); + Curl_set_in_callback(data, false); + + if(CURL_WRITEFUNC_PAUSE == wrote) + /* here we pass in the HEADER bit only since if this was body as well + then it was passed already and clearly that didn't trigger the + pause, so this is saved for later with the HEADER bit only */ + return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); + + if(wrote != len) { + failf(data, "Failed writing header"); + return CURLE_WRITE_ERROR; + } + } + + return CURLE_OK; +} + + +/* Curl_client_write() sends data to the write callback(s) + + The bit pattern defines to what "streams" to write to. Body and/or header. + The defines are in sendf.h of course. + + If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the + local character encoding. This is a problem and should be changed in + the future to leave the original data alone. + */ +CURLcode Curl_client_write(struct connectdata *conn, + int type, + char *ptr, + size_t len) +{ + struct Curl_easy *data = conn->data; + + if(0 == len) + len = strlen(ptr); + + DEBUGASSERT(type <= 3); + + /* FTP data may need conversion. */ + if((type & CLIENTWRITE_BODY) && + (conn->handler->protocol & PROTO_FAMILY_FTP) && + conn->proto.ftpc.transfertype == 'A') { + /* convert from the network encoding */ + CURLcode result = Curl_convert_from_network(data, ptr, len); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + +#ifdef CURL_DO_LINEEND_CONV + /* convert end-of-line markers */ + len = convert_lineends(data, ptr, len); +#endif /* CURL_DO_LINEEND_CONV */ + } + + return chop_write(conn, type, ptr, len); +} + +CURLcode Curl_read_plain(curl_socket_t sockfd, + char *buf, + size_t bytesfromsocket, + ssize_t *n) +{ + ssize_t nread = sread(sockfd, buf, bytesfromsocket); + + if(-1 == nread) { + int err = SOCKERRNO; + int return_error; +#ifdef USE_WINSOCK + return_error = WSAEWOULDBLOCK == err; +#else + return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err; +#endif + if(return_error) + return CURLE_AGAIN; + return CURLE_RECV_ERROR; + } + + /* we only return number of bytes read when we return OK */ + *n = nread; + return CURLE_OK; +} + +/* + * Internal read-from-socket function. This is meant to deal with plain + * sockets, SSL sockets and kerberos sockets. + * + * Returns a regular CURLcode value. + */ +CURLcode Curl_read(struct connectdata *conn, /* connection data */ + curl_socket_t sockfd, /* read from this socket */ + char *buf, /* store read data here */ + size_t sizerequested, /* max amount to read */ + ssize_t *n) /* amount bytes read */ +{ + CURLcode result = CURLE_RECV_ERROR; + ssize_t nread = 0; + size_t bytesfromsocket = 0; + char *buffertofill = NULL; + struct Curl_easy *data = conn->data; + + /* Set 'num' to 0 or 1, depending on which socket that has been sent here. + If it is the second socket, we set num to 1. Otherwise to 0. This lets + us use the correct ssl handle. */ + int num = (sockfd == conn->sock[SECONDARYSOCKET]); + + *n = 0; /* reset amount to zero */ + + bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size); + buffertofill = buf; + + nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result); + if(nread < 0) + return result; + + *n += nread; + + return CURLE_OK; +} + +/* return 0 on success */ +int Curl_debug(struct Curl_easy *data, curl_infotype type, + char *ptr, size_t size) +{ + static const char s_infotype[CURLINFO_END][3] = { + "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; + int rc = 0; + +#ifdef CURL_DOES_CONVERSIONS + char *buf = NULL; + size_t conv_size = 0; + + switch(type) { + case CURLINFO_HEADER_OUT: + buf = Curl_memdup(ptr, size); + if(!buf) + return 1; + conv_size = size; + + /* Special processing is needed for this block if it + * contains both headers and data (separated by CRLFCRLF). + * We want to convert just the headers, leaving the data as-is. + */ + if(size > 4) { + size_t i; + for(i = 0; i < size-4; i++) { + if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) { + /* convert everything through this CRLFCRLF but no further */ + conv_size = i + 4; + break; + } + } + } + + Curl_convert_from_network(data, buf, conv_size); + /* Curl_convert_from_network calls failf if unsuccessful */ + /* we might as well continue even if it fails... */ + ptr = buf; /* switch pointer to use my buffer instead */ + break; + default: + /* leave everything else as-is */ + break; + } +#endif /* CURL_DOES_CONVERSIONS */ + + if(data->set.fdebug) { + Curl_set_in_callback(data, true); + rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); + Curl_set_in_callback(data, false); + } + else { + switch(type) { + case CURLINFO_TEXT: + case CURLINFO_HEADER_OUT: + case CURLINFO_HEADER_IN: + fwrite(s_infotype[type], 2, 1, data->set.err); + fwrite(ptr, size, 1, data->set.err); +#ifdef CURL_DOES_CONVERSIONS + if(size != conv_size) { + /* we had untranslated data so we need an explicit newline */ + fwrite("\n", 1, 1, data->set.err); + } +#endif + break; + default: /* nada */ + break; + } + } +#ifdef CURL_DOES_CONVERSIONS + free(buf); +#endif + return rc; +} diff --git a/libcurl/lib/sendf.h b/libcurl/lib/sendf.h new file mode 100644 index 0000000..638d595 --- /dev/null +++ b/libcurl/lib/sendf.h @@ -0,0 +1,92 @@ +#ifndef HEADER_CURL_SENDF_H +#define HEADER_CURL_SENDF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *, + const char *fmt, ...); +void Curl_infof(struct Curl_easy *, const char *fmt, ...); +void Curl_failf(struct Curl_easy *, const char *fmt, ...); + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + +#if defined(HAVE_VARIADIC_MACROS_C99) +#define infof(...) Curl_nop_stmt +#elif defined(HAVE_VARIADIC_MACROS_GCC) +#define infof(x...) Curl_nop_stmt +#else +//#error "missing VARIADIC macro define, fix and rebuild!" +#define infof (void) +#endif + +#else /* CURL_DISABLE_VERBOSE_STRINGS */ + +#define infof Curl_infof + +#endif /* CURL_DISABLE_VERBOSE_STRINGS */ + +#define failf Curl_failf + +#define CLIENTWRITE_BODY (1<<0) +#define CLIENTWRITE_HEADER (1<<1) +#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) + +CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, + size_t len) WARN_UNUSED_RESULT; + +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex); + +/* internal read-function, does plain socket only */ +CURLcode Curl_read_plain(curl_socket_t sockfd, + char *buf, + size_t bytesfromsocket, + ssize_t *n); + +ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, + size_t len, CURLcode *code); +ssize_t Curl_send_plain(struct connectdata *conn, int num, + const void *mem, size_t len, CURLcode *code); + +/* internal read-function, does plain socket, SSL and krb4 */ +CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd, + char *buf, size_t buffersize, + ssize_t *n); +/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */ +CURLcode Curl_write(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, size_t len, + ssize_t *written); + +/* internal write-function, does plain sockets ONLY */ +CURLcode Curl_write_plain(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, size_t len, + ssize_t *written); + +/* the function used to output verbose information */ +int Curl_debug(struct Curl_easy *data, curl_infotype type, + char *ptr, size_t size); + + +#endif /* HEADER_CURL_SENDF_H */ diff --git a/libcurl/lib/setopt.c b/libcurl/lib/setopt.c new file mode 100644 index 0000000..1dbf00f --- /dev/null +++ b/libcurl/lib/setopt.c @@ -0,0 +1,2779 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_LINUX_TCP_H +#include +#endif + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "content_encoding.h" +#include "strcase.h" +#include "share.h" +#include "vtls/vtls.h" +#include "warnless.h" +#include "sendf.h" +#include "http2.h" +#include "setopt.h" +#include "multiif.h" +#include "altsvc.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +CURLcode Curl_setstropt(char **charp, const char *s) +{ + /* Release the previous storage at `charp' and replace by a dynamic storage + copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */ + + Curl_safefree(*charp); + + if(s) { + char *str = strdup(s); + + if(str) { + size_t len = strlen(str); + if(len > CURL_MAX_INPUT_LENGTH) { + free(str); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } + if(!str) + return CURLE_OUT_OF_MEMORY; + + *charp = str; + } + + return CURLE_OK; +} + +static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) +{ + CURLcode result = CURLE_OK; + char *user = NULL; + char *passwd = NULL; + + /* Parse the login details if specified. It not then we treat NULL as a hint + to clear the existing data */ + if(option) { + result = Curl_parse_login_details(option, strlen(option), + (userp ? &user : NULL), + (passwdp ? &passwd : NULL), + NULL); + } + + if(!result) { + /* Store the username part of option if required */ + if(userp) { + if(!user && option && option[0] == ':') { + /* Allocate an empty string instead of returning NULL as user name */ + user = strdup(""); + if(!user) + result = CURLE_OUT_OF_MEMORY; + } + + Curl_safefree(*userp); + *userp = user; + } + + /* Store the password part of option if required */ + if(passwdp) { + Curl_safefree(*passwdp); + *passwdp = passwd; + } + } + + return result; +} + +#define C_SSLVERSION_VALUE(x) (x & 0xffff) +#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000) + +/* + * Do not make Curl_vsetopt() static: it is called from + * packages/OS400/ccsidcurl.c. + */ +CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) +{ + char *argptr; + CURLcode result = CURLE_OK; + long arg; + unsigned long uarg; + curl_off_t bigsize; + + switch(option) { + case CURLOPT_DNS_CACHE_TIMEOUT: + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.dns_cache_timeout = arg; + break; + case CURLOPT_DNS_USE_GLOBAL_CACHE: + /* deprecated */ + break; + case CURLOPT_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection for proxy */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_TLS13_CIPHERS: + if(Curl_ssl_tls13_ciphersuites()) { + /* set preferred list of TLS 1.3 cipher suites */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG], + va_arg(param, char *)); + } + else + return CURLE_NOT_BUILT_IN; + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_TLS13_CIPHERS: + if(Curl_ssl_tls13_ciphersuites()) { + /* set preferred list of TLS 1.3 cipher suites for proxy */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY], + va_arg(param, char *)); + } + else + return CURLE_NOT_BUILT_IN; + break; +#endif + case CURLOPT_RANDOM_FILE: + /* + * This is the path name to a file that contains random data to seed + * the random SSL stuff with. The file is only used for reading. + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE], + va_arg(param, char *)); + break; + case CURLOPT_EGDSOCKET: + /* + * The Entropy Gathering Daemon socket pathname + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET], + va_arg(param, char *)); + break; + case CURLOPT_MAXCONNECTS: + /* + * Set the absolute number of maximum simultaneous alive connection that + * libcurl is allowed to have. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxconnects = arg; + break; + case CURLOPT_FORBID_REUSE: + /* + * When this transfer is done, it must not be left to be reused by a + * subsequent transfer but shall be closed immediately. + */ + data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_FRESH_CONNECT: + /* + * This transfer shall not use a previously cached connection but + * should be made with a fresh new connect! + */ + data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_VERBOSE: + /* + * Verbose means infof() calls that give a lot of information about + * the connection and transfer procedures as well as internal choices. + */ + data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_HEADER: + /* + * Set to include the header in the general data output stream. + */ + data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_NOPROGRESS: + /* + * Shut off the internal supported progress meter + */ + data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE; + if(data->set.hide_progress) + data->progress.flags |= PGRS_HIDE; + else + data->progress.flags &= ~PGRS_HIDE; + break; + case CURLOPT_NOBODY: + /* + * Do not include the body part in the output data stream. + */ + data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_FAILONERROR: + /* + * Don't output the >=400 error code HTML-page, but instead only + * return error. + */ + data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_KEEP_SENDING_ON_ERROR: + data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + case CURLOPT_UPLOAD: + case CURLOPT_PUT: + /* + * We want to sent data to the remote host. If this is HTTP, that equals + * using the PUT request. + */ + data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE; + if(data->set.upload) { + /* If this is HTTP, PUT is what's needed to "upload" */ + data->set.httpreq = HTTPREQ_PUT; + data->set.opt_no_body = FALSE; /* this is implied */ + } + else + /* In HTTP, the opposite of upload is GET (unless NOBODY is true as + then this can be changed to HEAD later on) */ + data->set.httpreq = HTTPREQ_GET; + break; + case CURLOPT_REQUEST_TARGET: + result = Curl_setstropt(&data->set.str[STRING_TARGET], + va_arg(param, char *)); + break; + case CURLOPT_FILETIME: + /* + * Try to get the file time of the remote document. The time will + * later (possibly) become available using curl_easy_getinfo(). + */ + data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_SERVER_RESPONSE_TIMEOUT: + /* + * Option that specifies how quickly an server response must be obtained + * before it is considered failure. For pingpong protocols. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.server_response_timeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; +#ifndef CURL_DISABLE_TFTP + case CURLOPT_TFTP_NO_OPTIONS: + /* + * Option that prevents libcurl from sending TFTP option requests to the + * server. + */ + data->set.tftp_no_options = va_arg(param, long) != 0; + break; + case CURLOPT_TFTP_BLKSIZE: + /* + * TFTP option that specifies the block size to use for data transmission. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tftp_blksize = arg; + break; +#endif +#ifndef CURL_DISABLE_NETRC + case CURLOPT_NETRC: + /* + * Parse the $HOME/.netrc file + */ + arg = va_arg(param, long); + if((arg < CURL_NETRC_IGNORED) || (arg > CURL_NETRC_REQUIRED)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_netrc = (enum CURL_NETRC_OPTION)arg; + break; + case CURLOPT_NETRC_FILE: + /* + * Use this file instead of the $HOME/.netrc file + */ + result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE], + va_arg(param, char *)); + break; +#endif + case CURLOPT_TRANSFERTEXT: + /* + * This option was previously named 'FTPASCII'. Renamed to work with + * more protocols than merely FTP. + * + * Transfer using ASCII (instead of BINARY). + */ + data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_TIMECONDITION: + /* + * Set HTTP time condition. This must be one of the defines in the + * curl/curl.h header file. + */ + arg = va_arg(param, long); + if((arg < CURL_TIMECOND_NONE) || (arg > CURL_TIMECOND_LASTMOD)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.timecondition = (curl_TimeCond)arg; + break; + case CURLOPT_TIMEVALUE: + /* + * This is the value to compare with the remote document with the + * method set with CURLOPT_TIMECONDITION + */ + data->set.timevalue = (time_t)va_arg(param, long); + break; + + case CURLOPT_TIMEVALUE_LARGE: + /* + * This is the value to compare with the remote document with the + * method set with CURLOPT_TIMECONDITION + */ + data->set.timevalue = (time_t)va_arg(param, curl_off_t); + break; + + case CURLOPT_SSLVERSION: + case CURLOPT_PROXY_SSLVERSION: + /* + * Set explicit SSL version to try to connect with, as some SSL + * implementations are lame. + */ +#ifdef USE_SSL + { + long version, version_max; + struct ssl_primary_config *primary = (option == CURLOPT_SSLVERSION ? + &data->set.ssl.primary : + &data->set.proxy_ssl.primary); + + arg = va_arg(param, long); + + version = C_SSLVERSION_VALUE(arg); + version_max = C_SSLVERSION_MAX_VALUE(arg); + + if(version < CURL_SSLVERSION_DEFAULT || + version >= CURL_SSLVERSION_LAST || + version_max < CURL_SSLVERSION_MAX_NONE || + version_max >= CURL_SSLVERSION_MAX_LAST) + return CURLE_BAD_FUNCTION_ARGUMENT; + + primary->version = version; + primary->version_max = version_max; + } +#else + result = CURLE_UNKNOWN_OPTION; +#endif + break; + +#ifndef CURL_DISABLE_HTTP + case CURLOPT_AUTOREFERER: + /* + * Switch on automatic referer that gets set if curl follows locations. + */ + data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_ACCEPT_ENCODING: + /* + * String to use at the value of Accept-Encoding header. + * + * If the encoding is set to "" we use an Accept-Encoding header that + * encompasses all the encodings we support. + * If the encoding is set to NULL we don't send an Accept-Encoding header + * and ignore an received Content-Encoding header. + * + */ + argptr = va_arg(param, char *); + if(argptr && !*argptr) { + argptr = Curl_all_content_encodings(); + if(!argptr) + result = CURLE_OUT_OF_MEMORY; + else { + result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); + free(argptr); + } + } + else + result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); + break; + + case CURLOPT_TRANSFER_ENCODING: + data->set.http_transfer_encoding = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + + case CURLOPT_FOLLOWLOCATION: + /* + * Follow Location: header hints on a HTTP-server. + */ + data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_UNRESTRICTED_AUTH: + /* + * Send authentication (user+password) when following locations, even when + * hostname changed. + */ + data->set.allow_auth_to_other_hosts = + (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_MAXREDIRS: + /* + * The maximum amount of hops you allow curl to follow Location: + * headers. This should mostly be used to detect never-ending loops. + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxredirs = arg; + break; + + case CURLOPT_POSTREDIR: + /* + * Set the behaviour of POST when redirecting + * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302 + * CURL_REDIR_POST_301 - POST is kept as POST after 301 + * CURL_REDIR_POST_302 - POST is kept as POST after 302 + * CURL_REDIR_POST_303 - POST is kept as POST after 303 + * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303 + * other - POST is kept as POST after 301 and 302 + */ + arg = va_arg(param, long); + if(arg < CURL_REDIR_GET_ALL) + /* no return error on too high numbers since the bitmask could be + extended in a future */ + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.keep_post = arg & CURL_REDIR_POST_ALL; + break; + + case CURLOPT_POST: + /* Does this option serve a purpose anymore? Yes it does, when + CURLOPT_POSTFIELDS isn't used and the POST data is read off the + callback! */ + if(va_arg(param, long)) { + data->set.httpreq = HTTPREQ_POST; + data->set.opt_no_body = FALSE; /* this is implied */ + } + else + data->set.httpreq = HTTPREQ_GET; + break; + + case CURLOPT_COPYPOSTFIELDS: + /* + * A string with POST data. Makes curl HTTP POST. Even if it is NULL. + * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to + * CURLOPT_COPYPOSTFIELDS and not altered later. + */ + argptr = va_arg(param, char *); + + if(!argptr || data->set.postfieldsize == -1) + result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr); + else { + /* + * Check that requested length does not overflow the size_t type. + */ + + if((data->set.postfieldsize < 0) || + ((sizeof(curl_off_t) != sizeof(size_t)) && + (data->set.postfieldsize > (curl_off_t)((size_t)-1)))) + result = CURLE_OUT_OF_MEMORY; + else { + char *p; + + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + + /* Allocate even when size == 0. This satisfies the need of possible + later address compare to detect the COPYPOSTFIELDS mode, and + to mark that postfields is used rather than read function or + form data. + */ + p = malloc((size_t)(data->set.postfieldsize? + data->set.postfieldsize:1)); + + if(!p) + result = CURLE_OUT_OF_MEMORY; + else { + if(data->set.postfieldsize) + memcpy(p, argptr, (size_t)data->set.postfieldsize); + + data->set.str[STRING_COPYPOSTFIELDS] = p; + } + } + } + + data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS]; + data->set.httpreq = HTTPREQ_POST; + break; + + case CURLOPT_POSTFIELDS: + /* + * Like above, but use static data instead of copying it. + */ + data->set.postfields = va_arg(param, void *); + /* Release old copied data. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.httpreq = HTTPREQ_POST; + break; + + case CURLOPT_POSTFIELDSIZE: + /* + * The size of the POSTFIELD data to prevent libcurl to do strlen() to + * figure it out. Enables binary posts. + */ + bigsize = va_arg(param, long); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.postfieldsize < bigsize && + data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { + /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.postfields = NULL; + } + + data->set.postfieldsize = bigsize; + break; + + case CURLOPT_POSTFIELDSIZE_LARGE: + /* + * The size of the POSTFIELD data to prevent libcurl to do strlen() to + * figure it out. Enables binary posts. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.postfieldsize < bigsize && + data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { + /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.postfields = NULL; + } + + data->set.postfieldsize = bigsize; + break; + + case CURLOPT_HTTPPOST: + /* + * Set to make us do HTTP POST + */ + data->set.httppost = va_arg(param, struct curl_httppost *); + data->set.httpreq = HTTPREQ_POST_FORM; + data->set.opt_no_body = FALSE; /* this is implied */ + break; +#endif /* CURL_DISABLE_HTTP */ + + case CURLOPT_MIMEPOST: + /* + * Set to make us do MIME/form POST + */ + result = Curl_mime_set_subparts(&data->set.mimepost, + va_arg(param, curl_mime *), FALSE); + if(!result) { + data->set.httpreq = HTTPREQ_POST_MIME; + data->set.opt_no_body = FALSE; /* this is implied */ + } + break; + + case CURLOPT_REFERER: + /* + * String to set in the HTTP Referer: field. + */ + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + result = Curl_setstropt(&data->set.str[STRING_SET_REFERER], + va_arg(param, char *)); + data->change.referer = data->set.str[STRING_SET_REFERER]; + break; + + case CURLOPT_USERAGENT: + /* + * String to use in the HTTP User-Agent field + */ + result = Curl_setstropt(&data->set.str[STRING_USERAGENT], + va_arg(param, char *)); + break; + + case CURLOPT_HTTPHEADER: + /* + * Set a list with HTTP headers to use (or replace internals with) + */ + data->set.headers = va_arg(param, struct curl_slist *); + break; + +#ifndef CURL_DISABLE_HTTP +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXYHEADER: + /* + * Set a list with proxy headers to use (or replace internals with) + * + * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a + * long time we remain doing it this way until CURLOPT_PROXYHEADER is + * used. As soon as this option has been used, if set to anything but + * NULL, custom headers for proxies are only picked from this list. + * + * Set this option to NULL to restore the previous behavior. + */ + data->set.proxyheaders = va_arg(param, struct curl_slist *); + break; +#endif + case CURLOPT_HEADEROPT: + /* + * Set header option. + */ + arg = va_arg(param, long); + data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE); + break; + + case CURLOPT_HTTP200ALIASES: + /* + * Set a list of aliases for HTTP 200 in response header + */ + data->set.http200aliases = va_arg(param, struct curl_slist *); + break; + +#if !defined(CURL_DISABLE_COOKIES) + case CURLOPT_COOKIE: + /* + * Cookie string to send to the remote server in the request. + */ + result = Curl_setstropt(&data->set.str[STRING_COOKIE], + va_arg(param, char *)); + break; + + case CURLOPT_COOKIEFILE: + /* + * Set cookie file to read and parse. Can be used multiple times. + */ + argptr = (char *)va_arg(param, void *); + if(argptr) { + struct curl_slist *cl; + /* append the cookie file name to the list of file names, and deal with + them later */ + cl = curl_slist_append(data->change.cookielist, argptr); + if(!cl) { + curl_slist_free_all(data->change.cookielist); + data->change.cookielist = NULL; + return CURLE_OUT_OF_MEMORY; + } + data->change.cookielist = cl; /* store the list for later use */ + } + break; + + case CURLOPT_COOKIEJAR: + /* + * Set cookie file name to dump all cookies to when we're done. + */ + { + struct CookieInfo *newcookies; + result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR], + va_arg(param, char *)); + + /* + * Activate the cookie parser. This may or may not already + * have been made. + */ + newcookies = Curl_cookie_init(data, NULL, data->cookies, + data->set.cookiesession); + if(!newcookies) + result = CURLE_OUT_OF_MEMORY; + data->cookies = newcookies; + } + break; + + case CURLOPT_COOKIESESSION: + /* + * Set this option to TRUE to start a new "cookie session". It will + * prevent the forthcoming read-cookies-from-file actions to accept + * cookies that are marked as being session cookies, as they belong to a + * previous session. + * + * In the original Netscape cookie spec, "session cookies" are cookies + * with no expire date set. RFC2109 describes the same action if no + * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds + * a 'Discard' action that can enforce the discard even for cookies that + * have a Max-Age. + * + * We run mostly with the original cookie spec, as hardly anyone implements + * anything else. + */ + data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_COOKIELIST: + argptr = va_arg(param, char *); + + if(argptr == NULL) + break; + + if(strcasecompare(argptr, "ALL")) { + /* clear all cookies */ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_clearall(data->cookies); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + else if(strcasecompare(argptr, "SESS")) { + /* clear session cookies */ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_clearsess(data->cookies); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + else if(strcasecompare(argptr, "FLUSH")) { + /* flush cookies to file, takes care of the locking */ + Curl_flush_cookies(data, 0); + } + else if(strcasecompare(argptr, "RELOAD")) { + /* reload cookies from file */ + Curl_cookie_loadfiles(data); + break; + } + else { + if(!data->cookies) + /* if cookie engine was not running, activate it */ + data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); + + argptr = strdup(argptr); + if(!argptr || !data->cookies) { + result = CURLE_OUT_OF_MEMORY; + free(argptr); + } + else { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + + if(checkprefix("Set-Cookie:", argptr)) + /* HTTP Header format line */ + Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL, + NULL, TRUE); + + else + /* Netscape format line */ + Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL, + NULL, TRUE); + + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + free(argptr); + } + } + + break; +#endif /* !CURL_DISABLE_COOKIES */ + + case CURLOPT_HTTPGET: + /* + * Set to force us do HTTP GET + */ + if(va_arg(param, long)) { + data->set.httpreq = HTTPREQ_GET; + data->set.upload = FALSE; /* switch off upload */ + data->set.opt_no_body = FALSE; /* this is implied */ + } + break; + + case CURLOPT_HTTP_VERSION: + /* + * This sets a requested HTTP version to be used. The value is one of + * the listed enums in curl/curl.h. + */ + arg = va_arg(param, long); + if(arg < CURL_HTTP_VERSION_NONE) + return CURLE_BAD_FUNCTION_ARGUMENT; +#ifndef USE_NGHTTP2 + if(arg >= CURL_HTTP_VERSION_2) + return CURLE_UNSUPPORTED_PROTOCOL; +#else + if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) + return CURLE_UNSUPPORTED_PROTOCOL; + if(arg == CURL_HTTP_VERSION_NONE) + arg = CURL_HTTP_VERSION_2TLS; +#endif + data->set.httpversion = arg; + break; + + case CURLOPT_EXPECT_100_TIMEOUT_MS: + /* + * Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.expect_100_timeout = arg; + break; + + case CURLOPT_HTTP09_ALLOWED: + arg = va_arg(param, unsigned long); + if(arg > 1L) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.http09_allowed = arg ? TRUE : FALSE; + break; +#endif /* CURL_DISABLE_HTTP */ + + case CURLOPT_HTTPAUTH: + /* + * Set HTTP Authentication type BITMASK. + */ + { + int bitcheck; + bool authbits; + unsigned long auth = va_arg(param, unsigned long); + + if(auth == CURLAUTH_NONE) { + data->set.httpauth = auth; + break; + } + + /* the DIGEST_IE bit is only used to set a special marker, for all the + rest we need to handle it as normal DIGEST */ + data->state.authhost.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); + + if(auth & CURLAUTH_DIGEST_IE) { + auth |= CURLAUTH_DIGEST; /* set standard digest bit */ + auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ + } + + /* switch off bits we can't support */ +#ifndef USE_NTLM + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#elif !defined(NTLM_WB_ENABLED) + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#endif +#ifndef USE_SPNEGO + auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without + GSS-API or SSPI */ +#endif + + /* check if any auth bit lower than CURLAUTH_ONLY is still set */ + bitcheck = 0; + authbits = FALSE; + while(bitcheck < 31) { + if(auth & (1UL << bitcheck++)) { + authbits = TRUE; + break; + } + } + if(!authbits) + return CURLE_NOT_BUILT_IN; /* no supported types left! */ + + data->set.httpauth = auth; + } + break; + + case CURLOPT_CUSTOMREQUEST: + /* + * Set a custom string to use as request + */ + result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST], + va_arg(param, char *)); + + /* we don't set + data->set.httpreq = HTTPREQ_CUSTOM; + here, we continue as if we were using the already set type + and this just changes the actual request keyword */ + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_HTTPPROXYTUNNEL: + /* + * Tunnel operations through the proxy instead of normal proxy use + */ + data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + + case CURLOPT_PROXYPORT: + /* + * Explicitly set HTTP proxy port number. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.proxyport = arg; + break; + + case CURLOPT_PROXYAUTH: + /* + * Set HTTP Authentication type BITMASK. + */ + { + int bitcheck; + bool authbits; + unsigned long auth = va_arg(param, unsigned long); + + if(auth == CURLAUTH_NONE) { + data->set.proxyauth = auth; + break; + } + + /* the DIGEST_IE bit is only used to set a special marker, for all the + rest we need to handle it as normal DIGEST */ + data->state.authproxy.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); + + if(auth & CURLAUTH_DIGEST_IE) { + auth |= CURLAUTH_DIGEST; /* set standard digest bit */ + auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ + } + /* switch off bits we can't support */ +#ifndef USE_NTLM + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#elif !defined(NTLM_WB_ENABLED) + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#endif +#ifndef USE_SPNEGO + auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without + GSS-API or SSPI */ +#endif + + /* check if any auth bit lower than CURLAUTH_ONLY is still set */ + bitcheck = 0; + authbits = FALSE; + while(bitcheck < 31) { + if(auth & (1UL << bitcheck++)) { + authbits = TRUE; + break; + } + } + if(!authbits) + return CURLE_NOT_BUILT_IN; /* no supported types left! */ + + data->set.proxyauth = auth; + } + break; + + case CURLOPT_PROXY: + /* + * Set proxy server:port to use as proxy. + * + * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL) + * we explicitly say that we don't want to use a proxy + * (even though there might be environment variables saying so). + * + * Setting it to NULL, means no proxy but allows the environment variables + * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL). + */ + result = Curl_setstropt(&data->set.str[STRING_PROXY], + va_arg(param, char *)); + break; + + case CURLOPT_PRE_PROXY: + /* + * Set proxy server:port to use as SOCKS proxy. + * + * If the proxy is set to "" or NULL we explicitly say that we don't want + * to use the socks proxy. + */ + result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY], + va_arg(param, char *)); + break; + + case CURLOPT_PROXYTYPE: + /* + * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME + */ + arg = va_arg(param, long); + if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.proxytype = (curl_proxytype)arg; + break; + + case CURLOPT_PROXY_TRANSFER_MODE: + /* + * set transfer mode (;type=) when doing FTP via an HTTP proxy + */ + switch(va_arg(param, long)) { + case 0: + data->set.proxy_transfer_mode = FALSE; + break; + case 1: + data->set.proxy_transfer_mode = TRUE; + break; + default: + /* reserve other values for future use */ + result = CURLE_UNKNOWN_OPTION; + break; + } + break; +#endif /* CURL_DISABLE_PROXY */ + + case CURLOPT_SOCKS5_AUTH: + data->set.socks5auth = va_arg(param, unsigned long); + if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) + result = CURLE_NOT_BUILT_IN; + break; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + case CURLOPT_SOCKS5_GSSAPI_NEC: + /* + * Set flag for NEC SOCK5 support + */ + data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#endif +#ifndef CURL_DISABLE_PROXY + case CURLOPT_SOCKS5_GSSAPI_SERVICE: + case CURLOPT_PROXY_SERVICE_NAME: + /* + * Set proxy authentication service name for Kerberos 5 and SPNEGO + */ + result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SERVICE_NAME: + /* + * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO + */ + result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME], + va_arg(param, char *)); + break; + + case CURLOPT_HEADERDATA: + /* + * Custom pointer to pass the header write callback function + */ + data->set.writeheader = (void *)va_arg(param, void *); + break; + case CURLOPT_ERRORBUFFER: + /* + * Error buffer provided by the caller to get the human readable + * error string in. + */ + data->set.errorbuffer = va_arg(param, char *); + break; + case CURLOPT_WRITEDATA: + /* + * FILE pointer to write to. Or possibly + * used as argument to the write callback. + */ + data->set.out = va_arg(param, void *); + break; + + case CURLOPT_DIRLISTONLY: + /* + * An option that changes the command to one that asks for a list only, no + * file info details. Used for FTP, POP3 and SFTP. + */ + data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_APPEND: + /* + * We want to upload and append to an existing file. Used for FTP and + * SFTP. + */ + data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + +#ifndef CURL_DISABLE_FTP + case CURLOPT_FTP_FILEMETHOD: + /* + * How do access files over FTP. + */ + arg = va_arg(param, long); + if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftp_filemethod = (curl_ftpfile)arg; + break; + case CURLOPT_FTPPORT: + /* + * Use FTP PORT, this also specifies which IP address to use + */ + result = Curl_setstropt(&data->set.str[STRING_FTPPORT], + va_arg(param, char *)); + data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_EPRT: + data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_EPSV: + data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_PRET: + data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_SSL_CCC: + arg = va_arg(param, long); + if((arg < CURLFTPSSL_CCC_NONE) || (arg > CURLFTPSSL_CCC_ACTIVE)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftp_ccc = (curl_ftpccc)arg; + break; + + case CURLOPT_FTP_SKIP_PASV_IP: + /* + * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the + * bypass of the IP address in PASV responses. + */ + data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_ACCOUNT: + result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT], + va_arg(param, char *)); + break; + + case CURLOPT_FTP_ALTERNATIVE_TO_USER: + result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER], + va_arg(param, char *)); + break; + + case CURLOPT_FTPSSLAUTH: + /* + * Set a specific auth for FTP-SSL transfers. + */ + arg = va_arg(param, long); + if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftpsslauth = (curl_ftpauth)arg; + break; + case CURLOPT_KRBLEVEL: + /* + * A string that defines the kerberos security level. + */ + result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL], + va_arg(param, char *)); + data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE; + break; +#endif + case CURLOPT_FTP_CREATE_MISSING_DIRS: + /* + * An FTP/SFTP option that modifies an upload to create missing + * directories on the server. + */ + switch(va_arg(param, long)) { + case 0: + data->set.ftp_create_missing_dirs = 0; + break; + case 1: + data->set.ftp_create_missing_dirs = 1; + break; + case 2: + data->set.ftp_create_missing_dirs = 2; + break; + default: + /* reserve other values for future use */ + result = CURLE_UNKNOWN_OPTION; + break; + } + break; + case CURLOPT_READDATA: + /* + * FILE pointer to read the file to be uploaded from. Or possibly + * used as argument to the read callback. + */ + data->set.in_set = va_arg(param, void *); + break; + case CURLOPT_INFILESIZE: + /* + * If known, this should inform curl about the file size of the + * to-be-uploaded file. + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.filesize = arg; + break; + case CURLOPT_INFILESIZE_LARGE: + /* + * If known, this should inform curl about the file size of the + * to-be-uploaded file. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.filesize = bigsize; + break; + case CURLOPT_LOW_SPEED_LIMIT: + /* + * The low speed limit that if transfers are below this for + * CURLOPT_LOW_SPEED_TIME, the transfer is aborted. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.low_speed_limit = arg; + break; + case CURLOPT_MAX_SEND_SPEED_LARGE: + /* + * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE + * bytes per second the transfer is throttled.. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_send_speed = bigsize; + break; + case CURLOPT_MAX_RECV_SPEED_LARGE: + /* + * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per + * second the transfer is throttled.. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_recv_speed = bigsize; + break; + case CURLOPT_LOW_SPEED_TIME: + /* + * The low speed time that if transfers are below the set + * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.low_speed_time = arg; + break; + case CURLOPT_CURLU: + /* + * pass CURLU to set URL + */ + data->set.uh = va_arg(param, CURLU *); + break; + case CURLOPT_URL: + /* + * The URL to fetch. + */ + if(data->change.url_alloc) { + /* the already set URL is allocated, free it first! */ + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + result = Curl_setstropt(&data->set.str[STRING_SET_URL], + va_arg(param, char *)); + data->change.url = data->set.str[STRING_SET_URL]; + break; + case CURLOPT_PORT: + /* + * The port number to use when getting the URL + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_port = arg; + break; + case CURLOPT_TIMEOUT: + /* + * The maximum time you allow curl to use for a single transfer + * operation. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.timeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; + + case CURLOPT_TIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.timeout = arg; + break; + + case CURLOPT_CONNECTTIMEOUT: + /* + * The maximum time you allow curl to use to connect. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.connecttimeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; + + case CURLOPT_CONNECTTIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.connecttimeout = arg; + break; + + case CURLOPT_ACCEPTTIMEOUT_MS: + /* + * The maximum time you allow curl to wait for server connect + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.accepttimeout = arg; + break; + + case CURLOPT_USERPWD: + /* + * user:password to use in the operation + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_USERNAME], + &data->set.str[STRING_PASSWORD]); + break; + + case CURLOPT_USERNAME: + /* + * authentication user name to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_USERNAME], + va_arg(param, char *)); + break; + + case CURLOPT_PASSWORD: + /* + * authentication password to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PASSWORD], + va_arg(param, char *)); + break; + + case CURLOPT_LOGIN_OPTIONS: + /* + * authentication options to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_OPTIONS], + va_arg(param, char *)); + break; + + case CURLOPT_XOAUTH2_BEARER: + /* + * OAuth 2.0 bearer token to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_BEARER], + va_arg(param, char *)); + break; + + case CURLOPT_POSTQUOTE: + /* + * List of RAW FTP commands to use after a transfer + */ + data->set.postquote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_PREQUOTE: + /* + * List of RAW FTP commands to use prior to RETR (Wesley Laxton) + */ + data->set.prequote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_QUOTE: + /* + * List of RAW FTP commands to use before a transfer + */ + data->set.quote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_RESOLVE: + /* + * List of NAME:[address] names to populate the DNS cache with + * Prefix the NAME with dash (-) to _remove_ the name from the cache. + * + * Names added with this API will remain in the cache until explicitly + * removed or the handle is cleaned up. + * + * This API can remove any name from the DNS cache, but only entries + * that aren't actually in use right now will be pruned immediately. + */ + data->set.resolve = va_arg(param, struct curl_slist *); + data->change.resolve = data->set.resolve; + break; + case CURLOPT_PROGRESSFUNCTION: + /* + * Progress callback function + */ + data->set.fprogress = va_arg(param, curl_progress_callback); + if(data->set.fprogress) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + break; + + case CURLOPT_XFERINFOFUNCTION: + /* + * Transfer info callback function + */ + data->set.fxferinfo = va_arg(param, curl_xferinfo_callback); + if(data->set.fxferinfo) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + + break; + + case CURLOPT_PROGRESSDATA: + /* + * Custom client data to pass to the progress callback + */ + data->set.progress_client = va_arg(param, void *); + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXYUSERPWD: + /* + * user:password needed to use the proxy + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_PROXYUSERNAME], + &data->set.str[STRING_PROXYPASSWORD]); + break; + case CURLOPT_PROXYUSERNAME: + /* + * authentication user name to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME], + va_arg(param, char *)); + break; + case CURLOPT_PROXYPASSWORD: + /* + * authentication password to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD], + va_arg(param, char *)); + break; + case CURLOPT_NOPROXY: + /* + * proxy exception list + */ + result = Curl_setstropt(&data->set.str[STRING_NOPROXY], + va_arg(param, char *)); + break; +#endif + + case CURLOPT_RANGE: + /* + * What range of the file you want to transfer + */ + result = Curl_setstropt(&data->set.str[STRING_SET_RANGE], + va_arg(param, char *)); + break; + case CURLOPT_RESUME_FROM: + /* + * Resume transfer at the given file position + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.set_resume_from = arg; + break; + case CURLOPT_RESUME_FROM_LARGE: + /* + * Resume transfer at the given file position + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.set_resume_from = bigsize; + break; + case CURLOPT_DEBUGFUNCTION: + /* + * stderr write callback. + */ + data->set.fdebug = va_arg(param, curl_debug_callback); + /* + * if the callback provided is NULL, it'll use the default callback + */ + break; + case CURLOPT_DEBUGDATA: + /* + * Set to a void * that should receive all error writes. This + * defaults to CURLOPT_STDERR for normal operations. + */ + data->set.debugdata = va_arg(param, void *); + break; + case CURLOPT_STDERR: + /* + * Set to a FILE * that should receive all error writes. This + * defaults to stderr for normal operations. + */ + data->set.err = va_arg(param, FILE *); + if(!data->set.err) + data->set.err = stderr; + break; + case CURLOPT_HEADERFUNCTION: + /* + * Set header write callback + */ + data->set.fwrite_header = va_arg(param, curl_write_callback); + break; + case CURLOPT_WRITEFUNCTION: + /* + * Set data write callback + */ + data->set.fwrite_func = va_arg(param, curl_write_callback); + if(!data->set.fwrite_func) { + data->set.is_fwrite_set = 0; + /* When set to NULL, reset to our internal default function */ + data->set.fwrite_func = (curl_write_callback)fwrite; + } + else + data->set.is_fwrite_set = 1; + break; + case CURLOPT_READFUNCTION: + /* + * Read data callback + */ + data->set.fread_func_set = va_arg(param, curl_read_callback); + if(!data->set.fread_func_set) { + data->set.is_fread_set = 0; + /* When set to NULL, reset to our internal default function */ + data->set.fread_func_set = (curl_read_callback)fread; + } + else + data->set.is_fread_set = 1; + break; + case CURLOPT_SEEKFUNCTION: + /* + * Seek callback. Might be NULL. + */ + data->set.seek_func = va_arg(param, curl_seek_callback); + break; + case CURLOPT_SEEKDATA: + /* + * Seek control callback. Might be NULL. + */ + data->set.seek_client = va_arg(param, void *); + break; + case CURLOPT_CONV_FROM_NETWORK_FUNCTION: + /* + * "Convert from network encoding" callback + */ + data->set.convfromnetwork = va_arg(param, curl_conv_callback); + break; + case CURLOPT_CONV_TO_NETWORK_FUNCTION: + /* + * "Convert to network encoding" callback + */ + data->set.convtonetwork = va_arg(param, curl_conv_callback); + break; + case CURLOPT_CONV_FROM_UTF8_FUNCTION: + /* + * "Convert from UTF-8 encoding" callback + */ + data->set.convfromutf8 = va_arg(param, curl_conv_callback); + break; + case CURLOPT_IOCTLFUNCTION: + /* + * I/O control callback. Might be NULL. + */ + data->set.ioctl_func = va_arg(param, curl_ioctl_callback); + break; + case CURLOPT_IOCTLDATA: + /* + * I/O control data pointer. Might be NULL. + */ + data->set.ioctl_client = va_arg(param, void *); + break; + case CURLOPT_SSLCERT: + /* + * String that holds file name of the SSL certificate to use + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSLCERT: + /* + * String that holds file name of the SSL certificate to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SSLKEY: + /* + * String that holds file name of the SSL key to use + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSLKEY: + /* + * String that holds file name of the SSL key to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_KEYPASSWD: + /* + * String that holds the SSL or SSH private key password. + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_KEYPASSWD: + /* + * String that holds the SSL private key password for proxy. + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_SSLENGINE: + /* + * String that holds the SSL crypto engine. + */ + argptr = va_arg(param, char *); + if(argptr && argptr[0]) { + result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr); + if(!result) { + result = Curl_ssl_set_engine(data, argptr); + } + } + break; + + case CURLOPT_SSLENGINE_DEFAULT: + /* + * flag to set engine as default. + */ + Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL); + result = Curl_ssl_set_engine_default(data); + break; + case CURLOPT_CRLF: + /* + * Kludgy option to enable CRLF conversions. Subject for removal. + */ + data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_HAPROXYPROTOCOL: + /* + * Set to send the HAProxy Proxy Protocol header + */ + data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#endif + case CURLOPT_INTERFACE: + /* + * Set what interface or address/hostname to bind the socket to when + * performing an operation and thus what from-IP your connection will use. + */ + result = Curl_setstropt(&data->set.str[STRING_DEVICE], + va_arg(param, char *)); + break; + case CURLOPT_LOCALPORT: + /* + * Set what local port to bind the socket to when performing an operation. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.localport = curlx_sltous(arg); + break; + case CURLOPT_LOCALPORTRANGE: + /* + * Set number of local ports to try, starting with CURLOPT_LOCALPORT. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.localportrange = curlx_sltosi(arg); + break; + case CURLOPT_GSSAPI_DELEGATION: + /* + * GSS-API credential delegation bitmask + */ + arg = va_arg(param, long); + if(arg < CURLGSSAPI_DELEGATION_NONE) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.gssapi_delegation = arg; + break; + case CURLOPT_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying. + */ + data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ? + TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifypeer = + data->set.ssl.primary.verifypeer; + } + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying for proxy. + */ + data->set.proxy_ssl.primary.verifypeer = + (0 != va_arg(param, long))?TRUE:FALSE; + + /* Update the current connection proxy_ssl_config. */ + if(data->conn) { + data->conn->proxy_ssl_config.verifypeer = + data->set.proxy_ssl.primary.verifypeer; + } + break; +#endif + case CURLOPT_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifyhost = + data->set.ssl.primary.verifyhost; + } + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate for proxy + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE; + + /* Update the current connection proxy_ssl_config. */ + if(data->conn) { + data->conn->proxy_ssl_config.verifyhost = + data->set.proxy_ssl.primary.verifyhost; + } + break; +#endif + case CURLOPT_SSL_VERIFYSTATUS: + /* + * Enable certificate status verifying. + */ + if(!Curl_ssl_cert_status_request()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ? + TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifystatus = + data->set.ssl.primary.verifystatus; + } + break; + case CURLOPT_SSL_CTX_FUNCTION: + /* + * Set a SSL_CTX callback + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_SSL_CTX) + data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_SSL_CTX_DATA: + /* + * Set a SSL_CTX callback parameter pointer + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_SSL_CTX) + data->set.ssl.fsslctxp = va_arg(param, void *); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_SSL_FALSESTART: + /* + * Enable TLS false start. + */ + if(!Curl_ssl_false_start()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_CERTINFO: +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CERTINFO) + data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE; + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_PINNEDPUBLICKEY: + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY) + result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_PINNEDPUBLICKEY: + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY) + result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; +#endif + case CURLOPT_CAINFO: + /* + * Set CA info for SSL connection. Specify file name of the CA certificate + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_CAINFO: + /* + * Set CA info SSL connection for proxy. Specify file name of the + * CA certificate + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_CAPATH: + /* + * Set CA path info for SSL connection. Specify directory name of the CA + * certificates which have been prepared using openssl c_rehash utility. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CA_PATH) + /* This does not work on windows. */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_CAPATH: + /* + * Set CA path info for SSL connection proxy. Specify directory name of the + * CA certificates which have been prepared using openssl c_rehash utility. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CA_PATH) + /* This does not work on windows. */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; +#endif + case CURLOPT_CRLFILE: + /* + * Set CRL file info for SSL connection. Specify file name of the CRL + * to check certificates revocation + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_CRLFILE: + /* + * Set CRL file info for SSL connection for proxy. Specify file name of the + * CRL to check certificates revocation + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY], + va_arg(param, char *)); + break; +#endif + case CURLOPT_ISSUERCERT: + /* + * Set Issuer certificate file + * to check certificates issuer + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_TELNET + case CURLOPT_TELNETOPTIONS: + /* + * Set a linked list of telnet options + */ + data->set.telnet_options = va_arg(param, struct curl_slist *); + break; +#endif + case CURLOPT_BUFFERSIZE: + /* + * The application kindly asks for a differently sized receive buffer. + * If it seems reasonable, we'll use it. + */ + arg = va_arg(param, long); + + if(arg > READBUFFER_MAX) + arg = READBUFFER_MAX; + else if(arg < 1) + arg = READBUFFER_SIZE; + else if(arg < READBUFFER_MIN) + arg = READBUFFER_MIN; + + /* Resize if new size */ + if(arg != data->set.buffer_size) { + char *newbuff = realloc(data->state.buffer, arg + 1); + if(!newbuff) { + DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + else + data->state.buffer = newbuff; + } + data->set.buffer_size = arg; + + break; + + case CURLOPT_UPLOAD_BUFFERSIZE: + /* + * The application kindly asks for a differently sized upload buffer. + * Cap it to sensible. + */ + arg = va_arg(param, long); + + if(arg > UPLOADBUFFER_MAX) + arg = UPLOADBUFFER_MAX; + else if(arg < UPLOADBUFFER_MIN) + arg = UPLOADBUFFER_MIN; + + data->set.upload_buffer_size = arg; + Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */ + break; + + case CURLOPT_NOSIGNAL: + /* + * The application asks not to set any signal() or alarm() handlers, + * even when using a timeout. + */ + data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_SHARE: + { + struct Curl_share *set; + set = va_arg(param, struct Curl_share *); + + /* disconnect from old share, if any */ + if(data->share) { + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + + if(data->dns.hostcachetype == HCACHE_SHARED) { + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(data->share->cookies == data->cookies) + data->cookies = NULL; +#endif + + if(data->share->sslsession == data->state.session) + data->state.session = NULL; + +#ifdef USE_LIBPSL + if(data->psl == &data->share->psl) + data->psl = data->multi? &data->multi->psl: NULL; +#endif + + data->share->dirty--; + + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + data->share = NULL; + } + + /* use new share if it set */ + data->share = set; + if(data->share) { + + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + + data->share->dirty++; + + if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) { + /* use shared host cache */ + data->dns.hostcache = &data->share->hostcache; + data->dns.hostcachetype = HCACHE_SHARED; + } +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(data->share->cookies) { + /* use shared cookie list, first free own one if any */ + Curl_cookie_cleanup(data->cookies); + /* enable cookies since we now use a share that uses cookies! */ + data->cookies = data->share->cookies; + } +#endif /* CURL_DISABLE_HTTP */ + if(data->share->sslsession) { + data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions; + data->state.session = data->share->sslsession; + } +#ifdef USE_LIBPSL + if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL)) + data->psl = &data->share->psl; +#endif + + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + } + /* check for host cache not needed, + * it will be done by curl_easy_perform */ + } + break; + + case CURLOPT_PRIVATE: + /* + * Set private data pointer. + */ + data->set.private_data = va_arg(param, void *); + break; + + case CURLOPT_MAXFILESIZE: + /* + * Set the maximum size of a file to download. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_filesize = arg; + break; + +#ifdef USE_SSL + case CURLOPT_USE_SSL: + /* + * Make transfers attempt to use SSL/TLS. + */ + arg = va_arg(param, long); + if((arg < CURLUSESSL_NONE) || (arg > CURLUSESSL_ALL)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_ssl = (curl_usessl)arg; + break; + + case CURLOPT_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.proxy_ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + break; +#endif + +#endif + case CURLOPT_IPRESOLVE: + arg = va_arg(param, long); + if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ipver = arg; + break; + + case CURLOPT_MAXFILESIZE_LARGE: + /* + * Set the maximum size of a file to download. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_filesize = bigsize; + break; + + case CURLOPT_TCP_NODELAY: + /* + * Enable or disable TCP_NODELAY, which will disable/enable the Nagle + * algorithm + */ + data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_IGNORE_CONTENT_LENGTH: + data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_CONNECT_ONLY: + /* + * No data transfer, set up connection and let application use the socket + */ + data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_SOCKOPTFUNCTION: + /* + * socket callback function: called after socket() but before connect() + */ + data->set.fsockopt = va_arg(param, curl_sockopt_callback); + break; + + case CURLOPT_SOCKOPTDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.sockopt_client = va_arg(param, void *); + break; + + case CURLOPT_OPENSOCKETFUNCTION: + /* + * open/create socket callback function: called instead of socket(), + * before connect() + */ + data->set.fopensocket = va_arg(param, curl_opensocket_callback); + break; + + case CURLOPT_OPENSOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.opensocket_client = va_arg(param, void *); + break; + + case CURLOPT_CLOSESOCKETFUNCTION: + /* + * close socket callback function: called instead of close() + * when shutting down a connection + */ + data->set.fclosesocket = va_arg(param, curl_closesocket_callback); + break; + + case CURLOPT_RESOLVER_START_FUNCTION: + /* + * resolver start callback function: called before a new resolver request + * is started + */ + data->set.resolver_start = va_arg(param, curl_resolver_start_callback); + break; + + case CURLOPT_RESOLVER_START_DATA: + /* + * resolver start callback data pointer. Might be NULL. + */ + data->set.resolver_start_client = va_arg(param, void *); + break; + + case CURLOPT_CLOSESOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.closesocket_client = va_arg(param, void *); + break; + + case CURLOPT_SSL_SESSIONID_CACHE: + data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ? + TRUE : FALSE; + data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid; + break; + +#ifdef USE_SSH + /* we only include SSH options if explicitly built to support SSH */ + case CURLOPT_SSH_AUTH_TYPES: + data->set.ssh_auth_types = va_arg(param, long); + break; + + case CURLOPT_SSH_PUBLIC_KEYFILE: + /* + * Use this file instead of the $HOME/.ssh/id_dsa.pub file + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_PRIVATE_KEYFILE: + /* + * Use this file instead of the $HOME/.ssh/id_dsa file + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], + va_arg(param, char *)); + break; + case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: + /* + * Option to allow for the MD5 of the host public key to be checked + * for validation purposes. + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_KNOWNHOSTS: + /* + * Store the file name to read known hosts from. + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_KEYFUNCTION: + /* setting to NULL is fine since the ssh.c functions themselves will + then rever to use the internal default */ + data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback); + break; + + case CURLOPT_SSH_KEYDATA: + /* + * Custom client data to pass to the SSH keyfunc callback + */ + data->set.ssh_keyfunc_userp = va_arg(param, void *); + break; + + case CURLOPT_SSH_COMPRESSION: + data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE; + break; +#endif /* USE_SSH */ + + case CURLOPT_HTTP_TRANSFER_DECODING: + /* + * disable libcurl transfer encoding is used + */ + data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_HTTP_CONTENT_DECODING: + /* + * raw data passed to the application when content encoding is used + */ + data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; + break; + +#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) + case CURLOPT_NEW_FILE_PERMS: + /* + * Uses these permissions instead of 0644 + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 0777)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.new_file_perms = arg; + break; + + case CURLOPT_NEW_DIRECTORY_PERMS: + /* + * Uses these permissions instead of 0755 + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 0777)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.new_directory_perms = arg; + break; +#endif + + case CURLOPT_ADDRESS_SCOPE: + /* + * Use this scope id when using IPv6 + * We always get longs when passed plain numericals so we should check + * that the value fits into an unsigned 32 bit integer. + */ + uarg = va_arg(param, unsigned long); +#if SIZEOF_LONG > 4 + if(uarg > UINT_MAX) + return CURLE_BAD_FUNCTION_ARGUMENT; +#endif + data->set.scope_id = (unsigned int)uarg; + break; + + case CURLOPT_PROTOCOLS: + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + data->set.allowed_protocols = va_arg(param, long); + break; + + case CURLOPT_REDIR_PROTOCOLS: + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + data->set.redir_protocols = va_arg(param, long); + break; + + case CURLOPT_DEFAULT_PROTOCOL: + /* Set the protocol to use when the URL doesn't include any protocol */ + result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL], + va_arg(param, char *)); + break; +#ifndef CURL_DISABLE_SMTP + case CURLOPT_MAIL_FROM: + /* Set the SMTP mail originator */ + result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_AUTH: + /* Set the SMTP auth originator */ + result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_RCPT: + /* Set the list of mail recipients */ + data->set.mail_rcpt = va_arg(param, struct curl_slist *); + break; +#endif + + case CURLOPT_SASL_IR: + /* Enable/disable SASL initial response */ + data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#ifndef CURL_DISABLE_RTSP + case CURLOPT_RTSP_REQUEST: + { + /* + * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...) + * Would this be better if the RTSPREQ_* were just moved into here? + */ + long curl_rtspreq = va_arg(param, long); + Curl_RtspReq rtspreq = RTSPREQ_NONE; + switch(curl_rtspreq) { + case CURL_RTSPREQ_OPTIONS: + rtspreq = RTSPREQ_OPTIONS; + break; + + case CURL_RTSPREQ_DESCRIBE: + rtspreq = RTSPREQ_DESCRIBE; + break; + + case CURL_RTSPREQ_ANNOUNCE: + rtspreq = RTSPREQ_ANNOUNCE; + break; + + case CURL_RTSPREQ_SETUP: + rtspreq = RTSPREQ_SETUP; + break; + + case CURL_RTSPREQ_PLAY: + rtspreq = RTSPREQ_PLAY; + break; + + case CURL_RTSPREQ_PAUSE: + rtspreq = RTSPREQ_PAUSE; + break; + + case CURL_RTSPREQ_TEARDOWN: + rtspreq = RTSPREQ_TEARDOWN; + break; + + case CURL_RTSPREQ_GET_PARAMETER: + rtspreq = RTSPREQ_GET_PARAMETER; + break; + + case CURL_RTSPREQ_SET_PARAMETER: + rtspreq = RTSPREQ_SET_PARAMETER; + break; + + case CURL_RTSPREQ_RECORD: + rtspreq = RTSPREQ_RECORD; + break; + + case CURL_RTSPREQ_RECEIVE: + rtspreq = RTSPREQ_RECEIVE; + break; + default: + rtspreq = RTSPREQ_NONE; + } + + data->set.rtspreq = rtspreq; + break; + } + + + case CURLOPT_RTSP_SESSION_ID: + /* + * Set the RTSP Session ID manually. Useful if the application is + * resuming a previously established RTSP session + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_STREAM_URI: + /* + * Set the Stream URI for the RTSP request. Unless the request is + * for generic server options, the application will need to set this. + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_TRANSPORT: + /* + * The content of the Transport: header for the RTSP request + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_CLIENT_CSEQ: + /* + * Set the CSEQ number to issue for the next RTSP request. Useful if the + * application is resuming a previously broken connection. The CSEQ + * will increment from this new number henceforth. + */ + data->state.rtsp_next_client_CSeq = va_arg(param, long); + break; + + case CURLOPT_RTSP_SERVER_CSEQ: + /* Same as the above, but for server-initiated requests */ + data->state.rtsp_next_client_CSeq = va_arg(param, long); + break; + + case CURLOPT_INTERLEAVEDATA: + data->set.rtp_out = va_arg(param, void *); + break; + case CURLOPT_INTERLEAVEFUNCTION: + /* Set the user defined RTP write function */ + data->set.fwrite_rtp = va_arg(param, curl_write_callback); + break; +#endif +#ifndef CURL_DISABLE_FTP + case CURLOPT_WILDCARDMATCH: + data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_CHUNK_BGN_FUNCTION: + data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback); + break; + case CURLOPT_CHUNK_END_FUNCTION: + data->set.chunk_end = va_arg(param, curl_chunk_end_callback); + break; + case CURLOPT_FNMATCH_FUNCTION: + data->set.fnmatch = va_arg(param, curl_fnmatch_callback); + break; + case CURLOPT_CHUNK_DATA: + data->wildcard.customptr = va_arg(param, void *); + break; + case CURLOPT_FNMATCH_DATA: + data->set.fnmatch_data = va_arg(param, void *); + break; +#endif +#ifdef USE_TLS_SRP + case CURLOPT_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_PROXY_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.ssl.authtype = CURL_TLSAUTH_NONE; + break; + case CURLOPT_PROXY_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE; + break; +#endif +#ifdef USE_ARES + case CURLOPT_DNS_SERVERS: + result = Curl_set_dns_servers(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_INTERFACE: + result = Curl_set_dns_interface(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_LOCAL_IP4: + result = Curl_set_dns_local_ip4(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_LOCAL_IP6: + result = Curl_set_dns_local_ip6(data, va_arg(param, char *)); + break; +#endif + case CURLOPT_TCP_KEEPALIVE: + data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_TCP_KEEPIDLE: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tcp_keepidle = arg; + break; + case CURLOPT_TCP_KEEPINTVL: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tcp_keepintvl = arg; + break; + case CURLOPT_TCP_FASTOPEN: +#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \ + defined(TCP_FASTOPEN_CONNECT) + data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE; +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; +#ifdef USE_NGHTTP2 + case CURLOPT_SSL_ENABLE_NPN: + data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_SSL_ENABLE_ALPN: + data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#endif +#ifdef USE_UNIX_SOCKETS + case CURLOPT_UNIX_SOCKET_PATH: + data->set.abstract_unix_socket = FALSE; + result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], + va_arg(param, char *)); + break; + case CURLOPT_ABSTRACT_UNIX_SOCKET: + data->set.abstract_unix_socket = TRUE; + result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], + va_arg(param, char *)); + break; +#endif + + case CURLOPT_PATH_AS_IS: + data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_PIPEWAIT: + data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_STREAM_WEIGHT: +#ifndef USE_NGHTTP2 + return CURLE_NOT_BUILT_IN; +#else + arg = va_arg(param, long); + if((arg >= 1) && (arg <= 256)) + data->set.stream_weight = (int)arg; + break; +#endif + case CURLOPT_STREAM_DEPENDS: + case CURLOPT_STREAM_DEPENDS_E: + { +#ifndef USE_NGHTTP2 + return CURLE_NOT_BUILT_IN; +#else + struct Curl_easy *dep = va_arg(param, struct Curl_easy *); + if(!dep || GOOD_EASY_HANDLE(dep)) { + if(data->set.stream_depends_on) { + Curl_http2_remove_child(data->set.stream_depends_on, data); + } + Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E)); + } + break; +#endif + } + case CURLOPT_CONNECT_TO: + data->set.connect_to = va_arg(param, struct curl_slist *); + break; + case CURLOPT_SUPPRESS_CONNECT_HEADERS: + data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.happy_eyeballs_timeout = arg; + break; +#ifndef CURL_DISABLE_SHUFFLE_DNS + case CURLOPT_DNS_SHUFFLE_ADDRESSES: + data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE; + break; +#endif + case CURLOPT_DISALLOW_USERNAME_IN_URL: + data->set.disallow_username_in_url = + (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#ifndef CURL_DISABLE_DOH + case CURLOPT_DOH_URL: + result = Curl_setstropt(&data->set.str[STRING_DOH], + va_arg(param, char *)); + data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE; + break; +#endif + case CURLOPT_UPKEEP_INTERVAL_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.upkeep_interval_ms = arg; + break; + case CURLOPT_MAXAGE_CONN: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxage_conn = arg; + break; + case CURLOPT_TRAILERFUNCTION: +#ifndef CURL_DISABLE_HTTP + data->set.trailer_callback = va_arg(param, curl_trailer_callback); +#endif + break; + case CURLOPT_TRAILERDATA: +#ifndef CURL_DISABLE_HTTP + data->set.trailer_data = va_arg(param, void *); +#endif + break; +#ifdef USE_ALTSVC + case CURLOPT_ALTSVC: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + argptr = va_arg(param, char *); + result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr); + if(result) + return result; + (void)Curl_altsvc_load(data->asi, argptr); + break; + case CURLOPT_ALTSVC_CTRL: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + arg = va_arg(param, long); + result = Curl_altsvc_ctrl(data->asi, arg); + if(result) + return result; + break; +#endif + default: + /* unknown tag and its companion, just ignore: */ + result = CURLE_UNKNOWN_OPTION; + break; + } + + return result; +} + +/* + * curl_easy_setopt() is the external interface for setting options on an + * easy handle. + * + * NOTE: This is one of few API functions that are allowed to be called from + * within a callback. + */ + +#undef curl_easy_setopt +CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...) +{ + va_list arg; + CURLcode result; + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + va_start(arg, tag); + + result = Curl_vsetopt(data, tag, arg); + + va_end(arg); + return result; +} diff --git a/libcurl/lib/setopt.h b/libcurl/lib/setopt.h new file mode 100644 index 0000000..5e347dd --- /dev/null +++ b/libcurl/lib/setopt.h @@ -0,0 +1,28 @@ +#ifndef HEADER_CURL_SETOPT_H +#define HEADER_CURL_SETOPT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURLcode Curl_setstropt(char **charp, const char *s); +CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list arg); + +#endif /* HEADER_CURL_SETOPT_H */ diff --git a/libcurl/lib/setup-os400.h b/libcurl/lib/setup-os400.h new file mode 100644 index 0000000..a3c2a7b --- /dev/null +++ b/libcurl/lib/setup-os400.h @@ -0,0 +1,223 @@ +#ifndef HEADER_CURL_SETUP_OS400_H +#define HEADER_CURL_SETUP_OS400_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* OS/400 netdb.h does not define NI_MAXHOST. */ +#define NI_MAXHOST 1025 + +/* OS/400 netdb.h does not define NI_MAXSERV. */ +#define NI_MAXSERV 32 + +/* No OS/400 header file defines u_int32_t. */ +typedef unsigned long u_int32_t; + + +/* System API wrapper prototypes & definitions to support ASCII parameters. */ + +#include +#include +#include +#include +#include + +extern int Curl_getaddrinfo_a(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); +#define getaddrinfo Curl_getaddrinfo_a + + +extern int Curl_getnameinfo_a(const struct sockaddr *sa, + curl_socklen_t salen, + char *nodename, curl_socklen_t nodenamelen, + char *servname, curl_socklen_t servnamelen, + int flags); +#define getnameinfo Curl_getnameinfo_a + + +/* GSKit wrappers. */ + +extern int Curl_gsk_environment_open(gsk_handle * my_env_handle); +#define gsk_environment_open Curl_gsk_environment_open + +extern int Curl_gsk_secure_soc_open(gsk_handle my_env_handle, + gsk_handle * my_session_handle); +#define gsk_secure_soc_open Curl_gsk_secure_soc_open + +extern int Curl_gsk_environment_close(gsk_handle * my_env_handle); +#define gsk_environment_close Curl_gsk_environment_close + +extern int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle); +#define gsk_secure_soc_close Curl_gsk_secure_soc_close + +extern int Curl_gsk_environment_init(gsk_handle my_env_handle); +#define gsk_environment_init Curl_gsk_environment_init + +extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle); +#define gsk_secure_soc_init Curl_gsk_secure_soc_init + +extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, + GSK_BUF_ID bufID, + const char *buffer, + int bufSize); +#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a + +extern int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, + GSK_ENUM_ID enumID, + GSK_ENUM_VALUE enumValue); +#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum + +extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, + int numValue); +#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value + +extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle, + GSK_CALLBACK_ID callBackID, + void *callBackAreaPtr); +#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback + +extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, + GSK_BUF_ID bufID, + const char **buffer, + int *bufSize); +#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a + +extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, + GSK_ENUM_ID enumID, + GSK_ENUM_VALUE *enumValue); +#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum + +extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, + int *numValue); +#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value + +extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle, + GSK_CERT_ID certID, + const gsk_cert_data_elem **certDataElem, + int *certDataElementCount); +#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info + +extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, + GSK_MISC_ID miscID); +#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc + +extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle, + char *readBuffer, + int readBufSize, int *amtRead); +#define gsk_secure_soc_read Curl_gsk_secure_soc_read + +extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle, + char *writeBuffer, + int writeBufSize, int *amtWritten); +#define gsk_secure_soc_write Curl_gsk_secure_soc_write + +extern const char * Curl_gsk_strerror_a(int gsk_return_value); +#define gsk_strerror Curl_gsk_strerror_a + +extern int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle, + int IOCompletionPort, + Qso_OverlappedIO_t * communicationsArea); +#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit + + +/* GSSAPI wrappers. */ + +extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status, + gss_buffer_t in_name, + gss_OID in_name_type, + gss_name_t * out_name); +#define gss_import_name Curl_gss_import_name_a + + +extern OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status, + OM_uint32 status_value, + int status_type, gss_OID mech_type, + gss_msg_ctx_t * message_context, + gss_buffer_t status_string); +#define gss_display_status Curl_gss_display_status_a + + +extern OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status, + gss_cred_id_t cred_handle, + gss_ctx_id_t * context_handle, + gss_name_t target_name, + gss_OID mech_type, + gss_flags_t req_flags, + OM_uint32 time_req, + gss_channel_bindings_t + input_chan_bindings, + gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + gss_flags_t * ret_flags, + OM_uint32 * time_rec); +#define gss_init_sec_context Curl_gss_init_sec_context_a + + +extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token); +#define gss_delete_sec_context Curl_gss_delete_sec_context_a + + +/* LDAP wrappers. */ + +#define BerValue struct berval + +#define ldap_url_parse ldap_url_parse_utf8 +#define ldap_init Curl_ldap_init_a +#define ldap_simple_bind_s Curl_ldap_simple_bind_s_a +#define ldap_search_s Curl_ldap_search_s_a +#define ldap_get_values_len Curl_ldap_get_values_len_a +#define ldap_err2string Curl_ldap_err2string_a +#define ldap_get_dn Curl_ldap_get_dn_a +#define ldap_first_attribute Curl_ldap_first_attribute_a +#define ldap_next_attribute Curl_ldap_next_attribute_a + +/* Some socket functions must be wrapped to process textual addresses + like AF_UNIX. */ + +extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen); +extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen); +extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, + struct sockaddr * dstaddr, int addrlen); +extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, + struct sockaddr *fromaddr, int *addrlen); + +#define connect Curl_os400_connect +#define bind Curl_os400_bind +#define sendto Curl_os400_sendto +#define recvfrom Curl_os400_recvfrom + +#ifdef HAVE_LIBZ +#define zlibVersion Curl_os400_zlibVersion +#define inflateInit_ Curl_os400_inflateInit_ +#define inflateInit2_ Curl_os400_inflateInit2_ +#define inflate Curl_os400_inflate +#define inflateEnd Curl_os400_inflateEnd +#endif + +#endif /* HEADER_CURL_SETUP_OS400_H */ diff --git a/libcurl/lib/setup-vms.h b/libcurl/lib/setup-vms.h new file mode 100644 index 0000000..6c454ae --- /dev/null +++ b/libcurl/lib/setup-vms.h @@ -0,0 +1,443 @@ +#ifndef HEADER_CURL_SETUP_VMS_H +#define HEADER_CURL_SETUP_VMS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* */ +/* JEM, 12/30/12, VMS now generates config.h, so only define wrappers for */ +/* getenv(), getpwuid() and provide is_vms_shell() */ +/* Also need upper case symbols for system services, and */ +/* OpenSSL, and some Kerberos image */ + +#ifdef __DECC +#pragma message save +#pragma message disable dollarid +#endif + +/* Hide the stuff we are overriding */ +#define getenv decc_getenv +#ifdef __DECC +# if __INITIAL_POINTER_SIZE != 64 +# define getpwuid decc_getpwuid +# endif +#endif +#include +char *decc$getenv(const char *__name); +#include + +#include +#include + +#undef getenv +#undef getpwuid +#define getenv vms_getenv +#define getpwuid vms_getpwuid + +/* VAX needs these in upper case when compiling exact case */ +#define sys$assign SYS$ASSIGN +#define sys$dassgn SYS$DASSGN +#define sys$qiow SYS$QIOW + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __save +# endif +#endif + +#if __USE_LONG_GID_T +# define decc_getpwuid DECC$__LONG_GID_GETPWUID +#else +# if __INITIAL_POINTER_SIZE +# define decc_getpwuid decc$__32_getpwuid +# else +# define decc_getpwuid decc$getpwuid +# endif +#endif + + struct passwd * decc_getpwuid(uid_t uid); + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE == 32 +/* Translate the path, but only if the path is a VMS file specification */ +/* The translation is usually only needed for older versions of VMS */ +static char *vms_translate_path(const char *path) +{ + char *unix_path; + char *test_str; + + /* See if the result is in VMS format, if not, we are done */ + /* Assume that this is a PATH, not just some data */ + test_str = strpbrk(path, ":[<^"); + if(test_str == NULL) { + return (char *)path; + } + + unix_path = decc$translate_vms(path); + + if((int)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return (char *)path; + } +} +# else + /* VMS translate path is actually not needed on the current 64 bit */ + /* VMS platforms, so instead of figuring out the pointer settings */ + /* Change it to a noop */ +# define vms_translate_path(__path) __path +# endif +#endif + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __restore +# endif +#endif + +static char *vms_getenv(const char *envvar) +{ + char *result; + char *vms_path; + + /* first use the DECC getenv() function */ + result = decc$getenv(envvar); + if(result == NULL) { + return result; + } + + vms_path = result; + result = vms_translate_path(vms_path); + + /* note that if you backport this to use VAX C RTL, that the VAX C RTL */ + /* may do a malloc(2048) for each call to getenv(), so you will need */ + /* to add a free(vms_path) */ + /* Do not do a free() for DEC C RTL builds, which should be used for */ + /* VMS 5.5-2 and later, even if using GCC */ + + return result; +} + + +static struct passwd vms_passwd_cache; + +static struct passwd * vms_getpwuid(uid_t uid) +{ + struct passwd * my_passwd; + +/* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */ +#ifdef __DECC +# if __INITIAL_POINTER_SIZE + __char_ptr32 unix_path; +# else + char *unix_path; +# endif +#else + char *unix_path; +#endif + + my_passwd = decc_getpwuid(uid); + if(my_passwd == NULL) { + return my_passwd; + } + + unix_path = vms_translate_path(my_passwd->pw_dir); + + if((long)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return my_passwd; + } + + /* If no changes needed just return it */ + if(unix_path == my_passwd->pw_dir) { + return my_passwd; + } + + /* Need to copy the structure returned */ + /* Since curl is only using pw_dir, no need to fix up */ + /* the pw_shell when running under Bash */ + vms_passwd_cache.pw_name = my_passwd->pw_name; + vms_passwd_cache.pw_uid = my_passwd->pw_uid; + vms_passwd_cache.pw_gid = my_passwd->pw_uid; + vms_passwd_cache.pw_dir = unix_path; + vms_passwd_cache.pw_shell = my_passwd->pw_shell; + + return &vms_passwd_cache; +} + +#ifdef __DECC +#pragma message restore +#endif + +/* Bug - VMS OpenSSL and Kerberos universal symbols are in uppercase only */ +/* VMS libraries should have universal symbols in exact and uppercase */ + +#define ASN1_INTEGER_get ASN1_INTEGER_GET +#define ASN1_STRING_data ASN1_STRING_DATA +#define ASN1_STRING_length ASN1_STRING_LENGTH +#define ASN1_STRING_print ASN1_STRING_PRINT +#define ASN1_STRING_to_UTF8 ASN1_STRING_TO_UTF8 +#define ASN1_STRING_type ASN1_STRING_TYPE +#define BIO_ctrl BIO_CTRL +#define BIO_free BIO_FREE +#define BIO_new BIO_NEW +#define BIO_s_mem BIO_S_MEM +#define BN_bn2bin BN_BN2BIN +#define BN_num_bits BN_NUM_BITS +#define CRYPTO_cleanup_all_ex_data CRYPTO_CLEANUP_ALL_EX_DATA +#define CRYPTO_free CRYPTO_FREE +#define CRYPTO_malloc CRYPTO_MALLOC +#define CONF_modules_load_file CONF_MODULES_LOAD_FILE +#ifdef __VAX +# ifdef VMS_OLD_SSL + /* Ancient OpenSSL on VAX/VMS missing this constant */ +# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +# undef CONF_modules_load_file + static int CONF_modules_load_file(const char *filename, + const char *appname, + unsigned long flags) { + return 1; + } +# endif +#endif +#define DES_ecb_encrypt DES_ECB_ENCRYPT +#define DES_set_key DES_SET_KEY +#define DES_set_odd_parity DES_SET_ODD_PARITY +#define ENGINE_ctrl ENGINE_CTRL +#define ENGINE_ctrl_cmd ENGINE_CTRL_CMD +#define ENGINE_finish ENGINE_FINISH +#define ENGINE_free ENGINE_FREE +#define ENGINE_get_first ENGINE_GET_FIRST +#define ENGINE_get_id ENGINE_GET_ID +#define ENGINE_get_next ENGINE_GET_NEXT +#define ENGINE_init ENGINE_INIT +#define ENGINE_load_builtin_engines ENGINE_LOAD_BUILTIN_ENGINES +#define ENGINE_load_private_key ENGINE_LOAD_PRIVATE_KEY +#define ENGINE_set_default ENGINE_SET_DEFAULT +#define ERR_clear_error ERR_CLEAR_ERROR +#define ERR_error_string ERR_ERROR_STRING +#define ERR_error_string_n ERR_ERROR_STRING_N +#define ERR_free_strings ERR_FREE_STRINGS +#define ERR_get_error ERR_GET_ERROR +#define ERR_peek_error ERR_PEEK_ERROR +#define ERR_remove_state ERR_REMOVE_STATE +#define EVP_PKEY_copy_parameters EVP_PKEY_COPY_PARAMETERS +#define EVP_PKEY_free EVP_PKEY_FREE +#define EVP_cleanup EVP_CLEANUP +#define GENERAL_NAMES_free GENERAL_NAMES_FREE +#define i2d_X509_PUBKEY I2D_X509_PUBKEY +#define MD4_Final MD4_FINAL +#define MD4_Init MD4_INIT +#define MD4_Update MD4_UPDATE +#define MD5_Final MD5_FINAL +#define MD5_Init MD5_INIT +#define MD5_Update MD5_UPDATE +#define OPENSSL_add_all_algo_noconf OPENSSL_ADD_ALL_ALGO_NOCONF +#ifndef __VAX +#define OPENSSL_load_builtin_modules OPENSSL_LOAD_BUILTIN_MODULES +#endif +#define PEM_read_X509 PEM_READ_X509 +#define PEM_write_bio_X509 PEM_WRITE_BIO_X509 +#define PKCS12_PBE_add PKCS12_PBE_ADD +#define PKCS12_free PKCS12_FREE +#define PKCS12_parse PKCS12_PARSE +#define RAND_add RAND_ADD +#define RAND_bytes RAND_BYTES +#define RAND_egd RAND_EGD +#define RAND_file_name RAND_FILE_NAME +#define RAND_load_file RAND_LOAD_FILE +#define RAND_status RAND_STATUS +#define SSL_CIPHER_get_name SSL_CIPHER_GET_NAME +#define SSL_CTX_add_client_CA SSL_CTX_ADD_CLIENT_CA +#define SSL_CTX_callback_ctrl SSL_CTX_CALLBACK_CTRL +#define SSL_CTX_check_private_key SSL_CTX_CHECK_PRIVATE_KEY +#define SSL_CTX_ctrl SSL_CTX_CTRL +#define SSL_CTX_free SSL_CTX_FREE +#define SSL_CTX_get_cert_store SSL_CTX_GET_CERT_STORE +#define SSL_CTX_load_verify_locations SSL_CTX_LOAD_VERIFY_LOCATIONS +#define SSL_CTX_new SSL_CTX_NEW +#define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST +#define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD +#define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB +#define SSL_CTX_set_msg_callback SSL_CTX_SET_MSG_CALLBACK +#define SSL_CTX_set_verify SSL_CTX_SET_VERIFY +#define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY +#define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE +#define SSL_CTX_use_cert_chain_file SSL_CTX_USE_CERT_CHAIN_FILE +#define SSL_CTX_use_certificate SSL_CTX_USE_CERTIFICATE +#define SSL_CTX_use_certificate_file SSL_CTX_USE_CERTIFICATE_FILE +#define SSL_SESSION_free SSL_SESSION_FREE +#define SSL_connect SSL_CONNECT +#define SSL_free SSL_FREE +#define SSL_get1_session SSL_GET1_SESSION +#define SSL_get_certificate SSL_GET_CERTIFICATE +#define SSL_get_current_cipher SSL_GET_CURRENT_CIPHER +#define SSL_get_error SSL_GET_ERROR +#define SSL_get_peer_cert_chain SSL_GET_PEER_CERT_CHAIN +#define SSL_get_peer_certificate SSL_GET_PEER_CERTIFICATE +#define SSL_get_privatekey SSL_GET_PRIVATEKEY +#define SSL_get_session SSL_GET_SESSION +#define SSL_get_shutdown SSL_GET_SHUTDOWN +#define SSL_get_verify_result SSL_GET_VERIFY_RESULT +#define SSL_library_init SSL_LIBRARY_INIT +#define SSL_load_error_strings SSL_LOAD_ERROR_STRINGS +#define SSL_new SSL_NEW +#define SSL_peek SSL_PEEK +#define SSL_pending SSL_PENDING +#define SSL_read SSL_READ +#define SSL_set_connect_state SSL_SET_CONNECT_STATE +#define SSL_set_fd SSL_SET_FD +#define SSL_set_session SSL_SET_SESSION +#define SSL_shutdown SSL_SHUTDOWN +#define SSL_version SSL_VERSION +#define SSL_write SSL_WRITE +#define SSLeay SSLEAY +#define SSLv23_client_method SSLV23_CLIENT_METHOD +#define SSLv3_client_method SSLV3_CLIENT_METHOD +#define TLSv1_client_method TLSV1_CLIENT_METHOD +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_get0_user_data UI_GET0_USER_DATA +#define UI_get_input_flags UI_GET_INPUT_FLAGS +#define UI_get_string_type UI_GET_STRING_TYPE +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_method_get_closer UI_METHOD_GET_CLOSER +#define UI_method_get_opener UI_METHOD_GET_OPENER +#define UI_method_get_reader UI_METHOD_GET_READER +#define UI_method_get_writer UI_METHOD_GET_WRITER +#define UI_method_set_closer UI_METHOD_SET_CLOSER +#define UI_method_set_opener UI_METHOD_SET_OPENER +#define UI_method_set_reader UI_METHOD_SET_READER +#define UI_method_set_writer UI_METHOD_SET_WRITER +#define UI_OpenSSL UI_OPENSSL +#define UI_set_result UI_SET_RESULT +#define X509V3_EXT_print X509V3_EXT_PRINT +#define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL +#define X509_EXTENSION_get_data X509_EXTENSION_GET_DATA +#define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT +#define X509_LOOKUP_file X509_LOOKUP_FILE +#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA +#define X509_NAME_get_entry X509_NAME_GET_ENTRY +#define X509_NAME_get_index_by_NID X509_NAME_GET_INDEX_BY_NID +#define X509_NAME_print_ex X509_NAME_PRINT_EX +#define X509_STORE_CTX_get_current_cert X509_STORE_CTX_GET_CURRENT_CERT +#define X509_STORE_add_lookup X509_STORE_ADD_LOOKUP +#define X509_STORE_set_flags X509_STORE_SET_FLAGS +#define X509_check_issued X509_CHECK_ISSUED +#define X509_free X509_FREE +#define X509_get_ext_d2i X509_GET_EXT_D2I +#define X509_get_issuer_name X509_GET_ISSUER_NAME +#define X509_get_pubkey X509_GET_PUBKEY +#define X509_get_serialNumber X509_GET_SERIALNUMBER +#define X509_get_subject_name X509_GET_SUBJECT_NAME +#define X509_load_crl_file X509_LOAD_CRL_FILE +#define X509_verify_cert_error_string X509_VERIFY_CERT_ERROR_STRING +#define d2i_PKCS12_fp D2I_PKCS12_FP +#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT +#define sk_num SK_NUM +#define sk_pop SK_POP +#define sk_pop_free SK_POP_FREE +#define sk_value SK_VALUE +#ifdef __VAX +#define OPENSSL_NO_SHA256 +#endif +#define SHA256_Final SHA256_FINAL +#define SHA256_Init SHA256_INIT +#define SHA256_Update SHA256_UPDATE + +#define USE_UPPERCASE_GSSAPI 1 +#define gss_seal GSS_SEAL +#define gss_unseal GSS_UNSEAL + +#define USE_UPPERCASE_KRBAPI 1 + +/* AI_NUMERICHOST needed for IP V6 support in Curl */ +#ifdef HAVE_NETDB_H +#include +#ifndef AI_NUMERICHOST +#ifdef ENABLE_IPV6 +#undef ENABLE_IPV6 +#endif +#endif +#endif + +/* VAX symbols are always in uppercase */ +#ifdef __VAX +#define inflate INFLATE +#define inflateEnd INFLATEEND +#define inflateInit2_ INFLATEINIT2_ +#define inflateInit_ INFLATEINIT_ +#define zlibVersion ZLIBVERSION +#endif + +/* Older VAX OpenSSL port defines these as Macros */ +/* Need to include the headers first and then redefine */ +/* that way a newer port will also work if some one has one */ +#ifdef __VAX + +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) +# define des_set_odd_parity DES_SET_ODD_PARITY +# define des_set_key DES_SET_KEY +# define des_ecb_encrypt DES_ECB_ENCRYPT + +# endif +# include +# ifndef OpenSSL_add_all_algorithms +# define OpenSSL_add_all_algorithms OPENSSL_ADD_ALL_ALGORITHMS + void OPENSSL_ADD_ALL_ALGORITHMS(void); +# endif + + /* Curl defines these to lower case and VAX needs them in upper case */ + /* So we need static routines */ +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) + +# undef des_set_odd_parity +# undef DES_set_odd_parity +# undef des_set_key +# undef DES_set_key +# undef des_ecb_encrypt +# undef DES_ecb_encrypt + + static void des_set_odd_parity(des_cblock *key) { + DES_SET_ODD_PARITY(key); + } + + static int des_set_key(const_des_cblock *key, + des_key_schedule schedule) { + return DES_SET_KEY(key, schedule); + } + + static void des_ecb_encrypt(const_des_cblock *input, + des_cblock *output, + des_key_schedule ks, int enc) { + DES_ECB_ENCRYPT(input, output, ks, enc); + } +#endif +/* Need this to stop a macro redefinition error */ +#if OPENSSL_VERSION_NUMBER < 0x00907000L +# ifdef X509_STORE_set_flags +# undef X509_STORE_set_flags +# define X509_STORE_set_flags(x,y) Curl_nop_stmt +# endif +#endif +#endif + +#endif /* HEADER_CURL_SETUP_VMS_H */ diff --git a/libcurl/lib/sha256.c b/libcurl/lib/sha256.c new file mode 100644 index 0000000..f9287af --- /dev/null +++ b/libcurl/lib/sha256.c @@ -0,0 +1,267 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Florin Petriuc, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +#include "warnless.h" +#include "curl_sha256.h" + +#if defined(USE_OPENSSL) + +#include + +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) +#define USE_OPENSSL_SHA256 +#endif + +#endif + +#ifdef USE_OPENSSL_SHA256 +/* When OpenSSL is available we use the SHA256-function from OpenSSL */ +#include +#else + +/* When no other crypto library is available we use this code segment */ + +/* ===== start - public domain SHA256 implementation ===== */ +/* This is based on SHA256 implementation in LibTomCrypt that was released into + * public domain by Tom St Denis. */ + +#define WPA_GET_BE32(a) ((((unsigned long)(a)[0]) << 24) | \ + (((unsigned long)(a)[1]) << 16) | \ + (((unsigned long)(a)[2]) << 8) | \ + ((unsigned long)(a)[3])) +#define WPA_PUT_BE32(a, val) \ +do { \ + (a)[0] = (unsigned char)((((unsigned long) (val)) >> 24) & 0xff); \ + (a)[1] = (unsigned char)((((unsigned long) (val)) >> 16) & 0xff); \ + (a)[2] = (unsigned char)((((unsigned long) (val)) >> 8) & 0xff); \ + (a)[3] = (unsigned char)(((unsigned long) (val)) & 0xff); \ +} while(0) + +#ifdef HAVE_LONGLONG +#define WPA_PUT_BE64(a, val) \ +do { \ + (a)[0] = (unsigned char)(((unsigned long long)(val)) >> 56); \ + (a)[1] = (unsigned char)(((unsigned long long)(val)) >> 48); \ + (a)[2] = (unsigned char)(((unsigned long long)(val)) >> 40); \ + (a)[3] = (unsigned char)(((unsigned long long)(val)) >> 32); \ + (a)[4] = (unsigned char)(((unsigned long long)(val)) >> 24); \ + (a)[5] = (unsigned char)(((unsigned long long)(val)) >> 16); \ + (a)[6] = (unsigned char)(((unsigned long long)(val)) >> 8); \ + (a)[7] = (unsigned char)(((unsigned long long)(val)) & 0xff); \ +} while(0) +#else +#define WPA_PUT_BE64(a, val) \ +do { \ + (a)[0] = (unsigned char)(((unsigned __int64)(val)) >> 56); \ + (a)[1] = (unsigned char)(((unsigned __int64)(val)) >> 48); \ + (a)[2] = (unsigned char)(((unsigned __int64)(val)) >> 40); \ + (a)[3] = (unsigned char)(((unsigned __int64)(val)) >> 32); \ + (a)[4] = (unsigned char)(((unsigned __int64)(val)) >> 24); \ + (a)[5] = (unsigned char)(((unsigned __int64)(val)) >> 16); \ + (a)[6] = (unsigned char)(((unsigned __int64)(val)) >> 8); \ + (a)[7] = (unsigned char)(((unsigned __int64)(val)) & 0xff); \ +} while(0) +#endif + +typedef struct sha256_state { +#ifdef HAVE_LONGLONG + unsigned long long length; +#else + unsigned __int64 length; +#endif + unsigned long state[8], curlen; + unsigned char buf[64]; +} SHA256_CTX; +/* the K array */ +static const unsigned long K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; +/* Various logical functions */ +#define RORc(x, y) \ +(((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \ + ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL) +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x), (n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) +/* compress 512-bits */ +static int sha256_compress(struct sha256_state *md, + unsigned char *buf) +{ + unsigned long S[8], W[64]; + int i; + /* copy state into S */ + for(i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + /* copy the state into 512-bits into W[0..15] */ + for(i = 0; i < 16; i++) + W[i] = WPA_GET_BE32(buf + (4 * i)); + /* fill W[16..63] */ + for(i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + + W[i - 16]; + } + /* Compress */ +#define RND(a,b,c,d,e,f,g,h,i) \ + unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + unsigned long t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + for(i = 0; i < 64; ++i) { + unsigned long t; + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } + /* feedback */ + for(i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + return 0; +} +/* Initialize the hash state */ +static void SHA256_Init(struct sha256_state *md) +{ + md->curlen = 0; + md->length = 0; + md->state[0] = 0x6A09E667UL; + md->state[1] = 0xBB67AE85UL; + md->state[2] = 0x3C6EF372UL; + md->state[3] = 0xA54FF53AUL; + md->state[4] = 0x510E527FUL; + md->state[5] = 0x9B05688CUL; + md->state[6] = 0x1F83D9ABUL; + md->state[7] = 0x5BE0CD19UL; +} +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +static int SHA256_Update(struct sha256_state *md, + const unsigned char *in, + unsigned long inlen) +{ + unsigned long n; +#define block_size 64 + if(md->curlen > sizeof(md->buf)) + return -1; + while(inlen > 0) { + if(md->curlen == 0 && inlen >= block_size) { + if(sha256_compress(md, (unsigned char *)in) < 0) + return -1; + md->length += block_size * 8; + in += block_size; + inlen -= block_size; + } + else { + n = CURLMIN(inlen, (block_size - md->curlen)); + memcpy(md->buf + md->curlen, in, n); + md->curlen += n; + in += n; + inlen -= n; + if(md->curlen == block_size) { + if(sha256_compress(md, md->buf) < 0) + return -1; + md->length += 8 * block_size; + md->curlen = 0; + } + } + } + return 0; +} +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +static int SHA256_Final(unsigned char *out, + struct sha256_state *md) +{ + int i; + if(md->curlen >= sizeof(md->buf)) + return -1; + /* increase the length of the message */ + md->length += md->curlen * 8; + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if(md->curlen > 56) { + while(md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + sha256_compress(md, md->buf); + md->curlen = 0; + } + /* pad up to 56 bytes of zeroes */ + while(md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + /* store length */ + WPA_PUT_BE64(md->buf + 56, md->length); + sha256_compress(md, md->buf); + /* copy output */ + for(i = 0; i < 8; i++) + WPA_PUT_BE32(out + (4 * i), md->state[i]); + return 0; +} +/* ===== end - public domain SHA256 implementation ===== */ + +#endif + +void Curl_sha256it(unsigned char *outbuffer, /* 32 unsigned chars */ + const unsigned char *input) +{ + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, input, curlx_uztoui(strlen((char *)input))); + SHA256_Final(outbuffer, &ctx); +} + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libcurl/lib/share.c b/libcurl/lib/share.c new file mode 100644 index 0000000..3d51086 --- /dev/null +++ b/libcurl/lib/share.c @@ -0,0 +1,257 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "share.h" +#include "psl.h" +#include "vtls/vtls.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +struct Curl_share * +curl_share_init(void) +{ + struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); + if(share) { + share->specifier |= (1<hostcache)) { + free(share); + return NULL; + } + } + + return share; +} + +#undef curl_share_setopt +CURLSHcode +curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...) +{ + va_list param; + int type; + curl_lock_function lockfunc; + curl_unlock_function unlockfunc; + void *ptr; + CURLSHcode res = CURLSHE_OK; + + if(share->dirty) + /* don't allow setting options while one or more handles are already + using this share */ + return CURLSHE_IN_USE; + + va_start(param, option); + + switch(option) { + case CURLSHOPT_SHARE: + /* this is a type this share will share */ + type = va_arg(param, int); + share->specifier |= (1<cookies) { + share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE); + if(!share->cookies) + res = CURLSHE_NOMEM; + } +#else /* CURL_DISABLE_HTTP */ + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_SSL_SESSION: +#ifdef USE_SSL + if(!share->sslsession) { + share->max_ssl_sessions = 8; + share->sslsession = calloc(share->max_ssl_sessions, + sizeof(struct curl_ssl_session)); + share->sessionage = 0; + if(!share->sslsession) + res = CURLSHE_NOMEM; + } +#else + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ + if(Curl_conncache_init(&share->conn_cache, 103)) + res = CURLSHE_NOMEM; + break; + + case CURL_LOCK_DATA_PSL: +#ifndef USE_LIBPSL + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + default: + res = CURLSHE_BAD_OPTION; + } + break; + + case CURLSHOPT_UNSHARE: + /* this is a type this share will no longer share */ + type = va_arg(param, int); + share->specifier &= ~(1<cookies) { + Curl_cookie_cleanup(share->cookies); + share->cookies = NULL; + } +#else /* CURL_DISABLE_HTTP */ + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_SSL_SESSION: +#ifdef USE_SSL + Curl_safefree(share->sslsession); +#else + res = CURLSHE_NOT_BUILT_IN; +#endif + break; + + case CURL_LOCK_DATA_CONNECT: + break; + + default: + res = CURLSHE_BAD_OPTION; + break; + } + break; + + case CURLSHOPT_LOCKFUNC: + lockfunc = va_arg(param, curl_lock_function); + share->lockfunc = lockfunc; + break; + + case CURLSHOPT_UNLOCKFUNC: + unlockfunc = va_arg(param, curl_unlock_function); + share->unlockfunc = unlockfunc; + break; + + case CURLSHOPT_USERDATA: + ptr = va_arg(param, void *); + share->clientdata = ptr; + break; + + default: + res = CURLSHE_BAD_OPTION; + break; + } + + va_end(param); + + return res; +} + +CURLSHcode +curl_share_cleanup(struct Curl_share *share) +{ + if(share == NULL) + return CURLSHE_INVALID; + + if(share->lockfunc) + share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, + share->clientdata); + + if(share->dirty) { + if(share->unlockfunc) + share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); + return CURLSHE_IN_USE; + } + + Curl_conncache_close_all_connections(&share->conn_cache); + Curl_conncache_destroy(&share->conn_cache); + Curl_hash_destroy(&share->hostcache); + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + Curl_cookie_cleanup(share->cookies); +#endif + +#ifdef USE_SSL + if(share->sslsession) { + size_t i; + for(i = 0; i < share->max_ssl_sessions; i++) + Curl_ssl_kill_session(&(share->sslsession[i])); + free(share->sslsession); + } +#endif + + Curl_psl_destroy(&share->psl); + + if(share->unlockfunc) + share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); + free(share); + + return CURLSHE_OK; +} + + +CURLSHcode +Curl_share_lock(struct Curl_easy *data, curl_lock_data type, + curl_lock_access accesstype) +{ + struct Curl_share *share = data->share; + + if(share == NULL) + return CURLSHE_INVALID; + + if(share->specifier & (1<lockfunc) /* only call this if set! */ + share->lockfunc(data, type, accesstype, share->clientdata); + } + /* else if we don't share this, pretend successful lock */ + + return CURLSHE_OK; +} + +CURLSHcode +Curl_share_unlock(struct Curl_easy *data, curl_lock_data type) +{ + struct Curl_share *share = data->share; + + if(share == NULL) + return CURLSHE_INVALID; + + if(share->specifier & (1<unlockfunc) /* only call this if set! */ + share->unlockfunc (data, type, share->clientdata); + } + + return CURLSHE_OK; +} diff --git a/libcurl/lib/share.h b/libcurl/lib/share.h new file mode 100644 index 0000000..a7dea41 --- /dev/null +++ b/libcurl/lib/share.h @@ -0,0 +1,66 @@ +#ifndef HEADER_CURL_SHARE_H +#define HEADER_CURL_SHARE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "cookie.h" +#include "psl.h" +#include "urldata.h" +#include "conncache.h" + +/* SalfordC says "A structure member may not be volatile". Hence: + */ +#ifdef __SALFORDC__ +#define CURL_VOLATILE +#else +#define CURL_VOLATILE volatile +#endif + +/* this struct is libcurl-private, don't export details */ +struct Curl_share { + unsigned int specifier; + CURL_VOLATILE unsigned int dirty; + + curl_lock_function lockfunc; + curl_unlock_function unlockfunc; + void *clientdata; + struct conncache conn_cache; + struct curl_hash hostcache; +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + struct CookieInfo *cookies; +#endif +#ifdef USE_LIBPSL + struct PslCache psl; +#endif + + struct curl_ssl_session *sslsession; + size_t max_ssl_sessions; + long sessionage; +}; + +CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, + curl_lock_access); +CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data); + +#endif /* HEADER_CURL_SHARE_H */ diff --git a/libcurl/lib/sigpipe.h b/libcurl/lib/sigpipe.h new file mode 100644 index 0000000..3960a13 --- /dev/null +++ b/libcurl/lib/sigpipe.h @@ -0,0 +1,79 @@ +#ifndef HEADER_CURL_SIGPIPE_H +#define HEADER_CURL_SIGPIPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \ + (defined(USE_OPENSSL) || defined(USE_MBEDTLS)) +#include + +struct sigpipe_ignore { + struct sigaction old_pipe_act; + bool no_signal; +}; + +#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x + +/* + * sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl + * internals, and then sigpipe_restore() will restore the situation when we + * return from libcurl again. + */ +static void sigpipe_ignore(struct Curl_easy *data, + struct sigpipe_ignore *ig) +{ + /* get a local copy of no_signal because the Curl_easy might not be + around when we restore */ + ig->no_signal = data->set.no_signal; + if(!data->set.no_signal) { + struct sigaction action; + /* first, extract the existing situation */ + memset(&ig->old_pipe_act, 0, sizeof(struct sigaction)); + sigaction(SIGPIPE, NULL, &ig->old_pipe_act); + action = ig->old_pipe_act; + /* ignore this signal */ + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + } +} + +/* + * sigpipe_restore() puts back the outside world's opinion of signal handler + * and SIGPIPE handling. It MUST only be called after a corresponding + * sigpipe_ignore() was used. + */ +static void sigpipe_restore(struct sigpipe_ignore *ig) +{ + if(!ig->no_signal) + /* restore the outside state */ + sigaction(SIGPIPE, &ig->old_pipe_act, NULL); +} + +#else +/* for systems without sigaction */ +#define sigpipe_ignore(x,y) Curl_nop_stmt +#define sigpipe_restore(x) Curl_nop_stmt +#define SIGPIPE_VARIABLE(x) +#endif + +#endif /* HEADER_CURL_SIGPIPE_H */ diff --git a/libcurl/lib/slist.c b/libcurl/lib/slist.c new file mode 100644 index 0000000..392b84d --- /dev/null +++ b/libcurl/lib/slist.c @@ -0,0 +1,144 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "slist.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* returns last node in linked list */ +static struct curl_slist *slist_get_last(struct curl_slist *list) +{ + struct curl_slist *item; + + /* if caller passed us a NULL, return now */ + if(!list) + return NULL; + + /* loop through to find the last item */ + item = list; + while(item->next) { + item = item->next; + } + return item; +} + +/* + * Curl_slist_append_nodup() appends a string to the linked list. Rather than + * copying the string in dynamic storage, it takes its ownership. The string + * should have been malloc()ated. Curl_slist_append_nodup always returns + * the address of the first record, so that you can use this function as an + * initialization function as well as an append function. + * If an error occurs, NULL is returned and the string argument is NOT + * released. + */ +struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data) +{ + struct curl_slist *last; + struct curl_slist *new_item; + + DEBUGASSERT(data); + + new_item = malloc(sizeof(struct curl_slist)); + if(!new_item) + return NULL; + + new_item->next = NULL; + new_item->data = data; + + /* if this is the first item, then new_item *is* the list */ + if(!list) + return new_item; + + last = slist_get_last(list); + last->next = new_item; + return list; +} + +/* + * curl_slist_append() appends a string to the linked list. It always returns + * the address of the first record, so that you can use this function as an + * initialization function as well as an append function. If you find this + * bothersome, then simply create a separate _init function and call it + * appropriately from within the program. + */ +struct curl_slist *curl_slist_append(struct curl_slist *list, + const char *data) +{ + char *dupdata = strdup(data); + + if(!dupdata) + return NULL; + + list = Curl_slist_append_nodup(list, dupdata); + if(!list) + free(dupdata); + + return list; +} + +/* + * Curl_slist_duplicate() duplicates a linked list. It always returns the + * address of the first record of the cloned list or NULL in case of an + * error (or if the input list was NULL). + */ +struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist) +{ + struct curl_slist *outlist = NULL; + struct curl_slist *tmp; + + while(inlist) { + tmp = curl_slist_append(outlist, inlist->data); + + if(!tmp) { + curl_slist_free_all(outlist); + return NULL; + } + + outlist = tmp; + inlist = inlist->next; + } + return outlist; +} + +/* be nice and clean up resources */ +void curl_slist_free_all(struct curl_slist *list) +{ + struct curl_slist *next; + struct curl_slist *item; + + if(!list) + return; + + item = list; + do { + next = item->next; + Curl_safefree(item->data); + free(item); + item = next; + } while(next); +} diff --git a/libcurl/lib/slist.h b/libcurl/lib/slist.h new file mode 100644 index 0000000..d73dbf6 --- /dev/null +++ b/libcurl/lib/slist.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_SLIST_H +#define HEADER_CURL_SLIST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Curl_slist_duplicate() duplicates a linked list. It always returns the + * address of the first record of the cloned list or NULL in case of an + * error (or if the input list was NULL). + */ +struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist); + +/* + * Curl_slist_append_nodup() takes ownership of the given string and appends + * it to the list. + */ +struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, + char *data); + +#endif /* HEADER_CURL_SLIST_H */ diff --git a/libcurl/lib/smb.c b/libcurl/lib/smb.c new file mode 100644 index 0000000..870244c --- /dev/null +++ b/libcurl/lib/smb.c @@ -0,0 +1,1004 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014, Bill Nagel , Exacq Technologies + * Copyright (C) 2016-2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#define BUILDING_CURL_SMB_C + +#ifdef HAVE_PROCESS_H +#include +#ifdef CURL_WINDOWS_APP +#define getpid GetCurrentProcessId +#elif !defined(MSDOS) +#define getpid _getpid +#endif +#endif + +#include "smb.h" +#include "urldata.h" +#include "sendf.h" +#include "multiif.h" +#include "connect.h" +#include "progress.h" +#include "transfer.h" +#include "vtls/vtls.h" +#include "curl_ntlm_core.h" +#include "escape.h" +#include "curl_endian.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode smb_setup_connection(struct connectdata *conn); +static CURLcode smb_connect(struct connectdata *conn, bool *done); +static CURLcode smb_connection_state(struct connectdata *conn, bool *done); +static CURLcode smb_do(struct connectdata *conn, bool *done); +static CURLcode smb_request_state(struct connectdata *conn, bool *done); +static CURLcode smb_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode smb_disconnect(struct connectdata *conn, bool dead); +static int smb_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode smb_parse_url_path(struct connectdata *conn); + +/* + * SMB handler interface + */ +const struct Curl_handler Curl_handler_smb = { + "SMB", /* scheme */ + smb_setup_connection, /* setup_connection */ + smb_do, /* do_it */ + smb_done, /* done */ + ZERO_NULL, /* do_more */ + smb_connect, /* connect_it */ + smb_connection_state, /* connecting */ + smb_request_state, /* doing */ + smb_getsock, /* proto_getsock */ + smb_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smb_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SMB, /* defport */ + CURLPROTO_SMB, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +#ifdef USE_SSL +/* + * SMBS handler interface + */ +const struct Curl_handler Curl_handler_smbs = { + "SMBS", /* scheme */ + smb_setup_connection, /* setup_connection */ + smb_do, /* do_it */ + smb_done, /* done */ + ZERO_NULL, /* do_more */ + smb_connect, /* connect_it */ + smb_connection_state, /* connecting */ + smb_request_state, /* doing */ + smb_getsock, /* proto_getsock */ + smb_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smb_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SMBS, /* defport */ + CURLPROTO_SMBS, /* protocol */ + PROTOPT_SSL /* flags */ +}; +#endif + +#define MAX_PAYLOAD_SIZE 0x8000 +#define MAX_MESSAGE_SIZE (MAX_PAYLOAD_SIZE + 0x1000) +#define CLIENTNAME "curl" +#define SERVICENAME "?????" + +/* Append a string to an SMB message */ +#define MSGCAT(str) \ + strcpy(p, (str)); \ + p += strlen(str); + +/* Append a null-terminated string to an SMB message */ +#define MSGCATNULL(str) \ + strcpy(p, (str)); \ + p += strlen(str) + 1; + +/* SMB is mostly little endian */ +#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ + defined(__OS400__) +static unsigned short smb_swap16(unsigned short x) +{ + return (unsigned short) ((x << 8) | ((x >> 8) & 0xff)); +} + +static unsigned int smb_swap32(unsigned int x) +{ + return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | + ((x >> 24) & 0xff); +} + +static curl_off_t smb_swap64(curl_off_t x) +{ + return ((curl_off_t) smb_swap32((unsigned int) x) << 32) | + smb_swap32((unsigned int) (x >> 32)); +} + +#else +# define smb_swap16(x) (x) +# define smb_swap32(x) (x) +# define smb_swap64(x) (x) +#endif + +/* SMB request state */ +enum smb_req_state { + SMB_REQUESTING, + SMB_TREE_CONNECT, + SMB_OPEN, + SMB_DOWNLOAD, + SMB_UPLOAD, + SMB_CLOSE, + SMB_TREE_DISCONNECT, + SMB_DONE +}; + +/* SMB request data */ +struct smb_request { + enum smb_req_state state; + char *path; + unsigned short tid; /* Even if we connect to the same tree as another */ + unsigned short fid; /* request, the tid will be different */ + CURLcode result; +}; + +static void conn_state(struct connectdata *conn, enum smb_conn_state newstate) +{ + struct smb_conn *smbc = &conn->proto.smbc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* For debug purposes */ + static const char * const names[] = { + "SMB_NOT_CONNECTED", + "SMB_CONNECTING", + "SMB_NEGOTIATE", + "SMB_SETUP", + "SMB_CONNECTED", + /* LAST */ + }; + + if(smbc->state != newstate) + infof(conn->data, "SMB conn %p state change from %s to %s\n", + (void *)smbc, names[smbc->state], names[newstate]); +#endif + + smbc->state = newstate; +} + +static void request_state(struct connectdata *conn, + enum smb_req_state newstate) +{ + struct smb_request *req = conn->data->req.protop; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* For debug purposes */ + static const char * const names[] = { + "SMB_REQUESTING", + "SMB_TREE_CONNECT", + "SMB_OPEN", + "SMB_DOWNLOAD", + "SMB_UPLOAD", + "SMB_CLOSE", + "SMB_TREE_DISCONNECT", + "SMB_DONE", + /* LAST */ + }; + + if(req->state != newstate) + infof(conn->data, "SMB request %p state change from %s to %s\n", + (void *)req, names[req->state], names[newstate]); +#endif + + req->state = newstate; +} + +/* this should setup things in the connection, not in the easy + handle */ +static CURLcode smb_setup_connection(struct connectdata *conn) +{ + struct smb_request *req; + + /* Initialize the request state */ + conn->data->req.protop = req = calloc(1, sizeof(struct smb_request)); + if(!req) + return CURLE_OUT_OF_MEMORY; + + /* Parse the URL path */ + return smb_parse_url_path(conn); +} + +static CURLcode smb_connect(struct connectdata *conn, bool *done) +{ + struct smb_conn *smbc = &conn->proto.smbc; + char *slash; + + (void) done; + + /* Check we have a username and password to authenticate with */ + if(!conn->bits.user_passwd) + return CURLE_LOGIN_DENIED; + + /* Initialize the connection state */ + smbc->state = SMB_CONNECTING; + smbc->recv_buf = malloc(MAX_MESSAGE_SIZE); + if(!smbc->recv_buf) + return CURLE_OUT_OF_MEMORY; + + /* Multiple requests are allowed with this connection */ + connkeep(conn, "SMB default"); + + /* Parse the username, domain, and password */ + slash = strchr(conn->user, '/'); + if(!slash) + slash = strchr(conn->user, '\\'); + + if(slash) { + smbc->user = slash + 1; + smbc->domain = strdup(conn->user); + if(!smbc->domain) + return CURLE_OUT_OF_MEMORY; + smbc->domain[slash - conn->user] = 0; + } + else { + smbc->user = conn->user; + smbc->domain = strdup(conn->host.name); + if(!smbc->domain) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +static CURLcode smb_recv_message(struct connectdata *conn, void **msg) +{ + struct smb_conn *smbc = &conn->proto.smbc; + char *buf = smbc->recv_buf; + ssize_t bytes_read; + size_t nbt_size; + size_t msg_size; + size_t len = MAX_MESSAGE_SIZE - smbc->got; + CURLcode result; + + result = Curl_read(conn, FIRSTSOCKET, buf + smbc->got, len, &bytes_read); + if(result) + return result; + + if(!bytes_read) + return CURLE_OK; + + smbc->got += bytes_read; + + /* Check for a 32-bit nbt header */ + if(smbc->got < sizeof(unsigned int)) + return CURLE_OK; + + nbt_size = Curl_read16_be((const unsigned char *) + (buf + sizeof(unsigned short))) + + sizeof(unsigned int); + if(smbc->got < nbt_size) + return CURLE_OK; + + msg_size = sizeof(struct smb_header); + if(nbt_size >= msg_size + 1) { + /* Add the word count */ + msg_size += 1 + ((unsigned char) buf[msg_size]) * sizeof(unsigned short); + if(nbt_size >= msg_size + sizeof(unsigned short)) { + /* Add the byte count */ + msg_size += sizeof(unsigned short) + + Curl_read16_le((const unsigned char *)&buf[msg_size]); + if(nbt_size < msg_size) + return CURLE_READ_ERROR; + } + } + + *msg = buf; + + return CURLE_OK; +} + +static void smb_pop_message(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + + smbc->got = 0; +} + +static void smb_format_message(struct connectdata *conn, struct smb_header *h, + unsigned char cmd, size_t len) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_request *req = conn->data->req.protop; + unsigned int pid; + + memset(h, 0, sizeof(*h)); + h->nbt_length = htons((unsigned short) (sizeof(*h) - sizeof(unsigned int) + + len)); + memcpy((char *)h->magic, "\xffSMB", 4); + h->command = cmd; + h->flags = SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES; + h->flags2 = smb_swap16(SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAME); + h->uid = smb_swap16(smbc->uid); + h->tid = smb_swap16(req->tid); + pid = getpid(); + h->pid_high = smb_swap16((unsigned short)(pid >> 16)); + h->pid = smb_swap16((unsigned short) pid); +} + +static CURLcode smb_send(struct connectdata *conn, ssize_t len, + size_t upload_size) +{ + struct smb_conn *smbc = &conn->proto.smbc; + ssize_t bytes_written; + CURLcode result; + + result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf, + len, &bytes_written); + if(result) + return result; + + if(bytes_written != len) { + smbc->send_size = len; + smbc->sent = bytes_written; + } + + smbc->upload_size = upload_size; + + return CURLE_OK; +} + +static CURLcode smb_flush(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + ssize_t bytes_written; + ssize_t len = smbc->send_size - smbc->sent; + CURLcode result; + + if(!smbc->send_size) + return CURLE_OK; + + result = Curl_write(conn, FIRSTSOCKET, + conn->data->state.ulbuf + smbc->sent, + len, &bytes_written); + if(result) + return result; + + if(bytes_written != len) + smbc->sent += bytes_written; + else + smbc->send_size = 0; + + return CURLE_OK; +} + +static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd, + const void *msg, size_t msg_len) +{ + CURLcode result = Curl_get_upload_buffer(conn->data); + if(result) + return result; + smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf, + cmd, msg_len); + memcpy(conn->data->state.ulbuf + sizeof(struct smb_header), + msg, msg_len); + + return smb_send(conn, sizeof(struct smb_header) + msg_len, 0); +} + +static CURLcode smb_send_negotiate(struct connectdata *conn) +{ + const char *msg = "\x00\x0c\x00\x02NT LM 0.12"; + + return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15); +} + +static CURLcode smb_send_setup(struct connectdata *conn) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_setup msg; + char *p = msg.bytes; + unsigned char lm_hash[21]; + unsigned char lm[24]; + unsigned char nt_hash[21]; + unsigned char nt[24]; + + size_t byte_count = sizeof(lm) + sizeof(nt); + byte_count += strlen(smbc->user) + strlen(smbc->domain); + byte_count += strlen(OS) + strlen(CLIENTNAME) + 4; /* 4 null chars */ + if(byte_count > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash); + Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm); +#ifdef USE_NTRESPONSES + Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash); + Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt); +#else + memset(nt, 0, sizeof(nt)); +#endif + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_SETUP_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.max_buffer_size = smb_swap16(MAX_MESSAGE_SIZE); + msg.max_mpx_count = smb_swap16(1); + msg.vc_number = smb_swap16(1); + msg.session_key = smb_swap32(smbc->session_key); + msg.capabilities = smb_swap32(SMB_CAP_LARGE_FILES); + msg.lengths[0] = smb_swap16(sizeof(lm)); + msg.lengths[1] = smb_swap16(sizeof(nt)); + memcpy(p, lm, sizeof(lm)); + p += sizeof(lm); + memcpy(p, nt, sizeof(nt)); + p += sizeof(nt); + MSGCATNULL(smbc->user); + MSGCATNULL(smbc->domain); + MSGCATNULL(OS); + MSGCATNULL(CLIENTNAME); + byte_count = p - msg.bytes; + msg.byte_count = smb_swap16((unsigned short)byte_count); + + return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_tree_connect(struct connectdata *conn) +{ + struct smb_tree_connect msg; + struct smb_conn *smbc = &conn->proto.smbc; + char *p = msg.bytes; + + size_t byte_count = strlen(conn->host.name) + strlen(smbc->share); + byte_count += strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */ + if(byte_count > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_TREE_CONNECT_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.pw_len = 0; + MSGCAT("\\\\"); + MSGCAT(conn->host.name); + MSGCAT("\\"); + MSGCATNULL(smbc->share); + MSGCATNULL(SERVICENAME); /* Match any type of service */ + byte_count = p - msg.bytes; + msg.byte_count = smb_swap16((unsigned short)byte_count); + + return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_open(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_nt_create msg; + size_t byte_count; + + if((strlen(req->path) + 1) > sizeof(msg.bytes)) + return CURLE_FILESIZE_EXCEEDED; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_NT_CREATE_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + byte_count = strlen(req->path); + msg.name_length = smb_swap16((unsigned short)byte_count); + msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL); + if(conn->data->set.upload) { + msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE); + msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF); + } + else { + msg.access = smb_swap32(SMB_GENERIC_READ); + msg.create_disposition = smb_swap32(SMB_FILE_OPEN); + } + msg.byte_count = smb_swap16((unsigned short) ++byte_count); + strcpy(msg.bytes, req->path); + + return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg, + sizeof(msg) - sizeof(msg.bytes) + byte_count); +} + +static CURLcode smb_send_close(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_close msg; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_CLOSE; + msg.fid = smb_swap16(req->fid); + + return smb_send_message(conn, SMB_COM_CLOSE, &msg, sizeof(msg)); +} + +static CURLcode smb_send_tree_disconnect(struct connectdata *conn) +{ + struct smb_tree_disconnect msg; + + memset(&msg, 0, sizeof(msg)); + + return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg)); +} + +static CURLcode smb_send_read(struct connectdata *conn) +{ + struct smb_request *req = conn->data->req.protop; + curl_off_t offset = conn->data->req.offset; + struct smb_read msg; + + memset(&msg, 0, sizeof(msg)); + msg.word_count = SMB_WC_READ_ANDX; + msg.andx.command = SMB_COM_NO_ANDX_COMMAND; + msg.fid = smb_swap16(req->fid); + msg.offset = smb_swap32((unsigned int) offset); + msg.offset_high = smb_swap32((unsigned int) (offset >> 32)); + msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE); + msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE); + + return smb_send_message(conn, SMB_COM_READ_ANDX, &msg, sizeof(msg)); +} + +static CURLcode smb_send_write(struct connectdata *conn) +{ + struct smb_write *msg; + struct smb_request *req = conn->data->req.protop; + curl_off_t offset = conn->data->req.offset; + curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount; + CURLcode result = Curl_get_upload_buffer(conn->data); + if(result) + return result; + msg = (struct smb_write *)conn->data->state.ulbuf; + + if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */ + upload_size = MAX_PAYLOAD_SIZE - 1; + + memset(msg, 0, sizeof(*msg)); + msg->word_count = SMB_WC_WRITE_ANDX; + msg->andx.command = SMB_COM_NO_ANDX_COMMAND; + msg->fid = smb_swap16(req->fid); + msg->offset = smb_swap32((unsigned int) offset); + msg->offset_high = smb_swap32((unsigned int) (offset >> 32)); + msg->data_length = smb_swap16((unsigned short) upload_size); + msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int)); + msg->byte_count = smb_swap16((unsigned short) (upload_size + 1)); + + smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX, + sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size); + + return smb_send(conn, sizeof(*msg), (size_t) upload_size); +} + +static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg) +{ + struct smb_conn *smbc = &conn->proto.smbc; + CURLcode result; + + /* Check if there is data in the transfer buffer */ + if(!smbc->send_size && smbc->upload_size) { + size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ? + conn->data->set.upload_buffer_size : + smbc->upload_size; + conn->data->req.upload_fromhere = conn->data->state.ulbuf; + result = Curl_fillreadbuffer(conn, nread, &nread); + if(result && result != CURLE_AGAIN) + return result; + if(!nread) + return CURLE_OK; + + smbc->upload_size -= nread; + smbc->send_size = nread; + smbc->sent = 0; + } + + /* Check if there is data to send */ + if(smbc->send_size) { + result = smb_flush(conn); + if(result) + return result; + } + + /* Check if there is still data to be sent */ + if(smbc->send_size || smbc->upload_size) + return CURLE_AGAIN; + + return smb_recv_message(conn, msg); +} + +static CURLcode smb_connection_state(struct connectdata *conn, bool *done) +{ + struct smb_conn *smbc = &conn->proto.smbc; + struct smb_negotiate_response *nrsp; + struct smb_header *h; + CURLcode result; + void *msg = NULL; + + if(smbc->state == SMB_CONNECTING) { +#ifdef USE_SSL + if((conn->handler->flags & PROTOPT_SSL)) { + bool ssl_done = FALSE; + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done); + if(result && result != CURLE_AGAIN) + return result; + if(!ssl_done) + return CURLE_OK; + } +#endif + + result = smb_send_negotiate(conn); + if(result) { + connclose(conn, "SMB: failed to send negotiate message"); + return result; + } + + conn_state(conn, SMB_NEGOTIATE); + } + + /* Send the previous message and check for a response */ + result = smb_send_and_recv(conn, &msg); + if(result && result != CURLE_AGAIN) { + connclose(conn, "SMB: failed to communicate"); + return result; + } + + if(!msg) + return CURLE_OK; + + h = msg; + + switch(smbc->state) { + case SMB_NEGOTIATE: + if(h->status || smbc->got < sizeof(*nrsp) + sizeof(smbc->challenge) - 1) { + connclose(conn, "SMB: negotiation failed"); + return CURLE_COULDNT_CONNECT; + } + nrsp = msg; + memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge)); + smbc->session_key = smb_swap32(nrsp->session_key); + result = smb_send_setup(conn); + if(result) { + connclose(conn, "SMB: failed to send setup message"); + return result; + } + conn_state(conn, SMB_SETUP); + break; + + case SMB_SETUP: + if(h->status) { + connclose(conn, "SMB: authentication failed"); + return CURLE_LOGIN_DENIED; + } + smbc->uid = smb_swap16(h->uid); + conn_state(conn, SMB_CONNECTED); + *done = true; + break; + + default: + smb_pop_message(conn); + return CURLE_OK; /* ignore */ + } + + smb_pop_message(conn); + + return CURLE_OK; +} + +/* + * Convert a timestamp from the Windows world (100 nsec units from 1 Jan 1601) + * to Posix time. Cap the output to fit within a time_t. + */ +static void get_posix_time(time_t *out, curl_off_t timestamp) +{ + timestamp -= 116444736000000000; + timestamp /= 10000000; +#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T + if(timestamp > TIME_T_MAX) + *out = TIME_T_MAX; + else if(timestamp < TIME_T_MIN) + *out = TIME_T_MIN; + else +#endif + *out = (time_t) timestamp; +} + +static CURLcode smb_request_state(struct connectdata *conn, bool *done) +{ + struct smb_request *req = conn->data->req.protop; + struct smb_header *h; + struct smb_conn *smbc = &conn->proto.smbc; + enum smb_req_state next_state = SMB_DONE; + unsigned short len; + unsigned short off; + CURLcode result; + void *msg = NULL; + const struct smb_nt_create_response *smb_m; + + /* Start the request */ + if(req->state == SMB_REQUESTING) { + result = smb_send_tree_connect(conn); + if(result) { + connclose(conn, "SMB: failed to send tree connect message"); + return result; + } + + request_state(conn, SMB_TREE_CONNECT); + } + + /* Send the previous message and check for a response */ + result = smb_send_and_recv(conn, &msg); + if(result && result != CURLE_AGAIN) { + connclose(conn, "SMB: failed to communicate"); + return result; + } + + if(!msg) + return CURLE_OK; + + h = msg; + + switch(req->state) { + case SMB_TREE_CONNECT: + if(h->status) { + req->result = CURLE_REMOTE_FILE_NOT_FOUND; + if(h->status == smb_swap32(SMB_ERR_NOACCESS)) + req->result = CURLE_REMOTE_ACCESS_DENIED; + break; + } + req->tid = smb_swap16(h->tid); + next_state = SMB_OPEN; + break; + + case SMB_OPEN: + if(h->status || smbc->got < sizeof(struct smb_nt_create_response)) { + req->result = CURLE_REMOTE_FILE_NOT_FOUND; + if(h->status == smb_swap32(SMB_ERR_NOACCESS)) + req->result = CURLE_REMOTE_ACCESS_DENIED; + next_state = SMB_TREE_DISCONNECT; + break; + } + smb_m = (const struct smb_nt_create_response*) msg; + req->fid = smb_swap16(smb_m->fid); + conn->data->req.offset = 0; + if(conn->data->set.upload) { + conn->data->req.size = conn->data->state.infilesize; + Curl_pgrsSetUploadSize(conn->data, conn->data->req.size); + next_state = SMB_UPLOAD; + } + else { + smb_m = (const struct smb_nt_create_response*) msg; + conn->data->req.size = smb_swap64(smb_m->end_of_file); + if(conn->data->req.size < 0) { + req->result = CURLE_WEIRD_SERVER_REPLY; + next_state = SMB_CLOSE; + } + else { + Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size); + if(conn->data->set.get_filetime) + get_posix_time(&conn->data->info.filetime, smb_m->last_change_time); + next_state = SMB_DOWNLOAD; + } + } + break; + + case SMB_DOWNLOAD: + if(h->status || smbc->got < sizeof(struct smb_header) + 14) { + req->result = CURLE_RECV_ERROR; + next_state = SMB_CLOSE; + break; + } + len = Curl_read16_le(((const unsigned char *) msg) + + sizeof(struct smb_header) + 11); + off = Curl_read16_le(((const unsigned char *) msg) + + sizeof(struct smb_header) + 13); + if(len > 0) { + if(off + sizeof(unsigned int) + len > smbc->got) { + failf(conn->data, "Invalid input packet"); + result = CURLE_RECV_ERROR; + } + else + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *)msg + off + sizeof(unsigned int), + len); + if(result) { + req->result = result; + next_state = SMB_CLOSE; + break; + } + } + conn->data->req.bytecount += len; + conn->data->req.offset += len; + Curl_pgrsSetDownloadCounter(conn->data, conn->data->req.bytecount); + next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD; + break; + + case SMB_UPLOAD: + if(h->status || smbc->got < sizeof(struct smb_header) + 6) { + req->result = CURLE_UPLOAD_FAILED; + next_state = SMB_CLOSE; + break; + } + len = Curl_read16_le(((const unsigned char *) msg) + + sizeof(struct smb_header) + 5); + conn->data->req.bytecount += len; + conn->data->req.offset += len; + Curl_pgrsSetUploadCounter(conn->data, conn->data->req.bytecount); + if(conn->data->req.bytecount >= conn->data->req.size) + next_state = SMB_CLOSE; + else + next_state = SMB_UPLOAD; + break; + + case SMB_CLOSE: + /* We don't care if the close failed, proceed to tree disconnect anyway */ + next_state = SMB_TREE_DISCONNECT; + break; + + case SMB_TREE_DISCONNECT: + next_state = SMB_DONE; + break; + + default: + smb_pop_message(conn); + return CURLE_OK; /* ignore */ + } + + smb_pop_message(conn); + + switch(next_state) { + case SMB_OPEN: + result = smb_send_open(conn); + break; + + case SMB_DOWNLOAD: + result = smb_send_read(conn); + break; + + case SMB_UPLOAD: + result = smb_send_write(conn); + break; + + case SMB_CLOSE: + result = smb_send_close(conn); + break; + + case SMB_TREE_DISCONNECT: + result = smb_send_tree_disconnect(conn); + break; + + case SMB_DONE: + result = req->result; + *done = true; + break; + + default: + break; + } + + if(result) { + connclose(conn, "SMB: failed to send message"); + return result; + } + + request_state(conn, next_state); + + return CURLE_OK; +} + +static CURLcode smb_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void) premature; + Curl_safefree(conn->data->req.protop); + return status; +} + +static CURLcode smb_disconnect(struct connectdata *conn, bool dead) +{ + struct smb_conn *smbc = &conn->proto.smbc; + (void) dead; + Curl_safefree(smbc->share); + Curl_safefree(smbc->domain); + Curl_safefree(smbc->recv_buf); + return CURLE_OK; +} + +static int smb_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0); +} + +static CURLcode smb_do(struct connectdata *conn, bool *done) +{ + struct smb_conn *smbc = &conn->proto.smbc; + + *done = FALSE; + if(smbc->share) { + return CURLE_OK; + } + return CURLE_URL_MALFORMAT; +} + +static CURLcode smb_parse_url_path(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct smb_request *req = data->req.protop; + struct smb_conn *smbc = &conn->proto.smbc; + char *path; + char *slash; + + /* URL decode the path */ + CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL, + TRUE); + if(result) + return result; + + /* Parse the path for the share */ + smbc->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path); + free(path); + if(!smbc->share) + return CURLE_OUT_OF_MEMORY; + + slash = strchr(smbc->share, '/'); + if(!slash) + slash = strchr(smbc->share, '\\'); + + /* The share must be present */ + if(!slash) { + Curl_safefree(smbc->share); + return CURLE_URL_MALFORMAT; + } + + /* Parse the path for the file path converting any forward slashes into + backslashes */ + *slash++ = 0; + req->path = slash; + + for(; *slash; slash++) { + if(*slash == '/') + *slash = '\\'; + } + return CURLE_OK; +} + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */ diff --git a/libcurl/lib/smb.h b/libcurl/lib/smb.h new file mode 100644 index 0000000..9ce6b56 --- /dev/null +++ b/libcurl/lib/smb.h @@ -0,0 +1,259 @@ +#ifndef HEADER_CURL_SMB_H +#define HEADER_CURL_SMB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014, Bill Nagel , Exacq Technologies + * Copyright (C) 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +enum smb_conn_state { + SMB_NOT_CONNECTED = 0, + SMB_CONNECTING, + SMB_NEGOTIATE, + SMB_SETUP, + SMB_CONNECTED +}; + +struct smb_conn { + enum smb_conn_state state; + char *user; + char *domain; + char *share; + unsigned char challenge[8]; + unsigned int session_key; + unsigned short uid; + char *recv_buf; + size_t upload_size; + size_t send_size; + size_t sent; + size_t got; +}; + +/* + * Definitions for SMB protocol data structures + */ +#ifdef BUILDING_CURL_SMB_C + +#if defined(_MSC_VER) || defined(__ILEC400__) +# define PACK +# pragma pack(push) +# pragma pack(1) +#elif defined(__GNUC__) +# define PACK __attribute__((packed)) +#else +# define PACK +#endif + +#define SMB_COM_CLOSE 0x04 +#define SMB_COM_READ_ANDX 0x2e +#define SMB_COM_WRITE_ANDX 0x2f +#define SMB_COM_TREE_DISCONNECT 0x71 +#define SMB_COM_NEGOTIATE 0x72 +#define SMB_COM_SETUP_ANDX 0x73 +#define SMB_COM_TREE_CONNECT_ANDX 0x75 +#define SMB_COM_NT_CREATE_ANDX 0xa2 +#define SMB_COM_NO_ANDX_COMMAND 0xff + +#define SMB_WC_CLOSE 0x03 +#define SMB_WC_READ_ANDX 0x0c +#define SMB_WC_WRITE_ANDX 0x0e +#define SMB_WC_SETUP_ANDX 0x0d +#define SMB_WC_TREE_CONNECT_ANDX 0x04 +#define SMB_WC_NT_CREATE_ANDX 0x18 + +#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10 +#define SMB_FLAGS_CASELESS_PATHNAMES 0x08 +#define SMB_FLAGS2_UNICODE_STRINGS 0x8000 +#define SMB_FLAGS2_IS_LONG_NAME 0x0040 +#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001 + +#define SMB_CAP_LARGE_FILES 0x08 +#define SMB_GENERIC_WRITE 0x40000000 +#define SMB_GENERIC_READ 0x80000000 +#define SMB_FILE_SHARE_ALL 0x07 +#define SMB_FILE_OPEN 0x01 +#define SMB_FILE_OVERWRITE_IF 0x05 + +#define SMB_ERR_NOACCESS 0x00050001 + +struct smb_header { + unsigned char nbt_type; + unsigned char nbt_flags; + unsigned short nbt_length; + unsigned char magic[4]; + unsigned char command; + unsigned int status; + unsigned char flags; + unsigned short flags2; + unsigned short pid_high; + unsigned char signature[8]; + unsigned short pad; + unsigned short tid; + unsigned short pid; + unsigned short uid; + unsigned short mid; +} PACK; + +struct smb_negotiate_response { + struct smb_header h; + unsigned char word_count; + unsigned short dialect_index; + unsigned char security_mode; + unsigned short max_mpx_count; + unsigned short max_number_vcs; + unsigned int max_buffer_size; + unsigned int max_raw_size; + unsigned int session_key; + unsigned int capabilities; + unsigned int system_time_low; + unsigned int system_time_high; + unsigned short server_time_zone; + unsigned char encryption_key_length; + unsigned short byte_count; + char bytes[1]; +} PACK; + +struct andx { + unsigned char command; + unsigned char pad; + unsigned short offset; +} PACK; + +struct smb_setup { + unsigned char word_count; + struct andx andx; + unsigned short max_buffer_size; + unsigned short max_mpx_count; + unsigned short vc_number; + unsigned int session_key; + unsigned short lengths[2]; + unsigned int pad; + unsigned int capabilities; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_tree_connect { + unsigned char word_count; + struct andx andx; + unsigned short flags; + unsigned short pw_len; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_nt_create { + unsigned char word_count; + struct andx andx; + unsigned char pad; + unsigned short name_length; + unsigned int flags; + unsigned int root_fid; + unsigned int access; + curl_off_t allocation_size; + unsigned int ext_file_attributes; + unsigned int share_access; + unsigned int create_disposition; + unsigned int create_options; + unsigned int impersonation_level; + unsigned char security_flags; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_nt_create_response { + struct smb_header h; + unsigned char word_count; + struct andx andx; + unsigned char op_lock_level; + unsigned short fid; + unsigned int create_disposition; + + curl_off_t create_time; + curl_off_t last_access_time; + curl_off_t last_write_time; + curl_off_t last_change_time; + unsigned int ext_file_attributes; + curl_off_t allocation_size; + curl_off_t end_of_file; + +} PACK; + +struct smb_read { + unsigned char word_count; + struct andx andx; + unsigned short fid; + unsigned int offset; + unsigned short max_bytes; + unsigned short min_bytes; + unsigned int timeout; + unsigned short remaining; + unsigned int offset_high; + unsigned short byte_count; +} PACK; + +struct smb_write { + struct smb_header h; + unsigned char word_count; + struct andx andx; + unsigned short fid; + unsigned int offset; + unsigned int timeout; + unsigned short write_mode; + unsigned short remaining; + unsigned short pad; + unsigned short data_length; + unsigned short data_offset; + unsigned int offset_high; + unsigned short byte_count; + unsigned char pad2; +} PACK; + +struct smb_close { + unsigned char word_count; + unsigned short fid; + unsigned int last_mtime; + unsigned short byte_count; +} PACK; + +struct smb_tree_disconnect { + unsigned char word_count; + unsigned short byte_count; +} PACK; + +#if defined(_MSC_VER) || defined(__ILEC400__) +# pragma pack(pop) +#endif + +#endif /* BUILDING_CURL_SMB_C */ + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +extern const struct Curl_handler Curl_handler_smb; +extern const struct Curl_handler Curl_handler_smbs; + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */ + +#endif /* HEADER_CURL_SMB_H */ diff --git a/libcurl/lib/smtp.c b/libcurl/lib/smtp.c new file mode 100644 index 0000000..e10d0fb --- /dev/null +++ b/libcurl/lib/smtp.c @@ -0,0 +1,1639 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC1870 SMTP Service Extension for Message Size + * RFC2195 CRAM-MD5 authentication + * RFC2831 DIGEST-MD5 authentication + * RFC3207 SMTP over TLS + * RFC4422 Simple Authentication and Security Layer (SASL) + * RFC4616 PLAIN authentication + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * RFC4954 SMTP Authentication + * RFC5321 SMTP protocol + * RFC6749 OAuth 2.0 Authorization Framework + * RFC8314 Use of TLS for Email Submission and Access + * Draft SMTP URL Interface + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_SMTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "mime.h" +#include "socks.h" +#include "smtp.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "select.h" +#include "multiif.h" +#include "url.h" +#include "curl_gethostname.h" +#include "curl_sasl.h" +#include "warnless.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Local API functions */ +static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done); +static CURLcode smtp_do(struct connectdata *conn, bool *done); +static CURLcode smtp_done(struct connectdata *conn, CURLcode status, + bool premature); +static CURLcode smtp_connect(struct connectdata *conn, bool *done); +static CURLcode smtp_disconnect(struct connectdata *conn, bool dead); +static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done); +static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode smtp_setup_connection(struct connectdata *conn); +static CURLcode smtp_parse_url_options(struct connectdata *conn); +static CURLcode smtp_parse_url_path(struct connectdata *conn); +static CURLcode smtp_parse_custom_request(struct connectdata *conn); +static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, + const char *initresp); +static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); +static void smtp_get_message(char *buffer, char **outptr); + +/* + * SMTP protocol handler. + */ + +const struct Curl_handler Curl_handler_smtp = { + "SMTP", /* scheme */ + smtp_setup_connection, /* setup_connection */ + smtp_do, /* do_it */ + smtp_done, /* done */ + ZERO_NULL, /* do_more */ + smtp_connect, /* connect_it */ + smtp_multi_statemach, /* connecting */ + smtp_doing, /* doing */ + smtp_getsock, /* proto_getsock */ + smtp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smtp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SMTP, /* defport */ + CURLPROTO_SMTP, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ + PROTOPT_URLOPTIONS +}; + +#ifdef USE_SSL +/* + * SMTPS protocol handler. + */ + +const struct Curl_handler Curl_handler_smtps = { + "SMTPS", /* scheme */ + smtp_setup_connection, /* setup_connection */ + smtp_do, /* do_it */ + smtp_done, /* done */ + ZERO_NULL, /* do_more */ + smtp_connect, /* connect_it */ + smtp_multi_statemach, /* connecting */ + smtp_doing, /* doing */ + smtp_getsock, /* proto_getsock */ + smtp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + smtp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SMTPS, /* defport */ + CURLPROTO_SMTPS, /* protocol */ + PROTOPT_CLOSEACTION | PROTOPT_SSL + | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */ +}; +#endif + +/* SASL parameters for the smtp protocol */ +static const struct SASLproto saslsmtp = { + "smtp", /* The service name */ + 334, /* Code received when continuation is expected */ + 235, /* Code to receive upon authentication success */ + 512 - 8, /* Maximum initial response length (no max) */ + smtp_perform_auth, /* Send authentication command */ + smtp_continue_auth, /* Send authentication continuation */ + smtp_get_message /* Get SASL response message */ +}; + +#ifdef USE_SSL +static void smtp_to_smtps(struct connectdata *conn) +{ + /* Change the connection handler */ + conn->handler = &Curl_handler_smtps; + + /* Set the connection's upgraded to TLS flag */ + conn->tls_upgraded = TRUE; +} +#else +#define smtp_to_smtps(x) Curl_nop_stmt +#endif + +/*********************************************************************** + * + * smtp_endofresp() + * + * Checks for an ending SMTP status code at the start of the given string, but + * also detects various capabilities from the EHLO response including the + * supported authentication mechanisms. + */ +static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, + int *resp) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + bool result = FALSE; + + /* Nothing for us */ + if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) + return FALSE; + + /* Do we have a command response? This should be the response code followed + by a space and optionally some text as per RFC-5321 and as outlined in + Section 4. Examples of RFC-4954 but some e-mail servers ignore this and + only send the response code instead as per Section 4.2. */ + if(line[3] == ' ' || len == 5) { + char tmpline[6]; + + result = TRUE; + memset(tmpline, '\0', sizeof(tmpline)); + memcpy(tmpline, line, (len == 5 ? 5 : 3)); + *resp = curlx_sltosi(strtol(tmpline, NULL, 10)); + + /* Make sure real server never sends internal value */ + if(*resp == 1) + *resp = 0; + } + /* Do we have a multiline (continuation) response? */ + else if(line[3] == '-' && + (smtpc->state == SMTP_EHLO || smtpc->state == SMTP_COMMAND)) { + result = TRUE; + *resp = 1; /* Internal response code */ + } + + return result; +} + +/*********************************************************************** + * + * smtp_get_message() + * + * Gets the authentication message from the response buffer. + */ +static void smtp_get_message(char *buffer, char **outptr) +{ + size_t len = strlen(buffer); + char *message = NULL; + + if(len > 4) { + /* Find the start of the message */ + len -= 4; + for(message = buffer + 4; *message == ' ' || *message == '\t'; + message++, len--) + ; + + /* Find the end of the message */ + for(; len--;) + if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' && + message[len] != '\t') + break; + + /* Terminate the message */ + if(++len) { + message[len] = '\0'; + } + } + else + /* junk input => zero length output */ + message = &buffer[len]; + + *outptr = message; +} + +/*********************************************************************** + * + * state() + * + * This is the ONLY way to change SMTP state! + */ +static void state(struct connectdata *conn, smtpstate newstate) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "STOP", + "SERVERGREET", + "EHLO", + "HELO", + "STARTTLS", + "UPGRADETLS", + "AUTH", + "COMMAND", + "MAIL", + "RCPT", + "DATA", + "POSTDATA", + "QUIT", + /* LAST */ + }; + + if(smtpc->state != newstate) + infof(conn->data, "SMTP %p state change from %s to %s\n", + (void *)smtpc, names[smtpc->state], names[newstate]); +#endif + + smtpc->state = newstate; +} + +/*********************************************************************** + * + * smtp_perform_ehlo() + * + * Sends the EHLO command to not only initialise communication with the ESMTP + * server but to also obtain a list of server side supported capabilities. + */ +static CURLcode smtp_perform_ehlo(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */ + smtpc->sasl.authused = SASL_AUTH_NONE; /* Clear the authentication mechanism + used for esmtp connections */ + smtpc->tls_supported = FALSE; /* Clear the TLS capability */ + smtpc->auth_supported = FALSE; /* Clear the AUTH capability */ + + /* Send the EHLO command */ + result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain); + + if(!result) + state(conn, SMTP_EHLO); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_helo() + * + * Sends the HELO command to initialise communication with the SMTP server. + */ +static CURLcode smtp_perform_helo(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + smtpc->sasl.authused = SASL_AUTH_NONE; /* No authentication mechanism used + in smtp connections */ + + /* Send the HELO command */ + result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain); + + if(!result) + state(conn, SMTP_HELO); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_starttls() + * + * Sends the STLS command to start the upgrade to TLS. + */ +static CURLcode smtp_perform_starttls(struct connectdata *conn) +{ + /* Send the STARTTLS command */ + CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS"); + + if(!result) + state(conn, SMTP_STARTTLS); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_upgrade_tls() + * + * Performs the upgrade to TLS. + */ +static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn) +{ + /* Start the SSL connection */ + struct smtp_conn *smtpc = &conn->proto.smtpc; + CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + &smtpc->ssldone); + + if(!result) { + if(smtpc->state != SMTP_UPGRADETLS) + state(conn, SMTP_UPGRADETLS); + + if(smtpc->ssldone) { + smtp_to_smtps(conn); + result = smtp_perform_ehlo(conn); + } + } + + return result; +} + +/*********************************************************************** + * + * smtp_perform_auth() + * + * Sends an AUTH command allowing the client to login with the given SASL + * authentication mechanism. + */ +static CURLcode smtp_perform_auth(struct connectdata *conn, + const char *mech, + const char *initresp) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + if(initresp) { /* AUTH ... */ + /* Send the AUTH command with the initial response */ + result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); + } + else { + /* Send the AUTH command */ + result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); + } + + return result; +} + +/*********************************************************************** + * + * smtp_continue_auth() + * + * Sends SASL continuation data or cancellation. + */ +static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + + return Curl_pp_sendf(&smtpc->pp, "%s", resp); +} + +/*********************************************************************** + * + * smtp_perform_authentication() + * + * Initiates the authentication sequence, with the appropriate SASL + * authentication mechanism. + */ +static CURLcode smtp_perform_authentication(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + saslprogress progress; + + /* Check we have enough data to authenticate with, and the + server supports authentiation, and end the connect phase if not */ + if(!smtpc->auth_supported || + !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) { + state(conn, SMTP_STOP); + return result; + } + + /* Calculate the SASL login details */ + result = Curl_sasl_start(&smtpc->sasl, conn, FALSE, &progress); + + if(!result) { + if(progress == SASL_INPROGRESS) + state(conn, SMTP_AUTH); + else { + /* Other mechanisms not supported */ + infof(conn->data, "No known authentication mechanisms supported!\n"); + result = CURLE_LOGIN_DENIED; + } + } + + return result; +} + +/*********************************************************************** + * + * smtp_perform_command() + * + * Sends a SMTP based command. + */ +static CURLcode smtp_perform_command(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + + /* Send the command */ + if(smtp->rcpt) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s", + smtp->custom && smtp->custom[0] != '\0' ? + smtp->custom : "VRFY", + smtp->rcpt->data); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", + smtp->custom && smtp->custom[0] != '\0' ? + smtp->custom : "HELP"); + + if(!result) + state(conn, SMTP_COMMAND); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_mail() + * + * Sends an MAIL command to initiate the upload of a message. + */ +static CURLcode smtp_perform_mail(struct connectdata *conn) +{ + char *from = NULL; + char *auth = NULL; + char *size = NULL; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + /* Calculate the FROM parameter */ + if(!data->set.str[STRING_MAIL_FROM]) + /* Null reverse-path, RFC-5321, sect. 3.6.3 */ + from = strdup("<>"); + else if(data->set.str[STRING_MAIL_FROM][0] == '<') + from = aprintf("%s", data->set.str[STRING_MAIL_FROM]); + else + from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]); + + if(!from) + return CURLE_OUT_OF_MEMORY; + + /* Calculate the optional AUTH parameter */ + if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) { + if(data->set.str[STRING_MAIL_AUTH][0] != '\0') + auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]); + else + /* Empty AUTH, RFC-2554, sect. 5 */ + auth = strdup("<>"); + + if(!auth) { + free(from); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* Prepare the mime data if some. */ + if(data->set.mimepost.kind != MIMEKIND_NONE) { + /* Use the whole structure as data. */ + data->set.mimepost.flags &= ~MIME_BODY_ONLY; + + /* Add external headers and mime version. */ + curl_mime_headers(&data->set.mimepost, data->set.headers, 0); + result = Curl_mime_prepare_headers(&data->set.mimepost, NULL, + NULL, MIMESTRATEGY_MAIL); + + if(!result) + if(!Curl_checkheaders(conn, "Mime-Version")) + result = Curl_mime_add_header(&data->set.mimepost.curlheaders, + "Mime-Version: 1.0"); + + /* Make sure we will read the entire mime structure. */ + if(!result) + result = Curl_mime_rewind(&data->set.mimepost); + + if(result) { + free(from); + free(auth); + return result; + } + + data->state.infilesize = Curl_mime_size(&data->set.mimepost); + + /* Read from mime structure. */ + data->state.fread_func = (curl_read_callback) Curl_mime_read; + data->state.in = (void *) &data->set.mimepost; + } + + /* Calculate the optional SIZE parameter */ + if(conn->proto.smtpc.size_supported && data->state.infilesize > 0) { + size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize); + + if(!size) { + free(from); + free(auth); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* Send the MAIL command */ + if(!auth && !size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s", from); + else if(auth && !size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s AUTH=%s", from, auth); + else if(auth && size) + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, + "MAIL FROM:%s SIZE=%s", from, size); + + free(from); + free(auth); + free(size); + + if(!result) + state(conn, SMTP_MAIL); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_rcpt_to() + * + * Sends a RCPT TO command for a given recipient as part of the message upload + * process. + */ +static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + + /* Send the RCPT TO command */ + if(smtp->rcpt->data[0] == '<') + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s", + smtp->rcpt->data); + else + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", + smtp->rcpt->data); + if(!result) + state(conn, SMTP_RCPT); + + return result; +} + +/*********************************************************************** + * + * smtp_perform_quit() + * + * Performs the quit action prior to sclose() being called. + */ +static CURLcode smtp_perform_quit(struct connectdata *conn) +{ + /* Send the QUIT command */ + CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT"); + + if(!result) + state(conn, SMTP_QUIT); + + return result; +} + +/* For the initial server greeting */ +static CURLcode smtp_state_servergreet_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "Got unexpected smtp-server response: %d", smtpcode); + result = CURLE_WEIRD_SERVER_REPLY; + } + else + result = smtp_perform_ehlo(conn); + + return result; +} + +/* For STARTTLS responses */ +static CURLcode smtp_state_starttls_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 220) { + if(data->set.use_ssl != CURLUSESSL_TRY) { + failf(data, "STARTTLS denied, code %d", smtpcode); + result = CURLE_USE_SSL_FAILED; + } + else + result = smtp_perform_authentication(conn); + } + else + result = smtp_perform_upgrade_tls(conn); + + return result; +} + +/* For EHLO responses */ +static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2 && smtpcode != 1) { + if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) + result = smtp_perform_helo(conn); + else { + failf(data, "Remote access denied: %d", smtpcode); + result = CURLE_REMOTE_ACCESS_DENIED; + } + } + else { + line += 4; + len -= 4; + + /* Does the server support the STARTTLS capability? */ + if(len >= 8 && !memcmp(line, "STARTTLS", 8)) + smtpc->tls_supported = TRUE; + + /* Does the server support the SIZE capability? */ + else if(len >= 4 && !memcmp(line, "SIZE", 4)) + smtpc->size_supported = TRUE; + + /* Does the server support authentication? */ + else if(len >= 5 && !memcmp(line, "AUTH ", 5)) { + smtpc->auth_supported = TRUE; + + /* Advance past the AUTH keyword */ + line += 5; + len -= 5; + + /* Loop through the data line */ + for(;;) { + size_t llen; + size_t wordlen; + unsigned int mechbit; + + while(len && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + len--; + } + + if(!len) + break; + + /* Extract the word */ + for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Test the word for a matching authentication mechanism */ + mechbit = Curl_sasl_decode_mech(line, wordlen, &llen); + if(mechbit && llen == wordlen) + smtpc->sasl.authmechs |= mechbit; + + line += wordlen; + len -= wordlen; + } + } + + if(smtpcode != 1) { + if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* We don't have a SSL/TLS connection yet, but SSL is requested */ + if(smtpc->tls_supported) + /* Switch to TLS connection now */ + result = smtp_perform_starttls(conn); + else if(data->set.use_ssl == CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = smtp_perform_authentication(conn); + else { + failf(data, "STARTTLS not supported."); + result = CURLE_USE_SSL_FAILED; + } + } + else + result = smtp_perform_authentication(conn); + } + } + + return result; +} + +/* For HELO responses */ +static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "Remote access denied: %d", smtpcode); + result = CURLE_REMOTE_ACCESS_DENIED; + } + else + /* End of connect phase */ + state(conn, SMTP_STOP); + + return result; +} + +/* For SASL authentication responses */ +static CURLcode smtp_state_auth_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + saslprogress progress; + + (void)instate; /* no use for this yet */ + + result = Curl_sasl_continue(&smtpc->sasl, conn, smtpcode, &progress); + if(!result) + switch(progress) { + case SASL_DONE: + state(conn, SMTP_STOP); /* Authenticated */ + break; + case SASL_IDLE: /* No mechanism left after cancellation */ + failf(data, "Authentication cancelled"); + result = CURLE_LOGIN_DENIED; + break; + default: + break; + } + + return result; +} + +/* For command responses */ +static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + char *line = data->state.buffer; + size_t len = strlen(line); + + (void)instate; /* no use for this yet */ + + if((smtp->rcpt && smtpcode/100 != 2 && smtpcode != 553 && smtpcode != 1) || + (!smtp->rcpt && smtpcode/100 != 2 && smtpcode != 1)) { + failf(data, "Command failed: %d", smtpcode); + result = CURLE_RECV_ERROR; + } + else { + /* Temporarily add the LF character back and send as body to the client */ + if(!data->set.opt_no_body) { + line[len] = '\n'; + result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + line[len] = '\0'; + } + + if(smtpcode != 1) { + if(smtp->rcpt) { + smtp->rcpt = smtp->rcpt->next; + + if(smtp->rcpt) { + /* Send the next command */ + result = smtp_perform_command(conn); + } + else + /* End of DO phase */ + state(conn, SMTP_STOP); + } + else + /* End of DO phase */ + state(conn, SMTP_STOP); + } + } + + return result; +} + +/* For MAIL responses */ +static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "MAIL failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else + /* Start the RCPT TO command */ + result = smtp_perform_rcpt_to(conn); + + return result; +} + +/* For RCPT responses */ +static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + + (void)instate; /* no use for this yet */ + + if(smtpcode/100 != 2) { + failf(data, "RCPT failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else { + smtp->rcpt = smtp->rcpt->next; + + if(smtp->rcpt) + /* Send the next RCPT TO command */ + result = smtp_perform_rcpt_to(conn); + else { + /* Send the DATA command */ + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA"); + + if(!result) + state(conn, SMTP_DATA); + } + } + + return result; +} + +/* For DATA response */ +static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 354) { + failf(data, "DATA failed: %d", smtpcode); + result = CURLE_SEND_ERROR; + } + else { + /* Set the progress upload size */ + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* SMTP upload */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* End of DO phase */ + state(conn, SMTP_STOP); + } + + return result; +} + +/* For POSTDATA responses, which are received after the entire DATA + part has been sent to the server */ +static CURLcode smtp_state_postdata_resp(struct connectdata *conn, + int smtpcode, + smtpstate instate) +{ + CURLcode result = CURLE_OK; + + (void)instate; /* no use for this yet */ + + if(smtpcode != 250) + result = CURLE_RECV_ERROR; + + /* End of DONE phase */ + state(conn, SMTP_STOP); + + return result; +} + +static CURLcode smtp_statemach_act(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data = conn->data; + int smtpcode; + struct smtp_conn *smtpc = &conn->proto.smtpc; + struct pingpong *pp = &smtpc->pp; + size_t nread = 0; + + /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */ + if(smtpc->state == SMTP_UPGRADETLS) + return smtp_perform_upgrade_tls(conn); + + /* Flush any data that needs to be sent */ + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + do { + /* Read the response from the server */ + result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); + if(result) + return result; + + /* Store the latest response for later retrieval if necessary */ + if(smtpc->state != SMTP_QUIT && smtpcode != 1) + data->info.httpcode = smtpcode; + + if(!smtpcode) + break; + + /* We have now received a full SMTP server response */ + switch(smtpc->state) { + case SMTP_SERVERGREET: + result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_EHLO: + result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_HELO: + result = smtp_state_helo_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_STARTTLS: + result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_AUTH: + result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_COMMAND: + result = smtp_state_command_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_MAIL: + result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_RCPT: + result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_DATA: + result = smtp_state_data_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_POSTDATA: + result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state); + break; + + case SMTP_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, SMTP_STOP); + break; + } + } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp)); + + return result; +} + +/* Called repeatedly until done from multi.c */ +static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); + if(result || !smtpc->ssldone) + return result; + } + + result = Curl_pp_statemach(&smtpc->pp, FALSE, FALSE); + *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode smtp_block_statemach(struct connectdata *conn, + bool disconnecting) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + + while(smtpc->state != SMTP_STOP && !result) + result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting); + + return result; +} + +/* Allocate and initialize the SMTP struct for the current Curl_easy if + required */ +static CURLcode smtp_init(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp; + + smtp = data->req.protop = calloc(sizeof(struct SMTP), 1); + if(!smtp) + result = CURLE_OUT_OF_MEMORY; + + return result; +} + +/* For the SMTP "protocol connect" and "doing" phases only */ +static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.smtpc.pp, socks, numsocks); +} + +/*********************************************************************** + * + * smtp_connect() + * + * This function should do everything that is to be considered a part of + * the connection phase. + * + * The variable pointed to by 'done' will be TRUE if the protocol-layer + * connect phase is done when this function returns, or FALSE if not. + */ +static CURLcode smtp_connect(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + struct pingpong *pp = &smtpc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections in SMTP */ + connkeep(conn, "SMTP default"); + + /* Set the default response time-out */ + pp->response_time = RESP_TIMEOUT; + pp->statemach_act = smtp_statemach_act; + pp->endofresp = smtp_endofresp; + pp->conn = conn; + + /* Initialize the SASL storage */ + Curl_sasl_init(&smtpc->sasl, &saslsmtp); + + /* Initialise the pingpong layer */ + Curl_pp_init(pp); + + /* Parse the URL options */ + result = smtp_parse_url_options(conn); + if(result) + return result; + + /* Parse the URL path */ + result = smtp_parse_url_path(conn); + if(result) + return result; + + /* Start off waiting for the server greeting response */ + state(conn, SMTP_SERVERGREET); + + result = smtp_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * smtp_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode smtp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + struct pingpong *pp = &conn->proto.smtpc.pp; + char *eob; + ssize_t len; + ssize_t bytes_written; + + (void)premature; + + if(!smtp || !pp->conn) + return CURLE_OK; + + /* Cleanup our per-request based variables */ + Curl_safefree(smtp->custom); + + if(status) { + connclose(conn, "SMTP done with bad status"); /* marked for closure */ + result = status; /* use the already set error code */ + } + else if(!data->set.connect_only && data->set.mail_rcpt && + (data->set.upload || data->set.mimepost.kind)) { + /* Calculate the EOB taking into account any terminating CRLF from the + previous line of the email or the CRLF of the DATA command when there + is "no mail data". RFC-5321, sect. 4.1.1.4. + + Note: As some SSL backends, such as OpenSSL, will cause Curl_write() to + fail when using a different pointer following a previous write, that + returned CURLE_AGAIN, we duplicate the EOB now rather than when the + bytes written doesn't equal len. */ + if(smtp->trailing_crlf || !conn->data->state.infilesize) { + eob = strdup(&SMTP_EOB[2]); + len = SMTP_EOB_LEN - 2; + } + else { + eob = strdup(SMTP_EOB); + len = SMTP_EOB_LEN; + } + + if(!eob) + return CURLE_OUT_OF_MEMORY; + + /* Send the end of block data */ + result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written); + if(result) { + free(eob); + return result; + } + + if(bytes_written != len) { + /* The whole chunk was not sent so keep it around and adjust the + pingpong structure accordingly */ + pp->sendthis = eob; + pp->sendsize = len; + pp->sendleft = len - bytes_written; + } + else { + /* Successfully sent so adjust the response timeout relative to now */ + pp->response = Curl_now(); + + free(eob); + } + + state(conn, SMTP_POSTDATA); + + /* Run the state-machine */ + result = smtp_block_statemach(conn, FALSE); + } + + /* Clear the transfer mode for the next request */ + smtp->transfer = FTPTRANSFER_BODY; + + return result; +} + +/*********************************************************************** + * + * smtp_perform() + * + * This is the actual DO function for SMTP. Transfer a mail, send a command + * or get some data according to the options previously setup. + */ +static CURLcode smtp_perform(struct connectdata *conn, bool *connected, + bool *dophase_done) +{ + /* This is SMTP and no proxy */ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(data->set.opt_no_body) { + /* Requested no body means no transfer */ + smtp->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* Store the first recipient (or NULL if not specified) */ + smtp->rcpt = data->set.mail_rcpt; + + /* Initial data character is the first character in line: it is implicitly + preceded by a virtual CRLF. */ + smtp->trailing_crlf = TRUE; + smtp->eob = 2; + + /* Start the first command in the DO phase */ + if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt) + /* MAIL transfer */ + result = smtp_perform_mail(conn); + else + /* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */ + result = smtp_perform_command(conn); + + if(result) + return result; + + /* Run the state-machine */ + result = smtp_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + +/*********************************************************************** + * + * smtp_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (smtp_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode smtp_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + *done = FALSE; /* default to false */ + + /* Parse the custom request */ + result = smtp_parse_custom_request(conn); + if(result) + return result; + + result = smtp_regular_transfer(conn, done); + + return result; +} + +/*********************************************************************** + * + * smtp_disconnect() + * + * Disconnect from an SMTP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct smtp_conn *smtpc = &conn->proto.smtpc; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. */ + + /* The SMTP session may or may not have been allocated/setup at this + point! */ + if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart) + if(!smtp_perform_quit(conn)) + (void)smtp_block_statemach(conn, TRUE); /* ignore errors on QUIT */ + + /* Disconnect from the server */ + Curl_pp_disconnect(&smtpc->pp); + + /* Cleanup the SASL module */ + Curl_sasl_cleanup(conn, smtpc->sasl.authused); + + /* Cleanup our connection based variables */ + Curl_safefree(smtpc->domain); + + return CURLE_OK; +} + +/* Call this when the DO phase has completed */ +static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected) +{ + struct SMTP *smtp = conn->data->req.protop; + + (void)connected; + + if(smtp->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + + return CURLE_OK; +} + +/* Called from multi.c while DOing */ +static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = smtp_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = smtp_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/*********************************************************************** + * + * smtp_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + */ +static CURLcode smtp_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + bool connected = FALSE; + struct Curl_easy *data = conn->data; + + /* Make sure size is unknown at this point */ + data->req.size = -1; + + /* Set the progress data */ + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + /* Carry out the perform */ + result = smtp_perform(conn, &connected, dophase_done); + + /* Perform post DO phase operations if necessary */ + if(!result && *dophase_done) + result = smtp_dophase_done(conn, connected); + + return result; +} + +static CURLcode smtp_setup_connection(struct connectdata *conn) +{ + CURLcode result; + + /* Clear the TLS upgraded flag */ + conn->tls_upgraded = FALSE; + + /* Initialise the SMTP layer */ + result = smtp_init(conn); + if(result) + return result; + + return CURLE_OK; +} + +/*********************************************************************** + * + * smtp_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode smtp_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *ptr = conn->options; + + smtpc->sasl.resetprefs = TRUE; + + while(!result && ptr && *ptr) { + const char *key = ptr; + const char *value; + + while(*ptr && *ptr != '=') + ptr++; + + value = ptr + 1; + + while(*ptr && *ptr != ';') + ptr++; + + if(strncasecompare(key, "AUTH=", 5)) + result = Curl_sasl_parse_url_auth_option(&smtpc->sasl, + value, ptr - value); + else + result = CURLE_URL_MALFORMAT; + + if(*ptr == ';') + ptr++; + } + + return result; +} + +/*********************************************************************** + * + * smtp_parse_url_path() + * + * Parse the URL path into separate path components. + */ +static CURLcode smtp_parse_url_path(struct connectdata *conn) +{ + /* The SMTP struct is already initialised in smtp_connect() */ + struct Curl_easy *data = conn->data; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *path = &data->state.up.path[1]; /* skip leading path */ + char localhost[HOSTNAME_MAX + 1]; + + /* Calculate the path if necessary */ + if(!*path) { + if(!Curl_gethostname(localhost, sizeof(localhost))) + path = localhost; + else + path = "localhost"; + } + + /* URL decode the path and use it as the domain in our EHLO */ + return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); +} + +/*********************************************************************** + * + * smtp_parse_custom_request() + * + * Parse the custom request. + */ +static CURLcode smtp_parse_custom_request(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + const char *custom = data->set.str[STRING_CUSTOMREQUEST]; + + /* URL decode the custom request */ + if(custom) + result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE); + + return result; +} + +CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) +{ + /* When sending a SMTP payload we must detect CRLF. sequences making sure + they are sent as CRLF.. instead, as a . on the beginning of a line will + be deleted by the server when not part of an EOB terminator and a + genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of + data by the server + */ + ssize_t i; + ssize_t si; + struct Curl_easy *data = conn->data; + struct SMTP *smtp = data->req.protop; + char *scratch = data->state.scratch; + char *newscratch = NULL; + char *oldscratch = NULL; + size_t eob_sent; + + /* Do we need to allocate a scratch buffer? */ + if(!scratch || data->set.crlf) { + oldscratch = scratch; + + scratch = newscratch = malloc(2 * data->set.upload_buffer_size); + if(!newscratch) { + failf(data, "Failed to alloc scratch buffer!"); + + return CURLE_OUT_OF_MEMORY; + } + } + DEBUGASSERT(data->set.upload_buffer_size >= (size_t)nread); + + /* Have we already sent part of the EOB? */ + eob_sent = smtp->eob; + + /* This loop can be improved by some kind of Boyer-Moore style of + approach but that is saved for later... */ + for(i = 0, si = 0; i < nread; i++) { + if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) { + smtp->eob++; + + /* Is the EOB potentially the terminating CRLF? */ + if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob) + smtp->trailing_crlf = TRUE; + else + smtp->trailing_crlf = FALSE; + } + else if(smtp->eob) { + /* A previous substring matched so output that first */ + memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent); + si += smtp->eob - eob_sent; + + /* Then compare the first byte */ + if(SMTP_EOB[0] == data->req.upload_fromhere[i]) + smtp->eob = 1; + else + smtp->eob = 0; + + eob_sent = 0; + + /* Reset the trailing CRLF flag as there was more data */ + smtp->trailing_crlf = FALSE; + } + + /* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */ + if(SMTP_EOB_FIND_LEN == smtp->eob) { + /* Copy the replacement data to the target buffer */ + memcpy(&scratch[si], &SMTP_EOB_REPL[eob_sent], + SMTP_EOB_REPL_LEN - eob_sent); + si += SMTP_EOB_REPL_LEN - eob_sent; + smtp->eob = 0; + eob_sent = 0; + } + else if(!smtp->eob) + scratch[si++] = data->req.upload_fromhere[i]; + } + + if(smtp->eob - eob_sent) { + /* A substring matched before processing ended so output that now */ + memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent); + si += smtp->eob - eob_sent; + } + + /* Only use the new buffer if we replaced something */ + if(si != nread) { + /* Upload from the new (replaced) buffer instead */ + data->req.upload_fromhere = scratch; + + /* Save the buffer so it can be freed later */ + data->state.scratch = scratch; + + /* Free the old scratch buffer */ + free(oldscratch); + + /* Set the new amount too */ + data->req.upload_present = si; + } + else + free(newscratch); + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_SMTP */ diff --git a/libcurl/lib/smtp.h b/libcurl/lib/smtp.h new file mode 100644 index 0000000..b67340a --- /dev/null +++ b/libcurl/lib/smtp.h @@ -0,0 +1,91 @@ +#ifndef HEADER_CURL_SMTP_H +#define HEADER_CURL_SMTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * SMTP unique setup + ***************************************************************************/ +typedef enum { + SMTP_STOP, /* do nothing state, stops the state machine */ + SMTP_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + SMTP_EHLO, + SMTP_HELO, + SMTP_STARTTLS, + SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + SMTP_AUTH, + SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */ + SMTP_MAIL, /* MAIL FROM */ + SMTP_RCPT, /* RCPT TO */ + SMTP_DATA, + SMTP_POSTDATA, + SMTP_QUIT, + SMTP_LAST /* never used */ +} smtpstate; + +/* This SMTP struct is used in the Curl_easy. All SMTP data that is + connection-oriented must be in smtp_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct SMTP { + curl_pp_transfer transfer; + char *custom; /* Custom Request */ + struct curl_slist *rcpt; /* Recipient list */ + size_t eob; /* Number of bytes of the EOB (End Of Body) that + have been received so far */ + bool trailing_crlf; /* Specifies if the tailing CRLF is present */ +}; + +/* smtp_conn is used for struct connection-oriented data in the connectdata + struct */ +struct smtp_conn { + struct pingpong pp; + smtpstate state; /* Always use smtp.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + char *domain; /* Client address/name to send in the EHLO */ + struct SASL sasl; /* SASL-related storage */ + bool tls_supported; /* StartTLS capability supported by server */ + bool size_supported; /* If server supports SIZE extension according to + RFC 1870 */ + bool auth_supported; /* AUTH capability supported by server */ +}; + +extern const struct Curl_handler Curl_handler_smtp; +extern const struct Curl_handler Curl_handler_smtps; + +/* this is the 5-bytes End-Of-Body marker for SMTP */ +#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a" +#define SMTP_EOB_LEN 5 +#define SMTP_EOB_FIND_LEN 3 + +/* if found in data, replace it with this string instead */ +#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e" +#define SMTP_EOB_REPL_LEN 4 + +CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread); + +#endif /* HEADER_CURL_SMTP_H */ diff --git a/libcurl/lib/sockaddr.h b/libcurl/lib/sockaddr.h new file mode 100644 index 0000000..db14680 --- /dev/null +++ b/libcurl/lib/sockaddr.h @@ -0,0 +1,42 @@ +#ifndef HEADER_CURL_SOCKADDR_H +#define HEADER_CURL_SOCKADDR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +struct Curl_sockaddr_storage { + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sa_in6; +#endif +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE + struct sockaddr_storage sa_stor; +#else + char cbuf[256]; /* this should be big enough to fit a lot */ +#endif + } buffer; +}; + +#endif /* HEADER_CURL_SOCKADDR_H */ diff --git a/libcurl/lib/socks.c b/libcurl/lib/socks.c new file mode 100644 index 0000000..d8fcc3b --- /dev/null +++ b/libcurl/lib/socks.c @@ -0,0 +1,803 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_PROXY) + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "connect.h" +#include "timeval.h" +#include "socks.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * Helper read-from-socket functions. Does the same as Curl_read() but it + * blocks until all bytes amount of buffersize will be read. No more, no less. + * + * This is STUPID BLOCKING behaviour which we frown upon, but right now this + * is what we have... + */ +int Curl_blockread_all(struct connectdata *conn, /* connection data */ + curl_socket_t sockfd, /* read from this socket */ + char *buf, /* store read data here */ + ssize_t buffersize, /* max amount to read */ + ssize_t *n) /* amount bytes read */ +{ + ssize_t nread = 0; + ssize_t allread = 0; + int result; + *n = 0; + for(;;) { + timediff_t timeleft = Curl_timeleft(conn->data, NULL, TRUE); + if(timeleft < 0) { + /* we already got the timeout */ + result = CURLE_OPERATION_TIMEDOUT; + break; + } + if(SOCKET_READABLE(sockfd, timeleft) <= 0) { + result = ~CURLE_OK; + break; + } + result = Curl_read_plain(sockfd, buf, buffersize, &nread); + if(CURLE_AGAIN == result) + continue; + if(result) + break; + + if(buffersize == nread) { + allread += nread; + *n = allread; + result = CURLE_OK; + break; + } + if(!nread) { + result = ~CURLE_OK; + break; + } + + buffersize -= nread; + buf += nread; + allread += nread; + } + return result; +} + +/* +* This function logs in to a SOCKS4 proxy and sends the specifics to the final +* destination server. +* +* Reference : +* https://www.openssh.com/txt/socks4.protocol +* +* Note : +* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)" +* Nonsupport "Identification Protocol (RFC1413)" +*/ +CURLcode Curl_SOCKS4(const char *proxy_user, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn) +{ + const bool protocol4a = + (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE; +#define SOCKS4REQLEN 262 + unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user + id */ + CURLcode code; + curl_socket_t sock = conn->sock[sockindex]; + struct Curl_easy *data = conn->data; + + if(Curl_timeleft(data, NULL, TRUE) < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", + protocol4a ? "a" : "", hostname, remote_port); + + (void)curlx_nonblock(sock, FALSE); + + infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); + + /* + * Compose socks4 request + * + * Request format + * + * +----+----+----+----+----+----+----+----+----+----+....+----+ + * | VN | CD | DSTPORT | DSTIP | USERID |NULL| + * +----+----+----+----+----+----+----+----+----+----+....+----+ + * # of bytes: 1 1 2 4 variable 1 + */ + + socksreq[0] = 4; /* version (SOCKS4) */ + socksreq[1] = 1; /* connect */ + socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ + socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + + /* DNS resolve only for SOCKS4, not SOCKS4a */ + if(!protocol4a) { + struct Curl_dns_entry *dns; + Curl_addrinfo *hp = NULL; + int rc; + + rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns); + + if(rc == CURLRESOLV_ERROR) + return CURLE_COULDNT_RESOLVE_PROXY; + + if(rc == CURLRESOLV_PENDING) + /* ignores the return code, but 'dns' remains NULL on failure */ + (void)Curl_resolver_wait_resolv(conn, &dns); + + /* + * We cannot use 'hostent' as a struct that Curl_resolv() returns. It + * returns a Curl_addrinfo pointer that may not always look the same. + */ + if(dns) + hp = dns->addr; + if(hp) { + char buf[64]; + Curl_printable_address(hp, buf, sizeof(buf)); + + if(hp->ai_family == AF_INET) { + struct sockaddr_in *saddr_in; + + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; + socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0]; + socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1]; + socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2]; + socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3]; + + infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf); + } + else { + hp = NULL; /* fail! */ + + failf(data, "SOCKS4 connection to %s not supported\n", buf); + } + + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + } + if(!hp) { + failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.", + hostname); + return CURLE_COULDNT_RESOLVE_HOST; + } + } + + /* + * This is currently not supporting "Identification Protocol (RFC1413)". + */ + socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ + if(proxy_user) { + size_t plen = strlen(proxy_user); + if(plen >= sizeof(socksreq) - 8) { + failf(data, "Too long SOCKS proxy name, can't use!\n"); + return CURLE_COULDNT_CONNECT; + } + /* copy the proxy name WITH trailing zero */ + memcpy(socksreq + 8, proxy_user, plen + 1); + } + + /* + * Make connection + */ + { + int result; + ssize_t actualread; + ssize_t written; + ssize_t hostnamelen = 0; + ssize_t packetsize = 9 + + strlen((char *)socksreq + 8); /* size including NUL */ + + /* If SOCKS4a, set special invalid IP address 0.0.0.x */ + if(protocol4a) { + socksreq[4] = 0; + socksreq[5] = 0; + socksreq[6] = 0; + socksreq[7] = 1; + /* If still enough room in buffer, also append hostname */ + hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ + if(packetsize + hostnamelen <= SOCKS4REQLEN) + strcpy((char *)socksreq + packetsize, hostname); + else + hostnamelen = 0; /* Flag: hostname did not fit in buffer */ + } + + /* Send request */ + code = Curl_write_plain(conn, sock, (char *)socksreq, + packetsize + hostnamelen, + &written); + if(code || (written != packetsize + hostnamelen)) { + failf(data, "Failed to send SOCKS4 connect request."); + return CURLE_COULDNT_CONNECT; + } + if(protocol4a && hostnamelen == 0) { + /* SOCKS4a with very long hostname - send that name separately */ + hostnamelen = (ssize_t)strlen(hostname) + 1; + code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen, + &written); + if(code || (written != hostnamelen)) { + failf(data, "Failed to send SOCKS4 connect request."); + return CURLE_COULDNT_CONNECT; + } + } + + packetsize = 8; /* receive data size */ + + /* Receive response */ + result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize, + &actualread); + if(result || (actualread != packetsize)) { + failf(data, "Failed to receive SOCKS4 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + + /* + * Response format + * + * +----+----+----+----+----+----+----+----+ + * | VN | CD | DSTPORT | DSTIP | + * +----+----+----+----+----+----+----+----+ + * # of bytes: 1 1 2 4 + * + * VN is the version of the reply code and should be 0. CD is the result + * code with one of the following values: + * + * 90: request granted + * 91: request rejected or failed + * 92: request rejected because SOCKS server cannot connect to + * identd on the client + * 93: request rejected because the client program and identd + * report different user-ids + */ + + /* wrong version ? */ + if(socksreq[0] != 0) { + failf(data, + "SOCKS4 reply has wrong version, version should be 0."); + return CURLE_COULDNT_CONNECT; + } + + /* Result */ + switch(socksreq[1]) { + case 90: + infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":""); + break; + case 91: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected or failed.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + case 92: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected because SOCKS server cannot connect to " + "identd on the client.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + case 93: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", request rejected because the client program and identd " + "report different user-ids.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + default: + failf(data, + "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" + ", Unknown.", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]), + (unsigned char)socksreq[1]); + return CURLE_COULDNT_CONNECT; + } + } + + (void)curlx_nonblock(sock, TRUE); + + return CURLE_OK; /* Proxy was successful! */ +} + +/* + * This function logs in to a SOCKS5 proxy and sends the specifics to the final + * destination server. + */ +CURLcode Curl_SOCKS5(const char *proxy_user, + const char *proxy_password, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn) +{ + /* + According to the RFC1928, section "6. Replies". This is what a SOCK5 + replies: + + +----+-----+-------+------+----------+----------+ + |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + Where: + + o VER protocol version: X'05' + o REP Reply field: + o X'00' succeeded + */ + + unsigned char socksreq[600]; /* room for large user/pw (255 max each) */ + int idx; + ssize_t actualread; + ssize_t written; + int result; + CURLcode code; + curl_socket_t sock = conn->sock[sockindex]; + struct Curl_easy *data = conn->data; + timediff_t timeout; + bool socks5_resolve_local = + (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE; + const size_t hostname_len = strlen(hostname); + ssize_t len = 0; + const unsigned long auth = data->set.socks5auth; + bool allow_gssapi = FALSE; + + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n", + hostname, remote_port); + + /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ + if(!socks5_resolve_local && hostname_len > 255) { + infof(conn->data, "SOCKS5: server resolving disabled for hostnames of " + "length > 255 [actual len=%zu]\n", hostname_len); + socks5_resolve_local = TRUE; + } + + /* get timeout */ + timeout = Curl_timeleft(data, NULL, TRUE); + + if(timeout < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + (void)curlx_nonblock(sock, TRUE); + + /* wait until socket gets connected */ + result = SOCKET_WRITABLE(sock, timeout); + + if(-1 == result) { + failf(conn->data, "SOCKS5: no connection here"); + return CURLE_COULDNT_CONNECT; + } + if(0 == result) { + failf(conn->data, "SOCKS5: connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(result & CURL_CSELECT_ERR) { + failf(conn->data, "SOCKS5: error occurred during connection"); + return CURLE_COULDNT_CONNECT; + } + + if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) + infof(conn->data, + "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n", + auth); + if(!(auth & CURLAUTH_BASIC)) + /* disable username/password auth */ + proxy_user = NULL; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(auth & CURLAUTH_GSSAPI) + allow_gssapi = TRUE; +#endif + + idx = 0; + socksreq[idx++] = 5; /* version */ + idx++; /* reserve for the number of authentication methods */ + socksreq[idx++] = 0; /* no authentication */ + if(allow_gssapi) + socksreq[idx++] = 1; /* GSS-API */ + if(proxy_user) + socksreq[idx++] = 2; /* username/password */ + /* write the number of authentication methods */ + socksreq[1] = (unsigned char) (idx - 2); + + (void)curlx_nonblock(sock, FALSE); + + infof(data, "SOCKS5 communication to %s:%d\n", hostname, remote_port); + + code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]), + &written); + if(code || (written != (2 + (int)socksreq[1]))) { + failf(data, "Unable to send initial SOCKS5 request."); + return CURLE_COULDNT_CONNECT; + } + + (void)curlx_nonblock(sock, TRUE); + + result = SOCKET_READABLE(sock, timeout); + + if(-1 == result) { + failf(conn->data, "SOCKS5 nothing to read"); + return CURLE_COULDNT_CONNECT; + } + if(0 == result) { + failf(conn->data, "SOCKS5 read timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(result & CURL_CSELECT_ERR) { + failf(conn->data, "SOCKS5 read error occurred"); + return CURLE_RECV_ERROR; + } + + (void)curlx_nonblock(sock, FALSE); + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread); + if(result || (actualread != 2)) { + failf(data, "Unable to receive initial SOCKS5 response."); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[0] != 5) { + failf(data, "Received invalid version in initial SOCKS5 response."); + return CURLE_COULDNT_CONNECT; + } + if(socksreq[1] == 0) { + /* Nothing to do, no authentication needed */ + ; + } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + else if(allow_gssapi && (socksreq[1] == 1)) { + code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn); + if(code) { + failf(data, "Unable to negotiate SOCKS5 GSS-API context."); + return CURLE_COULDNT_CONNECT; + } + } +#endif + else if(socksreq[1] == 2) { + /* Needs user name and password */ + size_t proxy_user_len, proxy_password_len; + if(proxy_user && proxy_password) { + proxy_user_len = strlen(proxy_user); + proxy_password_len = strlen(proxy_password); + } + else { + proxy_user_len = 0; + proxy_password_len = 0; + } + + /* username/password request looks like + * +----+------+----------+------+----------+ + * |VER | ULEN | UNAME | PLEN | PASSWD | + * +----+------+----------+------+----------+ + * | 1 | 1 | 1 to 255 | 1 | 1 to 255 | + * +----+------+----------+------+----------+ + */ + len = 0; + socksreq[len++] = 1; /* username/pw subnegotiation version */ + socksreq[len++] = (unsigned char) proxy_user_len; + if(proxy_user && proxy_user_len) { + /* the length must fit in a single byte */ + if(proxy_user_len >= 255) { + failf(data, "Excessive user name length for proxy auth"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + memcpy(socksreq + len, proxy_user, proxy_user_len); + } + len += proxy_user_len; + socksreq[len++] = (unsigned char) proxy_password_len; + if(proxy_password && proxy_password_len) { + /* the length must fit in a single byte */ + if(proxy_password_len > 255) { + failf(data, "Excessive password length for proxy auth"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + memcpy(socksreq + len, proxy_password, proxy_password_len); + } + len += proxy_password_len; + + code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); + if(code || (len != written)) { + failf(data, "Failed to send SOCKS5 sub-negotiation request."); + return CURLE_COULDNT_CONNECT; + } + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread); + if(result || (actualread != 2)) { + failf(data, "Unable to receive SOCKS5 sub-negotiation response."); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] != 0) { /* status */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + return CURLE_COULDNT_CONNECT; + } + + /* Everything is good so far, user was authenticated! */ + } + else { + /* error */ + if(!allow_gssapi && (socksreq[1] == 1)) { + failf(data, + "SOCKS5 GSSAPI per-message authentication is not supported."); + return CURLE_COULDNT_CONNECT; + } + if(socksreq[1] == 255) { + if(!proxy_user || !*proxy_user) { + failf(data, + "No authentication method was acceptable. (It is quite likely" + " that the SOCKS5 server wanted a username/password, since none" + " was supplied to the server on this connection.)"); + } + else { + failf(data, "No authentication method was acceptable."); + } + return CURLE_COULDNT_CONNECT; + } + else { + failf(data, + "Undocumented SOCKS5 mode attempted to be used by server."); + return CURLE_COULDNT_CONNECT; + } + } + + /* Authentication is complete, now specify destination to the proxy */ + len = 0; + socksreq[len++] = 5; /* version (SOCKS5) */ + socksreq[len++] = 1; /* connect */ + socksreq[len++] = 0; /* must be zero */ + + if(!socks5_resolve_local) { + socksreq[len++] = 3; /* ATYP: domain name = 3 */ + socksreq[len++] = (char) hostname_len; /* address length */ + memcpy(&socksreq[len], hostname, hostname_len); /* address str w/o NULL */ + len += hostname_len; + } + else { + struct Curl_dns_entry *dns; + Curl_addrinfo *hp = NULL; + int rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns); + + if(rc == CURLRESOLV_ERROR) + return CURLE_COULDNT_RESOLVE_HOST; + + if(rc == CURLRESOLV_PENDING) { + /* this requires that we're in "wait for resolve" state */ + code = Curl_resolver_wait_resolv(conn, &dns); + if(code) + return code; + } + + /* + * We cannot use 'hostent' as a struct that Curl_resolv() returns. It + * returns a Curl_addrinfo pointer that may not always look the same. + */ + if(dns) + hp = dns->addr; + if(hp) { + char buf[64]; + Curl_printable_address(hp, buf, sizeof(buf)); + + if(hp->ai_family == AF_INET) { + int i; + struct sockaddr_in *saddr_in; + socksreq[len++] = 1; /* ATYP: IPv4 = 1 */ + + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; + for(i = 0; i < 4; i++) { + socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i]; + } + + infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf); + } +#ifdef ENABLE_IPV6 + else if(hp->ai_family == AF_INET6) { + int i; + struct sockaddr_in6 *saddr_in6; + socksreq[len++] = 4; /* ATYP: IPv6 = 4 */ + + saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr; + for(i = 0; i < 16; i++) { + socksreq[len++] = + ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i]; + } + + infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf); + } +#endif + else { + hp = NULL; /* fail! */ + + failf(data, "SOCKS5 connection to %s not supported\n", buf); + } + + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + } + if(!hp) { + failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", + hostname); + return CURLE_COULDNT_RESOLVE_HOST; + } + } + + socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ + socksreq[len++] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 GSS-API protection not yet implemented."); + } + else +#endif + code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); + + if(code || (len != written)) { + failf(data, "Failed to send SOCKS5 connect request."); + return CURLE_COULDNT_CONNECT; + } + + len = 10; /* minimum packet size is 10 */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(conn->socks5_gssapi_enctype) { + failf(data, "SOCKS5 GSS-API protection not yet implemented."); + } + else +#endif + result = Curl_blockread_all(conn, sock, (char *)socksreq, + len, &actualread); + + if(result || (len != actualread)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[0] != 5) { /* version */ + failf(data, + "SOCKS5 reply has wrong version, version should be 5."); + return CURLE_COULDNT_CONNECT; + } + + /* Fix: in general, returned BND.ADDR is variable length parameter by RFC + 1928, so the reply packet should be read until the end to avoid errors at + subsequent protocol level. + + +----+-----+-------+------+----------+----------+ + |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + ATYP: + o IP v4 address: X'01', BND.ADDR = 4 byte + o domain name: X'03', BND.ADDR = [ 1 byte length, string ] + o IP v6 address: X'04', BND.ADDR = 16 byte + */ + + /* Calculate real packet size */ + if(socksreq[3] == 3) { + /* domain name */ + int addrlen = (int) socksreq[4]; + len = 5 + addrlen + 2; + } + else if(socksreq[3] == 4) { + /* IPv6 */ + len = 4 + 16 + 2; + } + + /* At this point we already read first 10 bytes */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + if(!conn->socks5_gssapi_enctype) { + /* decrypt_gssapi_blockread already read the whole packet */ +#endif + if(len > 10) { + result = Curl_blockread_all(conn, sock, (char *)&socksreq[10], + len - 10, &actualread); + if(result || ((len - 10) != actualread)) { + failf(data, "Failed to receive SOCKS5 connect request ack."); + return CURLE_COULDNT_CONNECT; + } + } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + } +#endif + + if(socksreq[1] != 0) { /* Anything besides 0 is an error */ + if(socksreq[3] == 1) { + failf(data, + "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (((unsigned char)socksreq[8] << 8) | + (unsigned char)socksreq[9]), + (unsigned char)socksreq[1]); + } + else if(socksreq[3] == 3) { + unsigned char port_upper = (unsigned char)socksreq[len - 2]; + socksreq[len - 2] = 0; + failf(data, + "Can't complete SOCKS5 connection to %s:%d. (%d)", + (char *)&socksreq[5], + ((port_upper << 8) | + (unsigned char)socksreq[len - 1]), + (unsigned char)socksreq[1]); + socksreq[len - 2] = port_upper; + } + else if(socksreq[3] == 4) { + failf(data, + "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:" + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (unsigned char)socksreq[8], (unsigned char)socksreq[9], + (unsigned char)socksreq[10], (unsigned char)socksreq[11], + (unsigned char)socksreq[12], (unsigned char)socksreq[13], + (unsigned char)socksreq[14], (unsigned char)socksreq[15], + (unsigned char)socksreq[16], (unsigned char)socksreq[17], + (unsigned char)socksreq[18], (unsigned char)socksreq[19], + (((unsigned char)socksreq[20] << 8) | + (unsigned char)socksreq[21]), + (unsigned char)socksreq[1]); + } + return CURLE_COULDNT_CONNECT; + } + infof(data, "SOCKS5 request granted.\n"); + + (void)curlx_nonblock(sock, TRUE); + return CURLE_OK; /* Proxy was successful! */ +} + +#endif /* CURL_DISABLE_PROXY */ diff --git a/libcurl/lib/socks.h b/libcurl/lib/socks.h new file mode 100644 index 0000000..daa07c1 --- /dev/null +++ b/libcurl/lib/socks.h @@ -0,0 +1,75 @@ +#ifndef HEADER_CURL_SOCKS_H +#define HEADER_CURL_SOCKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DISABLE_PROXY +#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN +#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN +#else +/* + * Helper read-from-socket functions. Does the same as Curl_read() but it + * blocks until all bytes amount of buffersize will be read. No more, no less. + * + * This is STUPID BLOCKING behaviour which we frown upon, but right now this + * is what we have... + */ +int Curl_blockread_all(struct connectdata *conn, + curl_socket_t sockfd, + char *buf, + ssize_t buffersize, + ssize_t *n); + +/* + * This function logs in to a SOCKS4(a) proxy and sends the specifics to the + * final destination server. + */ +CURLcode Curl_SOCKS4(const char *proxy_name, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn); + +/* + * This function logs in to a SOCKS5 proxy and sends the specifics to the + * final destination server. + */ +CURLcode Curl_SOCKS5(const char *proxy_name, + const char *proxy_password, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn); + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) +/* + * This function handles the SOCKS5 GSS-API negotiation and initialisation + */ +CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn); +#endif + +#endif /* CURL_DISABLE_PROXY */ + +#endif /* HEADER_CURL_SOCKS_H */ diff --git a/libcurl/lib/socks_gssapi.c b/libcurl/lib/socks_gssapi.c new file mode 100644 index 0000000..65294bb --- /dev/null +++ b/libcurl/lib/socks_gssapi.c @@ -0,0 +1,527 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009, Markus Moeller, + * Copyright (C) 2012 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_PROXY) + +#include "curl_gssapi.h" +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "timeval.h" +#include "socks.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; + +/* + * Helper GSS-API error functions. + */ +static int check_gss_err(struct Curl_easy *data, + OM_uint32 major_status, + OM_uint32 minor_status, + const char *function) +{ + if(GSS_ERROR(major_status)) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char buf[1024]; + size_t len; + + len = 0; + msg_ctx = 0; + while(!msg_ctx) { + /* convert major status code (GSS-API error) to text */ + maj_stat = gss_display_status(&min_stat, major_status, + GSS_C_GSS_CODE, + GSS_C_NULL_OID, + &msg_ctx, &status_string); + if(maj_stat == GSS_S_COMPLETE) { + if(sizeof(buf) > len + status_string.length + 1) { + strcpy(buf + len, (char *) status_string.value); + len += status_string.length; + } + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + if(sizeof(buf) > len + 3) { + strcpy(buf + len, ".\n"); + len += 2; + } + msg_ctx = 0; + while(!msg_ctx) { + /* convert minor status code (underlying routine error) to text */ + maj_stat = gss_display_status(&min_stat, minor_status, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, &status_string); + if(maj_stat == GSS_S_COMPLETE) { + if(sizeof(buf) > len + status_string.length) + strcpy(buf + len, (char *) status_string.value); + gss_release_buffer(&min_stat, &status_string); + break; + } + gss_release_buffer(&min_stat, &status_string); + } + failf(data, "GSS-API error: %s failed:\n%s", function, buf); + return 1; + } + + return 0; +} + +CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sock = conn->sock[sockindex]; + CURLcode code; + ssize_t actualread; + ssize_t written; + int result; + OM_uint32 gss_major_status, gss_minor_status, gss_status; + OM_uint32 gss_ret_flags; + int gss_conf_state, gss_enc; + gss_buffer_desc service = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_send_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_recv_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc gss_w_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc* gss_token = GSS_C_NO_BUFFER; + gss_name_t server = GSS_C_NO_NAME; + gss_name_t gss_client_name = GSS_C_NO_NAME; + unsigned short us_length; + char *user = NULL; + unsigned char socksreq[4]; /* room for GSS-API exchange header only */ + const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ? + data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + const size_t serviceptr_length = strlen(serviceptr); + + /* GSS-API request looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + /* prepare service name */ + if(strchr(serviceptr, '/')) { + service.length = serviceptr_length; + service.value = malloc(service.length); + if(!service.value) + return CURLE_OUT_OF_MEMORY; + memcpy(service.value, serviceptr, service.length); + + gss_major_status = gss_import_name(&gss_minor_status, &service, + (gss_OID) GSS_C_NULL_OID, &server); + } + else { + service.value = malloc(serviceptr_length + + strlen(conn->socks_proxy.host.name) + 2); + if(!service.value) + return CURLE_OUT_OF_MEMORY; + service.length = serviceptr_length + + strlen(conn->socks_proxy.host.name) + 1; + msnprintf(service.value, service.length + 1, "%s@%s", + serviceptr, conn->socks_proxy.host.name); + + gss_major_status = gss_import_name(&gss_minor_status, &service, + GSS_C_NT_HOSTBASED_SERVICE, &server); + } + + gss_release_buffer(&gss_status, &service); /* clear allocated memory */ + + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_import_name()")) { + failf(data, "Failed to create service name."); + gss_release_name(&gss_status, &server); + return CURLE_COULDNT_CONNECT; + } + + /* As long as we need to keep sending some context info, and there's no */ + /* errors, keep sending it... */ + for(;;) { + gss_major_status = Curl_gss_init_sec_context(data, + &gss_minor_status, + &gss_context, + server, + &Curl_krb5_mech_oid, + NULL, + gss_token, + &gss_send_token, + TRUE, + &gss_ret_flags); + + if(gss_token != GSS_C_NO_BUFFER) + gss_release_buffer(&gss_status, &gss_recv_token); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_init_sec_context")) { + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to initial GSS-API token."); + return CURLE_COULDNT_CONNECT; + } + + if(gss_send_token.length != 0) { + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 1; /* authentication message type */ + us_length = htons((short)gss_send_token.length); + memcpy(socksreq + 2, &us_length, sizeof(short)); + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send GSS-API authentication request."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + code = Curl_write_plain(conn, sock, (char *)gss_send_token.value, + gss_send_token.length, &written); + + if(code || ((ssize_t)gss_send_token.length != written)) { + failf(data, "Failed to send GSS-API authentication token."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_send_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + } + + gss_release_buffer(&gss_status, &gss_send_token); + gss_release_buffer(&gss_status, &gss_recv_token); + if(gss_major_status != GSS_S_CONTINUE_NEEDED) break; + + /* analyse response */ + + /* GSS-API response looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive GSS-API authentication response."); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 1) { /* status / messgae type */ + failf(data, "Invalid GSS-API authentication response type (%d %d).", + socksreq[0], socksreq[1]); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq + 2, sizeof(short)); + us_length = ntohs(us_length); + + gss_recv_token.length = us_length; + gss_recv_token.value = malloc(us_length); + if(!gss_recv_token.value) { + failf(data, + "Could not allocate memory for GSS-API authentication " + "response token."); + gss_release_name(&gss_status, &server); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, + gss_recv_token.length, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive GSS-API authentication token."); + gss_release_name(&gss_status, &server); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + gss_token = &gss_recv_token; + } + + gss_release_name(&gss_status, &server); + + /* Everything is good so far, user was authenticated! */ + gss_major_status = gss_inquire_context(&gss_minor_status, gss_context, + &gss_client_name, NULL, NULL, NULL, + NULL, NULL, NULL); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_inquire_context")) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + gss_major_status = gss_display_name(&gss_minor_status, gss_client_name, + &gss_send_token, NULL); + if(check_gss_err(data, gss_major_status, + gss_minor_status, "gss_display_name")) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + user = malloc(gss_send_token.length + 1); + if(!user) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(user, gss_send_token.value, gss_send_token.length); + user[gss_send_token.length] = '\0'; + gss_release_name(&gss_status, &gss_client_name); + gss_release_buffer(&gss_status, &gss_send_token); + infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user); + free(user); + user = NULL; + + /* Do encryption */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 2; /* encryption message type */ + + gss_enc = 0; /* no data protection */ + /* do confidentiality protection if supported */ + if(gss_ret_flags & GSS_C_CONF_FLAG) + gss_enc = 2; + /* else do integrity protection */ + else if(gss_ret_flags & GSS_C_INTEG_FLAG) + gss_enc = 1; + + infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", + (gss_enc == 0)?"no":((gss_enc==1)?"integrity":"confidentiality")); + /* force for the moment to no data protection */ + gss_enc = 0; + /* + * Sending the encryption type in clear seems wrong. It should be + * protected with gss_seal()/gss_wrap(). See RFC1961 extract below + * The NEC reference implementations on which this is based is + * therefore at fault + * + * +------+------+------+.......................+ + * + ver | mtyp | len | token | + * +------+------+------+.......................+ + * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | + * +------+------+------+.......................+ + * + * Where: + * + * - "ver" is the protocol version number, here 1 to represent the + * first version of the SOCKS/GSS-API protocol + * + * - "mtyp" is the message type, here 2 to represent a protection + * -level negotiation message + * + * - "len" is the length of the "token" field in octets + * + * - "token" is the GSS-API encapsulated protection level + * + * The token is produced by encapsulating an octet containing the + * required protection level using gss_seal()/gss_wrap() with conf_req + * set to FALSE. The token is verified using gss_unseal()/ + * gss_unwrap(). + * + */ + if(data->set.socks5_gssapi_nec) { + us_length = htons((short)1); + memcpy(socksreq + 2, &us_length, sizeof(short)); + } + else { + gss_send_token.length = 1; + gss_send_token.value = malloc(1); + if(!gss_send_token.value) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + memcpy(gss_send_token.value, &gss_enc, 1); + + gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0, + GSS_C_QOP_DEFAULT, &gss_send_token, + &gss_conf_state, &gss_w_token); + + if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_wrap")) { + gss_release_buffer(&gss_status, &gss_send_token); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to wrap GSS-API encryption value into token."); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_send_token); + + us_length = htons((short)gss_w_token.length); + memcpy(socksreq + 2, &us_length, sizeof(short)); + } + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send GSS-API encryption request."); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(data->set.socks5_gssapi_nec) { + memcpy(socksreq, &gss_enc, 1); + code = Curl_write_plain(conn, sock, socksreq, 1, &written); + if(code || ( 1 != written)) { + failf(data, "Failed to send GSS-API encryption type."); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + } + else { + code = Curl_write_plain(conn, sock, (char *)gss_w_token.value, + gss_w_token.length, &written); + if(code || ((ssize_t)gss_w_token.length != written)) { + failf(data, "Failed to send GSS-API encryption type."); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_w_token); + } + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive GSS-API encryption response."); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 2) { /* status / messgae type */ + failf(data, "Invalid GSS-API encryption response type (%d %d).", + socksreq[0], socksreq[1]); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq + 2, sizeof(short)); + us_length = ntohs(us_length); + + gss_recv_token.length = us_length; + gss_recv_token.value = malloc(gss_recv_token.length); + if(!gss_recv_token.value) { + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_OUT_OF_MEMORY; + } + result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, + gss_recv_token.length, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive GSS-API encryptrion type."); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + if(!data->set.socks5_gssapi_nec) { + gss_major_status = gss_unwrap(&gss_minor_status, gss_context, + &gss_recv_token, &gss_w_token, + 0, GSS_C_QOP_DEFAULT); + + if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_unwrap")) { + gss_release_buffer(&gss_status, &gss_recv_token); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + failf(data, "Failed to unwrap GSS-API encryption value into token."); + return CURLE_COULDNT_CONNECT; + } + gss_release_buffer(&gss_status, &gss_recv_token); + + if(gss_w_token.length != 1) { + failf(data, "Invalid GSS-API encryption response length (%d).", + gss_w_token.length); + gss_release_buffer(&gss_status, &gss_w_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, gss_w_token.value, gss_w_token.length); + gss_release_buffer(&gss_status, &gss_w_token); + } + else { + if(gss_recv_token.length != 1) { + failf(data, "Invalid GSS-API encryption response length (%d).", + gss_recv_token.length); + gss_release_buffer(&gss_status, &gss_recv_token); + gss_delete_sec_context(&gss_status, &gss_context, NULL); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, gss_recv_token.value, gss_recv_token.length); + gss_release_buffer(&gss_status, &gss_recv_token); + } + + infof(data, "SOCKS5 access with%s protection granted.\n", + (socksreq[0] == 0)?"out GSS-API data": + ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality")); + + conn->socks5_gssapi_enctype = socksreq[0]; + if(socksreq[0] == 0) + gss_delete_sec_context(&gss_status, &gss_context, NULL); + + return CURLE_OK; +} + +#endif /* HAVE_GSSAPI && !CURL_DISABLE_PROXY */ diff --git a/libcurl/lib/socks_sspi.c b/libcurl/lib/socks_sspi.c new file mode 100644 index 0000000..57027ef --- /dev/null +++ b/libcurl/lib/socks_sspi.c @@ -0,0 +1,606 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 2009, 2011, Markus Moeller, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY) + +#include "urldata.h" +#include "sendf.h" +#include "connect.h" +#include "strerror.h" +#include "timeval.h" +#include "socks.h" +#include "curl_sspi.h" +#include "curl_multibyte.h" +#include "warnless.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Helper sspi error functions. + */ +static int check_sspi_err(struct connectdata *conn, + SECURITY_STATUS status, + const char *function) +{ + if(status != SEC_E_OK && + status != SEC_I_COMPLETE_AND_CONTINUE && + status != SEC_I_COMPLETE_NEEDED && + status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; + failf(conn->data, "SSPI error: %s failed: %s", function, + Curl_sspi_strerror(status, buffer, sizeof(buffer))); + return 1; + } + return 0; +} + +/* This is the SSPI-using version of this function */ +CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sock = conn->sock[sockindex]; + CURLcode code; + ssize_t actualread; + ssize_t written; + int result; + /* Needs GSS-API authentication */ + SECURITY_STATUS status; + unsigned long sspi_ret_flags = 0; + unsigned char gss_enc; + SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3]; + SecBufferDesc input_desc, output_desc, wrap_desc; + SecPkgContext_Sizes sspi_sizes; + CredHandle cred_handle; + CtxtHandle sspi_context; + PCtxtHandle context_handle = NULL; + SecPkgCredentials_Names names; + TimeStamp expiry; + char *service_name = NULL; + unsigned short us_length; + unsigned long qop; + unsigned char socksreq[4]; /* room for GSS-API exchange header only */ + const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ? + data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + const size_t service_length = strlen(service); + + /* GSS-API request looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + /* prepare service name */ + if(strchr(service, '/')) { + service_name = strdup(service); + if(!service_name) + return CURLE_OUT_OF_MEMORY; + } + else { + service_name = malloc(service_length + + strlen(conn->socks_proxy.host.name) + 2); + if(!service_name) + return CURLE_OUT_OF_MEMORY; + msnprintf(service_name, service_length + + strlen(conn->socks_proxy.host.name) + 2, "%s/%s", + service, conn->socks_proxy.host.name); + } + + input_desc.cBuffers = 1; + input_desc.pBuffers = &sspi_recv_token; + input_desc.ulVersion = SECBUFFER_VERSION; + + sspi_recv_token.BufferType = SECBUFFER_TOKEN; + sspi_recv_token.cbBuffer = 0; + sspi_recv_token.pvBuffer = NULL; + + output_desc.cBuffers = 1; + output_desc.pBuffers = &sspi_send_token; + output_desc.ulVersion = SECBUFFER_VERSION; + + sspi_send_token.BufferType = SECBUFFER_TOKEN; + sspi_send_token.cbBuffer = 0; + sspi_send_token.pvBuffer = NULL; + + wrap_desc.cBuffers = 3; + wrap_desc.pBuffers = sspi_w_token; + wrap_desc.ulVersion = SECBUFFER_VERSION; + + cred_handle.dwLower = 0; + cred_handle.dwUpper = 0; + + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT("Kerberos"), + SECPKG_CRED_OUTBOUND, + NULL, + NULL, + NULL, + NULL, + &cred_handle, + &expiry); + + if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) { + failf(data, "Failed to acquire credentials."); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + return CURLE_COULDNT_CONNECT; + } + + /* As long as we need to keep sending some context info, and there's no */ + /* errors, keep sending it... */ + for(;;) { + TCHAR *sname; + + sname = Curl_convert_UTF8_to_tchar(service_name); + if(!sname) + return CURLE_OUT_OF_MEMORY; + + status = s_pSecFn->InitializeSecurityContext(&cred_handle, + context_handle, + sname, + ISC_REQ_MUTUAL_AUTH | + ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_CONFIDENTIALITY | + ISC_REQ_REPLAY_DETECT, + 0, + SECURITY_NATIVE_DREP, + &input_desc, + 0, + &sspi_context, + &output_desc, + &sspi_ret_flags, + &expiry); + + Curl_unicodefree(sname); + + if(sspi_recv_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + sspi_recv_token.pvBuffer = NULL; + sspi_recv_token.cbBuffer = 0; + } + + if(check_sspi_err(conn, status, "InitializeSecurityContext")) { + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + failf(data, "Failed to initialise security context."); + return CURLE_COULDNT_CONNECT; + } + + if(sspi_send_token.cbBuffer != 0) { + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 1; /* authentication message type */ + us_length = htons((short)sspi_send_token.cbBuffer); + memcpy(socksreq + 2, &us_length, sizeof(short)); + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send SSPI authentication request."); + free(service_name); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, + sspi_send_token.cbBuffer, &written); + if(code || (sspi_send_token.cbBuffer != (size_t)written)) { + failf(data, "Failed to send SSPI authentication token."); + free(service_name); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + } + + if(sspi_send_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + sspi_send_token.pvBuffer = NULL; + } + sspi_send_token.cbBuffer = 0; + + if(sspi_recv_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + sspi_recv_token.pvBuffer = NULL; + } + sspi_recv_token.cbBuffer = 0; + + if(status != SEC_I_CONTINUE_NEEDED) + break; + + /* analyse response */ + + /* GSS-API response looks like + * +----+------+-----+----------------+ + * |VER | MTYP | LEN | TOKEN | + * +----+------+----------------------+ + * | 1 | 1 | 2 | up to 2^16 - 1 | + * +----+------+-----+----------------+ + */ + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive SSPI authentication response."); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 1) { /* status / messgae type */ + failf(data, "Invalid SSPI authentication response type (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq + 2, sizeof(short)); + us_length = ntohs(us_length); + + sspi_recv_token.cbBuffer = us_length; + sspi_recv_token.pvBuffer = malloc(us_length); + + if(!sspi_recv_token.pvBuffer) { + free(service_name); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer, + sspi_recv_token.cbBuffer, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive SSPI authentication token."); + free(service_name); + if(sspi_recv_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + context_handle = &sspi_context; + } + + free(service_name); + + /* Everything is good so far, user was authenticated! */ + status = s_pSecFn->QueryCredentialsAttributes(&cred_handle, + SECPKG_CRED_ATTR_NAMES, + &names); + s_pSecFn->FreeCredentialsHandle(&cred_handle); + if(check_sspi_err(conn, status, "QueryCredentialAttributes")) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + s_pSecFn->FreeContextBuffer(names.sUserName); + failf(data, "Failed to determine user name."); + return CURLE_COULDNT_CONNECT; + } + infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n", + names.sUserName); + s_pSecFn->FreeContextBuffer(names.sUserName); + + /* Do encryption */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 2; /* encryption message type */ + + gss_enc = 0; /* no data protection */ + /* do confidentiality protection if supported */ + if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY) + gss_enc = 2; + /* else do integrity protection */ + else if(sspi_ret_flags & ISC_REQ_INTEGRITY) + gss_enc = 1; + + infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", + (gss_enc == 0)?"no":((gss_enc == 1)?"integrity":"confidentiality") ); + /* force to no data protection, avoid encryption/decryption for now */ + gss_enc = 0; + /* + * Sending the encryption type in clear seems wrong. It should be + * protected with gss_seal()/gss_wrap(). See RFC1961 extract below + * The NEC reference implementations on which this is based is + * therefore at fault + * + * +------+------+------+.......................+ + * + ver | mtyp | len | token | + * +------+------+------+.......................+ + * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | + * +------+------+------+.......................+ + * + * Where: + * + * - "ver" is the protocol version number, here 1 to represent the + * first version of the SOCKS/GSS-API protocol + * + * - "mtyp" is the message type, here 2 to represent a protection + * -level negotiation message + * + * - "len" is the length of the "token" field in octets + * + * - "token" is the GSS-API encapsulated protection level + * + * The token is produced by encapsulating an octet containing the + * required protection level using gss_seal()/gss_wrap() with conf_req + * set to FALSE. The token is verified using gss_unseal()/ + * gss_unwrap(). + * + */ + + if(data->set.socks5_gssapi_nec) { + us_length = htons((short)1); + memcpy(socksreq + 2, &us_length, sizeof(short)); + } + else { + status = s_pSecFn->QueryContextAttributes(&sspi_context, + SECPKG_ATTR_SIZES, + &sspi_sizes); + if(check_sspi_err(conn, status, "QueryContextAttributes")) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + + sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer; + sspi_w_token[0].BufferType = SECBUFFER_TOKEN; + sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer); + + if(!sspi_w_token[0].pvBuffer) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + sspi_w_token[1].cbBuffer = 1; + sspi_w_token[1].pvBuffer = malloc(1); + if(!sspi_w_token[1].pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1); + sspi_w_token[2].BufferType = SECBUFFER_PADDING; + sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize; + sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize); + if(!sspi_w_token[2].pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + status = s_pSecFn->EncryptMessage(&sspi_context, + KERB_WRAP_NO_ENCRYPT, + &wrap_desc, + 0); + if(check_sspi_err(conn, status, "EncryptMessage")) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer + + sspi_w_token[1].cbBuffer + + sspi_w_token[2].cbBuffer; + sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer); + if(!sspi_send_token.pvBuffer) { + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer, + sspi_w_token[0].cbBuffer); + memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer, + sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); + memcpy((PUCHAR) sspi_send_token.pvBuffer + + sspi_w_token[0].cbBuffer + + sspi_w_token[1].cbBuffer, + sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer); + + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + sspi_w_token[0].pvBuffer = NULL; + sspi_w_token[0].cbBuffer = 0; + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + sspi_w_token[1].pvBuffer = NULL; + sspi_w_token[1].cbBuffer = 0; + s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); + sspi_w_token[2].pvBuffer = NULL; + sspi_w_token[2].cbBuffer = 0; + + us_length = htons((short)sspi_send_token.cbBuffer); + memcpy(socksreq + 2, &us_length, sizeof(short)); + } + + code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); + if(code || (4 != written)) { + failf(data, "Failed to send SSPI encryption request."); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(data->set.socks5_gssapi_nec) { + memcpy(socksreq, &gss_enc, 1); + code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written); + if(code || (1 != written)) { + failf(data, "Failed to send SSPI encryption type."); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + } + else { + code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, + sspi_send_token.cbBuffer, &written); + if(code || (sspi_send_token.cbBuffer != (size_t)written)) { + failf(data, "Failed to send SSPI encryption type."); + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + if(sspi_send_token.pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); + } + + result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); + if(result || (actualread != 4)) { + failf(data, "Failed to receive SSPI encryption response."); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + /* ignore the first (VER) byte */ + if(socksreq[1] == 255) { /* status / message type */ + failf(data, "User was rejected by the SOCKS5 server (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + if(socksreq[1] != 2) { /* status / message type */ + failf(data, "Invalid SSPI encryption response type (%u %u).", + (unsigned int)socksreq[0], (unsigned int)socksreq[1]); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(&us_length, socksreq + 2, sizeof(short)); + us_length = ntohs(us_length); + + sspi_w_token[0].cbBuffer = us_length; + sspi_w_token[0].pvBuffer = malloc(us_length); + if(!sspi_w_token[0].pvBuffer) { + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer, + sspi_w_token[0].cbBuffer, &actualread); + + if(result || (actualread != us_length)) { + failf(data, "Failed to receive SSPI encryption type."); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + + if(!data->set.socks5_gssapi_nec) { + wrap_desc.cBuffers = 2; + sspi_w_token[0].BufferType = SECBUFFER_STREAM; + sspi_w_token[1].BufferType = SECBUFFER_DATA; + sspi_w_token[1].cbBuffer = 0; + sspi_w_token[1].pvBuffer = NULL; + + status = s_pSecFn->DecryptMessage(&sspi_context, + &wrap_desc, + 0, + &qop); + + if(check_sspi_err(conn, status, "DecryptMessage")) { + if(sspi_w_token[0].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + if(sspi_w_token[1].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + failf(data, "Failed to query security context attributes."); + return CURLE_COULDNT_CONNECT; + } + + if(sspi_w_token[1].cbBuffer != 1) { + failf(data, "Invalid SSPI encryption response length (%lu).", + (unsigned long)sspi_w_token[1].cbBuffer); + if(sspi_w_token[0].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + if(sspi_w_token[1].pvBuffer) + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + + memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); + } + else { + if(sspi_w_token[0].cbBuffer != 1) { + failf(data, "Invalid SSPI encryption response length (%lu).", + (unsigned long)sspi_w_token[0].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + s_pSecFn->DeleteSecurityContext(&sspi_context); + return CURLE_COULDNT_CONNECT; + } + memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer); + s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); + } + + infof(data, "SOCKS5 access with%s protection granted.\n", + (socksreq[0] == 0)?"out GSS-API data": + ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality")); + + /* For later use if encryption is required + conn->socks5_gssapi_enctype = socksreq[0]; + if(socksreq[0] != 0) + conn->socks5_sspi_context = sspi_context; + else { + s_pSecFn->DeleteSecurityContext(&sspi_context); + conn->socks5_sspi_context = sspi_context; + } + */ + return CURLE_OK; +} +#endif diff --git a/libcurl/lib/speedcheck.c b/libcurl/lib/speedcheck.c new file mode 100644 index 0000000..3aeea91 --- /dev/null +++ b/libcurl/lib/speedcheck.c @@ -0,0 +1,73 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "sendf.h" +#include "multiif.h" +#include "speedcheck.h" + +void Curl_speedinit(struct Curl_easy *data) +{ + memset(&data->state.keeps_speed, 0, sizeof(struct curltime)); +} + +/* + * @unittest: 1606 + */ +CURLcode Curl_speedcheck(struct Curl_easy *data, + struct curltime now) +{ + if((data->progress.current_speed >= 0) && data->set.low_speed_time) { + if(data->progress.current_speed < data->set.low_speed_limit) { + if(!data->state.keeps_speed.tv_sec) + /* under the limit at this very moment */ + data->state.keeps_speed = now; + else { + /* how long has it been under the limit */ + timediff_t howlong = Curl_timediff(now, data->state.keeps_speed); + + if(howlong >= data->set.low_speed_time * 1000) { + /* too long */ + failf(data, + "Operation too slow. " + "Less than %ld bytes/sec transferred the last %ld seconds", + data->set.low_speed_limit, + data->set.low_speed_time); + return CURLE_OPERATION_TIMEDOUT; + } + } + } + else + /* faster right now */ + data->state.keeps_speed.tv_sec = 0; + } + + if(data->set.low_speed_limit) + /* if low speed limit is enabled, set the expire timer to make this + connection's speed get checked again in a second */ + Curl_expire(data, 1000, EXPIRE_SPEEDCHECK); + + return CURLE_OK; +} diff --git a/libcurl/lib/speedcheck.h b/libcurl/lib/speedcheck.h new file mode 100644 index 0000000..5c2dc9a --- /dev/null +++ b/libcurl/lib/speedcheck.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_SPEEDCHECK_H +#define HEADER_CURL_SPEEDCHECK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "timeval.h" + +void Curl_speedinit(struct Curl_easy *data); +CURLcode Curl_speedcheck(struct Curl_easy *data, + struct curltime now); + +#endif /* HEADER_CURL_SPEEDCHECK_H */ diff --git a/libcurl/lib/splay.c b/libcurl/lib/splay.c new file mode 100644 index 0000000..0f5fcd1 --- /dev/null +++ b/libcurl/lib/splay.c @@ -0,0 +1,276 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1997 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "splay.h" + +/* + * This macro compares two node keys i and j and returns: + * + * negative value: when i is smaller than j + * zero : when i is equal to j + * positive when : when i is larger than j + */ +#define compare(i,j) Curl_splaycomparekeys((i),(j)) + +/* + * Splay using the key i (which may or may not be in the tree.) The starting + * root is t. + */ +struct Curl_tree *Curl_splay(struct curltime i, + struct Curl_tree *t) +{ + struct Curl_tree N, *l, *r, *y; + + if(t == NULL) + return t; + N.smaller = N.larger = NULL; + l = r = &N; + + for(;;) { + long comp = compare(i, t->key); + if(comp < 0) { + if(t->smaller == NULL) + break; + if(compare(i, t->smaller->key) < 0) { + y = t->smaller; /* rotate smaller */ + t->smaller = y->larger; + y->larger = t; + t = y; + if(t->smaller == NULL) + break; + } + r->smaller = t; /* link smaller */ + r = t; + t = t->smaller; + } + else if(comp > 0) { + if(t->larger == NULL) + break; + if(compare(i, t->larger->key) > 0) { + y = t->larger; /* rotate larger */ + t->larger = y->smaller; + y->smaller = t; + t = y; + if(t->larger == NULL) + break; + } + l->larger = t; /* link larger */ + l = t; + t = t->larger; + } + else + break; + } + + l->larger = t->smaller; /* assemble */ + r->smaller = t->larger; + t->smaller = N.larger; + t->larger = N.smaller; + + return t; +} + +/* Insert key i into the tree t. Return a pointer to the resulting tree or + * NULL if something went wrong. + * + * @unittest: 1309 + */ +struct Curl_tree *Curl_splayinsert(struct curltime i, + struct Curl_tree *t, + struct Curl_tree *node) +{ + static const struct curltime KEY_NOTUSED = { + (time_t)-1, (unsigned int)-1 + }; /* will *NEVER* appear */ + + if(node == NULL) + return t; + + if(t != NULL) { + t = Curl_splay(i, t); + if(compare(i, t->key) == 0) { + /* There already exists a node in the tree with the very same key. Build + a doubly-linked circular list of nodes. We add the new 'node' struct + to the end of this list. */ + + node->key = KEY_NOTUSED; /* we set the key in the sub node to NOTUSED + to quickly identify this node as a subnode */ + node->samen = t; + node->samep = t->samep; + t->samep->samen = node; + t->samep = node; + + return t; /* the root node always stays the same */ + } + } + + if(t == NULL) { + node->smaller = node->larger = NULL; + } + else if(compare(i, t->key) < 0) { + node->smaller = t->smaller; + node->larger = t; + t->smaller = NULL; + + } + else { + node->larger = t->larger; + node->smaller = t; + t->larger = NULL; + } + node->key = i; + + /* no identical nodes (yet), we are the only one in the list of nodes */ + node->samen = node; + node->samep = node; + return node; +} + +/* Finds and deletes the best-fit node from the tree. Return a pointer to the + resulting tree. best-fit means the smallest node if it is not larger than + the key */ +struct Curl_tree *Curl_splaygetbest(struct curltime i, + struct Curl_tree *t, + struct Curl_tree **removed) +{ + static struct curltime tv_zero = {0, 0}; + struct Curl_tree *x; + + if(!t) { + *removed = NULL; /* none removed since there was no root */ + return NULL; + } + + /* find smallest */ + t = Curl_splay(tv_zero, t); + if(compare(i, t->key) < 0) { + /* even the smallest is too big */ + *removed = NULL; + return t; + } + + /* FIRST! Check if there is a list with identical keys */ + x = t->samen; + if(x != t) { + /* there is, pick one from the list */ + + /* 'x' is the new root node */ + + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + x->samep = t->samep; + t->samep->samen = x; + + *removed = t; + return x; /* new root */ + } + + /* we splayed the tree to the smallest element, there is no smaller */ + x = t->larger; + *removed = t; + + return x; +} + + +/* Deletes the very node we point out from the tree if it's there. Stores a + * pointer to the new resulting tree in 'newroot'. + * + * Returns zero on success and non-zero on errors! + * When returning error, it does not touch the 'newroot' pointer. + * + * NOTE: when the last node of the tree is removed, there's no tree left so + * 'newroot' will be made to point to NULL. + * + * @unittest: 1309 + */ +int Curl_splayremovebyaddr(struct Curl_tree *t, + struct Curl_tree *removenode, + struct Curl_tree **newroot) +{ + static const struct curltime KEY_NOTUSED = { + (time_t)-1, (unsigned int)-1 + }; /* will *NEVER* appear */ + struct Curl_tree *x; + + if(!t || !removenode) + return 1; + + if(compare(KEY_NOTUSED, removenode->key) == 0) { + /* Key set to NOTUSED means it is a subnode within a 'same' linked list + and thus we can unlink it easily. */ + if(removenode->samen == removenode) + /* A non-subnode should never be set to KEY_NOTUSED */ + return 3; + + removenode->samep->samen = removenode->samen; + removenode->samen->samep = removenode->samep; + + /* Ensures that double-remove gets caught. */ + removenode->samen = removenode; + + *newroot = t; /* return the same root */ + return 0; + } + + t = Curl_splay(removenode->key, t); + + /* First make sure that we got the same root node as the one we want + to remove, as otherwise we might be trying to remove a node that + isn't actually in the tree. + + We cannot just compare the keys here as a double remove in quick + succession of a node with key != KEY_NOTUSED && same != NULL + could return the same key but a different node. */ + if(t != removenode) + return 2; + + /* Check if there is a list with identical sizes, as then we're trying to + remove the root node of a list of nodes with identical keys. */ + x = t->samen; + if(x != t) { + /* 'x' is the new root node, we just make it use the root node's + smaller/larger links */ + + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + x->samep = t->samep; + t->samep->samen = x; + } + else { + /* Remove the root node */ + if(t->smaller == NULL) + x = t->larger; + else { + x = Curl_splay(removenode->key, t->smaller); + x->larger = t->larger; + } + } + + *newroot = x; /* store new root pointer */ + + return 0; +} diff --git a/libcurl/lib/splay.h b/libcurl/lib/splay.h new file mode 100644 index 0000000..9292f34 --- /dev/null +++ b/libcurl/lib/splay.h @@ -0,0 +1,62 @@ +#ifndef HEADER_CURL_SPLAY_H +#define HEADER_CURL_SPLAY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1997 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +#include "timeval.h" + +struct Curl_tree { + struct Curl_tree *smaller; /* smaller node */ + struct Curl_tree *larger; /* larger node */ + struct Curl_tree *samen; /* points to the next node with identical key */ + struct Curl_tree *samep; /* points to the prev node with identical key */ + struct curltime key; /* this node's "sort" key */ + void *payload; /* data the splay code doesn't care about */ +}; + +struct Curl_tree *Curl_splay(struct curltime i, + struct Curl_tree *t); + +struct Curl_tree *Curl_splayinsert(struct curltime key, + struct Curl_tree *t, + struct Curl_tree *newnode); + +#if 0 +struct Curl_tree *Curl_splayremove(struct curltime key, + struct Curl_tree *t, + struct Curl_tree **removed); +#endif + +struct Curl_tree *Curl_splaygetbest(struct curltime key, + struct Curl_tree *t, + struct Curl_tree **removed); + +int Curl_splayremovebyaddr(struct Curl_tree *t, + struct Curl_tree *removenode, + struct Curl_tree **newroot); + +#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \ + ( ((i.tv_sec) > (j.tv_sec)) ? 1 : \ + ( ((i.tv_usec) < (j.tv_usec)) ? -1 : \ + ( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0)))) + +#endif /* HEADER_CURL_SPLAY_H */ diff --git a/libcurl/lib/ssh-libssh.c b/libcurl/lib/ssh-libssh.c new file mode 100644 index 0000000..ca13376 --- /dev/null +++ b/libcurl/lib/ssh-libssh.c @@ -0,0 +1,2739 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2017 - 2019 Red Hat, Inc. + * + * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek, + * Robert Kolcun, Andreas Schneider + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_LIBSSH + +#include + +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "ssh.h" +#include "url.h" +#include "speedcheck.h" +#include "getinfo.h" +#include "strdup.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "strtoofft.h" +#include "multiif.h" +#include "select.h" +#include "warnless.h" + +/* for permission and open flags */ +#include +#include +#include +#include + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" +#include "curl_path.h" + +/* A recent macro provided by libssh. Or make our own. */ +#ifndef SSH_STRING_FREE_CHAR +/* !checksrc! disable ASSIGNWITHINCONDITION 1 */ +#define SSH_STRING_FREE_CHAR(x) \ + do { if((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0) +#endif + +/* Local functions: */ +static CURLcode myssh_connect(struct connectdata *conn, bool *done); +static CURLcode myssh_multi_statemach(struct connectdata *conn, + bool *done); +static CURLcode myssh_do_it(struct connectdata *conn, bool *done); + +static CURLcode scp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done); +static CURLcode scp_disconnect(struct connectdata *conn, + bool dead_connection); + +static CURLcode sftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done); + +static void sftp_quote(struct connectdata *conn); +static void sftp_quote_stat(struct connectdata *conn); + +static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock, + int numsocks); + +static int myssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, + int numsocks); + +static CURLcode myssh_setup_connection(struct connectdata *conn); + +/* + * SCP protocol handler. + */ + +const struct Curl_handler Curl_handler_scp = { + "SCP", /* scheme */ + myssh_setup_connection, /* setup_connection */ + myssh_do_it, /* do_it */ + scp_done, /* done */ + ZERO_NULL, /* do_more */ + myssh_connect, /* connect_it */ + myssh_multi_statemach, /* connecting */ + scp_doing, /* doing */ + myssh_getsock, /* proto_getsock */ + myssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + myssh_perform_getsock, /* perform_getsock */ + scp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */ +}; + +/* + * SFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_sftp = { + "SFTP", /* scheme */ + myssh_setup_connection, /* setup_connection */ + myssh_do_it, /* do_it */ + sftp_done, /* done */ + ZERO_NULL, /* do_more */ + myssh_connect, /* connect_it */ + myssh_multi_statemach, /* connecting */ + sftp_doing, /* doing */ + myssh_getsock, /* proto_getsock */ + myssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + myssh_perform_getsock, /* perform_getsock */ + sftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + +static CURLcode sftp_error_to_CURLE(int err) +{ + switch(err) { + case SSH_FX_OK: + return CURLE_OK; + + case SSH_FX_NO_SUCH_FILE: + case SSH_FX_NO_SUCH_PATH: + return CURLE_REMOTE_FILE_NOT_FOUND; + + case SSH_FX_PERMISSION_DENIED: + case SSH_FX_WRITE_PROTECT: + return CURLE_REMOTE_ACCESS_DENIED; + + case SSH_FX_FILE_ALREADY_EXISTS: + return CURLE_REMOTE_FILE_EXISTS; + + default: + break; + } + + return CURLE_SSH; +} + +#ifndef DEBUGBUILD +#define state(x,y) mystate(x,y) +#else +#define state(x,y) mystate(x,y, __LINE__) +#endif + +/* + * SSH State machine related code + */ +/* This is the ONLY way to change SSH state! */ +static void mystate(struct connectdata *conn, sshstate nowstate +#ifdef DEBUGBUILD + , int lineno +#endif + ) +{ + struct ssh_conn *sshc = &conn->proto.sshc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char *const names[] = { + "SSH_STOP", + "SSH_INIT", + "SSH_S_STARTUP", + "SSH_HOSTKEY", + "SSH_AUTHLIST", + "SSH_AUTH_PKEY_INIT", + "SSH_AUTH_PKEY", + "SSH_AUTH_PASS_INIT", + "SSH_AUTH_PASS", + "SSH_AUTH_AGENT_INIT", + "SSH_AUTH_AGENT_LIST", + "SSH_AUTH_AGENT", + "SSH_AUTH_HOST_INIT", + "SSH_AUTH_HOST", + "SSH_AUTH_KEY_INIT", + "SSH_AUTH_KEY", + "SSH_AUTH_GSSAPI", + "SSH_AUTH_DONE", + "SSH_SFTP_INIT", + "SSH_SFTP_REALPATH", + "SSH_SFTP_QUOTE_INIT", + "SSH_SFTP_POSTQUOTE_INIT", + "SSH_SFTP_QUOTE", + "SSH_SFTP_NEXT_QUOTE", + "SSH_SFTP_QUOTE_STAT", + "SSH_SFTP_QUOTE_SETSTAT", + "SSH_SFTP_QUOTE_SYMLINK", + "SSH_SFTP_QUOTE_MKDIR", + "SSH_SFTP_QUOTE_RENAME", + "SSH_SFTP_QUOTE_RMDIR", + "SSH_SFTP_QUOTE_UNLINK", + "SSH_SFTP_QUOTE_STATVFS", + "SSH_SFTP_GETINFO", + "SSH_SFTP_FILETIME", + "SSH_SFTP_TRANS_INIT", + "SSH_SFTP_UPLOAD_INIT", + "SSH_SFTP_CREATE_DIRS_INIT", + "SSH_SFTP_CREATE_DIRS", + "SSH_SFTP_CREATE_DIRS_MKDIR", + "SSH_SFTP_READDIR_INIT", + "SSH_SFTP_READDIR", + "SSH_SFTP_READDIR_LINK", + "SSH_SFTP_READDIR_BOTTOM", + "SSH_SFTP_READDIR_DONE", + "SSH_SFTP_DOWNLOAD_INIT", + "SSH_SFTP_DOWNLOAD_STAT", + "SSH_SFTP_CLOSE", + "SSH_SFTP_SHUTDOWN", + "SSH_SCP_TRANS_INIT", + "SSH_SCP_UPLOAD_INIT", + "SSH_SCP_DOWNLOAD_INIT", + "SSH_SCP_DOWNLOAD", + "SSH_SCP_DONE", + "SSH_SCP_SEND_EOF", + "SSH_SCP_WAIT_EOF", + "SSH_SCP_WAIT_CLOSE", + "SSH_SCP_CHANNEL_FREE", + "SSH_SESSION_DISCONNECT", + "SSH_SESSION_FREE", + "QUIT" + }; + + + if(sshc->state != nowstate) { + infof(conn->data, "SSH %p state change from %s to %s (line %d)\n", + (void *) sshc, names[sshc->state], names[nowstate], + lineno); + } +#endif + + sshc->state = nowstate; +} + +/* Multiple options: + * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5 + * hash (90s style auth, not sure we should have it here) + * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first + * use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE + * is returned by it. + * 3. none of the above. We only accept if it is present on known hosts. + * + * Returns SSH_OK or SSH_ERROR. + */ +static int myssh_is_known(struct connectdata *conn) +{ + int rc; + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + ssh_key pubkey; + size_t hlen; + unsigned char *hash = NULL; + char *base64 = NULL; + int vstate; + enum curl_khmatch keymatch; + struct curl_khkey foundkey; + curl_sshkeycallback func = + data->set.ssh_keyfunc; + + rc = ssh_get_publickey(sshc->ssh_session, &pubkey); + if(rc != SSH_OK) + return rc; + + if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) { + rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5, + &hash, &hlen); + if(rc != SSH_OK) + goto cleanup; + + if(hlen != strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) || + memcmp(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], hash, hlen)) { + rc = SSH_ERROR; + goto cleanup; + } + + rc = SSH_OK; + goto cleanup; + } + + if(data->set.ssl.primary.verifyhost != TRUE) { + rc = SSH_OK; + goto cleanup; + } + + vstate = ssh_is_server_known(sshc->ssh_session); + switch(vstate) { + case SSH_SERVER_KNOWN_OK: + keymatch = CURLKHMATCH_OK; + break; + case SSH_SERVER_FILE_NOT_FOUND: + /* fallthrough */ + case SSH_SERVER_NOT_KNOWN: + keymatch = CURLKHMATCH_MISSING; + break; + default: + keymatch = CURLKHMATCH_MISMATCH; + break; + } + + if(func) { /* use callback to determine action */ + rc = ssh_pki_export_pubkey_base64(pubkey, &base64); + if(rc != SSH_OK) + goto cleanup; + + foundkey.key = base64; + foundkey.len = strlen(base64); + + switch(ssh_key_type(pubkey)) { + case SSH_KEYTYPE_RSA: + foundkey.keytype = CURLKHTYPE_RSA; + break; + case SSH_KEYTYPE_RSA1: + foundkey.keytype = CURLKHTYPE_RSA1; + break; + case SSH_KEYTYPE_ECDSA: + foundkey.keytype = CURLKHTYPE_ECDSA; + break; +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0) + case SSH_KEYTYPE_ED25519: + foundkey.keytype = CURLKHTYPE_ED25519; + break; +#endif + case SSH_KEYTYPE_DSS: + foundkey.keytype = CURLKHTYPE_DSS; + break; + default: + rc = SSH_ERROR; + goto cleanup; + } + + /* we don't have anything equivalent to knownkey. Always NULL */ + Curl_set_in_callback(data, true); + rc = func(data, NULL, &foundkey, /* from the remote host */ + keymatch, data->set.ssh_keyfunc_userp); + Curl_set_in_callback(data, false); + + switch(rc) { + case CURLKHSTAT_FINE_ADD_TO_FILE: + rc = ssh_write_knownhost(sshc->ssh_session); + if(rc != SSH_OK) { + goto cleanup; + } + break; + case CURLKHSTAT_FINE: + break; + default: /* REJECT/DEFER */ + rc = SSH_ERROR; + goto cleanup; + } + } + else { + if(keymatch != CURLKHMATCH_OK) { + rc = SSH_ERROR; + goto cleanup; + } + } + rc = SSH_OK; + +cleanup: + if(hash) + ssh_clean_pubkey_hash(&hash); + ssh_key_free(pubkey); + return rc; +} + +#define MOVE_TO_ERROR_STATE(_r) { \ + state(conn, SSH_SESSION_DISCONNECT); \ + sshc->actualcode = _r; \ + rc = SSH_ERROR; \ + break; \ +} + +#define MOVE_TO_SFTP_CLOSE_STATE() { \ + state(conn, SSH_SFTP_CLOSE); \ + sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \ + rc = SSH_ERROR; \ + break; \ +} + +#define MOVE_TO_LAST_AUTH \ + if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \ + rc = SSH_OK; \ + state(conn, SSH_AUTH_PASS_INIT); \ + break; \ + } \ + else { \ + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \ + } + +#define MOVE_TO_TERTIARY_AUTH \ + if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \ + rc = SSH_OK; \ + state(conn, SSH_AUTH_KEY_INIT); \ + break; \ + } \ + else { \ + MOVE_TO_LAST_AUTH; \ + } + +#define MOVE_TO_SECONDARY_AUTH \ + if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \ + rc = SSH_OK; \ + state(conn, SSH_AUTH_GSSAPI); \ + break; \ + } \ + else { \ + MOVE_TO_TERTIARY_AUTH; \ + } + +static +int myssh_auth_interactive(struct connectdata *conn) +{ + int rc; + struct ssh_conn *sshc = &conn->proto.sshc; + int nprompts; + +restart: + switch(sshc->kbd_state) { + case 0: + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; + + if(rc != SSH_AUTH_INFO) + return SSH_ERROR; + + nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); + if(nprompts == SSH_ERROR || nprompts != 1) + return SSH_ERROR; + + rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd); + if(rc < 0) + return SSH_ERROR; + + /* FALLTHROUGH */ + case 1: + sshc->kbd_state = 1; + + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; + else if(rc == SSH_AUTH_SUCCESS) + rc = SSH_OK; + else if(rc == SSH_AUTH_INFO) { + nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); + if(nprompts != 0) + return SSH_ERROR; + + sshc->kbd_state = 2; + goto restart; + } + else + rc = SSH_ERROR; + break; + case 2: + sshc->kbd_state = 2; + + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; + else if(rc == SSH_AUTH_SUCCESS) + rc = SSH_OK; + else + rc = SSH_ERROR; + + break; + default: + return SSH_ERROR; + } + + sshc->kbd_state = 0; + return rc; +} + +/* + * ssh_statemach_act() runs the SSH state machine as far as it can without + * blocking and without reaching the end. The data the pointer 'block' points + * to will be set to TRUE if the libssh function returns SSH_AGAIN + * meaning it wants to be called again when the socket is ready + */ +static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SSHPROTO *protop = data->req.protop; + struct ssh_conn *sshc = &conn->proto.sshc; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int rc = SSH_NO_ERROR, err; + char *new_readdir_line; + int seekerr = CURL_SEEKFUNC_OK; + const char *err_msg; + *block = 0; /* we're not blocking by default */ + + do { + + switch(sshc->state) { + case SSH_INIT: + sshc->secondCreateDirs = 0; + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_OK; + +#if 0 + ssh_set_log_level(SSH_LOG_PROTOCOL); +#endif + + /* Set libssh to non-blocking, since everything internally is + non-blocking */ + ssh_set_blocking(sshc->ssh_session, 0); + + state(conn, SSH_S_STARTUP); + /* FALLTHROUGH */ + + case SSH_S_STARTUP: + rc = ssh_connect(sshc->ssh_session); + if(rc == SSH_AGAIN) + break; + + if(rc != SSH_OK) { + failf(data, "Failure establishing ssh session"); + MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT); + } + + state(conn, SSH_HOSTKEY); + + /* FALLTHROUGH */ + case SSH_HOSTKEY: + + rc = myssh_is_known(conn); + if(rc != SSH_OK) { + MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION); + } + + state(conn, SSH_AUTHLIST); + /* FALLTHROUGH */ + case SSH_AUTHLIST:{ + sshc->authed = FALSE; + + rc = ssh_userauth_none(sshc->ssh_session, NULL); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc == SSH_AUTH_SUCCESS) { + sshc->authed = TRUE; + infof(data, "Authenticated with none\n"); + state(conn, SSH_AUTH_DONE); + break; + } + else if(rc == SSH_AUTH_ERROR) { + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + } + + sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL); + if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { + state(conn, SSH_AUTH_PKEY_INIT); + infof(data, "Authentication using SSH public key file\n"); + } + else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { + state(conn, SSH_AUTH_GSSAPI); + } + else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { + state(conn, SSH_AUTH_KEY_INIT); + } + else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { + state(conn, SSH_AUTH_PASS_INIT); + } + else { /* unsupported authentication method */ + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + } + + break; + } + case SSH_AUTH_PKEY_INIT: + if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) { + MOVE_TO_SECONDARY_AUTH; + } + + /* Two choices, (1) private key was given on CMD, + * (2) use the "default" keys. */ + if(data->set.str[STRING_SSH_PRIVATE_KEY]) { + if(sshc->pubkey && !data->set.ssl.key_passwd) { + rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL, + sshc->pubkey); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc != SSH_OK) { + MOVE_TO_SECONDARY_AUTH; + } + } + + rc = ssh_pki_import_privkey_file(data-> + set.str[STRING_SSH_PRIVATE_KEY], + data->set.ssl.key_passwd, NULL, + NULL, &sshc->privkey); + if(rc != SSH_OK) { + failf(data, "Could not load private key file %s", + data->set.str[STRING_SSH_PRIVATE_KEY]); + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; + } + + state(conn, SSH_AUTH_PKEY); + break; + + } + else { + rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL, + data->set.ssl.key_passwd); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + if(rc == SSH_AUTH_SUCCESS) { + rc = SSH_OK; + sshc->authed = TRUE; + infof(data, "Completed public key authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + + MOVE_TO_SECONDARY_AUTH; + } + break; + case SSH_AUTH_PKEY: + rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc == SSH_AUTH_SUCCESS) { + sshc->authed = TRUE; + infof(data, "Completed public key authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + else { + infof(data, "Failed public key authentication (rc: %d)\n", rc); + MOVE_TO_SECONDARY_AUTH; + } + break; + + case SSH_AUTH_GSSAPI: + if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) { + MOVE_TO_TERTIARY_AUTH; + } + + rc = ssh_userauth_gssapi(sshc->ssh_session); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc == SSH_AUTH_SUCCESS) { + rc = SSH_OK; + sshc->authed = TRUE; + infof(data, "Completed gssapi authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + + MOVE_TO_TERTIARY_AUTH; + break; + + case SSH_AUTH_KEY_INIT: + if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) { + state(conn, SSH_AUTH_KEY); + } + else { + MOVE_TO_LAST_AUTH; + } + break; + + case SSH_AUTH_KEY: + + /* Authentication failed. Continue with keyboard-interactive now. */ + rc = myssh_auth_interactive(conn); + if(rc == SSH_AGAIN) { + break; + } + if(rc == SSH_OK) { + sshc->authed = TRUE; + infof(data, "completed keyboard interactive authentication\n"); + } + state(conn, SSH_AUTH_DONE); + break; + + case SSH_AUTH_PASS_INIT: + if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) { + /* Host key authentication is intentionally not implemented */ + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + } + state(conn, SSH_AUTH_PASS); + /* FALLTHROUGH */ + + case SSH_AUTH_PASS: + rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd); + if(rc == SSH_AUTH_AGAIN) { + rc = SSH_AGAIN; + break; + } + + if(rc == SSH_AUTH_SUCCESS) { + sshc->authed = TRUE; + infof(data, "Completed password authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + } + break; + + case SSH_AUTH_DONE: + if(!sshc->authed) { + failf(data, "Authentication failure"); + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; + } + + /* + * At this point we have an authenticated ssh session. + */ + infof(data, "Authentication complete\n"); + + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ + + conn->sockfd = sock; + conn->writesockfd = CURL_SOCKET_BAD; + + if(conn->handler->protocol == CURLPROTO_SFTP) { + state(conn, SSH_SFTP_INIT); + break; + } + infof(data, "SSH CONNECT phase done\n"); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_INIT: + ssh_set_blocking(sshc->ssh_session, 1); + + sshc->sftp_session = sftp_new(sshc->ssh_session); + if(!sshc->sftp_session) { + failf(data, "Failure initializing sftp session: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + break; + } + + rc = sftp_init(sshc->sftp_session); + if(rc != SSH_OK) { + rc = sftp_get_error(sshc->sftp_session); + failf(data, "Failure initializing sftp session: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc)); + break; + } + state(conn, SSH_SFTP_REALPATH); + /* FALLTHROUGH */ + case SSH_SFTP_REALPATH: + /* + * Get the "home" directory + */ + sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, "."); + if(sshc->homedir == NULL) { + MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + } + conn->data->state.most_recent_ftp_entrypath = sshc->homedir; + + /* This is the last step in the SFTP connect phase. Do note that while + we get the homedir here, we get the "workingpath" in the DO action + since the homedir will remain the same between request but the + working path will not. */ + DEBUGF(infof(data, "SSH CONNECT phase done\n")); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_QUOTE_INIT: + + result = Curl_getworkingpath(conn, sshc->homedir, &protop->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.quote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.quote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_SFTP_GETINFO); + } + break; + + case SSH_SFTP_POSTQUOTE_INIT: + if(data->set.postquote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.postquote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_QUOTE: + /* Send any quote commands */ + sftp_quote(conn); + break; + + case SSH_SFTP_NEXT_QUOTE: + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + + sshc->quote_item = sshc->quote_item->next; + + if(sshc->quote_item) { + state(conn, SSH_SFTP_QUOTE); + } + else { + if(sshc->nextstate != SSH_NO_STATE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_NO_STATE; + } + else { + state(conn, SSH_SFTP_GETINFO); + } + } + break; + + case SSH_SFTP_QUOTE_STAT: + sftp_quote_stat(conn); + break; + + case SSH_SFTP_QUOTE_SETSTAT: + rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2, + sshc->quote_attrs); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to set SFTP stats failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + /* sshc->actualcode = sftp_error_to_CURLE(err); + * we do not send the actual error; we return + * the error the libssh2 backend is returning */ + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_SYMLINK: + rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2, + sshc->quote_path1); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "symlink command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_MKDIR: + rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1, + (mode_t)data->set.new_directory_perms); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + failf(data, "mkdir command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RENAME: + rc = sftp_rename(sshc->sftp_session, sshc->quote_path1, + sshc->quote_path2); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "rename command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RMDIR: + rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + failf(data, "rmdir command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_UNLINK: + rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1); + if(rc != 0 && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + failf(data, "rm command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_STATVFS: + { + sftp_statvfs_t statvfs; + + statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1); + if(!statvfs && !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + failf(data, "statvfs command failed: %s", + ssh_get_error(sshc->ssh_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + else if(statvfs) { + char *tmp = aprintf("statvfs:\n" + "f_bsize: %llu\n" "f_frsize: %llu\n" + "f_blocks: %llu\n" "f_bfree: %llu\n" + "f_bavail: %llu\n" "f_files: %llu\n" + "f_ffree: %llu\n" "f_favail: %llu\n" + "f_fsid: %llu\n" "f_flag: %llu\n" + "f_namemax: %llu\n", + statvfs->f_bsize, statvfs->f_frsize, + statvfs->f_blocks, statvfs->f_bfree, + statvfs->f_bavail, statvfs->f_files, + statvfs->f_ffree, statvfs->f_favail, + statvfs->f_fsid, statvfs->f_flag, + statvfs->f_namemax); + sftp_statvfs_free(statvfs); + + if(!tmp) { + result = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + break; + } + + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + } + + case SSH_SFTP_GETINFO: + if(data->set.get_filetime) { + state(conn, SSH_SFTP_FILETIME); + } + else { + state(conn, SSH_SFTP_TRANS_INIT); + } + break; + + case SSH_SFTP_FILETIME: + { + sftp_attributes attrs; + + attrs = sftp_stat(sshc->sftp_session, protop->path); + if(attrs != 0) { + data->info.filetime = attrs->mtime; + sftp_attributes_free(attrs); + } + + state(conn, SSH_SFTP_TRANS_INIT); + break; + } + + case SSH_SFTP_TRANS_INIT: + if(data->set.upload) + state(conn, SSH_SFTP_UPLOAD_INIT); + else { + if(protop->path[strlen(protop->path)-1] == '/') + state(conn, SSH_SFTP_READDIR_INIT); + else + state(conn, SSH_SFTP_DOWNLOAD_INIT); + } + break; + + case SSH_SFTP_UPLOAD_INIT: + { + int flags; + + if(data->state.resume_from != 0) { + sftp_attributes attrs; + + if(data->state.resume_from < 0) { + attrs = sftp_stat(sshc->sftp_session, protop->path); + if(attrs != 0) { + curl_off_t size = attrs->size; + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME); + } + data->state.resume_from = attrs->size; + + sftp_attributes_free(attrs); + } + else { + data->state.resume_from = 0; + } + } + } + + if(data->set.ftp_append) + /* Try to open for append, but create if nonexisting */ + flags = O_WRONLY|O_CREAT|O_APPEND; + else if(data->state.resume_from > 0) + /* If we have restart position then open for append */ + flags = O_WRONLY|O_APPEND; + else + /* Clear file before writing (normal behaviour) */ + flags = O_WRONLY|O_APPEND|O_CREAT|O_TRUNC; + + if(sshc->sftp_file) + sftp_close(sshc->sftp_file); + sshc->sftp_file = + sftp_open(sshc->sftp_session, protop->path, + flags, (mode_t)data->set.new_file_perms); + if(!sshc->sftp_file) { + err = sftp_get_error(sshc->sftp_session); + + if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE || + err == SSH_FX_NO_SUCH_PATH)) && + (data->set.ftp_create_missing_dirs && + (strlen(protop->path) > 1))) { + /* try to create the path remotely */ + rc = 0; + sshc->secondCreateDirs = 1; + state(conn, SSH_SFTP_CREATE_DIRS_INIT); + break; + } + else { + MOVE_TO_SFTP_CLOSE_STATE(); + } + } + + /* If we have a restart point then we need to seek to the correct + position. */ + if(data->state.resume_from > 0) { + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + data->state.fread_func(data->state.buffer, 1, + readthisamountnow, data->state.in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST); + } + } while(passed < data->state.resume_from); + } + + /* now, decrease the size of the read */ + if(data->state.infilesize > 0) { + data->state.infilesize -= data->state.resume_from; + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + + rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); + if(rc != 0) { + MOVE_TO_SFTP_CLOSE_STATE(); + } + } + if(data->state.infilesize > 0) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + /* upload data */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh sftp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + /* since we don't really wait for anything at this point, we want the + state machine to move on as soon as possible so we set a very short + timeout here */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + state(conn, SSH_STOP); + break; + } + + case SSH_SFTP_CREATE_DIRS_INIT: + if(strlen(protop->path) > 1) { + sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */ + state(conn, SSH_SFTP_CREATE_DIRS); + } + else { + state(conn, SSH_SFTP_UPLOAD_INIT); + } + break; + + case SSH_SFTP_CREATE_DIRS: + sshc->slash_pos = strchr(sshc->slash_pos, '/'); + if(sshc->slash_pos) { + *sshc->slash_pos = 0; + + infof(data, "Creating directory '%s'\n", protop->path); + state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); + break; + } + state(conn, SSH_SFTP_UPLOAD_INIT); + break; + + case SSH_SFTP_CREATE_DIRS_MKDIR: + /* 'mode' - parameter is preliminary - default to 0644 */ + rc = sftp_mkdir(sshc->sftp_session, protop->path, + (mode_t)data->set.new_directory_perms); + *sshc->slash_pos = '/'; + ++sshc->slash_pos; + if(rc < 0) { + /* + * Abort if failure wasn't that the dir already exists or the + * permission was denied (creation might succeed further down the + * path) - retry on unspecific FAILURE also + */ + err = sftp_get_error(sshc->sftp_session); + if((err != SSH_FX_FILE_ALREADY_EXISTS) && + (err != SSH_FX_FAILURE) && + (err != SSH_FX_PERMISSION_DENIED)) { + MOVE_TO_SFTP_CLOSE_STATE(); + } + rc = 0; /* clear rc and continue */ + } + state(conn, SSH_SFTP_CREATE_DIRS); + break; + + case SSH_SFTP_READDIR_INIT: + Curl_pgrsSetDownloadSize(data, -1); + if(data->set.opt_no_body) { + state(conn, SSH_STOP); + break; + } + + /* + * This is a directory that we are trying to get, so produce a directory + * listing + */ + sshc->sftp_dir = sftp_opendir(sshc->sftp_session, + protop->path); + if(!sshc->sftp_dir) { + failf(data, "Could not open directory for reading: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_SFTP_CLOSE_STATE(); + } + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR: + + if(sshc->readdir_attrs) + sftp_attributes_free(sshc->readdir_attrs); + + sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir); + if(sshc->readdir_attrs) { + sshc->readdir_filename = sshc->readdir_attrs->name; + sshc->readdir_longentry = sshc->readdir_attrs->longname; + sshc->readdir_len = strlen(sshc->readdir_filename); + + if(data->set.ftp_list_only) { + char *tmpLine; + + tmpLine = aprintf("%s\n", sshc->readdir_filename); + if(tmpLine == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + result = Curl_client_write(conn, CLIENTWRITE_BODY, + tmpLine, sshc->readdir_len + 1); + free(tmpLine); + + if(result) { + state(conn, SSH_STOP); + break; + } + /* since this counts what we send to the client, we include the + newline in this counter */ + data->req.bytecount += sshc->readdir_len + 1; + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, + (char *)sshc->readdir_filename, + sshc->readdir_len); + } + } + else { + sshc->readdir_currLen = strlen(sshc->readdir_longentry); + sshc->readdir_totalLen = 80 + sshc->readdir_currLen; + sshc->readdir_line = calloc(sshc->readdir_totalLen, 1); + if(!sshc->readdir_line) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + memcpy(sshc->readdir_line, sshc->readdir_longentry, + sshc->readdir_currLen); + if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) && + ((sshc->readdir_attrs->permissions & S_IFMT) == + S_IFLNK)) { + sshc->readdir_linkPath = malloc(PATH_MAX + 1); + if(sshc->readdir_linkPath == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path, + sshc->readdir_filename); + + state(conn, SSH_SFTP_READDIR_LINK); + break; + } + state(conn, SSH_SFTP_READDIR_BOTTOM); + break; + } + } + else if(sshc->readdir_attrs == NULL && sftp_dir_eof(sshc->sftp_dir)) { + state(conn, SSH_SFTP_READDIR_DONE); + break; + } + else { + failf(data, "Could not open remote file for reading: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_SFTP_CLOSE_STATE(); + break; + } + break; + + case SSH_SFTP_READDIR_LINK: + if(sshc->readdir_link_attrs) + sftp_attributes_free(sshc->readdir_link_attrs); + + sshc->readdir_link_attrs = sftp_lstat(sshc->sftp_session, + sshc->readdir_linkPath); + if(sshc->readdir_link_attrs == 0) { + failf(data, "Could not read symlink for reading: %s", + ssh_get_error(sshc->ssh_session)); + MOVE_TO_SFTP_CLOSE_STATE(); + } + + if(sshc->readdir_link_attrs->name == NULL) { + sshc->readdir_tmp = sftp_readlink(sshc->sftp_session, + sshc->readdir_linkPath); + if(sshc->readdir_filename == NULL) + sshc->readdir_len = 0; + else + sshc->readdir_len = strlen(sshc->readdir_tmp); + sshc->readdir_longentry = NULL; + sshc->readdir_filename = sshc->readdir_tmp; + } + else { + sshc->readdir_len = strlen(sshc->readdir_link_attrs->name); + sshc->readdir_filename = sshc->readdir_link_attrs->name; + sshc->readdir_longentry = sshc->readdir_link_attrs->longname; + } + + Curl_safefree(sshc->readdir_linkPath); + + /* get room for the filename and extra output */ + sshc->readdir_totalLen += 4 + sshc->readdir_len; + new_readdir_line = Curl_saferealloc(sshc->readdir_line, + sshc->readdir_totalLen); + if(!new_readdir_line) { + sshc->readdir_line = NULL; + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + sshc->readdir_line = new_readdir_line; + + sshc->readdir_currLen += msnprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, + " -> %s", + sshc->readdir_filename); + + sftp_attributes_free(sshc->readdir_link_attrs); + sshc->readdir_link_attrs = NULL; + sshc->readdir_filename = NULL; + sshc->readdir_longentry = NULL; + + state(conn, SSH_SFTP_READDIR_BOTTOM); + /* FALLTHROUGH */ + case SSH_SFTP_READDIR_BOTTOM: + sshc->readdir_currLen += msnprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, "\n"); + result = Curl_client_write(conn, CLIENTWRITE_BODY, + sshc->readdir_line, + sshc->readdir_currLen); + + if(!result) { + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line, + sshc->readdir_currLen); + } + data->req.bytecount += sshc->readdir_currLen; + } + Curl_safefree(sshc->readdir_line); + ssh_string_free_char(sshc->readdir_tmp); + sshc->readdir_tmp = NULL; + + if(result) { + state(conn, SSH_STOP); + } + else + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR_DONE: + sftp_closedir(sshc->sftp_dir); + sshc->sftp_dir = NULL; + + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_DOWNLOAD_INIT: + /* + * Work on getting the specified file + */ + if(sshc->sftp_file) + sftp_close(sshc->sftp_file); + + sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path, + O_RDONLY, (mode_t)data->set.new_file_perms); + if(!sshc->sftp_file) { + failf(data, "Could not open remote file for reading: %s", + ssh_get_error(sshc->ssh_session)); + + MOVE_TO_SFTP_CLOSE_STATE(); + } + + state(conn, SSH_SFTP_DOWNLOAD_STAT); + break; + + case SSH_SFTP_DOWNLOAD_STAT: + { + sftp_attributes attrs; + curl_off_t size; + + attrs = sftp_fstat(sshc->sftp_file); + if(!attrs || + !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) || + (attrs->size == 0)) { + /* + * sftp_fstat didn't return an error, so maybe the server + * just doesn't support stat() + * OR the server doesn't return a file size with a stat() + * OR file size is 0 + */ + data->req.size = -1; + data->req.maxdownload = -1; + Curl_pgrsSetDownloadSize(data, -1); + size = 0; + } + else { + size = attrs->size; + + sftp_attributes_free(attrs); + + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(conn->data->state.use_range) { + curl_off_t from, to; + char *ptr; + char *ptr2; + CURLofft to_t; + CURLofft from_t; + + from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from); + if(from_t == CURL_OFFT_FLOW) { + return CURLE_RANGE_ERROR; + } + while(*ptr && (ISSPACE(*ptr) || (*ptr == '-'))) + ptr++; + to_t = curlx_strtoofft(ptr, &ptr2, 0, &to); + if(to_t == CURL_OFFT_FLOW) { + return CURLE_RANGE_ERROR; + } + if((to_t == CURL_OFFT_INVAL) /* no "to" value given */ + || (to >= size)) { + to = size - 1; + } + if(from_t) { + /* from is relative to end of file */ + from = size - to; + to = size - 1; + } + if(from > size) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", from, size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(from > to) { + from = to; + size = 0; + } + else { + size = to - from + 1; + } + + rc = sftp_seek64(sshc->sftp_file, from); + if(rc != 0) { + MOVE_TO_SFTP_CLOSE_STATE(); + } + } + data->req.size = size; + data->req.maxdownload = size; + Curl_pgrsSetDownloadSize(data, size); + } + + /* We can resume if we can seek to the resume position */ + if(data->state.resume_from) { + if(data->state.resume_from < 0) { + /* We're supposed to download the last abs(from) bytes */ + if((curl_off_t)size < -data->state.resume_from) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* download from where? */ + data->state.resume_from += size; + } + else { + if((curl_off_t)size < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + } + /* Does a completed file need to be seeked and started or closed ? */ + /* Now store the number of bytes we are expected to download */ + data->req.size = size - data->state.resume_from; + data->req.maxdownload = size - data->state.resume_from; + Curl_pgrsSetDownloadSize(data, + size - data->state.resume_from); + + rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); + if(rc != 0) { + MOVE_TO_SFTP_CLOSE_STATE(); + } + } + } + + /* Setup the actual download */ + if(data->req.size == 0) { + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + infof(data, "File already completely downloaded\n"); + state(conn, SSH_STOP); + break; + } + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + if(result) { + /* this should never occur; the close state should be entered + at the time the error occurs */ + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + sshc->sftp_recv_state = 0; + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_CLOSE: + if(sshc->sftp_file) { + sftp_close(sshc->sftp_file); + sshc->sftp_file = NULL; + } + Curl_safefree(protop->path); + + DEBUGF(infof(data, "SFTP DONE done\n")); + + /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT + After nextstate is executed, the control should come back to + SSH_SFTP_CLOSE to pass the correct result back */ + if(sshc->nextstate != SSH_NO_STATE && + sshc->nextstate != SSH_SFTP_CLOSE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_SFTP_CLOSE; + } + else { + state(conn, SSH_STOP); + result = sshc->actualcode; + } + break; + + case SSH_SFTP_SHUTDOWN: + /* during times we get here due to a broken transfer and then the + sftp_handle might not have been taken down so make sure that is done + before we proceed */ + + if(sshc->sftp_file) { + sftp_close(sshc->sftp_file); + sshc->sftp_file = NULL; + } + + if(sshc->sftp_session) { + sftp_free(sshc->sftp_session); + sshc->sftp_session = NULL; + } + + SSH_STRING_FREE_CHAR(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_DISCONNECT); + break; + + + case SSH_SCP_TRANS_INIT: + result = Curl_getworkingpath(conn, sshc->homedir, &protop->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */ + ssh_set_blocking(sshc->ssh_session, 1); + + if(data->set.upload) { + if(data->state.infilesize < 0) { + failf(data, "SCP requires a known file size for upload"); + sshc->actualcode = CURLE_UPLOAD_FAILED; + MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + } + + sshc->scp_session = + ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path); + state(conn, SSH_SCP_UPLOAD_INIT); + } + else { + sshc->scp_session = + ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path); + state(conn, SSH_SCP_DOWNLOAD_INIT); + } + + if(!sshc->scp_session) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + } + + break; + + case SSH_SCP_UPLOAD_INIT: + + rc = ssh_scp_init(sshc->scp_session); + if(rc != SSH_OK) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + } + + rc = ssh_scp_push_file(sshc->scp_session, protop->path, + data->state.infilesize, + (int)data->set.new_file_perms); + if(rc != SSH_OK) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + } + + /* upload data */ + Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh scp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + state(conn, SSH_STOP); + + break; + + case SSH_SCP_DOWNLOAD_INIT: + + rc = ssh_scp_init(sshc->scp_session); + if(rc != SSH_OK) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + } + state(conn, SSH_SCP_DOWNLOAD); + /* FALLTHROUGH */ + + case SSH_SCP_DOWNLOAD:{ + curl_off_t bytecount; + + rc = ssh_scp_pull_request(sshc->scp_session); + if(rc != SSH_SCP_REQUEST_NEWFILE) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(conn->data, "%s", err_msg); + MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND); + break; + } + + /* download data */ + bytecount = ssh_scp_request_get_size(sshc->scp_session); + data->req.maxdownload = (curl_off_t) bytecount; + Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + state(conn, SSH_STOP); + break; + } + case SSH_SCP_DONE: + if(data->set.upload) + state(conn, SSH_SCP_SEND_EOF); + else + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_SEND_EOF: + if(sshc->scp_session) { + rc = ssh_scp_close(sshc->scp_session); + if(rc == SSH_AGAIN) { + /* Currently the ssh_scp_close handles waiting for EOF in + * blocking way. + */ + break; + } + if(rc != SSH_OK) { + infof(data, "Failed to close libssh scp channel: %s\n", + ssh_get_error(sshc->ssh_session)); + } + } + + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_CHANNEL_FREE: + if(sshc->scp_session) { + ssh_scp_free(sshc->scp_session); + sshc->scp_session = NULL; + } + DEBUGF(infof(data, "SCP DONE phase complete\n")); + + ssh_set_blocking(sshc->ssh_session, 0); + + state(conn, SSH_SESSION_DISCONNECT); + /* FALLTHROUGH */ + + case SSH_SESSION_DISCONNECT: + /* during weird times when we've been prematurely aborted, the channel + is still alive when we reach this state and we MUST kill the channel + properly first */ + if(sshc->scp_session) { + ssh_scp_free(sshc->scp_session); + sshc->scp_session = NULL; + } + + ssh_disconnect(sshc->ssh_session); + + SSH_STRING_FREE_CHAR(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_FREE); + /* FALLTHROUGH */ + case SSH_SESSION_FREE: + if(sshc->ssh_session) { + ssh_free(sshc->ssh_session); + sshc->ssh_session = NULL; + } + + /* worst-case scenario cleanup */ + + DEBUGASSERT(sshc->ssh_session == NULL); + DEBUGASSERT(sshc->scp_session == NULL); + + if(sshc->readdir_tmp) { + ssh_string_free_char(sshc->readdir_tmp); + sshc->readdir_tmp = NULL; + } + + if(sshc->quote_attrs) + sftp_attributes_free(sshc->quote_attrs); + + if(sshc->readdir_attrs) + sftp_attributes_free(sshc->readdir_attrs); + + if(sshc->readdir_link_attrs) + sftp_attributes_free(sshc->readdir_link_attrs); + + if(sshc->privkey) + ssh_key_free(sshc->privkey); + if(sshc->pubkey) + ssh_key_free(sshc->pubkey); + + Curl_safefree(sshc->rsa_pub); + Curl_safefree(sshc->rsa); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + Curl_safefree(sshc->readdir_line); + Curl_safefree(sshc->readdir_linkPath); + SSH_STRING_FREE_CHAR(sshc->homedir); + + /* the code we are about to return */ + result = sshc->actualcode; + + memset(sshc, 0, sizeof(struct ssh_conn)); + + connclose(conn, "SSH session free"); + sshc->state = SSH_SESSION_FREE; /* current */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + + case SSH_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + + } + } while(!rc && (sshc->state != SSH_STOP)); + + + if(rc == SSH_AGAIN) { + /* we would block, we need to wait for the socket to be ready (in the + right direction too)! */ + *block = TRUE; + } + + return result; +} + + +/* called by the multi interface to figure out what socket(s) to wait for and + for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ +static int myssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ + int bitmap = GETSOCK_BLANK; + (void) numsocks; + + sock[0] = conn->sock[FIRSTSOCKET]; + + if(conn->waitfor & KEEP_RECV) + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + + if(conn->waitfor & KEEP_SEND) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +} + +/* Generic function called by the multi interface to figure out what socket(s) + to wait for and for what actions during the DOING and PROTOCONNECT states*/ +static int myssh_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ + /* if we know the direction we can use the generic *_getsock() function even + for the protocol_connect and doing states */ + return myssh_perform_getsock(conn, sock, numsocks); +} + +static void myssh_block2waitfor(struct connectdata *conn, bool block) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + + /* If it didn't block, or nothing was returned by ssh_get_poll_flags + * have the original set */ + conn->waitfor = sshc->orig_waitfor; + + if(block) { + int dir = ssh_get_poll_flags(sshc->ssh_session); + if(dir & SSH_READ_PENDING) { + /* translate the libssh define bits into our own bit defines */ + conn->waitfor = KEEP_RECV; + } + else if(dir & SSH_WRITE_PENDING) { + conn->waitfor = KEEP_SEND; + } + } +} + +/* called repeatedly until done from multi.c */ +static CURLcode myssh_multi_statemach(struct connectdata *conn, + bool *done) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + bool block; /* we store the status and use that to provide a ssh_getsock() + implementation */ + CURLcode result = myssh_statemach_act(conn, &block); + + *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + myssh_block2waitfor(conn, block); + + return result; +} + +static CURLcode myssh_block_statemach(struct connectdata *conn, + bool disconnect) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + while((sshc->state != SSH_STOP) && !result) { + bool block; + timediff_t left = 1000; + struct curltime now = Curl_now(); + + result = myssh_statemach_act(conn, &block); + if(result) + break; + + if(!disconnect) { + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + result = Curl_speedcheck(data, now); + if(result) + break; + + left = Curl_timeleft(data, NULL, FALSE); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } + } + + if(!result && block) { + curl_socket_t fd_read = conn->sock[FIRSTSOCKET]; + /* wait for the socket to become ready */ + (void) Curl_socket_check(fd_read, CURL_SOCKET_BAD, + CURL_SOCKET_BAD, left > 1000 ? 1000 : left); + } + + } + + return result; +} + +/* + * SSH setup connection + */ +static CURLcode myssh_setup_connection(struct connectdata *conn) +{ + struct SSHPROTO *ssh; + + conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO)); + if(!ssh) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +static Curl_recv scp_recv, sftp_recv; +static Curl_send scp_send, sftp_send; + +/* + * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to + * do protocol-specific actions at connect-time. + */ +static CURLcode myssh_connect(struct connectdata *conn, bool *done) +{ + struct ssh_conn *ssh; + CURLcode result; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data = conn->data; + + /* initialize per-handle data if not already */ + if(!data->req.protop) + myssh_setup_connection(conn); + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "SSH default"); + + if(conn->handler->protocol & CURLPROTO_SCP) { + conn->recv[FIRSTSOCKET] = scp_recv; + conn->send[FIRSTSOCKET] = scp_send; + } + else { + conn->recv[FIRSTSOCKET] = sftp_recv; + conn->send[FIRSTSOCKET] = sftp_send; + } + + ssh = &conn->proto.sshc; + + ssh->ssh_session = ssh_new(); + if(ssh->ssh_session == NULL) { + failf(data, "Failure initialising ssh session"); + return CURLE_FAILED_INIT; + } + + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_FD, &sock); + + if(conn->user) { + infof(data, "User: %s\n", conn->user); + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user); + } + + if(data->set.str[STRING_SSH_KNOWNHOSTS]) { + infof(data, "Known hosts: %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]); + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS, + data->set.str[STRING_SSH_KNOWNHOSTS]); + } + + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, conn->host.name); + if(conn->remote_port) + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_PORT, + &conn->remote_port); + + if(data->set.ssh_compression) { + ssh_options_set(ssh->ssh_session, SSH_OPTIONS_COMPRESSION, + "zlib,zlib@openssh.com,none"); + } + + ssh->privkey = NULL; + ssh->pubkey = NULL; + + if(data->set.str[STRING_SSH_PUBLIC_KEY]) { + int rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY], + &ssh->pubkey); + if(rc != SSH_OK) { + failf(data, "Could not load public key file"); + /* ignore */ + } + } + + /* we do not verify here, we do it at the state machine, + * after connection */ + + state(conn, SSH_INIT); + + result = myssh_multi_statemach(conn, done); + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result; + + result = myssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* + *********************************************************************** + * + * scp_perform() + * + * This is the actual DO function for SCP. Get a file according to + * the options previously setup. + */ + +static +CURLcode scp_perform(struct connectdata *conn, + bool *connected, bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SCP_TRANS_INIT); + + result = myssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +static CURLcode myssh_do_it(struct connectdata *conn, bool *done) +{ + CURLcode result; + bool connected = 0; + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + + *done = FALSE; /* default to false */ + + data->req.size = -1; /* make sure this is unknown at this point */ + + sshc->actualcode = CURLE_OK; /* reset error code */ + sshc->secondCreateDirs = 0; /* reset the create dir attempt state + variable */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + if(conn->handler->protocol & CURLPROTO_SCP) + result = scp_perform(conn, &connected, done); + else + result = sftp_perform(conn, &connected, done); + + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode scp_disconnect(struct connectdata *conn, + bool dead_connection) +{ + CURLcode result = CURLE_OK; + struct ssh_conn *ssh = &conn->proto.sshc; + (void) dead_connection; + + if(ssh->ssh_session) { + /* only if there's a session still around to use! */ + + state(conn, SSH_SESSION_DISCONNECT); + + result = myssh_block_statemach(conn, TRUE); + } + + return result; +} + +/* generic done function for both SCP and SFTP called from their specific + done functions */ +static CURLcode myssh_done(struct connectdata *conn, CURLcode status) +{ + CURLcode result = CURLE_OK; + struct SSHPROTO *protop = conn->data->req.protop; + + if(!status) { + /* run the state-machine */ + result = myssh_block_statemach(conn, FALSE); + } + else + result = status; + + if(protop) + Curl_safefree(protop->path); + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + conn->data->req.keepon = 0; /* clear all bits */ + return result; +} + + +static CURLcode scp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void) premature; /* not used */ + + if(!status) + state(conn, SSH_SCP_DONE); + + return myssh_done(conn, status); + +} + +static ssize_t scp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + int rc; + (void) sockindex; /* we only support SCP on the fixed known primary socket */ + (void) err; + + rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len); + +#if 0 + /* The following code is misleading, mostly added as wishful thinking + * that libssh at some point will implement non-blocking ssh_scp_write/read. + * Currently rc can only be number of bytes read or SSH_ERROR. */ + myssh_block2waitfor(conn, (rc == SSH_AGAIN) ? TRUE : FALSE); + + if(rc == SSH_AGAIN) { + *err = CURLE_AGAIN; + return 0; + } + else +#endif + if(rc != SSH_OK) { + *err = CURLE_SSH; + return -1; + } + + return len; +} + +static ssize_t scp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void) err; + (void) sockindex; /* we only support SCP on the fixed known primary socket */ + + /* libssh returns int */ + nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len); + +#if 0 + /* The following code is misleading, mostly added as wishful thinking + * that libssh at some point will implement non-blocking ssh_scp_write/read. + * Currently rc can only be SSH_OK or SSH_ERROR. */ + + myssh_block2waitfor(conn, (nread == SSH_AGAIN) ? TRUE : FALSE); + if(nread == SSH_AGAIN) { + *err = CURLE_AGAIN; + nread = -1; + } +#endif + + return nread; +} + +/* + * =============== SFTP =============== + */ + +/* + *********************************************************************** + * + * sftp_perform() + * + * This is the actual DO function for SFTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SFTP_QUOTE_INIT); + + /* run the state-machine */ + result = myssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = myssh_multi_statemach(conn, dophase_done); + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + (void) dead_connection; + + DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + + if(conn->proto.sshc.ssh_session) { + /* only if there's a session still around to use! */ + state(conn, SSH_SFTP_SHUTDOWN); + result = myssh_block_statemach(conn, TRUE); + } + + DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + + return result; + +} + +static CURLcode sftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + + if(!status) { + /* Post quote commands are executed after the SFTP_CLOSE state to avoid + errors that could happen due to open file handles during POSTQUOTE + operation */ + if(!premature && conn->data->set.postquote && !conn->bits.retry) + sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; + state(conn, SSH_SFTP_CLOSE); + } + return myssh_done(conn, status); +} + +/* return number of sent bytes */ +static ssize_t sftp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite; + (void)sockindex; + + nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len); + + myssh_block2waitfor(conn, FALSE); + +#if 0 /* not returned by libssh on write */ + if(nwrite == SSH_AGAIN) { + *err = CURLE_AGAIN; + nwrite = 0; + } + else +#endif + if(nwrite < 0) { + *err = CURLE_SSH; + nwrite = -1; + } + + return nwrite; +} + +/* + * Return number of received (decrypted) bytes + * or <0 on error + */ +static ssize_t sftp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void)sockindex; + + DEBUGASSERT(len < CURL_MAX_READ_SIZE); + + switch(conn->proto.sshc.sftp_recv_state) { + case 0: + conn->proto.sshc.sftp_file_index = + sftp_async_read_begin(conn->proto.sshc.sftp_file, + (uint32_t)len); + if(conn->proto.sshc.sftp_file_index < 0) { + *err = CURLE_RECV_ERROR; + return -1; + } + + /* FALLTHROUGH */ + case 1: + conn->proto.sshc.sftp_recv_state = 1; + + nread = sftp_async_read(conn->proto.sshc.sftp_file, + mem, (uint32_t)len, + conn->proto.sshc.sftp_file_index); + + myssh_block2waitfor(conn, (nread == SSH_AGAIN)?TRUE:FALSE); + + if(nread == SSH_AGAIN) { + *err = CURLE_AGAIN; + return -1; + } + else if(nread < 0) { + *err = CURLE_RECV_ERROR; + return -1; + } + + conn->proto.sshc.sftp_recv_state = 0; + return nread; + + default: + /* we never reach here */ + return -1; + } +} + +static void sftp_quote(struct connectdata *conn) +{ + const char *cp; + struct Curl_easy *data = conn->data; + struct SSHPROTO *protop = data->req.protop; + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result; + + /* + * Support some of the "FTP" commands + */ + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + if(strcasecompare("pwd", cmd)) { + /* output debug output if that is requested */ + char *tmp = aprintf("257 \"%s\" is current directory.\n", + protop->path); + if(!tmp) { + sshc->actualcode = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + return; + } + if(data->set.verbose) { + Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4); + Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp)); + } + /* this sends an FTP-like "header" to the header callback so that the + current directory can be read very similar to how it is read when + using ordinary FTP. */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + else + state(conn, SSH_SFTP_NEXT_QUOTE); + return; + } + + /* + * the arguments following the command must be separated from the + * command with a space so we can check for it unconditionally + */ + cp = strchr(cmd, ' '); + if(cp == NULL) { + failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + + /* + * also, every command takes at least one argument so we get that + * first argument right now + */ + result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error: Bad first parameter"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + return; + } + + /* + * SFTP is a binary protocol, so we don't send text commands + * to the server. Instead, we scan for commands used by + * OpenSSH's sftp program and call the appropriate libssh + * functions. + */ + if(strncasecompare(cmd, "chgrp ", 6) || + strncasecompare(cmd, "chmod ", 6) || + strncasecompare(cmd, "chown ", 6)) { + /* attribute change */ + + /* sshc->quote_path1 contains the mode to set */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in chgrp/chmod/chown: " + "Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + return; + } + sshc->quote_attrs = NULL; + state(conn, SSH_SFTP_QUOTE_STAT); + return; + } + if(strncasecompare(cmd, "ln ", 3) || + strncasecompare(cmd, "symlink ", 8)) { + /* symbolic linking */ + /* sshc->quote_path1 is the source */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in ln/symlink: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + return; + } + state(conn, SSH_SFTP_QUOTE_SYMLINK); + return; + } + else if(strncasecompare(cmd, "mkdir ", 6)) { + /* create dir */ + state(conn, SSH_SFTP_QUOTE_MKDIR); + return; + } + else if(strncasecompare(cmd, "rename ", 7)) { + /* rename file */ + /* first param is the source path */ + /* second param is the dest. path */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in rename: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + return; + } + state(conn, SSH_SFTP_QUOTE_RENAME); + return; + } + else if(strncasecompare(cmd, "rmdir ", 6)) { + /* delete dir */ + state(conn, SSH_SFTP_QUOTE_RMDIR); + return; + } + else if(strncasecompare(cmd, "rm ", 3)) { + state(conn, SSH_SFTP_QUOTE_UNLINK); + return; + } +#ifdef HAS_STATVFS_SUPPORT + else if(strncasecompare(cmd, "statvfs ", 8)) { + state(conn, SSH_SFTP_QUOTE_STATVFS); + return; + } +#endif + + failf(data, "Unknown SFTP command"); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; +} + +static void sftp_quote_stat(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + /* We read the file attributes, store them in sshc->quote_attrs + * and modify them accordingly to command. Then we switch to + * QUOTE_SETSTAT state to write new ones. + */ + + if(sshc->quote_attrs) + sftp_attributes_free(sshc->quote_attrs); + sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2); + if(sshc->quote_attrs == NULL) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to get SFTP stats failed: %d", + sftp_get_error(sshc->sftp_session)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + + /* Now set the new attributes... */ + if(strncasecompare(cmd, "chgrp", 5)) { + sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10); + if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chgrp gid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID; + } + else if(strncasecompare(cmd, "chmod", 5)) { + mode_t perms; + perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8); + /* permissions are octal */ + if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chmod permissions not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + sshc->quote_attrs->permissions = perms; + sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS; + } + else if(strncasecompare(cmd, "chown", 5)) { + sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10); + if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chown uid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + return; + } + sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID; + } + + /* Now send the completed structure... */ + state(conn, SSH_SFTP_QUOTE_SETSTAT); + return; +} + + +#endif /* USE_LIBSSH */ diff --git a/libcurl/lib/ssh.c b/libcurl/lib/ssh.c new file mode 100644 index 0000000..a265c3c --- /dev/null +++ b/libcurl/lib/ssh.c @@ -0,0 +1,3337 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* #define CURL_LIBSSH2_DEBUG */ + +#include "curl_setup.h" + +#ifdef USE_LIBSSH2 + +#include + +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "ssh.h" +#include "url.h" +#include "speedcheck.h" +#include "getinfo.h" +#include "strdup.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "strtoofft.h" +#include "multiif.h" +#include "select.h" +#include "warnless.h" +#include "curl_path.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if LIBSSH2_VERSION_NUM >= 0x010206 +/* libssh2_sftp_statvfs and friends were added in 1.2.6 */ +#define HAS_STATVFS_SUPPORT 1 +#endif + +#define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s)) + +#define sftp_libssh2_realpath(s,p,t,m) \ + libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \ + (t), (m), LIBSSH2_SFTP_REALPATH) + + +/* Local functions: */ +static const char *sftp_libssh2_strerror(int err); +static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); +static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc); +static LIBSSH2_FREE_FUNC(my_libssh2_free); + +static CURLcode ssh_connect(struct connectdata *conn, bool *done); +static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done); +static CURLcode ssh_do(struct connectdata *conn, bool *done); + +static CURLcode scp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode scp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection); + +static CURLcode sftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead); +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done); + +static int ssh_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks); + +static int ssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks); + +static CURLcode ssh_setup_connection(struct connectdata *conn); + +/* + * SCP protocol handler. + */ + +const struct Curl_handler Curl_handler_scp = { + "SCP", /* scheme */ + ssh_setup_connection, /* setup_connection */ + ssh_do, /* do_it */ + scp_done, /* done */ + ZERO_NULL, /* do_more */ + ssh_connect, /* connect_it */ + ssh_multi_statemach, /* connecting */ + scp_doing, /* doing */ + ssh_getsock, /* proto_getsock */ + ssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ssh_perform_getsock, /* perform_getsock */ + scp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + + +/* + * SFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_sftp = { + "SFTP", /* scheme */ + ssh_setup_connection, /* setup_connection */ + ssh_do, /* do_it */ + sftp_done, /* done */ + ZERO_NULL, /* do_more */ + ssh_connect, /* connect_it */ + ssh_multi_statemach, /* connecting */ + sftp_doing, /* doing */ + ssh_getsock, /* proto_getsock */ + ssh_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ssh_perform_getsock, /* perform_getsock */ + sftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION + | PROTOPT_NOURLQUERY /* flags */ +}; + +static void +kbd_callback(const char *name, int name_len, const char *instruction, + int instruction_len, int num_prompts, + const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, + void **abstract) +{ + struct connectdata *conn = (struct connectdata *)*abstract; + +#ifdef CURL_LIBSSH2_DEBUG + fprintf(stderr, "name=%s\n", name); + fprintf(stderr, "name_len=%d\n", name_len); + fprintf(stderr, "instruction=%s\n", instruction); + fprintf(stderr, "instruction_len=%d\n", instruction_len); + fprintf(stderr, "num_prompts=%d\n", num_prompts); +#else + (void)name; + (void)name_len; + (void)instruction; + (void)instruction_len; +#endif /* CURL_LIBSSH2_DEBUG */ + if(num_prompts == 1) { + responses[0].text = strdup(conn->passwd); + responses[0].length = curlx_uztoui(strlen(conn->passwd)); + } + (void)prompts; + (void)abstract; +} /* kbd_callback */ + +static CURLcode sftp_libssh2_error_to_CURLE(int err) +{ + switch(err) { + case LIBSSH2_FX_OK: + return CURLE_OK; + + case LIBSSH2_FX_NO_SUCH_FILE: + case LIBSSH2_FX_NO_SUCH_PATH: + return CURLE_REMOTE_FILE_NOT_FOUND; + + case LIBSSH2_FX_PERMISSION_DENIED: + case LIBSSH2_FX_WRITE_PROTECT: + case LIBSSH2_FX_LOCK_CONFlICT: + return CURLE_REMOTE_ACCESS_DENIED; + + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + case LIBSSH2_FX_QUOTA_EXCEEDED: + return CURLE_REMOTE_DISK_FULL; + + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + return CURLE_REMOTE_FILE_EXISTS; + + case LIBSSH2_FX_DIR_NOT_EMPTY: + return CURLE_QUOTE_ERROR; + + default: + break; + } + + return CURLE_SSH; +} + +static CURLcode libssh2_session_error_to_CURLE(int err) +{ + switch(err) { + /* Ordered by order of appearance in libssh2.h */ + case LIBSSH2_ERROR_NONE: + return CURLE_OK; + + /* This is the error returned by libssh2_scp_recv2 + * on unknown file */ + case LIBSSH2_ERROR_SCP_PROTOCOL: + return CURLE_REMOTE_FILE_NOT_FOUND; + + case LIBSSH2_ERROR_SOCKET_NONE: + return CURLE_COULDNT_CONNECT; + + case LIBSSH2_ERROR_ALLOC: + return CURLE_OUT_OF_MEMORY; + + case LIBSSH2_ERROR_SOCKET_SEND: + return CURLE_SEND_ERROR; + + case LIBSSH2_ERROR_HOSTKEY_INIT: + case LIBSSH2_ERROR_HOSTKEY_SIGN: + case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED: + case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: + return CURLE_PEER_FAILED_VERIFICATION; + + case LIBSSH2_ERROR_PASSWORD_EXPIRED: + return CURLE_LOGIN_DENIED; + + case LIBSSH2_ERROR_SOCKET_TIMEOUT: + case LIBSSH2_ERROR_TIMEOUT: + return CURLE_OPERATION_TIMEDOUT; + + case LIBSSH2_ERROR_EAGAIN: + return CURLE_AGAIN; + } + + return CURLE_SSH; +} + +static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc) +{ + (void)abstract; /* arg not used */ + return malloc(count); +} + +static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc) +{ + (void)abstract; /* arg not used */ + return realloc(ptr, count); +} + +static LIBSSH2_FREE_FUNC(my_libssh2_free) +{ + (void)abstract; /* arg not used */ + if(ptr) /* ssh2 agent sometimes call free with null ptr */ + free(ptr); +} + +/* + * SSH State machine related code + */ +/* This is the ONLY way to change SSH state! */ +static void state(struct connectdata *conn, sshstate nowstate) +{ + struct ssh_conn *sshc = &conn->proto.sshc; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ + static const char * const names[] = { + "SSH_STOP", + "SSH_INIT", + "SSH_S_STARTUP", + "SSH_HOSTKEY", + "SSH_AUTHLIST", + "SSH_AUTH_PKEY_INIT", + "SSH_AUTH_PKEY", + "SSH_AUTH_PASS_INIT", + "SSH_AUTH_PASS", + "SSH_AUTH_AGENT_INIT", + "SSH_AUTH_AGENT_LIST", + "SSH_AUTH_AGENT", + "SSH_AUTH_HOST_INIT", + "SSH_AUTH_HOST", + "SSH_AUTH_KEY_INIT", + "SSH_AUTH_KEY", + "SSH_AUTH_GSSAPI", + "SSH_AUTH_DONE", + "SSH_SFTP_INIT", + "SSH_SFTP_REALPATH", + "SSH_SFTP_QUOTE_INIT", + "SSH_SFTP_POSTQUOTE_INIT", + "SSH_SFTP_QUOTE", + "SSH_SFTP_NEXT_QUOTE", + "SSH_SFTP_QUOTE_STAT", + "SSH_SFTP_QUOTE_SETSTAT", + "SSH_SFTP_QUOTE_SYMLINK", + "SSH_SFTP_QUOTE_MKDIR", + "SSH_SFTP_QUOTE_RENAME", + "SSH_SFTP_QUOTE_RMDIR", + "SSH_SFTP_QUOTE_UNLINK", + "SSH_SFTP_QUOTE_STATVFS", + "SSH_SFTP_GETINFO", + "SSH_SFTP_FILETIME", + "SSH_SFTP_TRANS_INIT", + "SSH_SFTP_UPLOAD_INIT", + "SSH_SFTP_CREATE_DIRS_INIT", + "SSH_SFTP_CREATE_DIRS", + "SSH_SFTP_CREATE_DIRS_MKDIR", + "SSH_SFTP_READDIR_INIT", + "SSH_SFTP_READDIR", + "SSH_SFTP_READDIR_LINK", + "SSH_SFTP_READDIR_BOTTOM", + "SSH_SFTP_READDIR_DONE", + "SSH_SFTP_DOWNLOAD_INIT", + "SSH_SFTP_DOWNLOAD_STAT", + "SSH_SFTP_CLOSE", + "SSH_SFTP_SHUTDOWN", + "SSH_SCP_TRANS_INIT", + "SSH_SCP_UPLOAD_INIT", + "SSH_SCP_DOWNLOAD_INIT", + "SSH_SCP_DOWNLOAD", + "SSH_SCP_DONE", + "SSH_SCP_SEND_EOF", + "SSH_SCP_WAIT_EOF", + "SSH_SCP_WAIT_CLOSE", + "SSH_SCP_CHANNEL_FREE", + "SSH_SESSION_DISCONNECT", + "SSH_SESSION_FREE", + "QUIT" + }; + + /* a precaution to make sure the lists are in sync */ + DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); + + if(sshc->state != nowstate) { + infof(conn->data, "SFTP %p state change from %s to %s\n", + (void *)sshc, names[sshc->state], names[nowstate]); + } +#endif + + sshc->state = nowstate; +} + + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API +static int sshkeycallback(struct Curl_easy *easy, + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch match, + void *clientp) +{ + (void)easy; + (void)knownkey; + (void)foundkey; + (void)clientp; + + /* we only allow perfect matches, and we reject everything else */ + return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE; +} +#endif + +/* + * Earlier libssh2 versions didn't have the ability to seek to 64bit positions + * with 32bit size_t. + */ +#ifdef HAVE_LIBSSH2_SFTP_SEEK64 +#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y) +#else +#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y) +#endif + +/* + * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit + * architectures so we check of the necessary function is present. + */ +#ifndef HAVE_LIBSSH2_SCP_SEND64 +#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0) +#else +#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \ + (libssh2_uint64_t)d, 0, 0) +#endif + +/* + * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64. + */ +#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE +#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y) +#endif + +static CURLcode ssh_knownhost(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + struct Curl_easy *data = conn->data; + + if(data->set.str[STRING_SSH_KNOWNHOSTS]) { + /* we're asked to verify the host against a file */ + struct ssh_conn *sshc = &conn->proto.sshc; + int rc; + int keytype; + size_t keylen; + const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, + &keylen, &keytype); + int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE; + int keybit = 0; + + if(remotekey) { + /* + * A subject to figure out is what host name we need to pass in here. + * What host name does OpenSSH store in its file if an IDN name is + * used? + */ + struct libssh2_knownhost *host; + enum curl_khmatch keymatch; + curl_sshkeycallback func = + data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback; + struct curl_khkey knownkey; + struct curl_khkey *knownkeyp = NULL; + struct curl_khkey foundkey; + + keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS; + +#ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP + keycheck = libssh2_knownhost_checkp(sshc->kh, + conn->host.name, + (conn->remote_port != PORT_SSH)? + conn->remote_port:-1, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, + &host); +#else + keycheck = libssh2_knownhost_check(sshc->kh, + conn->host.name, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, + &host); +#endif + + infof(data, "SSH host check: %d, key: %s\n", keycheck, + (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? + host->key:""); + + /* setup 'knownkey' */ + if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) { + knownkey.key = host->key; + knownkey.len = 0; + knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + CURLKHTYPE_RSA : CURLKHTYPE_DSS; + knownkeyp = &knownkey; + } + + /* setup 'foundkey' */ + foundkey.key = remotekey; + foundkey.len = keylen; + foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? + CURLKHTYPE_RSA : CURLKHTYPE_DSS; + + /* + * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the + * curl_khmatch enum are ever modified, we need to introduce a + * translation table here! + */ + keymatch = (enum curl_khmatch)keycheck; + + /* Ask the callback how to behave */ + Curl_set_in_callback(data, true); + rc = func(data, knownkeyp, /* from the knownhosts file */ + &foundkey, /* from the remote host */ + keymatch, data->set.ssh_keyfunc_userp); + Curl_set_in_callback(data, false); + } + else + /* no remotekey means failure! */ + rc = CURLKHSTAT_REJECT; + + switch(rc) { + default: /* unknown return codes will equal reject */ + /* FALLTHROUGH */ + case CURLKHSTAT_REJECT: + state(conn, SSH_SESSION_FREE); + /* FALLTHROUGH */ + case CURLKHSTAT_DEFER: + /* DEFER means bail out but keep the SSH_HOSTKEY state */ + result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + break; + case CURLKHSTAT_FINE: + case CURLKHSTAT_FINE_ADD_TO_FILE: + /* proceed */ + if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { + /* the found host+key didn't match but has been told to be fine + anyway so we add it in memory */ + int addrc = libssh2_knownhost_add(sshc->kh, + conn->host.name, NULL, + remotekey, keylen, + LIBSSH2_KNOWNHOST_TYPE_PLAIN| + LIBSSH2_KNOWNHOST_KEYENC_RAW| + keybit, NULL); + if(addrc) + infof(data, "Warning adding the known host %s failed!\n", + conn->host.name); + else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) { + /* now we write the entire in-memory list of known hosts to the + known_hosts file */ + int wrc = + libssh2_knownhost_writefile(sshc->kh, + data->set.str[STRING_SSH_KNOWNHOSTS], + LIBSSH2_KNOWNHOST_FILE_OPENSSH); + if(wrc) { + infof(data, "Warning, writing %s failed!\n", + data->set.str[STRING_SSH_KNOWNHOSTS]); + } + } + } + break; + } + } +#else /* HAVE_LIBSSH2_KNOWNHOST_API */ + (void)conn; +#endif + return result; +} + +static CURLcode ssh_check_fingerprint(struct connectdata *conn) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + struct Curl_easy *data = conn->data; + const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; + char md5buffer[33]; + + const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session, + LIBSSH2_HOSTKEY_HASH_MD5); + + if(fingerprint) { + /* The fingerprint points to static storage (!), don't free() it. */ + int i; + for(i = 0; i < 16; i++) + msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]); + infof(data, "SSH MD5 fingerprint: %s\n", md5buffer); + } + + /* Before we authenticate we check the hostkey's MD5 fingerprint + * against a known fingerprint, if available. + */ + if(pubkey_md5 && strlen(pubkey_md5) == 32) { + if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) { + if(fingerprint) + failf(data, + "Denied establishing ssh session: mismatch md5 fingerprint. " + "Remote %s is not equal to %s", md5buffer, pubkey_md5); + else + failf(data, + "Denied establishing ssh session: md5 fingerprint not available"); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + return sshc->actualcode; + } + infof(data, "MD5 checksum match!\n"); + /* as we already matched, we skip the check for known hosts */ + return CURLE_OK; + } + return ssh_knownhost(conn); +} + +/* + * ssh_statemach_act() runs the SSH state machine as far as it can without + * blocking and without reaching the end. The data the pointer 'block' points + * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN + * meaning it wants to be called again when the socket is ready + */ + +static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct SSHPROTO *sftp_scp = data->req.protop; + struct ssh_conn *sshc = &conn->proto.sshc; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + char *new_readdir_line; + int rc = LIBSSH2_ERROR_NONE; + int err; + int seekerr = CURL_SEEKFUNC_OK; + *block = 0; /* we're not blocking by default */ + + do { + + switch(sshc->state) { + case SSH_INIT: + sshc->secondCreateDirs = 0; + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_OK; + + /* Set libssh2 to non-blocking, since everything internally is + non-blocking */ + libssh2_session_set_blocking(sshc->ssh_session, 0); + + state(conn, SSH_S_STARTUP); + /* FALLTHROUGH */ + + case SSH_S_STARTUP: + rc = libssh2_session_startup(sshc->ssh_session, (int)sock); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); + failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg); + + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_FAILED_INIT; + break; + } + + state(conn, SSH_HOSTKEY); + + /* FALLTHROUGH */ + case SSH_HOSTKEY: + /* + * Before we authenticate we should check the hostkey's fingerprint + * against our known hosts. How that is handled (reading from file, + * whatever) is up to us. + */ + result = ssh_check_fingerprint(conn); + if(!result) + state(conn, SSH_AUTHLIST); + /* ssh_check_fingerprint sets state appropriately on error */ + break; + + case SSH_AUTHLIST: + /* + * Figure out authentication methods + * NB: As soon as we have provided a username to an openssh server we + * must never change it later. Thus, always specify the correct username + * here, even though the libssh2 docs kind of indicate that it should be + * possible to get a 'generic' list (not user-specific) of authentication + * methods, presumably with a blank username. That won't work in my + * experience. + * So always specify it here. + */ + sshc->authlist = libssh2_userauth_list(sshc->ssh_session, + conn->user, + curlx_uztoui(strlen(conn->user))); + + if(!sshc->authlist) { + if(libssh2_userauth_authenticated(sshc->ssh_session)) { + sshc->authed = TRUE; + infof(data, "SSH user accepted with no authentication\n"); + state(conn, SSH_AUTH_DONE); + break; + } + err = libssh2_session_last_errno(sshc->ssh_session); + if(err == LIBSSH2_ERROR_EAGAIN) + rc = LIBSSH2_ERROR_EAGAIN; + else { + state(conn, SSH_SESSION_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(err); + } + break; + } + infof(data, "SSH authentication methods available: %s\n", + sshc->authlist); + + state(conn, SSH_AUTH_PKEY_INIT); + break; + + case SSH_AUTH_PKEY_INIT: + /* + * Check the supported auth types in the order I feel is most secure + * with the requested type of authentication + */ + sshc->authed = FALSE; + + if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && + (strstr(sshc->authlist, "publickey") != NULL)) { + bool out_of_memory = FALSE; + + sshc->rsa_pub = sshc->rsa = NULL; + + if(data->set.str[STRING_SSH_PRIVATE_KEY]) + sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); + else { + /* To ponder about: should really the lib be messing about with the + HOME environment variable etc? */ + char *home = curl_getenv("HOME"); + + /* If no private key file is specified, try some common paths. */ + if(home) { + /* Try ~/.ssh first. */ + sshc->rsa = aprintf("%s/.ssh/id_rsa", home); + if(!sshc->rsa) + out_of_memory = TRUE; + else if(access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + sshc->rsa = aprintf("%s/.ssh/id_dsa", home); + if(!sshc->rsa) + out_of_memory = TRUE; + else if(access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + } + } + free(home); + } + if(!out_of_memory && !sshc->rsa) { + /* Nothing found; try the current dir. */ + sshc->rsa = strdup("id_rsa"); + if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + sshc->rsa = strdup("id_dsa"); + if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { + Curl_safefree(sshc->rsa); + /* Out of guesses. Set to the empty string to avoid + * surprising info messages. */ + sshc->rsa = strdup(""); + } + } + } + } + + /* + * Unless the user explicitly specifies a public key file, let + * libssh2 extract the public key from the private key file. + * This is done by simply passing sshc->rsa_pub = NULL. + */ + if(data->set.str[STRING_SSH_PUBLIC_KEY] + /* treat empty string the same way as NULL */ + && data->set.str[STRING_SSH_PUBLIC_KEY][0]) { + sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); + if(!sshc->rsa_pub) + out_of_memory = TRUE; + } + + if(out_of_memory || sshc->rsa == NULL) { + Curl_safefree(sshc->rsa); + Curl_safefree(sshc->rsa_pub); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + sshc->passphrase = data->set.ssl.key_passwd; + if(!sshc->passphrase) + sshc->passphrase = ""; + + if(sshc->rsa_pub) + infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); + infof(data, "Using SSH private key file '%s'\n", sshc->rsa); + + state(conn, SSH_AUTH_PKEY); + } + else { + state(conn, SSH_AUTH_PASS_INIT); + } + break; + + case SSH_AUTH_PKEY: + /* The function below checks if the files exists, no need to stat() here. + */ + rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session, + conn->user, + curlx_uztoui( + strlen(conn->user)), + sshc->rsa_pub, + sshc->rsa, sshc->passphrase); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + + Curl_safefree(sshc->rsa_pub); + Curl_safefree(sshc->rsa); + + if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized SSH public key authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "SSH public key authentication failed: %s\n", err_msg); + state(conn, SSH_AUTH_PASS_INIT); + rc = 0; /* clear rc and continue */ + } + break; + + case SSH_AUTH_PASS_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) && + (strstr(sshc->authlist, "password") != NULL)) { + state(conn, SSH_AUTH_PASS); + } + else { + state(conn, SSH_AUTH_HOST_INIT); + rc = 0; /* clear rc and continue */ + } + break; + + case SSH_AUTH_PASS: + rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user, + curlx_uztoui(strlen(conn->user)), + conn->passwd, + curlx_uztoui(strlen(conn->passwd)), + NULL); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized password authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + state(conn, SSH_AUTH_HOST_INIT); + rc = 0; /* clear rc and continue */ + } + break; + + case SSH_AUTH_HOST_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && + (strstr(sshc->authlist, "hostbased") != NULL)) { + state(conn, SSH_AUTH_HOST); + } + else { + state(conn, SSH_AUTH_AGENT_INIT); + } + break; + + case SSH_AUTH_HOST: + state(conn, SSH_AUTH_AGENT_INIT); + break; + + case SSH_AUTH_AGENT_INIT: +#ifdef HAVE_LIBSSH2_AGENT_API + if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT) + && (strstr(sshc->authlist, "publickey") != NULL)) { + + /* Connect to the ssh-agent */ + /* The agent could be shared by a curl thread i believe + but nothing obvious as keys can be added/removed at any time */ + if(!sshc->ssh_agent) { + sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session); + if(!sshc->ssh_agent) { + infof(data, "Could not create agent object\n"); + + state(conn, SSH_AUTH_KEY_INIT); + break; + } + } + + rc = libssh2_agent_connect(sshc->ssh_agent); + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + if(rc < 0) { + infof(data, "Failure connecting to agent\n"); + state(conn, SSH_AUTH_KEY_INIT); + rc = 0; /* clear rc and continue */ + } + else { + state(conn, SSH_AUTH_AGENT_LIST); + } + } + else +#endif /* HAVE_LIBSSH2_AGENT_API */ + state(conn, SSH_AUTH_KEY_INIT); + break; + + case SSH_AUTH_AGENT_LIST: +#ifdef HAVE_LIBSSH2_AGENT_API + rc = libssh2_agent_list_identities(sshc->ssh_agent); + + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + if(rc < 0) { + infof(data, "Failure requesting identities to agent\n"); + state(conn, SSH_AUTH_KEY_INIT); + rc = 0; /* clear rc and continue */ + } + else { + state(conn, SSH_AUTH_AGENT); + sshc->sshagent_prev_identity = NULL; + } +#endif + break; + + case SSH_AUTH_AGENT: +#ifdef HAVE_LIBSSH2_AGENT_API + /* as prev_identity evolves only after an identity user auth finished we + can safely request it again as long as EAGAIN is returned here or by + libssh2_agent_userauth */ + rc = libssh2_agent_get_identity(sshc->ssh_agent, + &sshc->sshagent_identity, + sshc->sshagent_prev_identity); + if(rc == LIBSSH2_ERROR_EAGAIN) + break; + + if(rc == 0) { + rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user, + sshc->sshagent_identity); + + if(rc < 0) { + if(rc != LIBSSH2_ERROR_EAGAIN) { + /* tried and failed? go to next identity */ + sshc->sshagent_prev_identity = sshc->sshagent_identity; + } + break; + } + } + + if(rc < 0) + infof(data, "Failure requesting identities to agent\n"); + else if(rc == 1) + infof(data, "No identity would match\n"); + + if(rc == LIBSSH2_ERROR_NONE) { + sshc->authed = TRUE; + infof(data, "Agent based authentication successful\n"); + state(conn, SSH_AUTH_DONE); + } + else { + state(conn, SSH_AUTH_KEY_INIT); + rc = 0; /* clear rc and continue */ + } +#endif + break; + + case SSH_AUTH_KEY_INIT: + if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) + && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { + state(conn, SSH_AUTH_KEY); + } + else { + state(conn, SSH_AUTH_DONE); + } + break; + + case SSH_AUTH_KEY: + /* Authentication failed. Continue with keyboard-interactive now. */ + rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session, + conn->user, + curlx_uztoui( + strlen(conn->user)), + &kbd_callback); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc == 0) { + sshc->authed = TRUE; + infof(data, "Initialized keyboard interactive authentication\n"); + } + state(conn, SSH_AUTH_DONE); + break; + + case SSH_AUTH_DONE: + if(!sshc->authed) { + failf(data, "Authentication failure"); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_LOGIN_DENIED; + break; + } + + /* + * At this point we have an authenticated ssh session. + */ + infof(data, "Authentication complete\n"); + + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ + + conn->sockfd = sock; + conn->writesockfd = CURL_SOCKET_BAD; + + if(conn->handler->protocol == CURLPROTO_SFTP) { + state(conn, SSH_SFTP_INIT); + break; + } + infof(data, "SSH CONNECT phase done\n"); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_INIT: + /* + * Start the libssh2 sftp session + */ + sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session); + if(!sshc->sftp_session) { + char *err_msg = NULL; + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + failf(data, "Failure initializing sftp session: %s", err_msg); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_FAILED_INIT; + break; + } + state(conn, SSH_SFTP_REALPATH); + break; + + case SSH_SFTP_REALPATH: + { + char tempHome[PATH_MAX]; + + /* + * Get the "home" directory + */ + rc = sftp_libssh2_realpath(sshc->sftp_session, ".", + tempHome, PATH_MAX-1); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc > 0) { + /* It seems that this string is not always NULL terminated */ + tempHome[rc] = '\0'; + sshc->homedir = strdup(tempHome); + if(!sshc->homedir) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + conn->data->state.most_recent_ftp_entrypath = sshc->homedir; + } + else { + /* Return the error type */ + err = sftp_libssh2_last_error(sshc->sftp_session); + if(err) + result = sftp_libssh2_error_to_CURLE(err); + else + /* in this case, the error wasn't in the SFTP level but for example + a time-out or similar */ + result = CURLE_SSH; + sshc->actualcode = result; + DEBUGF(infof(data, "error = %d makes libcurl = %d\n", + err, (int)result)); + state(conn, SSH_STOP); + break; + } + } + /* This is the last step in the SFTP connect phase. Do note that while + we get the homedir here, we get the "workingpath" in the DO action + since the homedir will remain the same between request but the + working path will not. */ + DEBUGF(infof(data, "SSH CONNECT phase done\n")); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_QUOTE_INIT: + + result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.quote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.quote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_SFTP_GETINFO); + } + break; + + case SSH_SFTP_POSTQUOTE_INIT: + if(data->set.postquote) { + infof(data, "Sending quote commands\n"); + sshc->quote_item = data->set.postquote; + state(conn, SSH_SFTP_QUOTE); + } + else { + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_QUOTE: + /* Send any quote commands */ + { + const char *cp; + + /* + * Support some of the "FTP" commands + * + * 'sshc->quote_item' is already verified to be non-NULL before it + * switched to this state. + */ + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + if(strcasecompare("pwd", cmd)) { + /* output debug output if that is requested */ + char *tmp = aprintf("257 \"%s\" is current directory.\n", + sftp_scp->path); + if(!tmp) { + result = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + break; + } + if(data->set.verbose) { + Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4); + Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp)); + } + /* this sends an FTP-like "header" to the header callback so that the + current directory can be read very similar to how it is read when + using ordinary FTP. */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + else + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + } + { + /* + * the arguments following the command must be separated from the + * command with a space so we can check for it unconditionally + */ + cp = strchr(cmd, ' '); + if(cp == NULL) { + failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + + /* + * also, every command takes at least one argument so we get that + * first argument right now + */ + result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error: Bad first parameter"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + + /* + * SFTP is a binary protocol, so we don't send text commands + * to the server. Instead, we scan for commands used by + * OpenSSH's sftp program and call the appropriate libssh2 + * functions. + */ + if(strncasecompare(cmd, "chgrp ", 6) || + strncasecompare(cmd, "chmod ", 6) || + strncasecompare(cmd, "chown ", 6) ) { + /* attribute change */ + + /* sshc->quote_path1 contains the mode to set */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in chgrp/chmod/chown: " + "Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); + state(conn, SSH_SFTP_QUOTE_STAT); + break; + } + if(strncasecompare(cmd, "ln ", 3) || + strncasecompare(cmd, "symlink ", 8)) { + /* symbolic linking */ + /* sshc->quote_path1 is the source */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, + "Syntax error in ln/symlink: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + state(conn, SSH_SFTP_QUOTE_SYMLINK); + break; + } + else if(strncasecompare(cmd, "mkdir ", 6)) { + /* create dir */ + state(conn, SSH_SFTP_QUOTE_MKDIR); + break; + } + else if(strncasecompare(cmd, "rename ", 7)) { + /* rename file */ + /* first param is the source path */ + /* second param is the dest. path */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in rename: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + state(conn, SSH_SFTP_QUOTE_RENAME); + break; + } + else if(strncasecompare(cmd, "rmdir ", 6)) { + /* delete dir */ + state(conn, SSH_SFTP_QUOTE_RMDIR); + break; + } + else if(strncasecompare(cmd, "rm ", 3)) { + state(conn, SSH_SFTP_QUOTE_UNLINK); + break; + } +#ifdef HAS_STATVFS_SUPPORT + else if(strncasecompare(cmd, "statvfs ", 8)) { + state(conn, SSH_SFTP_QUOTE_STATVFS); + break; + } +#endif + + failf(data, "Unknown SFTP command"); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + break; + + case SSH_SFTP_NEXT_QUOTE: + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + + sshc->quote_item = sshc->quote_item->next; + + if(sshc->quote_item) { + state(conn, SSH_SFTP_QUOTE); + } + else { + if(sshc->nextstate != SSH_NO_STATE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_NO_STATE; + } + else { + state(conn, SSH_SFTP_GETINFO); + } + } + break; + + case SSH_SFTP_QUOTE_STAT: + { + char *cmd = sshc->quote_item->data; + sshc->acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal SFTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + sshc->acceptfail = TRUE; + } + + if(!strncasecompare(cmd, "chmod", 5)) { + /* Since chown and chgrp only set owner OR group but libssh2 wants to + * set them both at once, we need to obtain the current ownership + * first. This takes an extra protocol round trip. + */ + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_STAT, + &sshc->quote_attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { /* get those attributes */ + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to get SFTP stats failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + + /* Now set the new attributes... */ + if(strncasecompare(cmd, "chgrp", 5)) { + sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; + if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chgrp gid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + else if(strncasecompare(cmd, "chmod", 5)) { + sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; + /* permissions are octal */ + if(sshc->quote_attrs.permissions == 0 && + !ISDIGIT(sshc->quote_path1[0])) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chmod permissions not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + else if(strncasecompare(cmd, "chown", 5)) { + sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10); + sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; + if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) && + !sshc->acceptfail) { + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Syntax error: chown uid not a number"); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + } + + /* Now send the completed structure... */ + state(conn, SSH_SFTP_QUOTE_SETSTAT); + break; + } + + case SSH_SFTP_QUOTE_SETSTAT: + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_SETSTAT, + &sshc->quote_attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "Attempt to set SFTP stats failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_SYMLINK: + rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_SYMLINK); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "symlink command failed: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_MKDIR: + rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + data->set.new_directory_perms); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RENAME: + rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + sshc->quote_path2, + curlx_uztoui(strlen(sshc->quote_path2)), + LIBSSH2_SFTP_RENAME_OVERWRITE | + LIBSSH2_SFTP_RENAME_ATOMIC | + LIBSSH2_SFTP_RENAME_NATIVE); + + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + failf(data, "rename command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_RMDIR: + rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1))); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + + case SSH_SFTP_QUOTE_UNLINK: + rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1))); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "rm command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + +#ifdef HAS_STATVFS_SUPPORT + case SSH_SFTP_QUOTE_STATVFS: + { + LIBSSH2_SFTP_STATVFS statvfs; + rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1, + curlx_uztoui(strlen(sshc->quote_path1)), + &statvfs); + + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc != 0 && !sshc->acceptfail) { + err = sftp_libssh2_last_error(sshc->sftp_session); + Curl_safefree(sshc->quote_path1); + failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } + else if(rc == 0) { + char *tmp = aprintf("statvfs:\n" + "f_bsize: %llu\n" "f_frsize: %llu\n" + "f_blocks: %llu\n" "f_bfree: %llu\n" + "f_bavail: %llu\n" "f_files: %llu\n" + "f_ffree: %llu\n" "f_favail: %llu\n" + "f_fsid: %llu\n" "f_flag: %llu\n" + "f_namemax: %llu\n", + statvfs.f_bsize, statvfs.f_frsize, + statvfs.f_blocks, statvfs.f_bfree, + statvfs.f_bavail, statvfs.f_files, + statvfs.f_ffree, statvfs.f_favail, + statvfs.f_fsid, statvfs.f_flag, + statvfs.f_namemax); + if(!tmp) { + result = CURLE_OUT_OF_MEMORY; + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + break; + } + + result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); + free(tmp); + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + } + } + state(conn, SSH_SFTP_NEXT_QUOTE); + break; + } +#endif + case SSH_SFTP_GETINFO: + { + if(data->set.get_filetime) { + state(conn, SSH_SFTP_FILETIME); + } + else { + state(conn, SSH_SFTP_TRANS_INIT); + } + break; + } + + case SSH_SFTP_FILETIME: + { + LIBSSH2_SFTP_ATTRIBUTES attrs; + + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_SFTP_STAT, &attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc == 0) { + data->info.filetime = attrs.mtime; + } + + state(conn, SSH_SFTP_TRANS_INIT); + break; + } + + case SSH_SFTP_TRANS_INIT: + if(data->set.upload) + state(conn, SSH_SFTP_UPLOAD_INIT); + else { + if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') + state(conn, SSH_SFTP_READDIR_INIT); + else + state(conn, SSH_SFTP_DOWNLOAD_INIT); + } + break; + + case SSH_SFTP_UPLOAD_INIT: + { + unsigned long flags; + /* + * NOTE!!! libssh2 requires that the destination path is a full path + * that includes the destination file and name OR ends in a "/" + * If this is not done the destination file will be named the + * same name as the last directory in the path. + */ + + if(data->state.resume_from != 0) { + LIBSSH2_SFTP_ATTRIBUTES attrs; + if(data->state.resume_from < 0) { + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_SFTP_STAT, &attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + data->state.resume_from = 0; + } + else { + curl_off_t size = attrs.filesize; + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + data->state.resume_from = attrs.filesize; + } + } + } + + if(data->set.ftp_append) + /* Try to open for append, but create if nonexisting */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND; + else if(data->state.resume_from > 0) + /* If we have restart position then open for append */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND; + else + /* Clear file before writing (normal behaviour) */ + flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC; + + sshc->sftp_handle = + libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + flags, data->set.new_file_perms, + LIBSSH2_SFTP_OPENFILE); + + if(!sshc->sftp_handle) { + rc = libssh2_session_last_errno(sshc->ssh_session); + + if(LIBSSH2_ERROR_EAGAIN == rc) + break; + + if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) + /* only when there was an SFTP protocol error can we extract + the sftp error! */ + err = sftp_libssh2_last_error(sshc->sftp_session); + else + err = -1; /* not an sftp error at all */ + + if(sshc->secondCreateDirs) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; + failf(data, "Creating the dir/file failed: %s", + sftp_libssh2_strerror(err)); + break; + } + if(((err == LIBSSH2_FX_NO_SUCH_FILE) || + (err == LIBSSH2_FX_FAILURE) || + (err == LIBSSH2_FX_NO_SUCH_PATH)) && + (data->set.ftp_create_missing_dirs && + (strlen(sftp_scp->path) > 1))) { + /* try to create the path remotely */ + rc = 0; /* clear rc and continue */ + sshc->secondCreateDirs = 1; + state(conn, SSH_SFTP_CREATE_DIRS_INIT); + break; + } + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; + if(!sshc->actualcode) { + /* Sometimes, for some reason libssh2_sftp_last_error() returns + zero even though libssh2_sftp_open() failed previously! We need + to work around that! */ + sshc->actualcode = CURLE_SSH; + err = -1; + } + failf(data, "Upload failed: %s (%d/%d)", + err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error", + err, rc); + break; + } + + /* If we have a restart point then we need to seek to the correct + position. */ + if(data->state.resume_from > 0) { + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + Curl_set_in_callback(data, true); + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + Curl_set_in_callback(data, false); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed = 0; + + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + do { + size_t readthisamountnow = + (data->state.resume_from - passed > data->set.buffer_size) ? + (size_t)data->set.buffer_size : + curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread; + Curl_set_in_callback(data, true); + actuallyread = data->state.fread_func(data->state.buffer, 1, + readthisamountnow, + data->state.in); + Curl_set_in_callback(data, false); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); + } + + /* now, decrease the size of the read */ + if(data->state.infilesize > 0) { + data->state.infilesize -= data->state.resume_from; + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + + SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); + } + if(data->state.infilesize > 0) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + /* upload data */ + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + if(result) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh2 sftp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + /* since we don't really wait for anything at this point, we want the + state machine to move on as soon as possible so we set a very short + timeout here */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + + state(conn, SSH_STOP); + } + break; + } + + case SSH_SFTP_CREATE_DIRS_INIT: + if(strlen(sftp_scp->path) > 1) { + sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */ + state(conn, SSH_SFTP_CREATE_DIRS); + } + else { + state(conn, SSH_SFTP_UPLOAD_INIT); + } + break; + + case SSH_SFTP_CREATE_DIRS: + sshc->slash_pos = strchr(sshc->slash_pos, '/'); + if(sshc->slash_pos) { + *sshc->slash_pos = 0; + + infof(data, "Creating directory '%s'\n", sftp_scp->path); + state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); + break; + } + state(conn, SSH_SFTP_UPLOAD_INIT); + break; + + case SSH_SFTP_CREATE_DIRS_MKDIR: + /* 'mode' - parameter is preliminary - default to 0644 */ + rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + data->set.new_directory_perms); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + *sshc->slash_pos = '/'; + ++sshc->slash_pos; + if(rc < 0) { + /* + * Abort if failure wasn't that the dir already exists or the + * permission was denied (creation might succeed further down the + * path) - retry on unspecific FAILURE also + */ + err = sftp_libssh2_last_error(sshc->sftp_session); + if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) && + (err != LIBSSH2_FX_FAILURE) && + (err != LIBSSH2_FX_PERMISSION_DENIED)) { + result = sftp_libssh2_error_to_CURLE(err); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + rc = 0; /* clear rc and continue */ + } + state(conn, SSH_SFTP_CREATE_DIRS); + break; + + case SSH_SFTP_READDIR_INIT: + Curl_pgrsSetDownloadSize(data, -1); + if(data->set.opt_no_body) { + state(conn, SSH_STOP); + break; + } + + /* + * This is a directory that we are trying to get, so produce a directory + * listing + */ + sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session, + sftp_scp->path, + curlx_uztoui( + strlen(sftp_scp->path)), + 0, 0, LIBSSH2_SFTP_OPENDIR); + if(!sshc->sftp_handle) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + err = sftp_libssh2_last_error(sshc->sftp_session); + failf(data, "Could not open directory for reading: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + sshc->readdir_filename = malloc(PATH_MAX + 1); + if(!sshc->readdir_filename) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + sshc->readdir_longentry = malloc(PATH_MAX + 1); + if(!sshc->readdir_longentry) { + Curl_safefree(sshc->readdir_filename); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR: + rc = libssh2_sftp_readdir_ex(sshc->sftp_handle, + sshc->readdir_filename, + PATH_MAX, + sshc->readdir_longentry, + PATH_MAX, + &sshc->readdir_attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc > 0) { + sshc->readdir_len = (size_t) rc; + sshc->readdir_filename[sshc->readdir_len] = '\0'; + + if(data->set.ftp_list_only) { + char *tmpLine; + + tmpLine = aprintf("%s\n", sshc->readdir_filename); + if(tmpLine == NULL) { + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + result = Curl_client_write(conn, CLIENTWRITE_BODY, + tmpLine, sshc->readdir_len + 1); + free(tmpLine); + + if(result) { + state(conn, SSH_STOP); + break; + } + /* since this counts what we send to the client, we include the + newline in this counter */ + data->req.bytecount += sshc->readdir_len + 1; + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename, + sshc->readdir_len); + } + } + else { + sshc->readdir_currLen = strlen(sshc->readdir_longentry); + sshc->readdir_totalLen = 80 + sshc->readdir_currLen; + sshc->readdir_line = calloc(sshc->readdir_totalLen, 1); + if(!sshc->readdir_line) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + memcpy(sshc->readdir_line, sshc->readdir_longentry, + sshc->readdir_currLen); + if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && + ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == + LIBSSH2_SFTP_S_IFLNK)) { + sshc->readdir_linkPath = malloc(PATH_MAX + 1); + if(sshc->readdir_linkPath == NULL) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + + msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path, + sshc->readdir_filename); + state(conn, SSH_SFTP_READDIR_LINK); + break; + } + state(conn, SSH_SFTP_READDIR_BOTTOM); + break; + } + } + else if(rc == 0) { + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_READDIR_DONE); + break; + } + else if(rc < 0) { + err = sftp_libssh2_last_error(sshc->sftp_session); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + failf(data, "Could not open remote file for reading: %s :: %d", + sftp_libssh2_strerror(err), + libssh2_session_last_errno(sshc->ssh_session)); + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + break; + } + break; + + case SSH_SFTP_READDIR_LINK: + rc = + libssh2_sftp_symlink_ex(sshc->sftp_session, + sshc->readdir_linkPath, + curlx_uztoui(strlen(sshc->readdir_linkPath)), + sshc->readdir_filename, + PATH_MAX, LIBSSH2_SFTP_READLINK); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + sshc->readdir_len = (size_t) rc; + Curl_safefree(sshc->readdir_linkPath); + + /* get room for the filename and extra output */ + sshc->readdir_totalLen += 4 + sshc->readdir_len; + new_readdir_line = Curl_saferealloc(sshc->readdir_line, + sshc->readdir_totalLen); + if(!new_readdir_line) { + sshc->readdir_line = NULL; + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; + break; + } + sshc->readdir_line = new_readdir_line; + + sshc->readdir_currLen += msnprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, + " -> %s", + sshc->readdir_filename); + + state(conn, SSH_SFTP_READDIR_BOTTOM); + break; + + case SSH_SFTP_READDIR_BOTTOM: + sshc->readdir_currLen += msnprintf(sshc->readdir_line + + sshc->readdir_currLen, + sshc->readdir_totalLen - + sshc->readdir_currLen, "\n"); + result = Curl_client_write(conn, CLIENTWRITE_BODY, + sshc->readdir_line, + sshc->readdir_currLen); + + if(!result) { + + /* output debug output if that is requested */ + if(data->set.verbose) { + Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line, + sshc->readdir_currLen); + } + data->req.bytecount += sshc->readdir_currLen; + } + Curl_safefree(sshc->readdir_line); + if(result) { + state(conn, SSH_STOP); + } + else + state(conn, SSH_SFTP_READDIR); + break; + + case SSH_SFTP_READDIR_DONE: + if(libssh2_sftp_closedir(sshc->sftp_handle) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + sshc->sftp_handle = NULL; + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + state(conn, SSH_STOP); + break; + + case SSH_SFTP_DOWNLOAD_INIT: + /* + * Work on getting the specified file + */ + sshc->sftp_handle = + libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_FXF_READ, data->set.new_file_perms, + LIBSSH2_SFTP_OPENFILE); + if(!sshc->sftp_handle) { + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + err = sftp_libssh2_last_error(sshc->sftp_session); + failf(data, "Could not open remote file for reading: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + break; + } + state(conn, SSH_SFTP_DOWNLOAD_STAT); + break; + + case SSH_SFTP_DOWNLOAD_STAT: + { + LIBSSH2_SFTP_ATTRIBUTES attrs; + + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, + curlx_uztoui(strlen(sftp_scp->path)), + LIBSSH2_SFTP_STAT, &attrs); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc || + !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) || + (attrs.filesize == 0)) { + /* + * libssh2_sftp_open() didn't return an error, so maybe the server + * just doesn't support stat() + * OR the server doesn't return a file size with a stat() + * OR file size is 0 + */ + data->req.size = -1; + data->req.maxdownload = -1; + Curl_pgrsSetDownloadSize(data, -1); + } + else { + curl_off_t size = attrs.filesize; + + if(size < 0) { + failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(conn->data->state.use_range) { + curl_off_t from, to; + char *ptr; + char *ptr2; + CURLofft to_t; + CURLofft from_t; + + from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from); + if(from_t == CURL_OFFT_FLOW) + return CURLE_RANGE_ERROR; + while(*ptr && (ISSPACE(*ptr) || (*ptr == '-'))) + ptr++; + to_t = curlx_strtoofft(ptr, &ptr2, 0, &to); + if(to_t == CURL_OFFT_FLOW) + return CURLE_RANGE_ERROR; + if((to_t == CURL_OFFT_INVAL) /* no "to" value given */ + || (to >= size)) { + to = size - 1; + } + if(from_t) { + /* from is relative to end of file */ + from = size - to; + to = size - 1; + } + if(from > size) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + if(from > to) { + from = to; + size = 0; + } + else { + size = to - from + 1; + } + + SFTP_SEEK(conn->proto.sshc.sftp_handle, from); + } + data->req.size = size; + data->req.maxdownload = size; + Curl_pgrsSetDownloadSize(data, size); + } + + /* We can resume if we can seek to the resume position */ + if(data->state.resume_from) { + if(data->state.resume_from < 0) { + /* We're supposed to download the last abs(from) bytes */ + if((curl_off_t)attrs.filesize < -data->state.resume_from) { + failf(data, "Offset (%" + CURL_FORMAT_CURL_OFF_T ") was beyond file size (%" + CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* download from where? */ + data->state.resume_from += attrs.filesize; + } + else { + if((curl_off_t)attrs.filesize < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, attrs.filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + } + /* Does a completed file need to be seeked and started or closed ? */ + /* Now store the number of bytes we are expected to download */ + data->req.size = attrs.filesize - data->state.resume_from; + data->req.maxdownload = attrs.filesize - data->state.resume_from; + Curl_pgrsSetDownloadSize(data, + attrs.filesize - data->state.resume_from); + SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); + } + } + + /* Setup the actual download */ + if(data->req.size == 0) { + /* no data to transfer */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + infof(data, "File already completely downloaded\n"); + state(conn, SSH_STOP); + break; + } + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh2 recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + if(result) { + /* this should never occur; the close state should be entered + at the time the error occurs */ + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = result; + } + else { + state(conn, SSH_STOP); + } + break; + + case SSH_SFTP_CLOSE: + if(sshc->sftp_handle) { + rc = libssh2_sftp_close(sshc->sftp_handle); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg); + } + sshc->sftp_handle = NULL; + } + + Curl_safefree(sftp_scp->path); + + DEBUGF(infof(data, "SFTP DONE done\n")); + + /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT + After nextstate is executed, the control should come back to + SSH_SFTP_CLOSE to pass the correct result back */ + if(sshc->nextstate != SSH_NO_STATE && + sshc->nextstate != SSH_SFTP_CLOSE) { + state(conn, sshc->nextstate); + sshc->nextstate = SSH_SFTP_CLOSE; + } + else { + state(conn, SSH_STOP); + result = sshc->actualcode; + } + break; + + case SSH_SFTP_SHUTDOWN: + /* during times we get here due to a broken transfer and then the + sftp_handle might not have been taken down so make sure that is done + before we proceed */ + + if(sshc->sftp_handle) { + rc = libssh2_sftp_close(sshc->sftp_handle); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, + NULL, 0); + infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg); + } + sshc->sftp_handle = NULL; + } + if(sshc->sftp_session) { + rc = libssh2_sftp_shutdown(sshc->sftp_session); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + infof(data, "Failed to stop libssh2 sftp subsystem\n"); + } + sshc->sftp_session = NULL; + } + + Curl_safefree(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_DISCONNECT); + break; + + case SSH_SCP_TRANS_INIT: + result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path); + if(result) { + sshc->actualcode = result; + state(conn, SSH_STOP); + break; + } + + if(data->set.upload) { + if(data->state.infilesize < 0) { + failf(data, "SCP requires a known file size for upload"); + sshc->actualcode = CURLE_UPLOAD_FAILED; + state(conn, SSH_SCP_CHANNEL_FREE); + break; + } + state(conn, SSH_SCP_UPLOAD_INIT); + } + else { + state(conn, SSH_SCP_DOWNLOAD_INIT); + } + break; + + case SSH_SCP_UPLOAD_INIT: + /* + * libssh2 requires that the destination path is a full path that + * includes the destination file and name OR ends in a "/" . If this is + * not done the destination file will be named the same name as the last + * directory in the path. + */ + sshc->ssh_channel = + SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, + data->state.infilesize); + if(!sshc->ssh_channel) { + int ssh_err; + char *err_msg = NULL; + + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + + ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0)); + failf(conn->data, "%s", err_msg); + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + /* Map generic errors to upload failed */ + if(sshc->actualcode == CURLE_SSH || + sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND) + sshc->actualcode = CURLE_UPLOAD_FAILED; + break; + } + + /* upload data */ + Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->sockfd = conn->writesockfd; + + if(result) { + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = result; + } + else { + /* store this original bitmask setup to use later on if we can't + figure out a "real" bitmask */ + sshc->orig_waitfor = data->req.keepon; + + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh2 scp send function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_OUT; + + state(conn, SSH_STOP); + } + break; + + case SSH_SCP_DOWNLOAD_INIT: + { + curl_off_t bytecount; + + /* + * We must check the remote file; if it is a directory no values will + * be set in sb + */ + + /* + * If support for >2GB files exists, use it. + */ + + /* get a fresh new channel from the ssh layer */ +#if LIBSSH2_VERSION_NUM < 0x010700 + struct stat sb; + memset(&sb, 0, sizeof(struct stat)); + sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session, + sftp_scp->path, &sb); +#else + libssh2_struct_stat sb; + memset(&sb, 0, sizeof(libssh2_struct_stat)); + sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session, + sftp_scp->path, &sb); +#endif + + if(!sshc->ssh_channel) { + int ssh_err; + char *err_msg = NULL; + + if(libssh2_session_last_errno(sshc->ssh_session) == + LIBSSH2_ERROR_EAGAIN) { + rc = LIBSSH2_ERROR_EAGAIN; + break; + } + + + ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0)); + failf(conn->data, "%s", err_msg); + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + break; + } + + /* download data */ + bytecount = (curl_off_t)sb.st_size; + data->req.maxdownload = (curl_off_t)sb.st_size; + Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); + + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh2 recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; + + if(result) { + state(conn, SSH_SCP_CHANNEL_FREE); + sshc->actualcode = result; + } + else + state(conn, SSH_STOP); + } + break; + + case SSH_SCP_DONE: + if(data->set.upload) + state(conn, SSH_SCP_SEND_EOF); + else + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_SEND_EOF: + if(sshc->ssh_channel) { + rc = libssh2_channel_send_eof(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to send libssh2 channel EOF: %d %s\n", + rc, err_msg); + } + } + state(conn, SSH_SCP_WAIT_EOF); + break; + + case SSH_SCP_WAIT_EOF: + if(sshc->ssh_channel) { + rc = libssh2_channel_wait_eof(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg); + } + } + state(conn, SSH_SCP_WAIT_CLOSE); + break; + + case SSH_SCP_WAIT_CLOSE: + if(sshc->ssh_channel) { + rc = libssh2_channel_wait_closed(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Channel failed to close: %d %s\n", rc, err_msg); + } + } + state(conn, SSH_SCP_CHANNEL_FREE); + break; + + case SSH_SCP_CHANNEL_FREE: + if(sshc->ssh_channel) { + rc = libssh2_channel_free(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to free libssh2 scp subsystem: %d %s\n", + rc, err_msg); + } + sshc->ssh_channel = NULL; + } + DEBUGF(infof(data, "SCP DONE phase complete\n")); +#if 0 /* PREV */ + state(conn, SSH_SESSION_DISCONNECT); +#endif + state(conn, SSH_STOP); + result = sshc->actualcode; + break; + + case SSH_SESSION_DISCONNECT: + /* during weird times when we've been prematurely aborted, the channel + is still alive when we reach this state and we MUST kill the channel + properly first */ + if(sshc->ssh_channel) { + rc = libssh2_channel_free(sshc->ssh_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to free libssh2 scp subsystem: %d %s\n", + rc, err_msg); + } + sshc->ssh_channel = NULL; + } + + if(sshc->ssh_session) { + rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown"); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to disconnect libssh2 session: %d %s\n", + rc, err_msg); + } + } + + Curl_safefree(sshc->homedir); + conn->data->state.most_recent_ftp_entrypath = NULL; + + state(conn, SSH_SESSION_FREE); + break; + + case SSH_SESSION_FREE: +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + if(sshc->kh) { + libssh2_knownhost_free(sshc->kh); + sshc->kh = NULL; + } +#endif + +#ifdef HAVE_LIBSSH2_AGENT_API + if(sshc->ssh_agent) { + rc = libssh2_agent_disconnect(sshc->ssh_agent); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to disconnect from libssh2 agent: %d %s\n", + rc, err_msg); + } + libssh2_agent_free(sshc->ssh_agent); + sshc->ssh_agent = NULL; + + /* NB: there is no need to free identities, they are part of internal + agent stuff */ + sshc->sshagent_identity = NULL; + sshc->sshagent_prev_identity = NULL; + } +#endif + + if(sshc->ssh_session) { + rc = libssh2_session_free(sshc->ssh_session); + if(rc == LIBSSH2_ERROR_EAGAIN) { + break; + } + if(rc < 0) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, + &err_msg, NULL, 0); + infof(data, "Failed to free libssh2 session: %d %s\n", rc, err_msg); + } + sshc->ssh_session = NULL; + } + + /* worst-case scenario cleanup */ + + DEBUGASSERT(sshc->ssh_session == NULL); + DEBUGASSERT(sshc->ssh_channel == NULL); + DEBUGASSERT(sshc->sftp_session == NULL); + DEBUGASSERT(sshc->sftp_handle == NULL); +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + DEBUGASSERT(sshc->kh == NULL); +#endif +#ifdef HAVE_LIBSSH2_AGENT_API + DEBUGASSERT(sshc->ssh_agent == NULL); +#endif + + Curl_safefree(sshc->rsa_pub); + Curl_safefree(sshc->rsa); + + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); + + Curl_safefree(sshc->homedir); + + Curl_safefree(sshc->readdir_filename); + Curl_safefree(sshc->readdir_longentry); + Curl_safefree(sshc->readdir_line); + Curl_safefree(sshc->readdir_linkPath); + + /* the code we are about to return */ + result = sshc->actualcode; + + memset(sshc, 0, sizeof(struct ssh_conn)); + + connclose(conn, "SSH session free"); + sshc->state = SSH_SESSION_FREE; /* current */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + + case SSH_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + sshc->nextstate = SSH_NO_STATE; + state(conn, SSH_STOP); + break; + } + + } while(!rc && (sshc->state != SSH_STOP)); + + if(rc == LIBSSH2_ERROR_EAGAIN) { + /* we would block, we need to wait for the socket to be ready (in the + right direction too)! */ + *block = TRUE; + } + + return result; +} + +/* called by the multi interface to figure out what socket(s) to wait for and + for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ +static int ssh_perform_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks + number of sockets */ + int numsocks) +{ +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + int bitmap = GETSOCK_BLANK; + (void)numsocks; + + sock[0] = conn->sock[FIRSTSOCKET]; + + if(conn->waitfor & KEEP_RECV) + bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); + + if(conn->waitfor & KEEP_SEND) + bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); + + return bitmap; +#else + /* if we don't know the direction we can use the generic *_getsock() + function even for the protocol_connect and doing states */ + return Curl_single_getsock(conn, sock, numsocks); +#endif +} + +/* Generic function called by the multi interface to figure out what socket(s) + to wait for and for what actions during the DOING and PROTOCONNECT states*/ +static int ssh_getsock(struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks) +{ +#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + (void)conn; + (void)sock; + (void)numsocks; + /* if we don't know any direction we can just play along as we used to and + not provide any sensible info */ + return GETSOCK_BLANK; +#else + /* if we know the direction we can use the generic *_getsock() function even + for the protocol_connect and doing states */ + return ssh_perform_getsock(conn, sock, numsocks); +#endif +} + +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION +/* + * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this + * function is used to figure out in what direction and stores this info so + * that the multi interface can take advantage of it. Make sure to call this + * function in all cases so that when it _doesn't_ return EAGAIN we can + * restore the default wait bits. + */ +static void ssh_block2waitfor(struct connectdata *conn, bool block) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + int dir = 0; + if(block) { + dir = libssh2_session_block_directions(sshc->ssh_session); + if(dir) { + /* translate the libssh2 define bits into our own bit defines */ + conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | + ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); + } + } + if(!dir) + /* It didn't block or libssh2 didn't reveal in which direction, put back + the original set */ + conn->waitfor = sshc->orig_waitfor; +} +#else + /* no libssh2 directional support so we simply don't know */ +#define ssh_block2waitfor(x,y) Curl_nop_stmt +#endif + +/* called repeatedly until done from multi.c */ +static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + bool block; /* we store the status and use that to provide a ssh_getsock() + implementation */ + do { + result = ssh_statemach_act(conn, &block); + *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then + try again */ + } while(!result && !*done && !block); + ssh_block2waitfor(conn, block); + + return result; +} + +static CURLcode ssh_block_statemach(struct connectdata *conn, + bool disconnect) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + while((sshc->state != SSH_STOP) && !result) { + bool block; + timediff_t left = 1000; + struct curltime now = Curl_now(); + + result = ssh_statemach_act(conn, &block); + if(result) + break; + + if(!disconnect) { + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + result = Curl_speedcheck(data, now); + if(result) + break; + + left = Curl_timeleft(data, NULL, FALSE); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } + } + +#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION + if(!result && block) { + int dir = libssh2_session_block_directions(sshc->ssh_session); + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + curl_socket_t fd_read = CURL_SOCKET_BAD; + curl_socket_t fd_write = CURL_SOCKET_BAD; + if(LIBSSH2_SESSION_BLOCK_INBOUND & dir) + fd_read = sock; + if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) + fd_write = sock; + /* wait for the socket to become ready */ + (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, + left>1000?1000:left); /* ignore result */ + } +#endif + + } + + return result; +} + +/* + * SSH setup and connection + */ +static CURLcode ssh_setup_connection(struct connectdata *conn) +{ + struct SSHPROTO *ssh; + + conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO)); + if(!ssh) + return CURLE_OUT_OF_MEMORY; + + return CURLE_OK; +} + +static Curl_recv scp_recv, sftp_recv; +static Curl_send scp_send, sftp_send; + +/* + * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to + * do protocol-specific actions at connect-time. + */ +static CURLcode ssh_connect(struct connectdata *conn, bool *done) +{ +#ifdef CURL_LIBSSH2_DEBUG + curl_socket_t sock; +#endif + struct ssh_conn *ssh; + CURLcode result; + struct Curl_easy *data = conn->data; + + /* initialize per-handle data if not already */ + if(!data->req.protop) + ssh_setup_connection(conn); + + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + connkeep(conn, "SSH default"); + + if(conn->handler->protocol & CURLPROTO_SCP) { + conn->recv[FIRSTSOCKET] = scp_recv; + conn->send[FIRSTSOCKET] = scp_send; + } + else { + conn->recv[FIRSTSOCKET] = sftp_recv; + conn->send[FIRSTSOCKET] = sftp_send; + } + ssh = &conn->proto.sshc; + +#ifdef CURL_LIBSSH2_DEBUG + if(conn->user) { + infof(data, "User: %s\n", conn->user); + } + if(conn->passwd) { + infof(data, "Password: %s\n", conn->passwd); + } + sock = conn->sock[FIRSTSOCKET]; +#endif /* CURL_LIBSSH2_DEBUG */ + + ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, + my_libssh2_free, + my_libssh2_realloc, conn); + if(ssh->ssh_session == NULL) { + failf(data, "Failure initialising ssh session"); + return CURLE_FAILED_INIT; + } + + if(data->set.ssh_compression) { +#if LIBSSH2_VERSION_NUM >= 0x010208 + if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) +#endif + infof(data, "Failed to enable compression for ssh session\n"); + } + +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + if(data->set.str[STRING_SSH_KNOWNHOSTS]) { + int rc; + ssh->kh = libssh2_knownhost_init(ssh->ssh_session); + if(!ssh->kh) { + libssh2_session_free(ssh->ssh_session); + return CURLE_FAILED_INIT; + } + + /* read all known hosts from there */ + rc = libssh2_knownhost_readfile(ssh->kh, + data->set.str[STRING_SSH_KNOWNHOSTS], + LIBSSH2_KNOWNHOST_FILE_OPENSSH); + if(rc < 0) + infof(data, "Failed to read known hosts from %s\n", + data->set.str[STRING_SSH_KNOWNHOSTS]); + } +#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ + +#ifdef CURL_LIBSSH2_DEBUG + libssh2_trace(ssh->ssh_session, ~0); + infof(data, "SSH socket: %d\n", (int)sock); +#endif /* CURL_LIBSSH2_DEBUG */ + + state(conn, SSH_INIT); + + result = ssh_multi_statemach(conn, done); + + return result; +} + +/* + *********************************************************************** + * + * scp_perform() + * + * This is the actual DO function for SCP. Get a file according to + * the options previously setup. + */ + +static +CURLcode scp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SCP_TRANS_INIT); + + /* run the state-machine */ + result = ssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode scp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result; + result = ssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* + * The DO function is generic for both protocols. There was previously two + * separate ones but this way means less duplicated code. + */ + +static CURLcode ssh_do(struct connectdata *conn, bool *done) +{ + CURLcode result; + bool connected = 0; + struct Curl_easy *data = conn->data; + struct ssh_conn *sshc = &conn->proto.sshc; + + *done = FALSE; /* default to false */ + + data->req.size = -1; /* make sure this is unknown at this point */ + + sshc->actualcode = CURLE_OK; /* reset error code */ + sshc->secondCreateDirs = 0; /* reset the create dir attempt state + variable */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + if(conn->handler->protocol & CURLPROTO_SCP) + result = scp_perform(conn, &connected, done); + else + result = sftp_perform(conn, &connected, done); + + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + struct ssh_conn *ssh = &conn->proto.sshc; + (void) dead_connection; + + if(ssh->ssh_session) { + /* only if there's a session still around to use! */ + + state(conn, SSH_SESSION_DISCONNECT); + + result = ssh_block_statemach(conn, TRUE); + } + + return result; +} + +/* generic done function for both SCP and SFTP called from their specific + done functions */ +static CURLcode ssh_done(struct connectdata *conn, CURLcode status) +{ + CURLcode result = CURLE_OK; + struct SSHPROTO *sftp_scp = conn->data->req.protop; + + if(!status) { + /* run the state-machine */ + result = ssh_block_statemach(conn, FALSE); + } + else + result = status; + + if(sftp_scp) + Curl_safefree(sftp_scp->path); + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + conn->data->req.keepon = 0; /* clear all bits */ + return result; +} + + +static CURLcode scp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + (void)premature; /* not used */ + + if(!status) + state(conn, SSH_SCP_DONE); + + return ssh_done(conn, status); + +} + +static ssize_t scp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite; + (void)sockindex; /* we only support SCP on the fixed known primary socket */ + + /* libssh2_channel_write() returns int! */ + nwrite = (ssize_t) + libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len); + + ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nwrite == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nwrite = 0; + } + else if(nwrite < LIBSSH2_ERROR_NONE) { + *err = libssh2_session_error_to_CURLE((int)nwrite); + nwrite = -1; + } + + return nwrite; +} + +static ssize_t scp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void)sockindex; /* we only support SCP on the fixed known primary socket */ + + /* libssh2_channel_read() returns int */ + nread = (ssize_t) + libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len); + + ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + if(nread == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nread = -1; + } + + return nread; +} + +/* + * =============== SFTP =============== + */ + +/* + *********************************************************************** + * + * sftp_perform() + * + * This is the actual DO function for SFTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode sftp_perform(struct connectdata *conn, + bool *connected, + bool *dophase_done) +{ + CURLcode result = CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + state(conn, SSH_SFTP_QUOTE_INIT); + + /* run the state-machine */ + result = ssh_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + + return result; +} + +/* called from multi.c while DOing */ +static CURLcode sftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = ssh_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + return result; +} + +/* BLOCKING, but the function is using the state machine so the only reason + this is still blocking is that the multi interface code has no support for + disconnecting operations that takes a while */ +static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + CURLcode result = CURLE_OK; + (void) dead_connection; + + DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); + + if(conn->proto.sshc.ssh_session) { + /* only if there's a session still around to use! */ + state(conn, SSH_SFTP_SHUTDOWN); + result = ssh_block_statemach(conn, TRUE); + } + + DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); + + return result; + +} + +static CURLcode sftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct ssh_conn *sshc = &conn->proto.sshc; + + if(!status) { + /* Post quote commands are executed after the SFTP_CLOSE state to avoid + errors that could happen due to open file handles during POSTQUOTE + operation */ + if(!premature && conn->data->set.postquote && !conn->bits.retry) + sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; + state(conn, SSH_SFTP_CLOSE); + } + return ssh_done(conn, status); +} + +/* return number of sent bytes */ +static ssize_t sftp_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *err) +{ + ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 + but is changed to ssize_t in 0.15. These days we don't + support libssh2 0.15*/ + (void)sockindex; + + nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len); + + ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nwrite == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nwrite = 0; + } + else if(nwrite < LIBSSH2_ERROR_NONE) { + *err = libssh2_session_error_to_CURLE((int)nwrite); + nwrite = -1; + } + + return nwrite; +} + +/* + * Return number of received (decrypted) bytes + * or <0 on error + */ +static ssize_t sftp_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) +{ + ssize_t nread; + (void)sockindex; + + nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len); + + ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); + + if(nread == LIBSSH2_ERROR_EAGAIN) { + *err = CURLE_AGAIN; + nread = -1; + + } + else if(nread < 0) { + *err = libssh2_session_error_to_CURLE((int)nread); + } + return nread; +} + +static const char *sftp_libssh2_strerror(int err) +{ + switch(err) { + case LIBSSH2_FX_NO_SUCH_FILE: + return "No such file or directory"; + + case LIBSSH2_FX_PERMISSION_DENIED: + return "Permission denied"; + + case LIBSSH2_FX_FAILURE: + return "Operation failed"; + + case LIBSSH2_FX_BAD_MESSAGE: + return "Bad message from SFTP server"; + + case LIBSSH2_FX_NO_CONNECTION: + return "Not connected to SFTP server"; + + case LIBSSH2_FX_CONNECTION_LOST: + return "Connection to SFTP server lost"; + + case LIBSSH2_FX_OP_UNSUPPORTED: + return "Operation not supported by SFTP server"; + + case LIBSSH2_FX_INVALID_HANDLE: + return "Invalid handle"; + + case LIBSSH2_FX_NO_SUCH_PATH: + return "No such file or directory"; + + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + return "File already exists"; + + case LIBSSH2_FX_WRITE_PROTECT: + return "File is write protected"; + + case LIBSSH2_FX_NO_MEDIA: + return "No media"; + + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + return "Disk full"; + + case LIBSSH2_FX_QUOTA_EXCEEDED: + return "User quota exceeded"; + + case LIBSSH2_FX_UNKNOWN_PRINCIPLE: + return "Unknown principle"; + + case LIBSSH2_FX_LOCK_CONFlICT: + return "File lock conflict"; + + case LIBSSH2_FX_DIR_NOT_EMPTY: + return "Directory not empty"; + + case LIBSSH2_FX_NOT_A_DIRECTORY: + return "Not a directory"; + + case LIBSSH2_FX_INVALID_FILENAME: + return "Invalid filename"; + + case LIBSSH2_FX_LINK_LOOP: + return "Link points to itself"; + } + return "Unknown error in libssh2"; +} + +#endif /* USE_LIBSSH2 */ diff --git a/libcurl/lib/ssh.h b/libcurl/lib/ssh.h new file mode 100644 index 0000000..0620aac --- /dev/null +++ b/libcurl/lib/ssh.h @@ -0,0 +1,245 @@ +#ifndef HEADER_CURL_SSH_H +#define HEADER_CURL_SSH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_LIBSSH2_H) +#include +#include +#elif defined(HAVE_LIBSSH_LIBSSH_H) +#include +#include +#endif /* HAVE_LIBSSH2_H */ + +/**************************************************************************** + * SSH unique setup + ***************************************************************************/ +typedef enum { + SSH_NO_STATE = -1, /* Used for "nextState" so say there is none */ + SSH_STOP = 0, /* do nothing state, stops the state machine */ + + SSH_INIT, /* First state in SSH-CONNECT */ + SSH_S_STARTUP, /* Session startup */ + SSH_HOSTKEY, /* verify hostkey */ + SSH_AUTHLIST, + SSH_AUTH_PKEY_INIT, + SSH_AUTH_PKEY, + SSH_AUTH_PASS_INIT, + SSH_AUTH_PASS, + SSH_AUTH_AGENT_INIT, /* initialize then wait for connection to agent */ + SSH_AUTH_AGENT_LIST, /* ask for list then wait for entire list to come */ + SSH_AUTH_AGENT, /* attempt one key at a time */ + SSH_AUTH_HOST_INIT, + SSH_AUTH_HOST, + SSH_AUTH_KEY_INIT, + SSH_AUTH_KEY, + SSH_AUTH_GSSAPI, + SSH_AUTH_DONE, + SSH_SFTP_INIT, + SSH_SFTP_REALPATH, /* Last state in SSH-CONNECT */ + + SSH_SFTP_QUOTE_INIT, /* First state in SFTP-DO */ + SSH_SFTP_POSTQUOTE_INIT, /* (Possibly) First state in SFTP-DONE */ + SSH_SFTP_QUOTE, + SSH_SFTP_NEXT_QUOTE, + SSH_SFTP_QUOTE_STAT, + SSH_SFTP_QUOTE_SETSTAT, + SSH_SFTP_QUOTE_SYMLINK, + SSH_SFTP_QUOTE_MKDIR, + SSH_SFTP_QUOTE_RENAME, + SSH_SFTP_QUOTE_RMDIR, + SSH_SFTP_QUOTE_UNLINK, + SSH_SFTP_QUOTE_STATVFS, + SSH_SFTP_GETINFO, + SSH_SFTP_FILETIME, + SSH_SFTP_TRANS_INIT, + SSH_SFTP_UPLOAD_INIT, + SSH_SFTP_CREATE_DIRS_INIT, + SSH_SFTP_CREATE_DIRS, + SSH_SFTP_CREATE_DIRS_MKDIR, + SSH_SFTP_READDIR_INIT, + SSH_SFTP_READDIR, + SSH_SFTP_READDIR_LINK, + SSH_SFTP_READDIR_BOTTOM, + SSH_SFTP_READDIR_DONE, + SSH_SFTP_DOWNLOAD_INIT, + SSH_SFTP_DOWNLOAD_STAT, /* Last state in SFTP-DO */ + SSH_SFTP_CLOSE, /* Last state in SFTP-DONE */ + SSH_SFTP_SHUTDOWN, /* First state in SFTP-DISCONNECT */ + SSH_SCP_TRANS_INIT, /* First state in SCP-DO */ + SSH_SCP_UPLOAD_INIT, + SSH_SCP_DOWNLOAD_INIT, + SSH_SCP_DOWNLOAD, + SSH_SCP_DONE, + SSH_SCP_SEND_EOF, + SSH_SCP_WAIT_EOF, + SSH_SCP_WAIT_CLOSE, + SSH_SCP_CHANNEL_FREE, /* Last state in SCP-DONE */ + SSH_SESSION_DISCONNECT, /* First state in SCP-DISCONNECT */ + SSH_SESSION_FREE, /* Last state in SCP/SFTP-DISCONNECT */ + SSH_QUIT, + SSH_LAST /* never used */ +} sshstate; + +/* this struct is used in the HandleData struct which is part of the + Curl_easy, which means this is used on a per-easy handle basis. + Everything that is strictly related to a connection is banned from this + struct. */ +struct SSHPROTO { + char *path; /* the path we operate on */ +}; + +/* ssh_conn is used for struct connection-oriented data in the connectdata + struct */ +struct ssh_conn { + const char *authlist; /* List of auth. methods, managed by libssh2 */ + + /* common */ + const char *passphrase; /* pass-phrase to use */ + char *rsa_pub; /* path name */ + char *rsa; /* path name */ + bool authed; /* the connection has been authenticated fine */ + sshstate state; /* always use ssh.c:state() to change state! */ + sshstate nextstate; /* the state to goto after stopping */ + CURLcode actualcode; /* the actual error code */ + struct curl_slist *quote_item; /* for the quote option */ + char *quote_path1; /* two generic pointers for the QUOTE stuff */ + char *quote_path2; + + bool acceptfail; /* used by the SFTP_QUOTE (continue if + quote command fails) */ + char *homedir; /* when doing SFTP we figure out home dir in the + connect phase */ + size_t readdir_len, readdir_totalLen, readdir_currLen; + char *readdir_line; + char *readdir_linkPath; + /* end of READDIR stuff */ + + int secondCreateDirs; /* counter use by the code to see if the + second attempt has been made to change + to/create a directory */ + char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ + + int orig_waitfor; /* default READ/WRITE bits wait for */ + +#if defined(USE_LIBSSH) +/* our variables */ + unsigned kbd_state; /* 0 or 1 */ + ssh_key privkey; + ssh_key pubkey; + int auth_methods; + ssh_session ssh_session; + ssh_scp scp_session; + sftp_session sftp_session; + sftp_file sftp_file; + sftp_dir sftp_dir; + + unsigned sftp_recv_state; /* 0 or 1 */ + int sftp_file_index; /* for async read */ + sftp_attributes readdir_attrs; /* used by the SFTP readdir actions */ + sftp_attributes readdir_link_attrs; /* used by the SFTP readdir actions */ + sftp_attributes quote_attrs; /* used by the SFTP_QUOTE state */ + + const char *readdir_filename; /* points within readdir_attrs */ + const char *readdir_longentry; + char *readdir_tmp; +#elif defined(USE_LIBSSH2) + char *readdir_filename; + char *readdir_longentry; + + LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */ + + /* Here's a set of struct members used by the SFTP_READDIR state */ + LIBSSH2_SFTP_ATTRIBUTES readdir_attrs; + LIBSSH2_SESSION *ssh_session; /* Secure Shell session */ + LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */ + LIBSSH2_SFTP *sftp_session; /* SFTP handle */ + LIBSSH2_SFTP_HANDLE *sftp_handle; + +#ifdef HAVE_LIBSSH2_AGENT_API + LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */ + struct libssh2_agent_publickey *sshagent_identity, + *sshagent_prev_identity; +#endif + + /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h + header */ +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + LIBSSH2_KNOWNHOSTS *kh; +#endif +#endif /* USE_LIBSSH */ +}; + +#if defined(USE_LIBSSH) + +#define CURL_LIBSSH_VERSION ssh_version(0) + +extern const struct Curl_handler Curl_handler_scp; +extern const struct Curl_handler Curl_handler_sftp; + +#elif defined(USE_LIBSSH2) + +/* Feature detection based on version numbers to better work with + non-configure platforms */ + +#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000) +# error "SCP/SFTP protocols require libssh2 0.16 or later" +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010000 +#define HAVE_LIBSSH2_SFTP_SEEK64 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010100 +#define HAVE_LIBSSH2_VERSION 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010205 +#define HAVE_LIBSSH2_INIT 1 +#define HAVE_LIBSSH2_EXIT 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010206 +#define HAVE_LIBSSH2_KNOWNHOST_CHECKP 1 +#define HAVE_LIBSSH2_SCP_SEND64 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010208 +#define HAVE_LIBSSH2_SESSION_HANDSHAKE 1 +#endif + +#ifdef HAVE_LIBSSH2_VERSION +/* get it run-time if possible */ +#define CURL_LIBSSH2_VERSION libssh2_version(0) +#else +/* use build-time if run-time not possible */ +#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION +#endif + +extern const struct Curl_handler Curl_handler_scp; +extern const struct Curl_handler Curl_handler_sftp; + +#endif /* USE_LIBSSH2 */ + +#endif /* HEADER_CURL_SSH_H */ diff --git a/libcurl/lib/strcase.c b/libcurl/lib/strcase.c new file mode 100644 index 0000000..24bcca9 --- /dev/null +++ b/libcurl/lib/strcase.c @@ -0,0 +1,177 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "strcase.h" + +/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because + its behavior is altered by the current locale. */ +char Curl_raw_toupper(char in) +{ +#if !defined(CURL_DOES_CONVERSIONS) + if(in >= 'a' && in <= 'z') + return (char)('A' + in - 'a'); +#else + switch(in) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + case 'g': + return 'G'; + case 'h': + return 'H'; + case 'i': + return 'I'; + case 'j': + return 'J'; + case 'k': + return 'K'; + case 'l': + return 'L'; + case 'm': + return 'M'; + case 'n': + return 'N'; + case 'o': + return 'O'; + case 'p': + return 'P'; + case 'q': + return 'Q'; + case 'r': + return 'R'; + case 's': + return 'S'; + case 't': + return 'T'; + case 'u': + return 'U'; + case 'v': + return 'V'; + case 'w': + return 'W'; + case 'x': + return 'X'; + case 'y': + return 'Y'; + case 'z': + return 'Z'; + } +#endif + + return in; +} + +/* + * Curl_strcasecompare() is for doing "raw" case insensitive strings. This is + * meant to be locale independent and only compare strings we know are safe + * for this. See + * https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for some + * further explanation to why this function is necessary. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + * + * @unittest: 1301 + */ + +int Curl_strcasecompare(const char *first, const char *second) +{ + while(*first && *second) { + if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) + /* get out of the loop as soon as they don't match */ + break; + first++; + second++; + } + /* we do the comparison here (possibly again), just to make sure that if the + loop above is skipped because one of the strings reached zero, we must not + return this as a successful match */ + return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); +} + +int Curl_safe_strcasecompare(const char *first, const char *second) +{ + if(first && second) + /* both pointers point to something then compare them */ + return Curl_strcasecompare(first, second); + + /* if both pointers are NULL then treat them as equal */ + return (NULL == first && NULL == second); +} + +/* + * @unittest: 1301 + */ +int Curl_strncasecompare(const char *first, const char *second, size_t max) +{ + while(*first && *second && max) { + if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) { + break; + } + max--; + first++; + second++; + } + if(0 == max) + return 1; /* they are equal this far */ + + return Curl_raw_toupper(*first) == Curl_raw_toupper(*second); +} + +/* Copy an upper case version of the string from src to dest. The + * strings may overlap. No more than n characters of the string are copied + * (including any NUL) and the destination string will NOT be + * NUL-terminated if that limit is reached. + */ +void Curl_strntoupper(char *dest, const char *src, size_t n) +{ + if(n < 1) + return; + + do { + *dest++ = Curl_raw_toupper(*src); + } while(*src++ && --n); +} + +/* --- public functions --- */ + +int curl_strequal(const char *first, const char *second) +{ + return Curl_strcasecompare(first, second); +} +int curl_strnequal(const char *first, const char *second, size_t max) +{ + return Curl_strncasecompare(first, second, max); +} diff --git a/libcurl/lib/strcase.h b/libcurl/lib/strcase.h new file mode 100644 index 0000000..6fee384 --- /dev/null +++ b/libcurl/lib/strcase.h @@ -0,0 +1,50 @@ +#ifndef HEADER_CURL_STRCASE_H +#define HEADER_CURL_STRCASE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +/* + * Only "raw" case insensitive strings. This is meant to be locale independent + * and only compare strings we know are safe for this. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + */ + +#define strcasecompare(a,b) Curl_strcasecompare(a,b) +#define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c) + +int Curl_strcasecompare(const char *first, const char *second); +int Curl_safe_strcasecompare(const char *first, const char *second); +int Curl_strncasecompare(const char *first, const char *second, size_t max); + +char Curl_raw_toupper(char in); + +/* checkprefix() is a shorter version of the above, used when the first + argument is zero-byte terminated */ +#define checkprefix(a,b) curl_strnequal(a,b,strlen(a)) + +void Curl_strntoupper(char *dest, const char *src, size_t n); + +#endif /* HEADER_CURL_STRCASE_H */ diff --git a/libcurl/lib/strdup.c b/libcurl/lib/strdup.c new file mode 100644 index 0000000..51e7978 --- /dev/null +++ b/libcurl/lib/strdup.c @@ -0,0 +1,100 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "strdup.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" + +#ifndef HAVE_STRDUP +char *curlx_strdup(const char *str) +{ + size_t len; + char *newstr; + + if(!str) + return (char *)NULL; + + len = strlen(str); + + if(len >= ((size_t)-1) / sizeof(char)) + return (char *)NULL; + + newstr = malloc((len + 1)*sizeof(char)); + if(!newstr) + return (char *)NULL; + + memcpy(newstr, str, (len + 1)*sizeof(char)); + + return newstr; + +} +#endif + +/*************************************************************************** + * + * Curl_memdup(source, length) + * + * Copies the 'source' data to a newly allocated buffer (that is + * returned). Copies 'length' bytes. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +void *Curl_memdup(const void *src, size_t length) +{ + void *buffer = malloc(length); + if(!buffer) + return NULL; /* fail */ + + memcpy(buffer, src, length); + + return buffer; +} + +/*************************************************************************** + * + * Curl_saferealloc(ptr, size) + * + * Does a normal realloc(), but will free the data pointer if the realloc + * fails. If 'size' is non-zero, it will free the data and return a failure. + * + * This convenience function is provided and used to help us avoid a common + * mistake pattern when we could pass in a zero, catch the NULL return and end + * up free'ing the memory twice. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +void *Curl_saferealloc(void *ptr, size_t size) +{ + void *datap = realloc(ptr, size); + if(size && !datap) + /* only free 'ptr' if size was non-zero */ + free(ptr); + return datap; +} diff --git a/libcurl/lib/strdup.h b/libcurl/lib/strdup.h new file mode 100644 index 0000000..ae3d5d0 --- /dev/null +++ b/libcurl/lib/strdup.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_STRDUP_H +#define HEADER_CURL_STRDUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef HAVE_STRDUP +extern char *curlx_strdup(const char *str); +#endif +void *Curl_memdup(const void *src, size_t buffer_length); +void *Curl_saferealloc(void *ptr, size_t size); + +#endif /* HEADER_CURL_STRDUP_H */ diff --git a/libcurl/lib/strerror.c b/libcurl/lib/strerror.c new file mode 100644 index 0000000..132f0c7 --- /dev/null +++ b/libcurl/lib/strerror.c @@ -0,0 +1,1103 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2004 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_STRERROR_R +# if (!defined(HAVE_POSIX_STRERROR_R) && \ + !defined(HAVE_GLIBC_STRERROR_R) && \ + !defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)) +# error "strerror_r MUST be either POSIX, glibc or vxworks-style" +# endif +#endif + +#include + +#ifdef USE_LIBIDN2 +#include +#endif + +#ifdef USE_WINDOWS_SSPI +#include "curl_sspi.h" +#endif + +#include "strerror.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if defined(WIN32) || defined(_WIN32_WCE) +#define PRESERVE_WINDOWS_ERROR_CODE +#endif + +const char * +curl_easy_strerror(CURLcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLE_OK: + return "No error"; + + case CURLE_UNSUPPORTED_PROTOCOL: + return "Unsupported protocol"; + + case CURLE_FAILED_INIT: + return "Failed initialization"; + + case CURLE_URL_MALFORMAT: + return "URL using bad/illegal format or missing URL"; + + case CURLE_NOT_BUILT_IN: + return "A requested feature, protocol or option was not found built-in in" + " this libcurl due to a build-time decision."; + + case CURLE_COULDNT_RESOLVE_PROXY: + return "Couldn't resolve proxy name"; + + case CURLE_COULDNT_RESOLVE_HOST: + return "Couldn't resolve host name"; + + case CURLE_COULDNT_CONNECT: + return "Couldn't connect to server"; + + case CURLE_WEIRD_SERVER_REPLY: + return "Weird server reply"; + + case CURLE_REMOTE_ACCESS_DENIED: + return "Access denied to remote resource"; + + case CURLE_FTP_ACCEPT_FAILED: + return "FTP: The server failed to connect to data port"; + + case CURLE_FTP_ACCEPT_TIMEOUT: + return "FTP: Accepting server connect has timed out"; + + case CURLE_FTP_PRET_FAILED: + return "FTP: The server did not accept the PRET command."; + + case CURLE_FTP_WEIRD_PASS_REPLY: + return "FTP: unknown PASS reply"; + + case CURLE_FTP_WEIRD_PASV_REPLY: + return "FTP: unknown PASV reply"; + + case CURLE_FTP_WEIRD_227_FORMAT: + return "FTP: unknown 227 response format"; + + case CURLE_FTP_CANT_GET_HOST: + return "FTP: can't figure out the host in the PASV response"; + + case CURLE_HTTP2: + return "Error in the HTTP2 framing layer"; + + case CURLE_FTP_COULDNT_SET_TYPE: + return "FTP: couldn't set file type"; + + case CURLE_PARTIAL_FILE: + return "Transferred a partial file"; + + case CURLE_FTP_COULDNT_RETR_FILE: + return "FTP: couldn't retrieve (RETR failed) the specified file"; + + case CURLE_QUOTE_ERROR: + return "Quote command returned error"; + + case CURLE_HTTP_RETURNED_ERROR: + return "HTTP response code said error"; + + case CURLE_WRITE_ERROR: + return "Failed writing received data to disk/application"; + + case CURLE_UPLOAD_FAILED: + return "Upload failed (at start/before it took off)"; + + case CURLE_READ_ERROR: + return "Failed to open/read local data from file/application"; + + case CURLE_OUT_OF_MEMORY: + return "Out of memory"; + + case CURLE_OPERATION_TIMEDOUT: + return "Timeout was reached"; + + case CURLE_FTP_PORT_FAILED: + return "FTP: command PORT failed"; + + case CURLE_FTP_COULDNT_USE_REST: + return "FTP: command REST failed"; + + case CURLE_RANGE_ERROR: + return "Requested range was not delivered by the server"; + + case CURLE_HTTP_POST_ERROR: + return "Internal problem setting up the POST"; + + case CURLE_SSL_CONNECT_ERROR: + return "SSL connect error"; + + case CURLE_BAD_DOWNLOAD_RESUME: + return "Couldn't resume download"; + + case CURLE_FILE_COULDNT_READ_FILE: + return "Couldn't read a file:// file"; + + case CURLE_LDAP_CANNOT_BIND: + return "LDAP: cannot bind"; + + case CURLE_LDAP_SEARCH_FAILED: + return "LDAP: search failed"; + + case CURLE_FUNCTION_NOT_FOUND: + return "A required function in the library was not found"; + + case CURLE_ABORTED_BY_CALLBACK: + return "Operation was aborted by an application callback"; + + case CURLE_BAD_FUNCTION_ARGUMENT: + return "A libcurl function was given a bad argument"; + + case CURLE_INTERFACE_FAILED: + return "Failed binding local connection end"; + + case CURLE_TOO_MANY_REDIRECTS : + return "Number of redirects hit maximum amount"; + + case CURLE_UNKNOWN_OPTION: + return "An unknown option was passed in to libcurl"; + + case CURLE_TELNET_OPTION_SYNTAX : + return "Malformed telnet option"; + + case CURLE_GOT_NOTHING: + return "Server returned nothing (no headers, no data)"; + + case CURLE_SSL_ENGINE_NOTFOUND: + return "SSL crypto engine not found"; + + case CURLE_SSL_ENGINE_SETFAILED: + return "Can not set SSL crypto engine as default"; + + case CURLE_SSL_ENGINE_INITFAILED: + return "Failed to initialise SSL crypto engine"; + + case CURLE_SEND_ERROR: + return "Failed sending data to the peer"; + + case CURLE_RECV_ERROR: + return "Failure when receiving data from the peer"; + + case CURLE_SSL_CERTPROBLEM: + return "Problem with the local SSL certificate"; + + case CURLE_SSL_CIPHER: + return "Couldn't use specified SSL cipher"; + + case CURLE_PEER_FAILED_VERIFICATION: + return "SSL peer certificate or SSH remote key was not OK"; + + case CURLE_SSL_CACERT_BADFILE: + return "Problem with the SSL CA cert (path? access rights?)"; + + case CURLE_BAD_CONTENT_ENCODING: + return "Unrecognized or bad HTTP Content or Transfer-Encoding"; + + case CURLE_LDAP_INVALID_URL: + return "Invalid LDAP URL"; + + case CURLE_FILESIZE_EXCEEDED: + return "Maximum file size exceeded"; + + case CURLE_USE_SSL_FAILED: + return "Requested SSL level failed"; + + case CURLE_SSL_SHUTDOWN_FAILED: + return "Failed to shut down the SSL connection"; + + case CURLE_SSL_CRL_BADFILE: + return "Failed to load CRL file (path? access rights?, format?)"; + + case CURLE_SSL_ISSUER_ERROR: + return "Issuer check against peer certificate failed"; + + case CURLE_SEND_FAIL_REWIND: + return "Send failed since rewinding of the data stream failed"; + + case CURLE_LOGIN_DENIED: + return "Login denied"; + + case CURLE_TFTP_NOTFOUND: + return "TFTP: File Not Found"; + + case CURLE_TFTP_PERM: + return "TFTP: Access Violation"; + + case CURLE_REMOTE_DISK_FULL: + return "Disk full or allocation exceeded"; + + case CURLE_TFTP_ILLEGAL: + return "TFTP: Illegal operation"; + + case CURLE_TFTP_UNKNOWNID: + return "TFTP: Unknown transfer ID"; + + case CURLE_REMOTE_FILE_EXISTS: + return "Remote file already exists"; + + case CURLE_TFTP_NOSUCHUSER: + return "TFTP: No such user"; + + case CURLE_CONV_FAILED: + return "Conversion failed"; + + case CURLE_CONV_REQD: + return "Caller must register CURLOPT_CONV_ callback options"; + + case CURLE_REMOTE_FILE_NOT_FOUND: + return "Remote file not found"; + + case CURLE_SSH: + return "Error in the SSH layer"; + + case CURLE_AGAIN: + return "Socket not ready for send/recv"; + + case CURLE_RTSP_CSEQ_ERROR: + return "RTSP CSeq mismatch or invalid CSeq"; + + case CURLE_RTSP_SESSION_ERROR: + return "RTSP session error"; + + case CURLE_FTP_BAD_FILE_LIST: + return "Unable to parse FTP file list"; + + case CURLE_CHUNK_FAILED: + return "Chunk callback failed"; + + case CURLE_NO_CONNECTION_AVAILABLE: + return "The max connection limit is reached"; + + case CURLE_SSL_PINNEDPUBKEYNOTMATCH: + return "SSL public key does not match pinned public key"; + + case CURLE_SSL_INVALIDCERTSTATUS: + return "SSL server certificate status verification FAILED"; + + case CURLE_HTTP2_STREAM: + return "Stream error in the HTTP/2 framing layer"; + + case CURLE_RECURSIVE_API_CALL: + return "API function called from within callback"; + + /* error codes not used by current libcurl */ + case CURLE_OBSOLETE20: + case CURLE_OBSOLETE24: + case CURLE_OBSOLETE29: + case CURLE_OBSOLETE32: + case CURLE_OBSOLETE40: + case CURLE_OBSOLETE44: + case CURLE_OBSOLETE46: + case CURLE_OBSOLETE50: + case CURLE_OBSOLETE51: + case CURLE_OBSOLETE57: + case CURL_LAST: + break; + } + /* + * By using a switch, gcc -Wall will complain about enum values + * which do not appear, helping keep this function up-to-date. + * By using gcc -Wall -Werror, you can't forget. + * + * A table would not have the same benefit. Most compilers will + * generate code very similar to a table in any case, so there + * is little performance gain from a table. And something is broken + * for the user's application, anyways, so does it matter how fast + * it _doesn't_ work? + * + * The line number for the error will be near this comment, which + * is why it is here, and not at the start of the switch. + */ + return "Unknown error"; +#else + if(!error) + return "No error"; + else + return "Error"; +#endif +} + +const char * +curl_multi_strerror(CURLMcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLM_CALL_MULTI_PERFORM: + return "Please call curl_multi_perform() soon"; + + case CURLM_OK: + return "No error"; + + case CURLM_BAD_HANDLE: + return "Invalid multi handle"; + + case CURLM_BAD_EASY_HANDLE: + return "Invalid easy handle"; + + case CURLM_OUT_OF_MEMORY: + return "Out of memory"; + + case CURLM_INTERNAL_ERROR: + return "Internal error"; + + case CURLM_BAD_SOCKET: + return "Invalid socket argument"; + + case CURLM_UNKNOWN_OPTION: + return "Unknown option"; + + case CURLM_ADDED_ALREADY: + return "The easy handle is already added to a multi handle"; + + case CURLM_RECURSIVE_API_CALL: + return "API function called from within callback"; + + case CURLM_LAST: + break; + } + + return "Unknown error"; +#else + if(error == CURLM_OK) + return "No error"; + else + return "Error"; +#endif +} + +const char * +curl_share_strerror(CURLSHcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLSHE_OK: + return "No error"; + + case CURLSHE_BAD_OPTION: + return "Unknown share option"; + + case CURLSHE_IN_USE: + return "Share currently in use"; + + case CURLSHE_INVALID: + return "Invalid share handle"; + + case CURLSHE_NOMEM: + return "Out of memory"; + + case CURLSHE_NOT_BUILT_IN: + return "Feature not enabled in this library"; + + case CURLSHE_LAST: + break; + } + + return "CURLSHcode unknown"; +#else + if(error == CURLSHE_OK) + return "No error"; + else + return "Error"; +#endif +} + +#ifdef USE_WINSOCK + +/* This function handles most / all (?) Winsock errors curl is able to produce. + */ +static const char * +get_winsock_error (int err, char *buf, size_t len) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + const char *p; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(err) { + case WSAEINTR: + p = "Call interrupted"; + break; + case WSAEBADF: + p = "Bad file"; + break; + case WSAEACCES: + p = "Bad access"; + break; + case WSAEFAULT: + p = "Bad argument"; + break; + case WSAEINVAL: + p = "Invalid arguments"; + break; + case WSAEMFILE: + p = "Out of file descriptors"; + break; + case WSAEWOULDBLOCK: + p = "Call would block"; + break; + case WSAEINPROGRESS: + case WSAEALREADY: + p = "Blocking call in progress"; + break; + case WSAENOTSOCK: + p = "Descriptor is not a socket"; + break; + case WSAEDESTADDRREQ: + p = "Need destination address"; + break; + case WSAEMSGSIZE: + p = "Bad message size"; + break; + case WSAEPROTOTYPE: + p = "Bad protocol"; + break; + case WSAENOPROTOOPT: + p = "Protocol option is unsupported"; + break; + case WSAEPROTONOSUPPORT: + p = "Protocol is unsupported"; + break; + case WSAESOCKTNOSUPPORT: + p = "Socket is unsupported"; + break; + case WSAEOPNOTSUPP: + p = "Operation not supported"; + break; + case WSAEAFNOSUPPORT: + p = "Address family not supported"; + break; + case WSAEPFNOSUPPORT: + p = "Protocol family not supported"; + break; + case WSAEADDRINUSE: + p = "Address already in use"; + break; + case WSAEADDRNOTAVAIL: + p = "Address not available"; + break; + case WSAENETDOWN: + p = "Network down"; + break; + case WSAENETUNREACH: + p = "Network unreachable"; + break; + case WSAENETRESET: + p = "Network has been reset"; + break; + case WSAECONNABORTED: + p = "Connection was aborted"; + break; + case WSAECONNRESET: + p = "Connection was reset"; + break; + case WSAENOBUFS: + p = "No buffer space"; + break; + case WSAEISCONN: + p = "Socket is already connected"; + break; + case WSAENOTCONN: + p = "Socket is not connected"; + break; + case WSAESHUTDOWN: + p = "Socket has been shut down"; + break; + case WSAETOOMANYREFS: + p = "Too many references"; + break; + case WSAETIMEDOUT: + p = "Timed out"; + break; + case WSAECONNREFUSED: + p = "Connection refused"; + break; + case WSAELOOP: + p = "Loop??"; + break; + case WSAENAMETOOLONG: + p = "Name too long"; + break; + case WSAEHOSTDOWN: + p = "Host down"; + break; + case WSAEHOSTUNREACH: + p = "Host unreachable"; + break; + case WSAENOTEMPTY: + p = "Not empty"; + break; + case WSAEPROCLIM: + p = "Process limit reached"; + break; + case WSAEUSERS: + p = "Too many users"; + break; + case WSAEDQUOT: + p = "Bad quota"; + break; + case WSAESTALE: + p = "Something is stale"; + break; + case WSAEREMOTE: + p = "Remote error"; + break; +#ifdef WSAEDISCON /* missing in SalfordC! */ + case WSAEDISCON: + p = "Disconnected"; + break; +#endif + /* Extended Winsock errors */ + case WSASYSNOTREADY: + p = "Winsock library is not ready"; + break; + case WSANOTINITIALISED: + p = "Winsock library not initialised"; + break; + case WSAVERNOTSUPPORTED: + p = "Winsock version not supported"; + break; + + /* getXbyY() errors (already handled in herrmsg): + * Authoritative Answer: Host not found */ + case WSAHOST_NOT_FOUND: + p = "Host not found"; + break; + + /* Non-Authoritative: Host not found, or SERVERFAIL */ + case WSATRY_AGAIN: + p = "Host not found, try again"; + break; + + /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ + case WSANO_RECOVERY: + p = "Unrecoverable error in call to nameserver"; + break; + + /* Valid name, no data record of requested type */ + case WSANO_DATA: + p = "No data record of requested type"; + break; + + default: + return NULL; + } +#else + if(!err) + return NULL; + else + p = "error"; +#endif + strncpy(buf, p, len); + buf [len-1] = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return buf; +} +#endif /* USE_WINSOCK */ + +/* + * Our thread-safe and smart strerror() replacement. + * + * The 'err' argument passed in to this function MUST be a true errno number + * as reported on this system. We do no range checking on the number before + * we pass it to the "number-to-message" conversion function and there might + * be systems that don't do proper range checking in there themselves. + * + * We don't do range checking (on systems other than Windows) since there is + * no good reliable and portable way to do it. + */ +const char *Curl_strerror(int err, char *buf, size_t buflen) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + char *p; + size_t max; + + DEBUGASSERT(err >= 0); + + max = buflen - 1; + *buf = '\0'; + +#ifdef USE_WINSOCK + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL); + wcstombs(buf, wbuf, max); + } +#else + /* 'sys_nerr' is the maximum errno number, it is not widely portable */ + //if(err >= 0 && err < sys_nerr) + strncpy(buf, strerror(err), max); + /*else { + if(!get_winsock_error(err, buf, max) && + !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, buf, (DWORD)max, NULL)) + msnprintf(buf, max, "Unknown error %d (%#x)", err, err); + } + */ +#endif + +#else /* not USE_WINSOCK coming up */ + +#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R) + /* + * The POSIX-style strerror_r() may set errno to ERANGE if insufficient + * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated + * message string, or EINVAL if 'errnum' is not a valid error number. + */ + if(0 != strerror_r(err, buf, max)) { + if('\0' == buf[0]) + msnprintf(buf, max, "Unknown error %d", err); + } +#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R) + /* + * The glibc-style strerror_r() only *might* use the buffer we pass to + * the function, but it always returns the error message as a pointer, + * so we must copy that string unconditionally (if non-NULL). + */ + { + char buffer[256]; + char *msg = strerror_r(err, buffer, sizeof(buffer)); + if(msg) + strncpy(buf, msg, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R) + /* + * The vxworks-style strerror_r() does use the buffer we pass to the function. + * The buffer size should be at least NAME_MAX (256) + */ + { + char buffer[256]; + if(OK == strerror_r(err, buffer)) + strncpy(buf, buffer, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#else + { + char *msg = strerror(err); + if(msg) + strncpy(buf, msg, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#endif + +#endif /* end of ! USE_WINSOCK */ + + buf[max] = '\0'; /* make sure the string is zero terminated */ + + /* strip trailing '\r\n' or '\n'. */ + p = strrchr(buf, '\n'); + if(p && (p - buf) >= 2) + *p = '\0'; + p = strrchr(buf, '\r'); + if(p && (p - buf) >= 1) + *p = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return buf; +} + +#ifdef USE_WINDOWS_SSPI +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + const char *txt; + char *outbuf; + size_t outmax; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + char txtbuf[80]; + char msgbuf[256]; + char *p, *str, *msg = NULL; + bool msg_formatted = FALSE; +#endif + + outbuf = buf; + outmax = buflen - 1; + *outbuf = '\0'; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + + switch(err) { + case SEC_E_OK: + txt = "No error"; + break; + case CRYPT_E_REVOKED: + txt = "CRYPT_E_REVOKED"; + break; + case SEC_E_ALGORITHM_MISMATCH: + txt = "SEC_E_ALGORITHM_MISMATCH"; + break; + case SEC_E_BAD_BINDINGS: + txt = "SEC_E_BAD_BINDINGS"; + break; + case SEC_E_BAD_PKGID: + txt = "SEC_E_BAD_PKGID"; + break; + case SEC_E_BUFFER_TOO_SMALL: + txt = "SEC_E_BUFFER_TOO_SMALL"; + break; + case SEC_E_CANNOT_INSTALL: + txt = "SEC_E_CANNOT_INSTALL"; + break; + case SEC_E_CANNOT_PACK: + txt = "SEC_E_CANNOT_PACK"; + break; + case SEC_E_CERT_EXPIRED: + txt = "SEC_E_CERT_EXPIRED"; + break; + case SEC_E_CERT_UNKNOWN: + txt = "SEC_E_CERT_UNKNOWN"; + break; + case SEC_E_CERT_WRONG_USAGE: + txt = "SEC_E_CERT_WRONG_USAGE"; + break; + case SEC_E_CONTEXT_EXPIRED: + txt = "SEC_E_CONTEXT_EXPIRED"; + break; + case SEC_E_CROSSREALM_DELEGATION_FAILURE: + txt = "SEC_E_CROSSREALM_DELEGATION_FAILURE"; + break; + case SEC_E_CRYPTO_SYSTEM_INVALID: + txt = "SEC_E_CRYPTO_SYSTEM_INVALID"; + break; + case SEC_E_DECRYPT_FAILURE: + txt = "SEC_E_DECRYPT_FAILURE"; + break; + case SEC_E_DELEGATION_POLICY: + txt = "SEC_E_DELEGATION_POLICY"; + break; + case SEC_E_DELEGATION_REQUIRED: + txt = "SEC_E_DELEGATION_REQUIRED"; + break; + case SEC_E_DOWNGRADE_DETECTED: + txt = "SEC_E_DOWNGRADE_DETECTED"; + break; + case SEC_E_ENCRYPT_FAILURE: + txt = "SEC_E_ENCRYPT_FAILURE"; + break; + case SEC_E_ILLEGAL_MESSAGE: + txt = "SEC_E_ILLEGAL_MESSAGE"; + break; + case SEC_E_INCOMPLETE_CREDENTIALS: + txt = "SEC_E_INCOMPLETE_CREDENTIALS"; + break; + case SEC_E_INCOMPLETE_MESSAGE: + txt = "SEC_E_INCOMPLETE_MESSAGE"; + break; + case SEC_E_INSUFFICIENT_MEMORY: + txt = "SEC_E_INSUFFICIENT_MEMORY"; + break; + case SEC_E_INTERNAL_ERROR: + txt = "SEC_E_INTERNAL_ERROR"; + break; + case SEC_E_INVALID_HANDLE: + txt = "SEC_E_INVALID_HANDLE"; + break; + case SEC_E_INVALID_PARAMETER: + txt = "SEC_E_INVALID_PARAMETER"; + break; + case SEC_E_INVALID_TOKEN: + txt = "SEC_E_INVALID_TOKEN"; + break; + case SEC_E_ISSUING_CA_UNTRUSTED: + txt = "SEC_E_ISSUING_CA_UNTRUSTED"; + break; + case SEC_E_ISSUING_CA_UNTRUSTED_KDC: + txt = "SEC_E_ISSUING_CA_UNTRUSTED_KDC"; + break; + case SEC_E_KDC_CERT_EXPIRED: + txt = "SEC_E_KDC_CERT_EXPIRED"; + break; + case SEC_E_KDC_CERT_REVOKED: + txt = "SEC_E_KDC_CERT_REVOKED"; + break; + case SEC_E_KDC_INVALID_REQUEST: + txt = "SEC_E_KDC_INVALID_REQUEST"; + break; + case SEC_E_KDC_UNABLE_TO_REFER: + txt = "SEC_E_KDC_UNABLE_TO_REFER"; + break; + case SEC_E_KDC_UNKNOWN_ETYPE: + txt = "SEC_E_KDC_UNKNOWN_ETYPE"; + break; + case SEC_E_LOGON_DENIED: + txt = "SEC_E_LOGON_DENIED"; + break; + case SEC_E_MAX_REFERRALS_EXCEEDED: + txt = "SEC_E_MAX_REFERRALS_EXCEEDED"; + break; + case SEC_E_MESSAGE_ALTERED: + txt = "SEC_E_MESSAGE_ALTERED"; + break; + case SEC_E_MULTIPLE_ACCOUNTS: + txt = "SEC_E_MULTIPLE_ACCOUNTS"; + break; + case SEC_E_MUST_BE_KDC: + txt = "SEC_E_MUST_BE_KDC"; + break; + case SEC_E_NOT_OWNER: + txt = "SEC_E_NOT_OWNER"; + break; + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + txt = "SEC_E_NO_AUTHENTICATING_AUTHORITY"; + break; + case SEC_E_NO_CREDENTIALS: + txt = "SEC_E_NO_CREDENTIALS"; + break; + case SEC_E_NO_IMPERSONATION: + txt = "SEC_E_NO_IMPERSONATION"; + break; + case SEC_E_NO_IP_ADDRESSES: + txt = "SEC_E_NO_IP_ADDRESSES"; + break; + case SEC_E_NO_KERB_KEY: + txt = "SEC_E_NO_KERB_KEY"; + break; + case SEC_E_NO_PA_DATA: + txt = "SEC_E_NO_PA_DATA"; + break; + case SEC_E_NO_S4U_PROT_SUPPORT: + txt = "SEC_E_NO_S4U_PROT_SUPPORT"; + break; + case SEC_E_NO_TGT_REPLY: + txt = "SEC_E_NO_TGT_REPLY"; + break; + case SEC_E_OUT_OF_SEQUENCE: + txt = "SEC_E_OUT_OF_SEQUENCE"; + break; + case SEC_E_PKINIT_CLIENT_FAILURE: + txt = "SEC_E_PKINIT_CLIENT_FAILURE"; + break; + case SEC_E_PKINIT_NAME_MISMATCH: + txt = "SEC_E_PKINIT_NAME_MISMATCH"; + break; + case SEC_E_POLICY_NLTM_ONLY: + txt = "SEC_E_POLICY_NLTM_ONLY"; + break; + case SEC_E_QOP_NOT_SUPPORTED: + txt = "SEC_E_QOP_NOT_SUPPORTED"; + break; + case SEC_E_REVOCATION_OFFLINE_C: + txt = "SEC_E_REVOCATION_OFFLINE_C"; + break; + case SEC_E_REVOCATION_OFFLINE_KDC: + txt = "SEC_E_REVOCATION_OFFLINE_KDC"; + break; + case SEC_E_SECPKG_NOT_FOUND: + txt = "SEC_E_SECPKG_NOT_FOUND"; + break; + case SEC_E_SECURITY_QOS_FAILED: + txt = "SEC_E_SECURITY_QOS_FAILED"; + break; + case SEC_E_SHUTDOWN_IN_PROGRESS: + txt = "SEC_E_SHUTDOWN_IN_PROGRESS"; + break; + case SEC_E_SMARTCARD_CERT_EXPIRED: + txt = "SEC_E_SMARTCARD_CERT_EXPIRED"; + break; + case SEC_E_SMARTCARD_CERT_REVOKED: + txt = "SEC_E_SMARTCARD_CERT_REVOKED"; + break; + case SEC_E_SMARTCARD_LOGON_REQUIRED: + txt = "SEC_E_SMARTCARD_LOGON_REQUIRED"; + break; + case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED: + txt = "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED"; + break; + case SEC_E_TARGET_UNKNOWN: + txt = "SEC_E_TARGET_UNKNOWN"; + break; + case SEC_E_TIME_SKEW: + txt = "SEC_E_TIME_SKEW"; + break; + case SEC_E_TOO_MANY_PRINCIPALS: + txt = "SEC_E_TOO_MANY_PRINCIPALS"; + break; + case SEC_E_UNFINISHED_CONTEXT_DELETED: + txt = "SEC_E_UNFINISHED_CONTEXT_DELETED"; + break; + case SEC_E_UNKNOWN_CREDENTIALS: + txt = "SEC_E_UNKNOWN_CREDENTIALS"; + break; + case SEC_E_UNSUPPORTED_FUNCTION: + txt = "SEC_E_UNSUPPORTED_FUNCTION"; + break; + case SEC_E_UNSUPPORTED_PREAUTH: + txt = "SEC_E_UNSUPPORTED_PREAUTH"; + break; + case SEC_E_UNTRUSTED_ROOT: + txt = "SEC_E_UNTRUSTED_ROOT"; + break; + case SEC_E_WRONG_CREDENTIAL_HANDLE: + txt = "SEC_E_WRONG_CREDENTIAL_HANDLE"; + break; + case SEC_E_WRONG_PRINCIPAL: + txt = "SEC_E_WRONG_PRINCIPAL"; + break; + case SEC_I_COMPLETE_AND_CONTINUE: + txt = "SEC_I_COMPLETE_AND_CONTINUE"; + break; + case SEC_I_COMPLETE_NEEDED: + txt = "SEC_I_COMPLETE_NEEDED"; + break; + case SEC_I_CONTEXT_EXPIRED: + txt = "SEC_I_CONTEXT_EXPIRED"; + break; + case SEC_I_CONTINUE_NEEDED: + txt = "SEC_I_CONTINUE_NEEDED"; + break; + case SEC_I_INCOMPLETE_CREDENTIALS: + txt = "SEC_I_INCOMPLETE_CREDENTIALS"; + break; + case SEC_I_LOCAL_LOGON: + txt = "SEC_I_LOCAL_LOGON"; + break; + case SEC_I_NO_LSA_CONTEXT: + txt = "SEC_I_NO_LSA_CONTEXT"; + break; + case SEC_I_RENEGOTIATE: + txt = "SEC_I_RENEGOTIATE"; + break; + case SEC_I_SIGNATURE_NEEDED: + txt = "SEC_I_SIGNATURE_NEEDED"; + break; + default: + txt = "Unknown error"; + } + + if(err == SEC_E_OK) + strncpy(outbuf, txt, outmax); + else if(err == SEC_E_ILLEGAL_MESSAGE) + msnprintf(outbuf, outmax, + "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs " + "when a fatal SSL/TLS alert is received (e.g. handshake failed)." + " More detail may be available in the Windows System event log.", + err); + else { + str = txtbuf; + msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err); + txtbuf[sizeof(txtbuf)-1] = '\0'; + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) { + wcstombs(msgbuf, wbuf, sizeof(msgbuf)-1); + msg_formatted = TRUE; + } + } +#else + if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + msgbuf, sizeof(msgbuf)-1, NULL)) { + msg_formatted = TRUE; + } +#endif + if(msg_formatted) { + msgbuf[sizeof(msgbuf)-1] = '\0'; + /* strip trailing '\r\n' or '\n' */ + p = strrchr(msgbuf, '\n'); + if(p && (p - msgbuf) >= 2) + *p = '\0'; + p = strrchr(msgbuf, '\r'); + if(p && (p - msgbuf) >= 1) + *p = '\0'; + msg = msgbuf; + } + if(msg) + msnprintf(outbuf, outmax, "%s - %s", str, msg); + else + strncpy(outbuf, str, outmax); + } + +#else + + if(err == SEC_E_OK) + txt = "No error"; + else + txt = "Error"; + + strncpy(outbuf, txt, outmax); + +#endif + + outbuf[outmax] = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return outbuf; +} +#endif /* USE_WINDOWS_SSPI */ diff --git a/libcurl/lib/strerror.h b/libcurl/lib/strerror.h new file mode 100644 index 0000000..683b5b4 --- /dev/null +++ b/libcurl/lib/strerror.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_STRERROR_H +#define HEADER_CURL_STRERROR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "urldata.h" + +#define STRERROR_LEN 128 /* a suitable length */ + +const char *Curl_strerror(int err, char *buf, size_t buflen); +#ifdef USE_WINDOWS_SSPI +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen); +#endif + +#endif /* HEADER_CURL_STRERROR_H */ diff --git a/libcurl/lib/strtok.c b/libcurl/lib/strtok.c new file mode 100644 index 0000000..460eb87 --- /dev/null +++ b/libcurl/lib/strtok.c @@ -0,0 +1,66 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef HAVE_STRTOK_R +#include + +#include "strtok.h" + +char * +Curl_strtok_r(char *ptr, const char *sep, char **end) +{ + if(!ptr) + /* we got NULL input so then we get our last position instead */ + ptr = *end; + + /* pass all letters that are including in the separator string */ + while(*ptr && strchr(sep, *ptr)) + ++ptr; + + if(*ptr) { + /* so this is where the next piece of string starts */ + char *start = ptr; + + /* set the end pointer to the first byte after the start */ + *end = start + 1; + + /* scan through the string to find where it ends, it ends on a + null byte or a character that exists in the separator string */ + while(**end && !strchr(sep, **end)) + ++*end; + + if(**end) { + /* the end is not a null byte */ + **end = '\0'; /* zero terminate it! */ + ++*end; /* advance the last pointer to beyond the null byte */ + } + + return start; /* return the position where the string starts */ + } + + /* we ended up on a null byte, there are no more strings to find! */ + return NULL; +} + +#endif /* this was only compiled if strtok_r wasn't present */ diff --git a/libcurl/lib/strtok.h b/libcurl/lib/strtok.h new file mode 100644 index 0000000..90b831e --- /dev/null +++ b/libcurl/lib/strtok.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_STRTOK_H +#define HEADER_CURL_STRTOK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +#include + +#ifndef HAVE_STRTOK_R +char *Curl_strtok_r(char *s, const char *delim, char **last); +#define strtok_r Curl_strtok_r +#else +#include +#endif + +#endif /* HEADER_CURL_STRTOK_H */ diff --git a/libcurl/lib/strtoofft.c b/libcurl/lib/strtoofft.c new file mode 100644 index 0000000..546a3ff --- /dev/null +++ b/libcurl/lib/strtoofft.c @@ -0,0 +1,242 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include "curl_setup.h" + +#include "strtoofft.h" + +/* + * NOTE: + * + * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we + * could use in case strtoll() doesn't exist... See + * https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html + */ + +#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG) +# ifdef HAVE_STRTOLL +# define strtooff strtoll +# else +# if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64) +# if defined(_SAL_VERSION) + _Check_return_ _CRTIMP __int64 __cdecl _strtoi64( + _In_z_ const char *_String, + _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix); +# else + _CRTIMP __int64 __cdecl _strtoi64(const char *_String, + char **_EndPtr, int _Radix); +# endif +# define strtooff _strtoi64 +# else +# define PRIVATE_STRTOOFF 1 +# endif +# endif +#else +# define strtooff strtol +#endif + +#ifdef PRIVATE_STRTOOFF + +/* Range tests can be used for alphanum decoding if characters are consecutive, + like in ASCII. Else an array is scanned. Determine this condition now. */ + +#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25 + +#define NO_RANGE_TEST + +static const char valchars[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +#endif + +static int get_char(char c, int base); + +/** + * Custom version of the strtooff function. This extracts a curl_off_t + * value from the given input string and returns it. + */ +static curl_off_t strtooff(const char *nptr, char **endptr, int base) +{ + char *end; + int is_negative = 0; + int overflow; + int i; + curl_off_t value = 0; + curl_off_t newval; + + /* Skip leading whitespace. */ + end = (char *)nptr; + while(ISSPACE(end[0])) { + end++; + } + + /* Handle the sign, if any. */ + if(end[0] == '-') { + is_negative = 1; + end++; + } + else if(end[0] == '+') { + end++; + } + else if(end[0] == '\0') { + /* We had nothing but perhaps some whitespace -- there was no number. */ + if(endptr) { + *endptr = end; + } + return 0; + } + + /* Handle special beginnings, if present and allowed. */ + if(end[0] == '0' && end[1] == 'x') { + if(base == 16 || base == 0) { + end += 2; + base = 16; + } + } + else if(end[0] == '0') { + if(base == 8 || base == 0) { + end++; + base = 8; + } + } + + /* Matching strtol, if the base is 0 and it doesn't look like + * the number is octal or hex, we assume it's base 10. + */ + if(base == 0) { + base = 10; + } + + /* Loop handling digits. */ + value = 0; + overflow = 0; + for(i = get_char(end[0], base); + i != -1; + end++, i = get_char(end[0], base)) { + newval = base * value + i; + if(newval < value) { + /* We've overflowed. */ + overflow = 1; + break; + } + else + value = newval; + } + + if(!overflow) { + if(is_negative) { + /* Fix the sign. */ + value *= -1; + } + } + else { + if(is_negative) + value = CURL_OFF_T_MIN; + else + value = CURL_OFF_T_MAX; + + errno = ERANGE; + } + + if(endptr) + *endptr = end; + + return value; +} + +/** + * Returns the value of c in the given base, or -1 if c cannot + * be interpreted properly in that base (i.e., is out of range, + * is a null, etc.). + * + * @param c the character to interpret according to base + * @param base the base in which to interpret c + * + * @return the value of c in base, or -1 if c isn't in range + */ +static int get_char(char c, int base) +{ +#ifndef NO_RANGE_TEST + int value = -1; + if(c <= '9' && c >= '0') { + value = c - '0'; + } + else if(c <= 'Z' && c >= 'A') { + value = c - 'A' + 10; + } + else if(c <= 'z' && c >= 'a') { + value = c - 'a' + 10; + } +#else + const char *cp; + int value; + + cp = memchr(valchars, c, 10 + 26 + 26); + + if(!cp) + return -1; + + value = cp - valchars; + + if(value >= 10 + 26) + value -= 26; /* Lowercase. */ +#endif + + if(value >= base) { + value = -1; + } + + return value; +} +#endif /* Only present if we need strtoll, but don't have it. */ + +/* + * Parse a *positive* up to 64 bit number written in ascii. + */ +CURLofft curlx_strtoofft(const char *str, char **endp, int base, + curl_off_t *num) +{ + char *end; + curl_off_t number; + errno = 0; + *num = 0; /* clear by default */ + + while(*str && ISSPACE(*str)) + str++; + if('-' == *str) { + if(endp) + *endp = (char *)str; /* didn't actually move */ + return CURL_OFFT_INVAL; /* nothing parsed */ + } + number = strtooff(str, &end, base); + if(endp) + *endp = end; + if(errno == ERANGE) + /* overflow/underflow */ + return CURL_OFFT_FLOW; + else if(str == end) + /* nothing parsed */ + return CURL_OFFT_INVAL; + + *num = number; + return CURL_OFFT_OK; +} diff --git a/libcurl/lib/strtoofft.h b/libcurl/lib/strtoofft.h new file mode 100644 index 0000000..be19cd7 --- /dev/null +++ b/libcurl/lib/strtoofft.h @@ -0,0 +1,52 @@ +#ifndef HEADER_CURL_STRTOOFFT_H +#define HEADER_CURL_STRTOOFFT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * Determine which string to integral data type conversion function we use + * to implement string conversion to our curl_off_t integral data type. + * + * Notice that curl_off_t might be 64 or 32 bit wide, and that it might use + * an underlying data type which might be 'long', 'int64_t', 'long long' or + * '__int64' and more remotely other data types. + * + * On systems where the size of curl_off_t is greater than the size of 'long' + * the conversion function to use is strtoll() if it is available, otherwise, + * we emulate its functionality with our own clone. + * + * On systems where the size of curl_off_t is smaller or equal than the size + * of 'long' the conversion function to use is strtol(). + */ + +typedef enum { + CURL_OFFT_OK, /* parsed fine */ + CURL_OFFT_FLOW, /* over or underflow */ + CURL_OFFT_INVAL /* nothing was parsed */ +} CURLofft; + +CURLofft curlx_strtoofft(const char *str, char **endp, int base, + curl_off_t *num); + +#endif /* HEADER_CURL_STRTOOFFT_H */ diff --git a/libcurl/lib/system_win32.c b/libcurl/lib/system_win32.c new file mode 100644 index 0000000..da3c86c --- /dev/null +++ b/libcurl/lib/system_win32.c @@ -0,0 +1,451 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2016 - 2019, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(WIN32) + +#include +#include "system_win32.h" +#include "curl_sspi.h" +#include "warnless.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +LARGE_INTEGER Curl_freq; +bool Curl_isVistaOrGreater; + +/* Handle of iphlpapp.dll */ +static HMODULE s_hIpHlpApiDll = NULL; + +/* Pointer to the if_nametoindex function */ +IF_NAMETOINDEX_FN Curl_if_nametoindex = NULL; + +/* Curl_win32_init() performs win32 global initialization */ +CURLcode Curl_win32_init(long flags) +{ + /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which + is just for Winsock at the moment. Any required win32 initialization + should take place after this block. */ + if(flags & CURL_GLOBAL_WIN32) { +#ifdef USE_WINSOCK + WORD wVersionRequested; + WSADATA wsaData; + int res; + +#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) +#error IPV6_requires_winsock2 +#endif + + wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); + + res = WSAStartup(wVersionRequested, &wsaData); + + if(res != 0) + /* Tell the user that we couldn't find a usable */ + /* winsock.dll. */ + return CURLE_FAILED_INIT; + + /* Confirm that the Windows Sockets DLL supports what we need.*/ + /* Note that if the DLL supports versions greater */ + /* than wVersionRequested, it will still return */ + /* wVersionRequested in wVersion. wHighVersion contains the */ + /* highest supported version. */ + + if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { + /* Tell the user that we couldn't find a usable */ + + /* winsock.dll. */ + WSACleanup(); + return CURLE_FAILED_INIT; + } + /* The Windows Sockets DLL is acceptable. Proceed. */ + #elif defined(USE_LWIPSOCK) + lwip_init(); + #endif + } /* CURL_GLOBAL_WIN32 */ + +#ifdef USE_WINDOWS_SSPI + { + CURLcode result = Curl_sspi_global_init(); + if(result) + return result; + } +#endif + + #ifdef _XBOX +// Xbox does not support LoadLibrary or GetProcAddress +#else +s_hIpHlpApiDll = Curl_load_library(TEXT("iphlpapi.dll")); +if(s_hIpHlpApiDll) { + /* Get the address of the if_nametoindex function */ + IF_NAMETOINDEX_FN pIfNameToIndex = + CURLX_FUNCTION_CAST(IF_NAMETOINDEX_FN, + (GetProcAddress(s_hIpHlpApiDll, "if_nametoindex"))); + + if(pIfNameToIndex) + Curl_if_nametoindex = pIfNameToIndex; +} +#endif + + if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { + Curl_isVistaOrGreater = TRUE; + QueryPerformanceFrequency(&Curl_freq); + } + else + Curl_isVistaOrGreater = FALSE; + + return CURLE_OK; +} + +/* Curl_win32_cleanup() is the opposite of Curl_win32_init() */ +void Curl_win32_cleanup(long init_flags) +{ +#ifdef _XBOX + // Xbox does not support FreeLibrary +#else + if(s_hIpHlpApiDll) { + FreeLibrary(s_hIpHlpApiDll); + s_hIpHlpApiDll = NULL; + Curl_if_nametoindex = NULL; + } +#endif + +#ifdef USE_WINDOWS_SSPI + Curl_sspi_global_cleanup(); +#endif + + if(init_flags & CURL_GLOBAL_WIN32) { +#ifdef USE_WINSOCK + WSACleanup(); +#endif + } +} + +#if !defined(LOAD_WITH_ALTERED_SEARCH_PATH) +#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008 +#endif + +#if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32) +#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 +#endif + +/* We use our own typedef here since some headers might lack these */ +typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); + +/* See function definitions in winbase.h */ +#ifdef UNICODE +# ifdef _WIN32_WCE +# define LOADLIBARYEX L"LoadLibraryExW" +# else +# define LOADLIBARYEX "LoadLibraryExW" +# endif +#else +# define LOADLIBARYEX "LoadLibraryExA" +#endif + +/* + * Curl_verify_windows_version() + * + * This is used to verify if we are running on a specific windows version. + * + * Parameters: + * + * majorVersion [in] - The major version number. + * minorVersion [in] - The minor version number. + * platform [in] - The optional platform identifier. + * condition [in] - The test condition used to specifier whether we are + * checking a version less then, equal to or greater than + * what is specified in the major and minor version + * numbers. + * + * Returns TRUE if matched; otherwise FALSE. + */ +bool Curl_verify_windows_version(const unsigned int majorVersion, + const unsigned int minorVersion, + const PlatformIdentifier platform, + const VersionCondition condition) +{ + bool matched = FALSE; + +#if defined(CURL_WINDOWS_APP) + /* We have no way to determine the Windows version from Windows apps, + so let's assume we're running on the target Windows version. */ + /*const WORD fullVersion = MAKEWORD(minorVersion, majorVersion); + const WORD targetVersion = (WORD)_WIN32_WINNT; + + switch(condition) { + case VERSION_LESS_THAN: + matched = targetVersion < fullVersion; + break; + + case VERSION_LESS_THAN_EQUAL: + matched = targetVersion <= fullVersion; + break; + + case VERSION_EQUAL: + matched = targetVersion == fullVersion; + break; + + case VERSION_GREATER_THAN_EQUAL: + matched = targetVersion >= fullVersion; + break; + + case VERSION_GREATER_THAN: + matched = targetVersion > fullVersion; + break; + } + + if(matched && (platform == PLATFORM_WINDOWS)) { + /* we're always running on PLATFORM_WINNT */ + /*matched = FALSE; + }*/ +#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \ + (_WIN32_WINNT < _WIN32_WINNT_WIN2K) + /*OSVERSIONINFO osver; + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + + /* Find out Windows version */ + /*if(GetVersionEx(&osver)) { + /* Verify the Operating System version number */ + /*switch(condition) { + case VERSION_LESS_THAN: + if(osver.dwMajorVersion < majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion < minorVersion)) + matched = TRUE; + break; + + case VERSION_LESS_THAN_EQUAL: + if(osver.dwMajorVersion < majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion <= minorVersion)) + matched = TRUE; + break; + + case VERSION_EQUAL: + if(osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion == minorVersion) + matched = TRUE; + break; + + case VERSION_GREATER_THAN_EQUAL: + if(osver.dwMajorVersion > majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion >= minorVersion)) + matched = TRUE; + break; + + case VERSION_GREATER_THAN: + if(osver.dwMajorVersion > majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion > minorVersion)) + matched = TRUE; + break; + }*/ + + /* Verify the platform identifier (if necessary) */ + /*if(matched) { + switch(platform) { + case PLATFORM_WINDOWS: + if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) + matched = FALSE; + break; + + case PLATFORM_WINNT: + if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT) + matched = FALSE; + + default: */ /*like platform == PLATFORM_DONT_CARE */ + /*break; + } + } + }*/ +#else + ULONGLONG cm = 0; + OSVERSIONINFOEX osver; + BYTE majorCondition; + BYTE minorCondition; + BYTE spMajorCondition; + BYTE spMinorCondition; + + switch(condition) { + case VERSION_LESS_THAN: + majorCondition = VER_LESS; + minorCondition = VER_LESS; + spMajorCondition = VER_LESS_EQUAL; + spMinorCondition = VER_LESS_EQUAL; + break; + + case VERSION_LESS_THAN_EQUAL: + majorCondition = VER_LESS_EQUAL; + minorCondition = VER_LESS_EQUAL; + spMajorCondition = VER_LESS_EQUAL; + spMinorCondition = VER_LESS_EQUAL; + break; + + case VERSION_EQUAL: + majorCondition = VER_EQUAL; + minorCondition = VER_EQUAL; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + case VERSION_GREATER_THAN_EQUAL: + majorCondition = VER_GREATER_EQUAL; + minorCondition = VER_GREATER_EQUAL; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + case VERSION_GREATER_THAN: + majorCondition = VER_GREATER; + minorCondition = VER_GREATER; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + default: + return FALSE; + } + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + osver.dwMajorVersion = majorVersion; + osver.dwMinorVersion = minorVersion; + if(platform == PLATFORM_WINDOWS) + osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; + else if(platform == PLATFORM_WINNT) + osver.dwPlatformId = VER_PLATFORM_WIN32_NT; + + cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition); + cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition); + cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition); + cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition); + if(platform != PLATFORM_DONT_CARE) + cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL); + + if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), + cm)) + matched = TRUE; +#endif + + return matched; +} + +/* + * Curl_load_library() + * + * This is used to dynamically load DLLs using the most secure method available + * for the version of Windows that we are running on. + * + * Parameters: + * + * filename [in] - The filename or full path of the DLL to load. If only the + * filename is passed then the DLL will be loaded from the + * Windows system directory. + * + * Returns the handle of the module on success; otherwise NULL. + */ +#ifdef _XBOX +HMODULE Curl_load_library(LPCTSTR filename) { + (void)filename; + return NULL; // Xbox does not support dynamic library loading +} +#else +#ifndef CURL_WINDOWS_APP + HMODULE hModule = NULL; + LOADLIBRARYEX_FN pLoadLibraryEx = NULL; + + /* Get a handle to kernel32 so we can access it's functions at runtime */ + HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32")); + if(!hKernel32) + return NULL; + + /* Attempt to find LoadLibraryEx() which is only available on Windows 2000 + and above */ + pLoadLibraryEx = + CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN, + (GetProcAddress(hKernel32, LOADLIBARYEX))); + + /* Detect if there's already a path in the filename and load the library if + there is. Note: Both back slashes and forward slashes have been supported + since the earlier days of DOS at an API level although they are not + supported by command prompt */ + if(_tcspbrk(filename, TEXT("\\/"))) { + /** !checksrc! disable BANNEDFUNC 1 **/ + hModule = pLoadLibraryEx ? + pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : + LoadLibrary(filename); + } + /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only + supported on Windows Vista, Windows Server 2008, Windows 7 and Windows + Server 2008 R2 with this patch or natively on Windows 8 and above */ + else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) { + /* Load the DLL from the Windows system directory */ + hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + } + else { + /* Attempt to get the Windows system path */ + #ifdef _XBOX + UINT systemdirlen = 0; // Xbox does not have a system directory + #else + UINT systemdirlen = GetSystemDirectory(NULL, 0); + #endif + if(systemdirlen) { + /* Allocate space for the full DLL path (Room for the null terminator + is included in systemdirlen) */ + size_t filenamelen = _tcslen(filename); + TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen)); + if(path && GetSystemDirectory(path, systemdirlen)) { + /* Calculate the full DLL path */ + _tcscpy(path + _tcslen(path), TEXT("\\")); + _tcscpy(path + _tcslen(path), filename); + + /* Load the DLL from the Windows system directory */ + /** !checksrc! disable BANNEDFUNC 1 **/ + hModule = pLoadLibraryEx ? + pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : + LoadLibrary(path); + + } + free(path); + } + } + return hModule; +#else + /* the Universal Windows Platform (UWP) can't do this */ + (void)filename; + return NULL; +#endif + +} +#endif + +#endif /* WIN32 */ diff --git a/libcurl/lib/system_win32.h b/libcurl/lib/system_win32.h new file mode 100644 index 0000000..d2882fc --- /dev/null +++ b/libcurl/lib/system_win32.h @@ -0,0 +1,68 @@ +#ifndef HEADER_CURL_SYSTEM_WIN32_H +#define HEADER_CURL_SYSTEM_WIN32_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2016 - 2019, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(WIN32) + +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + +CURLcode Curl_win32_init(long flags); +void Curl_win32_cleanup(long init_flags); + +/* Version condition */ +typedef enum { + VERSION_LESS_THAN, + VERSION_LESS_THAN_EQUAL, + VERSION_EQUAL, + VERSION_GREATER_THAN_EQUAL, + VERSION_GREATER_THAN +} VersionCondition; + +/* Platform identifier */ +typedef enum { + PLATFORM_DONT_CARE, + PLATFORM_WINDOWS, + PLATFORM_WINNT +} PlatformIdentifier; + +/* We use our own typedef here since some headers might lack this */ +typedef unsigned int(WINAPI *IF_NAMETOINDEX_FN)(const char *); + +/* This is used instead of if_nametoindex if available on Windows */ +extern IF_NAMETOINDEX_FN Curl_if_nametoindex; + +/* This is used to verify if we are running on a specific windows version */ +bool Curl_verify_windows_version(const unsigned int majorVersion, + const unsigned int minorVersion, + const PlatformIdentifier platform, + const VersionCondition condition); + +/* This is used to dynamically load DLLs */ +HMODULE Curl_load_library(LPCTSTR filename); + +#endif /* WIN32 */ + +#endif /* HEADER_CURL_SYSTEM_WIN32_H */ diff --git a/libcurl/lib/telnet.c b/libcurl/lib/telnet.c new file mode 100644 index 0000000..955255c --- /dev/null +++ b/libcurl/lib/telnet.c @@ -0,0 +1,1699 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_TELNET + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "telnet.h" +#include "connect.h" +#include "progress.h" +#include "system_win32.h" +#include "arpa_telnet.h" +#include "select.h" +#include "strcase.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define SUBBUFSIZE 512 + +#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer +#define CURL_SB_TERM(x) \ + do { \ + x->subend = x->subpointer; \ + CURL_SB_CLEAR(x); \ + } WHILE_FALSE +#define CURL_SB_ACCUM(x,c) \ + do { \ + if(x->subpointer < (x->subbuffer + sizeof(x->subbuffer))) \ + *x->subpointer++ = (c); \ + } WHILE_FALSE + +#define CURL_SB_GET(x) ((*x->subpointer++)&0xff) +#define CURL_SB_LEN(x) (x->subend - x->subpointer) + +/* For posterity: +#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) +#define CURL_SB_EOF(x) (x->subpointer >= x->subend) */ + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define printoption(a,b,c,d) Curl_nop_stmt +#endif + +#ifdef USE_WINSOCK +typedef WSAEVENT (WINAPI *WSOCK2_EVENT)(void); +typedef FARPROC WSOCK2_FUNC; +static CURLcode check_wsock2(struct Curl_easy *data); +#endif + +static +CURLcode telrcv(struct connectdata *, + const unsigned char *inbuf, /* Data received from socket */ + ssize_t count); /* Number of bytes received */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void printoption(struct Curl_easy *data, + const char *direction, + int cmd, int option); +#endif + +static void negotiate(struct connectdata *); +static void send_negotiation(struct connectdata *, int cmd, int option); +static void set_local_option(struct connectdata *conn, + int option, int newstate); +static void set_remote_option(struct connectdata *conn, + int option, int newstate); + +static void printsub(struct Curl_easy *data, + int direction, unsigned char *pointer, + size_t length); +static void suboption(struct connectdata *); +static void sendsuboption(struct connectdata *conn, int option); + +static CURLcode telnet_do(struct connectdata *conn, bool *done); +static CURLcode telnet_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode send_telnet_data(struct connectdata *conn, + char *buffer, ssize_t nread); + +/* For negotiation compliant to RFC 1143 */ +#define CURL_NO 0 +#define CURL_YES 1 +#define CURL_WANTYES 2 +#define CURL_WANTNO 3 + +#define CURL_EMPTY 0 +#define CURL_OPPOSITE 1 + +/* + * Telnet receiver states for fsm + */ +typedef enum +{ + CURL_TS_DATA = 0, + CURL_TS_IAC, + CURL_TS_WILL, + CURL_TS_WONT, + CURL_TS_DO, + CURL_TS_DONT, + CURL_TS_CR, + CURL_TS_SB, /* sub-option collection */ + CURL_TS_SE /* looking for sub-option end */ +} TelnetReceive; + +struct TELNET { + int please_negotiate; + int already_negotiated; + int us[256]; + int usq[256]; + int us_preferred[256]; + int him[256]; + int himq[256]; + int him_preferred[256]; + int subnegotiation[256]; + char subopt_ttype[32]; /* Set with suboption TTYPE */ + char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */ + unsigned short subopt_wsx; /* Set with suboption NAWS */ + unsigned short subopt_wsy; /* Set with suboption NAWS */ + struct curl_slist *telnet_vars; /* Environment variables */ + + /* suboptions */ + unsigned char subbuffer[SUBBUFSIZE]; + unsigned char *subpointer, *subend; /* buffer for sub-options */ + + TelnetReceive telrcv_state; +}; + + +/* + * TELNET protocol handler. + */ + +const struct Curl_handler Curl_handler_telnet = { + "TELNET", /* scheme */ + ZERO_NULL, /* setup_connection */ + telnet_do, /* do_it */ + telnet_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_TELNET, /* defport */ + CURLPROTO_TELNET, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + + +#ifdef USE_WINSOCK +static CURLcode +check_wsock2(struct Curl_easy *data) +{ + int err; + WORD wVersionRequested; + WSADATA wsaData; + + DEBUGASSERT(data); + + /* telnet requires at least WinSock 2.0 so ask for it. */ + wVersionRequested = MAKEWORD(2, 0); + + err = WSAStartup(wVersionRequested, &wsaData); + + /* We must've called this once already, so this call */ + /* should always succeed. But, just in case... */ + if(err != 0) { + failf(data,"WSAStartup failed (%d)",err); + return CURLE_FAILED_INIT; + } + + /* We have to have a WSACleanup call for every successful */ + /* WSAStartup call. */ + WSACleanup(); + + /* Check that our version is supported */ + if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) { + /* Our version isn't supported */ + failf(data, "insufficient winsock version to support " + "telnet"); + return CURLE_FAILED_INIT; + } + + /* Our version is supported */ + return CURLE_OK; +} +#endif + +static +CURLcode init_telnet(struct connectdata *conn) +{ + struct TELNET *tn; + + tn = calloc(1, sizeof(struct TELNET)); + if(!tn) + return CURLE_OUT_OF_MEMORY; + + conn->data->req.protop = tn; /* make us known */ + + tn->telrcv_state = CURL_TS_DATA; + + /* Init suboptions */ + CURL_SB_CLEAR(tn); + + /* Set the options we want by default */ + tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES; + tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES; + + /* To be compliant with previous releases of libcurl + we enable this option by default. This behaviour + can be changed thanks to the "BINARY" option in + CURLOPT_TELNETOPTIONS + */ + tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES; + tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES; + + /* We must allow the server to echo what we sent + but it is not necessary to request the server + to do so (it might forces the server to close + the connection). Hence, we ignore ECHO in the + negotiate function + */ + tn->him_preferred[CURL_TELOPT_ECHO] = CURL_YES; + + /* Set the subnegotiation fields to send information + just after negotiation passed (do/will) + + Default values are (0,0) initialized by calloc. + According to the RFC1013 it is valid: + A value equal to zero is acceptable for the width (or height), + and means that no character width (or height) is being sent. + In this case, the width (or height) that will be assumed by the + Telnet server is operating system specific (it will probably be + based upon the terminal type information that may have been sent + using the TERMINAL TYPE Telnet option). */ + tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES; + return CURLE_OK; +} + +static void negotiate(struct connectdata *conn) +{ + int i; + struct TELNET *tn = (struct TELNET *) conn->data->req.protop; + + for(i = 0; i < CURL_NTELOPTS; i++) { + if(i == CURL_TELOPT_ECHO) + continue; + + if(tn->us_preferred[i] == CURL_YES) + set_local_option(conn, i, CURL_YES); + + if(tn->him_preferred[i] == CURL_YES) + set_remote_option(conn, i, CURL_YES); + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void printoption(struct Curl_easy *data, + const char *direction, int cmd, int option) +{ + if(data->set.verbose) { + if(cmd == CURL_IAC) { + if(CURL_TELCMD_OK(option)) + infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option)); + else + infof(data, "%s IAC %d\n", direction, option); + } + else { + const char *fmt = (cmd == CURL_WILL) ? "WILL" : + (cmd == CURL_WONT) ? "WONT" : + (cmd == CURL_DO) ? "DO" : + (cmd == CURL_DONT) ? "DONT" : 0; + if(fmt) { + const char *opt; + if(CURL_TELOPT_OK(option)) + opt = CURL_TELOPT(option); + else if(option == CURL_TELOPT_EXOPL) + opt = "EXOPL"; + else + opt = NULL; + + if(opt) + infof(data, "%s %s %s\n", direction, fmt, opt); + else + infof(data, "%s %s %d\n", direction, fmt, option); + } + else + infof(data, "%s %d %d\n", direction, cmd, option); + } + } +} +#endif + +static void send_negotiation(struct connectdata *conn, int cmd, int option) +{ + unsigned char buf[3]; + ssize_t bytes_written; + struct Curl_easy *data = conn->data; + + buf[0] = CURL_IAC; + buf[1] = (unsigned char)cmd; + buf[2] = (unsigned char)option; + + bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3); + if(bytes_written < 0) { + int err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + + printoption(conn->data, "SENT", cmd, option); +} + +static +void set_remote_option(struct connectdata *conn, int option, int newstate) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + if(newstate == CURL_YES) { + switch(tn->him[option]) { + case CURL_NO: + tn->him[option] = CURL_WANTYES; + send_negotiation(conn, CURL_DO, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Already negotiating for CURL_YES, queue the request */ + tn->himq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + /* Error: already queued an enable request */ + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Error: already negotiating for enable */ + break; + case CURL_OPPOSITE: + tn->himq[option] = CURL_EMPTY; + break; + } + break; + } + } + else { /* NO */ + switch(tn->him[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->him[option] = CURL_WANTNO; + send_negotiation(conn, CURL_DONT, option); + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Already negotiating for NO */ + break; + case CURL_OPPOSITE: + tn->himq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->himq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + break; + } + break; + } + } +} + +static +void rec_will(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->him[option]) { + case CURL_NO: + if(tn->him_preferred[option] == CURL_YES) { + tn->him[option] = CURL_YES; + send_negotiation(conn, CURL_DO, option); + } + else + send_negotiation(conn, CURL_DONT, option); + + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + /* Error: DONT answered by WILL */ + tn->him[option] = CURL_NO; + break; + case CURL_OPPOSITE: + /* Error: DONT answered by WILL */ + tn->him[option] = CURL_YES; + tn->himq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_YES; + break; + case CURL_OPPOSITE: + tn->him[option] = CURL_WANTNO; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_DONT, option); + break; + } + break; + } +} + +static +void rec_wont(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->him[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->him[option] = CURL_NO; + send_negotiation(conn, CURL_DONT, option); + break; + + case CURL_WANTNO: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_NO; + break; + + case CURL_OPPOSITE: + tn->him[option] = CURL_WANTYES; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_DO, option); + break; + } + break; + + case CURL_WANTYES: + switch(tn->himq[option]) { + case CURL_EMPTY: + tn->him[option] = CURL_NO; + break; + case CURL_OPPOSITE: + tn->him[option] = CURL_NO; + tn->himq[option] = CURL_EMPTY; + break; + } + break; + } +} + +static void +set_local_option(struct connectdata *conn, int option, int newstate) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + if(newstate == CURL_YES) { + switch(tn->us[option]) { + case CURL_NO: + tn->us[option] = CURL_WANTYES; + send_negotiation(conn, CURL_WILL, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Already negotiating for CURL_YES, queue the request */ + tn->usq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + /* Error: already queued an enable request */ + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Error: already negotiating for enable */ + break; + case CURL_OPPOSITE: + tn->usq[option] = CURL_EMPTY; + break; + } + break; + } + } + else { /* NO */ + switch(tn->us[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->us[option] = CURL_WANTNO; + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Already negotiating for NO */ + break; + case CURL_OPPOSITE: + tn->usq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->usq[option] = CURL_OPPOSITE; + break; + case CURL_OPPOSITE: + break; + } + break; + } + } +} + +static +void rec_do(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->us[option]) { + case CURL_NO: + if(tn->us_preferred[option] == CURL_YES) { + tn->us[option] = CURL_YES; + send_negotiation(conn, CURL_WILL, option); + if(tn->subnegotiation[option] == CURL_YES) + /* transmission of data option */ + sendsuboption(conn, option); + } + else if(tn->subnegotiation[option] == CURL_YES) { + /* send information to achieve this option*/ + tn->us[option] = CURL_YES; + send_negotiation(conn, CURL_WILL, option); + sendsuboption(conn, option); + } + else + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Error: DONT answered by WILL */ + tn->us[option] = CURL_NO; + break; + case CURL_OPPOSITE: + /* Error: DONT answered by WILL */ + tn->us[option] = CURL_YES; + tn->usq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_YES; + if(tn->subnegotiation[option] == CURL_YES) { + /* transmission of data option */ + sendsuboption(conn, option); + } + break; + case CURL_OPPOSITE: + tn->us[option] = CURL_WANTNO; + tn->himq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_WONT, option); + break; + } + break; + } +} + +static +void rec_dont(struct connectdata *conn, int option) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + switch(tn->us[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->us[option] = CURL_NO; + send_negotiation(conn, CURL_WONT, option); + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_NO; + break; + + case CURL_OPPOSITE: + tn->us[option] = CURL_WANTYES; + tn->usq[option] = CURL_EMPTY; + send_negotiation(conn, CURL_WILL, option); + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_NO; + break; + case CURL_OPPOSITE: + tn->us[option] = CURL_NO; + tn->usq[option] = CURL_EMPTY; + break; + } + break; + } +} + + +static void printsub(struct Curl_easy *data, + int direction, /* '<' or '>' */ + unsigned char *pointer, /* where suboption data is */ + size_t length) /* length of suboption data */ +{ + if(data->set.verbose) { + unsigned int i = 0; + if(direction) { + infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT"); + if(length >= 3) { + int j; + + i = pointer[length-2]; + j = pointer[length-1]; + + if(i != CURL_IAC || j != CURL_SE) { + infof(data, "(terminated by "); + if(CURL_TELOPT_OK(i)) + infof(data, "%s ", CURL_TELOPT(i)); + else if(CURL_TELCMD_OK(i)) + infof(data, "%s ", CURL_TELCMD(i)); + else + infof(data, "%u ", i); + if(CURL_TELOPT_OK(j)) + infof(data, "%s", CURL_TELOPT(j)); + else if(CURL_TELCMD_OK(j)) + infof(data, "%s", CURL_TELCMD(j)); + else + infof(data, "%d", j); + infof(data, ", not IAC SE!) "); + } + } + length -= 2; + } + if(length < 1) { + infof(data, "(Empty suboption?)"); + return; + } + + if(CURL_TELOPT_OK(pointer[0])) { + switch(pointer[0]) { + case CURL_TELOPT_TTYPE: + case CURL_TELOPT_XDISPLOC: + case CURL_TELOPT_NEW_ENVIRON: + case CURL_TELOPT_NAWS: + infof(data, "%s", CURL_TELOPT(pointer[0])); + break; + default: + infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0])); + break; + } + } + else + infof(data, "%d (unknown)", pointer[i]); + + switch(pointer[0]) { + case CURL_TELOPT_NAWS: + if(length > 4) + infof(data, "Width: %d ; Height: %d", (pointer[1]<<8) | pointer[2], + (pointer[3]<<8) | pointer[4]); + break; + default: + switch(pointer[1]) { + case CURL_TELQUAL_IS: + infof(data, " IS"); + break; + case CURL_TELQUAL_SEND: + infof(data, " SEND"); + break; + case CURL_TELQUAL_INFO: + infof(data, " INFO/REPLY"); + break; + case CURL_TELQUAL_NAME: + infof(data, " NAME"); + break; + } + + switch(pointer[0]) { + case CURL_TELOPT_TTYPE: + case CURL_TELOPT_XDISPLOC: + pointer[length] = 0; + infof(data, " \"%s\"", &pointer[2]); + break; + case CURL_TELOPT_NEW_ENVIRON: + if(pointer[1] == CURL_TELQUAL_IS) { + infof(data, " "); + for(i = 3; i < length; i++) { + switch(pointer[i]) { + case CURL_NEW_ENV_VAR: + infof(data, ", "); + break; + case CURL_NEW_ENV_VALUE: + infof(data, " = "); + break; + default: + infof(data, "%c", pointer[i]); + break; + } + } + } + break; + default: + for(i = 2; i < length; i++) + infof(data, " %.2x", pointer[i]); + break; + } + } + if(direction) + infof(data, "\n"); + } +} + +static CURLcode check_telnet_options(struct connectdata *conn) +{ + struct curl_slist *head; + struct curl_slist *beg; + char option_keyword[128] = ""; + char option_arg[256] = ""; + struct Curl_easy *data = conn->data; + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + CURLcode result = CURLE_OK; + int binary_option; + + /* Add the user name as an environment variable if it + was given on the command line */ + if(conn->bits.user_passwd) { + msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); + beg = curl_slist_append(tn->telnet_vars, option_arg); + if(!beg) { + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + return CURLE_OUT_OF_MEMORY; + } + tn->telnet_vars = beg; + tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; + } + + for(head = data->set.telnet_options; head; head = head->next) { + if(sscanf(head->data, "%127[^= ]%*[ =]%255s", + option_keyword, option_arg) == 2) { + + /* Terminal type */ + if(strcasecompare(option_keyword, "TTYPE")) { + strncpy(tn->subopt_ttype, option_arg, 31); + tn->subopt_ttype[31] = 0; /* String termination */ + tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES; + continue; + } + + /* Display variable */ + if(strcasecompare(option_keyword, "XDISPLOC")) { + strncpy(tn->subopt_xdisploc, option_arg, 127); + tn->subopt_xdisploc[127] = 0; /* String termination */ + tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES; + continue; + } + + /* Environment variable */ + if(strcasecompare(option_keyword, "NEW_ENV")) { + beg = curl_slist_append(tn->telnet_vars, option_arg); + if(!beg) { + result = CURLE_OUT_OF_MEMORY; + break; + } + tn->telnet_vars = beg; + tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; + continue; + } + + /* Window Size */ + if(strcasecompare(option_keyword, "WS")) { + if(sscanf(option_arg, "%hu%*[xX]%hu", + &tn->subopt_wsx, &tn->subopt_wsy) == 2) + tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES; + else { + failf(data, "Syntax error in telnet option: %s", head->data); + result = CURLE_TELNET_OPTION_SYNTAX; + break; + } + continue; + } + + /* To take care or not of the 8th bit in data exchange */ + if(strcasecompare(option_keyword, "BINARY")) { + binary_option = atoi(option_arg); + if(binary_option != 1) { + tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO; + tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO; + } + continue; + } + + failf(data, "Unknown telnet option %s", head->data); + result = CURLE_UNKNOWN_OPTION; + break; + } + failf(data, "Syntax error in telnet option: %s", head->data); + result = CURLE_TELNET_OPTION_SYNTAX; + break; + } + + if(result) { + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + } + + return result; +} + +/* + * suboption() + * + * Look at the sub-option buffer, and try to be helpful to the other + * side. + */ + +static void suboption(struct connectdata *conn) +{ + struct curl_slist *v; + unsigned char temp[2048]; + ssize_t bytes_written; + size_t len; + int err; + char varname[128] = ""; + char varval[128] = ""; + struct Curl_easy *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + + printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2); + switch(CURL_SB_GET(tn)) { + case CURL_TELOPT_TTYPE: + len = strlen(tn->subopt_ttype) + 4 + 2; + msnprintf((char *)temp, sizeof(temp), + "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE, + CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE); + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + case CURL_TELOPT_XDISPLOC: + len = strlen(tn->subopt_xdisploc) + 4 + 2; + msnprintf((char *)temp, sizeof(temp), + "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC, + CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE); + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + case CURL_TELOPT_NEW_ENVIRON: + msnprintf((char *)temp, sizeof(temp), + "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON, + CURL_TELQUAL_IS); + len = 4; + + for(v = tn->telnet_vars; v; v = v->next) { + size_t tmplen = (strlen(v->data) + 1); + /* Add the variable only if it fits */ + if(len + tmplen < (int)sizeof(temp)-6) { + if(sscanf(v->data, "%127[^,],%127s", varname, varval)) { + msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%s%c%s", CURL_NEW_ENV_VAR, varname, + CURL_NEW_ENV_VALUE, varval); + len += tmplen; + } + } + } + msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%c", CURL_IAC, CURL_SE); + len += 2; + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data,"Sending data failed (%d)",err); + } + printsub(data, '>', &temp[2], len-2); + break; + } + return; +} + + +/* + * sendsuboption() + * + * Send suboption information to the server side. + */ + +static void sendsuboption(struct connectdata *conn, int option) +{ + ssize_t bytes_written; + int err; + unsigned short x, y; + unsigned char *uc1, *uc2; + + struct Curl_easy *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + + switch(option) { + case CURL_TELOPT_NAWS: + /* We prepare data to be sent */ + CURL_SB_CLEAR(tn); + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SB); + CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS); + /* We must deal either with little or big endian processors */ + /* Window size must be sent according to the 'network order' */ + x = htons(tn->subopt_wsx); + y = htons(tn->subopt_wsy); + uc1 = (unsigned char *)&x; + uc2 = (unsigned char *)&y; + CURL_SB_ACCUM(tn, uc1[0]); + CURL_SB_ACCUM(tn, uc1[1]); + CURL_SB_ACCUM(tn, uc2[0]); + CURL_SB_ACCUM(tn, uc2[1]); + + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SE); + CURL_SB_TERM(tn); + /* data suboption is now ready */ + + printsub(data, '>', (unsigned char *)tn->subbuffer + 2, + CURL_SB_LEN(tn)-2); + + /* we send the header of the suboption... */ + bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + /* ... then the window size with the send_telnet_data() function + to deal with 0xFF cases ... */ + send_telnet_data(conn, (char *)tn->subbuffer + 3, 4); + /* ... and the footer */ + bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + break; + } +} + + +static +CURLcode telrcv(struct connectdata *conn, + const unsigned char *inbuf, /* Data received from socket */ + ssize_t count) /* Number of bytes received */ +{ + unsigned char c; + CURLcode result; + int in = 0; + int startwrite = -1; + struct Curl_easy *data = conn->data; + struct TELNET *tn = (struct TELNET *)data->req.protop; + +#define startskipping() \ + if(startwrite >= 0) { \ + result = Curl_client_write(conn, \ + CLIENTWRITE_BODY, \ + (char *)&inbuf[startwrite], \ + in-startwrite); \ + if(result) \ + return result; \ + } \ + startwrite = -1 + +#define writebyte() \ + if(startwrite < 0) \ + startwrite = in + +#define bufferflush() startskipping() + + while(count--) { + c = inbuf[in]; + + switch(tn->telrcv_state) { + case CURL_TS_CR: + tn->telrcv_state = CURL_TS_DATA; + if(c == '\0') { + startskipping(); + break; /* Ignore \0 after CR */ + } + writebyte(); + break; + + case CURL_TS_DATA: + if(c == CURL_IAC) { + tn->telrcv_state = CURL_TS_IAC; + startskipping(); + break; + } + else if(c == '\r') + tn->telrcv_state = CURL_TS_CR; + writebyte(); + break; + + case CURL_TS_IAC: + process_iac: + DEBUGASSERT(startwrite < 0); + switch(c) { + case CURL_WILL: + tn->telrcv_state = CURL_TS_WILL; + break; + case CURL_WONT: + tn->telrcv_state = CURL_TS_WONT; + break; + case CURL_DO: + tn->telrcv_state = CURL_TS_DO; + break; + case CURL_DONT: + tn->telrcv_state = CURL_TS_DONT; + break; + case CURL_SB: + CURL_SB_CLEAR(tn); + tn->telrcv_state = CURL_TS_SB; + break; + case CURL_IAC: + tn->telrcv_state = CURL_TS_DATA; + writebyte(); + break; + case CURL_DM: + case CURL_NOP: + case CURL_GA: + default: + tn->telrcv_state = CURL_TS_DATA; + printoption(data, "RCVD", CURL_IAC, c); + break; + } + break; + + case CURL_TS_WILL: + printoption(data, "RCVD", CURL_WILL, c); + tn->please_negotiate = 1; + rec_will(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_WONT: + printoption(data, "RCVD", CURL_WONT, c); + tn->please_negotiate = 1; + rec_wont(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_DO: + printoption(data, "RCVD", CURL_DO, c); + tn->please_negotiate = 1; + rec_do(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_DONT: + printoption(data, "RCVD", CURL_DONT, c); + tn->please_negotiate = 1; + rec_dont(conn, c); + tn->telrcv_state = CURL_TS_DATA; + break; + + case CURL_TS_SB: + if(c == CURL_IAC) + tn->telrcv_state = CURL_TS_SE; + else + CURL_SB_ACCUM(tn, c); + break; + + case CURL_TS_SE: + if(c != CURL_SE) { + if(c != CURL_IAC) { + /* + * This is an error. We only expect to get "IAC IAC" or "IAC SE". + * Several things may have happened. An IAC was not doubled, the + * IAC SE was left off, or another option got inserted into the + * suboption are all possibilities. If we assume that the IAC was + * not doubled, and really the IAC SE was left off, we could get + * into an infinite loop here. So, instead, we terminate the + * suboption, and process the partial suboption if we can. + */ + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, c); + tn->subpointer -= 2; + CURL_SB_TERM(tn); + + printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); + suboption(conn); /* handle sub-option */ + tn->telrcv_state = CURL_TS_IAC; + goto process_iac; + } + CURL_SB_ACCUM(tn, c); + tn->telrcv_state = CURL_TS_SB; + } + else { + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SE); + tn->subpointer -= 2; + CURL_SB_TERM(tn); + suboption(conn); /* handle sub-option */ + tn->telrcv_state = CURL_TS_DATA; + } + break; + } + ++in; + } + bufferflush(); + return CURLE_OK; +} + +/* Escape and send a telnet data block */ +static CURLcode send_telnet_data(struct connectdata *conn, + char *buffer, ssize_t nread) +{ + ssize_t escapes, i, outlen; + unsigned char *outbuf = NULL; + CURLcode result = CURLE_OK; + ssize_t bytes_written, total_written; + + /* Determine size of new buffer after escaping */ + escapes = 0; + for(i = 0; i < nread; i++) + if((unsigned char)buffer[i] == CURL_IAC) + escapes++; + outlen = nread + escapes; + + if(outlen == nread) + outbuf = (unsigned char *)buffer; + else { + ssize_t j; + outbuf = malloc(nread + escapes + 1); + if(!outbuf) + return CURLE_OUT_OF_MEMORY; + + j = 0; + for(i = 0; i < nread; i++) { + outbuf[j++] = buffer[i]; + if((unsigned char)buffer[i] == CURL_IAC) + outbuf[j++] = CURL_IAC; + } + outbuf[j] = '\0'; + } + + total_written = 0; + while(!result && total_written < outlen) { + /* Make sure socket is writable to avoid EWOULDBLOCK condition */ + struct pollfd pfd[1]; + pfd[0].fd = conn->sock[FIRSTSOCKET]; + pfd[0].events = POLLOUT; + switch(Curl_poll(pfd, 1, -1)) { + case -1: /* error, abort writing */ + case 0: /* timeout (will never happen) */ + result = CURLE_SEND_ERROR; + break; + default: /* write! */ + bytes_written = 0; + result = Curl_write(conn, conn->sock[FIRSTSOCKET], + outbuf + total_written, + outlen - total_written, + &bytes_written); + total_written += bytes_written; + break; + } + } + + /* Free malloc copy if escaped */ + if(outbuf != (unsigned char *)buffer) + free(outbuf); + + return result; +} + +static CURLcode telnet_done(struct connectdata *conn, + CURLcode status, bool premature) +{ + struct TELNET *tn = (struct TELNET *)conn->data->req.protop; + (void)status; /* unused */ + (void)premature; /* not used */ + + if(!tn) + return CURLE_OK; + + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; + + Curl_safefree(conn->data->req.protop); + + return CURLE_OK; +} + +static CURLcode telnet_do(struct connectdata *conn, bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; +#ifdef USE_WINSOCK + HMODULE wsock2; + WSOCK2_FUNC close_event_func; + WSOCK2_EVENT create_event_func; + WSOCK2_FUNC event_select_func; + WSOCK2_FUNC enum_netevents_func; + WSAEVENT event_handle; + WSANETWORKEVENTS events; + HANDLE stdin_handle; + HANDLE objs[2]; + DWORD obj_count; + DWORD wait_timeout; + DWORD readfile_read; + int err; +#else + int interval_ms; + struct pollfd pfd[2]; + int poll_cnt; + curl_off_t total_dl = 0; + curl_off_t total_ul = 0; +#endif + ssize_t nread; + struct curltime now; + bool keepon = TRUE; + char *buf = data->state.buffer; + struct TELNET *tn; + + *done = TRUE; /* unconditionally */ + + result = init_telnet(conn); + if(result) + return result; + + tn = (struct TELNET *)data->req.protop; + + result = check_telnet_options(conn); + if(result) + return result; + +#ifdef USE_WINSOCK + /* + ** This functionality only works with WinSock >= 2.0. So, + ** make sure we have it. + */ + result = check_wsock2(data); + if(result) + return result; + + /* OK, so we have WinSock 2.0. We need to dynamically */ + /* load ws2_32.dll and get the function pointers we need. */ + wsock2 = Curl_load_library(TEXT("WS2_32.DLL")); + if(wsock2 == NULL) { + failf(data, "failed to load WS2_32.DLL (%u)", GetLastError()); + return CURLE_FAILED_INIT; + } + + /* Grab a pointer to WSACreateEvent */ + create_event_func = + CURLX_FUNCTION_CAST(WSOCK2_EVENT, + (GetProcAddress(wsock2, "WSACreateEvent"))); + if(create_event_func == NULL) { + failf(data, "failed to find WSACreateEvent function (%u)", GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSACloseEvent */ + close_event_func = GetProcAddress(wsock2, "WSACloseEvent"); + if(close_event_func == NULL) { + failf(data, "failed to find WSACloseEvent function (%u)", GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSAEventSelect */ + event_select_func = GetProcAddress(wsock2, "WSAEventSelect"); + if(event_select_func == NULL) { + failf(data, "failed to find WSAEventSelect function (%u)", GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* And WSAEnumNetworkEvents */ + enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents"); + if(enum_netevents_func == NULL) { + failf(data, "failed to find WSAEnumNetworkEvents function (%u)", + GetLastError()); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* We want to wait for both stdin and the socket. Since + ** the select() function in winsock only works on sockets + ** we have to use the WaitForMultipleObjects() call. + */ + + /* First, create a sockets event object */ + event_handle = (WSAEVENT)create_event_func(); + if(event_handle == WSA_INVALID_EVENT) { + failf(data, "WSACreateEvent failed (%d)", SOCKERRNO); + FreeLibrary(wsock2); + return CURLE_FAILED_INIT; + } + + /* Tell winsock what events we want to listen to */ + if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == + SOCKET_ERROR) { + close_event_func(event_handle); + FreeLibrary(wsock2); + return CURLE_OK; + } + + /* The get the Windows file handle for stdin */ + stdin_handle = GetStdHandle(STD_INPUT_HANDLE); + + /* Create the list of objects to wait for */ + objs[0] = event_handle; + objs[1] = stdin_handle; + + /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, + else use the old WaitForMultipleObjects() way */ + if(GetFileType(stdin_handle) == FILE_TYPE_PIPE || + data->set.is_fread_set) { + /* Don't wait for stdin_handle, just wait for event_handle */ + obj_count = 1; + /* Check stdin_handle per 100 milliseconds */ + wait_timeout = 100; + } + else { + obj_count = 2; + wait_timeout = 1000; + } + + /* Keep on listening and act on events */ + while(keepon) { + const DWORD buf_size = (DWORD)data->set.buffer_size; + DWORD waitret = WaitForMultipleObjects(obj_count, objs, + FALSE, wait_timeout); + switch(waitret) { + case WAIT_TIMEOUT: + { + for(;;) { + if(data->set.is_fread_set) { + size_t n; + /* read from user-supplied method */ + n = data->state.fread_func(buf, 1, buf_size, data->state.in); + if(n == CURL_READFUNC_ABORT) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + if(n == CURL_READFUNC_PAUSE) + break; + + if(n == 0) /* no bytes */ + break; + + /* fall through with number of bytes read */ + readfile_read = (DWORD)n; + } + else { + /* read from stdin */ + if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + if(!readfile_read) + break; + + if(!ReadFile(stdin_handle, buf, buf_size, + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + } + + result = send_telnet_data(conn, buf, readfile_read); + if(result) { + keepon = FALSE; + break; + } + } + } + break; + + case WAIT_OBJECT_0 + 1: + { + if(!ReadFile(stdin_handle, buf, buf_size, + &readfile_read, NULL)) { + keepon = FALSE; + result = CURLE_READ_ERROR; + break; + } + + result = send_telnet_data(conn, buf, readfile_read); + if(result) { + keepon = FALSE; + break; + } + } + break; + + case WAIT_OBJECT_0: + + events.lNetworkEvents = 0; + if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { + err = SOCKERRNO; + if(err != EINPROGRESS) { + infof(data, "WSAEnumNetworkEvents failed (%d)", err); + keepon = FALSE; + result = CURLE_READ_ERROR; + } + break; + } + if(events.lNetworkEvents & FD_READ) { + /* read data from network */ + result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); + /* read would've blocked. Loop again */ + if(result == CURLE_AGAIN) + break; + /* returned not-zero, this an error */ + else if(result) { + keepon = FALSE; + break; + } + /* returned zero but actually received 0 or less here, + the server closed the connection and we bail out */ + else if(nread <= 0) { + keepon = FALSE; + break; + } + + result = telrcv(conn, (unsigned char *) buf, nread); + if(result) { + keepon = FALSE; + break; + } + + /* Negotiate if the peer has started negotiating, + otherwise don't. We don't want to speak telnet with + non-telnet servers, like POP or SMTP. */ + if(tn->please_negotiate && !tn->already_negotiated) { + negotiate(conn); + tn->already_negotiated = 1; + } + } + if(events.lNetworkEvents & FD_CLOSE) { + keepon = FALSE; + } + break; + + } + + if(data->set.timeout) { + now = Curl_now(); + if(Curl_timediff(now, conn->created) >= data->set.timeout) { + failf(data, "Time-out"); + result = CURLE_OPERATION_TIMEDOUT; + keepon = FALSE; + } + } + } + + /* We called WSACreateEvent, so call WSACloseEvent */ + if(!close_event_func(event_handle)) { + infof(data, "WSACloseEvent failed (%d)", SOCKERRNO); + } + + /* "Forget" pointers into the library we're about to free */ + create_event_func = NULL; + close_event_func = NULL; + event_select_func = NULL; + enum_netevents_func = NULL; + + /* We called LoadLibrary, so call FreeLibrary */ + if(!FreeLibrary(wsock2)) + infof(data, "FreeLibrary(wsock2) failed (%u)", GetLastError()); +#else + pfd[0].fd = sockfd; + pfd[0].events = POLLIN; + + if(data->set.is_fread_set) { + poll_cnt = 1; + interval_ms = 100; /* poll user-supplied read function */ + } + else { + /* really using fread, so infile is a FILE* */ + pfd[1].fd = fileno((FILE *)data->state.in); + pfd[1].events = POLLIN; + poll_cnt = 2; + interval_ms = 1 * 1000; + } + + while(keepon) { + switch(Curl_poll(pfd, poll_cnt, interval_ms)) { + case -1: /* error, stop reading */ + keepon = FALSE; + continue; + case 0: /* timeout */ + pfd[0].revents = 0; + pfd[1].revents = 0; + /* FALLTHROUGH */ + default: /* read! */ + if(pfd[0].revents & POLLIN) { + /* read data from network */ + result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); + /* read would've blocked. Loop again */ + if(result == CURLE_AGAIN) + break; + /* returned not-zero, this an error */ + if(result) { + keepon = FALSE; + break; + } + /* returned zero but actually received 0 or less here, + the server closed the connection and we bail out */ + else if(nread <= 0) { + keepon = FALSE; + break; + } + + total_dl += nread; + Curl_pgrsSetDownloadCounter(data, total_dl); + result = telrcv(conn, (unsigned char *)buf, nread); + if(result) { + keepon = FALSE; + break; + } + + /* Negotiate if the peer has started negotiating, + otherwise don't. We don't want to speak telnet with + non-telnet servers, like POP or SMTP. */ + if(tn->please_negotiate && !tn->already_negotiated) { + negotiate(conn); + tn->already_negotiated = 1; + } + } + + nread = 0; + if(poll_cnt == 2) { + if(pfd[1].revents & POLLIN) { /* read from in file */ + nread = read(pfd[1].fd, buf, data->set.buffer_size); + } + } + else { + /* read from user-supplied method */ + nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size, + data->state.in); + if(nread == CURL_READFUNC_ABORT) { + keepon = FALSE; + break; + } + if(nread == CURL_READFUNC_PAUSE) + break; + } + + if(nread > 0) { + result = send_telnet_data(conn, buf, nread); + if(result) { + keepon = FALSE; + break; + } + total_ul += nread; + Curl_pgrsSetUploadCounter(data, total_ul); + } + else if(nread < 0) + keepon = FALSE; + + break; + } /* poll switch statement */ + + if(data->set.timeout) { + now = Curl_now(); + if(Curl_timediff(now, conn->created) >= data->set.timeout) { + failf(data, "Time-out"); + result = CURLE_OPERATION_TIMEDOUT; + keepon = FALSE; + } + } + + if(Curl_pgrsUpdate(conn)) { + result = CURLE_ABORTED_BY_CALLBACK; + break; + } + } +#endif + /* mark this as "no further transfer wanted" */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + + return result; +} +#endif diff --git a/libcurl/lib/telnet.h b/libcurl/lib/telnet.h new file mode 100644 index 0000000..668a78a --- /dev/null +++ b/libcurl/lib/telnet.h @@ -0,0 +1,28 @@ +#ifndef HEADER_CURL_TELNET_H +#define HEADER_CURL_TELNET_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET +extern const struct Curl_handler Curl_handler_telnet; +#endif + +#endif /* HEADER_CURL_TELNET_H */ diff --git a/libcurl/lib/tftp.c b/libcurl/lib/tftp.c new file mode 100644 index 0000000..289cda2 --- /dev/null +++ b/libcurl/lib/tftp.c @@ -0,0 +1,1410 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_TFTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "urldata.h" +#include +#include "transfer.h" +#include "sendf.h" +#include "tftp.h" +#include "progress.h" +#include "connect.h" +#include "strerror.h" +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "multiif.h" +#include "url.h" +#include "strcase.h" +#include "speedcheck.h" +#include "select.h" +#include "escape.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* RFC2348 allows the block size to be negotiated */ +#define TFTP_BLKSIZE_DEFAULT 512 +#define TFTP_BLKSIZE_MIN 8 +#define TFTP_BLKSIZE_MAX 65464 +#define TFTP_OPTION_BLKSIZE "blksize" + +/* from RFC2349: */ +#define TFTP_OPTION_TSIZE "tsize" +#define TFTP_OPTION_INTERVAL "timeout" + +typedef enum { + TFTP_MODE_NETASCII = 0, + TFTP_MODE_OCTET +} tftp_mode_t; + +typedef enum { + TFTP_STATE_START = 0, + TFTP_STATE_RX, + TFTP_STATE_TX, + TFTP_STATE_FIN +} tftp_state_t; + +typedef enum { + TFTP_EVENT_NONE = -1, + TFTP_EVENT_INIT = 0, + TFTP_EVENT_RRQ = 1, + TFTP_EVENT_WRQ = 2, + TFTP_EVENT_DATA = 3, + TFTP_EVENT_ACK = 4, + TFTP_EVENT_ERROR = 5, + TFTP_EVENT_OACK = 6, + TFTP_EVENT_TIMEOUT +} tftp_event_t; + +typedef enum { + TFTP_ERR_UNDEF = 0, + TFTP_ERR_NOTFOUND, + TFTP_ERR_PERM, + TFTP_ERR_DISKFULL, + TFTP_ERR_ILLEGAL, + TFTP_ERR_UNKNOWNID, + TFTP_ERR_EXISTS, + TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */ + + /* The remaining error codes are internal to curl */ + TFTP_ERR_NONE = -100, + TFTP_ERR_TIMEOUT, + TFTP_ERR_NORESPONSE +} tftp_error_t; + +typedef struct tftp_packet { + unsigned char *data; +} tftp_packet_t; + +typedef struct tftp_state_data { + tftp_state_t state; + tftp_mode_t mode; + tftp_error_t error; + tftp_event_t event; + struct connectdata *conn; + curl_socket_t sockfd; + int retries; + int retry_time; + int retry_max; + time_t start_time; + time_t max_time; + time_t rx_time; + unsigned short block; + struct Curl_sockaddr_storage local_addr; + struct Curl_sockaddr_storage remote_addr; + curl_socklen_t remote_addrlen; + int rbytes; + int sbytes; + int blksize; + int requested_blksize; + tftp_packet_t rpacket; + tftp_packet_t spacket; +} tftp_state_data_t; + + +/* Forward declarations */ +static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event); +static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event); +static CURLcode tftp_connect(struct connectdata *conn, bool *done); +static CURLcode tftp_disconnect(struct connectdata *conn, + bool dead_connection); +static CURLcode tftp_do(struct connectdata *conn, bool *done); +static CURLcode tftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode tftp_setup_connection(struct connectdata * conn); +static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done); +static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done); +static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode tftp_translate_code(tftp_error_t error); + + +/* + * TFTP protocol handler. + */ + +const struct Curl_handler Curl_handler_tftp = { + "TFTP", /* scheme */ + tftp_setup_connection, /* setup_connection */ + tftp_do, /* do_it */ + tftp_done, /* done */ + ZERO_NULL, /* do_more */ + tftp_connect, /* connect_it */ + tftp_multi_statemach, /* connecting */ + tftp_doing, /* doing */ + tftp_getsock, /* proto_getsock */ + tftp_getsock, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + tftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + PORT_TFTP, /* defport */ + CURLPROTO_TFTP, /* protocol */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + +/********************************************************** + * + * tftp_set_timeouts - + * + * Set timeouts based on state machine state. + * Use user provided connect timeouts until DATA or ACK + * packet is received, then use user-provided transfer timeouts + * + * + **********************************************************/ +static CURLcode tftp_set_timeouts(tftp_state_data_t *state) +{ + time_t maxtime, timeout; + timediff_t timeout_ms; + bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; + + time(&state->start_time); + + /* Compute drop-dead time */ + timeout_ms = Curl_timeleft(state->conn->data, NULL, start); + + if(timeout_ms < 0) { + /* time-out, bail out, go home */ + failf(state->conn->data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + + if(start) { + + maxtime = (time_t)(timeout_ms + 500) / 1000; + state->max_time = state->start_time + maxtime; + + /* Set per-block timeout to total */ + timeout = maxtime; + + /* Average restart after 5 seconds */ + state->retry_max = (int)timeout/5; + + if(state->retry_max < 1) + /* avoid division by zero below */ + state->retry_max = 1; + + /* Compute the re-start interval to suit the timeout */ + state->retry_time = (int)timeout/state->retry_max; + if(state->retry_time<1) + state->retry_time = 1; + + } + else { + if(timeout_ms > 0) + maxtime = (time_t)(timeout_ms + 500) / 1000; + else + maxtime = 3600; + + state->max_time = state->start_time + maxtime; + + /* Set per-block timeout to total */ + timeout = maxtime; + + /* Average reposting an ACK after 5 seconds */ + state->retry_max = (int)timeout/5; + } + /* But bound the total number */ + if(state->retry_max<3) + state->retry_max = 3; + + if(state->retry_max>50) + state->retry_max = 50; + + /* Compute the re-ACK interval to suit the timeout */ + state->retry_time = (int)(timeout/state->retry_max); + if(state->retry_time<1) + state->retry_time = 1; + + infof(state->conn->data, + "set timeouts for state %d; Total %ld, retry %d maxtry %d\n", + (int)state->state, (long)(state->max_time-state->start_time), + state->retry_time, state->retry_max); + + /* init RX time */ + time(&state->rx_time); + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_set_send_first + * + * Event handler for the START state + * + **********************************************************/ + +static void setpacketevent(tftp_packet_t *packet, unsigned short num) +{ + packet->data[0] = (unsigned char)(num >> 8); + packet->data[1] = (unsigned char)(num & 0xff); +} + + +static void setpacketblock(tftp_packet_t *packet, unsigned short num) +{ + packet->data[2] = (unsigned char)(num >> 8); + packet->data[3] = (unsigned char)(num & 0xff); +} + +static unsigned short getrpacketevent(const tftp_packet_t *packet) +{ + return (unsigned short)((packet->data[0] << 8) | packet->data[1]); +} + +static unsigned short getrpacketblock(const tftp_packet_t *packet) +{ + return (unsigned short)((packet->data[2] << 8) | packet->data[3]); +} + +static size_t Curl_strnlen(const char *string, size_t maxlen) +{ + const char *end = memchr(string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} + +static const char *tftp_option_get(const char *buf, size_t len, + const char **option, const char **value) +{ + size_t loc; + + loc = Curl_strnlen(buf, len); + loc++; /* NULL term */ + + if(loc >= len) + return NULL; + *option = buf; + + loc += Curl_strnlen(buf + loc, len-loc); + loc++; /* NULL term */ + + if(loc > len) + return NULL; + *value = &buf[strlen(*option) + 1]; + + return &buf[loc]; +} + +static CURLcode tftp_parse_option_ack(tftp_state_data_t *state, + const char *ptr, int len) +{ + const char *tmp = ptr; + struct Curl_easy *data = state->conn->data; + + /* if OACK doesn't contain blksize option, the default (512) must be used */ + state->blksize = TFTP_BLKSIZE_DEFAULT; + + while(tmp < ptr + len) { + const char *option, *value; + + tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); + if(tmp == NULL) { + failf(data, "Malformed ACK packet, rejecting"); + return CURLE_TFTP_ILLEGAL; + } + + infof(data, "got option=(%s) value=(%s)\n", option, value); + + if(checkprefix(option, TFTP_OPTION_BLKSIZE)) { + long blksize; + + blksize = strtol(value, NULL, 10); + + if(!blksize) { + failf(data, "invalid blocksize value in OACK packet"); + return CURLE_TFTP_ILLEGAL; + } + if(blksize > TFTP_BLKSIZE_MAX) { + failf(data, "%s (%d)", "blksize is larger than max supported", + TFTP_BLKSIZE_MAX); + return CURLE_TFTP_ILLEGAL; + } + else if(blksize < TFTP_BLKSIZE_MIN) { + failf(data, "%s (%d)", "blksize is smaller than min supported", + TFTP_BLKSIZE_MIN); + return CURLE_TFTP_ILLEGAL; + } + else if(blksize > state->requested_blksize) { + /* could realloc pkt buffers here, but the spec doesn't call out + * support for the server requesting a bigger blksize than the client + * requests */ + failf(data, "%s (%ld)", + "server requested blksize larger than allocated", blksize); + return CURLE_TFTP_ILLEGAL; + } + + state->blksize = (int)blksize; + infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK", + state->blksize, "requested", state->requested_blksize); + } + else if(checkprefix(option, TFTP_OPTION_TSIZE)) { + long tsize = 0; + + tsize = strtol(value, NULL, 10); + infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize); + + /* tsize should be ignored on upload: Who cares about the size of the + remote file? */ + if(!data->set.upload) { + if(!tsize) { + failf(data, "invalid tsize -:%s:- value in OACK packet", value); + return CURLE_TFTP_ILLEGAL; + } + Curl_pgrsSetDownloadSize(data, tsize); + } + } + } + + return CURLE_OK; +} + +static size_t tftp_option_add(tftp_state_data_t *state, size_t csize, + char *buf, const char *option) +{ + if(( strlen(option) + csize + 1) > (size_t)state->blksize) + return 0; + strcpy(buf, option); + return strlen(option) + 1; +} + +static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + struct Curl_easy *data = state->conn->data; + + infof(data, "%s\n", "Connected for transmit"); +#endif + state->state = TFTP_STATE_TX; + result = tftp_set_timeouts(state); + if(result) + return result; + return tftp_tx(state, event); +} + +static CURLcode tftp_connect_for_rx(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + struct Curl_easy *data = state->conn->data; + + infof(data, "%s\n", "Connected for receive"); +#endif + state->state = TFTP_STATE_RX; + result = tftp_set_timeouts(state); + if(result) + return result; + return tftp_rx(state, event); +} + +static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) +{ + size_t sbytes; + ssize_t senddata; + const char *mode = "octet"; + char *filename; + struct Curl_easy *data = state->conn->data; + CURLcode result = CURLE_OK; + + /* Set ascii mode if -B flag was used */ + if(data->set.prefer_ascii) + mode = "netascii"; + + switch(event) { + + case TFTP_EVENT_INIT: /* Send the first packet out */ + case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */ + /* Increment the retry counter, quit if over the limit */ + state->retries++; + if(state->retries>state->retry_max) { + state->error = TFTP_ERR_NORESPONSE; + state->state = TFTP_STATE_FIN; + return result; + } + + if(data->set.upload) { + /* If we are uploading, send an WRQ */ + setpacketevent(&state->spacket, TFTP_EVENT_WRQ); + state->conn->data->req.upload_fromhere = + (char *)state->spacket.data + 4; + if(data->state.infilesize != -1) + Curl_pgrsSetUploadSize(data, data->state.infilesize); + } + else { + /* If we are downloading, send an RRQ */ + setpacketevent(&state->spacket, TFTP_EVENT_RRQ); + } + /* As RFC3617 describes the separator slash is not actually part of the + file name so we skip the always-present first letter of the path + string. */ + result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0, + &filename, NULL, FALSE); + if(result) + return result; + + if(strlen(filename) > (state->blksize - strlen(mode) - 4)) { + failf(data, "TFTP file name too long\n"); + free(filename); + return CURLE_TFTP_ILLEGAL; /* too long file name field */ + } + + msnprintf((char *)state->spacket.data + 2, + state->blksize, + "%s%c%s%c", filename, '\0', mode, '\0'); + sbytes = 4 + strlen(filename) + strlen(mode); + + /* optional addition of TFTP options */ + if(!data->set.tftp_no_options) { + char buf[64]; + /* add tsize option */ + if(data->set.upload && (data->state.infilesize != -1)) + msnprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, + data->state.infilesize); + else + strcpy(buf, "0"); /* the destination is large enough */ + + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, + TFTP_OPTION_TSIZE); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, buf); + /* add blksize option */ + msnprintf(buf, sizeof(buf), "%d", state->requested_blksize); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, + TFTP_OPTION_BLKSIZE); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, buf); + + /* add timeout option */ + msnprintf(buf, sizeof(buf), "%d", state->retry_time); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, + TFTP_OPTION_INTERVAL); + sbytes += tftp_option_add(state, sbytes, + (char *)state->spacket.data + sbytes, buf); + } + + /* the typecase for the 3rd argument is mostly for systems that do + not have a size_t argument, like older unixes that want an 'int' */ + senddata = sendto(state->sockfd, (void *)state->spacket.data, + (SEND_TYPE_ARG3)sbytes, 0, + state->conn->ip_addr->ai_addr, + state->conn->ip_addr->ai_addrlen); + if(senddata != (ssize_t)sbytes) { + char buffer[STRERROR_LEN]; + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + } + free(filename); + break; + + case TFTP_EVENT_OACK: + if(data->set.upload) { + result = tftp_connect_for_tx(state, event); + } + else { + result = tftp_connect_for_rx(state, event); + } + break; + + case TFTP_EVENT_ACK: /* Connected for transmit */ + result = tftp_connect_for_tx(state, event); + break; + + case TFTP_EVENT_DATA: /* Connected for receive */ + result = tftp_connect_for_rx(state, event); + break; + + case TFTP_EVENT_ERROR: + state->state = TFTP_STATE_FIN; + break; + + default: + failf(state->conn->data, "tftp_send_first: internal error"); + break; + } + + return result; +} + +/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit + boundary */ +#define NEXT_BLOCKNUM(x) (((x) + 1)&0xffff) + +/********************************************************** + * + * tftp_rx + * + * Event handler for the RX state + * + **********************************************************/ +static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) +{ + ssize_t sbytes; + int rblock; + struct Curl_easy *data = state->conn->data; + char buffer[STRERROR_LEN]; + + switch(event) { + + case TFTP_EVENT_DATA: + /* Is this the block we expect? */ + rblock = getrpacketblock(&state->rpacket); + if(NEXT_BLOCKNUM(state->block) == rblock) { + /* This is the expected block. Reset counters and ACK it. */ + state->retries = 0; + } + else if(state->block == rblock) { + /* This is the last recently received block again. Log it and ACK it + again. */ + infof(data, "Received last DATA packet block %d again.\n", rblock); + } + else { + /* totally unexpected, just log it */ + infof(data, + "Received unexpected DATA packet block %d, expecting block %d\n", + rblock, NEXT_BLOCKNUM(state->block)); + break; + } + + /* ACK this block. */ + state->block = (unsigned short)rblock; + setpacketevent(&state->spacket, TFTP_EVENT_ACK); + setpacketblock(&state->spacket, state->block); + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes < 0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + + /* Check if completed (That is, a less than full packet is received) */ + if(state->rbytes < (ssize_t)state->blksize + 4) { + state->state = TFTP_STATE_FIN; + } + else { + state->state = TFTP_STATE_RX; + } + time(&state->rx_time); + break; + + case TFTP_EVENT_OACK: + /* ACK option acknowledgement so we can move on to data */ + state->block = 0; + state->retries = 0; + setpacketevent(&state->spacket, TFTP_EVENT_ACK); + setpacketblock(&state->spacket, state->block); + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes < 0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + + /* we're ready to RX data */ + state->state = TFTP_STATE_RX; + time(&state->rx_time); + break; + + case TFTP_EVENT_TIMEOUT: + /* Increment the retry count and fail if over the limit */ + state->retries++; + infof(data, + "Timeout waiting for block %d ACK. Retries = %d\n", + NEXT_BLOCKNUM(state->block), state->retries); + if(state->retries > state->retry_max) { + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + } + else { + /* Resend the previous ACK */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + if(sbytes<0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + } + break; + + case TFTP_EVENT_ERROR: + setpacketevent(&state->spacket, TFTP_EVENT_ERROR); + setpacketblock(&state->spacket, state->block); + (void)sendto(state->sockfd, (void *)state->spacket.data, + 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* don't bother with the return code, but if the socket is still up we + * should be a good TFTP client and let the server know we're done */ + state->state = TFTP_STATE_FIN; + break; + + default: + failf(data, "%s", "tftp_rx: internal error"); + return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for + this */ + } + return CURLE_OK; +} + +/********************************************************** + * + * tftp_tx + * + * Event handler for the TX state + * + **********************************************************/ +static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) +{ + struct Curl_easy *data = state->conn->data; + ssize_t sbytes; + CURLcode result = CURLE_OK; + struct SingleRequest *k = &data->req; + size_t cb; /* Bytes currently read */ + char buffer[STRERROR_LEN]; + + switch(event) { + + case TFTP_EVENT_ACK: + case TFTP_EVENT_OACK: + if(event == TFTP_EVENT_ACK) { + /* Ack the packet */ + int rblock = getrpacketblock(&state->rpacket); + + if(rblock != state->block && + /* There's a bug in tftpd-hpa that causes it to send us an ack for + * 65535 when the block number wraps to 0. So when we're expecting + * 0, also accept 65535. See + * http://syslinux.zytor.com/archives/2010-September/015253.html + * */ + !(state->block == 0 && rblock == 65535)) { + /* This isn't the expected block. Log it and up the retry counter */ + infof(data, "Received ACK for block %d, expecting %d\n", + rblock, state->block); + state->retries++; + /* Bail out if over the maximum */ + if(state->retries>state->retry_max) { + failf(data, "tftp_tx: giving up waiting for block %d ack", + state->block); + result = CURLE_SEND_ERROR; + } + else { + /* Re-send the data packet */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4 + state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, + buffer, sizeof(buffer))); + result = CURLE_SEND_ERROR; + } + } + + return result; + } + /* This is the expected packet. Reset the counters and send the next + block */ + time(&state->rx_time); + state->block++; + } + else + state->block = 1; /* first data block is 1 when using OACK */ + + state->retries = 0; + setpacketevent(&state->spacket, TFTP_EVENT_DATA); + setpacketblock(&state->spacket, state->block); + if(state->block > 1 && state->sbytes < state->blksize) { + state->state = TFTP_STATE_FIN; + return CURLE_OK; + } + + /* TFTP considers data block size < 512 bytes as an end of session. So + * in some cases we must wait for additional data to build full (512 bytes) + * data block. + * */ + state->sbytes = 0; + state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4; + do { + result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes, + &cb); + if(result) + return result; + state->sbytes += (int)cb; + state->conn->data->req.upload_fromhere += cb; + } while(state->sbytes < state->blksize && cb != 0); + + sbytes = sendto(state->sockfd, (void *) state->spacket.data, + 4 + state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + /* Update the progress meter */ + k->writebytecount += state->sbytes; + Curl_pgrsSetUploadCounter(data, k->writebytecount); + break; + + case TFTP_EVENT_TIMEOUT: + /* Increment the retry counter and log the timeout */ + state->retries++; + infof(data, "Timeout waiting for block %d ACK. " + " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries); + /* Decide if we've had enough */ + if(state->retries > state->retry_max) { + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + } + else { + /* Re-send the data packet */ + sbytes = sendto(state->sockfd, (void *)state->spacket.data, + 4 + state->sbytes, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* Check all sbytes were sent */ + if(sbytes<0) { + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_SEND_ERROR; + } + /* since this was a re-send, we remain at the still byte position */ + Curl_pgrsSetUploadCounter(data, k->writebytecount); + } + break; + + case TFTP_EVENT_ERROR: + state->state = TFTP_STATE_FIN; + setpacketevent(&state->spacket, TFTP_EVENT_ERROR); + setpacketblock(&state->spacket, state->block); + (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG, + (struct sockaddr *)&state->remote_addr, + state->remote_addrlen); + /* don't bother with the return code, but if the socket is still up we + * should be a good TFTP client and let the server know we're done */ + state->state = TFTP_STATE_FIN; + break; + + default: + failf(data, "tftp_tx: internal error, event: %i", (int)(event)); + break; + } + + return result; +} + +/********************************************************** + * + * tftp_translate_code + * + * Translate internal error codes to CURL error codes + * + **********************************************************/ +static CURLcode tftp_translate_code(tftp_error_t error) +{ + CURLcode result = CURLE_OK; + + if(error != TFTP_ERR_NONE) { + switch(error) { + case TFTP_ERR_NOTFOUND: + result = CURLE_TFTP_NOTFOUND; + break; + case TFTP_ERR_PERM: + result = CURLE_TFTP_PERM; + break; + case TFTP_ERR_DISKFULL: + result = CURLE_REMOTE_DISK_FULL; + break; + case TFTP_ERR_UNDEF: + case TFTP_ERR_ILLEGAL: + result = CURLE_TFTP_ILLEGAL; + break; + case TFTP_ERR_UNKNOWNID: + result = CURLE_TFTP_UNKNOWNID; + break; + case TFTP_ERR_EXISTS: + result = CURLE_REMOTE_FILE_EXISTS; + break; + case TFTP_ERR_NOSUCHUSER: + result = CURLE_TFTP_NOSUCHUSER; + break; + case TFTP_ERR_TIMEOUT: + result = CURLE_OPERATION_TIMEDOUT; + break; + case TFTP_ERR_NORESPONSE: + result = CURLE_COULDNT_CONNECT; + break; + default: + result = CURLE_ABORTED_BY_CALLBACK; + break; + } + } + else + result = CURLE_OK; + + return result; +} + +/********************************************************** + * + * tftp_state_machine + * + * The tftp state machine event dispatcher + * + **********************************************************/ +static CURLcode tftp_state_machine(tftp_state_data_t *state, + tftp_event_t event) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = state->conn->data; + + switch(state->state) { + case TFTP_STATE_START: + DEBUGF(infof(data, "TFTP_STATE_START\n")); + result = tftp_send_first(state, event); + break; + case TFTP_STATE_RX: + DEBUGF(infof(data, "TFTP_STATE_RX\n")); + result = tftp_rx(state, event); + break; + case TFTP_STATE_TX: + DEBUGF(infof(data, "TFTP_STATE_TX\n")); + result = tftp_tx(state, event); + break; + case TFTP_STATE_FIN: + infof(data, "%s\n", "TFTP finished"); + break; + default: + DEBUGF(infof(data, "STATE: %d\n", state->state)); + failf(data, "%s", "Internal state machine error"); + result = CURLE_TFTP_ILLEGAL; + break; + } + + return result; +} + +/********************************************************** + * + * tftp_disconnect + * + * The disconnect callback + * + **********************************************************/ +static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + tftp_state_data_t *state = conn->proto.tftpc; + (void) dead_connection; + + /* done, free dynamically allocated pkt buffers */ + if(state) { + Curl_safefree(state->rpacket.data); + Curl_safefree(state->spacket.data); + free(state); + } + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_connect + * + * The connect callback + * + **********************************************************/ +static CURLcode tftp_connect(struct connectdata *conn, bool *done) +{ + tftp_state_data_t *state; + int blksize; + + blksize = TFTP_BLKSIZE_DEFAULT; + + state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t)); + if(!state) + return CURLE_OUT_OF_MEMORY; + + /* alloc pkt buffers based on specified blksize */ + if(conn->data->set.tftp_blksize) { + blksize = (int)conn->data->set.tftp_blksize; + if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN) + return CURLE_TFTP_ILLEGAL; + } + + if(!state->rpacket.data) { + state->rpacket.data = calloc(1, blksize + 2 + 2); + + if(!state->rpacket.data) + return CURLE_OUT_OF_MEMORY; + } + + if(!state->spacket.data) { + state->spacket.data = calloc(1, blksize + 2 + 2); + + if(!state->spacket.data) + return CURLE_OUT_OF_MEMORY; + } + + /* we don't keep TFTP connections up basically because there's none or very + * little gain for UDP */ + connclose(conn, "TFTP"); + + state->conn = conn; + state->sockfd = state->conn->sock[FIRSTSOCKET]; + state->state = TFTP_STATE_START; + state->error = TFTP_ERR_NONE; + state->blksize = blksize; + state->requested_blksize = blksize; + + ((struct sockaddr *)&state->local_addr)->sa_family = + (CURL_SA_FAMILY_T)(conn->ip_addr->ai_family); + + tftp_set_timeouts(state); + + if(!conn->bits.bound) { + /* If not already bound, bind to any interface, random UDP port. If it is + * reused or a custom local port was desired, this has already been done! + * + * We once used the size of the local_addr struct as the third argument + * for bind() to better work with IPv6 or whatever size the struct could + * have, but we learned that at least Tru64, AIX and IRIX *requires* the + * size of that argument to match the exact size of a 'sockaddr_in' struct + * when running IPv4-only. + * + * Therefore we use the size from the address we connected to, which we + * assume uses the same IP version and thus hopefully this works for both + * IPv4 and IPv6... + */ + int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, + conn->ip_addr->ai_addrlen); + if(rc) { + char buffer[STRERROR_LEN]; + failf(conn->data, "bind() failed; %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + return CURLE_COULDNT_CONNECT; + } + conn->bits.bound = TRUE; + } + + Curl_pgrsStartNow(conn->data); + + *done = TRUE; + + return CURLE_OK; +} + +/********************************************************** + * + * tftp_done + * + * The done callback + * + **********************************************************/ +static CURLcode tftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + CURLcode result = CURLE_OK; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + (void)status; /* unused */ + (void)premature; /* not used */ + + if(Curl_pgrsDone(conn)) + return CURLE_ABORTED_BY_CALLBACK; + + /* If we have encountered an error */ + if(state) + result = tftp_translate_code(state->error); + + return result; +} + +/********************************************************** + * + * tftp_getsock + * + * The getsock callback + * + **********************************************************/ +static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + + return GETSOCK_READSOCK(0); +} + +/********************************************************** + * + * tftp_receive_packet + * + * Called once select fires and data is ready on the socket + * + **********************************************************/ +static CURLcode tftp_receive_packet(struct connectdata *conn) +{ + struct Curl_sockaddr_storage fromaddr; + curl_socklen_t fromlen; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + struct SingleRequest *k = &data->req; + + /* Receive the packet */ + fromlen = sizeof(fromaddr); + state->rbytes = (int)recvfrom(state->sockfd, + (void *)state->rpacket.data, + state->blksize + 4, + 0, + (struct sockaddr *)&fromaddr, + &fromlen); + if(state->remote_addrlen == 0) { + memcpy(&state->remote_addr, &fromaddr, fromlen); + state->remote_addrlen = fromlen; + } + + /* Sanity check packet length */ + if(state->rbytes < 4) { + failf(data, "Received too short packet"); + /* Not a timeout, but how best to handle it? */ + state->event = TFTP_EVENT_TIMEOUT; + } + else { + /* The event is given by the TFTP packet time */ + unsigned short event = getrpacketevent(&state->rpacket); + state->event = (tftp_event_t)event; + + switch(state->event) { + case TFTP_EVENT_DATA: + /* Don't pass to the client empty or retransmitted packets */ + if(state->rbytes > 4 && + (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { + result = Curl_client_write(conn, CLIENTWRITE_BODY, + (char *)state->rpacket.data + 4, + state->rbytes-4); + if(result) { + tftp_state_machine(state, TFTP_EVENT_ERROR); + return result; + } + k->bytecount += state->rbytes-4; + Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount); + } + break; + case TFTP_EVENT_ERROR: + { + unsigned short error = getrpacketblock(&state->rpacket); + char *str = (char *)state->rpacket.data + 4; + size_t strn = state->rbytes - 4; + state->error = (tftp_error_t)error; + if(Curl_strnlen(str, strn) < strn) + infof(data, "TFTP error: %s\n", str); + break; + } + case TFTP_EVENT_ACK: + break; + case TFTP_EVENT_OACK: + result = tftp_parse_option_ack(state, + (const char *)state->rpacket.data + 2, + state->rbytes-2); + if(result) + return result; + break; + case TFTP_EVENT_RRQ: + case TFTP_EVENT_WRQ: + default: + failf(data, "%s", "Internal error: Unexpected packet"); + break; + } + + /* Update the progress meter */ + if(Curl_pgrsUpdate(conn)) { + tftp_state_machine(state, TFTP_EVENT_ERROR); + return CURLE_ABORTED_BY_CALLBACK; + } + } + return result; +} + +/********************************************************** + * + * tftp_state_timeout + * + * Check if timeouts have been reached + * + **********************************************************/ +static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) +{ + time_t current; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + if(event) + *event = TFTP_EVENT_NONE; + + time(¤t); + if(current > state->max_time) { + DEBUGF(infof(conn->data, "timeout: %ld > %ld\n", + (long)current, (long)state->max_time)); + state->error = TFTP_ERR_TIMEOUT; + state->state = TFTP_STATE_FIN; + return 0; + } + if(current > state->rx_time + state->retry_time) { + if(event) + *event = TFTP_EVENT_TIMEOUT; + time(&state->rx_time); /* update even though we received nothing */ + } + + /* there's a typecast below here since 'time_t' may in fact be larger than + 'long', but we estimate that a 'long' will still be able to hold number + of seconds even if "only" 32 bit */ + return (long)(state->max_time - current); +} + +/********************************************************** + * + * tftp_multi_statemach + * + * Handle single RX socket event and return + * + **********************************************************/ +static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) +{ + tftp_event_t event; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + long timeout_ms = tftp_state_timeout(conn, &event); + + *done = FALSE; + + if(timeout_ms <= 0) { + failf(data, "TFTP response timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + if(event != TFTP_EVENT_NONE) { + result = tftp_state_machine(state, event); + if(result) + return result; + *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; + if(*done) + /* Tell curl we're done */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + } + else { + /* no timeouts to handle, check our socket */ + int rc = SOCKET_READABLE(state->sockfd, 0); + + if(rc == -1) { + /* bail out */ + int error = SOCKERRNO; + char buffer[STRERROR_LEN]; + failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer))); + state->event = TFTP_EVENT_ERROR; + } + else if(rc != 0) { + result = tftp_receive_packet(conn); + if(result) + return result; + result = tftp_state_machine(state, state->event); + if(result) + return result; + *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; + if(*done) + /* Tell curl we're done */ + Curl_setup_transfer(data, -1, -1, FALSE, -1); + } + /* if rc == 0, then select() timed out */ + } + + return result; +} + +/********************************************************** + * + * tftp_doing + * + * Called from multi.c while DOing + * + **********************************************************/ +static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result; + result = tftp_multi_statemach(conn, dophase_done); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete\n")); + } + else if(!result) { + /* The multi code doesn't have this logic for the DOING state so we + provide it for TFTP since it may do the entire transfer in this + state. */ + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(conn->data, Curl_now()); + } + return result; +} + +/********************************************************** + * + * tftp_peform + * + * Entry point for transfer from tftp_do, sarts state mach + * + **********************************************************/ +static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) +{ + CURLcode result = CURLE_OK; + tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; + + *dophase_done = FALSE; + + result = tftp_state_machine(state, TFTP_EVENT_INIT); + + if((state->state == TFTP_STATE_FIN) || result) + return result; + + tftp_multi_statemach(conn, dophase_done); + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete\n")); + + return result; +} + + +/********************************************************** + * + * tftp_do + * + * The do callback + * + * This callback initiates the TFTP transfer + * + **********************************************************/ + +static CURLcode tftp_do(struct connectdata *conn, bool *done) +{ + tftp_state_data_t *state; + CURLcode result; + + *done = FALSE; + + if(!conn->proto.tftpc) { + result = tftp_connect(conn, done); + if(result) + return result; + } + + state = (tftp_state_data_t *)conn->proto.tftpc; + if(!state) + return CURLE_TFTP_ILLEGAL; + + result = tftp_perform(conn, done); + + /* If tftp_perform() returned an error, use that for return code. If it + was OK, see if tftp_translate_code() has an error. */ + if(!result) + /* If we have encountered an internal tftp error, translate it. */ + result = tftp_translate_code(state->error); + + return result; +} + +static CURLcode tftp_setup_connection(struct connectdata * conn) +{ + struct Curl_easy *data = conn->data; + char *type; + + conn->socktype = SOCK_DGRAM; /* UDP datagram based */ + + /* TFTP URLs support an extension like ";mode=" that + * we'll try to get now! */ + type = strstr(data->state.up.path, ";mode="); + + if(!type) + type = strstr(conn->host.rawalloc, ";mode="); + + if(type) { + char command; + *type = 0; /* it was in the middle of the hostname */ + command = Curl_raw_toupper(type[6]); + + switch(command) { + case 'A': /* ASCII mode */ + case 'N': /* NETASCII mode */ + data->set.prefer_ascii = TRUE; + break; + + case 'O': /* octet mode */ + case 'I': /* binary mode */ + default: + /* switch off ASCII */ + data->set.prefer_ascii = FALSE; + break; + } + } + + return CURLE_OK; +} +#endif diff --git a/libcurl/lib/tftp.h b/libcurl/lib/tftp.h new file mode 100644 index 0000000..1335f64 --- /dev/null +++ b/libcurl/lib/tftp.h @@ -0,0 +1,28 @@ +#ifndef HEADER_CURL_TFTP_H +#define HEADER_CURL_TFTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TFTP +extern const struct Curl_handler Curl_handler_tftp; +#endif + +#endif /* HEADER_CURL_TFTP_H */ diff --git a/libcurl/lib/timeval.c b/libcurl/lib/timeval.c new file mode 100644 index 0000000..dbb8bc0 --- /dev/null +++ b/libcurl/lib/timeval.c @@ -0,0 +1,214 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "timeval.h" + +#if defined(WIN32) && !defined(MSDOS) + +/* set in win32_init() */ +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + +struct curltime Curl_now(void) +{ + struct curltime now; + if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */ + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + now.tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart); + now.tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 / + Curl_freq.QuadPart); + } + else { + /* Disable /analyze warning that GetTickCount64 is preferred */ + /* Note: warning 28159 only exists in VS2005+ (_MSC_VER >= 1400) */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#pragma warning(push) +#pragma warning(disable:28159) +#endif + DWORD milliseconds = GetTickCount(); +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#pragma warning(pop) +#endif + + now.tv_sec = milliseconds / 1000; + now.tv_usec = (milliseconds % 1000) * 1000; + } + return now; +} + +#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) + +struct curltime Curl_now(void) +{ + /* + ** clock_gettime() is granted to be increased monotonically when the + ** monotonic clock is queried. Time starting point is unspecified, it + ** could be the system start-up time, the Epoch, or something else, + ** in any case the time starting point does not change once that the + ** system has started up. + */ +#ifdef HAVE_GETTIMEOFDAY + struct timeval now; +#endif + struct curltime cnow; + struct timespec tsnow; + + /* + ** clock_gettime() may be defined by Apple's SDK as weak symbol thus + ** code compiles but fails during run-time if clock_gettime() is + ** called on unsupported OS version. + */ +#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1) + bool have_clock_gettime = FALSE; + if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) + have_clock_gettime = TRUE; +#endif + + if( +#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1) + have_clock_gettime && +#endif + (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) { + cnow.tv_sec = tsnow.tv_sec; + cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000); + } + /* + ** Even when the configure process has truly detected monotonic clock + ** availability, it might happen that it is not actually available at + ** run-time. When this occurs simply fallback to other time source. + */ +#ifdef HAVE_GETTIMEOFDAY + else { + (void)gettimeofday(&now, NULL); + cnow.tv_sec = now.tv_sec; + cnow.tv_usec = (unsigned int)now.tv_usec; + } +#else + else { + cnow.tv_sec = time(NULL); + cnow.tv_usec = 0; + } +#endif + return cnow; +} + +#elif defined(HAVE_MACH_ABSOLUTE_TIME) + +#include +#include + +struct curltime Curl_now(void) +{ + /* + ** Monotonic timer on Mac OS is provided by mach_absolute_time(), which + ** returns time in Mach "absolute time units," which are platform-dependent. + ** To convert to nanoseconds, one must use conversion factors specified by + ** mach_timebase_info(). + */ + static mach_timebase_info_data_t timebase; + struct curltime cnow; + uint64_t usecs; + + if(0 == timebase.denom) + (void) mach_timebase_info(&timebase); + + usecs = mach_absolute_time(); + usecs *= timebase.numer; + usecs /= timebase.denom; + usecs /= 1000; + + cnow.tv_sec = usecs / 1000000; + cnow.tv_usec = (int)(usecs % 1000000); + + return cnow; +} + +#elif defined(HAVE_GETTIMEOFDAY) + +struct curltime Curl_now(void) +{ + /* + ** gettimeofday() is not granted to be increased monotonically, due to + ** clock drifting and external source time synchronization it can jump + ** forward or backward in time. + */ + struct timeval now; + struct curltime ret; + (void)gettimeofday(&now, NULL); + ret.tv_sec = now.tv_sec; + ret.tv_usec = (int)now.tv_usec; + return ret; +} + +#else + +struct curltime Curl_now(void) +{ + /* + ** time() returns the value of time in seconds since the Epoch. + */ + struct curltime now; + now.tv_sec = time(NULL); + now.tv_usec = 0; + return now; +} + +#endif + +#if SIZEOF_TIME_T < 8 +#define TIME_MAX INT_MAX +#define TIME_MIN INT_MIN +#else +#define TIME_MAX 9223372036854775807LL +#define TIME_MIN -9223372036854775807LL +#endif + +/* + * Returns: time difference in number of milliseconds. For too large diffs it + * returns max value. + * + * @unittest: 1323 + */ +timediff_t Curl_timediff(struct curltime newer, struct curltime older) +{ + timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; + if(diff >= (TIME_MAX/1000)) + return TIME_MAX; + else if(diff <= (TIME_MIN/1000)) + return TIME_MIN; + return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000; +} + +/* + * Returns: time difference in number of microseconds. For too large diffs it + * returns max value. + */ +timediff_t Curl_timediff_us(struct curltime newer, struct curltime older) +{ + timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; + if(diff >= (TIME_MAX/1000000)) + return TIME_MAX; + else if(diff <= (TIME_MIN/1000000)) + return TIME_MIN; + return diff * 1000000 + newer.tv_usec-older.tv_usec; +} diff --git a/libcurl/lib/timeval.h b/libcurl/lib/timeval.h new file mode 100644 index 0000000..96867d7 --- /dev/null +++ b/libcurl/lib/timeval.h @@ -0,0 +1,58 @@ +#ifndef HEADER_CURL_TIMEVAL_H +#define HEADER_CURL_TIMEVAL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if SIZEOF_TIME_T < 8 +typedef int timediff_t; +#define CURL_FORMAT_TIMEDIFF_T "d" +#else +typedef curl_off_t timediff_t; +#define CURL_FORMAT_TIMEDIFF_T CURL_FORMAT_CURL_OFF_T +#endif + +struct curltime { + time_t tv_sec; /* seconds */ + int tv_usec; /* microseconds */ +}; + +struct curltime Curl_now(void); + +/* + * Make sure that the first argument (t1) is the more recent time and t2 is + * the older time, as otherwise you get a weird negative time-diff back... + * + * Returns: the time difference in number of milliseconds. + */ +timediff_t Curl_timediff(struct curltime t1, struct curltime t2); + +/* + * Make sure that the first argument (t1) is the more recent time and t2 is + * the older time, as otherwise you get a weird negative time-diff back... + * + * Returns: the time difference in number of microseconds. + */ +timediff_t Curl_timediff_us(struct curltime newer, struct curltime older); + +#endif /* HEADER_CURL_TIMEVAL_H */ diff --git a/libcurl/lib/transfer.c b/libcurl/lib/transfer.c new file mode 100644 index 0000000..4426a4b --- /dev/null +++ b/libcurl/lib/transfer.c @@ -0,0 +1,1902 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "strtoofft.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#ifndef HAVE_SOCKET +#error "We can't compile without socket() support!" +#endif + +#include "urldata.h" +#include +#include "netrc.h" + +#include "content_encoding.h" +#include "hostip.h" +#include "transfer.h" +#include "sendf.h" +#include "speedcheck.h" +#include "progress.h" +#include "http.h" +#include "url.h" +#include "getinfo.h" +#include "vtls/vtls.h" +#include "select.h" +#include "multiif.h" +#include "connect.h" +#include "non-ascii.h" +#include "http2.h" +#include "mime.h" +#include "strcase.h" +#include "urlapi-int.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_IMAP) +/* + * checkheaders() checks the linked list of custom headers for a + * particular header (prefix). Provide the prefix without colon! + * + * Returns a pointer to the first matching header or NULL if none matched. + */ +char *Curl_checkheaders(const struct connectdata *conn, + const char *thisheader) +{ + struct curl_slist *head; + size_t thislen = strlen(thisheader); + struct Curl_easy *data = conn->data; + + for(head = data->set.headers; head; head = head->next) { + if(strncasecompare(head->data, thisheader, thislen) && + Curl_headersep(head->data[thislen]) ) + return head->data; + } + + return NULL; +} +#endif + +CURLcode Curl_get_upload_buffer(struct Curl_easy *data) +{ + if(!data->state.ulbuf) { + data->state.ulbuf = malloc(data->set.upload_buffer_size); + if(!data->state.ulbuf) + return CURLE_OUT_OF_MEMORY; + } + return CURLE_OK; +} + +#ifndef CURL_DISABLE_HTTP +/* + * This function will be called to loop through the trailers buffer + * until no more data is available for sending. + */ +static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems, + void *raw) +{ + struct Curl_easy *data = (struct Curl_easy *)raw; + Curl_send_buffer *trailers_buf = data->state.trailers_buf; + size_t bytes_left = trailers_buf->size_used-data->state.trailers_bytes_sent; + size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left; + if(to_copy) { + memcpy(buffer, + &trailers_buf->buffer[data->state.trailers_bytes_sent], + to_copy); + data->state.trailers_bytes_sent += to_copy; + } + return to_copy; +} + +static size_t Curl_trailers_left(void *raw) +{ + struct Curl_easy *data = (struct Curl_easy *)raw; + Curl_send_buffer *trailers_buf = data->state.trailers_buf; + return trailers_buf->size_used - data->state.trailers_bytes_sent; +} +#endif + +/* + * This function will call the read callback to fill our buffer with data + * to upload. + */ +CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, + size_t *nreadp) +{ + struct Curl_easy *data = conn->data; + size_t buffersize = bytes; + size_t nread; + + curl_read_callback readfunc = NULL; + void *extra_data = NULL; + +#ifdef CURL_DOES_CONVERSIONS + bool sending_http_headers = FALSE; + + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + const struct HTTP *http = data->req.protop; + + if(http->sending == HTTPSEND_REQUEST) + /* We're sending the HTTP request headers, not the data. + Remember that so we don't re-translate them into garbage. */ + sending_http_headers = TRUE; + } +#endif + +#ifndef CURL_DISABLE_HTTP + if(data->state.trailers_state == TRAILERS_INITIALIZED) { + struct curl_slist *trailers = NULL; + CURLcode c; + int trailers_ret_code; + + /* at this point we already verified that the callback exists + so we compile and store the trailers buffer, then proceed */ + infof(data, + "Moving trailers state machine from initialized to sending.\n"); + data->state.trailers_state = TRAILERS_SENDING; + data->state.trailers_buf = Curl_add_buffer_init(); + if(!data->state.trailers_buf) { + failf(data, "Unable to allocate trailing headers buffer !"); + return CURLE_OUT_OF_MEMORY; + } + data->state.trailers_bytes_sent = 0; + Curl_set_in_callback(data, true); + trailers_ret_code = data->set.trailer_callback(&trailers, + data->set.trailer_data); + Curl_set_in_callback(data, false); + if(trailers_ret_code == CURL_TRAILERFUNC_OK) { + c = Curl_http_compile_trailers(trailers, data->state.trailers_buf, data); + } + else { + failf(data, "operation aborted by trailing headers callback"); + *nreadp = 0; + c = CURLE_ABORTED_BY_CALLBACK; + } + if(c != CURLE_OK) { + Curl_add_buffer_free(&data->state.trailers_buf); + curl_slist_free_all(trailers); + return c; + } + infof(data, "Successfully compiled trailers.\r\n"); + curl_slist_free_all(trailers); + } +#endif + + /* if we are transmitting trailing data, we don't need to write + a chunk size so we skip this */ + if(data->req.upload_chunky && + data->state.trailers_state == TRAILERS_NONE) { + /* if chunked Transfer-Encoding */ + buffersize -= (8 + 2 + 2); /* 32bit hex + CRLF + CRLF */ + data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */ + } + +#ifndef CURL_DISABLE_HTTP + if(data->state.trailers_state == TRAILERS_SENDING) { + /* if we're here then that means that we already sent the last empty chunk + but we didn't send a final CR LF, so we sent 0 CR LF. We then start + pulling trailing data until we have no more at which point we + simply return to the previous point in the state machine as if + nothing happened. + */ + readfunc = Curl_trailers_read; + extra_data = (void *)data; + } + else +#endif + { + readfunc = data->state.fread_func; + extra_data = data->state.in; + } + + Curl_set_in_callback(data, true); + nread = readfunc(data->req.upload_fromhere, 1, + buffersize, extra_data); + Curl_set_in_callback(data, false); + + if(nread == CURL_READFUNC_ABORT) { + failf(data, "operation aborted by callback"); + *nreadp = 0; + return CURLE_ABORTED_BY_CALLBACK; + } + if(nread == CURL_READFUNC_PAUSE) { + struct SingleRequest *k = &data->req; + + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* protocols that work without network cannot be paused. This is + actually only FILE:// just now, and it can't pause since the transfer + isn't done using the "normal" procedure. */ + failf(data, "Read callback asked for PAUSE when not supported!"); + return CURLE_READ_ERROR; + } + + /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ + k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */ + if(data->req.upload_chunky) { + /* Back out the preallocation done above */ + data->req.upload_fromhere -= (8 + 2); + } + *nreadp = 0; + + return CURLE_OK; /* nothing was read */ + } + else if(nread > buffersize) { + /* the read function returned a too large value */ + *nreadp = 0; + failf(data, "read function returned funny value"); + return CURLE_READ_ERROR; + } + + if(!data->req.forbidchunk && data->req.upload_chunky) { + /* if chunked Transfer-Encoding + * build chunk: + * + * CRLF + * CRLF + */ + /* On non-ASCII platforms the may or may not be + translated based on set.prefer_ascii while the protocol + portion must always be translated to the network encoding. + To further complicate matters, line end conversion might be + done later on, so we need to prevent CRLFs from becoming + CRCRLFs if that's the case. To do this we use bare LFs + here, knowing they'll become CRLFs later on. + */ + + bool added_crlf = FALSE; + int hexlen = 0; + const char *endofline_native; + const char *endofline_network; + + if( +#ifdef CURL_DO_LINEEND_CONV + (data->set.prefer_ascii) || +#endif + (data->set.crlf)) { + /* \n will become \r\n later on */ + endofline_native = "\n"; + endofline_network = "\x0a"; + } + else { + endofline_native = "\r\n"; + endofline_network = "\x0d\x0a"; + } + + /* if we're not handling trailing data, proceed as usual */ + if(data->state.trailers_state != TRAILERS_SENDING) { + char hexbuffer[11] = ""; + hexlen = msnprintf(hexbuffer, sizeof(hexbuffer), + "%zx%s", nread, endofline_native); + + /* move buffer pointer */ + data->req.upload_fromhere -= hexlen; + nread += hexlen; + + /* copy the prefix to the buffer, leaving out the NUL */ + memcpy(data->req.upload_fromhere, hexbuffer, hexlen); + + /* always append ASCII CRLF to the data unless + we have a valid trailer callback */ +#ifndef CURL_DISABLE_HTTP + if((nread-hexlen) == 0 && + data->set.trailer_callback != NULL && + data->state.trailers_state == TRAILERS_NONE) { + data->state.trailers_state = TRAILERS_INITIALIZED; + } + else +#endif + { + memcpy(data->req.upload_fromhere + nread, + endofline_network, + strlen(endofline_network)); + added_crlf = TRUE; + } + } + +#ifdef CURL_DOES_CONVERSIONS + { + CURLcode result; + size_t length; + if(data->set.prefer_ascii) + /* translate the protocol and data */ + length = nread; + else + /* just translate the protocol portion */ + length = hexlen; + if(length) { + result = Curl_convert_to_network(data, data->req.upload_fromhere, + length); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + } + } +#endif /* CURL_DOES_CONVERSIONS */ + +#ifndef CURL_DISABLE_HTTP + if(data->state.trailers_state == TRAILERS_SENDING && + !Curl_trailers_left(data)) { + Curl_add_buffer_free(&data->state.trailers_buf); + data->state.trailers_state = TRAILERS_DONE; + data->set.trailer_data = NULL; + data->set.trailer_callback = NULL; + /* mark the transfer as done */ + data->req.upload_done = TRUE; + infof(data, "Signaling end of chunked upload after trailers.\n"); + } + else +#endif + if((nread - hexlen) == 0 && + data->state.trailers_state != TRAILERS_INITIALIZED) { + /* mark this as done once this chunk is transferred */ + data->req.upload_done = TRUE; + infof(data, + "Signaling end of chunked upload via terminating chunk.\n"); + } + + if(added_crlf) + nread += strlen(endofline_network); /* for the added end of line */ + } +#ifdef CURL_DOES_CONVERSIONS + else if((data->set.prefer_ascii) && (!sending_http_headers)) { + CURLcode result; + result = Curl_convert_to_network(data, data->req.upload_fromhere, nread); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + } +#endif /* CURL_DOES_CONVERSIONS */ + + *nreadp = nread; + + return CURLE_OK; +} + + +/* + * Curl_readrewind() rewinds the read stream. This is typically used for HTTP + * POST/PUT with multi-pass authentication when a sending was denied and a + * resend is necessary. + */ +CURLcode Curl_readrewind(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_mimepart *mimepart = &data->set.mimepost; + + conn->bits.rewindaftersend = FALSE; /* we rewind now */ + + /* explicitly switch off sending data on this connection now since we are + about to restart a new transfer and thus we want to avoid inadvertently + sending more data on the existing connection until the next transfer + starts */ + data->req.keepon &= ~KEEP_SEND; + + /* We have sent away data. If not using CURLOPT_POSTFIELDS or + CURLOPT_HTTPPOST, call app to rewind + */ + if(conn->handler->protocol & PROTO_FAMILY_HTTP) { + struct HTTP *http = data->req.protop; + + if(http->sendit) + mimepart = http->sendit; + } + if(data->set.postfields) + ; /* do nothing */ + else if(data->set.httpreq == HTTPREQ_POST_MIME || + data->set.httpreq == HTTPREQ_POST_FORM) { + if(Curl_mime_rewind(mimepart)) { + failf(data, "Cannot rewind mime/post data"); + return CURLE_SEND_FAIL_REWIND; + } + } + else { + if(data->set.seek_func) { + int err; + + Curl_set_in_callback(data, true); + err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET); + Curl_set_in_callback(data, false); + if(err) { + failf(data, "seek callback returned error %d", (int)err); + return CURLE_SEND_FAIL_REWIND; + } + } + else if(data->set.ioctl_func) { + curlioerr err; + + Curl_set_in_callback(data, true); + err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD, + data->set.ioctl_client); + Curl_set_in_callback(data, false); + infof(data, "the ioctl callback returned %d\n", (int)err); + + if(err) { + failf(data, "ioctl callback returned error %d", (int)err); + return CURLE_SEND_FAIL_REWIND; + } + } + else { + /* If no CURLOPT_READFUNCTION is used, we know that we operate on a + given FILE * stream and we can actually attempt to rewind that + ourselves with fseek() */ + if(data->state.fread_func == (curl_read_callback)fread) { + if(-1 != fseek(data->state.in, 0, SEEK_SET)) + /* successful rewind */ + return CURLE_OK; + } + + /* no callback set or failure above, makes us fail at once */ + failf(data, "necessary data rewind wasn't possible"); + return CURLE_SEND_FAIL_REWIND; + } + } + return CURLE_OK; +} + +static int data_pending(const struct connectdata *conn) +{ + /* in the case of libssh2, we can never be really sure that we have emptied + its internal buffers so we MUST always try until we get EAGAIN back */ + return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) || +#if defined(USE_NGHTTP2) + Curl_ssl_data_pending(conn, FIRSTSOCKET) || + /* For HTTP/2, we may read up everything including response body + with header fields in Curl_http_readwrite_headers. If no + content-length is provided, curl waits for the connection + close, which we emulate it using conn->proto.httpc.closed = + TRUE. The thing is if we read everything, then http2_recv won't + be called and we cannot signal the HTTP/2 stream has closed. As + a workaround, we return nonzero here to call http2_recv. */ + ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20); +#else + Curl_ssl_data_pending(conn, FIRSTSOCKET); +#endif +} + +/* + * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the + * remote document with the time provided by CURLOPT_TIMEVAL + */ +bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc) +{ + if((timeofdoc == 0) || (data->set.timevalue == 0)) + return TRUE; + + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + if(timeofdoc <= data->set.timevalue) { + infof(data, + "The requested document is not new enough\n"); + data->info.timecond = TRUE; + return FALSE; + } + break; + case CURL_TIMECOND_IFUNMODSINCE: + if(timeofdoc >= data->set.timevalue) { + infof(data, + "The requested document is not old enough\n"); + data->info.timecond = TRUE; + return FALSE; + } + break; + } + + return TRUE; +} + +/* + * Go ahead and do a read if we have a readable socket or if + * the stream was rewound (in which case we have data in a + * buffer) + * + * return '*comeback' TRUE if we didn't properly drain the socket so this + * function should get called again without select() or similar in between! + */ +static CURLcode readwrite_data(struct Curl_easy *data, + struct connectdata *conn, + struct SingleRequest *k, + int *didwhat, bool *done, + bool *comeback) +{ + CURLcode result = CURLE_OK; + ssize_t nread; /* number of bytes read */ + size_t excess = 0; /* excess bytes read */ + bool readmore = FALSE; /* used by RTP to signal for more data */ + int maxloops = 100; + + *done = FALSE; + *comeback = FALSE; + + /* This is where we loop until we have read everything there is to + read or we get a CURLE_AGAIN */ + do { + bool is_empty_data = FALSE; + size_t buffersize = data->set.buffer_size; + size_t bytestoread = buffersize; + + if( +#if defined(USE_NGHTTP2) + /* For HTTP/2, read data without caring about the content + length. This is safe because body in HTTP/2 is always + segmented thanks to its framing layer. Meanwhile, we have to + call Curl_read to ensure that http2_handle_stream_close is + called when we read all incoming bytes for a particular + stream. */ + !((conn->handler->protocol & PROTO_FAMILY_HTTP) && + conn->httpversion == 20) && +#endif + k->size != -1 && !k->header) { + /* make sure we don't read too much */ + curl_off_t totalleft = k->size - k->bytecount; + if(totalleft < (curl_off_t)bytestoread) + bytestoread = (size_t)totalleft; + } + + if(bytestoread) { + /* receive data from the network! */ + result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread); + + /* read would've blocked */ + if(CURLE_AGAIN == result) + break; /* get out of loop */ + + if(result>0) + return result; + } + else { + /* read nothing but since we wanted nothing we consider this an OK + situation to proceed from */ + DEBUGF(infof(data, "readwrite_data: we're done!\n")); + nread = 0; + } + + if((k->bytecount == 0) && (k->writebytecount == 0)) { + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + if(k->exp100 > EXP100_SEND_DATA) + /* set time stamp to compare with when waiting for the 100 */ + k->start100 = Curl_now(); + } + + *didwhat |= KEEP_RECV; + /* indicates data of zero size, i.e. empty file */ + is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE; + + /* NUL terminate, allowing string ops to be used */ + if(0 < nread || is_empty_data) { + k->buf[nread] = 0; + } + else { + /* if we receive 0 or less here, the server closed the connection + and we bail out from this! */ + DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n")); + k->keepon &= ~KEEP_RECV; + break; + } + + /* Default buffer to use when we write the buffer, it may be changed + in the flow below before the actual storing is done. */ + k->str = k->buf; + + if(conn->handler->readwrite) { + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + if(readmore) + break; + } + +#ifndef CURL_DISABLE_HTTP + /* Since this is a two-state thing, we check if we are parsing + headers at the moment or not. */ + if(k->header) { + /* we are in parse-the-header-mode */ + bool stop_reading = FALSE; + result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading); + if(result) + return result; + + if(conn->handler->readwrite && + (k->maxdownload <= 0 && nread > 0)) { + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + if(readmore) + break; + } + + if(stop_reading) { + /* We've stopped dealing with input, get out of the do-while loop */ + + if(nread > 0) { + infof(data, + "Excess found:" + " excess = %zd" + " url = %s (zero-length body)\n", + nread, data->state.up.path); + } + + break; + } + } +#endif /* CURL_DISABLE_HTTP */ + + + /* This is not an 'else if' since it may be a rest from the header + parsing, where the beginning of the buffer is headers and the end + is non-headers. */ + if(k->str && !k->header && (nread > 0 || is_empty_data)) { + + if(data->set.opt_no_body) { + /* data arrives although we want none, bail out */ + streamclose(conn, "ignoring body"); + *done = TRUE; + return CURLE_WEIRD_SERVER_REPLY; + } + +#ifndef CURL_DISABLE_HTTP + if(0 == k->bodywrites && !is_empty_data) { + /* These checks are only made the first time we are about to + write a piece of the body */ + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + /* HTTP-only checks */ + + if(data->req.newurl) { + if(conn->bits.close) { + /* Abort after the headers if "follow Location" is set + and we're set to close anyway. */ + k->keepon &= ~KEEP_RECV; + *done = TRUE; + return CURLE_OK; + } + /* We have a new url to load, but since we want to be able + to re-use this connection properly, we read the full + response in "ignore more" */ + k->ignorebody = TRUE; + infof(data, "Ignoring the response-body\n"); + } + if(data->state.resume_from && !k->content_range && + (data->set.httpreq == HTTPREQ_GET) && + !k->ignorebody) { + + if(k->size == data->state.resume_from) { + /* The resume point is at the end of file, consider this fine + even if it doesn't allow resume from here. */ + infof(data, "The entire document is already downloaded"); + connclose(conn, "already downloaded"); + /* Abort download */ + k->keepon &= ~KEEP_RECV; + *done = TRUE; + return CURLE_OK; + } + + /* we wanted to resume a download, although the server doesn't + * seem to support this and we did this with a GET (if it + * wasn't a GET we did a POST or PUT resume) */ + failf(data, "HTTP server doesn't seem to support " + "byte ranges. Cannot resume."); + return CURLE_RANGE_ERROR; + } + + if(data->set.timecondition && !data->state.range) { + /* A time condition has been set AND no ranges have been + requested. This seems to be what chapter 13.3.4 of + RFC 2616 defines to be the correct action for a + HTTP/1.1 client */ + + if(!Curl_meets_timecondition(data, k->timeofdoc)) { + *done = TRUE; + /* We're simulating a http 304 from server so we return + what should have been returned from the server */ + data->info.httpcode = 304; + infof(data, "Simulate a HTTP 304 response!\n"); + /* we abort the transfer before it is completed == we ruin the + re-use ability. Close the connection */ + connclose(conn, "Simulated 304 handling"); + return CURLE_OK; + } + } /* we have a time condition */ + + } /* this is HTTP or RTSP */ + } /* this is the first time we write a body part */ +#endif /* CURL_DISABLE_HTTP */ + + k->bodywrites++; + + /* pass data to the debug function before it gets "dechunked" */ + if(data->set.verbose) { + if(k->badheader) { + Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff, + (size_t)k->hbuflen); + if(k->badheader == HEADER_PARTHEADER) + Curl_debug(data, CURLINFO_DATA_IN, + k->str, (size_t)nread); + } + else + Curl_debug(data, CURLINFO_DATA_IN, + k->str, (size_t)nread); + } + +#ifndef CURL_DISABLE_HTTP + if(k->chunk) { + /* + * Here comes a chunked transfer flying and we need to decode this + * properly. While the name says read, this function both reads + * and writes away the data. The returned 'nread' holds the number + * of actual data it wrote to the client. + */ + + CHUNKcode res = + Curl_httpchunk_read(conn, k->str, nread, &nread); + + if(CHUNKE_OK < res) { + if(CHUNKE_WRITE_ERROR == res) { + failf(data, "Failed writing data"); + return CURLE_WRITE_ERROR; + } + failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res)); + return CURLE_RECV_ERROR; + } + if(CHUNKE_STOP == res) { + size_t dataleft; + /* we're done reading chunks! */ + k->keepon &= ~KEEP_RECV; /* read no more */ + + /* There are now possibly N number of bytes at the end of the + str buffer that weren't written to the client. + Push it back to be read on the next pass. */ + + dataleft = conn->chunk.dataleft; + if(dataleft != 0) { + infof(conn->data, "Leftovers after chunking: %zu bytes\n", + dataleft); + } + } + /* If it returned OK, we just keep going */ + } +#endif /* CURL_DISABLE_HTTP */ + + /* Account for body content stored in the header buffer */ + if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) { + DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n", + k->hbuflen)); + k->bytecount += k->hbuflen; + } + + if((-1 != k->maxdownload) && + (k->bytecount + nread >= k->maxdownload)) { + + excess = (size_t)(k->bytecount + nread - k->maxdownload); + if(excess > 0 && !k->ignorebody) { + infof(data, + "Excess found in a read:" + " excess = %zu" + ", size = %" CURL_FORMAT_CURL_OFF_T + ", maxdownload = %" CURL_FORMAT_CURL_OFF_T + ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n", + excess, k->size, k->maxdownload, k->bytecount); + } + + nread = (ssize_t) (k->maxdownload - k->bytecount); + if(nread < 0) /* this should be unusual */ + nread = 0; + + k->keepon &= ~KEEP_RECV; /* we're done reading */ + } + + k->bytecount += nread; + + Curl_pgrsSetDownloadCounter(data, k->bytecount); + + if(!k->chunk && (nread || k->badheader || is_empty_data)) { + /* If this is chunky transfer, it was already written */ + + if(k->badheader && !k->ignorebody) { + /* we parsed a piece of data wrongly assuming it was a header + and now we output it as body instead */ + + /* Don't let excess data pollute body writes */ + if(k->maxdownload == -1 || (curl_off_t)k->hbuflen <= k->maxdownload) + result = Curl_client_write(conn, CLIENTWRITE_BODY, + data->state.headerbuff, + k->hbuflen); + else + result = Curl_client_write(conn, CLIENTWRITE_BODY, + data->state.headerbuff, + (size_t)k->maxdownload); + + if(result) + return result; + } + if(k->badheader < HEADER_ALLBAD) { + /* This switch handles various content encodings. If there's an + error here, be sure to check over the almost identical code + in http_chunks.c. + Make sure that ALL_CONTENT_ENCODINGS contains all the + encodings handled here. */ + if(conn->data->set.http_ce_skip || !k->writer_stack) { + if(!k->ignorebody) { +#ifndef CURL_DISABLE_POP3 + if(conn->handler->protocol & PROTO_FAMILY_POP3) + result = Curl_pop3_write(conn, k->str, nread); + else +#endif /* CURL_DISABLE_POP3 */ + result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str, + nread); + } + } + else if(!k->ignorebody) + result = Curl_unencode_write(conn, k->writer_stack, k->str, nread); + } + k->badheader = HEADER_NORMAL; /* taken care of now */ + + if(result) + return result; + } + + } /* if(!header and data to read) */ + + if(conn->handler->readwrite && excess && !conn->bits.stream_was_rewound) { + /* Parse the excess data */ + k->str += nread; + + if(&k->str[excess] > &k->buf[data->set.buffer_size]) { + /* the excess amount was too excessive(!), make sure + it doesn't read out of buffer */ + excess = &k->buf[data->set.buffer_size] - k->str; + } + nread = (ssize_t)excess; + + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + return result; + + if(readmore) + k->keepon |= KEEP_RECV; /* we're not done reading */ + break; + } + + if(is_empty_data) { + /* if we received nothing, the server closed the connection and we + are done */ + k->keepon &= ~KEEP_RECV; + } + + if(k->keepon & KEEP_RECV_PAUSE) { + /* this is a paused transfer */ + break; + } + + } while(data_pending(conn) && maxloops--); + + if(maxloops <= 0) { + /* we mark it as read-again-please */ + conn->cselect_bits = CURL_CSELECT_IN; + *comeback = TRUE; + } + + if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) && + conn->bits.close) { + /* When we've read the entire thing and the close bit is set, the server + may now close the connection. If there's now any kind of sending going + on from our side, we need to stop that immediately. */ + infof(data, "we are done reading and this is set to close, stop send\n"); + k->keepon &= ~KEEP_SEND; /* no writing anymore either */ + } + + return CURLE_OK; +} + +CURLcode Curl_done_sending(struct connectdata *conn, + struct SingleRequest *k) +{ + k->keepon &= ~KEEP_SEND; /* we're done writing */ + + Curl_http2_done_sending(conn); + + if(conn->bits.rewindaftersend) { + CURLcode result = Curl_readrewind(conn); + if(result) + return result; + } + return CURLE_OK; +} + +#if defined(WIN32) && !defined(USE_LWIPSOCK) +#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY +#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B +#endif + +#ifdef _XBOX +static void win_update_buffer_size(curl_socket_t sockfd) +{ + // Xbox does not support WSAIoctl, so do nothing + (void)sockfd; // Prevents unused variable warning +} +#else +static void win_update_buffer_size(curl_socket_t sockfd) +{ + int result; + ULONG ideal; + DWORD ideallen; + result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0, + &ideal, sizeof(ideal), &ideallen, 0, 0); + if(result == 0) { + setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, + (const char *)&ideal, sizeof(ideal)); + } +} +#endif // _XBOX + +#else +#define win_update_buffer_size(x) +#endif + +/* + * Send data to upload to the server, when the socket is writable. + */ +static CURLcode readwrite_upload(struct Curl_easy *data, + struct connectdata *conn, + int *didwhat) +{ + ssize_t i, si; + ssize_t bytes_written; + CURLcode result; + ssize_t nread; /* number of bytes read */ + bool sending_http_headers = FALSE; + struct SingleRequest *k = &data->req; + + if((k->bytecount == 0) && (k->writebytecount == 0)) + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + + *didwhat |= KEEP_SEND; + + do { + /* only read more data if there's no upload data already + present in the upload buffer */ + if(0 == k->upload_present) { + result = Curl_get_upload_buffer(data); + if(result) + return result; + /* init the "upload from here" pointer */ + k->upload_fromhere = data->state.ulbuf; + + if(!k->upload_done) { + /* HTTP pollution, this should be written nicer to become more + protocol agnostic. */ + size_t fillcount; + struct HTTP *http = k->protop; + + if((k->exp100 == EXP100_SENDING_REQUEST) && + (http->sending == HTTPSEND_BODY)) { + /* If this call is to send body data, we must take some action: + We have sent off the full HTTP 1.1 request, and we shall now + go into the Expect: 100 state and await such a header */ + k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */ + k->keepon &= ~KEEP_SEND; /* disable writing */ + k->start100 = Curl_now(); /* timeout count starts now */ + *didwhat &= ~KEEP_SEND; /* we didn't write anything actually */ + /* set a timeout for the multi interface */ + Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT); + break; + } + + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { + if(http->sending == HTTPSEND_REQUEST) + /* We're sending the HTTP request headers, not the data. + Remember that so we don't change the line endings. */ + sending_http_headers = TRUE; + else + sending_http_headers = FALSE; + } + + result = Curl_fillreadbuffer(conn, data->set.upload_buffer_size, + &fillcount); + if(result) + return result; + + nread = fillcount; + } + else + nread = 0; /* we're done uploading/reading */ + + if(!nread && (k->keepon & KEEP_SEND_PAUSE)) { + /* this is a paused transfer */ + break; + } + if(nread <= 0) { + result = Curl_done_sending(conn, k); + if(result) + return result; + break; + } + + /* store number of bytes available for upload */ + k->upload_present = nread; + + /* convert LF to CRLF if so asked */ + if((!sending_http_headers) && ( +#ifdef CURL_DO_LINEEND_CONV + /* always convert if we're FTPing in ASCII mode */ + (data->set.prefer_ascii) || +#endif + (data->set.crlf))) { + /* Do we need to allocate a scratch buffer? */ + if(!data->state.scratch) { + data->state.scratch = malloc(2 * data->set.upload_buffer_size); + if(!data->state.scratch) { + failf(data, "Failed to alloc scratch buffer!"); + + return CURLE_OUT_OF_MEMORY; + } + } + + /* + * ASCII/EBCDIC Note: This is presumably a text (not binary) + * transfer so the data should already be in ASCII. + * That means the hex values for ASCII CR (0x0d) & LF (0x0a) + * must be used instead of the escape sequences \r & \n. + */ + for(i = 0, si = 0; i < nread; i++, si++) { + if(k->upload_fromhere[i] == 0x0a) { + data->state.scratch[si++] = 0x0d; + data->state.scratch[si] = 0x0a; + if(!data->set.crlf) { + /* we're here only because FTP is in ASCII mode... + bump infilesize for the LF we just added */ + if(data->state.infilesize != -1) + data->state.infilesize++; + } + } + else + data->state.scratch[si] = k->upload_fromhere[i]; + } + + if(si != nread) { + /* only perform the special operation if we really did replace + anything */ + nread = si; + + /* upload from the new (replaced) buffer instead */ + k->upload_fromhere = data->state.scratch; + + /* set the new amount too */ + k->upload_present = nread; + } + } + +#ifndef CURL_DISABLE_SMTP + if(conn->handler->protocol & PROTO_FAMILY_SMTP) { + result = Curl_smtp_escape_eob(conn, nread); + if(result) + return result; + } +#endif /* CURL_DISABLE_SMTP */ + } /* if 0 == k->upload_present */ + else { + /* We have a partial buffer left from a previous "round". Use + that instead of reading more data */ + } + + /* write to socket (send away data) */ + result = Curl_write(conn, + conn->writesockfd, /* socket to send to */ + k->upload_fromhere, /* buffer pointer */ + k->upload_present, /* buffer size */ + &bytes_written); /* actually sent */ + if(result) + return result; + + win_update_buffer_size(conn->writesockfd); + + if(data->set.verbose) + /* show the data before we change the pointer upload_fromhere */ + Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere, + (size_t)bytes_written); + + k->writebytecount += bytes_written; + Curl_pgrsSetUploadCounter(data, k->writebytecount); + + if((!k->upload_chunky || k->forbidchunk) && + (k->writebytecount == data->state.infilesize)) { + /* we have sent all data we were supposed to */ + k->upload_done = TRUE; + infof(data, "We are completely uploaded and fine\n"); + } + + if(k->upload_present != bytes_written) { + /* we only wrote a part of the buffer (if anything), deal with it! */ + + /* store the amount of bytes left in the buffer to write */ + k->upload_present -= bytes_written; + + /* advance the pointer where to find the buffer when the next send + is to happen */ + k->upload_fromhere += bytes_written; + } + else { + /* we've uploaded that buffer now */ + result = Curl_get_upload_buffer(data); + if(result) + return result; + k->upload_fromhere = data->state.ulbuf; + k->upload_present = 0; /* no more bytes left */ + + if(k->upload_done) { + result = Curl_done_sending(conn, k); + if(result) + return result; + } + } + + + } WHILE_FALSE; /* just to break out from! */ + + return CURLE_OK; +} + +/* + * Curl_readwrite() is the low-level function to be called when data is to + * be read and written to/from the connection. + * + * return '*comeback' TRUE if we didn't properly drain the socket so this + * function should get called again without select() or similar in between! + */ +CURLcode Curl_readwrite(struct connectdata *conn, + struct Curl_easy *data, + bool *done, + bool *comeback) +{ + struct SingleRequest *k = &data->req; + CURLcode result; + int didwhat = 0; + + curl_socket_t fd_read; + curl_socket_t fd_write; + int select_res = conn->cselect_bits; + + conn->cselect_bits = 0; + + /* only use the proper socket if the *_HOLD bit is not set simultaneously as + then we are in rate limiting state in that transfer direction */ + + if((k->keepon & KEEP_RECVBITS) == KEEP_RECV) + fd_read = conn->sockfd; + else + fd_read = CURL_SOCKET_BAD; + + if((k->keepon & KEEP_SENDBITS) == KEEP_SEND) + fd_write = conn->writesockfd; + else + fd_write = CURL_SOCKET_BAD; + + if(conn->data->state.drain) { + select_res |= CURL_CSELECT_IN; + DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n")); + } + + if(!select_res) /* Call for select()/poll() only, if read/write/error + status is not known. */ + select_res = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0); + + if(select_res == CURL_CSELECT_ERR) { + failf(data, "select/poll returned error"); + return CURLE_SEND_ERROR; + } + + /* We go ahead and do a read if we have a readable socket or if + the stream was rewound (in which case we have data in a + buffer) */ + if((k->keepon & KEEP_RECV) && + ((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) { + + result = readwrite_data(data, conn, k, &didwhat, done, comeback); + if(result || *done) + return result; + } + + /* If we still have writing to do, we check if we have a writable socket. */ + if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) { + /* write */ + + result = readwrite_upload(data, conn, &didwhat); + if(result) + return result; + } + + k->now = Curl_now(); + if(didwhat) { + ; + } + else { + /* no read no write, this is a timeout? */ + if(k->exp100 == EXP100_AWAITING_CONTINUE) { + /* This should allow some time for the header to arrive, but only a + very short time as otherwise it'll be too much wasted time too + often. */ + + /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status": + + Therefore, when a client sends this header field to an origin server + (possibly via a proxy) from which it has never seen a 100 (Continue) + status, the client SHOULD NOT wait for an indefinite period before + sending the request body. + + */ + + timediff_t ms = Curl_timediff(k->now, k->start100); + if(ms >= data->set.expect_100_timeout) { + /* we've waited long enough, continue anyway */ + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + infof(data, "Done waiting for 100-continue\n"); + } + } + } + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, k->now); + if(result) + return result; + + if(k->keepon) { + if(0 > Curl_timeleft(data, &k->now, FALSE)) { + if(k->size != -1) { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_timediff(k->now, data->progress.t_startsingle), + k->bytecount, k->size); + } + else { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_timediff(k->now, data->progress.t_startsingle), + k->bytecount); + } + return CURLE_OPERATION_TIMEDOUT; + } + } + else { + /* + * The transfer has been performed. Just make some general checks before + * returning. + */ + + if(!(data->set.opt_no_body) && (k->size != -1) && + (k->bytecount != k->size) && +#ifdef CURL_DO_LINEEND_CONV + /* Most FTP servers don't adjust their file SIZE response for CRLFs, + so we'll check to see if the discrepancy can be explained + by the number of CRLFs we've changed to LFs. + */ + (k->bytecount != (k->size + data->state.crlf_conversions)) && +#endif /* CURL_DO_LINEEND_CONV */ + !k->newurl) { + failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T + " bytes remaining to read", k->size - k->bytecount); + return CURLE_PARTIAL_FILE; + } + if(!(data->set.opt_no_body) && k->chunk && + (conn->chunk.state != CHUNK_STOP)) { + /* + * In chunked mode, return an error if the connection is closed prior to + * the empty (terminating) chunk is read. + * + * The condition above used to check for + * conn->proto.http->chunk.datasize != 0 which is true after reading + * *any* chunk, not just the empty chunk. + * + */ + failf(data, "transfer closed with outstanding read data remaining"); + return CURLE_PARTIAL_FILE; + } + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + } + + /* Now update the "done" boolean we return */ + *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND| + KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE; + + return CURLE_OK; +} + +/* + * Curl_single_getsock() gets called by the multi interface code when the app + * has requested to get the sockets for the current connection. This function + * will then be called once for every connection that the multi interface + * keeps track of. This function will only be called for connections that are + * in the proper state to have this information available. + */ +int Curl_single_getsock(const struct connectdata *conn, + curl_socket_t *sock, /* points to numsocks number + of sockets */ + int numsocks) +{ + const struct Curl_easy *data = conn->data; + int bitmap = GETSOCK_BLANK; + unsigned sockindex = 0; + + if(conn->handler->perform_getsock) + return conn->handler->perform_getsock(conn, sock, numsocks); + + if(numsocks < 2) + /* simple check but we might need two slots */ + return GETSOCK_BLANK; + + /* don't include HOLD and PAUSE connections */ + if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) { + + DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD); + + bitmap |= GETSOCK_READSOCK(sockindex); + sock[sockindex] = conn->sockfd; + } + + /* don't include HOLD and PAUSE connections */ + if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) { + + if((conn->sockfd != conn->writesockfd) || + bitmap == GETSOCK_BLANK) { + /* only if they are not the same socket and we have a readable + one, we increase index */ + if(bitmap != GETSOCK_BLANK) + sockindex++; /* increase index if we need two entries */ + + DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD); + + sock[sockindex] = conn->writesockfd; + } + + bitmap |= GETSOCK_WRITESOCK(sockindex); + } + + return bitmap; +} + +/* Curl_init_CONNECT() gets called each time the handle switches to CONNECT + which means this gets called once for each subsequent redirect etc */ +void Curl_init_CONNECT(struct Curl_easy *data) +{ + data->state.fread_func = data->set.fread_func_set; + data->state.in = data->set.in_set; +} + +/* + * Curl_pretransfer() is called immediately before a transfer starts, and only + * once for one transfer no matter if it has redirects or do multi-pass + * authentication etc. + */ +CURLcode Curl_pretransfer(struct Curl_easy *data) +{ + CURLcode result; + + if(!data->change.url && !data->set.uh) { + /* we can't do anything without URL */ + failf(data, "No URL set!"); + return CURLE_URL_MALFORMAT; + } + + /* since the URL may have been redirected in a previous use of this handle */ + if(data->change.url_alloc) { + /* the already set URL is allocated, free it first! */ + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + + if(!data->change.url && data->set.uh) { + CURLUcode uc; + uc = curl_url_get(data->set.uh, + CURLUPART_URL, &data->set.str[STRING_SET_URL], 0); + if(uc) { + failf(data, "No URL set!"); + return CURLE_URL_MALFORMAT; + } + } + + data->change.url = data->set.str[STRING_SET_URL]; + + /* Init the SSL session ID cache here. We do it here since we want to do it + after the *_setopt() calls (that could specify the size of the cache) but + before any transfer takes place. */ + result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions); + if(result) + return result; + + data->state.wildcardmatch = data->set.wildcard_enabled; + data->set.followlocation = 0; /* reset the location-follow counter */ + data->state.this_is_a_follow = FALSE; /* reset this */ + data->state.errorbuf = FALSE; /* no error has occurred */ + data->state.httpversion = 0; /* don't assume any particular server version */ + + data->state.authproblem = FALSE; + data->state.authhost.want = data->set.httpauth; + data->state.authproxy.want = data->set.proxyauth; + Curl_safefree(data->info.wouldredirect); + data->info.wouldredirect = NULL; + + if(data->set.httpreq == HTTPREQ_PUT) + data->state.infilesize = data->set.filesize; + else if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { + data->state.infilesize = data->set.postfieldsize; + if(data->set.postfields && (data->state.infilesize == -1)) + data->state.infilesize = (curl_off_t)strlen(data->set.postfields); + } + else + data->state.infilesize = 0; + + /* If there is a list of cookie files to read, do it now! */ + if(data->change.cookielist) + Curl_cookie_loadfiles(data); + + /* If there is a list of host pairs to deal with */ + if(data->change.resolve) + result = Curl_loadhostpairs(data); + + if(!result) { + /* Allow data->set.use_port to set which port to use. This needs to be + * disabled for example when we follow Location: headers to URLs using + * different ports! */ + data->state.allow_port = TRUE; + +#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) + /************************************************************* + * Tell signal handler to ignore SIGPIPE + *************************************************************/ + if(!data->set.no_signal) + data->state.prev_signal = signal(SIGPIPE, SIG_IGN); +#endif + + Curl_initinfo(data); /* reset session-specific information "variables" */ + Curl_pgrsResetTransferSizes(data); + Curl_pgrsStartNow(data); + + /* In case the handle is re-used and an authentication method was picked + in the session we need to make sure we only use the one(s) we now + consider to be fine */ + data->state.authhost.picked &= data->state.authhost.want; + data->state.authproxy.picked &= data->state.authproxy.want; + +#ifndef CURL_DISABLE_FTP + if(data->state.wildcardmatch) { + struct WildcardData *wc = &data->wildcard; + if(wc->state < CURLWC_INIT) { + result = Curl_wildcard_init(wc); /* init wildcard structures */ + if(result) + return CURLE_OUT_OF_MEMORY; + } + } +#endif + } + + return result; +} + +/* + * Curl_posttransfer() is called immediately after a transfer ends + */ +CURLcode Curl_posttransfer(struct Curl_easy *data) +{ +#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) + /* restore the signal handler for SIGPIPE before we get back */ + if(!data->set.no_signal) + signal(SIGPIPE, data->state.prev_signal); +#else + (void)data; /* unused parameter */ +#endif + + return CURLE_OK; +} + +/* + * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string + * as given by the remote server and set up the new URL to request. + * + * This function DOES NOT FREE the given url. + */ +CURLcode Curl_follow(struct Curl_easy *data, + char *newurl, /* the Location: string */ + followtype type) /* see transfer.h */ +{ +#ifdef CURL_DISABLE_HTTP + (void)data; + (void)newurl; + (void)type; + /* Location: following will not happen when HTTP is disabled */ + return CURLE_TOO_MANY_REDIRECTS; +#else + + /* Location: redirect */ + bool disallowport = FALSE; + bool reachedmax = FALSE; + CURLUcode uc; + + if(type == FOLLOW_REDIR) { + if((data->set.maxredirs != -1) && + (data->set.followlocation >= data->set.maxredirs)) { + reachedmax = TRUE; + type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected + to URL */ + } + else { + /* mark the next request as a followed location: */ + data->state.this_is_a_follow = TRUE; + + data->set.followlocation++; /* count location-followers */ + + if(data->set.http_auto_referer) { + /* We are asked to automatically set the previous URL as the referer + when we get the next URL. We pick the ->url field, which may or may + not be 100% correct */ + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + + data->change.referer = strdup(data->change.url); + if(!data->change.referer) + return CURLE_OUT_OF_MEMORY; + data->change.referer_alloc = TRUE; /* yes, free this later */ + } + } + } + + if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN)) + /* This is an absolute URL, don't allow the custom port number */ + disallowport = TRUE; + + DEBUGASSERT(data->state.uh); + uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, + (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME : 0); + if(uc) { + if(type != FOLLOW_FAKE) + return Curl_uc_to_curlcode(uc); + + /* the URL could not be parsed for some reason, but since this is FAKE + mode, just duplicate the field as-is */ + newurl = strdup(newurl); + if(!newurl) + return CURLE_OUT_OF_MEMORY; + } + else { + + uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + } + + if(type == FOLLOW_FAKE) { + /* we're only figuring out the new url if we would've followed locations + but now we're done so we can get out! */ + data->info.wouldredirect = newurl; + + if(reachedmax) { + failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs); + return CURLE_TOO_MANY_REDIRECTS; + } + return CURLE_OK; + } + + if(disallowport) + data->state.allow_port = FALSE; + + if(data->change.url_alloc) + Curl_safefree(data->change.url); + + data->change.url = newurl; + data->change.url_alloc = TRUE; + + infof(data, "Issue another request to this URL: '%s'\n", data->change.url); + + /* + * We get here when the HTTP code is 300-399 (and 401). We need to perform + * differently based on exactly what return code there was. + * + * News from 7.10.6: we can also get here on a 401 or 407, in case we act on + * a HTTP (proxy-) authentication scheme other than Basic. + */ + switch(data->info.httpcode) { + /* 401 - Act on a WWW-Authenticate, we keep on moving and do the + Authorization: XXXX header in the HTTP request code snippet */ + /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the + Proxy-Authorization: XXXX header in the HTTP request code snippet */ + /* 300 - Multiple Choices */ + /* 306 - Not used */ + /* 307 - Temporary Redirect */ + default: /* for all above (and the unknown ones) */ + /* Some codes are explicitly mentioned since I've checked RFC2616 and they + * seem to be OK to POST to. + */ + break; + case 301: /* Moved Permanently */ + /* (quote from RFC7231, section 6.4.2) + * + * Note: For historical reasons, a user agent MAY change the request + * method from POST to GET for the subsequent request. If this + * behavior is undesired, the 307 (Temporary Redirect) status code + * can be used instead. + * + * ---- + * + * Many webservers expect this, so these servers often answers to a POST + * request with an error page. To be sure that libcurl gets the page that + * most user agents would get, libcurl has to force GET. + * + * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and + * can be overridden with CURLOPT_POSTREDIR. + */ + if((data->set.httpreq == HTTPREQ_POST + || data->set.httpreq == HTTPREQ_POST_FORM + || data->set.httpreq == HTTPREQ_POST_MIME) + && !(data->set.keep_post & CURL_REDIR_POST_301)) { + infof(data, "Switch from POST to GET\n"); + data->set.httpreq = HTTPREQ_GET; + } + break; + case 302: /* Found */ + /* (quote from RFC7231, section 6.4.3) + * + * Note: For historical reasons, a user agent MAY change the request + * method from POST to GET for the subsequent request. If this + * behavior is undesired, the 307 (Temporary Redirect) status code + * can be used instead. + * + * ---- + * + * Many webservers expect this, so these servers often answers to a POST + * request with an error page. To be sure that libcurl gets the page that + * most user agents would get, libcurl has to force GET. + * + * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and + * can be overridden with CURLOPT_POSTREDIR. + */ + if((data->set.httpreq == HTTPREQ_POST + || data->set.httpreq == HTTPREQ_POST_FORM + || data->set.httpreq == HTTPREQ_POST_MIME) + && !(data->set.keep_post & CURL_REDIR_POST_302)) { + infof(data, "Switch from POST to GET\n"); + data->set.httpreq = HTTPREQ_GET; + } + break; + + case 303: /* See Other */ + /* Disable both types of POSTs, unless the user explicitly + asks for POST after POST */ + if(data->set.httpreq != HTTPREQ_GET + && !(data->set.keep_post & CURL_REDIR_POST_303)) { + data->set.httpreq = HTTPREQ_GET; /* enforce GET request */ + infof(data, "Disables POST, goes with %s\n", + data->set.opt_no_body?"HEAD":"GET"); + } + break; + case 304: /* Not Modified */ + /* 304 means we did a conditional request and it was "Not modified". + * We shouldn't get any Location: header in this response! + */ + break; + case 305: /* Use Proxy */ + /* (quote from RFC2616, section 10.3.6): + * "The requested resource MUST be accessed through the proxy given + * by the Location field. The Location field gives the URI of the + * proxy. The recipient is expected to repeat this single request + * via the proxy. 305 responses MUST only be generated by origin + * servers." + */ + break; + } + Curl_pgrsTime(data, TIMER_REDIRECT); + Curl_pgrsResetTransferSizes(data); + + return CURLE_OK; +#endif /* CURL_DISABLE_HTTP */ +} + +/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted. + + NOTE: that the *url is malloc()ed. */ +CURLcode Curl_retry_request(struct connectdata *conn, + char **url) +{ + struct Curl_easy *data = conn->data; + bool retry = FALSE; + *url = NULL; + + /* if we're talking upload, we can't do the checks below, unless the protocol + is HTTP as when uploading over HTTP we will still get a response */ + if(data->set.upload && + !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP))) + return CURLE_OK; + + if((data->req.bytecount + data->req.headerbytecount == 0) && + conn->bits.reuse && + (!data->set.opt_no_body + || (conn->handler->protocol & PROTO_FAMILY_HTTP)) && + (data->set.rtspreq != RTSPREQ_RECEIVE)) + /* We got no data, we attempted to re-use a connection. For HTTP this + can be a retry so we try again regardless if we expected a body. + For other protocols we only try again only if we expected a body. + + This might happen if the connection was left alive when we were + done using it before, but that was closed when we wanted to read from + it again. Bad luck. Retry the same request on a fresh connect! */ + retry = TRUE; + else if(data->state.refused_stream && + (data->req.bytecount + data->req.headerbytecount == 0) ) { + /* This was sent on a refused stream, safe to rerun. A refused stream + error can typically only happen on HTTP/2 level if the stream is safe + to issue again, but the nghttp2 API can deliver the message to other + streams as well, which is why this adds the check the data counters + too. */ + infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n"); + data->state.refused_stream = FALSE; /* clear again */ + retry = TRUE; + } + if(retry) { + infof(conn->data, "Connection died, retrying a fresh connect\n"); + *url = strdup(conn->data->change.url); + if(!*url) + return CURLE_OUT_OF_MEMORY; + + connclose(conn, "retry"); /* close this connection */ + conn->bits.retry = TRUE; /* mark this as a connection we're about + to retry. Marking it this way should + prevent i.e HTTP transfers to return + error just because nothing has been + transferred! */ + + + if(conn->handler->protocol&PROTO_FAMILY_HTTP) { + if(data->req.writebytecount) { + CURLcode result = Curl_readrewind(conn); + if(result) { + Curl_safefree(*url); + return result; + } + } + } + } + return CURLE_OK; +} + +/* + * Curl_setup_transfer() is called to setup some basic properties for the + * upcoming transfer. + */ +void +Curl_setup_transfer( + struct Curl_easy *data, /* transfer */ + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + int writesockindex /* socket index to write to, it may very well be + the same we read from. -1 disables */ + ) +{ + struct SingleRequest *k = &data->req; + struct connectdata *conn = data->conn; + DEBUGASSERT(conn != NULL); + DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); + + if(conn->bits.multiplex || conn->httpversion == 20) { + /* when multiplexing, the read/write sockets need to be the same! */ + conn->sockfd = sockindex == -1 ? + ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) : + conn->sock[sockindex]; + conn->writesockfd = conn->sockfd; + } + else { + conn->sockfd = sockindex == -1 ? + CURL_SOCKET_BAD : conn->sock[sockindex]; + conn->writesockfd = writesockindex == -1 ? + CURL_SOCKET_BAD:conn->sock[writesockindex]; + } + k->getheader = getheader; + + k->size = size; + + /* The code sequence below is placed in this function just because all + necessary input is not always known in do_complete() as this function may + be called after that */ + + if(!k->getheader) { + k->header = FALSE; + if(size > 0) + Curl_pgrsSetDownloadSize(data, size); + } + /* we want header and/or body, if neither then don't do this! */ + if(k->getheader || !data->set.opt_no_body) { + + if(sockindex != -1) + k->keepon |= KEEP_RECV; + + if(writesockindex != -1) { + struct HTTP *http = data->req.protop; + /* HTTP 1.1 magic: + + Even if we require a 100-return code before uploading data, we might + need to write data before that since the REQUEST may not have been + finished sent off just yet. + + Thus, we must check if the request has been sent before we set the + state info where we wait for the 100-return code + */ + if((data->state.expect100header) && + (conn->handler->protocol&PROTO_FAMILY_HTTP) && + (http->sending == HTTPSEND_BODY)) { + /* wait with write until we either got 100-continue or a timeout */ + k->exp100 = EXP100_AWAITING_CONTINUE; + k->start100 = Curl_now(); + + /* Set a timeout for the multi interface. Add the inaccuracy margin so + that we don't fire slightly too early and get denied to run. */ + Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT); + } + else { + if(data->state.expect100header) + /* when we've sent off the rest of the headers, we must await a + 100-continue but first finish sending the request */ + k->exp100 = EXP100_SENDING_REQUEST; + + /* enable the write bit when we're not waiting for continue */ + k->keepon |= KEEP_SEND; + } + } /* if(writesockindex != -1) */ + } /* if(k->getheader || !data->set.opt_no_body) */ + +} diff --git a/libcurl/lib/transfer.h b/libcurl/lib/transfer.h new file mode 100644 index 0000000..da36f19 --- /dev/null +++ b/libcurl/lib/transfer.h @@ -0,0 +1,73 @@ +#ifndef HEADER_CURL_TRANSFER_H +#define HEADER_CURL_TRANSFER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define Curl_headersep(x) ((((x)==':') || ((x)==';'))) +char *Curl_checkheaders(const struct connectdata *conn, + const char *thisheader); + +void Curl_init_CONNECT(struct Curl_easy *data); + +CURLcode Curl_pretransfer(struct Curl_easy *data); +CURLcode Curl_posttransfer(struct Curl_easy *data); + +typedef enum { + FOLLOW_NONE, /* not used within the function, just a placeholder to + allow initing to this */ + FOLLOW_FAKE, /* only records stuff, not actually following */ + FOLLOW_RETRY, /* set if this is a request retry as opposed to a real + redirect following */ + FOLLOW_REDIR, /* a full true redirect */ + FOLLOW_LAST /* never used */ +} followtype; + +CURLcode Curl_follow(struct Curl_easy *data, char *newurl, + followtype type); +CURLcode Curl_readwrite(struct connectdata *conn, + struct Curl_easy *data, bool *done, + bool *comeback); +int Curl_single_getsock(const struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +CURLcode Curl_readrewind(struct connectdata *conn); +CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, + size_t *nreadp); +CURLcode Curl_retry_request(struct connectdata *conn, char **url); +bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc); +CURLcode Curl_get_upload_buffer(struct Curl_easy *data); + +CURLcode Curl_done_sending(struct connectdata *conn, + struct SingleRequest *k); + +/* This sets up a forthcoming transfer */ +void +Curl_setup_transfer (struct Curl_easy *data, + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + int writesockindex /* socket index to write to. May be + the same we read from. -1 + disables */ + ); + +#endif /* HEADER_CURL_TRANSFER_H */ diff --git a/libcurl/lib/url.c b/libcurl/lib/url.c new file mode 100644 index 0000000..2b47b23 --- /dev/null +++ b/libcurl/lib/url.c @@ -0,0 +1,4195 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_IPHLPAPI_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef __VMS +#include +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + +#ifndef HAVE_SOCKET +#error "We can't compile without socket() support!" +#endif + +#include + +#ifdef USE_LIBIDN2 +#include + +#elif defined(USE_WIN32_IDN) +/* prototype for curl_win32_idn_to_ascii() */ +bool curl_win32_idn_to_ascii(const char *in, char **out); +#endif /* USE_LIBIDN2 */ + +#include "urldata.h" +#include "netrc.h" + +#include "formdata.h" +#include "mime.h" +#include "vtls/vtls.h" +#include "hostip.h" +#include "transfer.h" +#include "sendf.h" +#include "progress.h" +#include "cookie.h" +#include "strcase.h" +#include "strerror.h" +#include "escape.h" +#include "strtok.h" +#include "share.h" +#include "content_encoding.h" +#include "http_digest.h" +#include "http_negotiate.h" +#include "select.h" +#include "multiif.h" +#include "easyif.h" +#include "speedcheck.h" +#include "warnless.h" +#include "non-ascii.h" +#include "inet_pton.h" +#include "getinfo.h" +#include "urlapi-int.h" +#include "system_win32.h" + +/* And now for the protocols */ +#include "ftp.h" +#include "dict.h" +#include "telnet.h" +#include "tftp.h" +#include "http.h" +#include "http2.h" +#include "file.h" +#include "curl_ldap.h" +#include "ssh.h" +#include "imap.h" +#include "url.h" +#include "connect.h" +#include "inet_ntop.h" +#include "http_ntlm.h" +#include "socks.h" +#include "curl_rtmp.h" +#include "gopher.h" +#include "http_proxy.h" +#include "conncache.h" +#include "multihandle.h" +#include "dotdot.h" +#include "strdup.h" +#include "setopt.h" +#include "altsvc.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static void conn_free(struct connectdata *conn); +static void free_idnconverted_hostname(struct hostname *host); +static unsigned int get_protocol_family(unsigned int protocol); + +/* Some parts of the code (e.g. chunked encoding) assume this buffer has at + * more than just a few bytes to play with. Don't let it become too small or + * bad things will happen. + */ +#if READBUFFER_SIZE < READBUFFER_MIN +# error READBUFFER_SIZE is too small +#endif + + +/* + * Protocol table. + */ + +static const struct Curl_handler * const protocols[] = { + +#ifndef CURL_DISABLE_HTTP + &Curl_handler_http, +#endif + +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_https, +#endif + +#ifndef CURL_DISABLE_FTP + &Curl_handler_ftp, +#endif + +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + &Curl_handler_ftps, +#endif + +#ifndef CURL_DISABLE_TELNET + &Curl_handler_telnet, +#endif + +#ifndef CURL_DISABLE_DICT + &Curl_handler_dict, +#endif + +#ifndef CURL_DISABLE_LDAP + &Curl_handler_ldap, +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + &Curl_handler_ldaps, +#endif +#endif + +#ifndef CURL_DISABLE_FILE + &Curl_handler_file, +#endif + +#ifndef CURL_DISABLE_TFTP + &Curl_handler_tftp, +#endif + +#if defined(USE_SSH) + &Curl_handler_scp, +#endif + +#if defined(USE_SSH) + &Curl_handler_sftp, +#endif + +#ifndef CURL_DISABLE_IMAP + &Curl_handler_imap, +#ifdef USE_SSL + &Curl_handler_imaps, +#endif +#endif + +#ifndef CURL_DISABLE_POP3 + &Curl_handler_pop3, +#ifdef USE_SSL + &Curl_handler_pop3s, +#endif +#endif + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) && \ + (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)) + &Curl_handler_smb, +#ifdef USE_SSL + &Curl_handler_smbs, +#endif +#endif + +#ifndef CURL_DISABLE_SMTP + &Curl_handler_smtp, +#ifdef USE_SSL + &Curl_handler_smtps, +#endif +#endif + +#ifndef CURL_DISABLE_RTSP + &Curl_handler_rtsp, +#endif + +#ifndef CURL_DISABLE_GOPHER + &Curl_handler_gopher, +#endif + +#ifdef USE_LIBRTMP + &Curl_handler_rtmp, + &Curl_handler_rtmpt, + &Curl_handler_rtmpe, + &Curl_handler_rtmpte, + &Curl_handler_rtmps, + &Curl_handler_rtmpts, +#endif + + (struct Curl_handler *) NULL +}; + +/* + * Dummy handler for undefined protocol schemes. + */ + +static const struct Curl_handler Curl_handler_dummy = { + "", /* scheme */ + ZERO_NULL, /* setup_connection */ + ZERO_NULL, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ + 0, /* defport */ + 0, /* protocol */ + PROTOPT_NONE /* flags */ +}; + +void Curl_freeset(struct Curl_easy *data) +{ + /* Free all dynamic strings stored in the data->set substructure. */ + enum dupstring i; + for(i = (enum dupstring)0; i < STRING_LAST; i++) { + Curl_safefree(data->set.str[i]); + } + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + data->change.referer = NULL; + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + data->change.url = NULL; + + Curl_mime_cleanpart(&data->set.mimepost); +} + +/* free the URL pieces */ +static void up_free(struct Curl_easy *data) +{ + struct urlpieces *up = &data->state.up; + Curl_safefree(up->scheme); + Curl_safefree(up->hostname); + Curl_safefree(up->port); + Curl_safefree(up->user); + Curl_safefree(up->password); + Curl_safefree(up->options); + Curl_safefree(up->path); + Curl_safefree(up->query); + curl_url_cleanup(data->state.uh); + data->state.uh = NULL; +} + +/* + * This is the internal function curl_easy_cleanup() calls. This should + * cleanup and free all resources associated with this sessionhandle. + * + * NOTE: if we ever add something that attempts to write to a socket or + * similar here, we must ignore SIGPIPE first. It is currently only done + * when curl_easy_perform() is invoked. + */ + +CURLcode Curl_close(struct Curl_easy *data) +{ + struct Curl_multi *m; + + if(!data) + return CURLE_OK; + + Curl_expire_clear(data); /* shut off timers */ + + m = data->multi; + if(m) + /* This handle is still part of a multi handle, take care of this first + and detach this handle from there. */ + curl_multi_remove_handle(data->multi, data); + + if(data->multi_easy) { + /* when curl_easy_perform() is used, it creates its own multi handle to + use and this is the one */ + curl_multi_cleanup(data->multi_easy); + data->multi_easy = NULL; + } + + /* Destroy the timeout list that is held in the easy handle. It is + /normally/ done by curl_multi_remove_handle() but this is "just in + case" */ + Curl_llist_destroy(&data->state.timeoutlist, NULL); + + data->magic = 0; /* force a clear AFTER the possibly enforced removal from + the multi handle, since that function uses the magic + field! */ + + if(data->state.rangestringalloc) + free(data->state.range); + + /* freed here just in case DONE wasn't called */ + Curl_free_request_state(data); + + /* Close down all open SSL info and sessions */ + Curl_ssl_close_all(data); + Curl_safefree(data->state.first_host); + Curl_safefree(data->state.scratch); + Curl_ssl_free_certinfo(data); + + /* Cleanup possible redirect junk */ + free(data->req.newurl); + data->req.newurl = NULL; + + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + data->change.referer = NULL; + + up_free(data); + Curl_safefree(data->state.buffer); + Curl_safefree(data->state.headerbuff); + Curl_safefree(data->state.ulbuf); + Curl_flush_cookies(data, 1); +#ifdef USE_ALTSVC + Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]); + Curl_altsvc_cleanup(data->asi); + data->asi = NULL; +#endif +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + Curl_http_auth_cleanup_digest(data); +#endif + Curl_safefree(data->info.contenttype); + Curl_safefree(data->info.wouldredirect); + + /* this destroys the channel and we cannot use it anymore after this */ + Curl_resolver_cleanup(data->state.resolver); + + Curl_http2_cleanup_dependencies(data); + Curl_convert_close(data); + + /* No longer a dirty share, if it exists */ + if(data->share) { + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + data->share->dirty--; + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + } + + /* destruct wildcard structures if it is needed */ + Curl_wildcard_dtor(&data->wildcard); + Curl_freeset(data); + free(data); + return CURLE_OK; +} + +/* + * Initialize the UserDefined fields within a Curl_easy. + * This may be safely called on a new or existing Curl_easy. + */ +CURLcode Curl_init_userdefined(struct Curl_easy *data) +{ + struct UserDefined *set = &data->set; + CURLcode result = CURLE_OK; + + set->out = stdout; /* default output to stdout */ + set->in_set = stdin; /* default input from stdin */ + set->err = stderr; /* default stderr to stderr */ + + /* use fwrite as default function to store output */ + set->fwrite_func = (curl_write_callback)fwrite; + + /* use fread as default function to read input */ + set->fread_func_set = (curl_read_callback)fread; + set->is_fread_set = 0; + set->is_fwrite_set = 0; + + set->seek_func = ZERO_NULL; + set->seek_client = ZERO_NULL; + + /* conversion callbacks for non-ASCII hosts */ + set->convfromnetwork = ZERO_NULL; + set->convtonetwork = ZERO_NULL; + set->convfromutf8 = ZERO_NULL; + + set->filesize = -1; /* we don't know the size */ + set->postfieldsize = -1; /* unknown size */ + set->maxredirs = -1; /* allow any amount by default */ + + set->httpreq = HTTPREQ_GET; /* Default HTTP request */ + set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */ +#ifndef CURL_DISABLE_FTP + set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ + set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */ + set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */ + set->ftp_filemethod = FTPFILE_MULTICWD; +#endif + set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ + + /* Set the default size of the SSL session ID cache */ + set->general_ssl.max_ssl_sessions = 5; + + set->proxyport = 0; + set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ + set->httpauth = CURLAUTH_BASIC; /* defaults to basic */ + set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */ + + /* SOCKS5 proxy auth defaults to username/password + GSS-API */ + set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI; + + /* make libcurl quiet by default: */ + set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */ + + Curl_mime_initpart(&set->mimepost, data); + + /* + * libcurl 7.10 introduced SSL verification *by default*! This needs to be + * switched off unless wanted. + */ + set->ssl.primary.verifypeer = TRUE; + set->ssl.primary.verifyhost = TRUE; +#ifdef USE_TLS_SRP + set->ssl.authtype = CURL_TLSAUTH_NONE; +#endif + set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth + type */ + set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by + default */ + set->proxy_ssl = set->ssl; + + set->new_file_perms = 0644; /* Default permissions */ + set->new_directory_perms = 0755; /* Default permissions */ + + /* for the *protocols fields we don't use the CURLPROTO_ALL convenience + define since we internally only use the lower 16 bits for the passed + in bitmask to not conflict with the private bits */ + set->allowed_protocols = CURLPROTO_ALL; + set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP | + CURLPROTO_FTPS; + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + /* + * disallow unprotected protection negotiation NEC reference implementation + * seem not to follow rfc1961 section 4.3/4.4 + */ + set->socks5_gssapi_nec = FALSE; +#endif + + /* Set the default CA cert bundle/path detected/specified at build time. + * + * If Schannel is the selected SSL backend then these locations are + * ignored. We allow setting CA location for schannel only when explicitly + * specified by the user via CURLOPT_CAINFO / --cacert. + */ + if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) { +#if defined(CURL_CA_BUNDLE) + result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE); + if(result) + return result; + + result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], + CURL_CA_BUNDLE); + if(result) + return result; +#endif +#if defined(CURL_CA_PATH) + result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH); + if(result) + return result; + + result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH); + if(result) + return result; +#endif + } + + set->wildcard_enabled = FALSE; + set->chunk_bgn = ZERO_NULL; + set->chunk_end = ZERO_NULL; + set->tcp_keepalive = FALSE; + set->tcp_keepintvl = 60; + set->tcp_keepidle = 60; + set->tcp_fastopen = FALSE; + set->tcp_nodelay = TRUE; + set->ssl_enable_npn = TRUE; + set->ssl_enable_alpn = TRUE; + set->expect_100_timeout = 1000L; /* Wait for a second by default. */ + set->sep_headers = TRUE; /* separated header lists by default */ + set->buffer_size = READBUFFER_SIZE; + set->upload_buffer_size = UPLOADBUFFER_DEFAULT; + set->happy_eyeballs_timeout = CURL_HET_DEFAULT; + set->fnmatch = ZERO_NULL; + set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT; + set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */ + set->maxage_conn = 118; + set->http09_allowed = TRUE; + set->httpversion = +#ifdef USE_NGHTTP2 + CURL_HTTP_VERSION_2TLS +#else + CURL_HTTP_VERSION_1_1 +#endif + ; + Curl_http2_init_userset(set); + return result; +} + +/** + * Curl_open() + * + * @param curl is a pointer to a sessionhandle pointer that gets set by this + * function. + * @return CURLcode + */ + +CURLcode Curl_open(struct Curl_easy **curl) +{ + CURLcode result; + struct Curl_easy *data; + + /* Very simple start-up: alloc the struct, init it with zeroes and return */ + data = calloc(1, sizeof(struct Curl_easy)); + if(!data) { + /* this is a very serious error */ + DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n")); + return CURLE_OUT_OF_MEMORY; + } + + data->magic = CURLEASY_MAGIC_NUMBER; + + result = Curl_resolver_init(data, &data->state.resolver); + if(result) { + DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); + free(data); + return result; + } + + /* We do some initial setup here, all those fields that can't be just 0 */ + + data->state.buffer = malloc(READBUFFER_SIZE + 1); + if(!data->state.buffer) { + DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + else { + data->state.headerbuff = malloc(HEADERSIZE); + if(!data->state.headerbuff) { + DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + else { + result = Curl_init_userdefined(data); + + data->state.headersize = HEADERSIZE; + Curl_convert_init(data); + Curl_initinfo(data); + + /* most recent connection is not yet defined */ + data->state.lastconnect = NULL; + + data->progress.flags |= PGRS_HIDE; + data->state.current_speed = -1; /* init to negative == impossible */ + + Curl_http2_init_state(&data->state); + } + } + + if(result) { + Curl_resolver_cleanup(data->state.resolver); + free(data->state.buffer); + free(data->state.headerbuff); + Curl_freeset(data); + free(data); + data = NULL; + } + else + *curl = data; + + return result; +} + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND +static void conn_reset_postponed_data(struct connectdata *conn, int num) +{ + struct postponed_data * const psnd = &(conn->postponed[num]); + if(psnd->buffer) { + DEBUGASSERT(psnd->allocated_size > 0); + DEBUGASSERT(psnd->recv_size <= psnd->allocated_size); + DEBUGASSERT(psnd->recv_size ? + (psnd->recv_processed < psnd->recv_size) : + (psnd->recv_processed == 0)); + DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD); + free(psnd->buffer); + psnd->buffer = NULL; + psnd->allocated_size = 0; + psnd->recv_size = 0; + psnd->recv_processed = 0; +#ifdef DEBUGBUILD + psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */ +#endif /* DEBUGBUILD */ + } + else { + DEBUGASSERT(psnd->allocated_size == 0); + DEBUGASSERT(psnd->recv_size == 0); + DEBUGASSERT(psnd->recv_processed == 0); + DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD); + } +} + +static void conn_reset_all_postponed_data(struct connectdata *conn) +{ + conn_reset_postponed_data(conn, 0); + conn_reset_postponed_data(conn, 1); +} +#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ +/* Use "do-nothing" macro instead of function when workaround not used */ +#define conn_reset_all_postponed_data(c) do {} WHILE_FALSE +#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ + + +static void conn_shutdown(struct connectdata *conn) +{ + if(!conn) + return; + + infof(conn->data, "Closing connection %ld\n", conn->connection_id); + DEBUGASSERT(conn->data); + + /* possible left-overs from the async name resolvers */ + Curl_resolver_cancel(conn); + + /* close the SSL stuff before we close any sockets since they will/may + write to the sockets */ + Curl_ssl_close(conn, FIRSTSOCKET); + Curl_ssl_close(conn, SECONDARYSOCKET); + + /* close possibly still open sockets */ + if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) + Curl_closesocket(conn, conn->sock[FIRSTSOCKET]); + if(CURL_SOCKET_BAD != conn->tempsock[0]) + Curl_closesocket(conn, conn->tempsock[0]); + if(CURL_SOCKET_BAD != conn->tempsock[1]) + Curl_closesocket(conn, conn->tempsock[1]); + + /* unlink ourselves. this should be called last since other shutdown + procedures need a valid conn->data and this may clear it. */ + Curl_conncache_remove_conn(conn->data, conn, TRUE); +} + +static void conn_free(struct connectdata *conn) +{ + if(!conn) + return; + + free_idnconverted_hostname(&conn->host); + free_idnconverted_hostname(&conn->conn_to_host); + free_idnconverted_hostname(&conn->http_proxy.host); + free_idnconverted_hostname(&conn->socks_proxy.host); + + Curl_safefree(conn->user); + Curl_safefree(conn->passwd); + Curl_safefree(conn->oauth_bearer); + Curl_safefree(conn->options); + Curl_safefree(conn->http_proxy.user); + Curl_safefree(conn->socks_proxy.user); + Curl_safefree(conn->http_proxy.passwd); + Curl_safefree(conn->socks_proxy.passwd); + Curl_safefree(conn->allocptr.proxyuserpwd); + Curl_safefree(conn->allocptr.uagent); + Curl_safefree(conn->allocptr.userpwd); + Curl_safefree(conn->allocptr.accept_encoding); + Curl_safefree(conn->allocptr.te); + Curl_safefree(conn->allocptr.rangeline); + Curl_safefree(conn->allocptr.ref); + Curl_safefree(conn->allocptr.host); + Curl_safefree(conn->allocptr.cookiehost); + Curl_safefree(conn->allocptr.rtsp_transport); + Curl_safefree(conn->trailer); + Curl_safefree(conn->host.rawalloc); /* host name buffer */ + Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ + Curl_safefree(conn->hostname_resolve); + Curl_safefree(conn->secondaryhostname); + Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */ + Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */ + Curl_safefree(conn->connect_state); + + conn_reset_all_postponed_data(conn); + Curl_llist_destroy(&conn->easyq, NULL); + Curl_safefree(conn->localdev); + Curl_free_primary_ssl_config(&conn->ssl_config); + Curl_free_primary_ssl_config(&conn->proxy_ssl_config); + +#ifdef USE_UNIX_SOCKETS + Curl_safefree(conn->unix_domain_socket); +#endif + +#ifdef USE_SSL + Curl_safefree(conn->ssl_extra); +#endif + free(conn); /* free all the connection oriented data */ +} + +/* + * Disconnects the given connection. Note the connection may not be the + * primary connection, like when freeing room in the connection cache or + * killing of a dead old connection. + * + * A connection needs an easy handle when closing down. We support this passed + * in separately since the connection to get closed here is often already + * disassociated from an easy handle. + * + * This function MUST NOT reset state in the Curl_easy struct if that + * isn't strictly bound to the life-time of *this* particular connection. + * + */ + +CURLcode Curl_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) +{ + if(!conn) + return CURLE_OK; /* this is closed and fine already */ + + if(!data) { + DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n")); + return CURLE_OK; + } + + /* + * If this connection isn't marked to force-close, leave it open if there + * are other users of it + */ + if(CONN_INUSE(conn) && !dead_connection) { + DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn))); + return CURLE_OK; + } + + if(conn->dns_entry != NULL) { + Curl_resolv_unlock(data, conn->dns_entry); + conn->dns_entry = NULL; + } + + Curl_hostcache_prune(data); /* kill old DNS cache entries */ + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + /* Cleanup NTLM connection-related data */ + Curl_http_auth_cleanup_ntlm(conn); +#endif +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + /* Cleanup NEGOTIATE connection-related data */ + Curl_http_auth_cleanup_negotiate(conn); +#endif + + /* the protocol specific disconnect handler and conn_shutdown need a transfer + for the connection! */ + conn->data = data; + + if(conn->bits.connect_only) + /* treat the connection as dead in CONNECT_ONLY situations */ + dead_connection = TRUE; + + if(conn->handler->disconnect) + /* This is set if protocol-specific cleanups should be made */ + conn->handler->disconnect(conn, dead_connection); + + conn_shutdown(conn); + conn_free(conn); + return CURLE_OK; +} + +/* + * This function should return TRUE if the socket is to be assumed to + * be dead. Most commonly this happens when the server has closed the + * connection due to inactivity. + */ +static bool SocketIsDead(curl_socket_t sock) +{ + int sval; + bool ret_val = TRUE; + + sval = SOCKET_READABLE(sock, 0); + if(sval == 0) + /* timeout */ + ret_val = FALSE; + + return ret_val; +} + +/* + * IsMultiplexingPossible() + * + * Return a bitmask with the available multiplexing options for the given + * requested connection. + */ +static int IsMultiplexingPossible(const struct Curl_easy *handle, + const struct connectdata *conn) +{ + int avail = 0; + + /* If a HTTP protocol and multiplexing is enabled */ + if((conn->handler->protocol & PROTO_FAMILY_HTTP) && + (!conn->bits.protoconnstart || !conn->bits.close)) { + + if(Curl_multiplex_wanted(handle->multi) && + (handle->set.httpversion >= CURL_HTTP_VERSION_2)) + /* allows HTTP/2 */ + avail |= CURLPIPE_MULTIPLEX; + } + return avail; +} + +#ifndef CURL_DISABLE_PROXY +static bool +proxy_info_matches(const struct proxy_info* data, + const struct proxy_info* needle) +{ + if((data->proxytype == needle->proxytype) && + (data->port == needle->port) && + Curl_safe_strcasecompare(data->host.name, needle->host.name)) + return TRUE; + + return FALSE; +} +#else +/* disabled, won't get called */ +#define proxy_info_matches(x,y) FALSE +#endif + +/* A connection has to have been idle for a shorter time than 'maxage_conn' to + be subject for reuse. The success rate is just too low after this. */ + +static bool conn_maxage(struct Curl_easy *data, + struct connectdata *conn, + struct curltime now) +{ + if(!conn->data) { + timediff_t idletime = Curl_timediff(now, conn->lastused); + idletime /= 1000; /* integer seconds is fine */ + + if(idletime > data->set.maxage_conn) { + infof(data, "Too old connection (%ld seconds), disconnect it\n", + idletime); + return TRUE; + } + } + return FALSE; +} + +/* + * This function checks if the given connection is dead and extracts it from + * the connection cache if so. + * + * When this is called as a Curl_conncache_foreach() callback, the connection + * cache lock is held! + * + * Returns TRUE if the connection was dead and extracted. + */ +static bool extract_if_dead(struct connectdata *conn, + struct Curl_easy *data) +{ + if(!CONN_INUSE(conn) && !conn->data) { + /* The check for a dead socket makes sense only if the connection isn't in + use */ + bool dead; + struct curltime now = Curl_now(); + if(conn_maxage(data, conn, now)) { + dead = TRUE; + } + else if(conn->handler->connection_check) { + /* The protocol has a special method for checking the state of the + connection. Use it to check if the connection is dead. */ + unsigned int state; + struct Curl_easy *olddata = conn->data; + conn->data = data; /* use this transfer for now */ + state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD); + conn->data = olddata; + dead = (state & CONNRESULT_DEAD); + } + else { + /* Use the general method for determining the death of a connection */ + dead = SocketIsDead(conn->sock[FIRSTSOCKET]); + } + + if(dead) { + infof(data, "Connection %ld seems to be dead!\n", conn->connection_id); + Curl_conncache_remove_conn(data, conn, FALSE); + return TRUE; + } + } + return FALSE; +} + +struct prunedead { + struct Curl_easy *data; + struct connectdata *extracted; +}; + +/* + * Wrapper to use extract_if_dead() function in Curl_conncache_foreach() + * + */ +static int call_extract_if_dead(struct connectdata *conn, void *param) +{ + struct prunedead *p = (struct prunedead *)param; + if(extract_if_dead(conn, p->data)) { + /* stop the iteration here, pass back the connection that was extracted */ + p->extracted = conn; + return 1; + } + return 0; /* continue iteration */ +} + +/* + * This function scans the connection cache for half-open/dead connections, + * closes and removes them. + * The cleanup is done at most once per second. + */ +static void prune_dead_connections(struct Curl_easy *data) +{ + struct curltime now = Curl_now(); + time_t elapsed = Curl_timediff(now, data->state.conn_cache->last_cleanup); + + if(elapsed >= 1000L) { + struct prunedead prune; + prune.data = data; + prune.extracted = NULL; + while(Curl_conncache_foreach(data, data->state.conn_cache, &prune, + call_extract_if_dead)) { + /* disconnect it */ + (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE); + } + data->state.conn_cache->last_cleanup = now; + } +} + +/* + * Given one filled in connection struct (named needle), this function should + * detect if there already is one that has all the significant details + * exactly the same and thus should be used instead. + * + * If there is a match, this function returns TRUE - and has marked the + * connection as 'in-use'. It must later be called with ConnectionDone() to + * return back to 'idle' (unused) state. + * + * The force_reuse flag is set if the connection must be used. + */ +static bool +ConnectionExists(struct Curl_easy *data, + struct connectdata *needle, + struct connectdata **usethis, + bool *force_reuse, + bool *waitpipe) +{ + struct connectdata *check; + struct connectdata *chosen = 0; + bool foundPendingCandidate = FALSE; + bool canmultiplex = IsMultiplexingPossible(data, needle); + struct connectbundle *bundle; + const char *hostbundle; + +#ifdef USE_NTLM + bool wantNTLMhttp = ((data->state.authhost.want & + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + (needle->handler->protocol & PROTO_FAMILY_HTTP)); + bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd && + ((data->state.authproxy.want & + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + (needle->handler->protocol & PROTO_FAMILY_HTTP))); +#endif + + *force_reuse = FALSE; + *waitpipe = FALSE; + + /* Look up the bundle with all the connections to this particular host. + Locks the connection cache, beware of early returns! */ + bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache, + &hostbundle); + if(bundle) { + /* Max pipe length is zero (unlimited) for multiplexed connections */ + struct curl_llist_element *curr; + + infof(data, "Found bundle for host %s: %p [%s]\n", + hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? + "can multiplex" : "serially")); + + /* We can't multiplex if we don't know anything about the server */ + if(canmultiplex) { + if(bundle->multiuse == BUNDLE_UNKNOWN) { + if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) { + infof(data, "Server doesn't support multiplex yet, wait\n"); + *waitpipe = TRUE; + Curl_conncache_unlock(data); + return FALSE; /* no re-use */ + } + + infof(data, "Server doesn't support multiplex (yet)\n"); + canmultiplex = FALSE; + } + if((bundle->multiuse == BUNDLE_MULTIPLEX) && + !Curl_multiplex_wanted(data->multi)) { + infof(data, "Could multiplex, but not asked to!\n"); + canmultiplex = FALSE; + } + if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { + infof(data, "Can not multiplex, even if we wanted to!\n"); + canmultiplex = FALSE; + } + } + + curr = bundle->conn_list.head; + while(curr) { + bool match = FALSE; + size_t multiplexed; + + /* + * Note that if we use a HTTP proxy in normal mode (no tunneling), we + * check connections to that proxy and not to the actual remote server. + */ + check = curr->ptr; + curr = curr->next; + + if(check->bits.connect_only) + /* connect-only connections will not be reused */ + continue; + + multiplexed = CONN_INUSE(check) && + (bundle->multiuse == BUNDLE_MULTIPLEX); + + if(canmultiplex) { + if(check->bits.protoconnstart && check->bits.close) + continue; + } + else { + if(multiplexed) { + /* can only happen within multi handles, and means that another easy + handle is using this connection */ + continue; + } + + if(Curl_resolver_asynch()) { + /* ip_addr_str[0] is NUL only if the resolving of the name hasn't + completed yet and until then we don't re-use this connection */ + if(!check->ip_addr_str[0]) { + infof(data, + "Connection #%ld is still name resolving, can't reuse\n", + check->connection_id); + continue; + } + } + + if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) || + check->bits.close) { + if(!check->bits.close) + foundPendingCandidate = TRUE; + /* Don't pick a connection that hasn't connected yet or that is going + to get closed. */ + infof(data, "Connection #%ld isn't open enough, can't reuse\n", + check->connection_id); + continue; + } + } + +#ifdef USE_UNIX_SOCKETS + if(needle->unix_domain_socket) { + if(!check->unix_domain_socket) + continue; + if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) + continue; + if(needle->abstract_unix_socket != check->abstract_unix_socket) + continue; + } + else if(check->unix_domain_socket) + continue; +#endif + + if((needle->handler->flags&PROTOPT_SSL) != + (check->handler->flags&PROTOPT_SSL)) + /* don't do mixed SSL and non-SSL connections */ + if(get_protocol_family(check->handler->protocol) != + needle->handler->protocol || !check->tls_upgraded) + /* except protocols that have been upgraded via TLS */ + continue; + + if(needle->bits.httpproxy != check->bits.httpproxy || + needle->bits.socksproxy != check->bits.socksproxy) + continue; + + if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy, + &check->socks_proxy)) + continue; + + if(needle->bits.conn_to_host != check->bits.conn_to_host) + /* don't mix connections that use the "connect to host" feature and + * connections that don't use this feature */ + continue; + + if(needle->bits.conn_to_port != check->bits.conn_to_port) + /* don't mix connections that use the "connect to port" feature and + * connections that don't use this feature */ + continue; + + if(needle->bits.httpproxy) { + if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) + continue; + + if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) + continue; + + if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) { + /* use https proxy */ + if(needle->handler->flags&PROTOPT_SSL) { + /* use double layer ssl */ + if(!Curl_ssl_config_matches(&needle->proxy_ssl_config, + &check->proxy_ssl_config)) + continue; + if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete) + continue; + } + else { + if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) + continue; + if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) + continue; + } + } + } + + if(!canmultiplex && check->data) + /* this request can't be multiplexed but the checked connection is + already in use so we skip it */ + continue; + + if(CONN_INUSE(check) && check->data && + (check->data->multi != needle->data->multi)) + /* this could be subject for multiplex use, but only if they belong to + * the same multi handle */ + continue; + + if(needle->localdev || needle->localport) { + /* If we are bound to a specific local end (IP+port), we must not + re-use a random other one, although if we didn't ask for a + particular one we can reuse one that was bound. + + This comparison is a bit rough and too strict. Since the input + parameters can be specified in numerous ways and still end up the + same it would take a lot of processing to make it really accurate. + Instead, this matching will assume that re-uses of bound connections + will most likely also re-use the exact same binding parameters and + missing out a few edge cases shouldn't hurt anyone very much. + */ + if((check->localport != needle->localport) || + (check->localportrange != needle->localportrange) || + (needle->localdev && + (!check->localdev || strcmp(check->localdev, needle->localdev)))) + continue; + } + + if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ + if(strcmp(needle->user, check->user) || + strcmp(needle->passwd, check->passwd)) { + /* one of them was different */ + continue; + } + } + + if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) || + needle->bits.tunnel_proxy) { + /* The requested connection does not use a HTTP proxy or it uses SSL or + it is a non-SSL protocol tunneled or it is a non-SSL protocol which + is allowed to be upgraded via TLS */ + + if((strcasecompare(needle->handler->scheme, check->handler->scheme) || + (get_protocol_family(check->handler->protocol) == + needle->handler->protocol && check->tls_upgraded)) && + (!needle->bits.conn_to_host || strcasecompare( + needle->conn_to_host.name, check->conn_to_host.name)) && + (!needle->bits.conn_to_port || + needle->conn_to_port == check->conn_to_port) && + strcasecompare(needle->host.name, check->host.name) && + needle->remote_port == check->remote_port) { + /* The schemes match or the the protocol family is the same and the + previous connection was TLS upgraded, and the hostname and host + port match */ + if(needle->handler->flags & PROTOPT_SSL) { + /* This is a SSL connection so verify that we're using the same + SSL options as well */ + if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) { + DEBUGF(infof(data, + "Connection #%ld has different SSL parameters, " + "can't reuse\n", + check->connection_id)); + continue; + } + if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) { + foundPendingCandidate = TRUE; + DEBUGF(infof(data, + "Connection #%ld has not started SSL connect, " + "can't reuse\n", + check->connection_id)); + continue; + } + } + match = TRUE; + } + } + else { + /* The requested connection is using the same HTTP proxy in normal + mode (no tunneling) */ + match = TRUE; + } + + if(match) { +#if defined(USE_NTLM) + /* If we are looking for an HTTP+NTLM connection, check if this is + already authenticating with the right credentials. If not, keep + looking so that we can reuse NTLM connections if + possible. (Especially we must not reuse the same connection if + partway through a handshake!) */ + if(wantNTLMhttp) { + if(strcmp(needle->user, check->user) || + strcmp(needle->passwd, check->passwd)) + continue; + } + else if(check->http_ntlm_state != NTLMSTATE_NONE) { + /* Connection is using NTLM auth but we don't want NTLM */ + continue; + } + + /* Same for Proxy NTLM authentication */ + if(wantProxyNTLMhttp) { + /* Both check->http_proxy.user and check->http_proxy.passwd can be + * NULL */ + if(!check->http_proxy.user || !check->http_proxy.passwd) + continue; + + if(strcmp(needle->http_proxy.user, check->http_proxy.user) || + strcmp(needle->http_proxy.passwd, check->http_proxy.passwd)) + continue; + } + else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { + /* Proxy connection is using NTLM auth but we don't want NTLM */ + continue; + } + + if(wantNTLMhttp || wantProxyNTLMhttp) { + /* Credentials are already checked, we can use this connection */ + chosen = check; + + if((wantNTLMhttp && + (check->http_ntlm_state != NTLMSTATE_NONE)) || + (wantProxyNTLMhttp && + (check->proxy_ntlm_state != NTLMSTATE_NONE))) { + /* We must use this connection, no other */ + *force_reuse = TRUE; + break; + } + + /* Continue look up for a better connection */ + continue; + } +#endif + if(canmultiplex) { + /* We can multiplex if we want to. Let's continue looking for + the optimal connection to use. */ + + if(!multiplexed) { + /* We have the optimal connection. Let's stop looking. */ + chosen = check; + break; + } + +#ifdef USE_NGHTTP2 + /* If multiplexed, make sure we don't go over concurrency limit */ + if(check->bits.multiplex) { + /* Multiplexed connections can only be HTTP/2 for now */ + struct http_conn *httpc = &check->proto.httpc; + if(multiplexed >= httpc->settings.max_concurrent_streams) { + infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n", + multiplexed); + continue; + } + } +#endif + /* When not multiplexed, we have a match here! */ + chosen = check; + infof(data, "Multiplexed connection found!\n"); + break; + } + else { + /* We have found a connection. Let's stop searching. */ + chosen = check; + break; + } + } + } + } + + if(chosen) { + /* mark it as used before releasing the lock */ + chosen->data = data; /* own it! */ + Curl_conncache_unlock(data); + *usethis = chosen; + return TRUE; /* yes, we found one to use! */ + } + Curl_conncache_unlock(data); + + if(foundPendingCandidate && data->set.pipewait) { + infof(data, + "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n"); + *waitpipe = TRUE; + } + + return FALSE; /* no matching connecting exists */ +} + +/* after a TCP connection to the proxy has been verified, this function does + the next magic step. + + Note: this function's sub-functions call failf() + +*/ +CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + + if(conn->bits.socksproxy) { +#ifndef CURL_DISABLE_PROXY + /* for the secondary socket (FTP), use the "connect to host" + * but ignore the "connect to port" (use the secondary port) + */ + const char * const host = conn->bits.httpproxy ? + conn->http_proxy.host.name : + conn->bits.conn_to_host ? + conn->conn_to_host.name : + sockindex == SECONDARYSOCKET ? + conn->secondaryhostname : conn->host.name; + const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port : + sockindex == SECONDARYSOCKET ? conn->secondary_port : + conn->bits.conn_to_port ? conn->conn_to_port : + conn->remote_port; + conn->bits.socksproxy_connecting = TRUE; + switch(conn->socks_proxy.proxytype) { + case CURLPROXY_SOCKS5: + case CURLPROXY_SOCKS5_HOSTNAME: + result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd, + host, port, sockindex, conn); + break; + + case CURLPROXY_SOCKS4: + case CURLPROXY_SOCKS4A: + result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex, + conn); + break; + + default: + failf(conn->data, "unknown proxytype option given"); + result = CURLE_COULDNT_CONNECT; + } /* switch proxytype */ + conn->bits.socksproxy_connecting = FALSE; +#else + (void)sockindex; +#endif /* CURL_DISABLE_PROXY */ + } + + return result; +} + +/* + * verboseconnect() displays verbose information after a connect + */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS +void Curl_verboseconnect(struct connectdata *conn) +{ + if(conn->data->set.verbose) + infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", + conn->bits.socksproxy ? conn->socks_proxy.host.dispname : + conn->bits.httpproxy ? conn->http_proxy.host.dispname : + conn->bits.conn_to_host ? conn->conn_to_host.dispname : + conn->host.dispname, + conn->ip_addr_str, conn->port, conn->connection_id); +} +#endif + +int Curl_protocol_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn->handler->proto_getsock) + return conn->handler->proto_getsock(conn, socks, numsocks); + /* Backup getsock logic. Since there is a live socket in use, we must wait + for it or it will be removed from watching when the multi_socket API is + used. */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0); +} + +int Curl_doing_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + if(conn && conn->handler->doing_getsock) + return conn->handler->doing_getsock(conn, socks, numsocks); + return GETSOCK_BLANK; +} + +/* + * We are doing protocol-specific connecting and this is being called over and + * over from the multi interface until the connection phase is done on + * protocol layer. + */ + +CURLcode Curl_protocol_connecting(struct connectdata *conn, + bool *done) +{ + CURLcode result = CURLE_OK; + + if(conn && conn->handler->connecting) { + *done = FALSE; + result = conn->handler->connecting(conn, done); + } + else + *done = TRUE; + + return result; +} + +/* + * We are DOING this is being called over and over from the multi interface + * until the DOING phase is done on protocol layer. + */ + +CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + + if(conn && conn->handler->doing) { + *done = FALSE; + result = conn->handler->doing(conn, done); + } + else + *done = TRUE; + + return result; +} + +/* + * We have discovered that the TCP connection has been successful, we can now + * proceed with some action. + * + */ +CURLcode Curl_protocol_connect(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result = CURLE_OK; + + *protocol_done = FALSE; + + if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) { + /* We already are connected, get back. This may happen when the connect + worked fine in the first call, like when we connect to a local server + or proxy. Note that we don't know if the protocol is actually done. + + Unless this protocol doesn't have any protocol-connect callback, as + then we know we're done. */ + if(!conn->handler->connecting) + *protocol_done = TRUE; + + return CURLE_OK; + } + + if(!conn->bits.protoconnstart) { + + result = Curl_proxy_connect(conn, FIRSTSOCKET); + if(result) + return result; + + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + /* wait for HTTPS proxy SSL initialization to complete */ + return CURLE_OK; + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && + Curl_connect_ongoing(conn)) + /* when using an HTTP tunnel proxy, await complete tunnel establishment + before proceeding further. Return CURLE_OK so we'll be called again */ + return CURLE_OK; + + if(conn->handler->connect_it) { + /* is there a protocol-specific connect() procedure? */ + + /* Call the protocol-specific connect function */ + result = conn->handler->connect_it(conn, protocol_done); + } + else + *protocol_done = TRUE; + + /* it has started, possibly even completed but that knowledge isn't stored + in this bit! */ + if(!result) + conn->bits.protoconnstart = TRUE; + } + + return result; /* pass back status */ +} + +/* + * Helpers for IDNA conversions. + */ +static bool is_ASCII_name(const char *hostname) +{ + const unsigned char *ch = (const unsigned char *)hostname; + + while(*ch) { + if(*ch++ & 0x80) + return FALSE; + } + return TRUE; +} + +/* + * Strip single trailing dot in the hostname, + * primarily for SNI and http host header. + */ +static void strip_trailing_dot(struct hostname *host) +{ + size_t len; + if(!host || !host->name) + return; + len = strlen(host->name); + if(len && (host->name[len-1] == '.')) + host->name[len-1] = 0; +} + +/* + * Perform any necessary IDN conversion of hostname + */ +static CURLcode idnconvert_hostname(struct connectdata *conn, + struct hostname *host) +{ + struct Curl_easy *data = conn->data; + +#ifndef USE_LIBIDN2 + (void)data; + (void)conn; +#elif defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)conn; +#endif + + /* set the name we use to display the host name */ + host->dispname = host->name; + + /* Check name for non-ASCII and convert hostname to ACE form if we can */ + if(!is_ASCII_name(host->name)) { +#ifdef USE_LIBIDN2 + if(idn2_check_version(IDN2_VERSION)) { + char *ace_hostname = NULL; +#if IDN2_VERSION_NUMBER >= 0x00140000 + /* IDN2_NFC_INPUT: Normalize input string using normalization form C. + IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional + processing. */ + int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL; +#else + int flags = IDN2_NFC_INPUT; +#endif + int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags); + if(rc == IDN2_OK) { + host->encalloc = (char *)ace_hostname; + /* change the name pointer to point to the encoded hostname */ + host->name = host->encalloc; + } + else { + failf(data, "Failed to convert %s to ACE; %s\n", host->name, + idn2_strerror(rc)); + return CURLE_URL_MALFORMAT; + } + } +#elif defined(USE_WIN32_IDN) + char *ace_hostname = NULL; + + if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) { + host->encalloc = ace_hostname; + /* change the name pointer to point to the encoded hostname */ + host->name = host->encalloc; + } + else { + failf(data, "Failed to convert %s to ACE;\n", host->name); + return CURLE_URL_MALFORMAT; + } +#else + infof(data, "IDN support not present, can't parse Unicode domains\n"); +#endif + } + return CURLE_OK; +} + +/* + * Frees data allocated by idnconvert_hostname() + */ +static void free_idnconverted_hostname(struct hostname *host) +{ +#if defined(USE_LIBIDN2) + if(host->encalloc) { + idn2_free(host->encalloc); /* must be freed with idn2_free() since this was + allocated by libidn */ + host->encalloc = NULL; + } +#elif defined(USE_WIN32_IDN) + free(host->encalloc); /* must be freed with free() since this was + allocated by curl_win32_idn_to_ascii */ + host->encalloc = NULL; +#else + (void)host; +#endif +} + +/* + * Allocate and initialize a new connectdata object. + */ +static struct connectdata *allocate_conn(struct Curl_easy *data) +{ + struct connectdata *conn = calloc(1, sizeof(struct connectdata)); + if(!conn) + return NULL; + +#ifdef USE_SSL + /* The SSL backend-specific data (ssl_backend_data) objects are allocated as + a separate array to ensure suitable alignment. + Note that these backend pointers can be swapped by vtls (eg ssl backend + data becomes proxy backend data). */ + { + size_t sslsize = Curl_ssl->sizeof_ssl_backend_data; + char *ssl = calloc(4, sslsize); + if(!ssl) { + free(conn); + return NULL; + } + conn->ssl_extra = ssl; + conn->ssl[0].backend = (void *)ssl; + conn->ssl[1].backend = (void *)(ssl + sslsize); + conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize); + conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize); + } +#endif + + conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined + already from start to avoid NULL + situations and checks */ + + /* and we setup a few fields in case we end up actually using this struct */ + + conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */ + conn->connection_id = -1; /* no ID */ + conn->port = -1; /* unknown at this point */ + conn->remote_port = -1; /* unknown at this point */ +#if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD) + conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */ + conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */ +#endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */ + + /* Default protocol-independent behavior doesn't support persistent + connections, so we set this to force-close. Protocols that support + this need to set this to FALSE in their "curl_do" functions. */ + connclose(conn, "Default to force-close"); + + /* Store creation time to help future close decision making */ + conn->created = Curl_now(); + + /* Store current time to give a baseline to keepalive connection times. */ + conn->keepalive = Curl_now(); + + /* Store off the configured connection upkeep time. */ + conn->upkeep_interval_ms = data->set.upkeep_interval_ms; + + conn->data = data; /* Setup the association between this connection + and the Curl_easy */ + + conn->http_proxy.proxytype = data->set.proxytype; + conn->socks_proxy.proxytype = CURLPROXY_SOCKS4; + +#if !defined(CURL_DISABLE_PROXY) + /* note that these two proxy bits are now just on what looks to be + requested, they may be altered down the road */ + conn->bits.proxy = (data->set.str[STRING_PROXY] && + *data->set.str[STRING_PROXY]) ? TRUE : FALSE; + conn->bits.httpproxy = (conn->bits.proxy && + (conn->http_proxy.proxytype == CURLPROXY_HTTP || + conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 || + conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ? + TRUE : FALSE; + conn->bits.socksproxy = (conn->bits.proxy && + !conn->bits.httpproxy) ? TRUE : FALSE; + + if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) { + conn->bits.proxy = TRUE; + conn->bits.socksproxy = TRUE; + } + + conn->bits.proxy_user_passwd = + (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE; + conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; +#endif /* CURL_DISABLE_PROXY */ + + conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE; +#ifndef CURL_DISABLE_FTP + conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; + conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; +#endif + conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus; + conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer; + conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost; + conn->proxy_ssl_config.verifystatus = + data->set.proxy_ssl.primary.verifystatus; + conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; + conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; + conn->ip_version = data->set.ipver; + conn->bits.connect_only = data->set.connect_only; + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; +#endif + + /* Initialize the easy handle list */ + Curl_llist_init(&conn->easyq, NULL); + +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CLEAR; +#endif + + /* Store the local bind parameters that will be used for this connection */ + if(data->set.str[STRING_DEVICE]) { + conn->localdev = strdup(data->set.str[STRING_DEVICE]); + if(!conn->localdev) + goto error; + } + conn->localportrange = data->set.localportrange; + conn->localport = data->set.localport; + + /* the close socket stuff needs to be copied to the connection struct as + it may live on without (this specific) Curl_easy */ + conn->fclosesocket = data->set.fclosesocket; + conn->closesocket_client = data->set.closesocket_client; + + return conn; + error: + + Curl_llist_destroy(&conn->easyq, NULL); + free(conn->localdev); +#ifdef USE_SSL + free(conn->ssl_extra); +#endif + free(conn); + return NULL; +} + +/* returns the handler if the given scheme is built-in */ +const struct Curl_handler *Curl_builtin_scheme(const char *scheme) +{ + const struct Curl_handler * const *pp; + const struct Curl_handler *p; + /* Scan protocol handler table and match against 'scheme'. The handler may + be changed later when the protocol specific setup function is called. */ + for(pp = protocols; (p = *pp) != NULL; pp++) + if(strcasecompare(p->scheme, scheme)) + /* Protocol found in table. Check if allowed */ + return p; + return NULL; /* not found */ +} + + +static CURLcode findprotocol(struct Curl_easy *data, + struct connectdata *conn, + const char *protostr) +{ + const struct Curl_handler *p = Curl_builtin_scheme(protostr); + + if(p && /* Protocol found in table. Check if allowed */ + (data->set.allowed_protocols & p->protocol)) { + + /* it is allowed for "normal" request, now do an extra check if this is + the result of a redirect */ + if(data->state.this_is_a_follow && + !(data->set.redir_protocols & p->protocol)) + /* nope, get out */ + ; + else { + /* Perform setup complement if some. */ + conn->handler = conn->given = p; + + /* 'port' and 'remote_port' are set in setup_connection_internals() */ + return CURLE_OK; + } + } + + /* The protocol was not found in the table, but we don't have to assign it + to anything since it is already assigned to a dummy-struct in the + create_conn() function when the connectdata struct is allocated. */ + failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME, + protostr); + + return CURLE_UNSUPPORTED_PROTOCOL; +} + + +CURLcode Curl_uc_to_curlcode(CURLUcode uc) +{ + switch(uc) { + default: + return CURLE_URL_MALFORMAT; + case CURLUE_UNSUPPORTED_SCHEME: + return CURLE_UNSUPPORTED_PROTOCOL; + case CURLUE_OUT_OF_MEMORY: + return CURLE_OUT_OF_MEMORY; + case CURLUE_USER_NOT_ALLOWED: + return CURLE_LOGIN_DENIED; + } +} + +/* + * If the URL was set with an IPv6 numerical address with a zone id part, set + * the scope_id based on that! + */ + +static void zonefrom_url(CURLU *uh, struct connectdata *conn) +{ + char *zoneid; + CURLUcode uc; + + uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0); + + if(!uc && zoneid) { + char *endp; + unsigned long scope = strtoul(zoneid, &endp, 10); + if(!*endp && (scope < UINT_MAX)) + /* A plain number, use it directly as a scope id. */ + conn->scope_id = (unsigned int)scope; +#if defined(HAVE_IF_NAMETOINDEX) + else { +#elif defined(WIN32) + else if(Curl_if_nametoindex) { +#endif + +#if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32) + /* Zone identifier is not numeric */ + unsigned int scopeidx = 0; +#if defined(WIN32) + scopeidx = Curl_if_nametoindex(zoneid); +#else + scopeidx = if_nametoindex(zoneid); +#endif + if(!scopeidx) + infof(conn->data, "Invalid zoneid: %s; %s\n", zoneid, + strerror(errno)); + else + conn->scope_id = scopeidx; + } +#endif /* HAVE_IF_NAMETOINDEX || WIN32 */ + + free(zoneid); + } +} + +/* + * Parse URL and fill in the relevant members of the connection struct. + */ +static CURLcode parseurlandfillconn(struct Curl_easy *data, + struct connectdata *conn) +{ + CURLcode result; + CURLU *uh; + CURLUcode uc; + char *hostname; + + up_free(data); /* cleanup previous leftovers first */ + + /* parse the URL */ + if(data->set.uh) { + uh = data->state.uh = curl_url_dup(data->set.uh); + } + else { + uh = data->state.uh = curl_url(); + } + + if(!uh) + return CURLE_OUT_OF_MEMORY; + + if(data->set.str[STRING_DEFAULT_PROTOCOL] && + !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) { + char *url; + if(data->change.url_alloc) + free(data->change.url); + url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL], + data->change.url); + if(!url) + return CURLE_OUT_OF_MEMORY; + data->change.url = url; + data->change.url_alloc = TRUE; + } + + if(!data->set.uh) { + uc = curl_url_set(uh, CURLUPART_URL, data->change.url, + CURLU_GUESS_SCHEME | + CURLU_NON_SUPPORT_SCHEME | + (data->set.disallow_username_in_url ? + CURLU_DISALLOW_USER : 0) | + (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)); + if(uc) { + DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url)); + return Curl_uc_to_curlcode(uc); + } + } + + uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + + result = findprotocol(data, conn, data->state.up.scheme); + if(result) + return result; + + uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, + CURLU_URLDECODE); + if(!uc) { + conn->user = strdup(data->state.up.user); + if(!conn->user) + return CURLE_OUT_OF_MEMORY; + conn->bits.user_passwd = TRUE; + } + else if(uc != CURLUE_NO_USER) + return Curl_uc_to_curlcode(uc); + + uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, + CURLU_URLDECODE); + if(!uc) { + conn->passwd = strdup(data->state.up.password); + if(!conn->passwd) + return CURLE_OUT_OF_MEMORY; + conn->bits.user_passwd = TRUE; + } + else if(uc != CURLUE_NO_PASSWORD) + return Curl_uc_to_curlcode(uc); + + uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options, + CURLU_URLDECODE); + if(!uc) { + conn->options = strdup(data->state.up.options); + if(!conn->options) + return CURLE_OUT_OF_MEMORY; + } + else if(uc != CURLUE_NO_OPTIONS) + return Curl_uc_to_curlcode(uc); + + uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0); + if(uc) { + if(!strcasecompare("file", data->state.up.scheme)) + return CURLE_OUT_OF_MEMORY; + } + + uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + + uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port, + CURLU_DEFAULT_PORT); + if(uc) { + if(!strcasecompare("file", data->state.up.scheme)) + return CURLE_OUT_OF_MEMORY; + } + else { + unsigned long port = strtoul(data->state.up.port, NULL, 10); + conn->port = conn->remote_port = curlx_ultous(port); + } + + (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); + + hostname = data->state.up.hostname; + if(!hostname) + /* this is for file:// transfers, get a dummy made */ + hostname = (char *)""; + + if(hostname[0] == '[') { + /* This looks like an IPv6 address literal. See if there is an address + scope. */ + size_t hlen; + conn->bits.ipv6_ip = TRUE; + /* cut off the brackets! */ + hostname++; + hlen = strlen(hostname); + hostname[hlen - 1] = 0; + + zonefrom_url(uh, conn); + } + + /* make sure the connect struct gets its own copy of the host name */ + conn->host.rawalloc = strdup(hostname); + if(!conn->host.rawalloc) + return CURLE_OUT_OF_MEMORY; + conn->host.name = conn->host.rawalloc; + + if(data->set.scope_id) + /* Override any scope that was set above. */ + conn->scope_id = data->set.scope_id; + + return CURLE_OK; +} + + +/* + * If we're doing a resumed transfer, we need to setup our stuff + * properly. + */ +static CURLcode setup_range(struct Curl_easy *data) +{ + struct UrlState *s = &data->state; + s->resume_from = data->set.set_resume_from; + if(s->resume_from || data->set.str[STRING_SET_RANGE]) { + if(s->rangestringalloc) + free(s->range); + + if(s->resume_from) + s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from); + else + s->range = strdup(data->set.str[STRING_SET_RANGE]); + + s->rangestringalloc = (s->range) ? TRUE : FALSE; + + if(!s->range) + return CURLE_OUT_OF_MEMORY; + + /* tell ourselves to fetch this range */ + s->use_range = TRUE; /* enable range download */ + } + else + s->use_range = FALSE; /* disable range download */ + + return CURLE_OK; +} + + +/* + * setup_connection_internals() - + * + * Setup connection internals specific to the requested protocol in the + * Curl_easy. This is inited and setup before the connection is made but + * is about the particular protocol that is to be used. + * + * This MUST get called after proxy magic has been figured out. + */ +static CURLcode setup_connection_internals(struct connectdata *conn) +{ + const struct Curl_handler * p; + CURLcode result; + conn->socktype = SOCK_STREAM; /* most of them are TCP streams */ + + /* Perform setup complement if some. */ + p = conn->handler; + + if(p->setup_connection) { + result = (*p->setup_connection)(conn); + + if(result) + return result; + + p = conn->handler; /* May have changed. */ + } + + if(conn->port < 0) + /* we check for -1 here since if proxy was detected already, this + was very likely already set to the proxy port */ + conn->port = p->defport; + + return CURLE_OK; +} + +/* + * Curl_free_request_state() should free temp data that was allocated in the + * Curl_easy for this single request. + */ + +void Curl_free_request_state(struct Curl_easy *data) +{ + Curl_safefree(data->req.protop); + Curl_safefree(data->req.newurl); +} + + +#ifndef CURL_DISABLE_PROXY +/**************************************************************** +* Checks if the host is in the noproxy list. returns true if it matches +* and therefore the proxy should NOT be used. +****************************************************************/ +static bool check_noproxy(const char *name, const char *no_proxy) +{ + /* no_proxy=domain1.dom,host.domain2.dom + * (a comma-separated list of hosts which should + * not be proxied, or an asterisk to override + * all proxy variables) + */ + if(no_proxy && no_proxy[0]) { + size_t tok_start; + size_t tok_end; + const char *separator = ", "; + size_t no_proxy_len; + size_t namelen; + char *endptr; + if(strcasecompare("*", no_proxy)) { + return TRUE; + } + + /* NO_PROXY was specified and it wasn't just an asterisk */ + + no_proxy_len = strlen(no_proxy); + if(name[0] == '[') { + /* IPv6 numerical address */ + endptr = strchr(name, ']'); + if(!endptr) + return FALSE; + name++; + namelen = endptr - name; + } + else + namelen = strlen(name); + + for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) { + while(tok_start < no_proxy_len && + strchr(separator, no_proxy[tok_start]) != NULL) { + /* Look for the beginning of the token. */ + ++tok_start; + } + + if(tok_start == no_proxy_len) + break; /* It was all trailing separator chars, no more tokens. */ + + for(tok_end = tok_start; tok_end < no_proxy_len && + strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end) + /* Look for the end of the token. */ + ; + + /* To match previous behaviour, where it was necessary to specify + * ".local.com" to prevent matching "notlocal.com", we will leave + * the '.' off. + */ + if(no_proxy[tok_start] == '.') + ++tok_start; + + if((tok_end - tok_start) <= namelen) { + /* Match the last part of the name to the domain we are checking. */ + const char *checkn = name + namelen - (tok_end - tok_start); + if(strncasecompare(no_proxy + tok_start, checkn, + tok_end - tok_start)) { + if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') { + /* We either have an exact match, or the previous character is a . + * so it is within the same domain, so no proxy for this host. + */ + return TRUE; + } + } + } /* if((tok_end - tok_start) <= namelen) */ + } /* for(tok_start = 0; tok_start < no_proxy_len; + tok_start = tok_end + 1) */ + } /* NO_PROXY was specified and it wasn't just an asterisk */ + + return FALSE; +} + +#ifndef CURL_DISABLE_HTTP +/**************************************************************** +* Detect what (if any) proxy to use. Remember that this selects a host +* name and is not limited to HTTP proxies only. +* The returned pointer must be freed by the caller (unless NULL) +****************************************************************/ +static char *detect_proxy(struct connectdata *conn) +{ + char *proxy = NULL; + + /* If proxy was not specified, we check for default proxy environment + * variables, to enable i.e Lynx compliance: + * + * http_proxy=http://some.server.dom:port/ + * https_proxy=http://some.server.dom:port/ + * ftp_proxy=http://some.server.dom:port/ + * no_proxy=domain1.dom,host.domain2.dom + * (a comma-separated list of hosts which should + * not be proxied, or an asterisk to override + * all proxy variables) + * all_proxy=http://some.server.dom:port/ + * (seems to exist for the CERN www lib. Probably + * the first to check for.) + * + * For compatibility, the all-uppercase versions of these variables are + * checked if the lowercase versions don't exist. + */ + char proxy_env[128]; + const char *protop = conn->handler->scheme; + char *envp = proxy_env; + char *prox; + + /* Now, build _proxy and check for such a one to use */ + while(*protop) + *envp++ = (char)tolower((int)*protop++); + + /* append _proxy */ + strcpy(envp, "_proxy"); + + /* read the protocol proxy: */ + prox = curl_getenv(proxy_env); + + /* + * We don't try the uppercase version of HTTP_PROXY because of + * security reasons: + * + * When curl is used in a webserver application + * environment (cgi or php), this environment variable can + * be controlled by the web server user by setting the + * http header 'Proxy:' to some value. + * + * This can cause 'internal' http/ftp requests to be + * arbitrarily redirected by any external attacker. + */ + if(!prox && !strcasecompare("http_proxy", proxy_env)) { + /* There was no lowercase variable, try the uppercase version: */ + Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env)); + prox = curl_getenv(proxy_env); + } + + envp = proxy_env; + if(prox) { + proxy = prox; /* use this */ + } + else { + envp = (char *)"all_proxy"; + proxy = curl_getenv(envp); /* default proxy to use */ + if(!proxy) { + envp = (char *)"ALL_PROXY"; + proxy = curl_getenv(envp); + } + } + if(proxy) + infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy); + + return proxy; +} +#endif /* CURL_DISABLE_HTTP */ + +/* + * If this is supposed to use a proxy, we need to figure out the proxy + * host name, so that we can re-use an existing connection + * that may exist registered to the same proxy host. + */ +static CURLcode parse_proxy(struct Curl_easy *data, + struct connectdata *conn, char *proxy, + curl_proxytype proxytype) +{ + char *portptr = NULL; + long port = -1; + char *proxyuser = NULL; + char *proxypasswd = NULL; + char *host; + bool sockstype; + CURLUcode uc; + struct proxy_info *proxyinfo; + CURLU *uhp = curl_url(); + CURLcode result = CURLE_OK; + char *scheme = NULL; + + /* When parsing the proxy, allowing non-supported schemes since we have + these made up ones for proxies. Guess scheme for URLs without it. */ + uc = curl_url_set(uhp, CURLUPART_URL, proxy, + CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME); + if(!uc) { + /* parsed okay as a URL */ + uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0); + if(uc) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + + if(strcasecompare("https", scheme)) + proxytype = CURLPROXY_HTTPS; + else if(strcasecompare("socks5h", scheme)) + proxytype = CURLPROXY_SOCKS5_HOSTNAME; + else if(strcasecompare("socks5", scheme)) + proxytype = CURLPROXY_SOCKS5; + else if(strcasecompare("socks4a", scheme)) + proxytype = CURLPROXY_SOCKS4A; + else if(strcasecompare("socks4", scheme) || + strcasecompare("socks", scheme)) + proxytype = CURLPROXY_SOCKS4; + else if(strcasecompare("http", scheme)) + ; /* leave it as HTTP or HTTP/1.0 */ + else { + /* Any other xxx:// reject! */ + failf(data, "Unsupported proxy scheme for \'%s\'", proxy); + result = CURLE_COULDNT_CONNECT; + goto error; + } + } + else { + failf(data, "Unsupported proxy syntax in \'%s\'", proxy); + result = CURLE_COULDNT_RESOLVE_PROXY; + goto error; + } + +#ifdef USE_SSL + if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)) +#endif + if(proxytype == CURLPROXY_HTTPS) { + failf(data, "Unsupported proxy \'%s\', libcurl is built without the " + "HTTPS-proxy support.", proxy); + result = CURLE_NOT_BUILT_IN; + goto error; + } + + sockstype = + proxytype == CURLPROXY_SOCKS5_HOSTNAME || + proxytype == CURLPROXY_SOCKS5 || + proxytype == CURLPROXY_SOCKS4A || + proxytype == CURLPROXY_SOCKS4; + + proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy; + proxyinfo->proxytype = proxytype; + + /* Is there a username and password given in this proxy url? */ + curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE); + curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE); + if(proxyuser || proxypasswd) { + Curl_safefree(proxyinfo->user); + proxyinfo->user = proxyuser; + Curl_safefree(proxyinfo->passwd); + if(!proxypasswd) { + proxypasswd = strdup(""); + if(!proxypasswd) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + } + proxyinfo->passwd = proxypasswd; + conn->bits.proxy_user_passwd = TRUE; /* enable it */ + } + + curl_url_get(uhp, CURLUPART_PORT, &portptr, 0); + + if(portptr) { + port = strtol(portptr, NULL, 10); + free(portptr); + } + else { + if(data->set.proxyport) + /* None given in the proxy string, then get the default one if it is + given */ + port = data->set.proxyport; + else { + if(proxytype == CURLPROXY_HTTPS) + port = CURL_DEFAULT_HTTPS_PROXY_PORT; + else + port = CURL_DEFAULT_PROXY_PORT; + } + } + if(port >= 0) { + proxyinfo->port = port; + if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc) + conn->port = port; + } + + /* now, clone the proxy host name */ + uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE); + if(uc) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } + Curl_safefree(proxyinfo->host.rawalloc); + proxyinfo->host.rawalloc = host; + if(host[0] == '[') { + /* this is a numerical IPv6, strip off the brackets */ + size_t len = strlen(host); + host[len-1] = 0; /* clear the trailing bracket */ + host++; + zonefrom_url(uhp, conn); + } + proxyinfo->host.name = host; + + error: + free(scheme); + curl_url_cleanup(uhp); + return result; +} + +/* + * Extract the user and password from the authentication string + */ +static CURLcode parse_proxy_auth(struct Curl_easy *data, + struct connectdata *conn) +{ + char proxyuser[MAX_CURL_USER_LENGTH]=""; + char proxypasswd[MAX_CURL_PASSWORD_LENGTH]=""; + CURLcode result; + + if(data->set.str[STRING_PROXYUSERNAME] != NULL) { + strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME], + MAX_CURL_USER_LENGTH); + proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/ + } + if(data->set.str[STRING_PROXYPASSWORD] != NULL) { + strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD], + MAX_CURL_PASSWORD_LENGTH); + proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/ + } + + result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL, + FALSE); + if(!result) + result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd, + NULL, FALSE); + return result; +} + +/* create_conn helper to parse and init proxy values. to be called after unix + socket init but before any proxy vars are evaluated. */ +static CURLcode create_conn_helper_init_proxy(struct connectdata *conn) +{ + char *proxy = NULL; + char *socksproxy = NULL; + char *no_proxy = NULL; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + /************************************************************* + * Extract the user and password from the authentication string + *************************************************************/ + if(conn->bits.proxy_user_passwd) { + result = parse_proxy_auth(data, conn); + if(result) + goto out; + } + + /************************************************************* + * Detect what (if any) proxy to use + *************************************************************/ + if(data->set.str[STRING_PROXY]) { + proxy = strdup(data->set.str[STRING_PROXY]); + /* if global proxy is set, this is it */ + if(NULL == proxy) { + failf(data, "memory shortage"); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + + if(data->set.str[STRING_PRE_PROXY]) { + socksproxy = strdup(data->set.str[STRING_PRE_PROXY]); + /* if global socks proxy is set, this is it */ + if(NULL == socksproxy) { + failf(data, "memory shortage"); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + + if(!data->set.str[STRING_NOPROXY]) { + const char *p = "no_proxy"; + no_proxy = curl_getenv(p); + if(!no_proxy) { + p = "NO_PROXY"; + no_proxy = curl_getenv(p); + } + if(no_proxy) { + infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy); + } + } + + if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ? + data->set.str[STRING_NOPROXY] : no_proxy)) { + Curl_safefree(proxy); + Curl_safefree(socksproxy); + } +#ifndef CURL_DISABLE_HTTP + else if(!proxy && !socksproxy) + /* if the host is not in the noproxy list, detect proxy. */ + proxy = detect_proxy(conn); +#endif /* CURL_DISABLE_HTTP */ + + Curl_safefree(no_proxy); + +#ifdef USE_UNIX_SOCKETS + /* For the time being do not mix proxy and unix domain sockets. See #1274 */ + if(proxy && conn->unix_domain_socket) { + free(proxy); + proxy = NULL; + } +#endif + + if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) { + free(proxy); /* Don't bother with an empty proxy string or if the + protocol doesn't work with network */ + proxy = NULL; + } + if(socksproxy && (!*socksproxy || + (conn->handler->flags & PROTOPT_NONETWORK))) { + free(socksproxy); /* Don't bother with an empty socks proxy string or if + the protocol doesn't work with network */ + socksproxy = NULL; + } + + /*********************************************************************** + * If this is supposed to use a proxy, we need to figure out the proxy host + * name, proxy type and port number, so that we can re-use an existing + * connection that may exist registered to the same proxy host. + ***********************************************************************/ + if(proxy || socksproxy) { + if(proxy) { + result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype); + Curl_safefree(proxy); /* parse_proxy copies the proxy string */ + if(result) + goto out; + } + + if(socksproxy) { + result = parse_proxy(data, conn, socksproxy, + conn->socks_proxy.proxytype); + /* parse_proxy copies the socks proxy string */ + Curl_safefree(socksproxy); + if(result) + goto out; + } + + if(conn->http_proxy.host.rawalloc) { +#ifdef CURL_DISABLE_HTTP + /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ + result = CURLE_UNSUPPORTED_PROTOCOL; + goto out; +#else + /* force this connection's protocol to become HTTP if compatible */ + if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) { + if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) && + !conn->bits.tunnel_proxy) + conn->handler = &Curl_handler_http; + else + /* if not converting to HTTP over the proxy, enforce tunneling */ + conn->bits.tunnel_proxy = TRUE; + } + conn->bits.httpproxy = TRUE; +#endif + } + else { + conn->bits.httpproxy = FALSE; /* not a HTTP proxy */ + conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */ + } + + if(conn->socks_proxy.host.rawalloc) { + if(!conn->http_proxy.host.rawalloc) { + /* once a socks proxy */ + if(!conn->socks_proxy.user) { + conn->socks_proxy.user = conn->http_proxy.user; + conn->http_proxy.user = NULL; + Curl_safefree(conn->socks_proxy.passwd); + conn->socks_proxy.passwd = conn->http_proxy.passwd; + conn->http_proxy.passwd = NULL; + } + } + conn->bits.socksproxy = TRUE; + } + else + conn->bits.socksproxy = FALSE; /* not a socks proxy */ + } + else { + conn->bits.socksproxy = FALSE; + conn->bits.httpproxy = FALSE; + } + conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy; + + if(!conn->bits.proxy) { + /* we aren't using the proxy after all... */ + conn->bits.proxy = FALSE; + conn->bits.httpproxy = FALSE; + conn->bits.socksproxy = FALSE; + conn->bits.proxy_user_passwd = FALSE; + conn->bits.tunnel_proxy = FALSE; + } + +out: + + free(socksproxy); + free(proxy); + return result; +} +#endif /* CURL_DISABLE_PROXY */ + +/* + * Curl_parse_login_details() + * + * This is used to parse a login string for user name, password and options in + * the following formats: + * + * user + * user:password + * user:password;options + * user;options + * user;options:password + * :password + * :password;options + * ;options + * ;options:password + * + * Parameters: + * + * login [in] - The login string. + * len [in] - The length of the login string. + * userp [in/out] - The address where a pointer to newly allocated memory + * holding the user will be stored upon completion. + * passwdp [in/out] - The address where a pointer to newly allocated memory + * holding the password will be stored upon completion. + * optionsp [in/out] - The address where a pointer to newly allocated memory + * holding the options will be stored upon completion. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_parse_login_details(const char *login, const size_t len, + char **userp, char **passwdp, + char **optionsp) +{ + CURLcode result = CURLE_OK; + char *ubuf = NULL; + char *pbuf = NULL; + char *obuf = NULL; + const char *psep = NULL; + const char *osep = NULL; + size_t ulen; + size_t plen; + size_t olen; + + /* Attempt to find the password separator */ + if(passwdp) { + psep = strchr(login, ':'); + + /* Within the constraint of the login string */ + if(psep >= login + len) + psep = NULL; + } + + /* Attempt to find the options separator */ + if(optionsp) { + osep = strchr(login, ';'); + + /* Within the constraint of the login string */ + if(osep >= login + len) + osep = NULL; + } + + /* Calculate the portion lengths */ + ulen = (psep ? + (size_t)(osep && psep > osep ? osep - login : psep - login) : + (osep ? (size_t)(osep - login) : len)); + plen = (psep ? + (osep && osep > psep ? (size_t)(osep - psep) : + (size_t)(login + len - psep)) - 1 : 0); + olen = (osep ? + (psep && psep > osep ? (size_t)(psep - osep) : + (size_t)(login + len - osep)) - 1 : 0); + + /* Allocate the user portion buffer */ + if(userp && ulen) { + ubuf = malloc(ulen + 1); + if(!ubuf) + result = CURLE_OUT_OF_MEMORY; + } + + /* Allocate the password portion buffer */ + if(!result && passwdp && plen) { + pbuf = malloc(plen + 1); + if(!pbuf) { + free(ubuf); + result = CURLE_OUT_OF_MEMORY; + } + } + + /* Allocate the options portion buffer */ + if(!result && optionsp && olen) { + obuf = malloc(olen + 1); + if(!obuf) { + free(pbuf); + free(ubuf); + result = CURLE_OUT_OF_MEMORY; + } + } + + if(!result) { + /* Store the user portion if necessary */ + if(ubuf) { + memcpy(ubuf, login, ulen); + ubuf[ulen] = '\0'; + Curl_safefree(*userp); + *userp = ubuf; + } + + /* Store the password portion if necessary */ + if(pbuf) { + memcpy(pbuf, psep + 1, plen); + pbuf[plen] = '\0'; + Curl_safefree(*passwdp); + *passwdp = pbuf; + } + + /* Store the options portion if necessary */ + if(obuf) { + memcpy(obuf, osep + 1, olen); + obuf[olen] = '\0'; + Curl_safefree(*optionsp); + *optionsp = obuf; + } + } + + return result; +} + +/************************************************************* + * Figure out the remote port number and fix it in the URL + * + * No matter if we use a proxy or not, we have to figure out the remote + * port number of various reasons. + * + * The port number embedded in the URL is replaced, if necessary. + *************************************************************/ +static CURLcode parse_remote_port(struct Curl_easy *data, + struct connectdata *conn) +{ + + if(data->set.use_port && data->state.allow_port) { + /* if set, we use this instead of the port possibly given in the URL */ + char portbuf[16]; + CURLUcode uc; + conn->remote_port = (unsigned short)data->set.use_port; + msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port); + uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0); + if(uc) + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + +/* + * Override the login details from the URL with that in the CURLOPT_USERPWD + * option or a .netrc file, if applicable. + */ +static CURLcode override_login(struct Curl_easy *data, + struct connectdata *conn, + char **userp, char **passwdp, char **optionsp) +{ + bool user_changed = FALSE; + bool passwd_changed = FALSE; + CURLUcode uc; + + if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) { + /* ignore user+password in the URL */ + if(*userp) { + Curl_safefree(*userp); + user_changed = TRUE; + } + if(*passwdp) { + Curl_safefree(*passwdp); + passwd_changed = TRUE; + } + conn->bits.user_passwd = FALSE; /* disable user+password */ + } + + if(data->set.str[STRING_USERNAME]) { + free(*userp); + *userp = strdup(data->set.str[STRING_USERNAME]); + if(!*userp) + return CURLE_OUT_OF_MEMORY; + conn->bits.user_passwd = TRUE; /* enable user+password */ + user_changed = TRUE; + } + + if(data->set.str[STRING_PASSWORD]) { + free(*passwdp); + *passwdp = strdup(data->set.str[STRING_PASSWORD]); + if(!*passwdp) + return CURLE_OUT_OF_MEMORY; + conn->bits.user_passwd = TRUE; /* enable user+password */ + passwd_changed = TRUE; + } + + if(data->set.str[STRING_OPTIONS]) { + free(*optionsp); + *optionsp = strdup(data->set.str[STRING_OPTIONS]); + if(!*optionsp) + return CURLE_OUT_OF_MEMORY; + } + + conn->bits.netrc = FALSE; + if(data->set.use_netrc != CURL_NETRC_IGNORED && + (!*userp || !**userp || !*passwdp || !**passwdp)) { + bool netrc_user_changed = FALSE; + bool netrc_passwd_changed = FALSE; + int ret; + + ret = Curl_parsenetrc(conn->host.name, + userp, passwdp, + &netrc_user_changed, &netrc_passwd_changed, + data->set.str[STRING_NETRC_FILE]); + if(ret > 0) { + infof(data, "Couldn't find host %s in the " + DOT_CHAR "netrc file; using defaults\n", + conn->host.name); + } + else if(ret < 0) { + return CURLE_OUT_OF_MEMORY; + } + else { + /* set bits.netrc TRUE to remember that we got the name from a .netrc + file, so that it is safe to use even if we followed a Location: to a + different host or similar. */ + conn->bits.netrc = TRUE; + conn->bits.user_passwd = TRUE; /* enable user+password */ + + if(netrc_user_changed) { + user_changed = TRUE; + } + if(netrc_passwd_changed) { + passwd_changed = TRUE; + } + } + } + + /* for updated strings, we update them in the URL */ + if(user_changed) { + uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + } + if(passwd_changed) { + uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, 0); + if(uc) + return Curl_uc_to_curlcode(uc); + } + return CURLE_OK; +} + +/* + * Set the login details so they're available in the connection + */ +static CURLcode set_login(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + const char *setuser = CURL_DEFAULT_USER; + const char *setpasswd = CURL_DEFAULT_PASSWORD; + + /* If our protocol needs a password and we have none, use the defaults */ + if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) + ; + else { + setuser = ""; + setpasswd = ""; + } + /* Store the default user */ + if(!conn->user) { + conn->user = strdup(setuser); + if(!conn->user) + return CURLE_OUT_OF_MEMORY; + } + + /* Store the default password */ + if(!conn->passwd) { + conn->passwd = strdup(setpasswd); + if(!conn->passwd) + result = CURLE_OUT_OF_MEMORY; + } + + /* if there's a user without password, consider password blank */ + if(conn->user && !conn->passwd) { + conn->passwd = strdup(""); + if(!conn->passwd) + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + +/* + * Parses a "host:port" string to connect to. + * The hostname and the port may be empty; in this case, NULL is returned for + * the hostname and -1 for the port. + */ +static CURLcode parse_connect_to_host_port(struct Curl_easy *data, + const char *host, + char **hostname_result, + int *port_result) +{ + char *host_dup; + char *hostptr; + char *host_portno; + char *portptr; + int port = -1; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + *hostname_result = NULL; + *port_result = -1; + + if(!host || !*host) + return CURLE_OK; + + host_dup = strdup(host); + if(!host_dup) + return CURLE_OUT_OF_MEMORY; + + hostptr = host_dup; + + /* start scanning for port number at this point */ + portptr = hostptr; + + /* detect and extract RFC6874-style IPv6-addresses */ + if(*hostptr == '[') { +#ifdef ENABLE_IPV6 + char *ptr = ++hostptr; /* advance beyond the initial bracket */ + while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.'))) + ptr++; + if(*ptr == '%') { + /* There might be a zone identifier */ + if(strncmp("%25", ptr, 3)) + infof(data, "Please URL encode %% as %%25, see RFC 6874.\n"); + ptr++; + /* Allow unreserved characters as defined in RFC 3986 */ + while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') || + (*ptr == '.') || (*ptr == '_') || (*ptr == '~'))) + ptr++; + } + if(*ptr == ']') + /* yeps, it ended nicely with a bracket as well */ + *ptr++ = '\0'; + else + infof(data, "Invalid IPv6 address format\n"); + portptr = ptr; + /* Note that if this didn't end with a bracket, we still advanced the + * hostptr first, but I can't see anything wrong with that as no host + * name nor a numeric can legally start with a bracket. + */ +#else + failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!"); + free(host_dup); + return CURLE_NOT_BUILT_IN; +#endif + } + + /* Get port number off server.com:1080 */ + host_portno = strchr(portptr, ':'); + if(host_portno) { + char *endp = NULL; + *host_portno = '\0'; /* cut off number from host name */ + host_portno++; + if(*host_portno) { + long portparse = strtol(host_portno, &endp, 10); + if((endp && *endp) || (portparse < 0) || (portparse > 65535)) { + infof(data, "No valid port number in connect to host string (%s)\n", + host_portno); + hostptr = NULL; + port = -1; + } + else + port = (int)portparse; /* we know it will fit */ + } + } + + /* now, clone the cleaned host name */ + if(hostptr) { + *hostname_result = strdup(hostptr); + if(!*hostname_result) { + free(host_dup); + return CURLE_OUT_OF_MEMORY; + } + } + + *port_result = port; + + free(host_dup); + return CURLE_OK; +} + +/* + * Parses one "connect to" string in the form: + * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT". + */ +static CURLcode parse_connect_to_string(struct Curl_easy *data, + struct connectdata *conn, + const char *conn_to_host, + char **host_result, + int *port_result) +{ + CURLcode result = CURLE_OK; + const char *ptr = conn_to_host; + int host_match = FALSE; + int port_match = FALSE; + + *host_result = NULL; + *port_result = -1; + + if(*ptr == ':') { + /* an empty hostname always matches */ + host_match = TRUE; + ptr++; + } + else { + /* check whether the URL's hostname matches */ + size_t hostname_to_match_len; + char *hostname_to_match = aprintf("%s%s%s", + conn->bits.ipv6_ip ? "[" : "", + conn->host.name, + conn->bits.ipv6_ip ? "]" : ""); + if(!hostname_to_match) + return CURLE_OUT_OF_MEMORY; + hostname_to_match_len = strlen(hostname_to_match); + host_match = strncasecompare(ptr, hostname_to_match, + hostname_to_match_len); + free(hostname_to_match); + ptr += hostname_to_match_len; + + host_match = host_match && *ptr == ':'; + ptr++; + } + + if(host_match) { + if(*ptr == ':') { + /* an empty port always matches */ + port_match = TRUE; + ptr++; + } + else { + /* check whether the URL's port matches */ + char *ptr_next = strchr(ptr, ':'); + if(ptr_next) { + char *endp = NULL; + long port_to_match = strtol(ptr, &endp, 10); + if((endp == ptr_next) && (port_to_match == conn->remote_port)) { + port_match = TRUE; + ptr = ptr_next + 1; + } + } + } + } + + if(host_match && port_match) { + /* parse the hostname and port to connect to */ + result = parse_connect_to_host_port(data, ptr, host_result, port_result); + } + + return result; +} + +/* + * Processes all strings in the "connect to" slist, and uses the "connect + * to host" and "connect to port" of the first string that matches. + */ +static CURLcode parse_connect_to_slist(struct Curl_easy *data, + struct connectdata *conn, + struct curl_slist *conn_to_host) +{ + CURLcode result = CURLE_OK; + char *host = NULL; + int port = -1; + + while(conn_to_host && !host && port == -1) { + result = parse_connect_to_string(data, conn, conn_to_host->data, + &host, &port); + if(result) + return result; + + if(host && *host) { + conn->conn_to_host.rawalloc = host; + conn->conn_to_host.name = host; + conn->bits.conn_to_host = TRUE; + + infof(data, "Connecting to hostname: %s\n", host); + } + else { + /* no "connect to host" */ + conn->bits.conn_to_host = FALSE; + Curl_safefree(host); + } + + if(port >= 0) { + conn->conn_to_port = port; + conn->bits.conn_to_port = TRUE; + infof(data, "Connecting to port: %d\n", port); + } + else { + /* no "connect to port" */ + conn->bits.conn_to_port = FALSE; + port = -1; + } + + conn_to_host = conn_to_host->next; + } + +#ifdef USE_ALTSVC + if(data->asi && !host && (port == -1) && + (conn->handler->protocol == CURLPROTO_HTTPS)) { + /* no connect_to match, try alt-svc! */ + const char *nhost; + int nport; + enum alpnid nalpnid; + bool hit; + host = conn->host.rawalloc; + hit = Curl_altsvc_lookup(data->asi, + ALPN_h1, host, conn->remote_port, /* from */ + &nalpnid, &nhost, &nport /* to */); + if(hit) { + char *hostd = strdup((char *)nhost); + if(!hostd) + return CURLE_OUT_OF_MEMORY; + conn->conn_to_host.rawalloc = hostd; + conn->conn_to_host.name = hostd; + conn->bits.conn_to_host = TRUE; + conn->conn_to_port = nport; + conn->bits.conn_to_port = TRUE; + infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n", + Curl_alpnid2str(ALPN_h1), host, conn->remote_port, + Curl_alpnid2str(nalpnid), hostd, nport); + } + } +#endif + + return result; +} + +/************************************************************* + * Resolve the address of the server or proxy + *************************************************************/ +static CURLcode resolve_server(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ + CURLcode result = CURLE_OK; + timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + + DEBUGASSERT(conn); + DEBUGASSERT(data); + /************************************************************* + * Resolve the name of the server or proxy + *************************************************************/ + if(conn->bits.reuse) + /* We're reusing the connection - no need to resolve anything, and + idnconvert_hostname() was called already in create_conn() for the re-use + case. */ + *async = FALSE; + + else { + /* this is a fresh connect */ + int rc; + struct Curl_dns_entry *hostaddr; + +#ifdef USE_UNIX_SOCKETS + if(conn->unix_domain_socket) { + /* Unix domain sockets are local. The host gets ignored, just use the + * specified domain socket address. Do not cache "DNS entries". There is + * no DNS involved and we already have the filesystem path available */ + const char *path = conn->unix_domain_socket; + + hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); + if(!hostaddr) + result = CURLE_OUT_OF_MEMORY; + else { + bool longpath = FALSE; + hostaddr->addr = Curl_unix2addr(path, &longpath, + conn->abstract_unix_socket); + if(hostaddr->addr) + hostaddr->inuse++; + else { + /* Long paths are not supported for now */ + if(longpath) { + failf(data, "Unix socket path too long: '%s'", path); + result = CURLE_COULDNT_RESOLVE_HOST; + } + else + result = CURLE_OUT_OF_MEMORY; + free(hostaddr); + hostaddr = NULL; + } + } + } + else +#endif + if(!conn->bits.proxy) { + struct hostname *connhost; + if(conn->bits.conn_to_host) + connhost = &conn->conn_to_host; + else + connhost = &conn->host; + + /* If not connecting via a proxy, extract the port from the URL, if it is + * there, thus overriding any defaults that might have been set above. */ + if(conn->bits.conn_to_port) + conn->port = conn->conn_to_port; + else + conn->port = conn->remote_port; + + /* Resolve target host right on */ + conn->hostname_resolve = strdup(connhost->name); + if(!conn->hostname_resolve) + return CURLE_OUT_OF_MEMORY; + rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port, + &hostaddr, timeout_ms); + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + + else if(rc == CURLRESOLV_TIMEDOUT) + result = CURLE_OPERATION_TIMEDOUT; + + else if(!hostaddr) { + failf(data, "Couldn't resolve host '%s'", connhost->dispname); + result = CURLE_COULDNT_RESOLVE_HOST; + /* don't return yet, we need to clean up the timeout first */ + } + } + else { + /* This is a proxy that hasn't been resolved yet. */ + + struct hostname * const host = conn->bits.socksproxy ? + &conn->socks_proxy.host : &conn->http_proxy.host; + + /* resolve proxy */ + conn->hostname_resolve = strdup(host->name); + if(!conn->hostname_resolve) + return CURLE_OUT_OF_MEMORY; + rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port, + &hostaddr, timeout_ms); + + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + + else if(rc == CURLRESOLV_TIMEDOUT) + result = CURLE_OPERATION_TIMEDOUT; + + else if(!hostaddr) { + failf(data, "Couldn't resolve proxy '%s'", host->dispname); + result = CURLE_COULDNT_RESOLVE_PROXY; + /* don't return yet, we need to clean up the timeout first */ + } + } + DEBUGASSERT(conn->dns_entry == NULL); + conn->dns_entry = hostaddr; + } + + return result; +} + +/* + * Cleanup the connection just allocated before we can move along and use the + * previously existing one. All relevant data is copied over and old_conn is + * ready for freeing once this function returns. + */ +static void reuse_conn(struct connectdata *old_conn, + struct connectdata *conn) +{ + free_idnconverted_hostname(&old_conn->http_proxy.host); + free_idnconverted_hostname(&old_conn->socks_proxy.host); + + free(old_conn->http_proxy.host.rawalloc); + free(old_conn->socks_proxy.host.rawalloc); + + /* free the SSL config struct from this connection struct as this was + allocated in vain and is targeted for destruction */ + Curl_free_primary_ssl_config(&old_conn->ssl_config); + Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config); + + conn->data = old_conn->data; + + /* get the user+password information from the old_conn struct since it may + * be new for this request even when we re-use an existing connection */ + conn->bits.user_passwd = old_conn->bits.user_passwd; + if(conn->bits.user_passwd) { + /* use the new user name and password though */ + Curl_safefree(conn->user); + Curl_safefree(conn->passwd); + conn->user = old_conn->user; + conn->passwd = old_conn->passwd; + old_conn->user = NULL; + old_conn->passwd = NULL; + } + + conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd; + if(conn->bits.proxy_user_passwd) { + /* use the new proxy user name and proxy password though */ + Curl_safefree(conn->http_proxy.user); + Curl_safefree(conn->socks_proxy.user); + Curl_safefree(conn->http_proxy.passwd); + Curl_safefree(conn->socks_proxy.passwd); + conn->http_proxy.user = old_conn->http_proxy.user; + conn->socks_proxy.user = old_conn->socks_proxy.user; + conn->http_proxy.passwd = old_conn->http_proxy.passwd; + conn->socks_proxy.passwd = old_conn->socks_proxy.passwd; + old_conn->http_proxy.user = NULL; + old_conn->socks_proxy.user = NULL; + old_conn->http_proxy.passwd = NULL; + old_conn->socks_proxy.passwd = NULL; + } + + /* host can change, when doing keepalive with a proxy or if the case is + different this time etc */ + free_idnconverted_hostname(&conn->host); + free_idnconverted_hostname(&conn->conn_to_host); + Curl_safefree(conn->host.rawalloc); + Curl_safefree(conn->conn_to_host.rawalloc); + conn->host = old_conn->host; + conn->conn_to_host = old_conn->conn_to_host; + conn->conn_to_port = old_conn->conn_to_port; + conn->remote_port = old_conn->remote_port; + Curl_safefree(conn->hostname_resolve); + + conn->hostname_resolve = old_conn->hostname_resolve; + old_conn->hostname_resolve = NULL; + + /* persist connection info in session handle */ + Curl_persistconninfo(conn); + + conn_reset_all_postponed_data(old_conn); /* free buffers */ + + /* re-use init */ + conn->bits.reuse = TRUE; /* yes, we're re-using here */ + + Curl_safefree(old_conn->user); + Curl_safefree(old_conn->passwd); + Curl_safefree(old_conn->options); + Curl_safefree(old_conn->http_proxy.user); + Curl_safefree(old_conn->socks_proxy.user); + Curl_safefree(old_conn->http_proxy.passwd); + Curl_safefree(old_conn->socks_proxy.passwd); + Curl_safefree(old_conn->localdev); + Curl_llist_destroy(&old_conn->easyq, NULL); + +#ifdef USE_UNIX_SOCKETS + Curl_safefree(old_conn->unix_domain_socket); +#endif +} + +/** + * create_conn() sets up a new connectdata struct, or re-uses an already + * existing one, and resolves host name. + * + * if this function returns CURLE_OK and *async is set to TRUE, the resolve + * response will be coming asynchronously. If *async is FALSE, the name is + * already resolved. + * + * @param data The sessionhandle pointer + * @param in_connect is set to the next connection data pointer + * @param async is set TRUE when an async DNS resolution is pending + * @see Curl_setup_conn() + * + * *NOTE* this function assigns the conn->data pointer! + */ + +static CURLcode create_conn(struct Curl_easy *data, + struct connectdata **in_connect, + bool *async) +{ + CURLcode result = CURLE_OK; + struct connectdata *conn; + struct connectdata *conn_temp = NULL; + bool reuse; + bool connections_available = TRUE; + bool force_reuse = FALSE; + bool waitpipe = FALSE; + size_t max_host_connections = Curl_multi_max_host_connections(data->multi); + size_t max_total_connections = Curl_multi_max_total_connections(data->multi); + + *async = FALSE; + *in_connect = NULL; + + /************************************************************* + * Check input data + *************************************************************/ + if(!data->change.url) { + result = CURLE_URL_MALFORMAT; + goto out; + } + + /* First, split up the current URL in parts so that we can use the + parts for checking against the already present connections. In order + to not have to modify everything at once, we allocate a temporary + connection data struct and fill in for comparison purposes. */ + conn = allocate_conn(data); + + if(!conn) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + /* We must set the return variable as soon as possible, so that our + parent can cleanup any possible allocs we may have done before + any failure */ + *in_connect = conn; + + result = parseurlandfillconn(data, conn); + if(result) + goto out; + + if(data->set.str[STRING_BEARER]) { + conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]); + if(!conn->oauth_bearer) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + +#ifdef USE_UNIX_SOCKETS + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); + if(conn->unix_domain_socket == NULL) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + conn->abstract_unix_socket = data->set.abstract_unix_socket; + } +#endif + + /* After the unix socket init but before the proxy vars are used, parse and + initialize the proxy vars */ +#ifndef CURL_DISABLE_PROXY + result = create_conn_helper_init_proxy(conn); + if(result) + goto out; +#endif + + /************************************************************* + * If the protocol is using SSL and HTTP proxy is used, we set + * the tunnel_proxy bit. + *************************************************************/ + if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy) + conn->bits.tunnel_proxy = TRUE; + + /************************************************************* + * Figure out the remote port number and fix it in the URL + *************************************************************/ + result = parse_remote_port(data, conn); + if(result) + goto out; + + /* Check for overridden login details and set them accordingly so they + they are known when protocol->setup_connection is called! */ + result = override_login(data, conn, &conn->user, &conn->passwd, + &conn->options); + if(result) + goto out; + + result = set_login(conn); /* default credentials */ + if(result) + goto out; + + /************************************************************* + * Process the "connect to" linked list of hostname/port mappings. + * Do this after the remote port number has been fixed in the URL. + *************************************************************/ + result = parse_connect_to_slist(data, conn, data->set.connect_to); + if(result) + goto out; + + /************************************************************* + * IDN-convert the hostnames + *************************************************************/ + result = idnconvert_hostname(conn, &conn->host); + if(result) + goto out; + if(conn->bits.conn_to_host) { + result = idnconvert_hostname(conn, &conn->conn_to_host); + if(result) + goto out; + } + if(conn->bits.httpproxy) { + result = idnconvert_hostname(conn, &conn->http_proxy.host); + if(result) + goto out; + } + if(conn->bits.socksproxy) { + result = idnconvert_hostname(conn, &conn->socks_proxy.host); + if(result) + goto out; + } + + /************************************************************* + * Check whether the host and the "connect to host" are equal. + * Do this after the hostnames have been IDN-converted. + *************************************************************/ + if(conn->bits.conn_to_host && + strcasecompare(conn->conn_to_host.name, conn->host.name)) { + conn->bits.conn_to_host = FALSE; + } + + /************************************************************* + * Check whether the port and the "connect to port" are equal. + * Do this after the remote port number has been fixed in the URL. + *************************************************************/ + if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) { + conn->bits.conn_to_port = FALSE; + } + + /************************************************************* + * If the "connect to" feature is used with an HTTP proxy, + * we set the tunnel_proxy bit. + *************************************************************/ + if((conn->bits.conn_to_host || conn->bits.conn_to_port) && + conn->bits.httpproxy) + conn->bits.tunnel_proxy = TRUE; + + /************************************************************* + * Setup internals depending on protocol. Needs to be done after + * we figured out what/if proxy to use. + *************************************************************/ + result = setup_connection_internals(conn); + if(result) + goto out; + + conn->recv[FIRSTSOCKET] = Curl_recv_plain; + conn->send[FIRSTSOCKET] = Curl_send_plain; + conn->recv[SECONDARYSOCKET] = Curl_recv_plain; + conn->send[SECONDARYSOCKET] = Curl_send_plain; + + conn->bits.tcp_fastopen = data->set.tcp_fastopen; + + /*********************************************************************** + * file: is a special case in that it doesn't need a network connection + ***********************************************************************/ +#ifndef CURL_DISABLE_FILE + if(conn->handler->flags & PROTOPT_NONETWORK) { + bool done; + /* this is supposed to be the connect function so we better at least check + that the file is present here! */ + DEBUGASSERT(conn->handler->connect_it); + Curl_persistconninfo(conn); + result = conn->handler->connect_it(conn, &done); + + /* Setup a "faked" transfer that'll do nothing */ + if(!result) { + conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */ + + result = Curl_conncache_add_conn(data->state.conn_cache, conn); + if(result) + goto out; + + /* + * Setup whatever necessary for a resumed transfer + */ + result = setup_range(data); + if(result) { + DEBUGASSERT(conn->handler->done); + /* we ignore the return code for the protocol-specific DONE */ + (void)conn->handler->done(conn, result, FALSE); + goto out; + } + Curl_attach_connnection(data, conn); + Curl_setup_transfer(data, -1, -1, FALSE, -1); + } + + /* since we skip do_init() */ + Curl_init_do(data, conn); + + goto out; + } +#endif + + /* Get a cloned copy of the SSL config situation stored in the + connection struct. But to get this going nicely, we must first make + sure that the strings in the master copy are pointing to the correct + strings in the session handle strings array! + + Keep in mind that the pointers in the master copy are pointing to strings + that will be freed as part of the Curl_easy struct, but all cloned + copies will be separately allocated. + */ + data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG]; + data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; + data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG]; + data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; + data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.proxy_ssl.primary.random_file = + data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_ORIG]; + data->set.proxy_ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; + data->set.ssl.primary.cipher_list13 = + data->set.str[STRING_SSL_CIPHER13_LIST_ORIG]; + data->set.proxy_ssl.primary.cipher_list13 = + data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; + + data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG]; + data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; + data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG]; + data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; + data->set.ssl.cert = data->set.str[STRING_CERT_ORIG]; + data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY]; + data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG]; + data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; + data->set.ssl.key = data->set.str[STRING_KEY_ORIG]; + data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; + data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG]; + data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; + data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG]; + data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; + data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG]; + data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; +#ifdef USE_TLS_SRP + data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG]; + data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG]; + data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; +#endif + + if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, + &conn->ssl_config)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary, + &conn->proxy_ssl_config)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + prune_dead_connections(data); + + /************************************************************* + * Check the current list of connections to see if we can + * re-use an already existing one or if we have to create a + * new one. + *************************************************************/ + + DEBUGASSERT(conn->user); + DEBUGASSERT(conn->passwd); + + /* reuse_fresh is TRUE if we are told to use a new connection by force, but + we only acknowledge this option if this is not a re-used connection + already (which happens due to follow-location or during a HTTP + authentication phase). CONNECT_ONLY transfers also refuse reuse. */ + if((data->set.reuse_fresh && !data->state.this_is_a_follow) || + data->set.connect_only) + reuse = FALSE; + else + reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe); + + /* If we found a reusable connection that is now marked as in use, we may + still want to open a new connection if we are multiplexing. */ + if(reuse && !force_reuse && IsMultiplexingPossible(data, conn_temp)) { + size_t multiplexed = CONN_INUSE(conn_temp); + if(multiplexed > 0) { + infof(data, "Found connection %ld, with %zu requests on it\n", + conn_temp->connection_id, multiplexed); + + if(Curl_conncache_bundle_size(conn_temp) < max_host_connections && + Curl_conncache_size(data) < max_total_connections) { + /* We want a new connection anyway */ + reuse = FALSE; + + infof(data, "We can reuse, but we want a new connection anyway\n"); + Curl_conncache_return_conn(conn_temp); + } + } + } + + if(reuse) { + /* + * We already have a connection for this, we got the former connection + * in the conn_temp variable and thus we need to cleanup the one we + * just allocated before we can move along and use the previously + * existing one. + */ + reuse_conn(conn, conn_temp); +#ifdef USE_SSL + free(conn->ssl_extra); +#endif + free(conn); /* we don't need this anymore */ + conn = conn_temp; + *in_connect = conn; + + infof(data, "Re-using existing connection! (#%ld) with %s %s\n", + conn->connection_id, + conn->bits.proxy?"proxy":"host", + conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname : + conn->http_proxy.host.name ? conn->http_proxy.host.dispname : + conn->host.dispname); + } + else { + /* We have decided that we want a new connection. However, we may not + be able to do that if we have reached the limit of how many + connections we are allowed to open. */ + + if(conn->handler->flags & PROTOPT_ALPN_NPN) { + /* The protocol wants it, so set the bits if enabled in the easy handle + (default) */ + if(data->set.ssl_enable_alpn) + conn->bits.tls_enable_alpn = TRUE; + if(data->set.ssl_enable_npn) + conn->bits.tls_enable_npn = TRUE; + } + + if(waitpipe) + /* There is a connection that *might* become usable for multiplexing + "soon", and we wait for that */ + connections_available = FALSE; + else { + /* this gets a lock on the conncache */ + const char *bundlehost; + struct connectbundle *bundle = + Curl_conncache_find_bundle(conn, data->state.conn_cache, &bundlehost); + + if(max_host_connections > 0 && bundle && + (bundle->num_connections >= max_host_connections)) { + struct connectdata *conn_candidate; + + /* The bundle is full. Extract the oldest connection. */ + conn_candidate = Curl_conncache_extract_bundle(data, bundle); + Curl_conncache_unlock(data); + + if(conn_candidate) + (void)Curl_disconnect(data, conn_candidate, + /* dead_connection */ FALSE); + else { + infof(data, "No more connections allowed to host %s: %zu\n", + bundlehost, max_host_connections); + connections_available = FALSE; + } + } + else + Curl_conncache_unlock(data); + + } + + if(connections_available && + (max_total_connections > 0) && + (Curl_conncache_size(data) >= max_total_connections)) { + struct connectdata *conn_candidate; + + /* The cache is full. Let's see if we can kill a connection. */ + conn_candidate = Curl_conncache_extract_oldest(data); + if(conn_candidate) + (void)Curl_disconnect(data, conn_candidate, + /* dead_connection */ FALSE); + else { + infof(data, "No connections available in cache\n"); + connections_available = FALSE; + } + } + + if(!connections_available) { + infof(data, "No connections available.\n"); + + conn_free(conn); + *in_connect = NULL; + + result = CURLE_NO_CONNECTION_AVAILABLE; + goto out; + } + else { + /* + * This is a brand new connection, so let's store it in the connection + * cache of ours! + */ + result = Curl_conncache_add_conn(data->state.conn_cache, conn); + if(result) + goto out; + } + +#if defined(USE_NTLM) + /* If NTLM is requested in a part of this connection, make sure we don't + assume the state is fine as this is a fresh connection and NTLM is + connection based. */ + if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + data->state.authhost.done) { + infof(data, "NTLM picked AND auth done set, clear picked!\n"); + data->state.authhost.picked = CURLAUTH_NONE; + data->state.authhost.done = FALSE; + } + + if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + data->state.authproxy.done) { + infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n"); + data->state.authproxy.picked = CURLAUTH_NONE; + data->state.authproxy.done = FALSE; + } +#endif + } + + /* Setup and init stuff before DO starts, in preparing for the transfer. */ + Curl_init_do(data, conn); + + /* + * Setup whatever necessary for a resumed transfer + */ + result = setup_range(data); + if(result) + goto out; + + /* Continue connectdata initialization here. */ + + /* + * Inherit the proper values from the urldata struct AFTER we have arranged + * the persistent connection stuff + */ + conn->seek_func = data->set.seek_func; + conn->seek_client = data->set.seek_client; + + /************************************************************* + * Resolve the address of the server or proxy + *************************************************************/ + result = resolve_server(data, conn, async); + + /* Strip trailing dots. resolve_server copied the name. */ + strip_trailing_dot(&conn->host); + if(conn->bits.httpproxy) + strip_trailing_dot(&conn->http_proxy.host); + if(conn->bits.socksproxy) + strip_trailing_dot(&conn->socks_proxy.host); + if(conn->bits.conn_to_host) + strip_trailing_dot(&conn->conn_to_host); + +out: + return result; +} + +/* Curl_setup_conn() is called after the name resolve initiated in + * create_conn() is all done. + * + * Curl_setup_conn() also handles reused connections + * + * conn->data MUST already have been setup fine (in create_conn) + */ + +CURLcode Curl_setup_conn(struct connectdata *conn, + bool *protocol_done) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + Curl_pgrsTime(data, TIMER_NAMELOOKUP); + + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* nothing to setup when not using a network */ + *protocol_done = TRUE; + return result; + } + *protocol_done = FALSE; /* default to not done */ + + /* set proxy_connect_closed to false unconditionally already here since it + is used strictly to provide extra information to a parent function in the + case of proxy CONNECT failures and we must make sure we don't have it + lingering set from a previous invoke */ + conn->bits.proxy_connect_closed = FALSE; + + /* + * Set user-agent. Used for HTTP, but since we can attempt to tunnel + * basically anything through a http proxy we can't limit this based on + * protocol. + */ + if(data->set.str[STRING_USERAGENT]) { + Curl_safefree(conn->allocptr.uagent); + conn->allocptr.uagent = + aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]); + if(!conn->allocptr.uagent) + return CURLE_OUT_OF_MEMORY; + } + + data->req.headerbytecount = 0; + +#ifdef CURL_DO_LINEEND_CONV + data->state.crlf_conversions = 0; /* reset CRLF conversion counter */ +#endif /* CURL_DO_LINEEND_CONV */ + + /* set start time here for timeout purposes in the connect procedure, it + is later set again for the progress meter purpose */ + conn->now = Curl_now(); + + if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) { + conn->bits.tcpconnect[FIRSTSOCKET] = FALSE; + result = Curl_connecthost(conn, conn->dns_entry); + if(result) + return result; + } + else { + Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */ + Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */ + conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; + *protocol_done = TRUE; + Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]); + Curl_verboseconnect(conn); + } + + conn->now = Curl_now(); /* time this *after* the connect is done, we set + this here perhaps a second time */ + return result; +} + +CURLcode Curl_connect(struct Curl_easy *data, + bool *asyncp, + bool *protocol_done) +{ + CURLcode result; + struct connectdata *conn; + + *asyncp = FALSE; /* assume synchronous resolves by default */ + + /* init the single-transfer specific data */ + Curl_free_request_state(data); + memset(&data->req, 0, sizeof(struct SingleRequest)); + data->req.maxdownload = -1; + + /* call the stuff that needs to be called */ + result = create_conn(data, &conn, asyncp); + + if(!result) { + if(CONN_INUSE(conn)) + /* multiplexed */ + *protocol_done = TRUE; + else if(!*asyncp) { + /* DNS resolution is done: that's either because this is a reused + connection, in which case DNS was unnecessary, or because DNS + really did finish already (synch resolver/fast async resolve) */ + result = Curl_setup_conn(conn, protocol_done); + } + } + + if(result == CURLE_NO_CONNECTION_AVAILABLE) { + return result; + } + else if(result && conn) { + /* We're not allowed to return failure with memory left allocated in the + connectdata struct, free those here */ + Curl_disconnect(data, conn, TRUE); + } + else if(!result && !data->conn) + /* FILE: transfers already have the connection attached */ + Curl_attach_connnection(data, conn); + + return result; +} + +/* + * Curl_init_do() inits the readwrite session. This is inited each time (in + * the DO function before the protocol-specific DO functions are invoked) for + * a transfer, sometimes multiple times on the same Curl_easy. Make sure + * nothing in here depends on stuff that are setup dynamically for the + * transfer. + * + * Allow this function to get called with 'conn' set to NULL. + */ + +CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) +{ + struct SingleRequest *k = &data->req; + + if(conn) { + conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to + use */ + /* if the protocol used doesn't support wildcards, switch it off */ + if(data->state.wildcardmatch && + !(conn->handler->flags & PROTOPT_WILDCARD)) + data->state.wildcardmatch = FALSE; + } + + data->state.done = FALSE; /* *_done() is not called yet */ + data->state.expect100header = FALSE; + + + if(data->set.opt_no_body) + /* in HTTP lingo, no body means using the HEAD request... */ + data->set.httpreq = HTTPREQ_HEAD; + else if(HTTPREQ_HEAD == data->set.httpreq) + /* ... but if unset there really is no perfect method that is the + "opposite" of HEAD but in reality most people probably think GET + then. The important thing is that we can't let it remain HEAD if the + opt_no_body is set FALSE since then we'll behave wrong when getting + HTTP. */ + data->set.httpreq = HTTPREQ_GET; + + k->start = Curl_now(); /* start time */ + k->now = k->start; /* current time is now */ + k->header = TRUE; /* assume header */ + + k->bytecount = 0; + + k->buf = data->state.buffer; + k->hbufp = data->state.headerbuff; + k->ignorebody = FALSE; + + Curl_speedinit(data); + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + + return CURLE_OK; +} + +/* +* get_protocol_family() +* +* This is used to return the protocol family for a given protocol. +* +* Parameters: +* +* protocol [in] - A single bit protocol identifier such as HTTP or HTTPS. +* +* Returns the family as a single bit protocol identifier. +*/ + +static unsigned int get_protocol_family(unsigned int protocol) +{ + unsigned int family; + + switch(protocol) { + case CURLPROTO_HTTP: + case CURLPROTO_HTTPS: + family = CURLPROTO_HTTP; + break; + + case CURLPROTO_FTP: + case CURLPROTO_FTPS: + family = CURLPROTO_FTP; + break; + + case CURLPROTO_SCP: + family = CURLPROTO_SCP; + break; + + case CURLPROTO_SFTP: + family = CURLPROTO_SFTP; + break; + + case CURLPROTO_TELNET: + family = CURLPROTO_TELNET; + break; + + case CURLPROTO_LDAP: + case CURLPROTO_LDAPS: + family = CURLPROTO_LDAP; + break; + + case CURLPROTO_DICT: + family = CURLPROTO_DICT; + break; + + case CURLPROTO_FILE: + family = CURLPROTO_FILE; + break; + + case CURLPROTO_TFTP: + family = CURLPROTO_TFTP; + break; + + case CURLPROTO_IMAP: + case CURLPROTO_IMAPS: + family = CURLPROTO_IMAP; + break; + + case CURLPROTO_POP3: + case CURLPROTO_POP3S: + family = CURLPROTO_POP3; + break; + + case CURLPROTO_SMTP: + case CURLPROTO_SMTPS: + family = CURLPROTO_SMTP; + break; + + case CURLPROTO_RTSP: + family = CURLPROTO_RTSP; + break; + + case CURLPROTO_RTMP: + case CURLPROTO_RTMPS: + family = CURLPROTO_RTMP; + break; + + case CURLPROTO_RTMPT: + case CURLPROTO_RTMPTS: + family = CURLPROTO_RTMPT; + break; + + case CURLPROTO_RTMPE: + family = CURLPROTO_RTMPE; + break; + + case CURLPROTO_RTMPTE: + family = CURLPROTO_RTMPTE; + break; + + case CURLPROTO_GOPHER: + family = CURLPROTO_GOPHER; + break; + + case CURLPROTO_SMB: + case CURLPROTO_SMBS: + family = CURLPROTO_SMB; + break; + + default: + family = 0; + break; + } + + return family; +} + + +/* + * Wrapper to call functions in Curl_conncache_foreach() + * + * Returns always 0. + */ +static int conn_upkeep(struct connectdata *conn, + void *param) +{ + /* Param is unused. */ + (void)param; + + if(conn->handler->connection_check) { + /* Do a protocol-specific keepalive check on the connection. */ + conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE); + } + + return 0; /* continue iteration */ +} + +CURLcode Curl_upkeep(struct conncache *conn_cache, + void *data) +{ + /* Loop over every connection and make connection alive. */ + Curl_conncache_foreach(data, + conn_cache, + data, + conn_upkeep); + return CURLE_OK; +} diff --git a/libcurl/lib/url.h b/libcurl/lib/url.h new file mode 100644 index 0000000..7c87432 --- /dev/null +++ b/libcurl/lib/url.h @@ -0,0 +1,100 @@ +#ifndef HEADER_CURL_URL_H +#define HEADER_CURL_URL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE +#define READBUFFER_MAX CURL_MAX_READ_SIZE +#define READBUFFER_MIN 1024 + +/* The default upload buffer size, should not be smaller than + CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in + a write callback. + + The size was 16KB for many years but was bumped to 64KB because it makes + libcurl able to do significantly faster uploads in some circumstances. Even + larger buffers can help further, but this is deemed a fair memory/speed + compromise. */ +#define UPLOADBUFFER_DEFAULT 65536 +#define UPLOADBUFFER_MAX (2*1024*1024) +#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE + +/* + * Prototypes for library-wide functions provided by url.c + */ + +CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn); +CURLcode Curl_open(struct Curl_easy **curl); +CURLcode Curl_init_userdefined(struct Curl_easy *data); + +void Curl_freeset(struct Curl_easy * data); +CURLcode Curl_uc_to_curlcode(CURLUcode uc); +CURLcode Curl_close(struct Curl_easy *data); /* opposite of curl_open() */ +CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect); +CURLcode Curl_disconnect(struct Curl_easy *data, + struct connectdata *, bool dead_connection); +CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done); +CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done); +CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done); +CURLcode Curl_setup_conn(struct connectdata *conn, + bool *protocol_done); +void Curl_free_request_state(struct Curl_easy *data); + +int Curl_protocol_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +int Curl_doing_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +CURLcode Curl_parse_login_details(const char *login, const size_t len, + char **userptr, char **passwdptr, + char **optionsptr); +CURLcode Curl_upkeep(struct conncache *conn_cache, void *data); + +const struct Curl_handler *Curl_builtin_scheme(const char *scheme); + +#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ +#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless + specified */ + +CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define Curl_verboseconnect(x) Curl_nop_stmt +#else +void Curl_verboseconnect(struct connectdata *conn); +#endif + +#define CONNECT_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[sockindex]) + +#define CONNECT_FIRSTSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[FIRSTSOCKET]) + +#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[SECONDARYSOCKET]) + +#endif /* HEADER_CURL_URL_H */ diff --git a/libcurl/lib/urlapi-int.h b/libcurl/lib/urlapi-int.h new file mode 100644 index 0000000..d14d53d --- /dev/null +++ b/libcurl/lib/urlapi-int.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_URLAPI_INT_H +#define HEADER_CURL_URLAPI_INT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +/* scheme is not URL encoded, the longest libcurl supported ones are... */ +#define MAX_SCHEME_LEN 40 + +bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen); + +#ifdef DEBUGBUILD +CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname); +#endif + +#endif /* HEADER_CURL_URLAPI_INT_H */ diff --git a/libcurl/lib/urlapi.c b/libcurl/lib/urlapi.c new file mode 100644 index 0000000..d07e4f5 --- /dev/null +++ b/libcurl/lib/urlapi.c @@ -0,0 +1,1440 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "urldata.h" +#include "urlapi-int.h" +#include "strcase.h" +#include "dotdot.h" +#include "url.h" +#include "escape.h" +#include "curl_ctype.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + + /* MSDOS/Windows style drive prefix, eg c: in c:foo */ +#define STARTS_WITH_DRIVE_PREFIX(str) \ + ((('a' <= str[0] && str[0] <= 'z') || \ + ('A' <= str[0] && str[0] <= 'Z')) && \ + (str[1] == ':')) + + /* MSDOS/Windows style drive prefix, optionally with + * a '|' instead of ':', followed by a slash or NUL */ +#define STARTS_WITH_URL_DRIVE_PREFIX(str) \ + ((('a' <= (str)[0] && (str)[0] <= 'z') || \ + ('A' <= (str)[0] && (str)[0] <= 'Z')) && \ + ((str)[1] == ':' || (str)[1] == '|') && \ + ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0)) + +/* Internal representation of CURLU. Point to URL-encoded strings. */ +struct Curl_URL { + char *scheme; + char *user; + char *password; + char *options; /* IMAP only? */ + char *host; + char *zoneid; /* for numerical IPv6 addresses */ + char *port; + char *path; + char *query; + char *fragment; + + char *scratch; /* temporary scratch area */ + long portnum; /* the numerical version */ +}; + +#define DEFAULT_SCHEME "https" + +static void free_urlhandle(struct Curl_URL *u) +{ + free(u->scheme); + free(u->user); + free(u->password); + free(u->options); + free(u->host); + free(u->zoneid); + free(u->port); + free(u->path); + free(u->query); + free(u->fragment); + free(u->scratch); +} + +/* move the full contents of one handle onto another and + free the original */ +static void mv_urlhandle(struct Curl_URL *from, + struct Curl_URL *to) +{ + free_urlhandle(to); + *to = *from; + free(from); +} + +/* + * Find the separator at the end of the host name, or the '?' in cases like + * http://www.url.com?id=2380 + */ +static const char *find_host_sep(const char *url) +{ + const char *sep; + const char *query; + + /* Find the start of the hostname */ + sep = strstr(url, "//"); + if(!sep) + sep = url; + else + sep += 2; + + query = strchr(sep, '?'); + sep = strchr(sep, '/'); + + if(!sep) + sep = url + strlen(url); + + if(!query) + query = url + strlen(url); + + return sep < query ? sep : query; +} + +/* + * Decide in an encoding-independent manner whether a character in an + * URL must be escaped. The same criterion must be used in strlen_url() + * and strcpy_url(). + */ +static bool urlchar_needs_escaping(int c) +{ + return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c)); +} + +/* + * strlen_url() returns the length of the given URL if the spaces within the + * URL were properly URL encoded. + * URL encoding should be skipped for host names, otherwise IDN resolution + * will fail. + */ +static size_t strlen_url(const char *url, bool relative) +{ + const unsigned char *ptr; + size_t newlen = 0; + bool left = TRUE; /* left side of the ? */ + const unsigned char *host_sep = (const unsigned char *) url; + + if(!relative) + host_sep = (const unsigned char *) find_host_sep(url); + + for(ptr = (unsigned char *)url; *ptr; ptr++) { + + if(ptr < host_sep) { + ++newlen; + continue; + } + + switch(*ptr) { + case '?': + left = FALSE; + /* FALLTHROUGH */ + default: + if(urlchar_needs_escaping(*ptr)) + newlen += 2; + newlen++; + break; + case ' ': + if(left) + newlen += 3; + else + newlen++; + break; + } + } + return newlen; +} + +/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in + * the source URL accordingly. + * URL encoding should be skipped for host names, otherwise IDN resolution + * will fail. + */ +static void strcpy_url(char *output, const char *url, bool relative) +{ + /* we must add this with whitespace-replacing */ + bool left = TRUE; + const unsigned char *iptr; + char *optr = output; + const unsigned char *host_sep = (const unsigned char *) url; + + if(!relative) + host_sep = (const unsigned char *) find_host_sep(url); + + for(iptr = (unsigned char *)url; /* read from here */ + *iptr; /* until zero byte */ + iptr++) { + + if(iptr < host_sep) { + *optr++ = *iptr; + continue; + } + + switch(*iptr) { + case '?': + left = FALSE; + /* FALLTHROUGH */ + default: + if(urlchar_needs_escaping(*iptr)) { + msnprintf(optr, 4, "%%%02x", *iptr); + optr += 3; + } + else + *optr++=*iptr; + break; + case ' ': + if(left) { + *optr++='%'; /* add a '%' */ + *optr++='2'; /* add a '2' */ + *optr++='0'; /* add a '0' */ + } + else + *optr++='+'; /* add a '+' here */ + break; + } + } + *optr = 0; /* zero terminate output buffer */ + +} + +/* + * Returns true if the given URL is absolute (as opposed to relative) within + * the buffer size. Returns the scheme in the buffer if TRUE and 'buf' is + * non-NULL. + */ +bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen) +{ + size_t i; +#ifdef WIN32 + if(STARTS_WITH_DRIVE_PREFIX(url)) + return FALSE; +#endif + for(i = 0; i < buflen && url[i]; ++i) { + char s = url[i]; + if((s == ':') && (url[i + 1] == '/')) { + if(buf) + buf[i] = 0; + return TRUE; + } + /* RFC 3986 3.1 explains: + scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + */ + else if(ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') ) { + if(buf) + buf[i] = (char)TOLOWER(s); + } + else + break; + } + return FALSE; +} + +/* + * Concatenate a relative URL to a base URL making it absolute. + * URL-encodes any spaces. + * The returned pointer must be freed by the caller unless NULL + * (returns NULL on out of memory). + */ +static char *concat_url(const char *base, const char *relurl) +{ + /*** + TRY to append this new path to the old URL + to the right of the host part. Oh crap, this is doomed to cause + problems in the future... + */ + char *newest; + char *protsep; + char *pathsep; + size_t newlen; + bool host_changed = FALSE; + + const char *useurl = relurl; + size_t urllen; + + /* we must make our own copy of the URL to play with, as it may + point to read-only data */ + char *url_clone = strdup(base); + + if(!url_clone) + return NULL; /* skip out of this NOW */ + + /* protsep points to the start of the host name */ + protsep = strstr(url_clone, "//"); + if(!protsep) + protsep = url_clone; + else + protsep += 2; /* pass the slashes */ + + if('/' != relurl[0]) { + int level = 0; + + /* First we need to find out if there's a ?-letter in the URL, + and cut it and the right-side of that off */ + pathsep = strchr(protsep, '?'); + if(pathsep) + *pathsep = 0; + + /* we have a relative path to append to the last slash if there's one + available, or if the new URL is just a query string (starts with a + '?') we append the new one at the end of the entire currently worked + out URL */ + if(useurl[0] != '?') { + pathsep = strrchr(protsep, '/'); + if(pathsep) + *pathsep = 0; + } + + /* Check if there's any slash after the host name, and if so, remember + that position instead */ + pathsep = strchr(protsep, '/'); + if(pathsep) + protsep = pathsep + 1; + else + protsep = NULL; + + /* now deal with one "./" or any amount of "../" in the newurl + and act accordingly */ + + if((useurl[0] == '.') && (useurl[1] == '/')) + useurl += 2; /* just skip the "./" */ + + while((useurl[0] == '.') && + (useurl[1] == '.') && + (useurl[2] == '/')) { + level++; + useurl += 3; /* pass the "../" */ + } + + if(protsep) { + while(level--) { + /* cut off one more level from the right of the original URL */ + pathsep = strrchr(protsep, '/'); + if(pathsep) + *pathsep = 0; + else { + *protsep = 0; + break; + } + } + } + } + else { + /* We got a new absolute path for this server */ + + if((relurl[0] == '/') && (relurl[1] == '/')) { + /* the new URL starts with //, just keep the protocol part from the + original one */ + *protsep = 0; + useurl = &relurl[2]; /* we keep the slashes from the original, so we + skip the new ones */ + host_changed = TRUE; + } + else { + /* cut off the original URL from the first slash, or deal with URLs + without slash */ + pathsep = strchr(protsep, '/'); + if(pathsep) { + /* When people use badly formatted URLs, such as + "http://www.url.com?dir=/home/daniel" we must not use the first + slash, if there's a ?-letter before it! */ + char *sep = strchr(protsep, '?'); + if(sep && (sep < pathsep)) + pathsep = sep; + *pathsep = 0; + } + else { + /* There was no slash. Now, since we might be operating on a badly + formatted URL, such as "http://www.url.com?id=2380" which doesn't + use a slash separator as it is supposed to, we need to check for a + ?-letter as well! */ + pathsep = strchr(protsep, '?'); + if(pathsep) + *pathsep = 0; + } + } + } + + /* If the new part contains a space, this is a mighty stupid redirect + but we still make an effort to do "right". To the left of a '?' + letter we replace each space with %20 while it is replaced with '+' + on the right side of the '?' letter. + */ + newlen = strlen_url(useurl, !host_changed); + + urllen = strlen(url_clone); + + newest = malloc(urllen + 1 + /* possible slash */ + newlen + 1 /* zero byte */); + + if(!newest) { + free(url_clone); /* don't leak this */ + return NULL; + } + + /* copy over the root url part */ + memcpy(newest, url_clone, urllen); + + /* check if we need to append a slash */ + if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0])) + ; + else + newest[urllen++]='/'; + + /* then append the new piece on the right side */ + strcpy_url(&newest[urllen], useurl, !host_changed); + + free(url_clone); + + return newest; +} + +/* + * parse_hostname_login() + * + * Parse the login details (user name, password and options) from the URL and + * strip them out of the host name + * + */ +static CURLUcode parse_hostname_login(struct Curl_URL *u, + const struct Curl_handler *h, + char **hostname, + unsigned int flags) +{ + CURLUcode result = CURLUE_OK; + CURLcode ccode; + char *userp = NULL; + char *passwdp = NULL; + char *optionsp = NULL; + + /* At this point, we're hoping all the other special cases have + * been taken care of, so conn->host.name is at most + * [user[:password][;options]]@]hostname + * + * We need somewhere to put the embedded details, so do that first. + */ + + char *ptr = strchr(*hostname, '@'); + char *login = *hostname; + + if(!ptr) + goto out; + + /* We will now try to extract the + * possible login information in a string like: + * ftp://user:password@ftp.my.site:8021/README */ + *hostname = ++ptr; + + /* We could use the login information in the URL so extract it. Only parse + options if the handler says we should. Note that 'h' might be NULL! */ + ccode = Curl_parse_login_details(login, ptr - login - 1, + &userp, &passwdp, + (h && (h->flags & PROTOPT_URLOPTIONS)) ? + &optionsp:NULL); + if(ccode) { + result = CURLUE_MALFORMED_INPUT; + goto out; + } + + if(userp) { + if(flags & CURLU_DISALLOW_USER) { + /* Option DISALLOW_USER is set and url contains username. */ + result = CURLUE_USER_NOT_ALLOWED; + goto out; + } + + u->user = userp; + } + + if(passwdp) + u->password = passwdp; + + if(optionsp) + u->options = optionsp; + + return CURLUE_OK; + out: + + free(userp); + free(passwdp); + free(optionsp); + + return result; +} + +UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname) +{ + char *portptr = NULL; + char endbracket; + int len; + + /* + * Find the end of an IPv6 address, either on the ']' ending bracket or + * a percent-encoded zone index. + */ + if(1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.]%c%n", + &endbracket, &len)) { + if(']' == endbracket) + portptr = &hostname[len]; + else if('%' == endbracket) { + int zonelen = len; + if(1 == sscanf(hostname + zonelen, "%*[^]]%c%n", &endbracket, &len)) { + if(']' != endbracket) + return CURLUE_MALFORMED_INPUT; + portptr = &hostname[--zonelen + len + 1]; + } + else + return CURLUE_MALFORMED_INPUT; + } + else + return CURLUE_MALFORMED_INPUT; + + /* this is a RFC2732-style specified IP-address */ + if(portptr && *portptr) { + if(*portptr != ':') + return CURLUE_MALFORMED_INPUT; + } + else + portptr = NULL; + } + else + portptr = strchr(hostname, ':'); + + if(portptr) { + char *rest; + long port; + char portbuf[7]; + + /* Browser behavior adaptation. If there's a colon with no digits after, + just cut off the name there which makes us ignore the colon and just + use the default port. Firefox, Chrome and Safari all do that. */ + if(!portptr[1]) { + *portptr = '\0'; + return CURLUE_OK; + } + + if(!ISDIGIT(portptr[1])) + return CURLUE_BAD_PORT_NUMBER; + + port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */ + + if((port <= 0) || (port > 0xffff)) + /* Single unix standard says port numbers are 16 bits long, but we don't + treat port zero as OK. */ + return CURLUE_BAD_PORT_NUMBER; + + if(rest[0]) + return CURLUE_BAD_PORT_NUMBER; + + *portptr++ = '\0'; /* cut off the name there */ + *rest = 0; + /* generate a new port number string to get rid of leading zeroes etc */ + msnprintf(portbuf, sizeof(portbuf), "%ld", port); + u->portnum = port; + u->port = strdup(portbuf); + if(!u->port) + return CURLUE_OUT_OF_MEMORY; + } + + return CURLUE_OK; +} + +/* scan for byte values < 31 or 127 */ +static CURLUcode junkscan(char *part) +{ + if(part) { + static const char badbytes[]={ + /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x7f, + 0x00 /* zero terminate */ + }; + size_t n = strlen(part); + size_t nfine = strcspn(part, badbytes); + if(nfine != n) + /* since we don't know which part is scanned, return a generic error + code */ + return CURLUE_MALFORMED_INPUT; + } + return CURLUE_OK; +} + +static CURLUcode hostname_check(struct Curl_URL *u, char *hostname) +{ + const char *l = NULL; /* accepted characters */ + size_t len; + size_t hlen = strlen(hostname); + + if(hostname[0] == '[') { + hostname++; + l = "0123456789abcdefABCDEF::."; + hlen -= 2; + } + + if(l) { + /* only valid letters are ok */ + len = strspn(hostname, l); + if(hlen != len) { + if(hostname[len] == '%') { + /* this could now be '%[zone id]' */ + char zoneid[16]; + int i = 0; + char *h = &hostname[len + 1]; + /* pass '25' if present and is a url encoded percent sign */ + if(!strncmp(h, "25", 2) && h[2] && (h[2] != ']')) + h += 2; + while(*h && (*h != ']') && (i < 15)) + zoneid[i++] = *h++; + if(!i || (']' != *h)) + return CURLUE_MALFORMED_INPUT; + zoneid[i] = 0; + u->zoneid = strdup(zoneid); + if(!u->zoneid) + return CURLUE_OUT_OF_MEMORY; + hostname[len] = ']'; /* insert end bracket */ + hostname[len + 1] = 0; /* terminate the hostname */ + } + else + return CURLUE_MALFORMED_INPUT; + /* hostname is fine */ + } + } + else { + /* letters from the second string is not ok */ + len = strcspn(hostname, " "); + if(hlen != len) + /* hostname with bad content */ + return CURLUE_MALFORMED_INPUT; + } + if(!hostname[0]) + return CURLUE_NO_HOST; + return CURLUE_OK; +} + +#define HOSTNAME_END(x) (((x) == '/') || ((x) == '?') || ((x) == '#')) + +static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) +{ + char *path; + bool path_alloced = FALSE; + char *hostname; + char *query = NULL; + char *fragment = NULL; + CURLUcode result; + bool url_has_scheme = FALSE; + char schemebuf[MAX_SCHEME_LEN + 1]; + char *schemep = NULL; + size_t schemelen = 0; + size_t urllen; + const struct Curl_handler *h = NULL; + + if(!url) + return CURLUE_MALFORMED_INPUT; + + /************************************************************* + * Parse the URL. + ************************************************************/ + /* allocate scratch area */ + urllen = strlen(url); + if(urllen > CURL_MAX_INPUT_LENGTH) + /* excessive input length */ + return CURLUE_MALFORMED_INPUT; + + path = u->scratch = malloc(urllen * 2 + 2); + if(!path) + return CURLUE_OUT_OF_MEMORY; + + hostname = &path[urllen + 1]; + hostname[0] = 0; + + if(Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf))) { + url_has_scheme = TRUE; + schemelen = strlen(schemebuf); + } + + /* handle the file: scheme */ + if(url_has_scheme && strcasecompare(schemebuf, "file")) { + /* path has been allocated large enough to hold this */ + strcpy(path, &url[5]); + + hostname = NULL; /* no host for file: URLs */ + u->scheme = strdup("file"); + if(!u->scheme) + return CURLUE_OUT_OF_MEMORY; + + /* Extra handling URLs with an authority component (i.e. that start with + * "file://") + * + * We allow omitted hostname (e.g. file:/) -- valid according to + * RFC 8089, but not the (current) WHAT-WG URL spec. + */ + if(path[0] == '/' && path[1] == '/') { + /* swallow the two slashes */ + char *ptr = &path[2]; + + /* + * According to RFC 8089, a file: URL can be reliably dereferenced if: + * + * o it has no/blank hostname, or + * + * o the hostname matches "localhost" (case-insensitively), or + * + * o the hostname is a FQDN that resolves to this machine. + * + * For brevity, we only consider URLs with empty, "localhost", or + * "127.0.0.1" hostnames as local. + * + * Additionally, there is an exception for URLs with a Windows drive + * letter in the authority (which was accidentally omitted from RFC 8089 + * Appendix E, but believe me, it was meant to be there. --MK) + */ + if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) { + /* the URL includes a host name, it must match "localhost" or + "127.0.0.1" to be valid */ + if(!checkprefix("localhost/", ptr) && + !checkprefix("127.0.0.1/", ptr)) { + /* Invalid file://hostname/, expected localhost or 127.0.0.1 or + none */ + return CURLUE_MALFORMED_INPUT; + } + ptr += 9; /* now points to the slash after the host */ + } + + path = ptr; + } + +#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__) + /* Don't allow Windows drive letters when not in Windows. + * This catches both "file:/c:" and "file:c:" */ + if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) || + STARTS_WITH_URL_DRIVE_PREFIX(path)) { + /* File drive letters are only accepted in MSDOS/Windows */ + return CURLUE_MALFORMED_INPUT; + } +#else + /* If the path starts with a slash and a drive letter, ditch the slash */ + if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) { + /* This cannot be done with strcpy, as the memory chunks overlap! */ + memmove(path, &path[1], strlen(&path[1]) + 1); + } +#endif + + } + else { + /* clear path */ + const char *p; + const char *hostp; + size_t len; + path[0] = 0; + + if(url_has_scheme) { + int i = 0; + p = &url[schemelen + 1]; + while(p && (*p == '/') && (i < 4)) { + p++; + i++; + } + if((i < 1) || (i>3)) + /* less than one or more than three slashes */ + return CURLUE_MALFORMED_INPUT; + + schemep = schemebuf; + if(!Curl_builtin_scheme(schemep) && + !(flags & CURLU_NON_SUPPORT_SCHEME)) + return CURLUE_UNSUPPORTED_SCHEME; + + if(junkscan(schemep)) + return CURLUE_MALFORMED_INPUT; + } + else { + /* no scheme! */ + + if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME))) + return CURLUE_MALFORMED_INPUT; + if(flags & CURLU_DEFAULT_SCHEME) + schemep = (char *) DEFAULT_SCHEME; + + /* + * The URL was badly formatted, let's try without scheme specified. + */ + p = url; + } + hostp = p; /* host name starts here */ + + while(*p && !HOSTNAME_END(*p)) /* find end of host name */ + p++; + + len = p - hostp; + if(!len) + return CURLUE_MALFORMED_INPUT; + + memcpy(hostname, hostp, len); + hostname[len] = 0; + + if((flags & CURLU_GUESS_SCHEME) && !schemep) { + /* legacy curl-style guess based on host name */ + if(checkprefix("ftp.", hostname)) + schemep = (char *)"ftp"; + else if(checkprefix("dict.", hostname)) + schemep = (char *)"dict"; + else if(checkprefix("ldap.", hostname)) + schemep = (char *)"ldap"; + else if(checkprefix("imap.", hostname)) + schemep = (char *)"imap"; + else if(checkprefix("smtp.", hostname)) + schemep = (char *)"smtp"; + else if(checkprefix("pop3.", hostname)) + schemep = (char *)"pop3"; + else + schemep = (char *)"http"; + } + + len = strlen(p); + memcpy(path, p, len); + path[len] = 0; + + u->scheme = strdup(schemep); + if(!u->scheme) + return CURLUE_OUT_OF_MEMORY; + } + + /* if this is a known scheme, get some details */ + h = Curl_builtin_scheme(u->scheme); + + if(junkscan(path)) + return CURLUE_MALFORMED_INPUT; + + query = strchr(path, '?'); + if(query) + *query++ = 0; + + fragment = strchr(query?query:path, '#'); + if(fragment) + *fragment++ = 0; + + if(!path[0]) + /* if there's no path set, unset */ + path = NULL; + else if(!(flags & CURLU_PATH_AS_IS)) { + /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */ + char *newp = Curl_dedotdotify(path); + if(!newp) + return CURLUE_OUT_OF_MEMORY; + + if(strcmp(newp, path)) { + /* if we got a new version */ + path = newp; + path_alloced = TRUE; + } + else + free(newp); + } + if(path) { + u->path = path_alloced?path:strdup(path); + if(!u->path) + return CURLUE_OUT_OF_MEMORY; + } + + if(hostname) { + /* + * Parse the login details and strip them out of the host name. + */ + if(junkscan(hostname)) + return CURLUE_MALFORMED_INPUT; + + result = parse_hostname_login(u, h, &hostname, flags); + if(result) + return result; + + result = Curl_parse_port(u, hostname); + if(result) + return result; + + result = hostname_check(u, hostname); + if(result) + return result; + + u->host = strdup(hostname); + if(!u->host) + return CURLUE_OUT_OF_MEMORY; + } + + if(query) { + u->query = strdup(query); + if(!u->query) + return CURLUE_OUT_OF_MEMORY; + } + if(fragment && fragment[0]) { + u->fragment = strdup(fragment); + if(!u->fragment) + return CURLUE_OUT_OF_MEMORY; + } + + free(u->scratch); + u->scratch = NULL; + + return CURLUE_OK; +} + +/* + * Parse the URL and set the relevant members of the Curl_URL struct. + */ +static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) +{ + CURLUcode result = seturl(url, u, flags); + if(result) { + free_urlhandle(u); + memset(u, 0, sizeof(struct Curl_URL)); + } + return result; +} + +/* + */ +CURLU *curl_url(void) +{ + return calloc(sizeof(struct Curl_URL), 1); +} + +void curl_url_cleanup(CURLU *u) +{ + if(u) { + free_urlhandle(u); + free(u); + } +} + +#define DUP(dest, src, name) \ + if(src->name) { \ + dest->name = strdup(src->name); \ + if(!dest->name) \ + goto fail; \ + } + +CURLU *curl_url_dup(CURLU *in) +{ + struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1); + if(u) { + DUP(u, in, scheme); + DUP(u, in, user); + DUP(u, in, password); + DUP(u, in, options); + DUP(u, in, host); + DUP(u, in, port); + DUP(u, in, path); + DUP(u, in, query); + DUP(u, in, fragment); + u->portnum = in->portnum; + } + return u; + fail: + curl_url_cleanup(u); + return NULL; +} + +CURLUcode curl_url_get(CURLU *u, CURLUPart what, + char **part, unsigned int flags) +{ + char *ptr; + CURLUcode ifmissing = CURLUE_UNKNOWN_PART; + char portbuf[7]; + bool urldecode = (flags & CURLU_URLDECODE)?1:0; + bool plusdecode = FALSE; + (void)flags; + if(!u) + return CURLUE_BAD_HANDLE; + if(!part) + return CURLUE_BAD_PARTPOINTER; + *part = NULL; + + switch(what) { + case CURLUPART_SCHEME: + ptr = u->scheme; + ifmissing = CURLUE_NO_SCHEME; + urldecode = FALSE; /* never for schemes */ + break; + case CURLUPART_USER: + ptr = u->user; + ifmissing = CURLUE_NO_USER; + break; + case CURLUPART_PASSWORD: + ptr = u->password; + ifmissing = CURLUE_NO_PASSWORD; + break; + case CURLUPART_OPTIONS: + ptr = u->options; + ifmissing = CURLUE_NO_OPTIONS; + break; + case CURLUPART_HOST: + ptr = u->host; + ifmissing = CURLUE_NO_HOST; + break; + case CURLUPART_ZONEID: + ptr = u->zoneid; + break; + case CURLUPART_PORT: + ptr = u->port; + ifmissing = CURLUE_NO_PORT; + urldecode = FALSE; /* never for port */ + if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) { + /* there's no stored port number, but asked to deliver + a default one for the scheme */ + const struct Curl_handler *h = + Curl_builtin_scheme(u->scheme); + if(h) { + msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport); + ptr = portbuf; + } + } + else if(ptr && u->scheme) { + /* there is a stored port number, but ask to inhibit if + it matches the default one for the scheme */ + const struct Curl_handler *h = + Curl_builtin_scheme(u->scheme); + if(h && (h->defport == u->portnum) && + (flags & CURLU_NO_DEFAULT_PORT)) + ptr = NULL; + } + break; + case CURLUPART_PATH: + ptr = u->path; + if(!ptr) { + ptr = u->path = strdup("/"); + if(!u->path) + return CURLUE_OUT_OF_MEMORY; + } + break; + case CURLUPART_QUERY: + ptr = u->query; + ifmissing = CURLUE_NO_QUERY; + plusdecode = urldecode; + break; + case CURLUPART_FRAGMENT: + ptr = u->fragment; + ifmissing = CURLUE_NO_FRAGMENT; + break; + case CURLUPART_URL: { + char *url; + char *scheme; + char *options = u->options; + char *port = u->port; + char *allochost = NULL; + if(u->scheme && strcasecompare("file", u->scheme)) { + url = aprintf("file://%s%s%s", + u->path, + u->fragment? "#": "", + u->fragment? u->fragment : ""); + } + else if(!u->host) + return CURLUE_NO_HOST; + else { + const struct Curl_handler *h = NULL; + if(u->scheme) + scheme = u->scheme; + else if(flags & CURLU_DEFAULT_SCHEME) + scheme = (char *) DEFAULT_SCHEME; + else + return CURLUE_NO_SCHEME; + + if(scheme) { + h = Curl_builtin_scheme(scheme); + if(!port && (flags & CURLU_DEFAULT_PORT)) { + /* there's no stored port number, but asked to deliver + a default one for the scheme */ + if(h) { + msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport); + port = portbuf; + } + } + else if(port) { + /* there is a stored port number, but asked to inhibit if it matches + the default one for the scheme */ + if(h && (h->defport == u->portnum) && + (flags & CURLU_NO_DEFAULT_PORT)) + port = NULL; + } + } + if(h && !(h->flags & PROTOPT_URLOPTIONS)) + options = NULL; + + if((u->host[0] == '[') && u->zoneid) { + /* make it '[ host %25 zoneid ]' */ + size_t hostlen = strlen(u->host); + size_t alen = hostlen + 3 + strlen(u->zoneid) + 1; + allochost = malloc(alen); + if(!allochost) + return CURLUE_OUT_OF_MEMORY; + memcpy(allochost, u->host, hostlen - 1); + msnprintf(&allochost[hostlen - 1], alen - hostlen + 1, + "%%25%s]", u->zoneid); + } + + url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + scheme, + u->user ? u->user : "", + u->password ? ":": "", + u->password ? u->password : "", + options ? ";" : "", + options ? options : "", + (u->user || u->password || options) ? "@": "", + allochost ? allochost : u->host, + port ? ":": "", + port ? port : "", + (u->path && (u->path[0] != '/')) ? "/": "", + u->path ? u->path : "/", + (u->query && u->query[0]) ? "?": "", + (u->query && u->query[0]) ? u->query : "", + u->fragment? "#": "", + u->fragment? u->fragment : ""); + free(allochost); + } + if(!url) + return CURLUE_OUT_OF_MEMORY; + *part = url; + return CURLUE_OK; + } + default: + ptr = NULL; + break; + } + if(ptr) { + *part = strdup(ptr); + if(!*part) + return CURLUE_OUT_OF_MEMORY; + if(plusdecode) { + /* convert + to space */ + char *plus; + for(plus = *part; *plus; ++plus) { + if(*plus == '+') + *plus = ' '; + } + } + if(urldecode) { + char *decoded; + size_t dlen; + CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen, TRUE); + free(*part); + if(res) { + *part = NULL; + return CURLUE_URLDECODE; + } + *part = decoded; + } + return CURLUE_OK; + } + else + return ifmissing; +} + +CURLUcode curl_url_set(CURLU *u, CURLUPart what, + const char *part, unsigned int flags) +{ + char **storep = NULL; + long port = 0; + bool urlencode = (flags & CURLU_URLENCODE)? 1 : 0; + bool plusencode = FALSE; + bool urlskipslash = FALSE; + bool appendquery = FALSE; + bool equalsencode = FALSE; + + if(!u) + return CURLUE_BAD_HANDLE; + if(!part) { + /* setting a part to NULL clears it */ + switch(what) { + case CURLUPART_URL: + break; + case CURLUPART_SCHEME: + storep = &u->scheme; + break; + case CURLUPART_USER: + storep = &u->user; + break; + case CURLUPART_PASSWORD: + storep = &u->password; + break; + case CURLUPART_OPTIONS: + storep = &u->options; + break; + case CURLUPART_HOST: + storep = &u->host; + break; + case CURLUPART_ZONEID: + storep = &u->zoneid; + break; + case CURLUPART_PORT: + u->portnum = 0; + storep = &u->port; + break; + case CURLUPART_PATH: + storep = &u->path; + break; + case CURLUPART_QUERY: + storep = &u->query; + break; + case CURLUPART_FRAGMENT: + storep = &u->fragment; + break; + default: + return CURLUE_UNKNOWN_PART; + } + if(storep && *storep) { + free(*storep); + *storep = NULL; + } + return CURLUE_OK; + } + + switch(what) { + case CURLUPART_SCHEME: + if(strlen(part) > MAX_SCHEME_LEN) + /* too long */ + return CURLUE_MALFORMED_INPUT; + if(!(flags & CURLU_NON_SUPPORT_SCHEME) && + /* verify that it is a fine scheme */ + !Curl_builtin_scheme(part)) + return CURLUE_UNSUPPORTED_SCHEME; + storep = &u->scheme; + urlencode = FALSE; /* never */ + break; + case CURLUPART_USER: + storep = &u->user; + break; + case CURLUPART_PASSWORD: + storep = &u->password; + break; + case CURLUPART_OPTIONS: + storep = &u->options; + break; + case CURLUPART_HOST: + storep = &u->host; + free(u->zoneid); + u->zoneid = NULL; + break; + case CURLUPART_ZONEID: + storep = &u->zoneid; + break; + case CURLUPART_PORT: + { + char *endp; + urlencode = FALSE; /* never */ + port = strtol(part, &endp, 10); /* Port number must be decimal */ + if((port <= 0) || (port > 0xffff)) + return CURLUE_BAD_PORT_NUMBER; + if(*endp) + /* weirdly provided number, not good! */ + return CURLUE_MALFORMED_INPUT; + storep = &u->port; + } + break; + case CURLUPART_PATH: + urlskipslash = TRUE; + storep = &u->path; + break; + case CURLUPART_QUERY: + plusencode = urlencode; + appendquery = (flags & CURLU_APPENDQUERY)?1:0; + equalsencode = appendquery; + storep = &u->query; + break; + case CURLUPART_FRAGMENT: + storep = &u->fragment; + break; + case CURLUPART_URL: { + /* + * Allow a new URL to replace the existing (if any) contents. + * + * If the existing contents is enough for a URL, allow a relative URL to + * replace it. + */ + CURLUcode result; + char *oldurl; + char *redired_url; + CURLU *handle2; + + if(Curl_is_absolute_url(part, NULL, MAX_SCHEME_LEN + 1)) { + handle2 = curl_url(); + if(!handle2) + return CURLUE_OUT_OF_MEMORY; + result = parseurl(part, handle2, flags); + if(!result) + mv_urlhandle(handle2, u); + else + curl_url_cleanup(handle2); + return result; + } + /* extract the full "old" URL to do the redirect on */ + result = curl_url_get(u, CURLUPART_URL, &oldurl, flags); + if(result) { + /* couldn't get the old URL, just use the new! */ + handle2 = curl_url(); + if(!handle2) + return CURLUE_OUT_OF_MEMORY; + result = parseurl(part, handle2, flags); + if(!result) + mv_urlhandle(handle2, u); + else + curl_url_cleanup(handle2); + return result; + } + + /* apply the relative part to create a new URL */ + redired_url = concat_url(oldurl, part); + free(oldurl); + if(!redired_url) + return CURLUE_OUT_OF_MEMORY; + + /* now parse the new URL */ + handle2 = curl_url(); + if(!handle2) { + free(redired_url); + return CURLUE_OUT_OF_MEMORY; + } + result = parseurl(redired_url, handle2, flags); + free(redired_url); + if(!result) + mv_urlhandle(handle2, u); + else + curl_url_cleanup(handle2); + return result; + } + default: + return CURLUE_UNKNOWN_PART; + } + if(storep) { + const char *newp = part; + size_t nalloc = strlen(part); + + if(nalloc > CURL_MAX_INPUT_LENGTH) + /* excessive input length */ + return CURLUE_MALFORMED_INPUT; + + if(urlencode) { + const unsigned char *i; + char *o; + bool free_part = FALSE; + char *enc = malloc(nalloc * 3 + 1); /* for worst case! */ + if(!enc) + return CURLUE_OUT_OF_MEMORY; + if(plusencode) { + /* space to plus */ + i = (const unsigned char *)part; + for(o = enc; *i; ++o, ++i) + *o = (*i == ' ') ? '+' : *i; + *o = 0; /* zero terminate */ + part = strdup(enc); + if(!part) { + free(enc); + return CURLUE_OUT_OF_MEMORY; + } + free_part = TRUE; + } + for(i = (const unsigned char *)part, o = enc; *i; i++) { + if(Curl_isunreserved(*i) || + ((*i == '/') && urlskipslash) || + ((*i == '=') && equalsencode) || + ((*i == '+') && plusencode)) { + if((*i == '=') && equalsencode) + /* only skip the first equals sign */ + equalsencode = FALSE; + *o = *i; + o++; + } + else { + msnprintf(o, 4, "%%%02x", *i); + o += 3; + } + } + *o = 0; /* zero terminate */ + newp = enc; + if(free_part) + free((char *)part); + } + else { + char *p; + newp = strdup(part); + if(!newp) + return CURLUE_OUT_OF_MEMORY; + p = (char *)newp; + while(*p) { + /* make sure percent encoded are lower case */ + if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) && + (ISUPPER(p[1]) || ISUPPER(p[2]))) { + p[1] = (char)TOLOWER(p[1]); + p[2] = (char)TOLOWER(p[2]); + p += 3; + } + else + p++; + } + } + + if(appendquery) { + /* Append the string onto the old query. Add a '&' separator if none is + present at the end of the exsting query already */ + size_t querylen = u->query ? strlen(u->query) : 0; + bool addamperand = querylen && (u->query[querylen -1] != '&'); + if(querylen) { + size_t newplen = strlen(newp); + char *p = malloc(querylen + addamperand + newplen + 1); + if(!p) { + free((char *)newp); + return CURLUE_OUT_OF_MEMORY; + } + strcpy(p, u->query); /* original query */ + if(addamperand) + p[querylen] = '&'; /* ampersand */ + strcpy(&p[querylen + addamperand], newp); /* new suffix */ + free((char *)newp); + free(*storep); + *storep = p; + return CURLUE_OK; + } + } + + if(what == CURLUPART_HOST) { + if(hostname_check(u, (char *)newp)) { + free((char *)newp); + return CURLUE_MALFORMED_INPUT; + } + } + + free(*storep); + *storep = (char *)newp; + } + /* set after the string, to make it not assigned if the allocation above + fails */ + if(port) + u->portnum = port; + return CURLUE_OK; +} diff --git a/libcurl/lib/urldata.h b/libcurl/lib/urldata.h new file mode 100644 index 0000000..fdc185b --- /dev/null +++ b/libcurl/lib/urldata.h @@ -0,0 +1,1837 @@ +#ifndef HEADER_CURL_URLDATA_H +#define HEADER_CURL_URLDATA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This file is for lib internal stuff */ + +#include "curl_setup.h" + +#define PORT_FTP 21 +#define PORT_FTPS 990 +#define PORT_TELNET 23 +#define PORT_HTTP 80 +#define PORT_HTTPS 443 +#define PORT_DICT 2628 +#define PORT_LDAP 389 +#define PORT_LDAPS 636 +#define PORT_TFTP 69 +#define PORT_SSH 22 +#define PORT_IMAP 143 +#define PORT_IMAPS 993 +#define PORT_POP3 110 +#define PORT_POP3S 995 +#define PORT_SMB 445 +#define PORT_SMBS 445 +#define PORT_SMTP 25 +#define PORT_SMTPS 465 /* sometimes called SSMTP */ +#define PORT_RTSP 554 +#define PORT_RTMP 1935 +#define PORT_RTMPT PORT_HTTP +#define PORT_RTMPS PORT_HTTPS +#define PORT_GOPHER 70 + +#define DICT_MATCH "/MATCH:" +#define DICT_MATCH2 "/M:" +#define DICT_MATCH3 "/FIND:" +#define DICT_DEFINE "/DEFINE:" +#define DICT_DEFINE2 "/D:" +#define DICT_DEFINE3 "/LOOKUP:" + +#define CURL_DEFAULT_USER "anonymous" +#define CURL_DEFAULT_PASSWORD "ftp@example.com" + +/* Convenience defines for checking protocols or their SSL based version. Each + protocol handler should only ever have a single CURLPROTO_ in its protocol + field. */ +#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS) +#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS) +#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S) +#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS) +#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS) + +#define DEFAULT_CONNCACHE_SIZE 5 + +/* length of longest IPv6 address string including the trailing null */ +#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + +/* Default FTP/IMAP etc response timeout in milliseconds. + Symbian OS panics when given a timeout much greater than 1/2 hour. +*/ +#define RESP_TIMEOUT (120*1000) + +/* Max string intput length is a precaution against abuse and to detect junk + input easier and better. */ +#define CURL_MAX_INPUT_LENGTH 8000000 + +#include "cookie.h" +#include "psl.h" +#include "formdata.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif + +#include "timeval.h" + +#include + +#include "http_chunks.h" /* for the structs and enum stuff */ +#include "hostip.h" +#include "hash.h" +#include "splay.h" + +/* return the count of bytes sent, or -1 on error */ +typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + const void *buf, /* data to write */ + size_t len, /* max amount to write */ + CURLcode *err); /* error to return */ + +/* return the count of bytes read, or -1 on error */ +typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + char *buf, /* store data here */ + size_t len, /* max amount to read */ + CURLcode *err); /* error to return */ + +#include "mime.h" +#include "imap.h" +#include "pop3.h" +#include "smtp.h" +#include "ftp.h" +#include "file.h" +#include "ssh.h" +#include "http.h" +#include "rtsp.h" +#include "smb.h" +#include "wildcard.h" +#include "multihandle.h" + +#ifdef HAVE_GSSAPI +# ifdef HAVE_GSSGNU +# include +# elif defined HAVE_GSSAPI_GSSAPI_H +# include +# else +# include +# endif +# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H +# include +# endif +#endif + +#ifdef HAVE_LIBSSH2_H +#include +#include +#endif /* HAVE_LIBSSH2_H */ + +/* Initial size of the buffer to store headers in, it'll be enlarged in case + of need. */ +#define HEADERSIZE 256 + +#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU +#define GOOD_EASY_HANDLE(x) \ + ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) + +/* the type we use for storing a single boolean bit */ +typedef unsigned int bit; + +#ifdef HAVE_GSSAPI +/* Types needed for krb5-ftp connections */ +struct krb5buffer { + void *data; + size_t size; + size_t index; + bit eof_flag:1; +}; + +enum protection_level { + PROT_NONE, /* first in list */ + PROT_CLEAR, + PROT_SAFE, + PROT_CONFIDENTIAL, + PROT_PRIVATE, + PROT_CMD, + PROT_LAST /* last in list */ +}; +#endif + +/* enum for the nonblocking SSL connection state machine */ +typedef enum { + ssl_connect_1, + ssl_connect_2, + ssl_connect_2_reading, + ssl_connect_2_writing, + ssl_connect_3, + ssl_connect_done +} ssl_connect_state; + +typedef enum { + ssl_connection_none, + ssl_connection_negotiating, + ssl_connection_complete +} ssl_connection_state; + +/* SSL backend-specific data; declared differently by each SSL backend */ +struct ssl_backend_data; + +/* struct for data related to each SSL connection */ +struct ssl_connect_data { + /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm + but at least asked to or meaning to use it. See 'state' for the exact + current state of the connection. */ + ssl_connection_state state; + ssl_connect_state connecting_state; +#if defined(USE_SSL) + struct ssl_backend_data *backend; +#endif + bit use:1; +}; + +struct ssl_primary_config { + long version; /* what version the client wants to use */ + long version_max; /* max supported version the client wants to use*/ + char *CApath; /* certificate dir (doesn't work on windows) */ + char *CAfile; /* certificate to verify peer against */ + char *clientcert; + char *random_file; /* path to file containing "random" data */ + char *egdsocket; /* path to file containing the EGD daemon socket */ + char *cipher_list; /* list of ciphers to use */ + char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ + bit verifypeer:1; /* set TRUE if this is desired */ + bit verifyhost:1; /* set TRUE if CN/SAN must match hostname */ + bit verifystatus:1; /* set TRUE if certificate status must be checked */ + bit sessionid:1; /* cache session IDs or not */ +}; + +struct ssl_config_data { + struct ssl_primary_config primary; + long certverifyresult; /* result from the certificate verification */ + char *CRLfile; /* CRL to check certificate revocation */ + char *issuercert;/* optional issuer certificate filename */ + curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ + void *fsslctxp; /* parameter for call back */ + char *cert; /* client certificate file name */ + char *cert_type; /* format for certificate (default: PEM)*/ + char *key; /* private key file name */ + char *key_type; /* format for private key (default: PEM) */ + char *key_passwd; /* plain text private key password */ +#ifdef USE_TLS_SRP + char *username; /* TLS username (for, e.g., SRP) */ + char *password; /* TLS password (for, e.g., SRP) */ + enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ +#endif + bit certinfo:1; /* gather lots of certificate info */ + bit falsestart:1; + bit enable_beast:1; /* allow this flaw for interoperability's sake*/ + bit no_revoke:1; /* disable SSL certificate revocation checks */ +}; + +struct ssl_general_config { + size_t max_ssl_sessions; /* SSL session id cache size */ +}; + +/* information stored about one single SSL session */ +struct curl_ssl_session { + char *name; /* host name for which this ID was used */ + char *conn_to_host; /* host name for the connection (may be NULL) */ + const char *scheme; /* protocol scheme used */ + void *sessionid; /* as returned from the SSL layer */ + size_t idsize; /* if known, otherwise 0 */ + long age; /* just a number, the higher the more recent */ + int remote_port; /* remote port */ + int conn_to_port; /* remote port for the connection (may be -1) */ + struct ssl_primary_config ssl_config; /* setup for this session */ +}; + +#ifdef USE_WINDOWS_SSPI +#include "curl_sspi.h" +#endif + +/* Struct used for Digest challenge-response authentication */ +struct digestdata { +#if defined(USE_WINDOWS_SSPI) + BYTE *input_token; + size_t input_token_len; + CtxtHandle *http_context; + /* copy of user/passwd used to make the identity for http_context. + either may be NULL. */ + char *user; + char *passwd; +#else + char *nonce; + char *cnonce; + char *realm; + int algo; + char *opaque; + char *qop; + char *algorithm; + int nc; /* nounce count */ + bit stale:1; /* set true for re-negotiation */ + bit userhash:1; +#endif +}; + +typedef enum { + NTLMSTATE_NONE, + NTLMSTATE_TYPE1, + NTLMSTATE_TYPE2, + NTLMSTATE_TYPE3, + NTLMSTATE_LAST +} curlntlm; + +typedef enum { + GSS_AUTHNONE, + GSS_AUTHRECV, + GSS_AUTHSENT, + GSS_AUTHDONE, + GSS_AUTHSUCC +} curlnegotiate; + +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) +#include +#endif + +/* Struct used for GSSAPI (Kerberos V5) authentication */ +#if defined(USE_KERBEROS5) +struct kerberos5data { +#if defined(USE_WINDOWS_SSPI) + CredHandle *credentials; + CtxtHandle *context; + TCHAR *spn; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + size_t token_max; + BYTE *output_token; +#else + gss_ctx_id_t context; + gss_name_t spn; +#endif +}; +#endif + +/* Struct used for NTLM challenge-response authentication */ +#if defined(USE_NTLM) +struct ntlmdata { +#ifdef USE_WINDOWS_SSPI +/* The sslContext is used for the Schannel bindings. The + * api is available on the Windows 7 SDK and later. + */ +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + CtxtHandle *sslContext; +#endif + CredHandle *credentials; + CtxtHandle *context; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + size_t token_max; + BYTE *output_token; + BYTE *input_token; + size_t input_token_len; + TCHAR *spn; +#else + unsigned int flags; + unsigned char nonce[8]; + void *target_info; /* TargetInfo received in the ntlm type-2 message */ + unsigned int target_info_len; +#endif +}; +#endif + +/* Struct used for Negotiate (SPNEGO) authentication */ +#ifdef USE_SPNEGO +struct negotiatedata { +#ifdef HAVE_GSSAPI + OM_uint32 status; + gss_ctx_id_t context; + gss_name_t spn; + gss_buffer_desc output_token; +#else +#ifdef USE_WINDOWS_SSPI +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + CtxtHandle *sslContext; +#endif + DWORD status; + CredHandle *credentials; + CtxtHandle *context; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + TCHAR *spn; + size_t token_max; + BYTE *output_token; + size_t output_token_length; +#endif +#endif + bool noauthpersist; + bool havenoauthpersist; + bool havenegdata; + bool havemultiplerequests; +}; +#endif + + +/* + * Boolean values that concerns this connection. + */ +struct ConnectBits { + /* always modify bits.close with the connclose() and connkeep() macros! */ + bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy + is complete */ + bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set + the first time on the first connect function call */ + bit close:1; /* if set, we close the connection after this request */ + bit reuse:1; /* if set, this is a re-used connection */ + bit conn_to_host:1; /* if set, this connection has a "connect to host" + that overrides the host in the URL */ + bit conn_to_port:1; /* if set, this connection has a "connect to port" + that overrides the port in the URL (remote port) */ + bit proxy:1; /* if set, this transfer is done through a proxy - any type */ + bit httpproxy:1; /* if set, this transfer is done through a http proxy */ + bit socksproxy:1; /* if set, this transfer is done through a socks proxy */ + bit user_passwd:1; /* do we use user+password for this connection? */ + bit proxy_user_passwd:1; /* user+password for the proxy? */ + bit ipv6_ip:1; /* we communicate with a remote site specified with pure IPv6 + IP address */ + bit ipv6:1; /* we communicate with a site using an IPv6 address */ + bit do_more:1; /* this is set TRUE if the ->curl_do_more() function is + supposed to be called, after ->curl_do() */ + bit protoconnstart:1;/* the protocol layer has STARTED its operation after + the TCP layer connect */ + bit retry:1; /* this connection is about to get closed and then + re-attempted at another connection. */ + bit tunnel_proxy:1; /* if CONNECT is used to "tunnel" through the proxy. + This is implicit when SSL-protocols are used through + proxies, but can also be enabled explicitly by + apps */ + bit authneg:1; /* TRUE when the auth phase has started, which means + that we are creating a request with an auth header, + but it is not the final request in the auth + negotiation. */ + bit rewindaftersend:1;/* TRUE when the sending couldn't be stopped even + though it will be discarded. When the whole send + operation is done, we must call the data rewind + callback. */ +#ifndef CURL_DISABLE_FTP + bit ftp_use_epsv:1; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out + EPSV doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_eprt:1; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out + EPRT doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_data_ssl:1; /* Enabled SSL for the data connection */ +#endif + bit netrc:1; /* name+password provided by netrc */ + bit userpwd_in_url:1; /* name+password found in url */ + bit stream_was_rewound:1; /* The stream was rewound after a request read + past the end of its response byte boundary */ + bit proxy_connect_closed:1; /* TRUE if a proxy disconnected the connection + in a CONNECT request with auth, so that + libcurl should reconnect and continue. */ + bit bound:1; /* set true if bind() has already been done on this socket/ + connection */ + bit type_set:1; /* type= was used in the URL */ + bit multiplex:1; /* connection is multiplexed */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit tls_enable_npn:1; /* TLS NPN extension? */ + bit tls_enable_alpn:1; /* TLS ALPN extension? */ + bit socksproxy_connecting:1; /* connecting through a socks proxy */ + bit connect_only:1; +}; + +struct hostname { + char *rawalloc; /* allocated "raw" version of the name */ + char *encalloc; /* allocated IDN-encoded version of the name */ + char *name; /* name to use internally, might be encoded, might be raw */ + const char *dispname; /* name to display, as 'name' might be encoded */ +}; + +/* + * Flags on the keepon member of the Curl_transfer_keeper + */ + +#define KEEP_NONE 0 +#define KEEP_RECV (1<<0) /* there is or may be data to read */ +#define KEEP_SEND (1<<1) /* there is or may be data to write */ +#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there + might still be data to read */ +#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there + might still be data to write */ +#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */ +#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */ + +#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) +#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) + +struct Curl_async { + char *hostname; + int port; + struct Curl_dns_entry *dns; + int status; /* if done is TRUE, this is the status from the callback */ + void *os_specific; /* 'struct thread_data' for Windows */ + bit done:1; /* set TRUE when the lookup is complete */ +}; + +#define FIRSTSOCKET 0 +#define SECONDARYSOCKET 1 + +/* These function pointer types are here only to allow easier typecasting + within the source when we need to cast between data pointers (such as NULL) + and function pointers. */ +typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *); +typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool); + +enum expect100 { + EXP100_SEND_DATA, /* enough waiting, just send the body now */ + EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ + EXP100_SENDING_REQUEST, /* still sending the request but will wait for + the 100 header once done with the request */ + EXP100_FAILED /* used on 417 Expectation Failed */ +}; + +enum upgrade101 { + UPGR101_INIT, /* default state */ + UPGR101_REQUESTED, /* upgrade requested */ + UPGR101_RECEIVED, /* response received */ + UPGR101_WORKING /* talking upgraded protocol */ +}; + +struct dohresponse { + unsigned char *memory; + size_t size; +}; + +/* one of these for each DoH request */ +struct dnsprobe { + CURL *easy; + int dnstype; + unsigned char dohbuffer[512]; + size_t dohlen; + struct dohresponse serverdoh; +}; + +struct dohdata { + struct curl_slist *headers; + struct dnsprobe probe[2]; + unsigned int pending; /* still outstanding requests */ + const char *host; + int port; +}; + +/* + * Request specific data in the easy handle (Curl_easy). Previously, + * these members were on the connectdata struct but since a conn struct may + * now be shared between different Curl_easys, we store connection-specific + * data here. This struct only keeps stuff that's interesting for *this* + * request, as it will be cleared between multiple ones + */ +struct SingleRequest { + curl_off_t size; /* -1 if unknown at this point */ + curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch, + -1 means unlimited */ + curl_off_t bytecount; /* total number of bytes read */ + curl_off_t writebytecount; /* number of bytes written */ + + curl_off_t headerbytecount; /* only count received headers */ + curl_off_t deductheadercount; /* this amount of bytes doesn't count when we + check if anything has been transferred at + the end of a connection. We use this + counter to make only a 100 reply (without a + following second response code) result in a + CURLE_GOT_NOTHING error code */ + + struct curltime start; /* transfer started at this time */ + struct curltime now; /* current time */ + enum { + HEADER_NORMAL, /* no bad header at all */ + HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest + is normal data */ + HEADER_ALLBAD /* all was believed to be header */ + } badheader; /* the header was deemed bad and will be + written as body */ + int headerline; /* counts header lines to better track the + first one */ + char *hbufp; /* points at *end* of header line */ + size_t hbuflen; + char *str; /* within buf */ + char *str_start; /* within buf */ + char *end_ptr; /* within buf */ + char *p; /* within headerbuff */ + curl_off_t offset; /* possible resume offset read from the + Content-Range: header */ + int httpcode; /* error code from the 'HTTP/1.? XXX' or + 'RTSP/1.? XXX' line */ + struct curltime start100; /* time stamp to wait for the 100 code from */ + enum expect100 exp100; /* expect 100 continue state */ + enum upgrade101 upgr101; /* 101 upgrade state */ + + struct contenc_writer_s *writer_stack; /* Content unencoding stack. */ + /* See sec 3.5, RFC2616. */ + time_t timeofdoc; + long bodywrites; + char *buf; + int keepon; + char *location; /* This points to an allocated version of the Location: + header data */ + char *newurl; /* Set to the new URL to use when a redirect or a retry is + wanted */ + + /* 'upload_present' is used to keep a byte counter of how much data there is + still left in the buffer, aimed for upload. */ + ssize_t upload_present; + + /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a + buffer, so the next read should read from where this pointer points to, + and the 'upload_present' contains the number of bytes available at this + position */ + char *upload_fromhere; + void *protop; /* Allocated protocol-specific data. Each protocol + handler makes sure this points to data it needs. */ +#ifndef CURL_DISABLE_DOH + struct dohdata doh; /* DoH specific data for this request */ +#endif + bit header:1; /* incoming data has HTTP header */ + bit content_range:1; /* set TRUE if Content-Range: was found */ + bit upload_done:1; /* set to TRUE when doing chunked transfer-encoding + upload and we're uploading the last chunk */ + bit ignorebody:1; /* we read a response-body but we ignore it! */ + bit http_bodyless:1; /* HTTP response status code is between 100 and 199, + 204 or 304 */ + bit chunk:1; /* if set, this is a chunked transfer-encoding */ + bit upload_chunky:1; /* set TRUE if we are doing chunked transfer-encoding + on upload */ + bit getheader:1; /* TRUE if header parsing is wanted */ + bit forbidchunk:1; /* used only to explicitly forbid chunk-upload for + specific upload buffers. See readmoredata() in http.c + for details. */ +}; + +/* + * Specific protocol handler. + */ + +struct Curl_handler { + const char *scheme; /* URL scheme name. */ + + /* Complement to setup_connection_internals(). */ + CURLcode (*setup_connection)(struct connectdata *); + + /* These two functions MUST be set to be protocol dependent */ + CURLcode (*do_it)(struct connectdata *, bool *done); + Curl_done_func done; + + /* If the curl_do() function is better made in two halves, this + * curl_do_more() function will be called afterwards, if set. For example + * for doing the FTP stuff after the PASV/PORT command. + */ + Curl_do_more_func do_more; + + /* This function *MAY* be set to a protocol-dependent function that is run + * after the connect() and everything is done, as a step in the connection. + * The 'done' pointer points to a bool that should be set to TRUE if the + * function completes before return. If it doesn't complete, the caller + * should call the curl_connecting() function until it is. + */ + CURLcode (*connect_it)(struct connectdata *, bool *done); + + /* See above. */ + CURLcode (*connecting)(struct connectdata *, bool *done); + CURLcode (*doing)(struct connectdata *, bool *done); + + /* Called from the multi interface during the PROTOCONNECT phase, and it + should then return a proper fd set */ + int (*proto_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DOING phase, and it should + then return a proper fd set */ + int (*doing_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DO_MORE phase, and it should + then return a proper fd set */ + int (*domore_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DO_DONE, PERFORM and + WAITPERFORM phases, and it should then return a proper fd set. Not setting + this will make libcurl use the generic default one. */ + int (*perform_getsock)(const struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* This function *MAY* be set to a protocol-dependent function that is run + * by the curl_disconnect(), as a step in the disconnection. If the handler + * is called because the connection has been considered dead, dead_connection + * is set to TRUE. + */ + CURLcode (*disconnect)(struct connectdata *, bool dead_connection); + + /* If used, this function gets called from transfer.c:readwrite_data() to + allow the protocol to do extra reads/writes */ + CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn, + ssize_t *nread, bool *readmore); + + /* This function can perform various checks on the connection. See + CONNCHECK_* for more information about the checks that can be performed, + and CONNRESULT_* for the results that can be returned. */ + unsigned int (*connection_check)(struct connectdata *conn, + unsigned int checks_to_perform); + + long defport; /* Default port. */ + unsigned int protocol; /* See CURLPROTO_* - this needs to be the single + specific protocol bit */ + unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ +}; + +#define PROTOPT_NONE 0 /* nothing extra */ +#define PROTOPT_SSL (1<<0) /* uses SSL */ +#define PROTOPT_DUAL (1<<1) /* this protocol uses two connections */ +#define PROTOPT_CLOSEACTION (1<<2) /* need action before socket close */ +/* some protocols will have to call the underlying functions without regard to + what exact state the socket signals. IE even if the socket says "readable", + the send function might need to be called while uploading, or vice versa. +*/ +#define PROTOPT_DIRLOCK (1<<3) +#define PROTOPT_NONETWORK (1<<4) /* protocol doesn't use the network! */ +#define PROTOPT_NEEDSPWD (1<<5) /* needs a password, and if none is set it + gets a default */ +#define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle + url query strings (?foo=bar) ! */ +#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per + request instead of per connection */ +#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */ +#define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */ +#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field + of the URL */ +#define PROTOPT_PROXY_AS_HTTP (1<<11) /* allow this non-HTTP scheme over a + HTTP proxy as HTTP proxies may know + this protocol and act as a gateway */ +#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */ + +#define CONNCHECK_NONE 0 /* No checks */ +#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */ +#define CONNCHECK_KEEPALIVE (1<<1) /* Perform any keepalive function. */ + +#define CONNRESULT_NONE 0 /* No extra information. */ +#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */ + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND +struct postponed_data { + char *buffer; /* Temporal store for received data during + sending, must be freed */ + size_t allocated_size; /* Size of temporal store */ + size_t recv_size; /* Size of received data during sending */ + size_t recv_processed; /* Size of processed part of postponed data */ +#ifdef DEBUGBUILD + curl_socket_t bindsock;/* Structure must be bound to specific socket, + used only for DEBUGASSERT */ +#endif /* DEBUGBUILD */ +}; +#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ + +struct proxy_info { + struct hostname host; + long port; + curl_proxytype proxytype; /* what kind of proxy that is in use */ + char *user; /* proxy user name string, allocated */ + char *passwd; /* proxy password string, allocated */ +}; + +#define CONNECT_BUFFER_SIZE 16384 + +/* struct for HTTP CONNECT state data */ +struct http_connect_state { + char connect_buffer[CONNECT_BUFFER_SIZE]; + int perline; /* count bytes per line */ + int keepon; + char *line_start; + char *ptr; /* where to store more data */ + curl_off_t cl; /* size of content to read and ignore */ + enum { + TUNNEL_INIT, /* init/default/no tunnel state */ + TUNNEL_CONNECT, /* CONNECT has been sent off */ + TUNNEL_COMPLETE /* CONNECT response received completely */ + } tunnel_state; + bit chunked_encoding:1; + bit close_connection:1; +}; + +/* + * The connectdata struct contains all fields and variables that should be + * unique for an entire connection. + */ +struct connectdata { + /* 'data' is the CURRENT Curl_easy using this connection -- take great + caution that this might very well vary between different times this + connection is used! */ + struct Curl_easy *data; + + struct curl_llist_element bundle_node; /* conncache */ + + /* chunk is for HTTP chunked encoding, but is in the general connectdata + struct only because we can do just about any protocol through a HTTP proxy + and a HTTP proxy may in fact respond using chunked encoding */ + struct Curl_chunker chunk; + + curl_closesocket_callback fclosesocket; /* function closing the socket(s) */ + void *closesocket_client; + + /* This is used by the connection cache logic. If this returns TRUE, this + handle is still used by one or more easy handles and can only used by any + other easy handle without careful consideration (== only for + multiplexing) and it cannot be used by another multi handle! */ +#define CONN_INUSE(c) ((c)->easyq.size) + + /**** Fields set when inited and not modified again */ + long connection_id; /* Contains a unique number to make it easier to + track the connections in the log output */ + + /* 'dns_entry' is the particular host we use. This points to an entry in the + DNS cache and it will not get pruned while locked. It gets unlocked in + Curl_done(). This entry will be NULL if the connection is re-used as then + there is no name resolve done. */ + struct Curl_dns_entry *dns_entry; + + /* 'ip_addr' is the particular IP we connected to. It points to a struct + within the DNS cache, so this pointer is only valid as long as the DNS + cache entry remains locked. It gets unlocked in Curl_done() */ + Curl_addrinfo *ip_addr; + Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */ + + /* 'ip_addr_str' is the ip_addr data as a human readable string. + It remains available as long as the connection does, which is longer than + the ip_addr itself. */ + char ip_addr_str[MAX_IPADR_LEN]; + + unsigned int scope_id; /* Scope id for IPv6 */ + + int socktype; /* SOCK_STREAM or SOCK_DGRAM */ + + struct hostname host; + char *hostname_resolve; /* host name to resolve to address, allocated */ + char *secondaryhostname; /* secondary socket host name (ftp) */ + struct hostname conn_to_host; /* the host to connect to. valid only if + bits.conn_to_host is set */ + + struct proxy_info socks_proxy; + struct proxy_info http_proxy; + + long port; /* which port to use locally */ + int remote_port; /* the remote port, not the proxy port! */ + int conn_to_port; /* the remote port to connect to. valid only if + bits.conn_to_port is set */ + unsigned short secondary_port; /* secondary socket remote port to connect to + (ftp) */ + + /* 'primary_ip' and 'primary_port' get filled with peer's numerical + ip address and port number whenever an outgoing connection is + *attempted* from the primary socket to a remote address. When more + than one address is tried for a connection these will hold data + for the last attempt. When the connection is actually established + these are updated with data which comes directly from the socket. */ + + char primary_ip[MAX_IPADR_LEN]; + long primary_port; + + /* 'local_ip' and 'local_port' get filled with local's numerical + ip address and port number whenever an outgoing connection is + **established** from the primary socket to a remote address. */ + + char local_ip[MAX_IPADR_LEN]; + long local_port; + + char *user; /* user name string, allocated */ + char *passwd; /* password string, allocated */ + char *options; /* options string, allocated */ + + char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */ + + int httpversion; /* the HTTP version*10 reported by the server */ + int rtspversion; /* the RTSP version*10 reported by the server */ + + struct curltime now; /* "current" time */ + struct curltime created; /* creation time */ + struct curltime lastused; /* when returned to the connection cache */ + curl_socket_t sock[2]; /* two sockets, the second is used for the data + transfer when doing FTP */ + curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */ + bool sock_accepted[2]; /* TRUE if the socket on this index was created with + accept() */ + Curl_recv *recv[2]; + Curl_send *send[2]; + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND + struct postponed_data postponed[2]; /* two buffers for two sockets */ +#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ + struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ + struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */ +#ifdef USE_SSL + void *ssl_extra; /* separately allocated backend-specific data */ +#endif + struct ssl_primary_config ssl_config; + struct ssl_primary_config proxy_ssl_config; + struct ConnectBits bits; /* various state-flags for this connection */ + + /* connecttime: when connect() is called on the current IP address. Used to + be able to track when to move on to try next IP - but only when the multi + interface is used. */ + struct curltime connecttime; + /* The two fields below get set in Curl_connecthost */ + int num_addr; /* number of addresses to try to connect to */ + time_t timeoutms_per_addr; /* how long time in milliseconds to spend on + trying to connect to each IP address */ + + const struct Curl_handler *handler; /* Connection's protocol handler */ + const struct Curl_handler *given; /* The protocol first given */ + + long ip_version; /* copied from the Curl_easy at creation time */ + + /* Protocols can use a custom keepalive mechanism to keep connections alive. + This allows those protocols to track the last time the keepalive mechanism + was used on this connection. */ + struct curltime keepalive; + + long upkeep_interval_ms; /* Time between calls for connection upkeep. */ + + /**** curl_get() phase fields */ + + curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */ + curl_socket_t writesockfd; /* socket to write to, it may very + well be the same we read from. + CURL_SOCKET_BAD disables */ + + /** Dynamically allocated strings, MUST be freed before this **/ + /** struct is killed. **/ + struct dynamically_allocated_data { + char *proxyuserpwd; + char *uagent; + char *accept_encoding; + char *userpwd; + char *rangeline; + char *ref; + char *host; + char *cookiehost; + char *rtsp_transport; + char *te; /* TE: request header */ + } allocptr; + +#ifdef HAVE_GSSAPI + bit sec_complete:1; /* if Kerberos is enabled for this connection */ + enum protection_level command_prot; + enum protection_level data_prot; + enum protection_level request_data_prot; + size_t buffer_size; + struct krb5buffer in_buffer; + void *app_data; + const struct Curl_sec_client_mech *mech; + struct sockaddr_in local_addr; +#endif + +#if defined(USE_KERBEROS5) /* Consider moving some of the above GSS-API */ + struct kerberos5data krb5; /* variables into the structure definition, */ +#endif /* however, some of them are ftp specific. */ + + struct curl_llist easyq; /* List of easy handles using this connection */ + curl_seek_callback seek_func; /* function that seeks the input */ + void *seek_client; /* pointer to pass to the seek() above */ + + /*************** Request - specific items ************/ +#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS) + CtxtHandle *sslContext; +#endif + +#if defined(USE_NTLM) + curlntlm http_ntlm_state; + curlntlm proxy_ntlm_state; + + struct ntlmdata ntlm; /* NTLM differs from other authentication schemes + because it authenticates connections, not + single requests! */ + struct ntlmdata proxyntlm; /* NTLM data for proxy */ + +#if defined(NTLM_WB_ENABLED) + /* used for communication with Samba's winbind daemon helper ntlm_auth */ + curl_socket_t ntlm_auth_hlpr_socket; + pid_t ntlm_auth_hlpr_pid; + char *challenge_header; + char *response_header; +#endif +#endif + +#ifdef USE_SPNEGO + curlnegotiate http_negotiate_state; + curlnegotiate proxy_negotiate_state; + + struct negotiatedata negotiate; /* state data for host Negotiate auth */ + struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ +#endif + + /* data used for the asynch name resolve callback */ + struct Curl_async async; + + /* These three are used for chunked-encoding trailer support */ + char *trailer; /* allocated buffer to store trailer in */ + int trlMax; /* allocated buffer size */ + int trlPos; /* index of where to store data */ + + union { + struct ftp_conn ftpc; + struct http_conn httpc; + struct ssh_conn sshc; + struct tftp_state_data *tftpc; + struct imap_conn imapc; + struct pop3_conn pop3c; + struct smtp_conn smtpc; + struct rtsp_conn rtspc; + struct smb_conn smbc; + void *generic; /* RTMP and LDAP use this */ + } proto; + + int cselect_bits; /* bitmask of socket events */ + int waitfor; /* current READ/WRITE bits to wait for */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + int socks5_gssapi_enctype; +#endif + + /* When this connection is created, store the conditions for the local end + bind. This is stored before the actual bind and before any connection is + made and will serve the purpose of being used for comparison reasons so + that subsequent bound-requested connections aren't accidentally re-using + wrong connections. */ + char *localdev; + unsigned short localport; + int localportrange; + struct http_connect_state *connect_state; /* for HTTP CONNECT */ + struct connectbundle *bundle; /* The bundle we are member of */ + int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ + +#ifdef USE_UNIX_SOCKETS + char *unix_domain_socket; + bit abstract_unix_socket:1; +#endif + bit tls_upgraded:1; + /* the two following *_inuse fields are only flags, not counters in any way. + If TRUE it means the channel is in use, and if FALSE it means the channel + is up for grabs by one. */ + bit readchannel_inuse:1; /* whether the read channel is in use by an easy + handle */ + bit writechannel_inuse:1; /* whether the write channel is in use by an easy + handle */ +}; + +/* The end of connectdata. */ + +/* + * Struct to keep statistical and informational data. + * All variables in this struct must be initialized/reset in Curl_initinfo(). + */ +struct PureInfo { + int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */ + int httpproxycode; /* response code from proxy when received separate */ + int httpversion; /* the http version number X.Y = X*10+Y */ + time_t filetime; /* If requested, this is might get set. Set to -1 if the + time was unretrievable. */ + curl_off_t header_size; /* size of read header(s) in bytes */ + curl_off_t request_size; /* the amount of bytes sent in the request(s) */ + unsigned long proxyauthavail; /* what proxy auth types were announced */ + unsigned long httpauthavail; /* what host auth types were announced */ + long numconnects; /* how many new connection did libcurl created */ + char *contenttype; /* the content type of the object */ + char *wouldredirect; /* URL this would've been redirected to if asked to */ + + /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip' + and, 'conn_local_port' are copied over from the connectdata struct in + order to allow curl_easy_getinfo() to return this information even when + the session handle is no longer associated with a connection, and also + allow curl_easy_reset() to clear this information from the session handle + without disturbing information which is still alive, and that might be + reused, in the connection cache. */ + + char conn_primary_ip[MAX_IPADR_LEN]; + long conn_primary_port; + char conn_local_ip[MAX_IPADR_LEN]; + long conn_local_port; + const char *conn_scheme; + unsigned int conn_protocol; + struct curl_certinfo certs; /* info about the certs, only populated in + OpenSSL, GnuTLS, Schannel, NSS and GSKit + builds. Asked for with CURLOPT_CERTINFO + / CURLINFO_CERTINFO */ + + bit timecond:1; /* set to TRUE if the time condition didn't match, which + thus made the document NOT get fetched */ +}; + + +struct Progress { + time_t lastshow; /* time() of the last displayed progress meter or NULL to + force redraw at next call */ + curl_off_t size_dl; /* total expected size */ + curl_off_t size_ul; /* total expected size */ + curl_off_t downloaded; /* transferred so far */ + curl_off_t uploaded; /* transferred so far */ + + curl_off_t current_speed; /* uses the currently fastest transfer */ + + int width; /* screen width at download start */ + int flags; /* see progress.h */ + + time_t timespent; + + curl_off_t dlspeed; + curl_off_t ulspeed; + + time_t t_nslookup; + time_t t_connect; + time_t t_appconnect; + time_t t_pretransfer; + time_t t_starttransfer; + time_t t_redirect; + + struct curltime start; + struct curltime t_startsingle; + struct curltime t_startop; + struct curltime t_acceptdata; + + + /* upload speed limit */ + struct curltime ul_limit_start; + curl_off_t ul_limit_size; + /* download speed limit */ + struct curltime dl_limit_start; + curl_off_t dl_limit_size; + +#define CURR_TIME (5 + 1) /* 6 entries for 5 seconds */ + + curl_off_t speeder[ CURR_TIME ]; + struct curltime speeder_time[ CURR_TIME ]; + int speeder_c; + bit callback:1; /* set when progress callback is used */ + bit is_t_startransfer_set:1; +}; + +typedef enum { + HTTPREQ_NONE, /* first in list */ + HTTPREQ_GET, + HTTPREQ_POST, + HTTPREQ_POST_FORM, /* we make a difference internally */ + HTTPREQ_POST_MIME, /* we make a difference internally */ + HTTPREQ_PUT, + HTTPREQ_HEAD, + HTTPREQ_OPTIONS, + HTTPREQ_LAST /* last in list */ +} Curl_HttpReq; + +typedef enum { + RTSPREQ_NONE, /* first in list */ + RTSPREQ_OPTIONS, + RTSPREQ_DESCRIBE, + RTSPREQ_ANNOUNCE, + RTSPREQ_SETUP, + RTSPREQ_PLAY, + RTSPREQ_PAUSE, + RTSPREQ_TEARDOWN, + RTSPREQ_GET_PARAMETER, + RTSPREQ_SET_PARAMETER, + RTSPREQ_RECORD, + RTSPREQ_RECEIVE, + RTSPREQ_LAST /* last in list */ +} Curl_RtspReq; + +/* + * Values that are generated, temporary or calculated internally for a + * "session handle" must be defined within the 'struct UrlState'. This struct + * will be used within the Curl_easy struct. When the 'Curl_easy' + * struct is cloned, this data MUST NOT be copied. + * + * Remember that any "state" information goes globally for the curl handle. + * Session-data MUST be put in the connectdata struct and here. */ +#define MAX_CURL_USER_LENGTH 256 +#define MAX_CURL_PASSWORD_LENGTH 256 + +struct auth { + unsigned long want; /* Bitmask set to the authentication methods wanted by + app (with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH). */ + unsigned long picked; + unsigned long avail; /* Bitmask for what the server reports to support for + this resource */ + bit done:1; /* TRUE when the auth phase is done and ready to do the + *actual* request */ + bit multipass:1; /* TRUE if this is not yet authenticated but within the + auth multipass negotiation */ + bit iestyle:1; /* TRUE if digest should be done IE-style or FALSE if it + should be RFC compliant */ +}; + +struct Curl_http2_dep { + struct Curl_http2_dep *next; + struct Curl_easy *data; +}; + +/* + * This struct is for holding data that was attempted to get sent to the user's + * callback but is held due to pausing. One instance per type (BOTH, HEADER, + * BODY). + */ +struct tempbuf { + char *buf; /* allocated buffer to keep data in when a write callback + returns to make the connection paused */ + size_t len; /* size of the 'tempwrite' allocated buffer */ + int type; /* type of the 'tempwrite' buffer as a bitmask that is used with + Curl_client_write() */ +}; + +/* Timers */ +typedef enum { + EXPIRE_100_TIMEOUT, + EXPIRE_ASYNC_NAME, + EXPIRE_CONNECTTIMEOUT, + EXPIRE_DNS_PER_NAME, + EXPIRE_HAPPY_EYEBALLS_DNS, /* See asyn-ares.c */ + EXPIRE_HAPPY_EYEBALLS, + EXPIRE_MULTI_PENDING, + EXPIRE_RUN_NOW, + EXPIRE_SPEEDCHECK, + EXPIRE_TIMEOUT, + EXPIRE_TOOFAST, + EXPIRE_LAST /* not an actual timer, used as a marker only */ +} expire_id; + + +typedef enum { + TRAILERS_NONE, + TRAILERS_INITIALIZED, + TRAILERS_SENDING, + TRAILERS_DONE +} trailers_state; + + +/* + * One instance for each timeout an easy handle can set. + */ +struct time_node { + struct curl_llist_element list; + struct curltime time; + expire_id eid; +}; + +/* individual pieces of the URL */ +struct urlpieces { + char *scheme; + char *hostname; + char *port; + char *user; + char *password; + char *options; + char *path; + char *query; +}; + +struct UrlState { + + /* Points to the connection cache */ + struct conncache *conn_cache; + + /* buffers to store authentication data in, as parsed from input options */ + struct curltime keeps_speed; /* for the progress meter really */ + + struct connectdata *lastconnect; /* The last connection, NULL if undefined */ + + char *headerbuff; /* allocated buffer to store headers in */ + size_t headersize; /* size of the allocation */ + + char *buffer; /* download buffer */ + char *ulbuf; /* allocated upload buffer or NULL */ + curl_off_t current_speed; /* the ProgressShow() function sets this, + bytes / second */ + char *first_host; /* host name of the first (not followed) request. + if set, this should be the host name that we will + sent authorization to, no else. Used to make Location: + following not keep sending user+password... This is + strdup() data. + */ + int first_remote_port; /* remote port of the first (not followed) request */ + struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ + long sessionage; /* number of the most recent session */ + unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */ + struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ + char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ + int os_errno; /* filled in with errno whenever an error occurs */ +#ifdef HAVE_SIGNAL + /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ + void (*prev_signal)(int sig); +#endif + struct digestdata digest; /* state data for host Digest auth */ + struct digestdata proxydigest; /* state data for proxy Digest auth */ + + struct auth authhost; /* auth details for host */ + struct auth authproxy; /* auth details for proxy */ + void *resolver; /* resolver state, if it is used in the URL state - + ares_channel f.e. */ + +#if defined(USE_OPENSSL) + /* void instead of ENGINE to avoid bleeding OpenSSL into this header */ + void *engine; +#endif /* USE_OPENSSL */ + struct curltime expiretime; /* set this with Curl_expire() only */ + struct Curl_tree timenode; /* for the splay stuff */ + struct curl_llist timeoutlist; /* list of pending timeouts */ + struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */ + + /* a place to store the most recently set FTP entrypath */ + char *most_recent_ftp_entrypath; + + int httpversion; /* the lowest HTTP version*10 reported by any server + involved in this request */ + +#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \ + !defined(__SYMBIAN32__) +/* do FTP line-end conversions on most platforms */ +#define CURL_DO_LINEEND_CONV + /* for FTP downloads: track CRLF sequences that span blocks */ + bit prev_block_had_trailing_cr:1; + /* for FTP downloads: how many CRLFs did we converted to LFs? */ + curl_off_t crlf_conversions; +#endif + char *range; /* range, if used. See README for detailed specification on + this syntax. */ + curl_off_t resume_from; /* continue [ftp] transfer from here */ + + /* This RTSP state information survives requests and connections */ + long rtsp_next_client_CSeq; /* the session's next client CSeq */ + long rtsp_next_server_CSeq; /* the session's next server CSeq */ + long rtsp_CSeq_recv; /* most recent CSeq received */ + + curl_off_t infilesize; /* size of file to upload, -1 means unknown. + Copied from set.filesize at start of operation */ + + size_t drain; /* Increased when this stream has data to read, even if its + socket is not necessarily is readable. Decreased when + checked. */ + + curl_read_callback fread_func; /* read callback/function */ + void *in; /* CURLOPT_READDATA */ + + struct Curl_easy *stream_depends_on; + int stream_weight; + CURLU *uh; /* URL handle for the current parsed URL */ + struct urlpieces up; +#ifndef CURL_DISABLE_HTTP + size_t trailers_bytes_sent; + Curl_send_buffer *trailers_buf; /* a buffer containing the compiled trailing + headers */ +#endif + trailers_state trailers_state; /* whether we are sending trailers + and what stage are we at */ +#ifdef CURLDEBUG + bit conncache_lock:1; +#endif + /* when curl_easy_perform() is called, the multi handle is "owned" by + the easy handle so curl_easy_cleanup() on such an easy handle will + also close the multi handle! */ + bit multi_owned_by_easy:1; + + bit this_is_a_follow:1; /* this is a followed Location: request */ + bit refused_stream:1; /* this was refused, try again */ + bit errorbuf:1; /* Set to TRUE if the error buffer is already filled in. + This must be set to FALSE every time _easy_perform() is + called. */ + bit allow_port:1; /* Is set.use_port allowed to take effect or not. This + is always set TRUE when curl_easy_perform() is called. */ + bit authproblem:1; /* TRUE if there's some problem authenticating */ + /* set after initial USER failure, to prevent an authentication loop */ + bit ftp_trying_alternative:1; + bit wildcardmatch:1; /* enable wildcard matching */ + bit expect100header:1; /* TRUE if we added Expect: 100-continue */ + bit use_range:1; + bit rangestringalloc:1; /* the range string is malloc()'ed */ + bit done:1; /* set to FALSE when Curl_init_do() is called and set to TRUE + when multi_done() is called, to prevent multi_done() to get + invoked twice when the multi interface is used. */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ + bit previouslypending:1; /* this transfer WAS in the multi->pending queue */ +}; + + +/* + * This 'DynamicStatic' struct defines dynamic states that actually change + * values in the 'UserDefined' area, which MUST be taken into consideration + * if the UserDefined struct is cloned or similar. You can probably just + * copy these, but each one indicate a special action on other data. + */ + +struct DynamicStatic { + char *url; /* work URL, copied from UserDefined */ + char *referer; /* referer string */ + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ + struct curl_slist *resolve; /* set to point to the set.resolve list when + this should be dealt with in pretransfer */ + bit url_alloc:1; /* URL string is malloc()'ed */ + bit referer_alloc:1; /* referer string is malloc()ed */ + bit wildcard_resolve:1; /* Set to true if any resolve change is a + wildcard */ +}; + +/* + * This 'UserDefined' struct must only contain data that is set once to go + * for many (perhaps) independent connections. Values that are generated or + * calculated internally for the "session handle" MUST be defined within the + * 'struct UrlState' instead. The only exceptions MUST note the changes in + * the 'DynamicStatic' struct. + * Character pointer fields point to dynamic storage, unless otherwise stated. + */ + +struct Curl_multi; /* declared and used only in multi.c */ + +enum dupstring { + STRING_CERT_ORIG, /* client certificate file name */ + STRING_CERT_PROXY, /* client certificate file name */ + STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/ + STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/ + STRING_COOKIE, /* HTTP cookie string to send */ + STRING_COOKIEJAR, /* dump all cookies to this file */ + STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */ + STRING_DEFAULT_PROTOCOL, /* Protocol to use when the URL doesn't specify */ + STRING_DEVICE, /* local network interface/address to use */ + STRING_ENCODING, /* Accept-Encoding string */ + STRING_FTP_ACCOUNT, /* ftp account data */ + STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */ + STRING_FTPPORT, /* port to send with the FTP PORT command */ + STRING_KEY_ORIG, /* private key file name */ + STRING_KEY_PROXY, /* private key file name */ + STRING_KEY_PASSWD_ORIG, /* plain text private key password */ + STRING_KEY_PASSWD_PROXY, /* plain text private key password */ + STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */ + STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */ + STRING_KRB_LEVEL, /* krb security level */ + STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find + $HOME/.netrc */ + STRING_PROXY, /* proxy to use */ + STRING_PRE_PROXY, /* pre socks proxy to use */ + STRING_SET_RANGE, /* range, if used */ + STRING_SET_REFERER, /* custom string for the HTTP referer field */ + STRING_SET_URL, /* what original URL to work on */ + STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */ + STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */ + STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */ + STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */ + STRING_SSL_CIPHER13_LIST_ORIG, /* list of TLS 1.3 ciphers to use */ + STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */ + STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */ + STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */ + STRING_USERAGENT, /* User-Agent string */ + STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */ + STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */ + STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */ + STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */ + STRING_SSL_ENGINE, /* name of ssl engine */ + STRING_USERNAME, /* , if used */ + STRING_PASSWORD, /* , if used */ + STRING_OPTIONS, /* , if used */ + STRING_PROXYUSERNAME, /* Proxy , if used */ + STRING_PROXYPASSWORD, /* Proxy , if used */ + STRING_NOPROXY, /* List of hosts which should not use the proxy, if + used */ + STRING_RTSP_SESSION_ID, /* Session ID to use */ + STRING_RTSP_STREAM_URI, /* Stream URI for this request */ + STRING_RTSP_TRANSPORT, /* Transport for this session */ +#ifdef USE_SSH + STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */ + STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */ + STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */ + STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */ +#endif + STRING_PROXY_SERVICE_NAME, /* Proxy service name */ + STRING_SERVICE_NAME, /* Service name */ + STRING_MAIL_FROM, + STRING_MAIL_AUTH, + +#ifdef USE_TLS_SRP + STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth */ + STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth */ +#endif + STRING_BEARER, /* , if used */ +#ifdef USE_UNIX_SOCKETS + STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */ +#endif + STRING_TARGET, /* CURLOPT_REQUEST_TARGET */ + STRING_DOH, /* CURLOPT_DOH_URL */ +#ifdef USE_ALTSVC + STRING_ALTSVC, /* CURLOPT_ALTSVC */ +#endif + /* -- end of zero-terminated strings -- */ + + STRING_LASTZEROTERMINATED, + + /* -- below this are pointers to binary data that cannot be strdup'ed. --- */ + + STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ + + STRING_LAST /* not used, just an end-of-list marker */ +}; + +/* callback that gets called when this easy handle is completed within a multi + handle. Only used for internally created transfers, like for example + DoH. */ +typedef int (*multidone_func)(struct Curl_easy *easy, CURLcode result); + +struct UserDefined { + FILE *err; /* the stderr user data goes here */ + void *debugdata; /* the data that will be passed to fdebug */ + char *errorbuffer; /* (Static) store failure messages in here */ + long proxyport; /* If non-zero, use this port number by default. If the + proxy string features a ":[port]" that one will override + this. */ + void *out; /* CURLOPT_WRITEDATA */ + void *in_set; /* CURLOPT_READDATA */ + void *writeheader; /* write the header to this if non-NULL */ + void *rtp_out; /* write RTP to this if non-NULL */ + long use_port; /* which port to use (when not using default) */ + unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */ + unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */ + unsigned long socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */ + long followlocation; /* as in HTTP Location: */ + long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1 + for infinity */ + + int keep_post; /* keep POSTs as POSTs after a 30x request; each + bit represents a request, from 301 to 303 */ + void *postfields; /* if POST, set the fields' values here */ + curl_seek_callback seek_func; /* function that seeks the input */ + curl_off_t postfieldsize; /* if POST, this might have a size to use instead + of strlen(), and then the data *may* be binary + (contain zero bytes) */ + unsigned short localport; /* local port number to bind to */ + int localportrange; /* number of additional port numbers to test in case the + 'localport' one can't be bind()ed */ + curl_write_callback fwrite_func; /* function that stores the output */ + curl_write_callback fwrite_header; /* function that stores headers */ + curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */ + curl_read_callback fread_func_set; /* function that reads the input */ + curl_progress_callback fprogress; /* OLD and deprecated progress callback */ + curl_xferinfo_callback fxferinfo; /* progress callback */ + curl_debug_callback fdebug; /* function that write informational data */ + curl_ioctl_callback ioctl_func; /* function for I/O control */ + curl_sockopt_callback fsockopt; /* function for setting socket options */ + void *sockopt_client; /* pointer to pass to the socket options callback */ + curl_opensocket_callback fopensocket; /* function for checking/translating + the address and opening the + socket */ + void *opensocket_client; + curl_closesocket_callback fclosesocket; /* function for closing the + socket */ + void *closesocket_client; + + void *seek_client; /* pointer to pass to the seek callback */ + /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ + /* function to convert from the network encoding: */ + curl_conv_callback convfromnetwork; + /* function to convert to the network encoding: */ + curl_conv_callback convtonetwork; + /* function to convert from UTF-8 encoding: */ + curl_conv_callback convfromutf8; + + void *progress_client; /* pointer to pass to the progress callback */ + void *ioctl_client; /* pointer to pass to the ioctl callback */ + long timeout; /* in milliseconds, 0 means no timeout */ + long connecttimeout; /* in milliseconds, 0 means no timeout */ + long accepttimeout; /* in milliseconds, 0 means no timeout */ + long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */ + long server_response_timeout; /* in milliseconds, 0 means no timeout */ + long maxage_conn; /* in seconds, max idle time to allow a connection that + is to be reused */ + long tftp_blksize; /* in bytes, 0 means use default */ + curl_off_t filesize; /* size of file to upload, -1 means unknown */ + long low_speed_limit; /* bytes/second */ + long low_speed_time; /* number of seconds */ + curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */ + curl_off_t max_recv_speed; /* high speed limit in bytes/second for + download */ + curl_off_t set_resume_from; /* continue [ftp] transfer from here */ + struct curl_slist *headers; /* linked list of extra headers */ + struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */ + struct curl_httppost *httppost; /* linked list of old POST data */ + curl_mimepart mimepost; /* MIME/POST data. */ + struct curl_slist *quote; /* after connection is established */ + struct curl_slist *postquote; /* after the transfer */ + struct curl_slist *prequote; /* before the transfer, after type */ + struct curl_slist *source_quote; /* 3rd party quote */ + struct curl_slist *source_prequote; /* in 3rd party transfer mode - before + the transfer on source host */ + struct curl_slist *source_postquote; /* in 3rd party transfer mode - after + the transfer on source host */ + struct curl_slist *telnet_options; /* linked list of telnet options */ + struct curl_slist *resolve; /* list of names to add/remove from + DNS cache */ + struct curl_slist *connect_to; /* list of host:port mappings to override + the hostname and port to connect to */ + curl_TimeCond timecondition; /* kind of time/date comparison */ + time_t timevalue; /* what time to compare with */ + Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ + long httpversion; /* when non-zero, a specific HTTP version requested to + be used in the library's request(s) */ + struct ssl_config_data ssl; /* user defined SSL stuff */ + struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ + struct ssl_general_config general_ssl; /* general user defined SSL stuff */ + curl_proxytype proxytype; /* what kind of proxy that is in use */ + long dns_cache_timeout; /* DNS cache timeout */ + long buffer_size; /* size of receive buffer to use */ + size_t upload_buffer_size; /* size of upload buffer to use, + keep it >= CURL_MAX_WRITE_SIZE */ + void *private_data; /* application-private data */ + struct curl_slist *http200aliases; /* linked list of aliases for http200 */ + long ipver; /* the CURL_IPRESOLVE_* defines in the public header file + 0 - whatever, 1 - v2, 2 - v6 */ + curl_off_t max_filesize; /* Maximum file size to download */ +#ifndef CURL_DISABLE_FTP + curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */ + curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */ + curl_ftpccc ftp_ccc; /* FTP CCC options */ +#endif + int ftp_create_missing_dirs; /* 1 - create directories that don't exist + 2 - the same but also allow MKD to fail once + */ + curl_sshkeycallback ssh_keyfunc; /* key matching callback */ + void *ssh_keyfunc_userp; /* custom pointer to callback */ + enum CURL_NETRC_OPTION + use_netrc; /* defined in include/curl.h */ + curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or + IMAP or POP3 or others! */ + long new_file_perms; /* Permissions to use when creating remote files */ + long new_directory_perms; /* Permissions to use when creating remote dirs */ + long ssh_auth_types; /* allowed SSH auth types */ + char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ + unsigned int scope_id; /* Scope id for IPv6 */ + long allowed_protocols; + long redir_protocols; + struct curl_slist *mail_rcpt; /* linked list of mail recipients */ + /* Common RTSP header options */ + Curl_RtspReq rtspreq; /* RTSP request type */ + long rtspversion; /* like httpversion, for RTSP */ + curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer + starts */ + curl_chunk_end_callback chunk_end; /* called after part transferring + stopped */ + curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds + to pattern (e.g. if WILDCARDMATCH is on) */ + void *fnmatch_data; + + long gssapi_delegation; /* GSS-API credential delegation, see the + documentation of CURLOPT_GSSAPI_DELEGATION */ + + long tcp_keepidle; /* seconds in idle before sending keepalive probe */ + long tcp_keepintvl; /* seconds between TCP keepalive probes */ + + size_t maxconnects; /* Max idle connections in the connection cache */ + + long expect_100_timeout; /* in milliseconds */ + struct Curl_easy *stream_depends_on; + int stream_weight; + struct Curl_http2_dep *stream_dependents; + + curl_resolver_start_callback resolver_start; /* optional callback called + before resolver start */ + void *resolver_start_client; /* pointer to pass to resolver start callback */ + long upkeep_interval_ms; /* Time between calls for connection upkeep. */ + multidone_func fmultidone; + struct Curl_easy *dohfor; /* this is a DoH request for that transfer */ + CURLU *uh; /* URL handle for the current parsed URL */ + void *trailer_data; /* pointer to pass to trailer data callback */ + curl_trailer_callback trailer_callback; /* trailing data callback */ + bit is_fread_set:1; /* has read callback been set to non-NULL? */ + bit is_fwrite_set:1; /* has write callback been set to non-NULL? */ + bit free_referer:1; /* set TRUE if 'referer' points to a string we + allocated */ + bit tftp_no_options:1; /* do not send TFTP options requests */ + bit sep_headers:1; /* handle host and proxy headers separately */ + bit cookiesession:1; /* new cookie session? */ + bit crlf:1; /* convert crlf on ftp upload(?) */ + bit strip_path_slash:1; /* strip off initial slash from path */ + bit ssh_compression:1; /* enable SSH compression */ + +/* Here follows boolean settings that define how to behave during + this session. They are STATIC, set by libcurl users or at least initially + and they don't change during operations. */ + bit get_filetime:1; /* get the time and get of the remote file */ + bit tunnel_thru_httpproxy:1; /* use CONNECT through a HTTP proxy */ + bit prefer_ascii:1; /* ASCII rather than binary */ + bit ftp_append:1; /* append, not overwrite, on upload */ + bit ftp_list_only:1; /* switch FTP command for listing directories */ +#ifndef CURL_DISABLE_FTP + bit ftp_use_port:1; /* use the FTP PORT command */ + bit ftp_use_epsv:1; /* if EPSV is to be attempted or not */ + bit ftp_use_eprt:1; /* if EPRT is to be attempted or not */ + bit ftp_use_pret:1; /* if PRET is to be used before PASV or not */ + bit ftp_skip_ip:1; /* skip the IP address the FTP server passes on to + us */ +#endif + bit hide_progress:1; /* don't use the progress meter */ + bit http_fail_on_error:1; /* fail on HTTP error codes >= 400 */ + bit http_keep_sending_on_error:1; /* for HTTP status codes >= 300 */ + bit http_follow_location:1; /* follow HTTP redirects */ + bit http_transfer_encoding:1; /* request compressed HTTP + transfer-encoding */ + bit allow_auth_to_other_hosts:1; + bit include_header:1; /* include received protocol headers in data output */ + bit http_set_referer:1; /* is a custom referer used */ + bit http_auto_referer:1; /* set "correct" referer when following + location: */ + bit opt_no_body:1; /* as set with CURLOPT_NOBODY */ + bit upload:1; /* upload request */ + bit verbose:1; /* output verbosity */ + bit krb:1; /* Kerberos connection requested */ + bit reuse_forbid:1; /* forbidden to be reused, close after use */ + bit reuse_fresh:1; /* do not re-use an existing connection */ + + bit no_signal:1; /* do not use any signal/alarm handler */ + bit tcp_nodelay:1; /* whether to enable TCP_NODELAY or not */ + bit ignorecl:1; /* ignore content length */ + bit connect_only:1; /* make connection, let application use the socket */ + bit http_te_skip:1; /* pass the raw body data to the user, even when + transfer-encoded (chunked, compressed) */ + bit http_ce_skip:1; /* pass the raw body data to the user, even when + content-encoded (chunked, compressed) */ + bit proxy_transfer_mode:1; /* set transfer mode (;type=) when doing + FTP via an HTTP proxy */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + bit socks5_gssapi_nec:1; /* Flag to support NEC SOCKS5 server */ +#endif + bit sasl_ir:1; /* Enable/disable SASL initial response */ + bit wildcard_enabled:1; /* enable wildcard matching */ + bit tcp_keepalive:1; /* use TCP keepalives */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit ssl_enable_npn:1; /* TLS NPN extension? */ + bit ssl_enable_alpn:1;/* TLS ALPN extension? */ + bit path_as_is:1; /* allow dotdots? */ + bit pipewait:1; /* wait for multiplex status before starting a new + connection */ + bit suppress_connect_headers:1; /* suppress proxy CONNECT response headers + from user callbacks */ + bit dns_shuffle_addresses:1; /* whether to shuffle addresses before use */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ + bit haproxyprotocol:1; /* whether to send HAProxy PROXY protocol v1 + header */ + bit abstract_unix_socket:1; + bit disallow_username_in_url:1; /* disallow username in url */ + bit doh:1; /* DNS-over-HTTPS enabled */ + bit doh_get:1; /* use GET for DoH requests, instead of POST */ + bit http09_allowed:1; /* allow HTTP/0.9 responses */ +}; + +struct Names { + struct curl_hash *hostcache; + enum { + HCACHE_NONE, /* not pointing to anything */ + HCACHE_MULTI, /* points to a shared one in the multi handle */ + HCACHE_SHARED /* points to a shared one in a shared object */ + } hostcachetype; +}; + +/* + * The 'connectdata' struct MUST have all the connection oriented stuff as we + * may have several simultaneous connections and connection structs in memory. + * + * The 'struct UserDefined' must only contain data that is set once to go for + * many (perhaps) independent connections. Values that are generated or + * calculated internally for the "session handle" must be defined within the + * 'struct UrlState' instead. + */ + +struct Curl_easy { + /* first, two fields for the linked list of these */ + struct Curl_easy *next; + struct Curl_easy *prev; + + struct connectdata *conn; + struct curl_llist_element connect_queue; + struct curl_llist_element conn_queue; /* list per connectdata */ + + CURLMstate mstate; /* the handle's state */ + CURLcode result; /* previous result */ + + struct Curl_message msg; /* A single posted message. */ + + /* Array with the plain socket numbers this handle takes care of, in no + particular order. Note that all sockets are added to the sockhash, where + the state etc are also kept. This array is mostly used to detect when a + socket is to be removed from the hash. See singlesocket(). */ + curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; + int actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in + sockets[] */ + int numsocks; + + struct Names dns; + struct Curl_multi *multi; /* if non-NULL, points to the multi handle + struct to which this "belongs" when used by + the multi interface */ + struct Curl_multi *multi_easy; /* if non-NULL, points to the multi handle + struct to which this "belongs" when used + by the easy interface */ + struct Curl_share *share; /* Share, handles global variable mutexing */ +#ifdef USE_LIBPSL + struct PslCache *psl; /* The associated PSL cache. */ +#endif + struct SingleRequest req; /* Request-specific data */ + struct UserDefined set; /* values set by the libcurl user */ + struct DynamicStatic change; /* possibly modified userdefined data */ + struct CookieInfo *cookies; /* the cookies, read from files and servers. + NOTE that the 'cookie' field in the + UserDefined struct defines if the "engine" + is to be used or not. */ +#ifdef USE_ALTSVC + struct altsvcinfo *asi; /* the alt-svc cache */ +#endif + struct Progress progress; /* for all the progress meter data */ + struct UrlState state; /* struct for fields used for state info and + other dynamic purposes */ +#ifndef CURL_DISABLE_FTP + struct WildcardData wildcard; /* wildcard download state info */ +#endif + struct PureInfo info; /* stats, reports and info data */ + struct curl_tlssessioninfo tsi; /* Information about the TLS session, only + valid after a client has asked for it */ +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) + iconv_t outbound_cd; /* for translating to the network encoding */ + iconv_t inbound_cd; /* for translating from the network encoding */ + iconv_t utf8_cd; /* for translating to UTF8 */ +#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ + unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */ +}; + +#define LIBCURL_NAME "libcurl" + +#endif /* HEADER_CURL_URLDATA_H */ diff --git a/libcurl/lib/vauth/cleartext.c b/libcurl/lib/vauth/cleartext.c new file mode 100644 index 0000000..6f452c1 --- /dev/null +++ b/libcurl/lib/vauth/cleartext.c @@ -0,0 +1,169 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4616 PLAIN authentication + * Draft LOGIN SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_POP3) + +#include +#include "urldata.h" + +#include "vauth/vauth.h" +#include "curl_base64.h" +#include "curl_md5.h" +#include "warnless.h" +#include "strtok.h" +#include "sendf.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_create_plain_message() + * + * This is used to generate an already encoded PLAIN message ready + * for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * authzid [in] - The authorization identity. + * authcid [in] - The authentication identity. + * passwd [in] - The password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, + const char *authzid, + const char *authcid, + const char *passwd, + char **outptr, size_t *outlen) +{ + CURLcode result; + char *plainauth; + size_t zlen; + size_t clen; + size_t plen; + size_t plainlen; + + *outlen = 0; + *outptr = NULL; + zlen = (authzid == NULL ? 0 : strlen(authzid)); + clen = strlen(authcid); + plen = strlen(passwd); + + /* Compute binary message length. Check for overflows. */ + if(((zlen + clen) > SIZE_T_MAX/4) || (plen > (SIZE_T_MAX/2 - 2))) + return CURLE_OUT_OF_MEMORY; + plainlen = zlen + clen + plen + 2; + + plainauth = malloc(plainlen); + if(!plainauth) + return CURLE_OUT_OF_MEMORY; + + /* Calculate the reply */ + if(zlen != 0) + memcpy(plainauth, authzid, zlen); + plainauth[zlen] = '\0'; + memcpy(plainauth + zlen + 1, authcid, clen); + plainauth[zlen + clen + 1] = '\0'; + memcpy(plainauth + zlen + clen + 2, passwd, plen); + + /* Base64 encode the reply */ + result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen); + free(plainauth); + + return result; +} + +/* + * Curl_auth_create_login_message() + * + * This is used to generate an already encoded LOGIN message containing the + * user name or password ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * valuep [in] - The user name or user's password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_login_message(struct Curl_easy *data, + const char *valuep, char **outptr, + size_t *outlen) +{ + size_t vlen = strlen(valuep); + + if(!vlen) { + /* Calculate an empty reply */ + *outptr = strdup("="); + if(*outptr) { + *outlen = (size_t) 1; + return CURLE_OK; + } + + *outlen = 0; + return CURLE_OUT_OF_MEMORY; + } + + /* Base64 encode the value */ + return Curl_base64_encode(data, valuep, vlen, outptr, outlen); +} + +/* + * Curl_auth_create_external_message() + * + * This is used to generate an already encoded EXTERNAL message containing + * the user name ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * user [in] - The user name. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_external_message(struct Curl_easy *data, + const char *user, char **outptr, + size_t *outlen) +{ + /* This is the same formatting as the login message */ + return Curl_auth_create_login_message(data, user, outptr, outlen); +} + +#endif /* if no users */ diff --git a/libcurl/lib/vauth/cram.c b/libcurl/lib/vauth/cram.c new file mode 100644 index 0000000..d148618 --- /dev/null +++ b/libcurl/lib/vauth/cram.c @@ -0,0 +1,138 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2195 CRAM-MD5 authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include +#include "urldata.h" + +#include "vauth/vauth.h" +#include "curl_base64.h" +#include "curl_hmac.h" +#include "curl_md5.h" +#include "warnless.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_decode_cram_md5_message() + * + * This is used to decode an already encoded CRAM-MD5 challenge message. + * + * Parameters: + * + * chlg64 [in] - The base64 encoded challenge message. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlg64len = strlen(chlg64); + + *outptr = NULL; + *outlen = 0; + + /* Decode the challenge if necessary */ + if(chlg64len && *chlg64 != '=') + result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen); + + return result; +} + +/* + * Curl_auth_create_cram_md5_message() + * + * This is used to generate an already encoded CRAM-MD5 response message ready + * for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg [in] - The challenge. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, + const char *chlg, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + HMAC_context *ctxt; + unsigned char digest[MD5_DIGEST_LEN]; + char *response; + + if(chlg) + chlglen = strlen(chlg); + + /* Compute the digest using the password as the key */ + ctxt = Curl_HMAC_init(Curl_HMAC_MD5, + (const unsigned char *) passwdp, + curlx_uztoui(strlen(passwdp))); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + /* Update the digest with the given challenge */ + if(chlglen > 0) + Curl_HMAC_update(ctxt, (const unsigned char *) chlg, + curlx_uztoui(chlglen)); + + /* Finalise the digest */ + Curl_HMAC_final(ctxt, digest); + + /* Generate the response */ + response = aprintf( + "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + userp, digest[0], digest[1], digest[2], digest[3], digest[4], + digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], + digest[11], digest[12], digest[13], digest[14], digest[15]); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the response */ + result = Curl_base64_encode(data, response, 0, outptr, outlen); + + free(response); + + return result; +} + +#endif /* !CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libcurl/lib/vauth/digest.c b/libcurl/lib/vauth/digest.c new file mode 100644 index 0000000..8cd4d83 --- /dev/null +++ b/libcurl/lib/vauth/digest.c @@ -0,0 +1,1005 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2831 DIGEST-MD5 authentication + * RFC7616 DIGEST-SHA256, DIGEST-SHA512-256 authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include + +#include "vauth/vauth.h" +#include "vauth/digest.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_hmac.h" +#include "curl_md5.h" +#include "curl_sha256.h" +#include "vtls/vtls.h" +#include "warnless.h" +#include "strtok.h" +#include "strcase.h" +#include "non-ascii.h" /* included for Curl_convert_... prototypes */ +#include "curl_printf.h" +#include "rand.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if !defined(USE_WINDOWS_SSPI) +#define DIGEST_QOP_VALUE_AUTH (1 << 0) +#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1) +#define DIGEST_QOP_VALUE_AUTH_CONF (1 << 2) + +#define DIGEST_QOP_VALUE_STRING_AUTH "auth" +#define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int" +#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf" + +/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines. + It converts digest text to ASCII so the MD5 will be correct for + what ultimately goes over the network. +*/ +#define CURL_OUTPUT_DIGEST_CONV(a, b) \ + result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \ + if(result) { \ + free(b); \ + return result; \ + } +#endif /* !USE_WINDOWS_SSPI */ + +bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, + const char **endptr) +{ + int c; + bool starts_with_quote = FALSE; + bool escape = FALSE; + + for(c = DIGEST_MAX_VALUE_LENGTH - 1; (*str && (*str != '=') && c--);) + *value++ = *str++; + *value = 0; + + if('=' != *str++) + /* eek, no match */ + return FALSE; + + if('\"' == *str) { + /* This starts with a quote so it must end with one as well! */ + str++; + starts_with_quote = TRUE; + } + + for(c = DIGEST_MAX_CONTENT_LENGTH - 1; *str && c--; str++) { + switch(*str) { + case '\\': + if(!escape) { + /* possibly the start of an escaped quote */ + escape = TRUE; + *content++ = '\\'; /* Even though this is an escape character, we still + store it as-is in the target buffer */ + continue; + } + break; + + case ',': + if(!starts_with_quote) { + /* This signals the end of the content if we didn't get a starting + quote and then we do "sloppy" parsing */ + c = 0; /* the end */ + continue; + } + break; + + case '\r': + case '\n': + /* end of string */ + c = 0; + continue; + + case '\"': + if(!escape && starts_with_quote) { + /* end of string */ + c = 0; + continue; + } + break; + } + + escape = FALSE; + *content++ = *str; + } + + *content = 0; + *endptr = str; + + return TRUE; +} + +#if !defined(USE_WINDOWS_SSPI) +/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/ +static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */ + unsigned char *dest) /* 33 bytes */ +{ + int i; + for(i = 0; i < 16; i++) + msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]); +} + +/* Convert sha256 chunk to RFC7616 -suitable ascii string*/ +static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */ + unsigned char *dest) /* 65 bytes */ +{ + int i; + for(i = 0; i < 32; i++) + msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]); +} + +/* Perform quoted-string escaping as described in RFC2616 and its errata */ +static char *auth_digest_string_quoted(const char *source) +{ + char *dest; + const char *s = source; + size_t n = 1; /* null terminator */ + + /* Calculate size needed */ + while(*s) { + ++n; + if(*s == '"' || *s == '\\') { + ++n; + } + ++s; + } + + dest = malloc(n); + if(dest) { + char *d = dest; + s = source; + while(*s) { + if(*s == '"' || *s == '\\') { + *d++ = '\\'; + } + *d++ = *s++; + } + *d = 0; + } + + return dest; +} + +/* Retrieves the value for a corresponding key from the challenge string + * returns TRUE if the key could be found, FALSE if it does not exists + */ +static bool auth_digest_get_key_value(const char *chlg, + const char *key, + char *value, + size_t max_val_len, + char end_char) +{ + char *find_pos; + size_t i; + + find_pos = strstr(chlg, key); + if(!find_pos) + return FALSE; + + find_pos += strlen(key); + + for(i = 0; *find_pos && *find_pos != end_char && i < max_val_len - 1; ++i) + value[i] = *find_pos++; + value[i] = '\0'; + + return TRUE; +} + +static CURLcode auth_digest_get_qop_values(const char *options, int *value) +{ + char *tmp; + char *token; + char *tok_buf = NULL; + + /* Initialise the output */ + *value = 0; + + /* Tokenise the list of qop values. Use a temporary clone of the buffer since + strtok_r() ruins it. */ + tmp = strdup(options); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + token = strtok_r(tmp, ",", &tok_buf); + while(token != NULL) { + if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) + *value |= DIGEST_QOP_VALUE_AUTH; + else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) + *value |= DIGEST_QOP_VALUE_AUTH_INT; + else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF)) + *value |= DIGEST_QOP_VALUE_AUTH_CONF; + + token = strtok_r(NULL, ",", &tok_buf); + } + + free(tmp); + + return CURLE_OK; +} + +/* + * auth_decode_digest_md5_message() + * + * This is used internally to decode an already encoded DIGEST-MD5 challenge + * message into the separate attributes. + * + * Parameters: + * + * chlg64 [in] - The base64 encoded challenge message. + * nonce [in/out] - The buffer where the nonce will be stored. + * nlen [in] - The length of the nonce buffer. + * realm [in/out] - The buffer where the realm will be stored. + * rlen [in] - The length of the realm buffer. + * alg [in/out] - The buffer where the algorithm will be stored. + * alen [in] - The length of the algorithm buffer. + * qop [in/out] - The buffer where the qop-options will be stored. + * qlen [in] - The length of the qop buffer. + * + * Returns CURLE_OK on success. + */ +static CURLcode auth_decode_digest_md5_message(const char *chlg64, + char *nonce, size_t nlen, + char *realm, size_t rlen, + char *alg, size_t alen, + char *qop, size_t qlen) +{ + CURLcode result = CURLE_OK; + unsigned char *chlg = NULL; + size_t chlglen = 0; + size_t chlg64len = strlen(chlg64); + + /* Decode the base-64 encoded challenge message */ + if(chlg64len && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) + return CURLE_BAD_CONTENT_ENCODING; + + /* Retrieve nonce string from the challenge */ + if(!auth_digest_get_key_value((char *) chlg, "nonce=\"", nonce, nlen, + '\"')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Retrieve realm string from the challenge */ + if(!auth_digest_get_key_value((char *) chlg, "realm=\"", realm, rlen, + '\"')) { + /* Challenge does not have a realm, set empty string [RFC2831] page 6 */ + strcpy(realm, ""); + } + + /* Retrieve algorithm string from the challenge */ + if(!auth_digest_get_key_value((char *) chlg, "algorithm=", alg, alen, ',')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Retrieve qop-options string from the challenge */ + if(!auth_digest_get_key_value((char *) chlg, "qop=\"", qop, qlen, '\"')) { + free(chlg); + return CURLE_BAD_CONTENT_ENCODING; + } + + free(chlg); + + return CURLE_OK; +} + +/* + * Curl_auth_is_digest_supported() + * + * This is used to evaluate if DIGEST is supported. + * + * Parameters: None + * + * Returns TRUE as DIGEST as handled by libcurl. + */ +bool Curl_auth_is_digest_supported(void) +{ + return TRUE; +} + +/* + * Curl_auth_create_digest_md5_message() + * + * This is used to generate an already encoded DIGEST-MD5 response message + * ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - The base64 encoded challenge message. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen) +{ + size_t i; + MD5_context *ctxt; + char *response = NULL; + unsigned char digest[MD5_DIGEST_LEN]; + char HA1_hex[2 * MD5_DIGEST_LEN + 1]; + char HA2_hex[2 * MD5_DIGEST_LEN + 1]; + char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; + char nonce[64]; + char realm[128]; + char algorithm[64]; + char qop_options[64]; + int qop_values; + char cnonce[33]; + char nonceCount[] = "00000001"; + char method[] = "AUTHENTICATE"; + char qop[] = DIGEST_QOP_VALUE_STRING_AUTH; + char *spn = NULL; + + /* Decode the challenge message */ + CURLcode result = auth_decode_digest_md5_message(chlg64, nonce, + sizeof(nonce), realm, + sizeof(realm), algorithm, + sizeof(algorithm), + qop_options, + sizeof(qop_options)); + if(result) + return result; + + /* We only support md5 sessions */ + if(strcmp(algorithm, "md5-sess") != 0) + return CURLE_BAD_CONTENT_ENCODING; + + /* Get the qop-values from the qop-options */ + result = auth_digest_get_qop_values(qop_options, &qop_values); + if(result) + return result; + + /* We only support auth quality-of-protection */ + if(!(qop_values & DIGEST_QOP_VALUE_AUTH)) + return CURLE_BAD_CONTENT_ENCODING; + + /* Generate 32 random hex chars, 32 bytes + 1 zero termination */ + result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce)); + if(result) + return result; + + /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) userp, + curlx_uztoui(strlen(userp))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) realm, + curlx_uztoui(strlen(realm))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) passwdp, + curlx_uztoui(strlen(passwdp))); + Curl_MD5_final(ctxt, digest); + + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) + return CURLE_OUT_OF_MEMORY; + + Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) nonce, + curlx_uztoui(strlen(nonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) cnonce, + curlx_uztoui(strlen(cnonce))); + Curl_MD5_final(ctxt, digest); + + /* Convert calculated 16 octet hex into 32 bytes string */ + for(i = 0; i < MD5_DIGEST_LEN; i++) + msnprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]); + + /* Generate our SPN */ + spn = Curl_auth_build_spn(service, realm, NULL); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Calculate H(A2) */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) { + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + Curl_MD5_update(ctxt, (const unsigned char *) method, + curlx_uztoui(strlen(method))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) spn, + curlx_uztoui(strlen(spn))); + Curl_MD5_final(ctxt, digest); + + for(i = 0; i < MD5_DIGEST_LEN; i++) + msnprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]); + + /* Now calculate the response hash */ + ctxt = Curl_MD5_init(Curl_DIGEST_MD5); + if(!ctxt) { + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) nonce, + curlx_uztoui(strlen(nonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + + Curl_MD5_update(ctxt, (const unsigned char *) nonceCount, + curlx_uztoui(strlen(nonceCount))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) cnonce, + curlx_uztoui(strlen(cnonce))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *) qop, + curlx_uztoui(strlen(qop))); + Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + + Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN); + Curl_MD5_final(ctxt, digest); + + for(i = 0; i < MD5_DIGEST_LEN; i++) + msnprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); + + /* Generate the response */ + response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\"," + "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s," + "qop=%s", + userp, realm, nonce, + cnonce, nonceCount, spn, resp_hash_hex, qop); + free(spn); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the response */ + result = Curl_base64_encode(data, response, 0, outptr, outlen); + + free(response); + + return result; +} + +/* + * Curl_auth_decode_digest_http_message() + * + * This is used to decode a HTTP DIGEST challenge message into the separate + * attributes. + * + * Parameters: + * + * chlg [in] - The challenge message. + * digest [in/out] - The digest data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_digest_http_message(const char *chlg, + struct digestdata *digest) +{ + bool before = FALSE; /* got a nonce before */ + bool foundAuth = FALSE; + bool foundAuthInt = FALSE; + char *token = NULL; + char *tmp = NULL; + + /* If we already have received a nonce, keep that in mind */ + if(digest->nonce) + before = TRUE; + + /* Clean up any former leftovers and initialise to defaults */ + Curl_auth_digest_cleanup(digest); + + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Extract a value=content pair */ + if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) { + if(strcasecompare(value, "nonce")) { + free(digest->nonce); + digest->nonce = strdup(content); + if(!digest->nonce) + return CURLE_OUT_OF_MEMORY; + } + else if(strcasecompare(value, "stale")) { + if(strcasecompare(content, "true")) { + digest->stale = TRUE; + digest->nc = 1; /* we make a new nonce now */ + } + } + else if(strcasecompare(value, "realm")) { + free(digest->realm); + digest->realm = strdup(content); + if(!digest->realm) + return CURLE_OUT_OF_MEMORY; + } + else if(strcasecompare(value, "opaque")) { + free(digest->opaque); + digest->opaque = strdup(content); + if(!digest->opaque) + return CURLE_OUT_OF_MEMORY; + } + else if(strcasecompare(value, "qop")) { + char *tok_buf = NULL; + /* Tokenize the list and choose auth if possible, use a temporary + clone of the buffer since strtok_r() ruins it */ + tmp = strdup(content); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + token = strtok_r(tmp, ",", &tok_buf); + while(token != NULL) { + if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) { + foundAuth = TRUE; + } + else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) { + foundAuthInt = TRUE; + } + token = strtok_r(NULL, ",", &tok_buf); + } + + free(tmp); + + /* Select only auth or auth-int. Otherwise, ignore */ + if(foundAuth) { + free(digest->qop); + digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH); + if(!digest->qop) + return CURLE_OUT_OF_MEMORY; + } + else if(foundAuthInt) { + free(digest->qop); + digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH_INT); + if(!digest->qop) + return CURLE_OUT_OF_MEMORY; + } + } + else if(strcasecompare(value, "algorithm")) { + free(digest->algorithm); + digest->algorithm = strdup(content); + if(!digest->algorithm) + return CURLE_OUT_OF_MEMORY; + + if(strcasecompare(content, "MD5-sess")) + digest->algo = CURLDIGESTALGO_MD5SESS; + else if(strcasecompare(content, "MD5")) + digest->algo = CURLDIGESTALGO_MD5; + else if(strcasecompare(content, "SHA-256")) + digest->algo = CURLDIGESTALGO_SHA256; + else if(strcasecompare(content, "SHA-256-SESS")) + digest->algo = CURLDIGESTALGO_SHA256SESS; + else if(strcasecompare(content, "SHA-512-256")) + digest->algo = CURLDIGESTALGO_SHA512_256; + else if(strcasecompare(content, "SHA-512-256-SESS")) + digest->algo = CURLDIGESTALGO_SHA512_256SESS; + else + return CURLE_BAD_CONTENT_ENCODING; + } + else if(strcasecompare(value, "userhash")) { + if(strcasecompare(content, "true")) { + digest->userhash = TRUE; + } + } + else { + /* Unknown specifier, ignore it! */ + } + } + else + break; /* We're done here */ + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Allow the list to be comma-separated */ + if(',' == *chlg) + chlg++; + } + + /* We had a nonce since before, and we got another one now without + 'stale=true'. This means we provided bad credentials in the previous + request */ + if(before && !digest->stale) + return CURLE_BAD_CONTENT_ENCODING; + + /* We got this header without a nonce, that's a bad Digest line! */ + if(!digest->nonce) + return CURLE_BAD_CONTENT_ENCODING; + + return CURLE_OK; +} + +/* + * _Curl_auth_create_digest_http_message() + * + * This is used to generate a HTTP DIGEST response message ready for sending + * to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * request [in] - The HTTP request. + * uripath [in] - The path of the HTTP uri. + * digest [in/out] - The digest data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +static CURLcode _Curl_auth_create_digest_http_message( + struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uripath, + struct digestdata *digest, + char **outptr, size_t *outlen, + void (*convert_to_ascii)(unsigned char *, unsigned char *), + void (*hash)(unsigned char *, const unsigned char *)) +{ + CURLcode result; + unsigned char hashbuf[32]; /* 32 bytes/256 bits */ + unsigned char request_digest[65]; + unsigned char *hashthis; + unsigned char ha1[65]; /* 64 digits and 1 zero byte */ + unsigned char ha2[65]; /* 64 digits and 1 zero byte */ + char userh[65]; + char *cnonce = NULL; + size_t cnonce_sz = 0; + char *userp_quoted; + char *response = NULL; + char *tmp = NULL; + + if(!digest->nc) + digest->nc = 1; + + if(!digest->cnonce) { + char cnoncebuf[33]; + result = Curl_rand_hex(data, (unsigned char *)cnoncebuf, + sizeof(cnoncebuf)); + if(result) + return result; + + result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), + &cnonce, &cnonce_sz); + if(result) + return result; + + digest->cnonce = cnonce; + } + + if(digest->userhash) { + hashthis = (unsigned char *) aprintf("%s:%s", userp, digest->realm); + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, hashthis); + hash(hashbuf, hashthis); + free(hashthis); + convert_to_ascii(hashbuf, (unsigned char *)userh); + } + + /* + If the algorithm is "MD5" or unspecified (which then defaults to MD5): + + A1 = unq(username-value) ":" unq(realm-value) ":" passwd + + If the algorithm is "MD5-sess" then: + + A1 = H(unq(username-value) ":" unq(realm-value) ":" passwd) ":" + unq(nonce-value) ":" unq(cnonce-value) + */ + + hashthis = (unsigned char *) + aprintf("%s:%s:%s", digest->userhash ? userh : userp, + digest->realm, passwdp); + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ + hash(hashbuf, hashthis); + free(hashthis); + convert_to_ascii(hashbuf, ha1); + + if(digest->algo == CURLDIGESTALGO_MD5SESS || + digest->algo == CURLDIGESTALGO_SHA256SESS || + digest->algo == CURLDIGESTALGO_SHA512_256SESS) { + /* nonce and cnonce are OUTSIDE the hash */ + tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, tmp); /* Convert on non-ASCII machines */ + hash(hashbuf, (unsigned char *) tmp); + free(tmp); + convert_to_ascii(hashbuf, ha1); + } + + /* + If the "qop" directive's value is "auth" or is unspecified, then A2 is: + + A2 = Method ":" digest-uri-value + + If the "qop" value is "auth-int", then A2 is: + + A2 = Method ":" digest-uri-value ":" H(entity-body) + + (The "Method" value is the HTTP request method as specified in section + 5.1.1 of RFC 2616) + */ + + hashthis = (unsigned char *) aprintf("%s:%s", request, uripath); + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + if(digest->qop && strcasecompare(digest->qop, "auth-int")) { + /* We don't support auth-int for PUT or POST */ + char hashed[65]; + unsigned char *hashthis2; + + hash(hashbuf, (const unsigned char *)""); + convert_to_ascii(hashbuf, (unsigned char *)hashed); + + hashthis2 = (unsigned char *)aprintf("%s:%s", hashthis, hashed); + free(hashthis); + hashthis = hashthis2; + } + + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ + hash(hashbuf, hashthis); + free(hashthis); + convert_to_ascii(hashbuf, ha2); + + if(digest->qop) { + hashthis = (unsigned char *) aprintf("%s:%s:%08x:%s:%s:%s", + ha1, + digest->nonce, + digest->nc, + digest->cnonce, + digest->qop, + ha2); + } + else { + hashthis = (unsigned char *) aprintf("%s:%s:%s", + ha1, + digest->nonce, + ha2); + } + + if(!hashthis) + return CURLE_OUT_OF_MEMORY; + + CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */ + hash(hashbuf, hashthis); + free(hashthis); + convert_to_ascii(hashbuf, request_digest); + + /* For test case 64 (snooped from a Mozilla 1.3a request) + + Authorization: Digest username="testuser", realm="testrealm", \ + nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca" + + Digest parameters are all quoted strings. Username which is provided by + the user will need double quotes and backslashes within it escaped. For + the other fields, this shouldn't be an issue. realm, nonce, and opaque + are copied as is from the server, escapes and all. cnonce is generated + with web-safe characters. uri is already percent encoded. nc is 8 hex + characters. algorithm and qop with standard values only contain web-safe + characters. + */ + userp_quoted = auth_digest_string_quoted(digest->userhash ? userh : userp); + if(!userp_quoted) + return CURLE_OUT_OF_MEMORY; + + if(digest->qop) { + response = aprintf("username=\"%s\", " + "realm=\"%s\", " + "nonce=\"%s\", " + "uri=\"%s\", " + "cnonce=\"%s\", " + "nc=%08x, " + "qop=%s, " + "response=\"%s\"", + userp_quoted, + digest->realm, + digest->nonce, + uripath, + digest->cnonce, + digest->nc, + digest->qop, + request_digest); + + if(strcasecompare(digest->qop, "auth")) + digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0 + padded which tells to the server how many times you are + using the same nonce in the qop=auth mode */ + } + else { + response = aprintf("username=\"%s\", " + "realm=\"%s\", " + "nonce=\"%s\", " + "uri=\"%s\", " + "response=\"%s\"", + userp_quoted, + digest->realm, + digest->nonce, + uripath, + request_digest); + } + free(userp_quoted); + if(!response) + return CURLE_OUT_OF_MEMORY; + + /* Add the optional fields */ + if(digest->opaque) { + /* Append the opaque */ + tmp = aprintf("%s, opaque=\"%s\"", response, digest->opaque); + free(response); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + response = tmp; + } + + if(digest->algorithm) { + /* Append the algorithm */ + tmp = aprintf("%s, algorithm=\"%s\"", response, digest->algorithm); + free(response); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + response = tmp; + } + + if(digest->userhash) { + /* Append the userhash */ + tmp = aprintf("%s, userhash=true", response); + free(response); + if(!tmp) + return CURLE_OUT_OF_MEMORY; + + response = tmp; + } + + /* Return the output */ + *outptr = response; + *outlen = strlen(response); + + return CURLE_OK; +} + +/* + * Curl_auth_create_digest_http_message() + * + * This is used to generate a HTTP DIGEST response message ready for sending + * to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * request [in] - The HTTP request. + * uripath [in] - The path of the HTTP uri. + * digest [in/out] - The digest data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uripath, + struct digestdata *digest, + char **outptr, size_t *outlen) +{ + switch(digest->algo) { + case CURLDIGESTALGO_MD5: + case CURLDIGESTALGO_MD5SESS: + return _Curl_auth_create_digest_http_message(data, userp, passwdp, + request, uripath, digest, + outptr, outlen, + auth_digest_md5_to_ascii, + Curl_md5it); + + case CURLDIGESTALGO_SHA256: + case CURLDIGESTALGO_SHA256SESS: + case CURLDIGESTALGO_SHA512_256: + case CURLDIGESTALGO_SHA512_256SESS: + return _Curl_auth_create_digest_http_message(data, userp, passwdp, + request, uripath, digest, + outptr, outlen, + auth_digest_sha256_to_ascii, + Curl_sha256it); + + default: + return CURLE_UNSUPPORTED_PROTOCOL; + } +} + +/* + * Curl_auth_digest_cleanup() + * + * This is used to clean up the digest specific data. + * + * Parameters: + * + * digest [in/out] - The digest data struct being cleaned up. + * + */ +void Curl_auth_digest_cleanup(struct digestdata *digest) +{ + Curl_safefree(digest->nonce); + Curl_safefree(digest->cnonce); + Curl_safefree(digest->realm); + Curl_safefree(digest->opaque); + Curl_safefree(digest->qop); + Curl_safefree(digest->algorithm); + + digest->nc = 0; + digest->algo = CURLDIGESTALGO_MD5; /* default algorithm */ + digest->stale = FALSE; /* default means normal, not stale */ + digest->userhash = FALSE; +} +#endif /* !USE_WINDOWS_SSPI */ + +#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libcurl/lib/vauth/digest.h b/libcurl/lib/vauth/digest.h new file mode 100644 index 0000000..8686c44 --- /dev/null +++ b/libcurl/lib/vauth/digest.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_DIGEST_H +#define HEADER_CURL_DIGEST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + +#define DIGEST_MAX_VALUE_LENGTH 256 +#define DIGEST_MAX_CONTENT_LENGTH 1024 + +enum { + CURLDIGESTALGO_MD5, + CURLDIGESTALGO_MD5SESS, + CURLDIGESTALGO_SHA256, + CURLDIGESTALGO_SHA256SESS, + CURLDIGESTALGO_SHA512_256, + CURLDIGESTALGO_SHA512_256SESS +}; + +/* This is used to extract the realm from a challenge message */ +bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, + const char **endptr); + +#endif + +#endif /* HEADER_CURL_DIGEST_H */ diff --git a/libcurl/lib/vauth/digest_sspi.c b/libcurl/lib/vauth/digest_sspi.c new file mode 100644 index 0000000..fe8093e --- /dev/null +++ b/libcurl/lib/vauth/digest_sspi.c @@ -0,0 +1,669 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2016, Steve Holme, . + * Copyright (C) 2015 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC2831 DIGEST-MD5 authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_CRYPTO_AUTH) + +#include + +#include "vauth/vauth.h" +#include "vauth/digest.h" +#include "urldata.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" +#include "strdup.h" +#include "strcase.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* +* Curl_auth_is_digest_supported() +* +* This is used to evaluate if DIGEST is supported. +* +* Parameters: None +* +* Returns TRUE if DIGEST is supported by Windows SSPI. +*/ +bool Curl_auth_is_digest_supported(void) +{ + PSecPkgInfo SecurityPackage; + SECURITY_STATUS status; + + /* Query the security package for Digest */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), + &SecurityPackage); + + return (status == SEC_E_OK ? TRUE : FALSE); +} + +/* + * Curl_auth_create_digest_md5_message() + * + * This is used to generate an already encoded DIGEST-MD5 response message + * ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - The base64 encoded challenge message. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + TCHAR *spn = NULL; + size_t chlglen = 0; + size_t token_max = 0; + unsigned char *input_token = NULL; + unsigned char *output_token = NULL; + CredHandle credentials; + CtxtHandle context; + PSecPkgInfo SecurityPackage; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + SecBuffer chlg_buf; + SecBuffer resp_buf; + SecBufferDesc chlg_desc; + SecBufferDesc resp_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + /* Decode the base-64 encoded challenge message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &input_token, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!input_token) { + infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Query the security package for DigestSSP */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), + &SecurityPackage); + if(status != SEC_E_OK) { + free(input_token); + + return CURLE_NOT_BUILT_IN; + } + + token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our response buffer */ + output_token = malloc(token_max); + if(!output_token) { + free(input_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Generate our SPN */ + spn = Curl_auth_build_spn(service, data->conn->host.name, NULL); + if(!spn) { + free(output_token); + free(input_token); + + return CURLE_OUT_OF_MEMORY; + } + + if(userp && *userp) { + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &identity); + if(result) { + free(spn); + free(output_token); + free(input_token); + + return result; + } + + /* Allow proper cleanup of the identity structure */ + p_identity = &identity; + } + else + /* Use the current Windows user */ + p_identity = NULL; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_DIGEST), + SECPKG_CRED_OUTBOUND, NULL, + p_identity, NULL, NULL, + &credentials, &expiry); + + if(status != SEC_E_OK) { + Curl_sspi_free_identity(p_identity); + free(spn); + free(output_token); + free(input_token); + + return CURLE_LOGIN_DENIED; + } + + /* Setup the challenge "input" security buffer */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 1; + chlg_desc.pBuffers = &chlg_buf; + chlg_buf.BufferType = SECBUFFER_TOKEN; + chlg_buf.pvBuffer = input_token; + chlg_buf.cbBuffer = curlx_uztoul(chlglen); + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = output_token; + resp_buf.cbBuffer = curlx_uztoul(token_max); + + /* Generate our response message */ + status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, spn, + 0, 0, 0, &chlg_desc, 0, + &context, &resp_desc, &attrs, + &expiry); + + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + s_pSecFn->FreeCredentialsHandle(&credentials); + Curl_sspi_free_identity(p_identity); + free(spn); + free(output_token); + free(input_token); + + return CURLE_RECV_ERROR; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer, + outptr, outlen); + + /* Free our handles */ + s_pSecFn->DeleteSecurityContext(&context); + s_pSecFn->FreeCredentialsHandle(&credentials); + + /* Free the identity structure */ + Curl_sspi_free_identity(p_identity); + + /* Free the SPN */ + free(spn); + + /* Free the response buffer */ + free(output_token); + + /* Free the decoded challenge message */ + free(input_token); + + return result; +} + +/* + * Curl_override_sspi_http_realm() + * + * This is used to populate the domain in a SSPI identity structure + * The realm is extracted from the challenge message and used as the + * domain if it is not already explicitly set. + * + * Parameters: + * + * chlg [in] - The challenge message. + * identity [in/out] - The identity structure. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_override_sspi_http_realm(const char *chlg, + SEC_WINNT_AUTH_IDENTITY *identity) +{ + xcharp_u domain, dup_domain; + + /* If domain is blank or unset, check challenge message for realm */ + if(!identity->Domain || !identity->DomainLength) { + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Extract a value=content pair */ + if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) { + if(strcasecompare(value, "realm")) { + + /* Setup identity's domain and length */ + domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *) content); + if(!domain.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + + dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr); + if(!dup_domain.tchar_ptr) { + Curl_unicodefree(domain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + + free(identity->Domain); + identity->Domain = dup_domain.tbyte_ptr; + identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr)); + dup_domain.tchar_ptr = NULL; + + Curl_unicodefree(domain.tchar_ptr); + } + else { + /* Unknown specifier, ignore it! */ + } + } + else + break; /* We're done here */ + + /* Pass all additional spaces here */ + while(*chlg && ISSPACE(*chlg)) + chlg++; + + /* Allow the list to be comma-separated */ + if(',' == *chlg) + chlg++; + } + } + + return CURLE_OK; +} + +/* + * Curl_auth_decode_digest_http_message() + * + * This is used to decode a HTTP DIGEST challenge message into the separate + * attributes. + * + * Parameters: + * + * chlg [in] - The challenge message. + * digest [in/out] - The digest data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_digest_http_message(const char *chlg, + struct digestdata *digest) +{ + size_t chlglen = strlen(chlg); + + /* We had an input token before so if there's another one now that means we + provided bad credentials in the previous request or it's stale. */ + if(digest->input_token) { + bool stale = false; + const char *p = chlg; + + /* Check for the 'stale' directive */ + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + while(*p && ISSPACE(*p)) + p++; + + if(!Curl_auth_digest_get_pair(p, value, content, &p)) + break; + + if(strcasecompare(value, "stale") && + strcasecompare(content, "true")) { + stale = true; + break; + } + + while(*p && ISSPACE(*p)) + p++; + + if(',' == *p) + p++; + } + + if(stale) + Curl_auth_digest_cleanup(digest); + else + return CURLE_LOGIN_DENIED; + } + + /* Store the challenge for use later */ + digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen + 1); + if(!digest->input_token) + return CURLE_OUT_OF_MEMORY; + + digest->input_token_len = chlglen; + + return CURLE_OK; +} + +/* + * Curl_auth_create_digest_http_message() + * + * This is used to generate a HTTP DIGEST response message ready for sending + * to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * request [in] - The HTTP request. + * uripath [in] - The path of the HTTP uri. + * digest [in/out] - The digest data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uripath, + struct digestdata *digest, + char **outptr, size_t *outlen) +{ + size_t token_max; + char *resp; + BYTE *output_token; + size_t output_token_len = 0; + PSecPkgInfo SecurityPackage; + SecBuffer chlg_buf[5]; + SecBufferDesc chlg_desc; + SECURITY_STATUS status; + + (void) data; + + /* Query the security package for DigestSSP */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), + &SecurityPackage); + if(status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate the output buffer according to the max token size as indicated + by the security package */ + output_token = malloc(token_max); + if(!output_token) { + return CURLE_OUT_OF_MEMORY; + } + + /* If the user/passwd that was used to make the identity for http_context + has changed then delete that context. */ + if((userp && !digest->user) || (!userp && digest->user) || + (passwdp && !digest->passwd) || (!passwdp && digest->passwd) || + (userp && digest->user && strcmp(userp, digest->user)) || + (passwdp && digest->passwd && strcmp(passwdp, digest->passwd))) { + if(digest->http_context) { + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); + } + Curl_safefree(digest->user); + Curl_safefree(digest->passwd); + } + + if(digest->http_context) { + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 5; + chlg_desc.pBuffers = chlg_buf; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = NULL; + chlg_buf[0].cbBuffer = 0; + chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[1].pvBuffer = (void *) request; + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[2].pvBuffer = (void *) uripath; + chlg_buf[2].cbBuffer = curlx_uztoul(strlen((const char *) uripath)); + chlg_buf[3].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[3].pvBuffer = NULL; + chlg_buf[3].cbBuffer = 0; + chlg_buf[4].BufferType = SECBUFFER_PADDING; + chlg_buf[4].pvBuffer = output_token; + chlg_buf[4].cbBuffer = curlx_uztoul(token_max); + + status = s_pSecFn->MakeSignature(digest->http_context, 0, &chlg_desc, 0); + if(status == SEC_E_OK) + output_token_len = chlg_buf[4].cbBuffer; + else { /* delete the context so a new one can be made */ + infof(data, "digest_sspi: MakeSignature failed, error 0x%08lx\n", + (long)status); + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); + } + } + + if(!digest->http_context) { + CredHandle credentials; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + SecBuffer resp_buf; + SecBufferDesc resp_desc; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + TCHAR *spn; + + /* free the copy of user/passwd used to make the previous identity */ + Curl_safefree(digest->user); + Curl_safefree(digest->passwd); + + if(userp && *userp) { + /* Populate our identity structure */ + if(Curl_create_sspi_identity(userp, passwdp, &identity)) { + free(output_token); + return CURLE_OUT_OF_MEMORY; + } + + /* Populate our identity domain */ + if(Curl_override_sspi_http_realm((const char *) digest->input_token, + &identity)) { + free(output_token); + return CURLE_OUT_OF_MEMORY; + } + + /* Allow proper cleanup of the identity structure */ + p_identity = &identity; + } + else + /* Use the current Windows user */ + p_identity = NULL; + + if(userp) { + digest->user = strdup(userp); + + if(!digest->user) { + free(output_token); + return CURLE_OUT_OF_MEMORY; + } + } + + if(passwdp) { + digest->passwd = strdup(passwdp); + + if(!digest->passwd) { + free(output_token); + Curl_safefree(digest->user); + return CURLE_OUT_OF_MEMORY; + } + } + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_DIGEST), + SECPKG_CRED_OUTBOUND, NULL, + p_identity, NULL, NULL, + &credentials, &expiry); + if(status != SEC_E_OK) { + Curl_sspi_free_identity(p_identity); + free(output_token); + + return CURLE_LOGIN_DENIED; + } + + /* Setup the challenge "input" security buffer if present */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 3; + chlg_desc.pBuffers = chlg_buf; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = digest->input_token; + chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len); + chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[1].pvBuffer = (void *) request; + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[2].pvBuffer = NULL; + chlg_buf[2].cbBuffer = 0; + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = output_token; + resp_buf.cbBuffer = curlx_uztoul(token_max); + + spn = Curl_convert_UTF8_to_tchar((char *) uripath); + if(!spn) { + s_pSecFn->FreeCredentialsHandle(&credentials); + + Curl_sspi_free_identity(p_identity); + free(output_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Allocate our new context handle */ + digest->http_context = calloc(1, sizeof(CtxtHandle)); + if(!digest->http_context) + return CURLE_OUT_OF_MEMORY; + + /* Generate our response message */ + status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, + spn, + ISC_REQ_USE_HTTP_STYLE, 0, 0, + &chlg_desc, 0, + digest->http_context, + &resp_desc, &attrs, &expiry); + Curl_unicodefree(spn); + + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + s_pSecFn->FreeCredentialsHandle(&credentials); + + Curl_sspi_free_identity(p_identity); + free(output_token); + + Curl_safefree(digest->http_context); + + return CURLE_OUT_OF_MEMORY; + } + + output_token_len = resp_buf.cbBuffer; + + s_pSecFn->FreeCredentialsHandle(&credentials); + Curl_sspi_free_identity(p_identity); + } + + resp = malloc(output_token_len + 1); + if(!resp) { + free(output_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Copy the generated response */ + memcpy(resp, output_token, output_token_len); + resp[output_token_len] = 0; + + /* Return the response */ + *outptr = resp; + *outlen = output_token_len; + + /* Free the response buffer */ + free(output_token); + + return CURLE_OK; +} + +/* + * Curl_auth_digest_cleanup() + * + * This is used to clean up the digest specific data. + * + * Parameters: + * + * digest [in/out] - The digest data struct being cleaned up. + * + */ +void Curl_auth_digest_cleanup(struct digestdata *digest) +{ + /* Free the input token */ + Curl_safefree(digest->input_token); + + /* Reset any variables */ + digest->input_token_len = 0; + + /* Delete security context */ + if(digest->http_context) { + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); + } + + /* Free the copy of user/passwd used to make the identity for http_context */ + Curl_safefree(digest->user); + Curl_safefree(digest->passwd); +} + +#endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_CRYPTO_AUTH */ diff --git a/libcurl/lib/vauth/krb5_gssapi.c b/libcurl/lib/vauth/krb5_gssapi.c new file mode 100644 index 0000000..ea0a5f1 --- /dev/null +++ b/libcurl/lib/vauth/krb5_gssapi.c @@ -0,0 +1,401 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2019, Steve Holme, . + * Copyright (C) 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && defined(USE_KERBEROS5) + +#include + +#include "vauth/vauth.h" +#include "curl_sasl.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_gssapi.h" +#include "sendf.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_gssapi_supported() + * + * This is used to evaluate if GSSAPI (Kerberos V5) is supported. + * + * Parameters: None + * + * Returns TRUE if Kerberos V5 is supported by the GSS-API library. + */ +bool Curl_auth_is_gssapi_supported(void) +{ + return TRUE; +} + +/* + * Curl_auth_create_gssapi_user_message() + * + * This is used to generate an already encoded GSSAPI (Kerberos V5) user token + * message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in[ - The host name. + * mutual_auth [in] - Flag specifying whether or not mutual authentication + * is enabled. + * chlg64 [in] - Pointer to the optional base64 encoded challenge + * message. + * krb5 [in/out] - The Kerberos 5 data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + const bool mutual_auth, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + unsigned char *chlg = NULL; + OM_uint32 major_status; + OM_uint32 minor_status; + OM_uint32 unused_status; + gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + + (void) userp; + (void) passwdp; + + if(!krb5->spn) { + /* Generate our SPN */ + char *spn = Curl_auth_build_spn(service, NULL, host); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Populate the SPN structure */ + spn_token.value = spn; + spn_token.length = strlen(spn); + + /* Import the SPN */ + major_status = gss_import_name(&minor_status, &spn_token, + GSS_C_NT_HOSTBASED_SERVICE, &krb5->spn); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_import_name() failed: ", + major_status, minor_status); + + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + free(spn); + } + + if(chlg64 && *chlg64) { + /* Decode the base-64 encoded challenge message */ + if(*chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + input_token.value = chlg; + input_token.length = chlglen; + } + + major_status = Curl_gss_init_sec_context(data, + &minor_status, + &krb5->context, + krb5->spn, + &Curl_krb5_mech_oid, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + &output_token, + mutual_auth, + NULL); + + /* Free the decoded challenge as it is not required anymore */ + free(input_token.value); + + if(GSS_ERROR(major_status)) { + if(output_token.value) + gss_release_buffer(&unused_status, &output_token); + + Curl_gss_log_error(data, "gss_init_sec_context() failed: ", + major_status, minor_status); + + return CURLE_RECV_ERROR; + } + + if(output_token.value && output_token.length) { + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token.value, + output_token.length, outptr, outlen); + + gss_release_buffer(&unused_status, &output_token); + } + else if(mutual_auth) { + *outptr = strdup(""); + if(!*outptr) + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + +/* + * Curl_auth_create_gssapi_security_message() + * + * This is used to generate an already encoded GSSAPI (Kerberos V5) security + * token message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - Pointer to the optional base64 encoded challenge message. + * krb5 [in/out] - The Kerberos 5 data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + size_t messagelen = 0; + unsigned char *chlg = NULL; + unsigned char *message = NULL; + OM_uint32 major_status; + OM_uint32 minor_status; + OM_uint32 unused_status; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + unsigned int indata = 0; + unsigned int outdata = 0; + gss_qop_t qop = GSS_C_QOP_DEFAULT; + unsigned int sec_layer = 0; + unsigned int max_size = 0; + gss_name_t username = GSS_C_NO_NAME; + gss_buffer_desc username_token; + + /* Decode the base-64 encoded input message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Get the fully qualified username back from the context */ + major_status = gss_inquire_context(&minor_status, krb5->context, + &username, NULL, NULL, NULL, NULL, + NULL, NULL); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_inquire_context() failed: ", + major_status, minor_status); + + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Convert the username from internal format to a displayable token */ + major_status = gss_display_name(&minor_status, username, + &username_token, NULL); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_display_name() failed: ", + major_status, minor_status); + + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the challenge "input" security buffer */ + input_token.value = chlg; + input_token.length = chlglen; + + /* Decrypt the inbound challenge and obtain the qop */ + major_status = gss_unwrap(&minor_status, krb5->context, &input_token, + &output_token, NULL, &qop); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_unwrap() failed: ", + major_status, minor_status); + + gss_release_buffer(&unused_status, &username_token); + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ + if(output_token.length != 4) { + infof(data, "GSSAPI handshake failure (invalid security data)\n"); + + gss_release_buffer(&unused_status, &username_token); + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Copy the data out and free the challenge as it is not required anymore */ + memcpy(&indata, output_token.value, 4); + gss_release_buffer(&unused_status, &output_token); + free(chlg); + + /* Extract the security layer */ + sec_layer = indata & 0x000000FF; + if(!(sec_layer & GSSAUTH_P_NONE)) { + infof(data, "GSSAPI handshake failure (invalid security layer)\n"); + + gss_release_buffer(&unused_status, &username_token); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Extract the maximum message size the server can receive */ + max_size = ntohl(indata & 0xFFFFFF00); + if(max_size > 0) { + /* The server has told us it supports a maximum receive buffer, however, as + we don't require one unless we are encrypting data, we tell the server + our receive buffer is zero. */ + max_size = 0; + } + + /* Allocate our message */ + messagelen = sizeof(outdata) + username_token.length + 1; + message = malloc(messagelen); + if(!message) { + gss_release_buffer(&unused_status, &username_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the message with the security layer, client supported receive + message size and authorization identity including the 0x00 based + terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization + identity is not terminated with the zero-valued (%x00) octet." it seems + necessary to include it. */ + outdata = htonl(max_size) | sec_layer; + memcpy(message, &outdata, sizeof(outdata)); + memcpy(message + sizeof(outdata), username_token.value, + username_token.length); + message[messagelen - 1] = '\0'; + + /* Free the username token as it is not required anymore */ + gss_release_buffer(&unused_status, &username_token); + + /* Setup the "authentication data" security buffer */ + input_token.value = message; + input_token.length = messagelen; + + /* Encrypt the data */ + major_status = gss_wrap(&minor_status, krb5->context, 0, + GSS_C_QOP_DEFAULT, &input_token, NULL, + &output_token); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_wrap() failed: ", + major_status, minor_status); + + free(message); + + return CURLE_OUT_OF_MEMORY; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) output_token.value, + output_token.length, outptr, outlen); + + /* Free the output buffer */ + gss_release_buffer(&unused_status, &output_token); + + /* Free the message buffer */ + free(message); + + return result; +} + +/* + * Curl_auth_cleanup_gssapi() + * + * This is used to clean up the GSSAPI (Kerberos V5) specific data. + * + * Parameters: + * + * krb5 [in/out] - The Kerberos 5 data struct being cleaned up. + * + */ +void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5) +{ + OM_uint32 minor_status; + + /* Free our security context */ + if(krb5->context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&minor_status, &krb5->context, GSS_C_NO_BUFFER); + krb5->context = GSS_C_NO_CONTEXT; + } + + /* Free the SPN */ + if(krb5->spn != GSS_C_NO_NAME) { + gss_release_name(&minor_status, &krb5->spn); + krb5->spn = GSS_C_NO_NAME; + } +} + +#endif /* HAVE_GSSAPI && USE_KERBEROS5 */ diff --git a/libcurl/lib/vauth/krb5_sspi.c b/libcurl/lib/vauth/krb5_sspi.c new file mode 100644 index 0000000..1f6e462 --- /dev/null +++ b/libcurl/lib/vauth/krb5_sspi.c @@ -0,0 +1,514 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2019, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && defined(USE_KERBEROS5) + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_gssapi_supported() + * + * This is used to evaluate if GSSAPI (Kerberos V5) is supported. + * + * Parameters: None + * + * Returns TRUE if Kerberos V5 is supported by Windows SSPI. + */ +bool Curl_auth_is_gssapi_supported(void) +{ + PSecPkgInfo SecurityPackage; + SECURITY_STATUS status; + + /* Query the security package for Kerberos */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_KERBEROS), + &SecurityPackage); + + return (status == SEC_E_OK ? TRUE : FALSE); +} + +/* + * Curl_auth_create_gssapi_user_message() + * + * This is used to generate an already encoded GSSAPI (Kerberos V5) user token + * message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * mutual_auth [in] - Flag specifying whether or not mutual authentication + * is enabled. + * chlg64 [in] - The optional base64 encoded challenge message. + * krb5 [in/out] - The Kerberos 5 data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + const bool mutual_auth, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + unsigned char *chlg = NULL; + CtxtHandle context; + PSecPkgInfo SecurityPackage; + SecBuffer chlg_buf; + SecBuffer resp_buf; + SecBufferDesc chlg_desc; + SecBufferDesc resp_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + if(!krb5->spn) { + /* Generate our SPN */ + krb5->spn = Curl_auth_build_spn(service, host, NULL); + if(!krb5->spn) + return CURLE_OUT_OF_MEMORY; + } + + if(!krb5->output_token) { + /* Query the security package for Kerberos */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_KERBEROS), + &SecurityPackage); + if(status != SEC_E_OK) { + return CURLE_NOT_BUILT_IN; + } + + krb5->token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our response buffer */ + krb5->output_token = malloc(krb5->token_max); + if(!krb5->output_token) + return CURLE_OUT_OF_MEMORY; + } + + if(!krb5->credentials) { + /* Do we have credentials to use or are we using single sign-on? */ + if(userp && *userp) { + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ + krb5->p_identity = &krb5->identity; + } + else + /* Use the current Windows user */ + krb5->p_identity = NULL; + + /* Allocate our credentials handle */ + krb5->credentials = calloc(1, sizeof(CredHandle)); + if(!krb5->credentials) + return CURLE_OUT_OF_MEMORY; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) + TEXT(SP_NAME_KERBEROS), + SECPKG_CRED_OUTBOUND, NULL, + krb5->p_identity, NULL, NULL, + krb5->credentials, &expiry); + if(status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + + /* Allocate our new context handle */ + krb5->context = calloc(1, sizeof(CtxtHandle)); + if(!krb5->context) + return CURLE_OUT_OF_MEMORY; + } + + if(chlg64 && *chlg64) { + /* Decode the base-64 encoded challenge message */ + if(*chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 1; + chlg_desc.pBuffers = &chlg_buf; + chlg_buf.BufferType = SECBUFFER_TOKEN; + chlg_buf.pvBuffer = chlg; + chlg_buf.cbBuffer = curlx_uztoul(chlglen); + } + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = krb5->output_token; + resp_buf.cbBuffer = curlx_uztoul(krb5->token_max); + + /* Generate our challenge-response message */ + status = s_pSecFn->InitializeSecurityContext(krb5->credentials, + chlg ? krb5->context : NULL, + krb5->spn, + (mutual_auth ? + ISC_REQ_MUTUAL_AUTH : 0), + 0, SECURITY_NATIVE_DREP, + chlg ? &chlg_desc : NULL, 0, + &context, + &resp_desc, &attrs, + &expiry); + + /* Free the decoded challenge as it is not required anymore */ + free(chlg); + + if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + return CURLE_RECV_ERROR; + } + + if(memcmp(&context, krb5->context, sizeof(context))) { + s_pSecFn->DeleteSecurityContext(krb5->context); + + memcpy(krb5->context, &context, sizeof(context)); + } + + if(resp_buf.cbBuffer) { + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) resp_buf.pvBuffer, + resp_buf.cbBuffer, outptr, outlen); + } + else if(mutual_auth) { + *outptr = strdup(""); + if(!*outptr) + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + +/* + * Curl_auth_create_gssapi_security_message() + * + * This is used to generate an already encoded GSSAPI (Kerberos V5) security + * token message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * chlg64 [in] - The optional base64 encoded challenge message. + * krb5 [in/out] - The Kerberos 5 data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen) +{ + CURLcode result = CURLE_OK; + size_t offset = 0; + size_t chlglen = 0; + size_t messagelen = 0; + size_t appdatalen = 0; + unsigned char *chlg = NULL; + unsigned char *trailer = NULL; + unsigned char *message = NULL; + unsigned char *padding = NULL; + unsigned char *appdata = NULL; + SecBuffer input_buf[2]; + SecBuffer wrap_buf[3]; + SecBufferDesc input_desc; + SecBufferDesc wrap_desc; + unsigned long indata = 0; + unsigned long outdata = 0; + unsigned long qop = 0; + unsigned long sec_layer = 0; + unsigned long max_size = 0; + SecPkgContext_Sizes sizes; + SecPkgCredentials_Names names; + SECURITY_STATUS status; + char *user_name; + + /* Decode the base-64 encoded input message */ + if(strlen(chlg64) && *chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Get our response size information */ + status = s_pSecFn->QueryContextAttributes(krb5->context, + SECPKG_ATTR_SIZES, + &sizes); + if(status != SEC_E_OK) { + free(chlg); + + return CURLE_OUT_OF_MEMORY; + } + + /* Get the fully qualified username back from the context */ + status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials, + SECPKG_CRED_ATTR_NAMES, + &names); + if(status != SEC_E_OK) { + free(chlg); + + return CURLE_RECV_ERROR; + } + + /* Setup the "input" security buffer */ + input_desc.ulVersion = SECBUFFER_VERSION; + input_desc.cBuffers = 2; + input_desc.pBuffers = input_buf; + input_buf[0].BufferType = SECBUFFER_STREAM; + input_buf[0].pvBuffer = chlg; + input_buf[0].cbBuffer = curlx_uztoul(chlglen); + input_buf[1].BufferType = SECBUFFER_DATA; + input_buf[1].pvBuffer = NULL; + input_buf[1].cbBuffer = 0; + + /* Decrypt the inbound challenge and obtain the qop */ + status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop); + if(status != SEC_E_OK) { + infof(data, "GSSAPI handshake failure (empty security message)\n"); + + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ + if(input_buf[1].cbBuffer != 4) { + infof(data, "GSSAPI handshake failure (invalid security data)\n"); + + free(chlg); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Copy the data out and free the challenge as it is not required anymore */ + memcpy(&indata, input_buf[1].pvBuffer, 4); + s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer); + free(chlg); + + /* Extract the security layer */ + sec_layer = indata & 0x000000FF; + if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) { + infof(data, "GSSAPI handshake failure (invalid security layer)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Extract the maximum message size the server can receive */ + max_size = ntohl(indata & 0xFFFFFF00); + if(max_size > 0) { + /* The server has told us it supports a maximum receive buffer, however, as + we don't require one unless we are encrypting data, we tell the server + our receive buffer is zero. */ + max_size = 0; + } + + /* Allocate the trailer */ + trailer = malloc(sizes.cbSecurityTrailer); + if(!trailer) + return CURLE_OUT_OF_MEMORY; + + /* Convert the user name to UTF8 when operating with Unicode */ + user_name = Curl_convert_tchar_to_UTF8(names.sUserName); + if(!user_name) { + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Allocate our message */ + messagelen = sizeof(outdata) + strlen(user_name) + 1; + message = malloc(messagelen); + if(!message) { + free(trailer); + Curl_unicodefree(user_name); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the message with the security layer, client supported receive + message size and authorization identity including the 0x00 based + terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization + identity is not terminated with the zero-valued (%x00) octet." it seems + necessary to include it. */ + outdata = htonl(max_size) | sec_layer; + memcpy(message, &outdata, sizeof(outdata)); + strcpy((char *) message + sizeof(outdata), user_name); + Curl_unicodefree(user_name); + + /* Allocate the padding */ + padding = malloc(sizes.cbBlockSize); + if(!padding) { + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Setup the "authentication data" security buffer */ + wrap_desc.ulVersion = SECBUFFER_VERSION; + wrap_desc.cBuffers = 3; + wrap_desc.pBuffers = wrap_buf; + wrap_buf[0].BufferType = SECBUFFER_TOKEN; + wrap_buf[0].pvBuffer = trailer; + wrap_buf[0].cbBuffer = sizes.cbSecurityTrailer; + wrap_buf[1].BufferType = SECBUFFER_DATA; + wrap_buf[1].pvBuffer = message; + wrap_buf[1].cbBuffer = curlx_uztoul(messagelen); + wrap_buf[2].BufferType = SECBUFFER_PADDING; + wrap_buf[2].pvBuffer = padding; + wrap_buf[2].cbBuffer = sizes.cbBlockSize; + + /* Encrypt the data */ + status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT, + &wrap_desc, 0); + if(status != SEC_E_OK) { + free(padding); + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Allocate the encryption (wrap) buffer */ + appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer + + wrap_buf[2].cbBuffer; + appdata = malloc(appdatalen); + if(!appdata) { + free(padding); + free(message); + free(trailer); + + return CURLE_OUT_OF_MEMORY; + } + + /* Populate the encryption buffer */ + memcpy(appdata, wrap_buf[0].pvBuffer, wrap_buf[0].cbBuffer); + offset += wrap_buf[0].cbBuffer; + memcpy(appdata + offset, wrap_buf[1].pvBuffer, wrap_buf[1].cbBuffer); + offset += wrap_buf[1].cbBuffer; + memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer); + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) appdata, appdatalen, outptr, + outlen); + + /* Free all of our local buffers */ + free(appdata); + free(padding); + free(message); + free(trailer); + + return result; +} + +/* + * Curl_auth_cleanup_gssapi() + * + * This is used to clean up the GSSAPI (Kerberos V5) specific data. + * + * Parameters: + * + * krb5 [in/out] - The Kerberos 5 data struct being cleaned up. + * + */ +void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5) +{ + /* Free our security context */ + if(krb5->context) { + s_pSecFn->DeleteSecurityContext(krb5->context); + free(krb5->context); + krb5->context = NULL; + } + + /* Free our credentials handle */ + if(krb5->credentials) { + s_pSecFn->FreeCredentialsHandle(krb5->credentials); + free(krb5->credentials); + krb5->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(krb5->p_identity); + krb5->p_identity = NULL; + + /* Free the SPN and output token */ + Curl_safefree(krb5->spn); + Curl_safefree(krb5->output_token); + + /* Reset any variables */ + krb5->token_max = 0; +} + +#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5*/ diff --git a/libcurl/lib/vauth/ntlm.c b/libcurl/lib/vauth/ntlm.c new file mode 100644 index 0000000..047c2b5 --- /dev/null +++ b/libcurl/lib/vauth/ntlm.c @@ -0,0 +1,871 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI) + +/* + * NTLM details: + * + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html + */ + +#define DEBUG_ME 0 + +#include "urldata.h" +#include "non-ascii.h" +#include "sendf.h" +#include "curl_base64.h" +#include "curl_ntlm_core.h" +#include "curl_gethostname.h" +#include "curl_multibyte.h" +#include "warnless.h" +#include "rand.h" +#include "vtls/vtls.h" + +/* SSL backend-specific #if branches in this file must be kept in the order + documented in curl_ntlm_core. */ +#if defined(NTLM_NEEDS_NSS_INIT) +#include "vtls/nssg.h" /* for Curl_nss_force_init() */ +#endif + +#define BUILDING_CURL_NTLM_MSGS_C +#include "vauth/vauth.h" +#include "vauth/ntlm.h" +#include "curl_endian.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* "NTLMSSP" signature is always in ASCII regardless of the platform */ +#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" + +#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)) +#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \ + ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff)) + +#if DEBUG_ME +# define DEBUG_OUT(x) x +static void ntlm_print_flags(FILE *handle, unsigned long flags) +{ + if(flags & NTLMFLAG_NEGOTIATE_UNICODE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE "); + if(flags & NTLMFLAG_NEGOTIATE_OEM) + fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM "); + if(flags & NTLMFLAG_REQUEST_TARGET) + fprintf(handle, "NTLMFLAG_REQUEST_TARGET "); + if(flags & (1<<3)) + fprintf(handle, "NTLMFLAG_UNKNOWN_3 "); + if(flags & NTLMFLAG_NEGOTIATE_SIGN) + fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN "); + if(flags & NTLMFLAG_NEGOTIATE_SEAL) + fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL "); + if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE "); + if(flags & NTLMFLAG_NEGOTIATE_LM_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY "); + if(flags & NTLMFLAG_NEGOTIATE_NETWARE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE "); + if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY "); + if(flags & (1<<10)) + fprintf(handle, "NTLMFLAG_UNKNOWN_10 "); + if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS) + fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS "); + if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED) + fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED "); + if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED) + fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED "); + if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL) + fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL "); + if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN) + fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN "); + if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN "); + if(flags & NTLMFLAG_TARGET_TYPE_SERVER) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER "); + if(flags & NTLMFLAG_TARGET_TYPE_SHARE) + fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE "); + if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) + fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY "); + if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE) + fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE "); + if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE) + fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE "); + if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY) + fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY "); + if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) + fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO "); + if(flags & (1<<24)) + fprintf(handle, "NTLMFLAG_UNKNOWN_24 "); + if(flags & (1<<25)) + fprintf(handle, "NTLMFLAG_UNKNOWN_25 "); + if(flags & (1<<26)) + fprintf(handle, "NTLMFLAG_UNKNOWN_26 "); + if(flags & (1<<27)) + fprintf(handle, "NTLMFLAG_UNKNOWN_27 "); + if(flags & (1<<28)) + fprintf(handle, "NTLMFLAG_UNKNOWN_28 "); + if(flags & NTLMFLAG_NEGOTIATE_128) + fprintf(handle, "NTLMFLAG_NEGOTIATE_128 "); + if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE) + fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE "); + if(flags & NTLMFLAG_NEGOTIATE_56) + fprintf(handle, "NTLMFLAG_NEGOTIATE_56 "); +} + +static void ntlm_print_hex(FILE *handle, const char *buf, size_t len) +{ + const char *p = buf; + + (void) handle; + + fprintf(stderr, "0x"); + while(len-- > 0) + fprintf(stderr, "%02.2x", (unsigned int)*p++); +} +#else +# define DEBUG_OUT(x) Curl_nop_stmt +#endif + +/* + * ntlm_decode_type2_target() + * + * This is used to decode the "target info" in the NTLM type-2 message + * received. + * + * Parameters: + * + * data [in] - The session handle. + * buffer [in] - The decoded type-2 message. + * size [in] - The input buffer size, at least 32 bytes. + * ntlm [in/out] - The NTLM data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, + unsigned char *buffer, + size_t size, + struct ntlmdata *ntlm) +{ + unsigned short target_info_len = 0; + unsigned int target_info_offset = 0; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + if(size >= 48) { + target_info_len = Curl_read16_le(&buffer[40]); + target_info_offset = Curl_read32_le(&buffer[44]); + if(target_info_len > 0) { + if((target_info_offset >= size) || + ((target_info_offset + target_info_len) > size) || + (target_info_offset < 48)) { + infof(data, "NTLM handshake failure (bad type-2 message). " + "Target Info Offset Len is set incorrect by the peer\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->target_info = malloc(target_info_len); + if(!ntlm->target_info) + return CURLE_OUT_OF_MEMORY; + + memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len); + } + } + + ntlm->target_info_len = target_info_len; + + return CURLE_OK; +} + +/* + NTLM message structure notes: + + A 'short' is a 'network short', a little-endian 16-bit unsigned value. + + A 'long' is a 'network long', a little-endian, 32-bit unsigned value. + + A 'security buffer' represents a triplet used to point to a buffer, + consisting of two shorts and one long: + + 1. A 'short' containing the length of the buffer content in bytes. + 2. A 'short' containing the allocated space for the buffer in bytes. + 3. A 'long' containing the offset to the start of the buffer in bytes, + from the beginning of the NTLM message. +*/ + +/* + * Curl_auth_is_ntlm_supported() + * + * This is used to evaluate if NTLM is supported. + * + * Parameters: None + * + * Returns TRUE as NTLM as handled by libcurl. + */ +bool Curl_auth_is_ntlm_supported(void) +{ + return TRUE; +} + +/* + * Curl_auth_decode_ntlm_type2_message() + * + * This is used to decode an already encoded NTLM type-2 message. The message + * is first decoded from a base64 string into a raw NTLM message and checked + * for validity before the appropriate data for creating a type-3 message is + * written to the given NTLM data structure. + * + * Parameters: + * + * data [in] - The session handle. + * type2msg [in] - The base64 encoded type-2 message. + * ntlm [in/out] - The NTLM data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, + const char *type2msg, + struct ntlmdata *ntlm) +{ + static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; + + /* NTLM type-2 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x02000000) + 12 Target Name security buffer + 20 Flags long + 24 Challenge 8 bytes + (32) Context 8 bytes (two consecutive longs) (*) + (40) Target Information security buffer (*) + (48) OS Version Structure 8 bytes (*) + 32 (48) (56) Start of data block (*) + (*) -> Optional + */ + + CURLcode result = CURLE_OK; + unsigned char *type2 = NULL; + size_t type2_len = 0; + +#if defined(NTLM_NEEDS_NSS_INIT) + /* Make sure the crypto backend is initialized */ + result = Curl_nss_force_init(data); + if(result) + return result; +#elif defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)data; +#endif + + /* Decode the base-64 encoded type-2 message */ + if(strlen(type2msg) && *type2msg != '=') { + result = Curl_base64_decode(type2msg, &type2, &type2_len); + if(result) + return result; + } + + /* Ensure we have a valid type-2 message */ + if(!type2) { + infof(data, "NTLM handshake failure (empty type-2 message)\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->flags = 0; + + if((type2_len < 32) || + (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) || + (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) { + /* This was not a good enough type-2 message */ + free(type2); + infof(data, "NTLM handshake failure (bad type-2 message)\n"); + return CURLE_BAD_CONTENT_ENCODING; + } + + ntlm->flags = Curl_read32_le(&type2[20]); + memcpy(ntlm->nonce, &type2[24], 8); + + if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { + result = ntlm_decode_type2_target(data, type2, type2_len, ntlm); + if(result) { + free(type2); + infof(data, "NTLM handshake failure (bad type-2 message)\n"); + return result; + } + } + + DEBUG_OUT({ + fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); + ntlm_print_flags(stderr, ntlm->flags); + fprintf(stderr, "\n nonce="); + ntlm_print_hex(stderr, (char *)ntlm->nonce, 8); + fprintf(stderr, "\n****\n"); + fprintf(stderr, "**** Header %s\n ", header); + }); + + free(type2); + + return result; +} + +/* copy the source to the destination and fill in zeroes in every + other destination byte! */ +static void unicodecpy(unsigned char *dest, const char *src, size_t length) +{ + size_t i; + for(i = 0; i < length; i++) { + dest[2 * i] = (unsigned char)src[i]; + dest[2 * i + 1] = '\0'; + } +} + +/* + * Curl_auth_create_ntlm_type1_message() + * + * This is used to generate an already encoded NTLM type-1 message ready for + * sending to the recipient using the appropriate compile time crypto API. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * ntlm [in/out] - The NTLM data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *hostname, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + /* NTLM type-1 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x01000000) + 12 Flags long + (16) Supplied Domain security buffer (*) + (24) Supplied Workstation security buffer (*) + (32) OS Version Structure 8 bytes (*) + (32) (40) Start of data block (*) + (*) -> Optional + */ + + size_t size; + + unsigned char ntlmbuf[NTLM_BUFSIZE]; + const char *host = ""; /* empty */ + const char *domain = ""; /* empty */ + size_t hostlen = 0; + size_t domlen = 0; + size_t hostoff = 0; + size_t domoff = hostoff + hostlen; /* This is 0: remember that host and + domain are empty */ + (void)userp; + (void)passwdp; + (void)service, + (void)hostname, + + /* Clean up any former leftovers and initialise to defaults */ + Curl_auth_cleanup_ntlm(ntlm); + +#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION) +#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY +#else +#define NTLM2FLAG 0 +#endif + msnprintf((char *)ntlmbuf, NTLM_BUFSIZE, + NTLMSSP_SIGNATURE "%c" + "\x01%c%c%c" /* 32-bit type = 1 */ + "%c%c%c%c" /* 32-bit NTLM flag field */ + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host name offset */ + "%c%c" /* 2 zeroes */ + "%s" /* host name */ + "%s", /* domain string */ + 0, /* trailing zero */ + 0, 0, 0, /* part of type-1 long */ + + LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0, 0, + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0, 0, + host, /* this is empty */ + domain /* this is empty */); + + /* Initial packet length */ + size = 32 + hostlen + domlen; + + DEBUG_OUT({ + fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x " + "0x%08.8x ", + LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), + NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); + ntlm_print_flags(stderr, + NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); + fprintf(stderr, "\n****\n"); + }); + + /* Return with binary blob encoded into base64 */ + return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen); +} + +/* + * Curl_auth_create_ntlm_type3_message() + * + * This is used to generate an already encoded NTLM type-3 message ready for + * sending to the recipient using the appropriate compile time crypto API. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * ntlm [in/out] - The NTLM data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) + +{ + /* NTLM type-3 message structure: + + Index Description Content + 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" + (0x4e544c4d53535000) + 8 NTLM Message Type long (0x03000000) + 12 LM/LMv2 Response security buffer + 20 NTLM/NTLMv2 Response security buffer + 28 Target Name security buffer + 36 User Name security buffer + 44 Workstation Name security buffer + (52) Session Key security buffer (*) + (60) Flags long (*) + (64) OS Version Structure 8 bytes (*) + 52 (64) (72) Start of data block + (*) -> Optional + */ + + CURLcode result = CURLE_OK; + size_t size; + unsigned char ntlmbuf[NTLM_BUFSIZE]; + int lmrespoff; + unsigned char lmresp[24]; /* fixed-size */ +#ifdef USE_NTRESPONSES + int ntrespoff; + unsigned int ntresplen = 24; + unsigned char ntresp[24]; /* fixed-size */ + unsigned char *ptr_ntresp = &ntresp[0]; + unsigned char *ntlmv2resp = NULL; +#endif + bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE; + char host[HOSTNAME_MAX + 1] = ""; + const char *user; + const char *domain = ""; + size_t hostoff = 0; + size_t useroff = 0; + size_t domoff = 0; + size_t hostlen = 0; + size_t userlen = 0; + size_t domlen = 0; + + user = strchr(userp, '\\'); + if(!user) + user = strchr(userp, '/'); + + if(user) { + domain = userp; + domlen = (user - domain); + user++; + } + else + user = userp; + + userlen = strlen(user); + + /* Get the machine's un-qualified host name as NTLM doesn't like the fully + qualified domain name */ + if(Curl_gethostname(host, sizeof(host))) { + infof(data, "gethostname() failed, continuing without!\n"); + hostlen = 0; + } + else { + hostlen = strlen(host); + } + +#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2) + if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { + unsigned char ntbuffer[0x18]; + unsigned char entropy[8]; + unsigned char ntlmv2hash[0x18]; + + result = Curl_rand(data, entropy, 8); + if(result) + return result; + + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen, + ntbuffer, ntlmv2hash); + if(result) + return result; + + /* LMv2 response */ + result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy, + &ntlm->nonce[0], lmresp); + if(result) + return result; + + /* NTLMv2 response */ + result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy, + ntlm, &ntlmv2resp, &ntresplen); + if(result) + return result; + + ptr_ntresp = ntlmv2resp; + } + else +#endif + +#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION) + /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ + if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) { + unsigned char ntbuffer[0x18]; + unsigned char tmp[0x18]; + unsigned char md5sum[MD5_DIGEST_LENGTH]; + unsigned char entropy[8]; + + /* Need to create 8 bytes random data */ + result = Curl_rand(data, entropy, 8); + if(result) + return result; + + /* 8 bytes random data as challenge in lmresp */ + memcpy(lmresp, entropy, 8); + + /* Pad with zeros */ + memset(lmresp + 8, 0, 0x10); + + /* Fill tmp with challenge(nonce?) + entropy */ + memcpy(tmp, &ntlm->nonce[0], 8); + memcpy(tmp + 8, entropy, 8); + + result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH); + if(!result) + /* We shall only use the first 8 bytes of md5sum, but the des code in + Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp); + + /* End of NTLM2 Session code */ + /* NTLM v2 session security is a misnomer because it is not NTLM v2. + It is NTLM v1 using the extended session security that is also + in NTLM v2 */ + } + else +#endif + { + +#ifdef USE_NTRESPONSES + unsigned char ntbuffer[0x18]; +#endif + unsigned char lmbuffer[0x18]; + +#ifdef USE_NTRESPONSES + result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp); +#endif + + result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer); + if(result) + return result; + + Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp); + + /* A safer but less compatible alternative is: + * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); + * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */ + } + + if(unicode) { + domlen = domlen * 2; + userlen = userlen * 2; + hostlen = hostlen * 2; + } + + lmrespoff = 64; /* size of the message header */ +#ifdef USE_NTRESPONSES + ntrespoff = lmrespoff + 0x18; + domoff = ntrespoff + ntresplen; +#else + domoff = lmrespoff + 0x18; +#endif + useroff = domoff + domlen; + hostoff = useroff + userlen; + + /* Create the big type-3 message binary blob */ + size = msnprintf((char *)ntlmbuf, NTLM_BUFSIZE, + NTLMSSP_SIGNATURE "%c" + "\x03%c%c%c" /* 32-bit type = 3 */ + + "%c%c" /* LanManager length */ + "%c%c" /* LanManager allocated space */ + "%c%c" /* LanManager offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* NT-response length */ + "%c%c" /* NT-response allocated space */ + "%c%c" /* NT-response offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* user length */ + "%c%c" /* user allocated space */ + "%c%c" /* user offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* session key length (unknown purpose) */ + "%c%c" /* session key allocated space (unknown purpose) */ + "%c%c" /* session key offset (unknown purpose) */ + "%c%c" /* 2 zeroes */ + + "%c%c%c%c", /* flags */ + + /* domain string */ + /* user string */ + /* host string */ + /* LanManager response */ + /* NT response */ + + 0, /* zero termination */ + 0, 0, 0, /* type-3 long, the 24 upper bits */ + + SHORTPAIR(0x18), /* LanManager response length, twice */ + SHORTPAIR(0x18), + SHORTPAIR(lmrespoff), + 0x0, 0x0, + +#ifdef USE_NTRESPONSES + SHORTPAIR(ntresplen), /* NT-response length, twice */ + SHORTPAIR(ntresplen), + SHORTPAIR(ntrespoff), + 0x0, 0x0, +#else + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, +#endif + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0x0, 0x0, + + SHORTPAIR(userlen), + SHORTPAIR(userlen), + SHORTPAIR(useroff), + 0x0, 0x0, + + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0x0, 0x0, + + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, + + LONGQUARTET(ntlm->flags)); + + DEBUGASSERT(size == 64); + DEBUGASSERT(size == (size_t)lmrespoff); + + /* We append the binary hashes */ + if(size < (NTLM_BUFSIZE - 0x18)) { + memcpy(&ntlmbuf[size], lmresp, 0x18); + size += 0x18; + } + + DEBUG_OUT({ + fprintf(stderr, "**** TYPE3 header lmresp="); + ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18); + }); + +#ifdef USE_NTRESPONSES + /* ntresplen + size should not be risking an integer overflow here */ + if(ntresplen + size > sizeof(ntlmbuf)) { + failf(data, "incoming NTLM message too big"); + return CURLE_OUT_OF_MEMORY; + } + DEBUGASSERT(size == (size_t)ntrespoff); + memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); + size += ntresplen; + + DEBUG_OUT({ + fprintf(stderr, "\n ntresp="); + ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen); + }); + + free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ + +#endif + + DEBUG_OUT({ + fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", + LONGQUARTET(ntlm->flags), ntlm->flags); + ntlm_print_flags(stderr, ntlm->flags); + fprintf(stderr, "\n****\n"); + }); + + /* Make sure that the domain, user and host strings fit in the + buffer before we copy them there. */ + if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) { + failf(data, "user + domain + host name too big"); + return CURLE_OUT_OF_MEMORY; + } + + DEBUGASSERT(size == domoff); + if(unicode) + unicodecpy(&ntlmbuf[size], domain, domlen / 2); + else + memcpy(&ntlmbuf[size], domain, domlen); + + size += domlen; + + DEBUGASSERT(size == useroff); + if(unicode) + unicodecpy(&ntlmbuf[size], user, userlen / 2); + else + memcpy(&ntlmbuf[size], user, userlen); + + size += userlen; + + DEBUGASSERT(size == hostoff); + if(unicode) + unicodecpy(&ntlmbuf[size], host, hostlen / 2); + else + memcpy(&ntlmbuf[size], host, hostlen); + + size += hostlen; + + /* Convert domain, user, and host to ASCII but leave the rest as-is */ + result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff], + size - domoff); + if(result) + return CURLE_CONV_FAILED; + + /* Return with binary blob encoded into base64 */ + result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen); + + Curl_auth_cleanup_ntlm(ntlm); + + return result; +} + +/* + * Curl_auth_cleanup_ntlm() + * + * This is used to clean up the NTLM specific data. + * + * Parameters: + * + * ntlm [in/out] - The NTLM data struct being cleaned up. + * + */ +void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm) +{ + /* Free the target info */ + Curl_safefree(ntlm->target_info); + + /* Reset any variables */ + ntlm->target_info_len = 0; +} + +#endif /* USE_NTLM && !USE_WINDOWS_SSPI */ diff --git a/libcurl/lib/vauth/ntlm.h b/libcurl/lib/vauth/ntlm.h new file mode 100644 index 0000000..1136b0f --- /dev/null +++ b/libcurl/lib/vauth/ntlm.h @@ -0,0 +1,143 @@ +#ifndef HEADER_VAUTH_NTLM_H +#define HEADER_VAUTH_NTLM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NTLM + +/* NTLM buffer fixed size, large enough for long user + host + domain */ +#define NTLM_BUFSIZE 1024 + +/* Stuff only required for curl_ntlm_msgs.c */ +#ifdef BUILDING_CURL_NTLM_MSGS_C + +/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */ + +#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) +/* Indicates that Unicode strings are supported for use in security buffer + data. */ + +#define NTLMFLAG_NEGOTIATE_OEM (1<<1) +/* Indicates that OEM strings are supported for use in security buffer data. */ + +#define NTLMFLAG_REQUEST_TARGET (1<<2) +/* Requests that the server's authentication realm be included in the Type 2 + message. */ + +/* unknown (1<<3) */ +#define NTLMFLAG_NEGOTIATE_SIGN (1<<4) +/* Specifies that authenticated communication between the client and server + should carry a digital signature (message integrity). */ + +#define NTLMFLAG_NEGOTIATE_SEAL (1<<5) +/* Specifies that authenticated communication between the client and server + should be encrypted (message confidentiality). */ + +#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6) +/* Indicates that datagram authentication is being used. */ + +#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7) +/* Indicates that the LAN Manager session key should be used for signing and + sealing authenticated communications. */ + +#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) +/* Indicates that NTLM authentication is being used. */ + +/* unknown (1<<10) */ + +#define NTLMFLAG_NEGOTIATE_ANONYMOUS (1<<11) +/* Sent by the client in the Type 3 message to indicate that an anonymous + context has been established. This also affects the response fields. */ + +#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12) +/* Sent by the client in the Type 1 message to indicate that a desired + authentication realm is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13) +/* Sent by the client in the Type 1 message to indicate that the client + workstation's name is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14) +/* Sent by the server to indicate that the server and client are on the same + machine. Implies that the client may use a pre-established local security + context rather than responding to the challenge. */ + +#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15) +/* Indicates that authenticated communication between the client and server + should be signed with a "dummy" signature. */ + +#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a domain. */ + +#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a server. */ + +#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a share. Presumably, this is for share-level + authentication. Usage is unclear. */ + +#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19) +/* Indicates that the NTLM2 signing and sealing scheme should be used for + protecting authenticated communications. */ + +#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23) +/* Sent by the server in the Type 2 message to indicate that it is including a + Target Information block in the message. */ + +/* unknown (1<24) */ +/* unknown (1<25) */ +/* unknown (1<26) */ +/* unknown (1<27) */ +/* unknown (1<28) */ + +#define NTLMFLAG_NEGOTIATE_128 (1<<29) +/* Indicates that 128-bit encryption is supported. */ + +#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30) +/* Indicates that the client will provide an encrypted master key in + the "Session Key" field of the Type 3 message. */ + +#define NTLMFLAG_NEGOTIATE_56 (1<<31) +/* Indicates that 56-bit encryption is supported. */ + +#endif /* BUILDING_CURL_NTLM_MSGS_C */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_VAUTH_NTLM_H */ diff --git a/libcurl/lib/vauth/ntlm_sspi.c b/libcurl/lib/vauth/ntlm_sspi.c new file mode 100644 index 0000000..589cca1 --- /dev/null +++ b/libcurl/lib/vauth/ntlm_sspi.c @@ -0,0 +1,371 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && defined(USE_NTLM) + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_ntlm_core.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_ntlm_supported() + * + * This is used to evaluate if NTLM is supported. + * + * Parameters: None + * + * Returns TRUE if NTLM is supported by Windows SSPI. + */ +bool Curl_auth_is_ntlm_supported(void) +{ + PSecPkgInfo SecurityPackage; + SECURITY_STATUS status; + + /* Query the security package for NTLM */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM), + &SecurityPackage); + + return (status == SEC_E_OK ? TRUE : FALSE); +} + +/* + * Curl_auth_create_ntlm_type1_message() + * + * This is used to generate an already encoded NTLM type-1 message ready for + * sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * ntlm [in/out] - The NTLM data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + PSecPkgInfo SecurityPackage; + SecBuffer type_1_buf; + SecBufferDesc type_1_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + /* Clean up any former leftovers and initialise to defaults */ + Curl_auth_cleanup_ntlm(ntlm); + + /* Query the security package for NTLM */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM), + &SecurityPackage); + if(status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + ntlm->token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our output buffer */ + ntlm->output_token = malloc(ntlm->token_max); + if(!ntlm->output_token) + return CURLE_OUT_OF_MEMORY; + + if(userp && *userp) { + CURLcode result; + + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &ntlm->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ + ntlm->p_identity = &ntlm->identity; + } + else + /* Use the current Windows user */ + ntlm->p_identity = NULL; + + /* Allocate our credentials handle */ + ntlm->credentials = calloc(1, sizeof(CredHandle)); + if(!ntlm->credentials) + return CURLE_OUT_OF_MEMORY; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_NTLM), + SECPKG_CRED_OUTBOUND, NULL, + ntlm->p_identity, NULL, NULL, + ntlm->credentials, &expiry); + if(status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + + /* Allocate our new context handle */ + ntlm->context = calloc(1, sizeof(CtxtHandle)); + if(!ntlm->context) + return CURLE_OUT_OF_MEMORY; + + ntlm->spn = Curl_auth_build_spn(service, host, NULL); + if(!ntlm->spn) + return CURLE_OUT_OF_MEMORY; + + /* Setup the type-1 "output" security buffer */ + type_1_desc.ulVersion = SECBUFFER_VERSION; + type_1_desc.cBuffers = 1; + type_1_desc.pBuffers = &type_1_buf; + type_1_buf.BufferType = SECBUFFER_TOKEN; + type_1_buf.pvBuffer = ntlm->output_token; + type_1_buf.cbBuffer = curlx_uztoul(ntlm->token_max); + + /* Generate our type-1 message */ + status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL, + ntlm->spn, + 0, 0, SECURITY_NETWORK_DREP, + NULL, 0, + ntlm->context, &type_1_desc, + &attrs, &expiry); + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(ntlm->context, &type_1_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) + return CURLE_RECV_ERROR; + + /* Base64 encode the response */ + return Curl_base64_encode(data, (char *) ntlm->output_token, + type_1_buf.cbBuffer, outptr, outlen); +} + +/* + * Curl_auth_decode_ntlm_type2_message() + * + * This is used to decode an already encoded NTLM type-2 message. + * + * Parameters: + * + * data [in] - The session handle. + * type2msg [in] - The base64 encoded type-2 message. + * ntlm [in/out] - The NTLM data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, + const char *type2msg, + struct ntlmdata *ntlm) +{ + CURLcode result = CURLE_OK; + unsigned char *type2 = NULL; + size_t type2_len = 0; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + /* Decode the base-64 encoded type-2 message */ + if(strlen(type2msg) && *type2msg != '=') { + result = Curl_base64_decode(type2msg, &type2, &type2_len); + if(result) + return result; + } + + /* Ensure we have a valid type-2 message */ + if(!type2) { + infof(data, "NTLM handshake failure (empty type-2 message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Simply store the challenge for use later */ + ntlm->input_token = type2; + ntlm->input_token_len = type2_len; + + return result; +} + +/* +* Curl_auth_create_ntlm_type3_message() + * Curl_auth_create_ntlm_type3_message() + * + * This is used to generate an already encoded NTLM type-3 message ready for + * sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * ntlm [in/out] - The NTLM data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + SecBuffer type_2_bufs[2]; + SecBuffer type_3_buf; + SecBufferDesc type_2_desc; + SecBufferDesc type_3_desc; + SECURITY_STATUS status; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + + (void) passwdp; + (void) userp; + + /* Setup the type-2 "input" security buffer */ + type_2_desc.ulVersion = SECBUFFER_VERSION; + type_2_desc.cBuffers = 1; + type_2_desc.pBuffers = &type_2_bufs[0]; + type_2_bufs[0].BufferType = SECBUFFER_TOKEN; + type_2_bufs[0].pvBuffer = ntlm->input_token; + type_2_bufs[0].cbBuffer = curlx_uztoul(ntlm->input_token_len); + +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + /* ssl context comes from schannel. + * When extended protection is used in IIS server, + * we have to pass a second SecBuffer to the SecBufferDesc + * otherwise IIS will not pass the authentication (401 response). + * Minimum supported version is Windows 7. + * https://docs.microsoft.com/en-us/security-updates + * /SecurityAdvisories/2009/973811 + */ + if(ntlm->sslContext) { + SEC_CHANNEL_BINDINGS channelBindings; + SecPkgContext_Bindings pkgBindings; + pkgBindings.Bindings = &channelBindings; + status = s_pSecFn->QueryContextAttributes( + ntlm->sslContext, + SECPKG_ATTR_ENDPOINT_BINDINGS, + &pkgBindings + ); + if(status == SEC_E_OK) { + type_2_desc.cBuffers++; + type_2_bufs[1].BufferType = SECBUFFER_CHANNEL_BINDINGS; + type_2_bufs[1].cbBuffer = pkgBindings.BindingsLength; + type_2_bufs[1].pvBuffer = pkgBindings.Bindings; + } + } +#endif + + /* Setup the type-3 "output" security buffer */ + type_3_desc.ulVersion = SECBUFFER_VERSION; + type_3_desc.cBuffers = 1; + type_3_desc.pBuffers = &type_3_buf; + type_3_buf.BufferType = SECBUFFER_TOKEN; + type_3_buf.pvBuffer = ntlm->output_token; + type_3_buf.cbBuffer = curlx_uztoul(ntlm->token_max); + + /* Generate our type-3 message */ + status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, + ntlm->context, + ntlm->spn, + 0, 0, SECURITY_NETWORK_DREP, + &type_2_desc, + 0, ntlm->context, + &type_3_desc, + &attrs, &expiry); + if(status != SEC_E_OK) { + infof(data, "NTLM handshake failure (type-3 message): Status=%x\n", + status); + + return CURLE_RECV_ERROR; + } + + /* Base64 encode the response */ + result = Curl_base64_encode(data, (char *) ntlm->output_token, + type_3_buf.cbBuffer, outptr, outlen); + + Curl_auth_cleanup_ntlm(ntlm); + + return result; +} + +/* + * Curl_auth_cleanup_ntlm() + * + * This is used to clean up the NTLM specific data. + * + * Parameters: + * + * ntlm [in/out] - The NTLM data struct being cleaned up. + * + */ +void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm) +{ + /* Free our security context */ + if(ntlm->context) { + s_pSecFn->DeleteSecurityContext(ntlm->context); + free(ntlm->context); + ntlm->context = NULL; + } + + /* Free our credentials handle */ + if(ntlm->credentials) { + s_pSecFn->FreeCredentialsHandle(ntlm->credentials); + free(ntlm->credentials); + ntlm->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(ntlm->p_identity); + ntlm->p_identity = NULL; + + /* Free the input and output tokens */ + Curl_safefree(ntlm->input_token); + Curl_safefree(ntlm->output_token); + + /* Reset any variables */ + ntlm->token_max = 0; + + Curl_safefree(ntlm->spn); +} + +#endif /* USE_WINDOWS_SSPI && USE_NTLM */ diff --git a/libcurl/lib/vauth/oauth2.c b/libcurl/lib/vauth/oauth2.c new file mode 100644 index 0000000..b4e9f8e --- /dev/null +++ b/libcurl/lib/vauth/oauth2.c @@ -0,0 +1,126 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC6749 OAuth 2.0 Authorization Framework + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_POP3) + +#include +#include "urldata.h" + +#include "vauth/vauth.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_create_oauth_bearer_message() + * + * This is used to generate an already encoded OAuth 2.0 message ready for + * sending to the recipient. + * + * Parameters: + * + * data[in] - The session handle. + * user[in] - The user name. + * host[in] - The host name. + * port[in] - The port(when not Port 80). + * bearer[in] - The bearer token. + * outptr[in / out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen[out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *host, + const long port, + const char *bearer, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + char *oauth = NULL; + + /* Generate the message */ + if(port == 0 || port == 80) + oauth = aprintf("n,a=%s,\1host=%s\1auth=Bearer %s\1\1", user, host, + bearer); + else + oauth = aprintf("n,a=%s,\1host=%s\1port=%ld\1auth=Bearer %s\1\1", user, + host, port, bearer); + if(!oauth) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the reply */ + result = Curl_base64_encode(data, oauth, strlen(oauth), outptr, outlen); + + free(oauth); + + return result; +} + +/* + * Curl_auth_create_xoauth_bearer_message() + * + * This is used to generate an already encoded XOAuth 2.0 message ready for + * sending to the recipient. + * + * Parameters: + * + * data[in] - The session handle. + * user[in] - The user name. + * bearer[in] - The bearer token. + * outptr[in / out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen[out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *bearer, + char **outptr, size_t *outlen) +{ + CURLcode result = CURLE_OK; + + /* Generate the message */ + char *xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer); + if(!xoauth) + return CURLE_OUT_OF_MEMORY; + + /* Base64 encode the reply */ + result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen); + + free(xoauth); + + return result; +} +#endif /* disabled, no users */ + diff --git a/libcurl/lib/vauth/spnego_gssapi.c b/libcurl/lib/vauth/spnego_gssapi.c new file mode 100644 index 0000000..5d43e11 --- /dev/null +++ b/libcurl/lib/vauth/spnego_gssapi.c @@ -0,0 +1,282 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4178 Simple and Protected GSS-API Negotiation Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_GSSAPI) && defined(USE_SPNEGO) + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "curl_base64.h" +#include "curl_gssapi.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_spnego_supported() + * + * This is used to evaluate if SPNEGO (Negotiate) is supported. + * + * Parameters: None + * + * Returns TRUE if Negotiate supported by the GSS-API library. + */ +bool Curl_auth_is_spnego_supported(void) +{ + return TRUE; +} + +/* + * Curl_auth_decode_spnego_message() + * + * This is used to decode an already encoded SPNEGO (Negotiate) challenge + * message. + * + * Parameters: + * + * data [in] - The session handle. + * userp [in] - The user name in the format User or Domain\User. + * passwdp [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * chlg64 [in] - The optional base64 encoded challenge message. + * nego [in/out] - The Negotiate data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, + const char *user, + const char *password, + const char *service, + const char *host, + const char *chlg64, + struct negotiatedata *nego) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + unsigned char *chlg = NULL; + OM_uint32 major_status; + OM_uint32 minor_status; + OM_uint32 unused_status; + gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + + (void) user; + (void) password; + + if(nego->context && nego->status == GSS_S_COMPLETE) { + /* We finished successfully our part of authentication, but server + * rejected it (since we're again here). Exit with an error since we + * can't invent anything better */ + Curl_auth_cleanup_spnego(nego); + return CURLE_LOGIN_DENIED; + } + + if(!nego->spn) { + /* Generate our SPN */ + char *spn = Curl_auth_build_spn(service, NULL, host); + if(!spn) + return CURLE_OUT_OF_MEMORY; + + /* Populate the SPN structure */ + spn_token.value = spn; + spn_token.length = strlen(spn); + + /* Import the SPN */ + major_status = gss_import_name(&minor_status, &spn_token, + GSS_C_NT_HOSTBASED_SERVICE, + &nego->spn); + if(GSS_ERROR(major_status)) { + Curl_gss_log_error(data, "gss_import_name() failed: ", + major_status, minor_status); + + free(spn); + + return CURLE_OUT_OF_MEMORY; + } + + free(spn); + } + + if(chlg64 && *chlg64) { + /* Decode the base-64 encoded challenge message */ + if(*chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "SPNEGO handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + input_token.value = chlg; + input_token.length = chlglen; + } + + /* Generate our challenge-response message */ + major_status = Curl_gss_init_sec_context(data, + &minor_status, + &nego->context, + nego->spn, + &Curl_spnego_mech_oid, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + &output_token, + TRUE, + NULL); + + /* Free the decoded challenge as it is not required anymore */ + Curl_safefree(input_token.value); + + nego->status = major_status; + if(GSS_ERROR(major_status)) { + if(output_token.value) + gss_release_buffer(&unused_status, &output_token); + + Curl_gss_log_error(data, "gss_init_sec_context() failed: ", + major_status, minor_status); + + return CURLE_LOGIN_DENIED; + } + + if(!output_token.value || !output_token.length) { + if(output_token.value) + gss_release_buffer(&unused_status, &output_token); + + return CURLE_OUT_OF_MEMORY; + } + + /* Free previous token */ + if(nego->output_token.length && nego->output_token.value) + gss_release_buffer(&unused_status, &nego->output_token); + + nego->output_token = output_token; + + return CURLE_OK; +} + +/* + * Curl_auth_create_spnego_message() + * + * This is used to generate an already encoded SPNEGO (Negotiate) response + * message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * nego [in/out] - The Negotiate data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, + struct negotiatedata *nego, + char **outptr, size_t *outlen) +{ + CURLcode result; + OM_uint32 minor_status; + + /* Base64 encode the already generated response */ + result = Curl_base64_encode(data, + nego->output_token.value, + nego->output_token.length, + outptr, outlen); + + if(result) { + gss_release_buffer(&minor_status, &nego->output_token); + nego->output_token.value = NULL; + nego->output_token.length = 0; + + return result; + } + + if(!*outptr || !*outlen) { + gss_release_buffer(&minor_status, &nego->output_token); + nego->output_token.value = NULL; + nego->output_token.length = 0; + + return CURLE_REMOTE_ACCESS_DENIED; + } + + return CURLE_OK; +} + +/* + * Curl_auth_cleanup_spnego() + * + * This is used to clean up the SPNEGO (Negotiate) specific data. + * + * Parameters: + * + * nego [in/out] - The Negotiate data struct being cleaned up. + * + */ +void Curl_auth_cleanup_spnego(struct negotiatedata *nego) +{ + OM_uint32 minor_status; + + /* Free our security context */ + if(nego->context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&minor_status, &nego->context, GSS_C_NO_BUFFER); + nego->context = GSS_C_NO_CONTEXT; + } + + /* Free the output token */ + if(nego->output_token.value) { + gss_release_buffer(&minor_status, &nego->output_token); + nego->output_token.value = NULL; + nego->output_token.length = 0; + + } + + /* Free the SPN */ + if(nego->spn != GSS_C_NO_NAME) { + gss_release_name(&minor_status, &nego->spn); + nego->spn = GSS_C_NO_NAME; + } + + /* Reset any variables */ + nego->status = 0; + nego->noauthpersist = FALSE; + nego->havenoauthpersist = FALSE; + nego->havenegdata = FALSE; + nego->havemultiplerequests = FALSE; +} + +#endif /* HAVE_GSSAPI && USE_SPNEGO */ diff --git a/libcurl/lib/vauth/spnego_sspi.c b/libcurl/lib/vauth/spnego_sspi.c new file mode 100644 index 0000000..4b21cc7 --- /dev/null +++ b/libcurl/lib/vauth/spnego_sspi.c @@ -0,0 +1,352 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * RFC4178 Simple and Protected GSS-API Negotiation Mechanism + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_WINDOWS_SSPI) && defined(USE_SPNEGO) + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "curl_base64.h" +#include "warnless.h" +#include "curl_multibyte.h" +#include "sendf.h" +#include "strerror.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_is_spnego_supported() + * + * This is used to evaluate if SPNEGO (Negotiate) is supported. + * + * Parameters: None + * + * Returns TRUE if Negotiate is supported by Windows SSPI. + */ +bool Curl_auth_is_spnego_supported(void) +{ + PSecPkgInfo SecurityPackage; + SECURITY_STATUS status; + + /* Query the security package for Negotiate */ + status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_NEGOTIATE), + &SecurityPackage); + + return (status == SEC_E_OK ? TRUE : FALSE); +} + +/* + * Curl_auth_decode_spnego_message() + * + * This is used to decode an already encoded SPNEGO (Negotiate) challenge + * message. + * + * Parameters: + * + * data [in] - The session handle. + * user [in] - The user name in the format User or Domain\User. + * password [in] - The user's password. + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * chlg64 [in] - The optional base64 encoded challenge message. + * nego [in/out] - The Negotiate data struct being used and modified. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, + const char *user, + const char *password, + const char *service, + const char *host, + const char *chlg64, + struct negotiatedata *nego) +{ + CURLcode result = CURLE_OK; + size_t chlglen = 0; + unsigned char *chlg = NULL; + PSecPkgInfo SecurityPackage; + SecBuffer chlg_buf[2]; + SecBuffer resp_buf; + SecBufferDesc chlg_desc; + SecBufferDesc resp_desc; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + + if(nego->context && nego->status == SEC_E_OK) { + /* We finished successfully our part of authentication, but server + * rejected it (since we're again here). Exit with an error since we + * can't invent anything better */ + Curl_auth_cleanup_spnego(nego); + return CURLE_LOGIN_DENIED; + } + + if(!nego->spn) { + /* Generate our SPN */ + nego->spn = Curl_auth_build_spn(service, host, NULL); + if(!nego->spn) + return CURLE_OUT_OF_MEMORY; + } + + if(!nego->output_token) { + /* Query the security package for Negotiate */ + nego->status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) + TEXT(SP_NAME_NEGOTIATE), + &SecurityPackage); + if(nego->status != SEC_E_OK) + return CURLE_NOT_BUILT_IN; + + nego->token_max = SecurityPackage->cbMaxToken; + + /* Release the package buffer as it is not required anymore */ + s_pSecFn->FreeContextBuffer(SecurityPackage); + + /* Allocate our output buffer */ + nego->output_token = malloc(nego->token_max); + if(!nego->output_token) + return CURLE_OUT_OF_MEMORY; + } + + if(!nego->credentials) { + /* Do we have credentials to use or are we using single sign-on? */ + if(user && *user) { + /* Populate our identity structure */ + result = Curl_create_sspi_identity(user, password, &nego->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ + nego->p_identity = &nego->identity; + } + else + /* Use the current Windows user */ + nego->p_identity = NULL; + + /* Allocate our credentials handle */ + nego->credentials = calloc(1, sizeof(CredHandle)); + if(!nego->credentials) + return CURLE_OUT_OF_MEMORY; + + /* Acquire our credentials handle */ + nego->status = + s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *)TEXT(SP_NAME_NEGOTIATE), + SECPKG_CRED_OUTBOUND, NULL, + nego->p_identity, NULL, NULL, + nego->credentials, &expiry); + if(nego->status != SEC_E_OK) + return CURLE_LOGIN_DENIED; + + /* Allocate our new context handle */ + nego->context = calloc(1, sizeof(CtxtHandle)); + if(!nego->context) + return CURLE_OUT_OF_MEMORY; + } + + if(chlg64 && *chlg64) { + /* Decode the base-64 encoded challenge message */ + if(*chlg64 != '=') { + result = Curl_base64_decode(chlg64, &chlg, &chlglen); + if(result) + return result; + } + + /* Ensure we have a valid challenge message */ + if(!chlg) { + infof(data, "SPNEGO handshake failure (empty challenge message)\n"); + + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Setup the challenge "input" security buffer */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 1; + chlg_desc.pBuffers = &chlg_buf[0]; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = chlg; + chlg_buf[0].cbBuffer = curlx_uztoul(chlglen); + +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + /* ssl context comes from Schannel. + * When extended protection is used in IIS server, + * we have to pass a second SecBuffer to the SecBufferDesc + * otherwise IIS will not pass the authentication (401 response). + * Minimum supported version is Windows 7. + * https://docs.microsoft.com/en-us/security-updates + * /SecurityAdvisories/2009/973811 + */ + if(nego->sslContext) { + SEC_CHANNEL_BINDINGS channelBindings; + SecPkgContext_Bindings pkgBindings; + pkgBindings.Bindings = &channelBindings; + nego->status = s_pSecFn->QueryContextAttributes( + nego->sslContext, + SECPKG_ATTR_ENDPOINT_BINDINGS, + &pkgBindings + ); + if(nego->status == SEC_E_OK) { + chlg_desc.cBuffers++; + chlg_buf[1].BufferType = SECBUFFER_CHANNEL_BINDINGS; + chlg_buf[1].cbBuffer = pkgBindings.BindingsLength; + chlg_buf[1].pvBuffer = pkgBindings.Bindings; + } + } +#endif + } + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = nego->output_token; + resp_buf.cbBuffer = curlx_uztoul(nego->token_max); + + /* Generate our challenge-response message */ + nego->status = s_pSecFn->InitializeSecurityContext(nego->credentials, + chlg ? nego->context : + NULL, + nego->spn, + ISC_REQ_CONFIDENTIALITY, + 0, SECURITY_NATIVE_DREP, + chlg ? &chlg_desc : NULL, + 0, nego->context, + &resp_desc, &attrs, + &expiry); + + /* Free the decoded challenge as it is not required anymore */ + free(chlg); + + if(GSS_ERROR(nego->status)) { + char buffer[STRERROR_LEN]; + failf(data, "InitializeSecurityContext failed: %s", + Curl_sspi_strerror(nego->status, buffer, sizeof(buffer))); + return CURLE_OUT_OF_MEMORY; + } + + if(nego->status == SEC_I_COMPLETE_NEEDED || + nego->status == SEC_I_COMPLETE_AND_CONTINUE) { + nego->status = s_pSecFn->CompleteAuthToken(nego->context, &resp_desc); + if(GSS_ERROR(nego->status)) { + return CURLE_RECV_ERROR; + } + } + + nego->output_token_length = resp_buf.cbBuffer; + + return result; +} + +/* + * Curl_auth_create_spnego_message() + * + * This is used to generate an already encoded SPNEGO (Negotiate) response + * message ready for sending to the recipient. + * + * Parameters: + * + * data [in] - The session handle. + * nego [in/out] - The Negotiate data struct being used and modified. + * outptr [in/out] - The address where a pointer to newly allocated memory + * holding the result will be stored upon completion. + * outlen [out] - The length of the output message. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, + struct negotiatedata *nego, + char **outptr, size_t *outlen) +{ + CURLcode result; + + /* Base64 encode the already generated response */ + result = Curl_base64_encode(data, + (const char *) nego->output_token, + nego->output_token_length, + outptr, outlen); + + if(result) + return result; + + if(!*outptr || !*outlen) { + free(*outptr); + return CURLE_REMOTE_ACCESS_DENIED; + } + + return CURLE_OK; +} + +/* + * Curl_auth_cleanup_spnego() + * + * This is used to clean up the SPNEGO (Negotiate) specific data. + * + * Parameters: + * + * nego [in/out] - The Negotiate data struct being cleaned up. + * + */ +void Curl_auth_cleanup_spnego(struct negotiatedata *nego) +{ + /* Free our security context */ + if(nego->context) { + s_pSecFn->DeleteSecurityContext(nego->context); + free(nego->context); + nego->context = NULL; + } + + /* Free our credentials handle */ + if(nego->credentials) { + s_pSecFn->FreeCredentialsHandle(nego->credentials); + free(nego->credentials); + nego->credentials = NULL; + } + + /* Free our identity */ + Curl_sspi_free_identity(nego->p_identity); + nego->p_identity = NULL; + + /* Free the SPN and output token */ + Curl_safefree(nego->spn); + Curl_safefree(nego->output_token); + + /* Reset any variables */ + nego->status = 0; + nego->token_max = 0; + nego->noauthpersist = FALSE; + nego->havenoauthpersist = FALSE; + nego->havenegdata = FALSE; + nego->havemultiplerequests = FALSE; +} + +#endif /* USE_WINDOWS_SSPI && USE_SPNEGO */ diff --git a/libcurl/lib/vauth/vauth.c b/libcurl/lib/vauth/vauth.c new file mode 100644 index 0000000..a9c5c9c --- /dev/null +++ b/libcurl/lib/vauth/vauth.c @@ -0,0 +1,147 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2019, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "vauth.h" +#include "curl_multibyte.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Curl_auth_build_spn() + * + * This is used to build a SPN string in the following formats: + * + * service/host@realm (Not currently used) + * service/host (Not used by GSS-API) + * service@realm (Not used by Windows SSPI) + * + * Parameters: + * + * service [in] - The service type such as http, smtp, pop or imap. + * host [in] - The host name. + * realm [in] - The realm. + * + * Returns a pointer to the newly allocated SPN. + */ +#if !defined(USE_WINDOWS_SSPI) +char *Curl_auth_build_spn(const char *service, const char *host, + const char *realm) +{ + char *spn = NULL; + + /* Generate our SPN */ + if(host && realm) + spn = aprintf("%s/%s@%s", service, host, realm); + else if(host) + spn = aprintf("%s/%s", service, host); + else if(realm) + spn = aprintf("%s@%s", service, realm); + + /* Return our newly allocated SPN */ + return spn; +} +#else +TCHAR *Curl_auth_build_spn(const char *service, const char *host, + const char *realm) +{ + char *utf8_spn = NULL; + TCHAR *tchar_spn = NULL; + + (void) realm; + + /* Note: We could use DsMakeSPN() or DsClientMakeSpnForTargetServer() rather + than doing this ourselves but the first is only available in Windows XP + and Windows Server 2003 and the latter is only available in Windows 2000 + but not Windows95/98/ME or Windows NT4.0 unless the Active Directory + Client Extensions are installed. As such it is far simpler for us to + formulate the SPN instead. */ + + /* Generate our UTF8 based SPN */ + utf8_spn = aprintf("%s/%s", service, host); + if(!utf8_spn) { + return NULL; + } + + /* Allocate our TCHAR based SPN */ + tchar_spn = Curl_convert_UTF8_to_tchar(utf8_spn); + if(!tchar_spn) { + free(utf8_spn); + + return NULL; + } + + /* Release the UTF8 variant when operating with Unicode */ + Curl_unicodefree(utf8_spn); + + /* Return our newly allocated SPN */ + return tchar_spn; +} +#endif /* USE_WINDOWS_SSPI */ + +/* + * Curl_auth_user_contains_domain() + * + * This is used to test if the specified user contains a Windows domain name as + * follows: + * + * Domain\User (Down-level Logon Name) + * Domain/User (curl Down-level format - for compatibility with existing code) + * User@Domain (User Principal Name) + * + * Note: The user name may be empty when using a GSS-API library or Windows + * SSPI as the user and domain are either obtained from the credentials cache + * when using GSS-API or via the currently logged in user's credentials when + * using Windows SSPI. + * + * Parameters: + * + * user [in] - The user name. + * + * Returns TRUE on success; otherwise FALSE. + */ +bool Curl_auth_user_contains_domain(const char *user) +{ + bool valid = FALSE; + + if(user && *user) { + /* Check we have a domain name or UPN present */ + char *p = strpbrk(user, "\\/@"); + + valid = (p != NULL && p > user && p < user + strlen(user) - 1 ? TRUE : + FALSE); + } +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + else + /* User and domain are obtained from the GSS-API credentials cache or the + currently logged in user from Windows */ + valid = TRUE; +#endif + + return valid; +} diff --git a/libcurl/lib/vauth/vauth.h b/libcurl/lib/vauth/vauth.h new file mode 100644 index 0000000..73bd25e --- /dev/null +++ b/libcurl/lib/vauth/vauth.h @@ -0,0 +1,215 @@ +#ifndef HEADER_CURL_VAUTH_H +#define HEADER_CURL_VAUTH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2019, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +struct Curl_easy; + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +struct digestdata; +#endif + +#if defined(USE_NTLM) +struct ntlmdata; +#endif + +#if defined(USE_KERBEROS5) +struct kerberos5data; +#endif + +#if (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) && defined(USE_SPNEGO) +struct negotiatedata; +#endif + +#if defined(USE_WINDOWS_SSPI) +#define GSS_ERROR(status) (status & 0x80000000) +#endif + +/* This is used to build a SPN string */ +#if !defined(USE_WINDOWS_SSPI) +char *Curl_auth_build_spn(const char *service, const char *host, + const char *realm); +#else +TCHAR *Curl_auth_build_spn(const char *service, const char *host, + const char *realm); +#endif + +/* This is used to test if the user contains a Windows domain name */ +bool Curl_auth_user_contains_domain(const char *user); + +/* This is used to generate a base64 encoded PLAIN cleartext message */ +CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, + const char *authzid, + const char *authcid, + const char *passwd, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded LOGIN cleartext message */ +CURLcode Curl_auth_create_login_message(struct Curl_easy *data, + const char *valuep, char **outptr, + size_t *outlen); + +/* This is used to generate a base64 encoded EXTERNAL cleartext message */ +CURLcode Curl_auth_create_external_message(struct Curl_easy *data, + const char *user, char **outptr, + size_t *outlen); + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +/* This is used to decode a CRAM-MD5 challenge message */ +CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen); + +/* This is used to generate a CRAM-MD5 response message */ +CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, + const char *chlg, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen); + +/* This is used to evaluate if DIGEST is supported */ +bool Curl_auth_is_digest_supported(void); + +/* This is used to generate a base64 encoded DIGEST-MD5 response message */ +CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen); + +/* This is used to decode a HTTP DIGEST challenge message */ +CURLcode Curl_auth_decode_digest_http_message(const char *chlg, + struct digestdata *digest); + +/* This is used to generate a HTTP DIGEST response message */ +CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uri, + struct digestdata *digest, + char **outptr, size_t *outlen); + +/* This is used to clean up the digest specific data */ +void Curl_auth_digest_cleanup(struct digestdata *digest); +#endif /* !CURL_DISABLE_CRYPTO_AUTH */ + +#if defined(USE_NTLM) +/* This is used to evaluate if NTLM is supported */ +bool Curl_auth_is_ntlm_supported(void); + +/* This is used to generate a base64 encoded NTLM type-1 message */ +CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + struct ntlmdata *ntlm, + char **outptr, + size_t *outlen); + +/* This is used to decode a base64 encoded NTLM type-2 message */ +CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, + const char *type2msg, + struct ntlmdata *ntlm); + +/* This is used to generate a base64 encoded NTLM type-3 message */ +CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen); + +/* This is used to clean up the NTLM specific data */ +void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm); +#endif /* USE_NTLM */ + +/* This is used to generate a base64 encoded OAuth 2.0 message */ +CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *host, + const long port, + const char *bearer, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded XOAuth 2.0 message */ +CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *bearer, + char **outptr, size_t *outlen); + +#if defined(USE_KERBEROS5) +/* This is used to evaluate if GSSAPI (Kerberos V5) is supported */ +bool Curl_auth_is_gssapi_supported(void); + +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token + message */ +CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + const bool mutual, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security + token message */ +CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *input, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen); + +/* This is used to clean up the GSSAPI specific data */ +void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5); +#endif /* USE_KERBEROS5 */ + +#if defined(USE_SPNEGO) +/* This is used to evaluate if SPNEGO (Negotiate) is supported */ +bool Curl_auth_is_spnego_supported(void); + +/* This is used to decode a base64 encoded SPNEGO (Negotiate) challenge + message */ +CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, + const char *user, + const char *passwood, + const char *service, + const char *host, + const char *chlg64, + struct negotiatedata *nego); + +/* This is used to generate a base64 encoded SPNEGO (Negotiate) response + message */ +CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, + struct negotiatedata *nego, + char **outptr, size_t *outlen); + +/* This is used to clean up the SPNEGO specifiec data */ +void Curl_auth_cleanup_spnego(struct negotiatedata *nego); + +#endif /* USE_SPNEGO */ + +#endif /* HEADER_CURL_VAUTH_H */ diff --git a/libcurl/lib/version.c b/libcurl/lib/version.c new file mode 100644 index 0000000..14b0531 --- /dev/null +++ b/libcurl/lib/version.c @@ -0,0 +1,467 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "vtls/vtls.h" +#include "http2.h" +#include "ssh.h" +#include "curl_printf.h" + +#ifdef USE_ARES +# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + (defined(WIN32) || defined(__SYMBIAN32__)) +# define CARES_STATICLIB +# endif +# include +#endif + +#ifdef USE_LIBIDN2 +#include +#endif + +#ifdef USE_LIBPSL +#include +#endif + +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#include +#endif + +#ifdef USE_LIBRTMP +#include +#endif + +#ifdef USE_LIBSSH2 +#include +#endif + +#ifdef HAVE_LIBSSH2_VERSION +/* get it run-time if possible */ +#define CURL_LIBSSH2_VERSION libssh2_version(0) +#else +/* use build-time if run-time not possible */ +#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION +#endif + +#ifdef HAVE_ZLIB_H +#include +#ifdef __SYMBIAN32__ +/* zlib pollutes the namespace with this definition */ +#undef WIN32 +#endif +#endif + +#ifdef HAVE_BROTLI +#include +#endif + +void Curl_version_init(void); + +/* For thread safety purposes this function is called by global_init so that + the static data in both version functions is initialized. */ +void Curl_version_init(void) +{ + curl_version(); + curl_version_info(CURLVERSION_NOW); +} + +#ifdef HAVE_BROTLI +static size_t brotli_version(char *buf, size_t bufsz) +{ + uint32_t brotli_version = BrotliDecoderVersion(); + unsigned int major = brotli_version >> 24; + unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12; + unsigned int patch = brotli_version & 0x00000FFF; + + return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch); +} +#endif + +char *curl_version(void) +{ + static bool initialized; + static char version[200]; + char *ptr = version; + size_t len; + size_t left = sizeof(version); + + if(initialized) + return version; + + strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION); + len = strlen(ptr); + left -= len; + ptr += len; + + if(left > 1) { + len = Curl_ssl_version(ptr + 1, left - 1); + + if(len > 0) { + *ptr = ' '; + left -= ++len; + ptr += len; + } + } + +#ifdef HAVE_LIBZ + len = msnprintf(ptr, left, " zlib/%s", zlibVersion()); + left -= len; + ptr += len; +#endif +#ifdef HAVE_BROTLI + len = msnprintf(ptr, left, "%s", " brotli/"); + left -= len; + ptr += len; + len = brotli_version(ptr, left); + left -= len; + ptr += len; +#endif +#ifdef USE_ARES + /* this function is only present in c-ares, not in the original ares */ + len = msnprintf(ptr, left, " c-ares/%s", ares_version(NULL)); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBIDN2 + if(idn2_check_version(IDN2_VERSION)) { + len = msnprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL)); + left -= len; + ptr += len; + } +#endif +#ifdef USE_LIBPSL + len = msnprintf(ptr, left, " libpsl/%s", psl_get_version()); + left -= len; + ptr += len; +#endif +#ifdef USE_WIN32_IDN + len = msnprintf(ptr, left, " WinIDN"); + left -= len; + ptr += len; +#endif +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#ifdef _LIBICONV_VERSION + len = msnprintf(ptr, left, " iconv/%d.%d", + _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255); +#else + /* version unknown */ + len = msnprintf(ptr, left, " iconv"); +#endif /* _LIBICONV_VERSION */ + left -= len; + ptr += len; +#endif +#ifdef USE_LIBSSH2 + len = msnprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBSSH + len = msnprintf(ptr, left, " libssh/%s", CURL_LIBSSH_VERSION); + left -= len; + ptr += len; +#endif +#ifdef USE_NGHTTP2 + len = Curl_http2_ver(ptr, left); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBRTMP + { + char suff[2]; + if(RTMP_LIB_VERSION & 0xff) { + suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1; + suff[1] = '\0'; + } + else + suff[0] = '\0'; + + msnprintf(ptr, left, " librtmp/%d.%d%s", + RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff, + suff); +/* + If another lib version is added below this one, this code would + also have to do: + + len = what msnprintf() returned + + left -= len; + ptr += len; +*/ + } +#endif + + /* Silent scan-build even if librtmp is not enabled. */ + (void) left; + (void) ptr; + + initialized = true; + return version; +} + +/* data for curl_version_info + + Keep the list sorted alphabetically. It is also written so that each + protocol line has its own #if line to make things easier on the eye. + */ + +static const char * const protocols[] = { +#ifndef CURL_DISABLE_DICT + "dict", +#endif +#ifndef CURL_DISABLE_FILE + "file", +#endif +#ifndef CURL_DISABLE_FTP + "ftp", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + "ftps", +#endif +#ifndef CURL_DISABLE_GOPHER + "gopher", +#endif +#ifndef CURL_DISABLE_HTTP + "http", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + "https", +#endif +#ifndef CURL_DISABLE_IMAP + "imap", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) + "imaps", +#endif +#ifndef CURL_DISABLE_LDAP + "ldap", +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + "ldaps", +#endif +#endif +#ifndef CURL_DISABLE_POP3 + "pop3", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) + "pop3s", +#endif +#ifdef USE_LIBRTMP + "rtmp", +#endif +#ifndef CURL_DISABLE_RTSP + "rtsp", +#endif +#if defined(USE_SSH) + "scp", + "sftp", +#endif +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) && \ + (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)) + "smb", +# ifdef USE_SSL + "smbs", +# endif +#endif +#ifndef CURL_DISABLE_SMTP + "smtp", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) + "smtps", +#endif +#ifndef CURL_DISABLE_TELNET + "telnet", +#endif +#ifndef CURL_DISABLE_TFTP + "tftp", +#endif + + NULL +}; + +static curl_version_info_data version_info = { + CURLVERSION_NOW, + LIBCURL_VERSION, + LIBCURL_VERSION_NUM, + OS, /* as found by configure or set by hand at build-time */ + 0 /* features is 0 by default */ +#ifdef ENABLE_IPV6 + | CURL_VERSION_IPV6 +#endif +#ifdef USE_SSL + | CURL_VERSION_SSL +#endif +#ifdef USE_NTLM + | CURL_VERSION_NTLM +#endif +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + | CURL_VERSION_NTLM_WB +#endif +#ifdef USE_SPNEGO + | CURL_VERSION_SPNEGO +#endif +#ifdef USE_KERBEROS5 + | CURL_VERSION_KERBEROS5 +#endif +#ifdef HAVE_GSSAPI + | CURL_VERSION_GSSAPI +#endif +#ifdef USE_WINDOWS_SSPI + | CURL_VERSION_SSPI +#endif +#ifdef HAVE_LIBZ + | CURL_VERSION_LIBZ +#endif +#ifdef DEBUGBUILD + | CURL_VERSION_DEBUG +#endif +#ifdef CURLDEBUG + | CURL_VERSION_CURLDEBUG +#endif +#ifdef CURLRES_ASYNCH + | CURL_VERSION_ASYNCHDNS +#endif +#if (CURL_SIZEOF_CURL_OFF_T > 4) && \ + ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) + | CURL_VERSION_LARGEFILE +#endif +#if defined(CURL_DOES_CONVERSIONS) + | CURL_VERSION_CONV +#endif +#if defined(USE_TLS_SRP) + | CURL_VERSION_TLSAUTH_SRP +#endif +#if defined(USE_NGHTTP2) + | CURL_VERSION_HTTP2 +#endif +#if defined(USE_UNIX_SOCKETS) + | CURL_VERSION_UNIX_SOCKETS +#endif +#if defined(USE_LIBPSL) + | CURL_VERSION_PSL +#endif +#if defined(CURL_WITH_MULTI_SSL) + | CURL_VERSION_MULTI_SSL +#endif +#if defined(HAVE_BROTLI) + | CURL_VERSION_BROTLI +#endif +#if defined(USE_ALTSVC) + | CURL_VERSION_ALTSVC +#endif + , + NULL, /* ssl_version */ + 0, /* ssl_version_num, this is kept at zero */ + NULL, /* zlib_version */ + protocols, + NULL, /* c-ares version */ + 0, /* c-ares version numerical */ + NULL, /* libidn version */ + 0, /* iconv version */ + NULL, /* ssh lib version */ + 0, /* brotli_ver_num */ + NULL, /* brotli version */ +}; + +curl_version_info_data *curl_version_info(CURLversion stamp) +{ + static bool initialized; +#if defined(USE_SSH) + static char ssh_buffer[80]; +#endif +#ifdef USE_SSL +#ifdef CURL_WITH_MULTI_SSL + static char ssl_buffer[200]; +#else + static char ssl_buffer[80]; +#endif +#endif +#ifdef HAVE_BROTLI + static char brotli_buffer[80]; +#endif + + if(initialized) + return &version_info; + +#ifdef USE_SSL + Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer)); + version_info.ssl_version = ssl_buffer; + if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY) + version_info.features |= CURL_VERSION_HTTPS_PROXY; + else + version_info.features &= ~CURL_VERSION_HTTPS_PROXY; +#endif + +#ifdef HAVE_LIBZ + version_info.libz_version = zlibVersion(); + /* libz left NULL if non-existing */ +#endif +#ifdef USE_ARES + { + int aresnum; + version_info.ares = ares_version(&aresnum); + version_info.ares_num = aresnum; + } +#endif +#ifdef USE_LIBIDN2 + /* This returns a version string if we use the given version or later, + otherwise it returns NULL */ + version_info.libidn = idn2_check_version(IDN2_VERSION); + if(version_info.libidn) + version_info.features |= CURL_VERSION_IDN; +#elif defined(USE_WIN32_IDN) + version_info.features |= CURL_VERSION_IDN; +#endif + +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#ifdef _LIBICONV_VERSION + version_info.iconv_ver_num = _LIBICONV_VERSION; +#else + /* version unknown */ + version_info.iconv_ver_num = -1; +#endif /* _LIBICONV_VERSION */ +#endif + +#if defined(USE_LIBSSH2) + msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION); + version_info.libssh_version = ssh_buffer; +#elif defined(USE_LIBSSH) + msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh/%s", CURL_LIBSSH_VERSION); + version_info.libssh_version = ssh_buffer; +#endif + +#ifdef HAVE_BROTLI + version_info.brotli_ver_num = BrotliDecoderVersion(); + brotli_version(brotli_buffer, sizeof(brotli_buffer)); + version_info.brotli_version = brotli_buffer; +#endif + + (void)stamp; /* avoid compiler warnings, we don't use this */ + + initialized = true; + return &version_info; +} diff --git a/libcurl/lib/vtls/axtls.c b/libcurl/lib/vtls/axtls.c new file mode 100644 index 0000000..f0e3766 --- /dev/null +++ b/libcurl/lib/vtls/axtls.c @@ -0,0 +1,706 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, DirecTV, Contact: Eric Hu, . + * Copyright (C) 2010 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all axTLS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +#include "curl_setup.h" + +#ifdef USE_AXTLS +#include +#include +#include "axtls.h" + +#include "sendf.h" +#include "inet_pton.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "curl_printf.h" +#include "hostcheck.h" +#include + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + + +/* Global axTLS init, called from Curl_ssl_init() */ +int Curl_axtls_init(void) +{ +/* axTLS has no global init. Everything is done through SSL and SSL_CTX + * structs stored in connectdata structure. Perhaps can move to axtls.h. + */ + return 1; +} + +int Curl_axtls_cleanup(void) +{ + /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */ + return 1; +} + +static CURLcode map_error_to_curl(int axtls_err) +{ + switch(axtls_err) { + case SSL_ERROR_NOT_SUPPORTED: + case SSL_ERROR_INVALID_VERSION: + case -70: /* protocol version alert from server */ + return CURLE_UNSUPPORTED_PROTOCOL; + break; + case SSL_ERROR_NO_CIPHER: + return CURLE_SSL_CIPHER; + break; + case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */ + case SSL_ERROR_NO_CERT_DEFINED: + case -42: /* bad certificate alert from server */ + case -43: /* unsupported cert alert from server */ + case -44: /* cert revoked alert from server */ + case -45: /* cert expired alert from server */ + case -46: /* cert unknown alert from server */ + return CURLE_SSL_CERTPROBLEM; + break; + case SSL_X509_ERROR(X509_NOT_OK): + case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT): + case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE): + case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID): + case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED): + case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED): + case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN): + case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): + case SSL_X509_ERROR(X509_INVALID_PRIV_KEY): + return CURLE_PEER_FAILED_VERIFICATION; + break; + case -48: /* unknown ca alert from server */ + return CURLE_SSL_CACERT; + break; + case -49: /* access denied alert from server */ + return CURLE_REMOTE_ACCESS_DENIED; + break; + case SSL_ERROR_CONN_LOST: + case SSL_ERROR_SOCK_SETUP_FAILURE: + case SSL_ERROR_INVALID_HANDSHAKE: + case SSL_ERROR_INVALID_PROT_MSG: + case SSL_ERROR_INVALID_HMAC: + case SSL_ERROR_INVALID_SESSION: + case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */ + case SSL_ERROR_FINISHED_INVALID: + case SSL_ERROR_NO_CLIENT_RENOG: + default: + return CURLE_SSL_CONNECT_ERROR; + break; + } +} + +static Curl_recv axtls_recv; +static Curl_send axtls_send; + +static void free_ssl_structs(struct ssl_connect_data *connssl) +{ + if(connssl->ssl) { + ssl_free(connssl->ssl); + connssl->ssl = NULL; + } + if(connssl->ssl_ctx) { + ssl_ctx_free(connssl->ssl_ctx); + connssl->ssl_ctx = NULL; + } +} + +/* + * For both blocking and non-blocking connects, this function sets up the + * ssl context and state. This function is called after the TCP connect + * has completed. + */ +static CURLcode connect_prep(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + SSL_CTX *ssl_ctx; + SSL *ssl = NULL; + int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0}; + int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0}; + int i, ssl_fcn_return; + + /* Assuming users will not compile in custom key/cert to axTLS. + * Also, even for blocking connects, use axTLS non-blocking feature. + */ + uint32_t client_option = SSL_NO_DEFAULT_KEY | + SSL_SERVER_VERIFY_LATER | + SSL_CONNECT_IN_PARTS; + + if(conn->ssl[sockindex].state == ssl_connection_complete) + /* to make us tolerant against being called more than once for the + same connection */ + return CURLE_OK; + + if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { + failf(data, "axtls does not support CURL_SSLVERSION_MAX"); + return CURLE_SSL_CONNECT_ERROR; + } + + + /* axTLS only supports TLSv1 */ + /* check to see if we've been told to use an explicit SSL/TLS version */ + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + break; + default: + failf(data, "axTLS only supports TLS 1.0 and 1.1, " + "and it cannot be specified which one to use"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef AXTLSDEBUG + client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS; +#endif /* AXTLSDEBUG */ + + /* Allocate an SSL_CTX struct */ + ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS); + if(ssl_ctx == NULL) { + failf(data, "unable to create client SSL context"); + return CURLE_SSL_CONNECT_ERROR; + } + + conn->ssl[sockindex].ssl_ctx = ssl_ctx; + conn->ssl[sockindex].ssl = NULL; + + /* Load the trusted CA cert bundle file */ + if(SSL_CONN_CONFIG(CAfile)) { + if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, + SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) { + infof(data, "error reading ca cert file %s \n", + SSL_CONN_CONFIG(CAfile)); + if(SSL_CONN_CONFIG(verifypeer)) { + return CURLE_SSL_CACERT_BADFILE; + } + } + else + infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile)); + } + + /* gtls.c tasks we're skipping for now: + * 1) certificate revocation list checking + * 2) dns name assignment to host + * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore + * 4) set certificate priority. axTLS ignores type and sends certs in + * order added. can probably ignore this. + */ + + /* Load client certificate */ + if(SSL_SET_OPTION(cert)) { + i=0; + /* Instead of trying to analyze cert type here, let axTLS try them all. */ + while(cert_types[i] != 0) { + ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], + SSL_SET_OPTION(cert), NULL); + if(ssl_fcn_return == SSL_OK) { + infof(data, "successfully read cert file %s \n", + SSL_SET_OPTION(cert)); + break; + } + i++; + } + /* Tried all cert types, none worked. */ + if(cert_types[i] == 0) { + failf(data, "%s is not x509 or pkcs12 format", + SSL_SET_OPTION(cert)); + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load client key. + If a pkcs12 file successfully loaded a cert, then there's nothing to do + because the key has already been loaded. */ + if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) { + i=0; + /* Instead of trying to analyze key type here, let axTLS try them all. */ + while(key_types[i] != 0) { + ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], + SSL_SET_OPTION(key), NULL); + if(ssl_fcn_return == SSL_OK) { + infof(data, "successfully read key file %s \n", + SSL_SET_OPTION(key)); + break; + } + i++; + } + /* Tried all key types, none worked. */ + if(key_types[i] == 0) { + failf(data, "Failure: %s is not a supported key file", + SSL_SET_OPTION(key)); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* gtls.c does more here that is being left out for now + * 1) set session credentials. can probably ignore since axtls puts this + * info in the ssl_ctx struct + * 2) setting up callbacks. these seem gnutls specific + */ + + if(SSL_SET_OPTION(primary.sessionid)) { + const uint8_t *ssl_sessionid; + size_t ssl_idsize; + + /* In axTLS, handshaking happens inside ssl_client_new. */ + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize, + sockindex)) { + /* we got a session id, use it! */ + infof(data, "SSL re-using session ID\n"); + ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], + ssl_sessionid, (uint8_t)ssl_idsize, NULL); + } + Curl_ssl_sessionid_unlock(conn); + } + + if(!ssl) + ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL); + + conn->ssl[sockindex].ssl = ssl; + return CURLE_OK; +} + +/* + * For both blocking and non-blocking connects, this function finalizes the + * SSL connection. + */ +static CURLcode connect_finish(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + SSL *ssl = conn->ssl[sockindex].ssl; + const char *peer_CN; + uint32_t dns_altname_index; + const char *dns_altname; + int8_t found_subject_alt_names = 0; + int8_t found_subject_alt_name_matching_conn = 0; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + + /* Here, gtls.c gets the peer certificates and fails out depending on + * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? + */ + + /* Verify server's certificate */ + if(SSL_CONN_CONFIG(verifypeer)) { + if(ssl_verify_cert(ssl) != SSL_OK) { + Curl_axtls_close(conn, sockindex); + failf(data, "server cert verify failed"); + return CURLE_PEER_FAILED_VERIFICATION; + } + } + else + infof(data, "\t server certificate verification SKIPPED\n"); + + /* Here, gtls.c does issuer verification. axTLS has no straightforward + * equivalent, so omitting for now.*/ + + /* Here, gtls.c does the following + * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but + * it seems useful. This is now implemented, by Oscar Koeroo + * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert + * 3) displays a bunch of cert information. axTLS doesn't support most of + * this, but a couple fields are available. + */ + + /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a + risk of an inifite loop */ + for(dns_altname_index = 0; ; dns_altname_index++) { + dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index); + if(dns_altname == NULL) { + break; + } + found_subject_alt_names = 1; + + infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n", + dns_altname, hostname); + if(Curl_cert_hostcheck(dns_altname, hostname)) { + found_subject_alt_name_matching_conn = 1; + break; + } + } + + /* RFC2818 checks */ + if(found_subject_alt_names && !found_subject_alt_name_matching_conn) { + if(SSL_CONN_CONFIG(verifyhost)) { + /* Break connection ! */ + Curl_axtls_close(conn, sockindex); + failf(data, "\tsubjectAltName(s) do not match %s\n", dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\tsubjectAltName(s) do not match %s\n", dispname); + } + else if(found_subject_alt_names == 0) { + /* Per RFC2818, when no Subject Alt Names were available, examine the peer + CN as a legacy fallback */ + peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); + if(peer_CN == NULL) { + if(SSL_CONN_CONFIG(verifyhost)) { + Curl_axtls_close(conn, sockindex); + failf(data, "unable to obtain common name from peer certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "unable to obtain common name from peer certificate"); + } + else { + if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { + if(SSL_CONN_CONFIG(verifyhost)) { + /* Break connection ! */ + Curl_axtls_close(conn, sockindex); + failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", + peer_CN, dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\tcommon name \"%s\" does not match \"%s\"\n", + peer_CN, dispname); + } + } + } + + /* General housekeeping */ + conn->ssl[sockindex].state = ssl_connection_complete; + conn->recv[sockindex] = axtls_recv; + conn->send[sockindex] = axtls_send; + + /* Put our freshly minted SSL session in cache */ + if(SSL_SET_OPTION(primary.sessionid)) { + const uint8_t *ssl_sessionid = ssl_get_session_id(ssl); + size_t ssl_idsize = ssl_get_session_id_size(ssl); + Curl_ssl_sessionid_lock(conn); + if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize, + sockindex) != CURLE_OK) + infof(data, "failed to add session to cache\n"); + Curl_ssl_sessionid_unlock(conn); + } + + return CURLE_OK; +} + +/* + * Use axTLS's non-blocking connection feature to open an SSL connection. + * This is called after a TCP connection is already established. + */ +CURLcode Curl_axtls_connect_nonblocking( + struct connectdata *conn, + int sockindex, + bool *done) +{ + CURLcode conn_step; + int ssl_fcn_return; + int i; + + *done = FALSE; + /* connectdata is calloc'd and connecting_state is only changed in this + function, so this is safe, as the state is effectively initialized. */ + if(conn->ssl[sockindex].connecting_state == ssl_connect_1) { + conn_step = connect_prep(conn, sockindex); + if(conn_step != CURLE_OK) { + Curl_axtls_close(conn, sockindex); + return conn_step; + } + conn->ssl[sockindex].connecting_state = ssl_connect_2; + } + + if(conn->ssl[sockindex].connecting_state == ssl_connect_2) { + /* Check to make sure handshake was ok. */ + if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) { + /* Loop to perform more work in between sleeps. This is work around the + fact that axtls does not expose any knowledge about when work needs + to be performed. This can save ~25% of time on SSL handshakes. */ + for(i=0; i<5; i++) { + ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL); + if(ssl_fcn_return < 0) { + Curl_axtls_close(conn, sockindex); + ssl_display_error(ssl_fcn_return); /* goes to stdout. */ + return map_error_to_curl(ssl_fcn_return); + } + return CURLE_OK; + } + } + infof(conn->data, "handshake completed successfully\n"); + conn->ssl[sockindex].connecting_state = ssl_connect_3; + } + + if(conn->ssl[sockindex].connecting_state == ssl_connect_3) { + conn_step = connect_finish(conn, sockindex); + if(conn_step != CURLE_OK) { + Curl_axtls_close(conn, sockindex); + return conn_step; + } + + /* Reset connect state */ + conn->ssl[sockindex].connecting_state = ssl_connect_1; + + *done = TRUE; + return CURLE_OK; + } + + /* Unrecognized state. Things are very bad. */ + conn->ssl[sockindex].state = ssl_connection_none; + conn->ssl[sockindex].connecting_state = ssl_connect_1; + /* Return value perhaps not strictly correct, but distinguishes the issue.*/ + return CURLE_BAD_FUNCTION_ARGUMENT; +} + + +/* + * This function is called after the TCP connect has completed. Setup the TLS + * layer and do all necessary magic for a blocking connect. + */ +CURLcode +Curl_axtls_connect(struct connectdata *conn, + int sockindex) + +{ + struct Curl_easy *data = conn->data; + CURLcode conn_step = connect_prep(conn, sockindex); + int ssl_fcn_return; + SSL *ssl = conn->ssl[sockindex].ssl; + long timeout_ms; + + if(conn_step != CURLE_OK) { + Curl_axtls_close(conn, sockindex); + return conn_step; + } + + /* Check to make sure handshake was ok. */ + while(ssl_handshake_status(ssl) != SSL_OK) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + ssl_fcn_return = ssl_read(ssl, NULL); + if(ssl_fcn_return < 0) { + Curl_axtls_close(conn, sockindex); + ssl_display_error(ssl_fcn_return); /* goes to stdout. */ + return map_error_to_curl(ssl_fcn_return); + } + /* TODO: avoid polling */ + Curl_wait_ms(10); + } + infof(conn->data, "handshake completed successfully\n"); + + conn_step = connect_finish(conn, sockindex); + if(conn_step != CURLE_OK) { + Curl_axtls_close(conn, sockindex); + return conn_step; + } + + return CURLE_OK; +} + +/* return number of sent (non-SSL) bytes */ +static ssize_t axtls_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *err) +{ + /* ssl_write() returns 'int' while write() and send() returns 'size_t' */ + int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); + + infof(conn->data, " axtls_send\n"); + + if(rc < 0) { + *err = map_error_to_curl(rc); + rc = -1; /* generic error code for send failure */ + } + + *err = CURLE_OK; + return rc; +} + +void Curl_axtls_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + infof(conn->data, " Curl_axtls_close\n"); + + /* line from openssl.c: (void)SSL_shutdown(connssl->ssl); + axTLS compat layer does nothing for SSL_shutdown */ + + /* The following line is from openssl.c. There seems to be no axTLS + equivalent. ssl_free and ssl_ctx_free close things. + SSL_set_connect_state(connssl->handle); */ + + free_ssl_structs(connssl); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) +{ + /* Outline taken from openssl.c since functions are in axTLS compat layer. + axTLS's error set is much smaller, so a lot of error-handling was removed. + */ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + uint8_t *buf; + ssize_t nread; + + infof(conn->data, " Curl_axtls_shutdown\n"); + + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + (void)SSL_shutdown(connssl->ssl); + */ + + if(connssl->ssl) { + int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); + if(what > 0) { + /* Something to read, let's do it and hope that it is the close + notify alert from the server. buf is managed internally by + axTLS and will be released upon calling ssl_free via + free_ssl_structs. */ + nread = (ssize_t)ssl_read(connssl->ssl, &buf); + + if(nread < SSL_OK) { + failf(data, "close notify alert not received during shutdown"); + retval = -1; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + } + + free_ssl_structs(connssl); + } + return retval; +} + +static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *err) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + ssize_t ret = 0; + uint8_t *read_buf; + + infof(conn->data, " axtls_recv\n"); + + *err = CURLE_OK; + if(connssl) { + ret = ssl_read(connssl->ssl, &read_buf); + if(ret > SSL_OK) { + /* ssl_read returns SSL_OK if there is more data to read, so if it is + larger, then all data has been read already. */ + memcpy(buf, read_buf, + (size_t)ret > buffersize ? buffersize : (size_t)ret); + } + else if(ret == SSL_OK) { + /* more data to be read, signal caller to call again */ + *err = CURLE_AGAIN; + ret = -1; + } + else if(ret == -3) { + /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS + team approves proposed fix. */ + Curl_axtls_close(conn, num); + } + else { + failf(conn->data, "axTLS recv error (%d)", ret); + *err = map_error_to_curl((int) ret); + ret = -1; + } + } + + return ret; +} + +/* + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +int Curl_axtls_check_cxn(struct connectdata *conn) +{ + /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1); + axTLS compat layer always returns the last argument, so connection is + always alive? */ + + infof(conn->data, " Curl_axtls_check_cxn\n"); + return 1; /* connection still in place */ +} + +void Curl_axtls_session_free(void *ptr) +{ + (void)ptr; + /* free the ID */ + /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL + compatibility layer does nothing, so we do nothing too. */ +} + +size_t Curl_axtls_version(char *buffer, size_t size) +{ + return snprintf(buffer, size, "axTLS/%s", ssl_version()); +} + +CURLcode Curl_axtls_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) +{ + static bool ssl_seeded = FALSE; + (void)data; + if(!ssl_seeded) { + ssl_seeded = TRUE; + /* Initialize the seed if not already done. This call is not exactly thread + * safe (and neither is the ssl_seeded check), but the worst effect of a + * race condition is that some global resources will leak. */ + RNG_initialize(); + } + get_random((int)length, entropy); + return CURLE_OK; +} + +#endif /* USE_AXTLS */ diff --git a/libcurl/lib/vtls/axtls.h b/libcurl/lib/vtls/axtls.h new file mode 100644 index 0000000..53797ea --- /dev/null +++ b/libcurl/lib/vtls/axtls.h @@ -0,0 +1,71 @@ +#ifndef HEADER_CURL_AXTLS_H +#define HEADER_CURL_AXTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, DirecTV, Contact: Eric Hu + * Copyright (C) 2010 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_AXTLS +#include "curl/curl.h" +#include "urldata.h" + +int Curl_axtls_init(void); +int Curl_axtls_cleanup(void); +CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex); +CURLcode Curl_axtls_connect_nonblocking( + struct connectdata *conn, + int sockindex, + bool *done); + + /* close a SSL connection */ +void Curl_axtls_close(struct connectdata *conn, int sockindex); + +void Curl_axtls_session_free(void *ptr); +size_t Curl_axtls_version(char *buffer, size_t size); +int Curl_axtls_shutdown(struct connectdata *conn, int sockindex); +int Curl_axtls_check_cxn(struct connectdata *conn); +CURLcode Curl_axtls_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length); + +/* Set the API backend definition to axTLS */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS + +/* API setup for axTLS */ +#define curlssl_init Curl_axtls_init +#define curlssl_cleanup Curl_axtls_cleanup +#define curlssl_connect Curl_axtls_connect +#define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking +#define curlssl_session_free(x) Curl_axtls_session_free(x) +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_axtls_close +#define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y) +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_axtls_version +#define curlssl_check_cxn(x) Curl_axtls_check_cxn(x) +#define curlssl_data_pending(x,y) ((void)x, (void)y, 0) +#define curlssl_random(x,y,z) Curl_axtls_random(x,y,z) + +#endif /* USE_AXTLS */ +#endif /* HEADER_CURL_AXTLS_H */ + diff --git a/libcurl/lib/vtls/bearssl.c b/libcurl/lib/vtls/bearssl.c new file mode 100644 index 0000000..81dc0d2 --- /dev/null +++ b/libcurl/lib/vtls/bearssl.c @@ -0,0 +1,1662 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * BearSSL TLS backend for libcurl + * Designed for Xbox (Visual Studio 2003 / C89 compatible) + * + * This file implements the libcurl vtls interface using BearSSL. + * BearSSL is ideal for Xbox because: + * - Written in C89/C90 (VS 2003 compatible) + * - No dynamic memory allocation + * - Small footprint + * - No external dependencies + * + * Xbox-specific enhancements: + * - Trust anchors loaded from embedded CA database (750+ CAs) + * - Session caching for TLS resumption + * - Descriptive error messages + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_BEARSSL + +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "vtls.h" +#include "connect.h" +#include "select.h" +#include "multiif.h" + +/* Xbox-specific BearSSL integration */ +#ifdef _XBOX +#include "bearssl_xbox.h" +#define BEARSSL_XBOX_INTEGRATION 1 +#else +#define BEARSSL_XBOX_INTEGRATION 0 +#endif + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* + * Xbox time validation callback for X.509 certificate checking. + * + * The Xbox's internal RTC is unreliable: no NTP (Xbox Live for original Xbox + * is defunct), CMOS battery may be dead after 20+ years, and the clock can + * reset to 2000-01-01 or similar. A wrong system clock causes BearSSL's + * time(NULL)-based date validation to reject perfectly valid certificates. + * + * We skip date validation entirely. Trust anchor verification and optional + * certificate pinning provide the real security guarantees. + * + * Return: 0 = within validity period (always) + */ +#ifdef _XBOX +static int bearssl_xbox_time_check(void *tctx, + uint32_t not_before_days, uint32_t not_before_seconds, + uint32_t not_after_days, uint32_t not_after_seconds) +{ + (void)tctx; + (void)not_before_days; + (void)not_before_seconds; + (void)not_after_days; + (void)not_after_seconds; + return 0; +} +#endif + +/* Secure cipher suites - ECDHE with AEAD only */ +static const uint16_t bearssl_secure_suites[] = { + BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +}; +#define BEARSSL_SECURE_SUITES_COUNT 6 + +/* + * ALPN protocol names for HTTP/1.1 + * + * ALPN (Application-Layer Protocol Negotiation) is a TLS extension that allows + * the client and server to negotiate which application protocol to use over + * the encrypted connection. Modern HTTPS servers (especially CDNs like + * Cloudflare) require ALPN to be present in the TLS handshake. + * + * Without ALPN, many servers will: + * - Reject the connection outright + * - Assume HTTP/2 and fail when receiving HTTP/1.1 + * - Reset the connection after handshake completes + * + * We advertise "http/1.1" since this libcurl build doesn't support HTTP/2. + */ +static const char *bearssl_alpn_protocols[] = { "http/1.1" }; +#define BEARSSL_ALPN_PROTOCOLS_COUNT 1 + +/* + * "No Anchor" X509 validator - wraps br_x509_minimal but accepts all certs. + * + * This approach uses BearSSL's proven certificate parsing code (br_x509_minimal) + * but overrides the validation result to always succeed. This is safer than + * implementing our own certificate decoder. + * + * Used when SSL_VERIFYPEER is disabled. + * + * NOTE: We use a POINTER to the minimal context (not embedded) to avoid + * memory layout issues with the union in ssl_backend_data. + */ +typedef struct { + const br_x509_class *vtable; + br_x509_minimal_context *minimal; /* Pointer to minimal validator */ + /* Certificate pinning: hash the leaf (first) certificate */ + br_sha256_context pin_sha256; /* SHA-256 running hash of leaf cert */ + unsigned char leaf_hash[32]; /* Final SHA-256 of leaf certificate */ + int cert_index; /* 0 = leaf cert, increments per cert */ + int leaf_hash_valid; /* 1 if leaf_hash has been computed */ + char pin_hostname[256]; /* Hostname for pin lookup */ +} br_x509_noanchor_context; + +/* Forward the call to minimal validator */ +static void xc_noanchor_start_chain(const br_x509_class **ctx, + const char *server_name) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: start_chain called, ctx=%p, xc=%p, minimal=%p\n", + (void*)ctx, (void*)xc, (void*)xc->minimal); + OutputDebugStringA(dbg); + if(xc->minimal) { + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: server=%s, minimal->vtable=%p\n", + server_name ? server_name : "(null)", + (void*)xc->minimal->vtable); + OutputDebugStringA(dbg); + } + } +#endif + if(!xc->minimal || !xc->minimal->vtable) { + OutputDebugStringA("BearSSL noanchor X509: ERROR - minimal or vtable is NULL!\n"); + return; + } + + /* Reset pinning state for this new chain */ + xc->cert_index = 0; + xc->leaf_hash_valid = 0; + memset(xc->leaf_hash, 0, sizeof(xc->leaf_hash)); + if(server_name) { + strncpy(xc->pin_hostname, server_name, sizeof(xc->pin_hostname) - 1); + xc->pin_hostname[sizeof(xc->pin_hostname) - 1] = '\0'; + } + else { + xc->pin_hostname[0] = '\0'; + } + + xc->minimal->vtable->start_chain(&xc->minimal->vtable, server_name); + OutputDebugStringA("BearSSL noanchor X509: start_chain forwarded OK\n"); +} + +static void xc_noanchor_start_cert(const br_x509_class **ctx, uint32_t length) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL noanchor X509: start_cert[%d], length=%u\n", + xc->cert_index, (unsigned)length); + OutputDebugStringA(dbg); + } +#endif + /* For the leaf certificate (index 0), start hashing for pin check */ + if(xc->cert_index == 0) { + br_sha256_init(&xc->pin_sha256); + } + xc->minimal->vtable->start_cert(&xc->minimal->vtable, length); +} + +static void xc_noanchor_append(const br_x509_class **ctx, + const unsigned char *buf, size_t len) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; + /* Feed leaf certificate bytes into SHA-256 for pinning */ + if(xc->cert_index == 0) { + br_sha256_update(&xc->pin_sha256, buf, len); + } + xc->minimal->vtable->append(&xc->minimal->vtable, buf, len); +} + +static void xc_noanchor_end_cert(const br_x509_class **ctx) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; +#ifdef _XBOX + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL noanchor X509: end_cert[%d]\n", + xc->cert_index); + OutputDebugStringA(dbg); + } +#endif + xc->minimal->vtable->end_cert(&xc->minimal->vtable); + + /* Finalize the SHA-256 hash of the leaf certificate */ + if(xc->cert_index == 0) { + br_sha256_out(&xc->pin_sha256, xc->leaf_hash); + xc->leaf_hash_valid = 1; +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: leaf cert SHA-256: " + "%02X%02X%02X%02X%02X%02X%02X%02X...\n", + xc->leaf_hash[0], xc->leaf_hash[1], + xc->leaf_hash[2], xc->leaf_hash[3], + xc->leaf_hash[4], xc->leaf_hash[5], + xc->leaf_hash[6], xc->leaf_hash[7]); + OutputDebugStringA(dbg); + } +#endif + } + xc->cert_index++; + +#ifdef _XBOX + /* Log the minimal validator's state after processing certificate */ + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: minimal->err=%d, pkey.key_type=%d\n", + xc->minimal->err, xc->minimal->pkey.key_type); + OutputDebugStringA(dbg); + + if(xc->minimal->pkey.key_type == BR_KEYTYPE_RSA) { + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: RSA key - n=%p nlen=%u e=%p elen=%u\n", + (void*)xc->minimal->pkey.key.rsa.n, + (unsigned)xc->minimal->pkey.key.rsa.nlen, + (void*)xc->minimal->pkey.key.rsa.e, + (unsigned)xc->minimal->pkey.key.rsa.elen); + OutputDebugStringA(dbg); + } + else if(xc->minimal->pkey.key_type == BR_KEYTYPE_EC) { + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: EC key - curve=%d q=%p qlen=%u\n", + xc->minimal->pkey.key.ec.curve, + (void*)xc->minimal->pkey.key.ec.q, + (unsigned)xc->minimal->pkey.key.ec.qlen); + OutputDebugStringA(dbg); + } + } +#endif +} + +static unsigned xc_noanchor_end_chain(const br_x509_class **ctx) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; + unsigned result; + + /* Call the minimal validator's end_chain */ + result = xc->minimal->vtable->end_chain(&xc->minimal->vtable); + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: end_chain, minimal returned %u (err=%d)\n", + result, xc->minimal->err); + OutputDebugStringA(dbg); + } +#endif + + /* + * Override the result: accept certificates in insecure mode. + * + * When SSL_VERIFYPEER is disabled, we accept all validation errors: + * - BR_ERR_X509_OK (32) - success + * - BR_ERR_X509_EXPIRED (54) - certificate expired or not yet valid + * - BR_ERR_X509_DN_MISMATCH (55) - issuer/subject DN mismatch + * - BR_ERR_X509_BAD_SERVER_NAME (56) - server name doesn't match cert + * - BR_ERR_X509_NOT_TRUSTED (62) - no matching trust anchor + * + * We only fail on actual parsing errors (33-52) which indicate a + * malformed certificate that cannot be used. + */ + if(result == BR_ERR_X509_OK || + result == BR_ERR_X509_EXPIRED || + result == BR_ERR_X509_DN_MISMATCH || + result == BR_ERR_X509_BAD_SERVER_NAME || + result == BR_ERR_X509_CRITICAL_EXTENSION || + result == BR_ERR_X509_NOT_CA || + result == BR_ERR_X509_FORBIDDEN_KEY_USAGE || + result == BR_ERR_X509_WEAK_PUBLIC_KEY || + result == BR_ERR_X509_NOT_TRUSTED) { + + /* + * Certificate pinning check: if a pin is registered for this hostname, + * verify the leaf certificate hash matches. This runs even in insecure + * mode because pinning is an explicit trust decision by the application. + */ +#if BEARSSL_XBOX_INTEGRATION + if(xc->leaf_hash_valid && xc->pin_hostname[0] != '\0') { + if(!bearssl_xbox_pin_verify_hash(xc->pin_hostname, xc->leaf_hash)) { +#ifdef _XBOX + OutputDebugStringA("BearSSL noanchor X509: CERTIFICATE PIN MISMATCH - rejecting!\n"); +#endif + return BR_ERR_X509_NOT_TRUSTED; + } + } +#endif + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: accepting certificate (insecure mode, result=%u)\n", + result); + OutputDebugStringA(dbg); + } +#endif + return 0; /* Success */ + } + + /* For actual parsing errors (bad certificate format, etc.), we still fail */ +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: certificate parsing error %u\n", result); + OutputDebugStringA(dbg); + } +#endif + return result; +} + +static const br_x509_pkey *xc_noanchor_get_pkey( + const br_x509_class *const *ctx, unsigned *usages) +{ + br_x509_noanchor_context *xc = (br_x509_noanchor_context *)ctx; + const br_x509_pkey *pk; + + /* Get the public key from the minimal validator */ + pk = xc->minimal->vtable->get_pkey(&xc->minimal->vtable, usages); + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: get_pkey returned %p (err=%d, key_type=%d)\n", + (void*)pk, xc->minimal->err, xc->minimal->pkey.key_type); + OutputDebugStringA(dbg); + } +#endif + + /* + * The minimal validator only returns the key if err is OK (32) or + * NOT_TRUSTED (62). For other validation errors like BAD_SERVER_NAME (56), + * EXPIRED (54), etc., it returns NULL even though the key was parsed. + * + * In insecure mode, we need to return the key for any validation error + * as long as the key itself was successfully parsed. + */ + if(!pk) { + /* + * Minimal validator didn't return key. Check if the key was parsed + * successfully - if so, return it directly. This handles validation + * errors like BAD_SERVER_NAME where the cert is valid but doesn't + * match requirements we're choosing to ignore. + */ + if(xc->minimal->pkey.key_type == BR_KEYTYPE_RSA || + xc->minimal->pkey.key_type == BR_KEYTYPE_EC) { +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL noanchor X509: returning key directly (err=%d bypassed)\n", + xc->minimal->err); + OutputDebugStringA(dbg); + } +#endif + if(usages) + *usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN; + return &xc->minimal->pkey; + } +#ifdef _XBOX + OutputDebugStringA("BearSSL noanchor X509: ERROR - no valid key available!\n"); +#endif + } + + return pk; +} + +static const br_x509_class br_x509_noanchor_vtable = { + sizeof(br_x509_noanchor_context), + xc_noanchor_start_chain, + xc_noanchor_start_cert, + xc_noanchor_append, + xc_noanchor_end_cert, + xc_noanchor_end_chain, + xc_noanchor_get_pkey +}; + +/* + * Legacy insecure validator kept for reference but not used. + * The noanchor approach above is preferred. + */ +#if 0 /* DISABLED - using noanchor instead */ + +typedef struct { + const br_x509_class *vtable; + br_x509_decoder_context decoder; + br_x509_pkey pkey; + unsigned char pkey_data[BR_EC_KBUF_PUB_MAX_SIZE]; + unsigned char rsa_n[512]; + unsigned char rsa_e[8]; + int first_cert; + int pkey_valid; + uint32_t expected_len; + uint32_t received_len; +} br_x509_insecure_context; + +static void xc_insecure_start_chain(const br_x509_class **ctx, + const char *server_name) +{ + br_x509_insecure_context *xc = (br_x509_insecure_context *)ctx; + (void)server_name; + xc->first_cert = 1; + xc->pkey_valid = 0; +} + +/* ... rest of insecure implementation ... */ + +#endif /* DISABLED */ + +/* BearSSL backend data structure */ +struct ssl_backend_data { + br_ssl_client_context sc; + br_x509_minimal_context xc_minimal; /* Minimal X509 validator */ + br_x509_noanchor_context xc_noanchor; /* Noanchor wrapper (small, just vtable + pointer) */ + int using_noanchor; /* Are we using the noanchor (no-verify) validator? */ + unsigned char iobuf[BR_SSL_BUFSIZE_BIDI]; + br_sslio_context ioc; + int active; /* Is the SSL connection active? */ + int session_resumed; /* Was session resumed? */ + unsigned char resume_master_secret[48]; /* Master secret from resume attempt */ + int io_error; /* Have we had a socket I/O error? Skip graceful close if so */ + unsigned char leaf_cert_hash[32]; /* SHA-256 of leaf cert (from X.509 callback) */ + int leaf_cert_hash_valid; /* 1 if hash was captured */ + char hostname[256]; /* Hostname for session caching */ +#if BEARSSL_XBOX_INTEGRATION + br_x509_trust_anchor *file_anchors; /* Per-connection CAs from CURLOPT_CAINFO */ + size_t file_anchor_count; +#endif +}; + +#define BACKEND connssl->backend + +/* Forward declarations for send/recv functions */ +static Curl_recv bearssl_recv; +static Curl_send bearssl_send; + +/* Global state for trust anchor initialization */ +static int bearssl_trust_anchors_loaded = 0; +#if BEARSSL_XBOX_INTEGRATION +static int bearssl_trust_store_updated = 0; +#endif + +/* Low-level socket read callback for BearSSL */ +static int +sock_read(void *ctx, unsigned char *buf, size_t len) +{ + curl_socket_t fd = *(curl_socket_t *)ctx; + ssize_t rlen; + + /* + * Simple blocking read - no retry loop. + * The socket should already be in blocking mode, and libcurl manages + * timeouts at a higher level. We just do a single recv() call. + */ + rlen = recv(fd, (char *)buf, (int)len, 0); + + if(rlen > 0) { + /* Success - got data */ +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL sock_read: got %d bytes\n", (int)rlen); + OutputDebugStringA(dbg); + } +#endif + return (int)rlen; + } + + if(rlen == 0) { + /* Connection closed by peer */ +#ifdef BEARSSL_VERBOSE_DEBUG + OutputDebugStringA("BearSSL sock_read: connection closed by peer\n"); +#endif + return -1; + } + + /* rlen < 0 - error */ + { + int err = SOCKERRNO; +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL sock_read: recv error %d\n", err); + OutputDebugStringA(dbg); + } +#endif + + /* For EINTR, we could retry, but it's simpler to let the caller handle it */ + if(err == EWOULDBLOCK || err == EAGAIN) { + /* Would block - return 0 to indicate no data available yet */ + /* BearSSL will handle this appropriately */ + return 0; + } + + /* Real error - return -1 */ + return -1; + } +} + +/* Low-level socket write callback for BearSSL */ +static int +sock_write(void *ctx, const unsigned char *buf, size_t len) +{ + curl_socket_t fd = *(curl_socket_t *)ctx; + ssize_t wlen; + + /* + * Simple blocking write - no retry loop. + * The socket should already be in blocking mode, and libcurl manages + * timeouts at a higher level. We just do a single send() call. + */ + wlen = send(fd, (const char *)buf, (int)len, 0); + + if(wlen > 0) { + /* Success - data sent */ +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL sock_write: sent %d bytes\n", (int)wlen); + OutputDebugStringA(dbg); + } +#endif + return (int)wlen; + } + + if(wlen == 0) { + /* No data sent - treat as would-block */ + return 0; + } + + /* wlen < 0 - error */ + { + int err = SOCKERRNO; +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[64]; + msnprintf(dbg, sizeof(dbg), "BearSSL sock_write: send error %d\n", err); + OutputDebugStringA(dbg); + } +#endif + + if(err == EWOULDBLOCK || err == EAGAIN) { + /* Would block - return 0 to indicate no data sent yet */ + return 0; + } + + /* Real error - return -1 */ + return -1; + } +} + +/* Get descriptive error message for BearSSL error code */ +static const char * +bearssl_error_string(int err) +{ +#if BEARSSL_XBOX_INTEGRATION + return bearssl_xbox_error_string(err); +#else + /* Fallback error messages for non-Xbox builds */ + switch(err) { + case BR_ERR_OK: return "Success"; + case BR_ERR_BAD_PARAM: return "Bad parameter"; + case BR_ERR_BAD_STATE: return "Invalid state"; + case BR_ERR_UNSUPPORTED_VERSION: return "Unsupported TLS version"; + case BR_ERR_BAD_VERSION: return "Bad TLS version"; + case BR_ERR_TOO_LARGE: return "Record too large"; + case BR_ERR_BAD_MAC: return "MAC verification failed"; + case BR_ERR_NO_RANDOM: return "No random seed"; + case BR_ERR_UNKNOWN_TYPE: return "Unknown record type"; + case BR_ERR_UNEXPECTED: return "Unexpected message"; + case BR_ERR_BAD_CCS: return "Bad ChangeCipherSpec"; + case BR_ERR_BAD_ALERT: return "Bad alert"; + case BR_ERR_BAD_HANDSHAKE: return "Bad handshake message"; + case BR_ERR_OVERSIZED_ID: return "Oversized ID"; + case BR_ERR_BAD_CIPHER_SUITE: return "Bad cipher suite"; + case BR_ERR_BAD_COMPRESSION: return "Bad compression"; + case BR_ERR_BAD_FRAGLEN: return "Bad fragment length"; + case BR_ERR_BAD_SECRENEG: return "Bad secure renegotiation"; + case BR_ERR_EXTRA_EXTENSION: return "Extra extension"; + case BR_ERR_BAD_SNI: return "Bad SNI"; + case BR_ERR_BAD_HELLO_DONE: return "Bad HelloDone"; + case BR_ERR_LIMIT_EXCEEDED: return "Limit exceeded"; + case BR_ERR_BAD_FINISHED: return "Bad Finished message"; + case BR_ERR_RESUME_MISMATCH: return "Session resume mismatch"; + case BR_ERR_INVALID_ALGORITHM: return "Invalid algorithm"; + case BR_ERR_BAD_SIGNATURE: return "Bad signature"; + case BR_ERR_WRONG_KEY_USAGE: return "Wrong key usage"; + case BR_ERR_NO_CLIENT_AUTH: return "No client auth"; + case BR_ERR_IO: return "I/O error"; + default: + if(err >= 256 && err < 512) + return "Received fatal alert from server"; + if(err >= 512) + return "Sent fatal alert to server"; + return "Unknown SSL error"; + } +#endif +} + +static int Curl_bearssl_init(void) +{ +#if BEARSSL_XBOX_INTEGRATION + /* Initialize trust anchors from Xbox certificate store */ + if(!bearssl_trust_anchors_loaded) { + bearssl_xbox_init_trust_anchors(); + bearssl_xbox_session_init(); + bearssl_trust_anchors_loaded = 1; + } +#endif + return 1; +} + +static void Curl_bearssl_cleanup(void) +{ +#if BEARSSL_XBOX_INTEGRATION + if(bearssl_trust_anchors_loaded) { + bearssl_xbox_session_shutdown(); + bearssl_xbox_cleanup_trust_anchors(); + bearssl_trust_anchors_loaded = 0; + bearssl_trust_store_updated = 0; + } +#endif +} + +static size_t Curl_bearssl_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "BearSSL/0.6-Xbox"); +} + +static CURLcode Curl_bearssl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ + br_hmac_drbg_context rng; + br_prng_seeder seeder; + + (void)data; + + seeder = br_prng_seeder_system(NULL); + if(!seeder) { + return CURLE_SSL_CONNECT_ERROR; + } + + br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0); + if(!seeder(&rng.vtable)) { + return CURLE_SSL_CONNECT_ERROR; + } + + br_hmac_drbg_generate(&rng, entropy, length); + return CURLE_OK; +} + +static CURLcode +bearssl_connect_step1(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + br_x509_trust_anchor *trust_anchors = NULL; + size_t trust_anchor_count = 0; + int session_resume = 0; +#if BEARSSL_XBOX_INTEGRATION + br_ssl_session_parameters session_params; +#endif + + /* + * NOTE: BACKEND memory is pre-allocated by the vtls layer in url.c as part + * of a single contiguous block for all SSL contexts. We must NOT allocate + * or free it ourselves - that would corrupt the heap. + * + * See url.c:allocate_conn() which does: + * conn->ssl[0].backend = (void *)ssl; + * conn->ssl[1].backend = (void *)(ssl + sslsize); + * conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize); + * conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize); + */ + DEBUGASSERT(BACKEND != NULL); + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL step1: Using pre-allocated backend at %p, size=%u bytes\n", + (void*)BACKEND, (unsigned)sizeof(struct ssl_backend_data)); + OutputDebugStringA(dbg); + } +#endif + + /* Clear the backend structure for fresh initialization */ + memset(BACKEND, 0, sizeof(struct ssl_backend_data)); + + /* Store hostname for session caching */ + strncpy(BACKEND->hostname, hostname, sizeof(BACKEND->hostname) - 1); + BACKEND->hostname[sizeof(BACKEND->hostname) - 1] = '\0'; + BACKEND->session_resumed = 0; + +#if BEARSSL_XBOX_INTEGRATION + /* Auto-download cacert.pem on first connection if not on disk. + * Done here (not in Curl_bearssl_init) because XNet needs time + * after DHCP before TCP connects work reliably. */ + if(!bearssl_trust_store_updated) { + bearssl_trust_store_updated = 1; + bearssl_xbox_update_trust_store(); + } +#endif + + /* Check if certificate verification is disabled */ + if(!SSL_CONN_CONFIG(verifypeer)) { + /* + * No verification - use the "noanchor" validator that wraps br_x509_minimal + * but accepts all certificates. This leverages BearSSL's proven certificate + * parsing code while bypassing the trust validation. + */ + OutputDebugStringA("BearSSL: Certificate verification DISABLED - using noanchor validator\n"); + BACKEND->using_noanchor = 1; + +#ifdef _XBOX + { + char dbg[512]; + msnprintf(dbg, sizeof(dbg), + "BearSSL: BACKEND=%p, sizeof(ssl_backend_data)=%u\n", + (void*)BACKEND, (unsigned)sizeof(struct ssl_backend_data)); + OutputDebugStringA(dbg); + msnprintf(dbg, sizeof(dbg), + "BearSSL: sizeof(br_ssl_client_context)=%u\n", + (unsigned)sizeof(br_ssl_client_context)); + OutputDebugStringA(dbg); + msnprintf(dbg, sizeof(dbg), + "BearSSL: sizeof(br_x509_minimal_context)=%u\n", + (unsigned)sizeof(br_x509_minimal_context)); + OutputDebugStringA(dbg); + msnprintf(dbg, sizeof(dbg), + "BearSSL: &BACKEND->sc=%p, &BACKEND->xc_minimal=%p\n", + (void*)&BACKEND->sc, (void*)&BACKEND->xc_minimal); + OutputDebugStringA(dbg); + } +#endif + + OutputDebugStringA("BearSSL: Calling br_ssl_client_init_full...\n"); + + /* + * Initialize the SSL client with the minimal X509 validator. + * We pass NULL trust anchors - the minimal validator will fail with + * NOT_TRUSTED, but our noanchor wrapper overrides that to accept anyway. + */ + br_ssl_client_init_full(&BACKEND->sc, &BACKEND->xc_minimal, NULL, 0); + + OutputDebugStringA("BearSSL: br_ssl_client_init_full done\n"); + +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL: xc_minimal at %p, xc_minimal.vtable = %p\n", + (void*)&BACKEND->xc_minimal, + (void*)BACKEND->xc_minimal.vtable); + OutputDebugStringA(dbg); + } +#endif + + /* Set up the noanchor wrapper to point to the minimal validator */ + BACKEND->xc_noanchor.vtable = &br_x509_noanchor_vtable; + BACKEND->xc_noanchor.minimal = &BACKEND->xc_minimal; + + OutputDebugStringA("BearSSL: Setting X509 engine to noanchor wrapper...\n"); + +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL: xc_noanchor at %p, vtable=%p, minimal=%p\n", + (void*)&BACKEND->xc_noanchor, + (void*)BACKEND->xc_noanchor.vtable, + (void*)BACKEND->xc_noanchor.minimal); + OutputDebugStringA(dbg); + } +#endif + + /* Replace the X509 engine with our noanchor validator wrapper */ + br_ssl_engine_set_x509(&BACKEND->sc.eng, &BACKEND->xc_noanchor.vtable); + OutputDebugStringA("BearSSL: Noanchor X509 validator installed\n"); + } + else { +#if BEARSSL_XBOX_INTEGRATION + { + /* Check for CURLOPT_CAINFO or default Xbox CA path */ + const char *cafile = SSL_CONN_CONFIG(CAfile); + + /* If no explicit CA file, try the default Xbox TDATA path */ + if(!cafile || !cafile[0]) { + cafile = BEARSSL_XBOX_DEFAULT_CA_FILE; + } + + /* Try loading CA bundle from PEM file */ + if(bearssl_xbox_load_ca_file(cafile, + &BACKEND->file_anchors, &BACKEND->file_anchor_count) == 0) { + trust_anchors = BACKEND->file_anchors; + trust_anchor_count = BACKEND->file_anchor_count; + infof(data, "BearSSL: Loaded %zu trust anchors from %s\n", + trust_anchor_count, cafile); + } + + /* Fall back to compiled-in trust anchors */ + if(!trust_anchors) { + trust_anchors = bearssl_xbox_get_trust_anchors(); + trust_anchor_count = bearssl_xbox_get_trust_anchor_count(); + } + } + + if(!trust_anchors || trust_anchor_count == 0) { + failf(data, "BearSSL: No trust anchors available for certificate verification"); + return CURLE_SSL_CACERT_BADFILE; + } + infof(data, "BearSSL: Using %zu trust anchors for verification\n", + trust_anchor_count); +#else + /* No trust anchors available - cannot verify */ + failf(data, "BearSSL: Certificate verification requested but no trust anchors available"); + return CURLE_SSL_CACERT_BADFILE; +#endif + + BACKEND->using_noanchor = 0; + /* Initialize the BearSSL client context with trust anchors */ + br_ssl_client_init_full(&BACKEND->sc, &BACKEND->xc_minimal, + trust_anchors, trust_anchor_count); + +#ifdef _XBOX + /* Skip certificate date validation - Xbox clock is unreliable */ + br_x509_minimal_set_time_callback(&BACKEND->xc_minimal, + NULL, bearssl_xbox_time_check); +#endif + } + + OutputDebugStringA("BearSSL: Setting protocol versions...\n"); + + /* Set protocol versions based on CURLOPT_SSLVERSION */ + { + /* + * Default to TLS 1.2 minimum for security. + * TLS 1.0 and 1.1 are deprecated and have known vulnerabilities. + */ + int min_ver = BR_TLS12; + int max_ver = BR_TLS12; + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + /* Default: TLS 1.2 only (most compatible + secure) */ + min_ver = BR_TLS12; + break; + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + /* Allow TLS 1.0 if explicitly requested (legacy support) */ + min_ver = BR_TLS10; + break; + case CURL_SSLVERSION_TLSv1_1: + min_ver = BR_TLS11; + break; + case CURL_SSLVERSION_TLSv1_2: + min_ver = BR_TLS12; + break; + case CURL_SSLVERSION_TLSv1_3: + /* BearSSL doesn't support TLS 1.3 */ + failf(data, "BearSSL does not support TLS 1.3"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unsupported SSL version"); + return CURLE_SSL_CONNECT_ERROR; + } + + br_ssl_engine_set_versions(&BACKEND->sc.eng, min_ver, max_ver); + } + OutputDebugStringA("BearSSL: Protocol versions set\n"); + + /* Use secure cipher suites only */ + br_ssl_engine_set_suites(&BACKEND->sc.eng, + bearssl_secure_suites, BEARSSL_SECURE_SUITES_COUNT); + OutputDebugStringA("BearSSL: Cipher suites set\n"); + + /* + * Set ALPN (Application-Layer Protocol Negotiation) protocols. + * + * This tells the server we want to speak HTTP/1.1. Without ALPN, modern + * servers like Cloudflare may reset the connection after handshake because + * they don't know what protocol the client expects. + */ + br_ssl_engine_set_protocol_names(&BACKEND->sc.eng, + bearssl_alpn_protocols, + BEARSSL_ALPN_PROTOCOLS_COUNT); + OutputDebugStringA("BearSSL: ALPN protocols set (http/1.1)\n"); + + /* Set I/O buffer */ + br_ssl_engine_set_buffer(&BACKEND->sc.eng, BACKEND->iobuf, + sizeof(BACKEND->iobuf), 1); + OutputDebugStringA("BearSSL: I/O buffer set\n"); + +#if BEARSSL_XBOX_INTEGRATION + /* Try to resume previous session */ + if(bearssl_xbox_session_get(hostname, &session_params)) { + br_ssl_engine_set_session_parameters(&BACKEND->sc.eng, &session_params); + memcpy(BACKEND->resume_master_secret, session_params.master_secret, 48); + session_resume = 1; + infof(data, "BearSSL: Attempting session resumption for %s\n", hostname); + } +#endif + + OutputDebugStringA("BearSSL: Calling br_ssl_client_reset...\n"); + + /* Reset the client context for the new connection */ + br_ssl_client_reset(&BACKEND->sc, hostname, session_resume); + + OutputDebugStringA("BearSSL: br_ssl_client_reset done\n"); + +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL step1: hostname=%s, socket=%d, sockindex=%d\n", + hostname, (int)conn->sock[sockindex], sockindex); + OutputDebugStringA(dbg); + + /* Verify socket is valid */ + if(conn->sock[sockindex] == CURL_SOCKET_BAD) { + OutputDebugStringA("BearSSL step1: ERROR - socket is INVALID!\n"); + } + } +#endif + + OutputDebugStringA("BearSSL: Calling br_sslio_init...\n"); + + /* Initialize the I/O wrapper */ + br_sslio_init(&BACKEND->ioc, &BACKEND->sc.eng, + sock_read, &conn->sock[sockindex], + sock_write, &conn->sock[sockindex]); + + OutputDebugStringA("BearSSL: br_sslio_init done\n"); + + /* Note: BACKEND->active is set in step3 after handshake completes */ + connssl->connecting_state = ssl_connect_2; + + OutputDebugStringA("BearSSL step1: complete, moving to step2\n"); + return CURLE_OK; +} + +static CURLcode +bearssl_connect_step2(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned state; + int err; + + state = br_ssl_engine_current_state(&BACKEND->sc.eng); + +#ifdef _XBOX + { + static int step2_call_count = 0; + char dbg[256]; + step2_call_count++; + msnprintf(dbg, sizeof(dbg), + "BearSSL step2 [%d]: state=0x%x (CLOSED=%d SENDREC=%d RECVREC=%d SENDAPP=%d)\n", + step2_call_count, state, + (state & BR_SSL_CLOSED) ? 1 : 0, + (state & BR_SSL_SENDREC) ? 1 : 0, + (state & BR_SSL_RECVREC) ? 1 : 0, + (state & BR_SSL_SENDAPP) ? 1 : 0); + OutputDebugStringA(dbg); + } +#endif + + /* Check for errors */ + err = br_ssl_engine_last_error(&BACKEND->sc.eng); + if(err != BR_ERR_OK) { +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: engine error %d\n", err); + OutputDebugStringA(dbg); + } +#endif + failf(data, "BearSSL: %s (error %d)", bearssl_error_string(err), err); + return CURLE_SSL_CONNECT_ERROR; + } + + /* Check if handshake is complete */ + if(state & BR_SSL_SENDAPP) { + /* Handshake complete, application data can be sent */ + connssl->connecting_state = ssl_connect_3; + return CURLE_OK; + } + + /* Handshake still in progress */ + if(state & BR_SSL_SENDREC) { + /* Need to send data */ + int ret; + OutputDebugStringA("BearSSL step2: flushing send buffer...\n"); + ret = br_sslio_flush(&BACKEND->ioc); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: flush returned %d\n", ret); + OutputDebugStringA(dbg); + } +#endif + if(ret < 0) { + err = br_ssl_engine_last_error(&BACKEND->sc.eng); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: flush error, engine err=%d\n", err); + OutputDebugStringA(dbg); + } +#endif + if(err != BR_ERR_OK) { + failf(data, "BearSSL handshake: %s (error %d)", + bearssl_error_string(err), err); + return CURLE_SSL_CONNECT_ERROR; + } + } + } + + if(state & BR_SSL_RECVREC) { + /* Need to receive data - handled by sslio layer */ + unsigned char tmp[1]; + int ret; + OutputDebugStringA("BearSSL step2: attempting to receive...\n"); + ret = br_sslio_read(&BACKEND->ioc, tmp, 0); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: read returned %d\n", ret); + OutputDebugStringA(dbg); + } +#endif + if(ret < 0) { + err = br_ssl_engine_last_error(&BACKEND->sc.eng); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL step2: read error, engine err=%d\n", err); + OutputDebugStringA(dbg); + } +#endif + if(err != BR_ERR_OK && err != BR_ERR_IO) { + failf(data, "BearSSL handshake: %s (error %d)", + bearssl_error_string(err), err); + return CURLE_SSL_CONNECT_ERROR; + } + } + } + + /* Check state again */ + state = br_ssl_engine_current_state(&BACKEND->sc.eng); + if(state & BR_SSL_SENDAPP) { + connssl->connecting_state = ssl_connect_3; + return CURLE_OK; + } + + /* Still connecting */ + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static CURLcode +bearssl_connect_step3(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + br_ssl_session_parameters session_params; + unsigned version; + const char *version_str; + + /* Get negotiated TLS version */ + version = br_ssl_engine_get_version(&BACKEND->sc.eng); + switch(version) { + case BR_TLS10: version_str = "TLS 1.0"; break; + case BR_TLS11: version_str = "TLS 1.1"; break; + case BR_TLS12: version_str = "TLS 1.2"; break; + default: version_str = "Unknown"; break; + } + + /* Log ALPN negotiation result */ + { + const char *alpn_protocol; + alpn_protocol = br_ssl_engine_get_selected_protocol(&BACKEND->sc.eng); + if(alpn_protocol) { + infof(data, "BearSSL: ALPN negotiated protocol: %s\n", alpn_protocol); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL: ALPN selected: %s\n", alpn_protocol); + OutputDebugStringA(dbg); + } +#endif + } + else { + infof(data, "BearSSL: ALPN not negotiated (server may not support it)\n"); +#ifdef _XBOX + OutputDebugStringA("BearSSL: ALPN not negotiated by server\n"); +#endif + } + } + + /* Check if session was resumed by comparing master secrets. + * Both ID-based and ticket-based (RFC 5077) resumption reuse the + * original master secret; a full handshake always derives a new one. */ + br_ssl_engine_get_session_parameters(&BACKEND->sc.eng, &session_params); + if(memcmp(BACKEND->resume_master_secret, session_params.master_secret, + 48) == 0 + && session_params.master_secret[0] != 0) { + BACKEND->session_resumed = 1; + } + infof(data, "BearSSL: %s connection using %s\n", + BACKEND->session_resumed ? "Resumed" : "New", version_str); +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL: %s connection using %s\n", + BACKEND->session_resumed ? "Resumed" : "New", version_str); + OutputDebugStringA(dbg); + } +#endif + +#if BEARSSL_XBOX_INTEGRATION + /* Store session for future resumption. + * Store if we have a session ID or a session ticket (RFC 5077). */ + if(session_params.session_id_len > 0 + || session_params.session_ticket_len > 0) { + bearssl_xbox_session_store(BACKEND->hostname, &session_params); + } + + /* Copy captured leaf certificate hash from X.509 callback. + * On resumed sessions, no X.509 validation runs so the hash won't + * be available — this is expected and not an error. */ + if(BACKEND->using_noanchor && BACKEND->xc_noanchor.leaf_hash_valid) { + memcpy(BACKEND->leaf_cert_hash, BACKEND->xc_noanchor.leaf_hash, 32); + BACKEND->leaf_cert_hash_valid = 1; +#ifdef _XBOX + { + char dbg[256]; + msnprintf(dbg, sizeof(dbg), + "BearSSL step3: Leaf cert SHA-256: " + "%02X%02X%02X%02X %02X%02X%02X%02X " + "%02X%02X%02X%02X %02X%02X%02X%02X " + "%02X%02X%02X%02X %02X%02X%02X%02X " + "%02X%02X%02X%02X %02X%02X%02X%02X\n", + BACKEND->leaf_cert_hash[0], BACKEND->leaf_cert_hash[1], + BACKEND->leaf_cert_hash[2], BACKEND->leaf_cert_hash[3], + BACKEND->leaf_cert_hash[4], BACKEND->leaf_cert_hash[5], + BACKEND->leaf_cert_hash[6], BACKEND->leaf_cert_hash[7], + BACKEND->leaf_cert_hash[8], BACKEND->leaf_cert_hash[9], + BACKEND->leaf_cert_hash[10], BACKEND->leaf_cert_hash[11], + BACKEND->leaf_cert_hash[12], BACKEND->leaf_cert_hash[13], + BACKEND->leaf_cert_hash[14], BACKEND->leaf_cert_hash[15], + BACKEND->leaf_cert_hash[16], BACKEND->leaf_cert_hash[17], + BACKEND->leaf_cert_hash[18], BACKEND->leaf_cert_hash[19], + BACKEND->leaf_cert_hash[20], BACKEND->leaf_cert_hash[21], + BACKEND->leaf_cert_hash[22], BACKEND->leaf_cert_hash[23], + BACKEND->leaf_cert_hash[24], BACKEND->leaf_cert_hash[25], + BACKEND->leaf_cert_hash[26], BACKEND->leaf_cert_hash[27], + BACKEND->leaf_cert_hash[28], BACKEND->leaf_cert_hash[29], + BACKEND->leaf_cert_hash[30], BACKEND->leaf_cert_hash[31]); + OutputDebugStringA(dbg); + } +#endif + } + else if(BACKEND->session_resumed) { +#ifdef _XBOX + OutputDebugStringA("BearSSL step3: Leaf cert hash not available (resumed session)\n"); +#endif + } +#endif + + /* Connection is now established - mark SSL as active for proper cleanup */ + /* + * CRITICAL: Register our SSL send/recv functions with libcurl. + * + * libcurl uses conn->recv[sockindex] and conn->send[sockindex] for all + * data transfer. If we don't set these to our BearSSL functions, libcurl + * will send raw unencrypted data over the TLS connection, causing the + * server to reset the connection. + * + * This was the root cause of the "connection reset after handshake" bug. + */ + conn->recv[sockindex] = bearssl_recv; + conn->send[sockindex] = bearssl_send; + +#ifdef _XBOX + OutputDebugStringA("BearSSL: Registered send/recv handlers with libcurl\n"); +#endif + + BACKEND->active = 1; + connssl->connecting_state = ssl_connect_done; + connssl->state = ssl_connection_complete; + + return CURLE_OK; +} + +static CURLcode +bearssl_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* Check if already connected */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + timeout_ms = Curl_timeleft(data, NULL, TRUE); + if(timeout_ms < 0) { + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + result = bearssl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state) { + timeout_ms = Curl_timeleft(data, NULL, TRUE); + if(timeout_ms < 0) { + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* Check socket readiness */ + what = Curl_socket_check(sockfd, CURL_SOCKET_BAD, sockfd, + nonblocking ? 0 : timeout_ms); + if(what < 0) { + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + + result = bearssl_connect_step2(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_3 == connssl->connecting_state) { + result = bearssl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + *done = TRUE; + } + else { + *done = FALSE; + } + + return CURLE_OK; +} + +static CURLcode +Curl_bearssl_connect_blocking(struct connectdata *conn, int sockindex) +{ + bool done = FALSE; + CURLcode result; + + result = bearssl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + return CURLE_OK; +} + +static CURLcode +Curl_bearssl_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + return bearssl_connect_common(conn, sockindex, TRUE, done); +} + +static void Curl_bearssl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL close: sockindex=%d, state=%d, backend=%p\n", + sockindex, (int)connssl->state, (void*)BACKEND); + OutputDebugStringA(dbg); + } +#endif + + /* Free per-connection file-loaded trust anchors even if handshake didn't + * complete (e.g. step1 failed after loading CAs but before connecting). + * Must happen before the early-return guard below. */ +#if BEARSSL_XBOX_INTEGRATION + if(BACKEND && BACKEND->file_anchors) { + bearssl_xbox_free_loaded_anchors(BACKEND->file_anchors, + BACKEND->file_anchor_count); + BACKEND->file_anchors = NULL; + BACKEND->file_anchor_count = 0; + } +#endif + + /* Only cleanup SSL state if it was actually initialized */ + if(connssl->state == ssl_connection_none) + return; + + if(BACKEND) { + if(BACKEND->active) { + /* + * Attempt graceful TLS close only if the connection is still healthy. + * br_sslio_close() sends a close_notify alert, which calls sock_write(). + * If the socket is dead, sock_write() fails and BearSSL's I/O state + * becomes inconsistent, causing heap corruption. Guard against this by + * checking io_error (set by bearssl_send/recv on failure), the engine + * error code, and the engine closed flag. + */ + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + unsigned state = br_ssl_engine_current_state(&BACKEND->sc.eng); + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL close: io_error=%d, err=%d, state=0x%x\n", + BACKEND->io_error, err, state); + OutputDebugStringA(dbg); + } +#endif + + if(!BACKEND->io_error && err == BR_ERR_OK && !(state & BR_SSL_CLOSED)) { + br_sslio_close(&BACKEND->ioc); + } + BACKEND->active = 0; + } + /* + * NOTE: Do NOT free BACKEND! The vtls layer allocates all backend memory + * as a single block in url.c:allocate_conn(). Freeing BACKEND here would + * corrupt the heap because it's an offset into a larger allocation. + * + * Just clear the backend data to prepare for potential reuse. + */ +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL: Clearing backend at %p (NOT freeing - vtls manages memory)\n", + (void*)BACKEND); + OutputDebugStringA(dbg); + } +#endif + + /* file_anchors already freed above (before early-return guard) */ + + /* Clear backend data but do NOT free (vtls owns the memory) */ + memset(BACKEND, 0, sizeof(struct ssl_backend_data)); + } + + /* Reset state */ + connssl->state = ssl_connection_none; + connssl->connecting_state = ssl_connect_1; +} + +static void Curl_bearssl_close_all(struct Curl_easy *data) +{ + (void)data; +} + +static int Curl_bearssl_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + +#ifdef _XBOX + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), + "BearSSL shutdown: sockindex=%d, state=%d, backend=%p\n", + sockindex, (int)connssl->state, (void*)BACKEND); + OutputDebugStringA(dbg); + } +#endif + + /* Only shutdown if SSL was actually initialized */ + if(connssl->state == ssl_connection_none) + return 0; + + /* Check BACKEND exists before accessing it */ + if(!BACKEND) + return 0; + + if(BACKEND->active) { + /* + * Only attempt graceful TLS close if no I/O errors occurred. + * Avoid trying to send close_notify on a dead socket. + */ + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + unsigned state = br_ssl_engine_current_state(&BACKEND->sc.eng); + + if(!BACKEND->io_error && err == BR_ERR_OK && !(state & BR_SSL_CLOSED)) { + br_sslio_close(&BACKEND->ioc); + } + BACKEND->active = 0; + } + + return 0; +} + +static ssize_t bearssl_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int ret; + int flush_ret; + + /* Defensive check - BACKEND must be valid */ + if(!BACKEND || !BACKEND->active) { + OutputDebugStringA("bearssl_send: BACKEND invalid, returning error\n"); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL send: len=%u, active=%d\n", + (unsigned)len, BACKEND->active); + OutputDebugStringA(dbg); + } +#endif + + ret = br_sslio_write(&BACKEND->ioc, mem, len); + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + unsigned state = br_ssl_engine_current_state(&BACKEND->sc.eng); + msnprintf(dbg, sizeof(dbg), "BearSSL send: write returned %d, err=%d, state=0x%x\n", + ret, err, state); + OutputDebugStringA(dbg); + } +#endif + + if(ret < 0) { + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + /* Mark that we've had an I/O error - skip graceful close later */ + BACKEND->io_error = 1; + if(err == BR_ERR_OK || err == BR_ERR_IO) { + *curlcode = CURLE_AGAIN; + } + else { + *curlcode = CURLE_SEND_ERROR; + } + return -1; + } + + /* Flush the data to ensure it's sent immediately */ + flush_ret = br_sslio_flush(&BACKEND->ioc); + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL send: flush returned %d\n", flush_ret); + OutputDebugStringA(dbg); + } +#endif + + if(flush_ret < 0) { + BACKEND->io_error = 1; + } + + return (ssize_t)ret; +} + +static ssize_t bearssl_recv(struct connectdata *conn, int sockindex, + char *buf, size_t buffersize, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int ret; + + /* Defensive check - BACKEND must be valid */ + if(!BACKEND || !BACKEND->active) { + OutputDebugStringA("bearssl_recv: BACKEND invalid, returning error\n"); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL recv: buffersize=%u, active=%d\n", + (unsigned)buffersize, BACKEND->active); + OutputDebugStringA(dbg); + } +#endif + + ret = br_sslio_read(&BACKEND->ioc, buf, buffersize); + +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + unsigned state = br_ssl_engine_current_state(&BACKEND->sc.eng); + msnprintf(dbg, sizeof(dbg), "BearSSL recv: read returned %d, err=%d, state=0x%x\n", + ret, err, state); + OutputDebugStringA(dbg); + } +#endif + + if(ret < 0) { + int err = br_ssl_engine_last_error(&BACKEND->sc.eng); + /* Mark that we've had an I/O error - skip graceful close later */ + BACKEND->io_error = 1; +#ifdef BEARSSL_VERBOSE_DEBUG + { + char dbg[128]; + msnprintf(dbg, sizeof(dbg), "BearSSL recv: ERROR - setting io_error=1, err=%d\n", err); + OutputDebugStringA(dbg); + } +#endif + if(err == BR_ERR_OK || err == BR_ERR_IO) { + *curlcode = CURLE_AGAIN; + } + else { + *curlcode = CURLE_RECV_ERROR; + } + return -1; + } + + return (ssize_t)ret; +} + +static bool Curl_bearssl_data_pending(const struct connectdata *conn, + int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned state; + + /* Check if SSL was initialized before accessing BACKEND */ + if(connssl->state == ssl_connection_none) + return FALSE; + + if(!BACKEND || !BACKEND->active) + return FALSE; + + state = br_ssl_engine_current_state(&BACKEND->sc.eng); + return (state & BR_SSL_RECVAPP) ? TRUE : FALSE; +} + +static int Curl_bearssl_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + int err; + + /* Check if SSL was initialized before accessing BACKEND */ + if(connssl->state == ssl_connection_none) + return 0; + + if(!BACKEND || !BACKEND->active) + return 0; + + err = br_ssl_engine_last_error(&BACKEND->sc.eng); + return (err == BR_ERR_OK) ? 1 : 0; +} + +static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) +{ + (void)info; + /* Check if SSL was initialized before accessing BACKEND */ + if(connssl->state == ssl_connection_none) + return NULL; + return BACKEND ? &BACKEND->sc : NULL; +} + +static void Curl_bearssl_session_free(void *ptr) +{ + (void)ptr; + /* BearSSL session handling is different; no dynamic session objects */ +} + +const struct Curl_ssl Curl_ssl_bearssl = { + { CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */ + SSLSUPP_CA_PATH | + SSLSUPP_SSL_CTX, /* supports */ + sizeof(struct ssl_backend_data), + + Curl_bearssl_init, /* init */ + Curl_bearssl_cleanup, /* cleanup */ + Curl_bearssl_version, /* version */ + Curl_bearssl_check_cxn, /* check_cxn */ + Curl_bearssl_shutdown, /* shutdown */ + Curl_bearssl_data_pending, /* data_pending */ + Curl_bearssl_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_bearssl_connect_blocking, /* connect_blocking */ + Curl_bearssl_connect_nonblocking, /* connect_nonblocking */ + Curl_bearssl_get_internals, /* get_internals */ + Curl_bearssl_close, /* close_one */ + Curl_bearssl_close_all, /* close_all */ + Curl_bearssl_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + NULL /* sha256sum */ +}; + +#endif /* USE_BEARSSL */ diff --git a/libcurl/lib/vtls/bearssl.h b/libcurl/lib/vtls/bearssl.h new file mode 100644 index 0000000..a008d58 --- /dev/null +++ b/libcurl/lib/vtls/bearssl.h @@ -0,0 +1,21 @@ +#ifndef HEADER_CURL_BEARSSL_H +#define HEADER_CURL_BEARSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * BearSSL TLS backend for libcurl + * Designed for Xbox (Visual Studio 2003 / C89 compatible) + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_BEARSSL + +extern const struct Curl_ssl Curl_ssl_bearssl; + +#endif /* USE_BEARSSL */ +#endif /* HEADER_CURL_BEARSSL_H */ diff --git a/libcurl/lib/vtls/bearssl_ssl.h b/libcurl/lib/vtls/bearssl_ssl.h new file mode 100644 index 0000000..a5911f8 --- /dev/null +++ b/libcurl/lib/vtls/bearssl_ssl.h @@ -0,0 +1,4306 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * 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. + */ + +#ifndef BR_BEARSSL_SSL_H__ +#define BR_BEARSSL_SSL_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" +#include "bearssl_hmac.h" +#include "bearssl_prf.h" +#include "bearssl_rand.h" +#include "bearssl_x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ssl.h + * + * # SSL + * + * For an overview of the SSL/TLS API, see [the BearSSL Web + * site](https://www.bearssl.org/api1.html). + * + * The `BR_TLS_*` constants correspond to the standard cipher suites and + * their values in the [IANA + * registry](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4). + * + * The `BR_ALERT_*` constants are for standard TLS alert messages. When + * a fatal alert message is sent of received, then the SSL engine context + * status is set to the sum of that alert value (an integer in the 0..255 + * range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert, + * `BR_ERR_RECV_FATAL_ALERT` for a received alert). + */ + +/** \brief Optimal input buffer size. */ +#define BR_SSL_BUFSIZE_INPUT (16384 + 325) + +/** \brief Optimal output buffer size. */ +#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85) + +/** \brief Optimal buffer size for monodirectional engine + (shared input/output buffer). */ +#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT + +/** \brief Optimal buffer size for bidirectional engine + (single buffer split into two separate input/output buffers). */ +#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT) + +/* + * Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1 + * and TLS 1.2). Note that though there is a constant for SSL 3.0, that + * protocol version is not actually supported. + */ + +/** \brief Protocol version: SSL 3.0 (unsupported). */ +#define BR_SSL30 0x0300 +/** \brief Protocol version: TLS 1.0. */ +#define BR_TLS10 0x0301 +/** \brief Protocol version: TLS 1.1. */ +#define BR_TLS11 0x0302 +/** \brief Protocol version: TLS 1.2. */ +#define BR_TLS12 0x0303 + +/* + * Error constants. They are used to report the reason why a context has + * been marked as failed. + * + * Implementation note: SSL-level error codes should be in the 1..31 + * range. The 32..63 range is for certificate decoding and validation + * errors. Received fatal alerts imply an error code in the 256..511 range. + */ + +/** \brief SSL status: no error so far (0). */ +#define BR_ERR_OK 0 + +/** \brief SSL status: caller-provided parameter is incorrect. */ +#define BR_ERR_BAD_PARAM 1 + +/** \brief SSL status: operation requested by the caller cannot be applied + with the current context state (e.g. reading data while outgoing data + is waiting to be sent). */ +#define BR_ERR_BAD_STATE 2 + +/** \brief SSL status: incoming protocol or record version is unsupported. */ +#define BR_ERR_UNSUPPORTED_VERSION 3 + +/** \brief SSL status: incoming record version does not match the expected + version. */ +#define BR_ERR_BAD_VERSION 4 + +/** \brief SSL status: incoming record length is invalid. */ +#define BR_ERR_BAD_LENGTH 5 + +/** \brief SSL status: incoming record is too large to be processed, or + buffer is too small for the handshake message to send. */ +#define BR_ERR_TOO_LARGE 6 + +/** \brief SSL status: decryption found an invalid padding, or the record + MAC is not correct. */ +#define BR_ERR_BAD_MAC 7 + +/** \brief SSL status: no initial entropy was provided, and none can be + obtained from the OS. */ +#define BR_ERR_NO_RANDOM 8 + +/** \brief SSL status: incoming record type is unknown. */ +#define BR_ERR_UNKNOWN_TYPE 9 + +/** \brief SSL status: incoming record or message has wrong type with + regards to the current engine state. */ +#define BR_ERR_UNEXPECTED 10 + +/** \brief SSL status: ChangeCipherSpec message from the peer has invalid + contents. */ +#define BR_ERR_BAD_CCS 12 + +/** \brief SSL status: alert message from the peer has invalid contents + (odd length). */ +#define BR_ERR_BAD_ALERT 13 + +/** \brief SSL status: incoming handshake message decoding failed. */ +#define BR_ERR_BAD_HANDSHAKE 14 + +/** \brief SSL status: ServerHello contains a session ID which is larger + than 32 bytes. */ +#define BR_ERR_OVERSIZED_ID 15 + +/** \brief SSL status: server wants to use a cipher suite that we did + not claim to support. This is also reported if we tried to advertise + a cipher suite that we do not support. */ +#define BR_ERR_BAD_CIPHER_SUITE 16 + +/** \brief SSL status: server wants to use a compression that we did not + claim to support. */ +#define BR_ERR_BAD_COMPRESSION 17 + +/** \brief SSL status: server's max fragment length does not match + client's. */ +#define BR_ERR_BAD_FRAGLEN 18 + +/** \brief SSL status: secure renegotiation failed. */ +#define BR_ERR_BAD_SECRENEG 19 + +/** \brief SSL status: server sent an extension type that we did not + announce, or used the same extension type several times in a single + ServerHello. */ +#define BR_ERR_EXTRA_EXTENSION 20 + +/** \brief SSL status: invalid Server Name Indication contents (when + used by the server, this extension shall be empty). */ +#define BR_ERR_BAD_SNI 21 + +/** \brief SSL status: invalid ServerHelloDone from the server (length + is not 0). */ +#define BR_ERR_BAD_HELLO_DONE 22 + +/** \brief SSL status: internal limit exceeded (e.g. server's public key + is too large). */ +#define BR_ERR_LIMIT_EXCEEDED 23 + +/** \brief SSL status: Finished message from peer does not match the + expected value. */ +#define BR_ERR_BAD_FINISHED 24 + +/** \brief SSL status: session resumption attempt with distinct version + or cipher suite. */ +#define BR_ERR_RESUME_MISMATCH 25 + +/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve, + signature algorithm, hash function). */ +#define BR_ERR_INVALID_ALGORITHM 26 + +/** \brief SSL status: invalid signature (on ServerKeyExchange from + server, or in CertificateVerify from client). */ +#define BR_ERR_BAD_SIGNATURE 27 + +/** \brief SSL status: peer's public key does not have the proper type + or is not allowed for requested operation. */ +#define BR_ERR_WRONG_KEY_USAGE 28 + +/** \brief SSL status: client did not send a certificate upon request, + or the client certificate could not be validated. */ +#define BR_ERR_NO_CLIENT_AUTH 29 + +/** \brief SSL status: I/O error or premature close on underlying + transport stream. This error code is set only by the simplified + I/O API ("br_sslio_*"). */ +#define BR_ERR_IO 31 + +/** \brief SSL status: base value for a received fatal alert. + + When a fatal alert is received from the peer, the alert value + is added to this constant. */ +#define BR_ERR_RECV_FATAL_ALERT 256 + +/** \brief SSL status: base value for a sent fatal alert. + + When a fatal alert is sent to the peer, the alert value is added + to this constant. */ +#define BR_ERR_SEND_FATAL_ALERT 512 + +/* ===================================================================== */ + +/** + * \brief Decryption engine for SSL. + * + * When processing incoming records, the SSL engine will use a decryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The decryption engine is responsible for applying decryption, verifying + * MAC, and keeping track of the record sequence number. + */ +typedef struct br_sslrec_in_class_ br_sslrec_in_class; +struct br_sslrec_in_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Test validity of the incoming record length. + * + * This function returns 1 if the announced length for an + * incoming record is valid, 0 otherwise, + * + * \param ctx decryption engine context. + * \param record_len incoming record length. + * \return 1 of a valid length, 0 otherwise. + */ + int (*check_length)(const br_sslrec_in_class *const *ctx, + size_t record_len); + + /** + * \brief Decrypt the incoming record. + * + * This function may assume that the record length is valid + * (it has been previously tested with `check_length()`). + * Decryption is done in place; `*len` is updated with the + * cleartext length, and the address of the first plaintext + * byte is returned. If the record is correct but empty, then + * `*len` is set to 0 and a non-`NULL` pointer is returned. + * + * On decryption/MAC error, `NULL` is returned. + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param payload address of encrypted payload. + * \param len pointer to payload length (updated). + * \return pointer to plaintext, or `NULL` on error. + */ + unsigned char *(*decrypt)(const br_sslrec_in_class **ctx, + int record_type, unsigned version, + void *payload, size_t *len); +}; + +/** + * \brief Encryption engine for SSL. + * + * When building outgoing records, the SSL engine will use an encryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The encryption engine is responsible for applying encryption and MAC, + * and keeping track of the record sequence number. + */ +typedef struct br_sslrec_out_class_ br_sslrec_out_class; +struct br_sslrec_out_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Compute maximum plaintext sizes and offsets. + * + * When this function is called, the `*start` and `*end` + * values contain offsets designating the free area in the + * outgoing buffer for plaintext data; that free area is + * preceded by a 5-byte space which will receive the record + * header. + * + * The `max_plaintext()` function is responsible for adjusting + * both `*start` and `*end` to make room for any record-specific + * header, MAC, padding, and possible split. + * + * \param ctx encryption engine context. + * \param start pointer to start of plaintext offset (updated). + * \param end pointer to start of plaintext offset (updated). + */ + void (*max_plaintext)(const br_sslrec_out_class *const *ctx, + size_t *start, size_t *end); + + /** + * \brief Perform record encryption. + * + * This function encrypts the record. The plaintext address and + * length are provided. Returned value is the start of the + * encrypted record (or sequence of records, if a split was + * performed), _including_ the 5-byte header, and `*len` is + * adjusted to the total size of the record(s), there again + * including the header(s). + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param plaintext address of plaintext. + * \param len pointer to plaintext length (updated). + * \return pointer to start of built record. + */ + unsigned char *(*encrypt)(const br_sslrec_out_class **ctx, + int record_type, unsigned version, + void *plaintext, size_t *len); +}; + +/** + * \brief Context for a no-encryption engine. + * + * The no-encryption engine processes outgoing records during the initial + * handshake, before encryption is applied. + */ +typedef struct { + /** \brief No-encryption engine vtable. */ + const br_sslrec_out_class *vtable; +} br_sslrec_out_clear_context; + +/** \brief Static, constant vtable for the no-encryption engine. */ +extern const br_sslrec_out_class br_sslrec_out_clear_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CBC mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class; +struct br_sslrec_in_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC decryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_in_cbc_class **ctx, + const br_block_cbcdec_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for CBC mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class; +struct br_sslrec_out_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC encryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_out_cbc_class **ctx, + const br_block_cbcenc_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Context structure for decrypting incoming records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_in_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcdec_class *vtable; + br_aes_gen_cbcdec_keys aes; + br_des_gen_cbcdec_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_in_cbc_context; + +/** + * \brief Static, constant vtable for record decryption with CBC. + */ +extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable; + +/** + * \brief Context structure for encrypting outgoing records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_out_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcenc_class *vtable; + br_aes_gen_cbcenc_keys aes; + br_des_gen_cbcenc_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_out_cbc_context; + +/** + * \brief Static, constant vtable for record encryption with CBC. + */ +extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for GCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class; +struct br_sslrec_in_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_in_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for GCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class; +struct br_sslrec_out_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_out_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Context structure for processing records with GCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_gcm_class *in; + const br_sslrec_out_gcm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctr_class *vtable; + br_aes_gen_ctr_keys aes; + } bc; + br_ghash gh; + unsigned char iv[4]; + unsigned char h[16]; +#endif +} br_sslrec_gcm_context; + +/** + * \brief Static, constant vtable for record decryption with GCM. + */ +extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable; + +/** + * \brief Static, constant vtable for record encryption with GCM. + */ +extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class; +struct br_sslrec_in_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_in_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Record encryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class; +struct br_sslrec_out_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_out_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Context structure for processing records with ChaCha20+Poly1305. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_chapol_class *in; + const br_sslrec_out_chapol_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + unsigned char key[32]; + unsigned char iv[12]; + br_chacha20_run ichacha; + br_poly1305_run ipoly; +#endif +} br_sslrec_chapol_context; + +/** + * \brief Static, constant vtable for record decryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable; + +/** + * \brief Static, constant vtable for record encryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class; +struct br_sslrec_in_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_in_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Record encryption engine class, for CCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class; +struct br_sslrec_out_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_out_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Context structure for processing records with CCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_ccm_class *in; + const br_sslrec_out_ccm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctrcbc_class *vtable; + br_aes_gen_ctrcbc_keys aes; + } bc; + unsigned char iv[4]; + size_t tag_len; +#endif +} br_sslrec_ccm_context; + +/** + * \brief Static, constant vtable for record decryption with CCM. + */ +extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable; + +/** + * \brief Static, constant vtable for record encryption with CCM. + */ +extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable; + +/* ===================================================================== */ + +/** + * \brief Type for session parameters, to be saved for session resumption. + */ +typedef struct { + /** \brief Session ID buffer. */ + unsigned char session_id[32]; + /** \brief Session ID length (in bytes, at most 32). */ + unsigned char session_id_len; + /** \brief Protocol version. */ + uint16_t version; + /** \brief Cipher suite. */ + uint16_t cipher_suite; + /** \brief Master secret. */ + unsigned char master_secret[48]; + /** \brief Session ticket (RFC 5077), opaque blob from server. */ + unsigned char session_ticket[1024]; + /** \brief Session ticket length (0 if no ticket). */ + uint16_t session_ticket_len; +} br_ssl_session_parameters; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Maximum number of cipher suites supported by a client or server. + */ +#define BR_MAX_CIPHER_SUITES 48 +#endif + +/** + * \brief Context structure for SSL engine. + * + * This strucuture is common to the client and server; both the client + * context (`br_ssl_client_context`) and the server context + * (`br_ssl_server_context`) include a `br_ssl_engine_context` as their + * first field. + * + * The engine context manages records, including alerts, closures, and + * transitions to new encryption/MAC algorithms. Processing of handshake + * records is delegated to externally provided code. This structure + * should not be used directly. + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* + * The error code. When non-zero, then the state is "failed" and + * no I/O may occur until reset. + */ + int err; + + /* + * Configured I/O buffers. They are either disjoint, or identical. + */ + unsigned char *ibuf, *obuf; + size_t ibuf_len, obuf_len; + + /* + * Maximum fragment length applies to outgoing records; incoming + * records can be processed as long as they fit in the input + * buffer. It is guaranteed that incoming records at least as big + * as max_frag_len can be processed. + */ + uint16_t max_frag_len; + unsigned char log_max_frag_len; + unsigned char peer_log_max_frag_len; + + /* + * Buffering management registers. + */ + size_t ixa, ixb, ixc; + size_t oxa, oxb, oxc; + unsigned char iomode; + unsigned char incrypt; + + /* + * Shutdown flag: when set to non-zero, incoming record bytes + * will not be accepted anymore. This is used after a close_notify + * has been received: afterwards, the engine no longer claims that + * it could receive bytes from the transport medium. + */ + unsigned char shutdown_recv; + + /* + * 'record_type_in' is set to the incoming record type when the + * record header has been received. + * 'record_type_out' is used to make the next outgoing record + * header when it is ready to go. + */ + unsigned char record_type_in, record_type_out; + + /* + * When a record is received, its version is extracted: + * -- if 'version_in' is 0, then it is set to the received version; + * -- otherwise, if the received version is not identical to + * the 'version_in' contents, then a failure is reported. + * + * This implements the SSL requirement that all records shall + * use the negotiated protocol version, once decided (in the + * ServerHello). It is up to the handshake handler to adjust this + * field when necessary. + */ + uint16_t version_in; + + /* + * 'version_out' is used when the next outgoing record is ready + * to go. + */ + uint16_t version_out; + + /* + * Record handler contexts. + */ + union { + const br_sslrec_in_class *vtable; + br_sslrec_in_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } in; + union { + const br_sslrec_out_class *vtable; + br_sslrec_out_clear_context clear; + br_sslrec_out_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } out; + + /* + * The "application data" flag. Value: + * 0 handshake is in process, no application data acceptable + * 1 application data can be sent and received + * 2 closing, no application data can be sent, but some + * can still be received (and discarded) + */ + unsigned char application_data; + + /* + * Context RNG. + * + * rng_init_done is initially 0. It is set to 1 when the + * basic structure of the RNG is set, and 2 when some + * entropy has been pushed in. The value 2 marks the RNG + * as "properly seeded". + * + * rng_os_rand_done is initially 0. It is set to 1 when + * some seeding from the OS or hardware has been attempted. + */ + br_hmac_drbg_context rng; + int rng_init_done; + int rng_os_rand_done; + + /* + * Supported minimum and maximum versions, and cipher suites. + */ + uint16_t version_min; + uint16_t version_max; + uint16_t suites_buf[BR_MAX_CIPHER_SUITES]; + unsigned char suites_num; + + /* + * For clients, the server name to send as a SNI extension. For + * servers, the name received in the SNI extension (if any). + */ + char server_name[256]; + + /* + * "Security parameters". These are filled by the handshake + * handler, and used when switching encryption state. + */ + unsigned char client_random[32]; + unsigned char server_random[32]; + br_ssl_session_parameters session; + + /* + * ECDHE elements: curve and point from the peer. The server also + * uses that buffer for the point to send to the client. + */ + unsigned char ecdhe_curve; + unsigned char ecdhe_point[133]; + unsigned char ecdhe_point_len; + + /* + * Secure renegotiation (RFC 5746): 'reneg' can be: + * 0 first handshake (server support is not known) + * 1 peer does not support secure renegotiation + * 2 peer supports secure renegotiation + * + * The saved_finished buffer contains the client and the + * server "Finished" values from the last handshake, in + * that order (12 bytes each). + */ + unsigned char reneg; + unsigned char saved_finished[24]; + + /* + * Session ticket (RFC 5077) support flag. Set to 1 when the + * server confirms ticket support in its ServerHello extensions. + */ + unsigned char session_ticket_ok; + + /* + * Behavioural flags. + */ + uint32_t flags; + + /* + * Context variables for the handshake processor. The 'pad' must + * be large enough to accommodate an RSA-encrypted pre-master + * secret, or an RSA signature; since we want to support up to + * RSA-4096, this means at least 512 bytes. (Other pad usages + * require its length to be at least 256.) + */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + unsigned char pad[512]; + unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out; + size_t hlen_in, hlen_out; + void (*hsrun)(void *ctx); + + /* + * The 'action' value communicates OOB information between the + * engine and the handshake processor. + * + * From the engine: + * 0 invocation triggered by I/O + * 1 invocation triggered by explicit close + * 2 invocation triggered by explicit renegotiation + */ + unsigned char action; + + /* + * State for alert messages. Value is either 0, or the value of + * the alert level byte (level is either 1 for warning, or 2 for + * fatal; we convert all other values to 'fatal'). + */ + unsigned char alert; + + /* + * Closure flags. This flag is set when a close_notify has been + * received from the peer. + */ + unsigned char close_received; + + /* + * Multi-hasher for the handshake messages. The handshake handler + * is responsible for resetting it when appropriate. + */ + br_multihash_context mhash; + + /* + * Pointer to the X.509 engine. The engine is supposed to be + * already initialized. It is used to validate the peer's + * certificate. + */ + const br_x509_class **x509ctx; + + /* + * Certificate chain to send. This is used by both client and + * server, when they send their respective Certificate messages. + * If chain_len is 0, then chain may be NULL. + */ + const br_x509_certificate *chain; + size_t chain_len; + const unsigned char *cert_cur; + size_t cert_len; + + /* + * List of supported protocol names (ALPN extension). If unset, + * (number of names is 0), then: + * - the client sends no ALPN extension; + * - the server ignores any incoming ALPN extension. + * + * Otherwise: + * - the client sends an ALPN extension with all the names; + * - the server selects the first protocol in its list that + * the client also supports, or fails (fatal alert 120) + * if the client sends an ALPN extension and there is no + * match. + * + * The 'selected_protocol' field contains 1+n if the matching + * name has index n in the list (the value is 0 if no match was + * performed, e.g. the peer did not send an ALPN extension). + */ + const char **protocol_names; + uint16_t protocol_names_num; + uint16_t selected_protocol; + + /* + * Pointers to implementations; left to NULL for unsupported + * functions. For the raw hash functions, implementations are + * referenced from the multihasher (mhash field). + */ + br_tls_prf_impl prf10; + br_tls_prf_impl prf_sha256; + br_tls_prf_impl prf_sha384; + const br_block_cbcenc_class *iaes_cbcenc; + const br_block_cbcdec_class *iaes_cbcdec; + const br_block_ctr_class *iaes_ctr; + const br_block_ctrcbc_class *iaes_ctrcbc; + const br_block_cbcenc_class *ides_cbcenc; + const br_block_cbcdec_class *ides_cbcdec; + br_ghash ighash; + br_chacha20_run ichacha; + br_poly1305_run ipoly; + const br_sslrec_in_cbc_class *icbc_in; + const br_sslrec_out_cbc_class *icbc_out; + const br_sslrec_in_gcm_class *igcm_in; + const br_sslrec_out_gcm_class *igcm_out; + const br_sslrec_in_chapol_class *ichapol_in; + const br_sslrec_out_chapol_class *ichapol_out; + const br_sslrec_in_ccm_class *iccm_in; + const br_sslrec_out_ccm_class *iccm_out; + const br_ec_impl *iec; + br_rsa_pkcs1_vrfy irsavrfy; + br_ecdsa_vrfy iecdsa; +#endif +} br_ssl_engine_context; + +/** + * \brief Get currently defined engine behavioural flags. + * + * \param cc SSL engine context. + * \return the flags. + */ +static __inline uint32_t +br_ssl_engine_get_flags(br_ssl_engine_context *cc) +{ + return cc->flags; +} + +/** + * \brief Set all engine behavioural flags. + * + * \param cc SSL engine context. + * \param flags new value for all flags. + */ +static __inline void +br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags = flags; +} + +/** + * \brief Set some engine behavioural flags. + * + * The flags set in the `flags` parameter are set in the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags additional set flags. + */ +static __inline void +br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags |= flags; +} + +/** + * \brief Clear some engine behavioural flags. + * + * The flags set in the `flags` parameter are cleared from the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags flags to remove. + */ +static __inline void +br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags &= ~flags; +} + +/** + * \brief Behavioural flag: enforce server preferences. + * + * If this flag is set, then the server will enforce its own cipher suite + * preference order; otherwise, it follows the client preferences. + */ +#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0) + +/** + * \brief Behavioural flag: disable renegotiation. + * + * If this flag is set, then renegotiations are rejected unconditionally: + * they won't be honoured if asked for programmatically, and requests from + * the peer are rejected. + */ +#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1) + +/** + * \brief Behavioural flag: tolerate lack of client authentication. + * + * If this flag is set in a server and the server requests a client + * certificate, but the authentication fails (the client does not send + * a certificate, or the client's certificate chain cannot be validated), + * then the connection keeps on. Without this flag, a failed client + * authentication terminates the connection. + * + * Notes: + * + * - If the client's certificate can be validated and its public key is + * supported, then a wrong signature value terminates the connection + * regardless of that flag. + * + * - If using full-static ECDH, then a failure to validate the client's + * certificate prevents the handshake from succeeding. + */ +#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2) + +/** + * \brief Behavioural flag: fail on application protocol mismatch. + * + * The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301)) + * allows the client to send a list of application protocol names, and + * the server to select one. A mismatch is one of the following occurrences: + * + * - On the client: the client sends a list of names, the server + * responds with a protocol name which is _not_ part of the list of + * names sent by the client. + * + * - On the server: the client sends a list of names, and the server + * is also configured with a list of names, but there is no common + * protocol name between the two lists. + * + * Normal behaviour in case of mismatch is to report no matching name + * (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on. + * If the flag is set, then a mismatch implies a protocol failure (if + * the mismatch is detected by the server, it will send a fatal alert). + * + * Note: even with this flag, `br_ssl_engine_get_selected_protocol()` + * may still return `NULL` if the client or the server does not send an + * ALPN extension at all. + */ +#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3) + +/** + * \brief Set the minimum and maximum supported protocol versions. + * + * The two provided versions MUST be supported by the implementation + * (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower + * than `version_min`. + * + * \param cc SSL engine context. + * \param version_min minimum supported TLS version. + * \param version_max maximum supported TLS version. + */ +static __inline void +br_ssl_engine_set_versions(br_ssl_engine_context *cc, + unsigned version_min, unsigned version_max) +{ + cc->version_min = (uint16_t)version_min; + cc->version_max = (uint16_t)version_max; +} + +/** + * \brief Set the list of cipher suites advertised by this context. + * + * The provided array is copied into the context. It is the caller + * responsibility to ensure that all provided suites will be supported + * by the context. The engine context has enough room to receive _all_ + * suites supported by the implementation. The provided array MUST NOT + * contain duplicates. + * + * If the engine is for a client, the "signaling" pseudo-cipher suite + * `TLS_FALLBACK_SCSV` can be added at the end of the list, if the + * calling application is performing a voluntary downgrade (voluntary + * downgrades are not recommended, but if such a downgrade is done, then + * adding the fallback pseudo-suite is a good idea). + * + * \param cc SSL engine context. + * \param suites cipher suites. + * \param suites_num number of cipher suites. + */ +void br_ssl_engine_set_suites(br_ssl_engine_context *cc, + const uint16_t *suites, size_t suites_num); + +/** + * \brief Set the X.509 engine. + * + * The caller shall ensure that the X.509 engine is properly initialised. + * + * \param cc SSL engine context. + * \param x509ctx X.509 certificate validation context. + */ +static __inline void +br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx) +{ + cc->x509ctx = x509ctx; +} + +/** + * \brief Set the supported protocol names. + * + * Protocol names are part of the ALPN extension ([RFC + * 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a + * character string, containing no more than 255 characters (256 with the + * terminating zero). When names are set, then: + * + * - The client will send an ALPN extension, containing the names. If + * the server responds with an ALPN extension, the client will verify + * that the response contains one of its name, and report that name + * through `br_ssl_engine_get_selected_protocol()`. + * + * - The server will parse incoming ALPN extension (from clients), and + * try to find a common protocol; if none is found, the connection + * is aborted with a fatal alert. On match, a response ALPN extension + * is sent, and name is reported through + * `br_ssl_engine_get_selected_protocol()`. + * + * The provided array is linked in, and must remain valid while the + * connection is live. + * + * Names MUST NOT be empty. Names MUST NOT be longer than 255 characters + * (excluding the terminating 0). + * + * \param ctx SSL engine context. + * \param names list of protocol names (zero-terminated). + * \param num number of protocol names (MUST be 1 or more). + */ +static __inline void +br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx, + const char **names, size_t num) +{ + ctx->protocol_names = names; + ctx->protocol_names_num = (uint16_t)num; +} + +/** + * \brief Get the selected protocol. + * + * If this context was initialised with a non-empty list of protocol + * names, and both client and server sent ALPN extensions during the + * handshake, and a common name was found, then that name is returned. + * Otherwise, `NULL` is returned. + * + * The returned pointer is one of the pointers provided to the context + * with `br_ssl_engine_set_protocol_names()`. + * + * \return the selected protocol, or `NULL`. + */ +static __inline const char * +br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx) +{ + unsigned k; + + k = ctx->selected_protocol; + return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1]; +} + +/** + * \brief Set a hash function implementation (by ID). + * + * Hash functions set with this call will be used for SSL/TLS specific + * usages, not X.509 certificate validation. Only "standard" hash functions + * may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl` + * is `NULL`, then the hash function support is removed, not added. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \param impl hash function implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_hash(br_ssl_engine_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Get a hash function implementation (by ID). + * + * This function retrieves a hash function implementation which was + * set with `br_ssl_engine_set_hash()`. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \return the hash function implementation (or `NULL`). + */ +static __inline const br_hash_class * +br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id) +{ + return br_multihash_getimpl(&ctx->mhash, id); +} + +/** + * \brief Set the PRF implementation (for TLS 1.0 and 1.1). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the PRF used in TLS 1.0 and 1.1. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf10 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-256 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-256 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha256 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-384 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-384 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha384 = impl; +} + +/** + * \brief Set the AES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc AES/CBC encryption implementation (or `NULL`). + * \param impl_dec AES/CBC decryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->iaes_cbcenc = impl_enc; + cc->iaes_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" AES/CBC implementations. + * + * This function configures in the engine the AES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR encryption/decryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc, + const br_block_ctr_class *impl) +{ + cc->iaes_ctr = impl; +} + +/** + * \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH). + * + * This function configures in the engine the AES/CTR and GHASH + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for GCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc); + +/** + * \brief Set the DES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc DES/CBC encryption implementation (or `NULL`). + * \param impl_dec DES/CBC decryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->ides_cbcenc = impl_enc; + cc->ides_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" DES/CBC implementations. + * + * This function configures in the engine the DES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the GHASH implementation (used in GCM mode). + * + * \param cc SSL engine context. + * \param impl GHASH implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl) +{ + cc->ighash = impl; +} + +/** + * \brief Set the ChaCha20 implementation. + * + * \param cc SSL engine context. + * \param ichacha ChaCha20 implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_chacha20(br_ssl_engine_context *cc, + br_chacha20_run ichacha) +{ + cc->ichacha = ichacha; +} + +/** + * \brief Set the Poly1305 implementation. + * + * \param cc SSL engine context. + * \param ipoly Poly1305 implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_poly1305(br_ssl_engine_context *cc, + br_poly1305_run ipoly) +{ + cc->ipoly = ipoly; +} + +/** + * \brief Set the "default" ChaCha20 and Poly1305 implementations. + * + * This function configures in the engine the ChaCha20 and Poly1305 + * implementations that should provide best runtime performance on the + * local system, while still being safe (in particular, constant-time). + * It also sets the handlers for ChaCha20+Poly1305 records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR+CBC implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc, + const br_block_ctrcbc_class *impl) +{ + cc->iaes_ctrcbc = impl; +} + +/** + * \brief Set the "default" implementations for AES/CCM. + * + * This function configures in the engine the AES/CTR+CBC + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for CCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc); + +/** + * \brief Set the record encryption and decryption engines for CBC + HMAC. + * + * \param cc SSL engine context. + * \param impl_in record CBC decryption implementation (or `NULL`). + * \param impl_out record CBC encryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_cbc(br_ssl_engine_context *cc, + const br_sslrec_in_cbc_class *impl_in, + const br_sslrec_out_cbc_class *impl_out) +{ + cc->icbc_in = impl_in; + cc->icbc_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for GCM. + * + * \param cc SSL engine context. + * \param impl_in record GCM decryption implementation (or `NULL`). + * \param impl_out record GCM encryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_gcm(br_ssl_engine_context *cc, + const br_sslrec_in_gcm_class *impl_in, + const br_sslrec_out_gcm_class *impl_out) +{ + cc->igcm_in = impl_in; + cc->igcm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for CCM. + * + * \param cc SSL engine context. + * \param impl_in record CCM decryption implementation (or `NULL`). + * \param impl_out record CCM encryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_ccm(br_ssl_engine_context *cc, + const br_sslrec_in_ccm_class *impl_in, + const br_sslrec_out_ccm_class *impl_out) +{ + cc->iccm_in = impl_in; + cc->iccm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for + * ChaCha20+Poly1305. + * + * \param cc SSL engine context. + * \param impl_in record ChaCha20 decryption implementation (or `NULL`). + * \param impl_out record ChaCha20 encryption implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_chapol(br_ssl_engine_context *cc, + const br_sslrec_in_chapol_class *impl_in, + const br_sslrec_out_chapol_class *impl_out) +{ + cc->ichapol_in = impl_in; + cc->ichapol_out = impl_out; +} + +/** + * \brief Set the EC implementation. + * + * The elliptic curve implementation will be used for ECDH and ECDHE + * cipher suites, and for ECDSA support. + * + * \param cc SSL engine context. + * \param iec EC implementation (or `NULL`). + */ +static __inline void +br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec) +{ + cc->iec = iec; +} + +/** + * \brief Set the "default" EC implementation. + * + * This function sets the elliptic curve implementation for ECDH and + * ECDHE cipher suites, and for ECDSA support. It selects the fastest + * implementation on the current system. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc); + +/** + * \brief Get the EC implementation configured in the provided engine. + * + * \param cc SSL engine context. + * \return the EC implementation. + */ +static __inline const br_ec_impl * +br_ssl_engine_get_ec(br_ssl_engine_context *cc) +{ + return cc->iec; +} + +/** + * \brief Set the RSA signature verification implementation. + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, and that certificate contains a RSA key). + * + * \param cc SSL engine context. + * \param irsavrfy RSA signature verification implementation. + */ +static __inline void +br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy) +{ + cc->irsavrfy = irsavrfy; +} + +/** + * \brief Set the "default" RSA implementation (signature verification). + * + * This function sets the RSA implementation (signature verification) + * to the fastest implementation available on the current platform. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc); + +/** + * \brief Get the RSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the RSA signature verification implementation. + */ +static __inline br_rsa_pkcs1_vrfy +br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc) +{ + return cc->irsavrfy; +} + +/* + * \brief Set the ECDSA implementation (signature verification). + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, that certificate contains an EC key, + * and full-static ECDH is not used). + * + * The ECDSA implementation will use the EC core implementation configured + * in the engine context. + * + * \param cc client context. + * \param iecdsa ECDSA verification implementation. + */ +static __inline void +br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa) +{ + cc->iecdsa = iecdsa; +} + +/** + * \brief Set the "default" ECDSA implementation (signature verification). + * + * This function sets the ECDSA implementation (signature verification) + * to the fastest implementation available on the current platform. This + * call also sets the elliptic curve implementation itself, there again + * to the fastest EC implementation available. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc); + +/** + * \brief Get the ECDSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the ECDSA signature verification implementation. + */ +static __inline br_ecdsa_vrfy +br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc) +{ + return cc->iecdsa; +} + +/** + * \brief Set the I/O buffer for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * The provided buffer will be used as long as the engine context is + * used. The caller is responsible for keeping it available. + * + * If `bidi` is 0, then the engine will operate in half-duplex mode + * (it won't be able to send data while there is unprocessed incoming + * data in the buffer, and it won't be able to receive data while there + * is unsent data in the buffer). The optimal buffer size in half-duplex + * mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra + * bytes are ignored. If the buffer is smaller, then this limits the + * capacity of the engine to support all allowed record sizes. + * + * If `bidi` is 1, then the engine will split the buffer into two + * parts, for separate handling of outgoing and incoming data. This + * enables full-duplex processing, but requires more RAM. The optimal + * buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the + * buffer is larger, then extra bytes are ignored. If the buffer is + * smaller, then the split will favour the incoming part, so that + * interoperability is maximised. + * + * \param cc SSL engine context + * \param iobuf I/O buffer. + * \param iobuf_len I/O buffer length (in bytes). + * \param bidi non-zero for full-duplex mode. + */ +void br_ssl_engine_set_buffer(br_ssl_engine_context *cc, + void *iobuf, size_t iobuf_len, int bidi); + +/** + * \brief Set the I/O buffers for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * This function is similar to `br_ssl_engine_set_buffer()`, except + * that it enforces full-duplex mode, and the two I/O buffers are + * provided as separate chunks. + * + * The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT` + * evaluate to the optimal (maximum) sizes for the input and output + * buffer, respectively. + * + * \param cc SSL engine context + * \param ibuf input buffer. + * \param ibuf_len input buffer length (in bytes). + * \param obuf output buffer. + * \param obuf_len output buffer length (in bytes). + */ +void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc, + void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len); + +/** + * \brief Inject some "initial entropy" in the context. + * + * This entropy will be added to what can be obtained from the + * underlying operating system, if that OS is supported. + * + * This function may be called several times; all injected entropy chunks + * are cumulatively mixed. + * + * If entropy gathering from the OS is supported and compiled in, then this + * step is optional. Otherwise, it is mandatory to inject randomness, and + * the caller MUST take care to push (as one or several successive calls) + * enough entropy to achieve cryptographic resistance (at least 80 bits, + * preferably 128 or more). The engine will report an error if no entropy + * was provided and none can be obtained from the OS. + * + * Take care that this function cannot assess the cryptographic quality of + * the provided bytes. + * + * In all generality, "entropy" must here be considered to mean "that + * which the attacker cannot predict". If your OS/architecture does not + * have a suitable source of randomness, then you can make do with the + * combination of a large enough secret value (possibly a copy of an + * asymmetric private key that you also store on the system) AND a + * non-repeating value (e.g. current time, provided that the local clock + * cannot be reset or altered by the attacker). + * + * \param cc SSL engine context. + * \param data extra entropy to inject. + * \param len length of the extra data (in bytes). + */ +void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc, + const void *data, size_t len); + +/** + * \brief Get the "server name" in this engine. + * + * For clients, this is the name provided with `br_ssl_client_reset()`; + * for servers, this is the name received from the client as part of the + * ClientHello message. If there is no such name (e.g. the client did + * not send an SNI extension) then the returned string is empty + * (returned pointer points to a byte of value 0). + * + * The returned pointer refers to a buffer inside the context, which may + * be overwritten as part of normal SSL activity (even within the same + * connection, if a renegotiation occurs). + * + * \param cc SSL engine context. + * \return the server name (possibly empty). + */ +static __inline const char * +br_ssl_engine_get_server_name(const br_ssl_engine_context *cc) +{ + return cc->server_name; +} + +/** + * \brief Get the protocol version. + * + * This function returns the protocol version that is used by the + * engine. That value is set after sending (for a server) or receiving + * (for a client) the ServerHello message. + * + * \param cc SSL engine context. + * \return the protocol version. + */ +static __inline unsigned +br_ssl_engine_get_version(const br_ssl_engine_context *cc) +{ + return cc->session.version; +} + +/** + * \brief Get a copy of the session parameters. + * + * The session parameters are filled during the handshake, so this + * function shall not be called before completion of the handshake. + * The initial handshake is completed when the context first allows + * application data to be injected. + * + * This function copies the current session parameters into the provided + * structure. Beware that the session parameters include the master + * secret, which is sensitive data, to handle with great care. + * + * \param cc SSL engine context. + * \param pp destination structure for the session parameters. + */ +static __inline void +br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc, + br_ssl_session_parameters *pp) +{ + memcpy(pp, &cc->session, sizeof *pp); +} + +/** + * \brief Set the session parameters to the provided values. + * + * This function is meant to be used in the client, before doing a new + * handshake; a session resumption will be attempted with these + * parameters. In the server, this function has no effect. + * + * \param cc SSL engine context. + * \param pp source structure for the session parameters. + */ +static __inline void +br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc, + const br_ssl_session_parameters *pp) +{ + memcpy(&cc->session, pp, sizeof *pp); +} + +/** + * \brief Get identifier for the curve used for key exchange. + * + * If the cipher suite uses ECDHE, then this function returns the + * identifier for the curve used for transient parameters. This is + * defined during the course of the handshake, when the ServerKeyExchange + * is sent (on the server) or received (on the client). If the + * cipher suite does not use ECDHE (e.g. static ECDH, or RSA key + * exchange), then this value is indeterminate. + * + * @param cc SSL engine context. + * @return the ECDHE curve identifier. + */ +static __inline int +br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc) +{ + return cc->ecdhe_curve; +} + +/** + * \brief Get the current engine state. + * + * An SSL engine (client or server) has, at any time, a state which is + * the combination of zero, one or more of these flags: + * + * - `BR_SSL_CLOSED` + * + * Engine is finished, no more I/O (until next reset). + * + * - `BR_SSL_SENDREC` + * + * Engine has some bytes to send to the peer. + * + * - `BR_SSL_RECVREC` + * + * Engine expects some bytes from the peer. + * + * - `BR_SSL_SENDAPP` + * + * Engine may receive application data to send (or flush). + * + * - `BR_SSL_RECVAPP` + * + * Engine has obtained some application data from the peer, + * that should be read by the caller. + * + * If no flag at all is set (state value is 0), then the engine is not + * fully initialised yet. + * + * The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag + * is set. To distinguish between a normal closure and an error, use + * `br_ssl_engine_last_error()`. + * + * Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually + * exclusive: the input buffer, at any point, either accumulates + * plaintext data, or contains an assembled record that is being sent. + * Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive. + * This may change in a future library version. + * + * \param cc SSL engine context. + * \return the current engine state. + */ +unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc); + +/** \brief SSL engine state: closed or failed. */ +#define BR_SSL_CLOSED 0x0001 +/** \brief SSL engine state: record data is ready to be sent to the peer. */ +#define BR_SSL_SENDREC 0x0002 +/** \brief SSL engine state: engine may receive records from the peer. */ +#define BR_SSL_RECVREC 0x0004 +/** \brief SSL engine state: engine may accept application data to send. */ +#define BR_SSL_SENDAPP 0x0008 +/** \brief SSL engine state: engine has received application data. */ +#define BR_SSL_RECVAPP 0x0010 + +/** + * \brief Get the engine error indicator. + * + * The error indicator is `BR_ERR_OK` (0) if no error was encountered + * since the last call to `br_ssl_client_reset()` or + * `br_ssl_server_reset()`. Other status values are "sticky": they + * remain set, and prevent all I/O activity, until cleared. Only the + * reset calls clear the error indicator. + * + * \param cc SSL engine context. + * \return 0, or a non-zero error code. + */ +static __inline int +br_ssl_engine_last_error(const br_ssl_engine_context *cc) +{ + return cc->err; +} + +/* + * There are four I/O operations, each identified by a symbolic name: + * + * sendapp inject application data in the engine + * recvapp retrieving application data from the engine + * sendrec sending records on the transport medium + * recvrec receiving records from the transport medium + * + * Terminology works thus: in a layered model where the SSL engine sits + * between the application and the network, "send" designates operations + * where bytes flow from application to network, and "recv" for the + * reverse operation. Application data (the plaintext that is to be + * conveyed through SSL) is "app", while encrypted records are "rec". + * Note that from the SSL engine point of view, "sendapp" and "recvrec" + * designate bytes that enter the engine ("inject" operation), while + * "recvapp" and "sendrec" designate bytes that exit the engine + * ("extract" operation). + * + * For the operation 'xxx', two functions are defined: + * + * br_ssl_engine_xxx_buf + * Returns a pointer and length to the buffer to use for that + * operation. '*len' is set to the number of bytes that may be read + * from the buffer (extract operation) or written to the buffer + * (inject operation). If no byte may be exchanged for that operation + * at that point, then '*len' is set to zero, and NULL is returned. + * The engine state is unmodified by this call. + * + * br_ssl_engine_xxx_ack + * Informs the engine that 'len' bytes have been read from the buffer + * (extract operation) or written to the buffer (inject operation). + * The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed + * that which was obtained from a preceding br_ssl_engine_xxx_buf() + * call. + */ + +/** + * \brief Get buffer for application data to send. + * + * If the engine is ready to accept application data to send to the + * peer, then this call returns a pointer to the buffer where such + * data shall be written, and its length is written in `*len`. + * Otherwise, `*len` is set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data output buffer length, or 0. + * \return the application data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new application data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_sendapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for received application data. + * + * If the engine has received application data from the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data input buffer length, or 0. + * \return the application data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some received application data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_recvapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for record data to send. + * + * If the engine has prepared some records to send to the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data output buffer length, or 0. + * \return the record data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some sent record data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_sendrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for incoming records. + * + * If the engine is ready to accept records from the peer, then this + * call returns a pointer to the buffer where such data shall be + * written, and its length is written in `*len`. Otherwise, `*len` is + * set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data input buffer length, or 0. + * \return the record data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new record data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_recvrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Flush buffered application data. + * + * If some application data has been buffered in the engine, then wrap + * it into a record and mark it for sending. If no application data has + * been buffered but the engine would be ready to accept some, AND the + * `force` parameter is non-zero, then an empty record is assembled and + * marked for sending. In all other cases, this function does nothing. + * + * Empty records are technically legal, but not all existing SSL/TLS + * implementations support them. Empty records can be useful as a + * transparent "keep-alive" mechanism to maintain some low-level + * network activity. + * + * \param cc SSL engine context. + * \param force non-zero to force sending an empty record. + */ +void br_ssl_engine_flush(br_ssl_engine_context *cc, int force); + +/** + * \brief Initiate a closure. + * + * If, at that point, the context is open and in ready state, then a + * `close_notify` alert is assembled and marked for sending; this + * triggers the closure protocol. Otherwise, no such alert is assembled. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_close(br_ssl_engine_context *cc); + +/** + * \brief Initiate a renegotiation. + * + * If the engine is failed or closed, or if the peer is known not to + * support secure renegotiation (RFC 5746), or if renegotiations have + * been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there + * is buffered incoming application data, then this function returns 0 + * and nothing else happens. + * + * Otherwise, this function returns 1, and a renegotiation attempt is + * triggered (if a handshake is already ongoing at that point, then + * no new handshake is triggered). + * + * \param cc SSL engine context. + * \return 1 on success, 0 on error. + */ +int br_ssl_engine_renegotiate(br_ssl_engine_context *cc); + +/** + * \brief Export key material from a connected SSL engine (RFC 5705). + * + * This calls compute a secret key of arbitrary length from the master + * secret of a connected SSL engine. If the provided context is not + * currently in "application data" state (initial handshake is not + * finished, another handshake is ongoing, or the connection failed or + * was closed), then this function returns 0. Otherwise, a secret key of + * length `len` bytes is computed and written in the buffer pointed to + * by `dst`, and 1 is returned. + * + * The computed key follows the specification described in RFC 5705. + * That RFC includes two key computations, with and without a "context + * value". If `context` is `NULL`, then the variant without context is + * used; otherwise, the `context_len` bytes located at the address + * pointed to by `context` are used in the computation. Note that it + * is possible to have a "with context" key with a context length of + * zero bytes, by setting `context` to a non-`NULL` value but + * `context_len` to 0. + * + * When context bytes are used, the context length MUST NOT exceed + * 65535 bytes. + * + * \param cc SSL engine context. + * \param dst destination buffer for exported key. + * \param len exported key length (in bytes). + * \param label disambiguation label. + * \param context context value (or `NULL`). + * \param context_len context length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ssl_key_export(br_ssl_engine_context *cc, + void *dst, size_t len, const char *label, + const void *context, size_t context_len); + +/* + * Pre-declaration for the SSL client context. + */ +typedef struct br_ssl_client_context_ br_ssl_client_context; + +/** + * \brief Type for the client certificate, if requested by the server. + */ +typedef struct { + /** + * \brief Authentication type. + * + * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA` + * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange). + */ + int auth_type; + + /** + * \brief Hash function for computing the CertificateVerify. + * + * This is the symbolic identifier for the hash function that + * will be used to produce the hash of handshake messages, to + * be signed into the CertificateVerify. For full static ECDH + * (client and server certificates are both EC in the same + * curve, and static ECDH is used), this value is set to -1. + * + * Take care that with TLS 1.0 and 1.1, that value MUST match + * the protocol requirements: value must be 0 (MD5+SHA-1) for + * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only + * TLS 1.2 allows for other hash functions. + */ + int hash_id; + + /** + * \brief Certificate chain to send to the server. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The client + * code does not try to decode these elements. If there is no + * chain to send to the server, then this pointer shall be + * set to `NULL`. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + * + * If there is no chain to send to the server, then this value + * shall be set to 0. + */ + size_t chain_len; + +} br_ssl_client_certificate; + +/* + * Note: the constants below for signatures match the TLS constants. + */ + +/** \brief Client authentication type: static ECDH. */ +#define BR_AUTH_ECDH 0 +/** \brief Client authentication type: RSA signature. */ +#define BR_AUTH_RSA 1 +/** \brief Client authentication type: ECDSA signature. */ +#define BR_AUTH_ECDSA 3 + +/** + * \brief Class type for a certificate handler (client side). + * + * A certificate handler selects a client certificate chain to send to + * the server, upon explicit request from that server. It receives + * the list of trust anchor DN from the server, and supported types + * of certificates and signatures, and returns the chain to use. It + * is also invoked to perform the corresponding private key operation + * (a signature, or an ECDH computation). + * + * The SSL client engine will first push the trust anchor DN with + * `start_name_list()`, `start_name()`, `append_name()`, `end_name()` + * and `end_name_list()`. Then it will call `choose()`, to select the + * actual chain (and signature/hash algorithms). Finally, it will call + * either `do_sign()` or `do_keyx()`, depending on the algorithm choices. + */ +typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class; +struct br_ssl_client_certificate_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Begin reception of a list of trust anchor names. This + * is called while parsing the incoming CertificateRequest. + * + * \param pctx certificate handler context. + */ + void (*start_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Begin reception of a new trust anchor name. + * + * The total encoded name length is provided; it is less than + * 65535 bytes. + * + * \param pctx certificate handler context. + * \param len encoded name length (in bytes). + */ + void (*start_name)(const br_ssl_client_certificate_class **pctx, + size_t len); + + /** + * \brief Receive some more bytes for the current trust anchor name. + * + * The provided reference (`data`) points to a transient buffer + * they may be reused as soon as this function returns. The chunk + * length (`len`) is never zero. + * + * \param pctx certificate handler context. + * \param data anchor name chunk. + * \param len anchor name chunk length (in bytes). + */ + void (*append_name)(const br_ssl_client_certificate_class **pctx, + const unsigned char *data, size_t len); + + /** + * \brief End current trust anchor name. + * + * This function is called when all the encoded anchor name data + * has been provided. + * + * \param pctx certificate handler context. + */ + void (*end_name)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief End list of trust anchor names. + * + * This function is called when all the anchor names in the + * CertificateRequest message have been obtained. + * + * \param pctx certificate handler context. + */ + void (*end_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Select client certificate and algorithms. + * + * This callback function shall fill the provided `choices` + * structure with the selected algorithms and certificate chain. + * The `hash_id`, `chain` and `chain_len` fields must be set. If + * the client cannot or does not wish to send a certificate, + * then it shall set `chain` to `NULL` and `chain_len` to 0. + * + * The `auth_types` parameter describes the authentication types, + * signature algorithms and hash functions that are supported by + * both the client context and the server, and compatible with + * the current protocol version. This is a bit field with the + * following contents: + * + * - If RSA signatures with hash function x are supported, then + * bit x is set. + * + * - If ECDSA signatures with hash function x are supported, + * then bit 8+x is set. + * + * - If static ECDH is supported, with a RSA-signed certificate, + * then bit 16 is set. + * + * - If static ECDH is supported, with an ECDSA-signed certificate, + * then bit 17 is set. + * + * Notes: + * + * - When using TLS 1.0 or 1.1, the hash function for RSA + * signatures is always the special MD5+SHA-1 (id 0), and the + * hash function for ECDSA signatures is always SHA-1 (id 2). + * + * - When using TLS 1.2, the list of hash functions is trimmed + * down to include only hash functions that the client context + * can support. The actual server list can be obtained with + * `br_ssl_client_get_server_hashes()`; that list may be used + * to select the certificate chain to send to the server. + * + * \param pctx certificate handler context. + * \param cc SSL client context. + * \param auth_types supported authentication types and algorithms. + * \param choices destination structure for the policy choices. + */ + void (*choose)(const br_ssl_client_certificate_class **pctx, + const br_ssl_client_context *cc, uint32_t auth_types, + br_ssl_client_certificate *choices); + + /** + * \brief Perform key exchange (client part). + * + * This callback is invoked in case of a full static ECDH key + * exchange: + * + * - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`; + * + * - the server requests a client certificate; + * + * - the client has, and sends, a client certificate that + * uses an EC key in the same curve as the server's key, + * and chooses static ECDH (the `hash_id` field in the choice + * structure was set to -1). + * + * In that situation, this callback is invoked to compute the + * client-side ECDH: the provided `data` (of length `*len` bytes) + * is the server's public key point (as decoded from its + * certificate), and the client shall multiply that point with + * its own private key, and write back the X coordinate of the + * resulting point in the same buffer, starting at offset 0. + * The `*len` value shall be modified to designate the actual + * length of the X coordinate. + * + * The callback must uphold the following: + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx certificate handler context. + * \param data server public key point. + * \param len public key point length / X coordinate length. + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (client authentication). + * + * This callback is invoked when a client certificate was sent, + * and static ECDH is not used. It shall compute a signature, + * using the client's private key, over the provided hash value + * (which is the hash of all previous handshake messages). + * + * On input, the hash value to sign is in `data`, of size + * `hv_len`; the involved hash function is identified by + * `hash_id`. The signature shall be computed and written + * back into `data`; the total size of that buffer is `len` + * bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * For RSA signatures, the `hash_id` may be 0, in which case + * this is the special header-less signature specified in TLS 1.0 + * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1 + * v1.5 signatures shall be computed. + * + * For ECDSA signatures, the signature value shall use the ASN.1 + * based encoding. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx certificate handler context. + * \param hash_id hash function identifier. + * \param hv_len hash value length (in bytes). + * \param data input/output buffer (hash value, then signature). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_client_certificate_class **pctx, + int hash_id, size_t hv_len, unsigned char *data, size_t len); +}; + +/** + * \brief A single-chain RSA client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_client_certificate_rsa_context; + +/** + * \brief A single-chain EC client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * This handler may support both static ECDH, and ECDSA signatures + * (either usage may be selectively disabled). + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_client_certificate_ec_context; + +/** + * \brief Context structure for a SSL client. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_client_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Minimum ClientHello length; padding with an extension (RFC + * 7685) is added if necessary to match at least that length. + * Such padding is nominally unnecessary, but it has been used + * to work around some server implementation bugs. + */ + uint16_t min_clienthello_len; + + /* + * Bit field for algoithms (hash + signature) supported by the + * server when requesting a client certificate. + */ + uint32_t hashes; + + /* + * Server's public key curve. + */ + int server_curve; + + /* + * Context for certificate handler. + */ + const br_ssl_client_certificate_class **client_auth_vtable; + + /* + * Client authentication type. + */ + unsigned char auth_type; + + /* + * Hash function to use for the client signature. This is 0xFF + * if static ECDH is used. + */ + unsigned char hash_id; + + /* + * For the core certificate handlers, thus avoiding (in most + * cases) the need for an externally provided policy context. + */ + union { + const br_ssl_client_certificate_class *vtable; + br_ssl_client_certificate_rsa_context single_rsa; + br_ssl_client_certificate_ec_context single_ec; + } client_auth; + + /* + * Implementations. + */ + br_rsa_public irsapub; +#endif +}; + +/** + * \brief Get the hash functions and signature algorithms supported by + * the server. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc client context. + * \return the server-supported hash functions and signature algorithms. + */ +static __inline uint32_t +br_ssl_client_get_server_hashes(const br_ssl_client_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the server key curve. + * + * This function returns the ID for the curve used by the server's public + * key. This is set when the server's certificate chain is processed; + * this value is 0 if the server's key is not an EC key. + * + * \return the server's public key curve ID, or 0. + */ +static __inline int +br_ssl_client_get_server_curve(const br_ssl_client_context *cc) +{ + return cc->server_curve; +} + +/* + * Each br_ssl_client_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full all supported versions and suites; constant-time implementations + * TODO: add other profiles + */ + +/** + * \brief SSL client profile: full. + * + * This function initialises the provided SSL client context with + * all supported algorithms and cipher suites. It also initialises + * a companion X.509 validation engine with all supported algorithms, + * and the provided trust anchors; the X.509 engine will be used by + * the client context to validate the server's certificate. + * + * \param cc client context to initialise. + * \param xc X.509 validation context to initialise. + * \param trust_anchors trust anchors to use. + * \param trust_anchors_num number of trust anchors. + */ +void br_ssl_client_init_full(br_ssl_client_context *cc, + br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Clear the complete contents of a SSL client context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc client context to clear. + */ +void br_ssl_client_zero(br_ssl_client_context *cc); + +/** + * \brief Set an externally provided client certificate handler context. + * + * The handler's methods are invoked when the server requests a client + * certificate. + * + * \param cc client context. + * \param pctx certificate handler context (pointer to its vtable field). + */ +static __inline void +br_ssl_client_set_client_certificate(br_ssl_client_context *cc, + const br_ssl_client_certificate_class **pctx) +{ + cc->client_auth_vtable = pctx; +} + +/** + * \brief Set the RSA public-key operations implementation. + * + * This will be used to encrypt the pre-master secret with the server's + * RSA public key (RSA-encryption cipher suites only). + * + * \param cc client context. + * \param irsapub RSA public-key encryption implementation. + */ +static __inline void +br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub) +{ + cc->irsapub = irsapub; +} + +/** + * \brief Set the "default" RSA implementation for public-key operations. + * + * This sets the RSA implementation in the client context (for encrypting + * the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest + * available on the current platform. + * + * \param cc client context. + */ +void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc); + +/** + * \brief Set the minimum ClientHello length (RFC 7685 padding). + * + * If this value is set and the ClientHello would be shorter, then + * the Pad ClientHello extension will be added with enough padding bytes + * to reach the target size. Because of the extension header, the resulting + * size will sometimes be slightly more than `len` bytes if the target + * size cannot be exactly met. + * + * The target length relates to the _contents_ of the ClientHello, not + * counting its 4-byte header. For instance, if `len` is set to 512, + * then the padding will bring the ClientHello size to 516 bytes with its + * header, and 521 bytes when counting the 5-byte record header. + * + * \param cc client context. + * \param len minimum ClientHello length (in bytes). + */ +static __inline void +br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len) +{ + cc->min_clienthello_len = len; +} + +/** + * \brief Prepare or reset a client context for a new connection. + * + * The `server_name` parameter is used to fill the SNI extension; the + * X.509 "minimal" engine will also match that name against the server + * names included in the server's certificate. If the parameter is + * `NULL` then no SNI extension will be sent, and the X.509 "minimal" + * engine (if used for server certificate validation) will not check + * presence of any specific name in the received certificate. + * + * Therefore, setting the `server_name` to `NULL` shall be reserved + * to cases where alternate or additional methods are used to ascertain + * that the right server public key is used (e.g. a "known key" model). + * + * If `resume_session` is non-zero and the context was previously used + * then the session parameters may be reused (depending on whether the + * server previously sent a non-empty session ID, and accepts the session + * resumption). The session parameters for session resumption can also + * be set explicitly with `br_ssl_engine_set_session_parameters()`. + * + * On failure, the context is marked as failed, and this function + * returns 0. A possible failure condition is when no initial entropy + * was injected, and none could be obtained from the OS (either OS + * randomness gathering is not supported, or it failed). + * + * \param cc client context. + * \param server_name target server name, or `NULL`. + * \param resume_session non-zero to try session resumption. + * \return 0 on failure, 1 on success. + */ +int br_ssl_client_reset(br_ssl_client_context *cc, + const char *server_name, int resume_session); + +/** + * \brief Forget any session in the context. + * + * This means that the next handshake that uses this context will + * necessarily be a full handshake (this applies both to new connections + * and to renegotiations). + * + * \param cc client context. + */ +static __inline void +br_ssl_client_forget_session(br_ssl_client_context *cc) +{ + cc->eng.session.session_id_len = 0; +} + +/** + * \brief Set client certificate chain and key (single RSA case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an RSA public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * \param cc SSL client context. + * \param chain client certificate chain (SSL order: EE comes first). + * \param chain_len client chain length (number of certificates). + * \param sk client private key. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_client_set_single_rsa(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign); + +/* + * \brief Set the client certificate chain and key (single EC case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an EC public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX` + * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value + * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA + * signature implementation must be provided; otherwise, the `iecdsa` + * parameter may be 0. + * + * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or + * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA + * that issued (signed) the client certificate. That value is used with + * full static ECDH: support of the certificate by the server depends + * on how the certificate was signed. (Note: when using TLS 1.2, this + * parameter is ignored; but its value matters for TLS 1.0 and 1.1.) + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_client_set_single_ec(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Type for a "translated cipher suite", as an array of two + * 16-bit integers. + * + * The first element is the cipher suite identifier (as used on the wire). + * The second element is the concatenation of four 4-bit elements which + * characterise the cipher suite contents. In most to least significant + * order, these 4-bit elements are: + * + * - Bits 12 to 15: key exchange + server key type + * + * | val | symbolic constant | suite type | details | + * | :-- | :----------------------- | :---------- | :----------------------------------------------- | + * | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) | + * | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) | + * | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) | + * | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA | + * | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA | + * + * - Bits 8 to 11: symmetric encryption algorithm + * + * | val | symbolic constant | symmetric encryption | key strength (bits) | + * | :-- | :--------------------- | :------------------- | :------------------ | + * | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 | + * | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 | + * | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 | + * | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 | + * | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 | + * | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 | + * + * - Bits 4 to 7: MAC algorithm + * + * | val | symbolic constant | MAC type | details | + * | :-- | :----------------- | :----------- | :------------------------------------ | + * | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) | + * | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` | + * | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` | + * + * - Bits 0 to 3: hash function for PRF when used with TLS-1.2 + * + * | val | symbolic constant | hash function | details | + * | :-- | :----------------- | :------------ | :----------------------------------- | + * | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` | + * + * For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has + * standard identifier 0x009C, and is translated to 0x0304, for, in + * that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0), + * SHA-256 in the TLS PRF (4). + */ +typedef uint16_t br_suite_translated[2]; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Constants are already documented in the br_suite_translated type. + */ + +#define BR_SSLKEYX_RSA 0 +#define BR_SSLKEYX_ECDHE_RSA 1 +#define BR_SSLKEYX_ECDHE_ECDSA 2 +#define BR_SSLKEYX_ECDH_RSA 3 +#define BR_SSLKEYX_ECDH_ECDSA 4 + +#define BR_SSLENC_3DES_CBC 0 +#define BR_SSLENC_AES128_CBC 1 +#define BR_SSLENC_AES256_CBC 2 +#define BR_SSLENC_AES128_GCM 3 +#define BR_SSLENC_AES256_GCM 4 +#define BR_SSLENC_CHACHA20 5 + +#define BR_SSLMAC_AEAD 0 +#define BR_SSLMAC_SHA1 br_sha1_ID +#define BR_SSLMAC_SHA256 br_sha256_ID +#define BR_SSLMAC_SHA384 br_sha384_ID + +#define BR_SSLPRF_SHA256 br_sha256_ID +#define BR_SSLPRF_SHA384 br_sha384_ID + +#endif + +/* + * Pre-declaration for the SSL server context. + */ +typedef struct br_ssl_server_context_ br_ssl_server_context; + +/** + * \brief Type for the server policy choices, taken after analysis of + * the client message (ClientHello). + */ +typedef struct { + /** + * \brief Cipher suite to use with that client. + */ + uint16_t cipher_suite; + + /** + * \brief Hash function or algorithm for signing the ServerKeyExchange. + * + * This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*` + * cipher suites; it is used only for `TLS_ECDHE_*` suites, in + * which the server _signs_ the ephemeral EC Diffie-Hellman + * parameters sent to the client. + * + * This identifier must be one of the following values: + * + * - `0xFF00 + id`, where `id` is a hash function identifier + * (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions); + * + * - a full 16-bit identifier, lower than `0xFF00`. + * + * If the first option is used, then the SSL engine will + * compute the hash of the data that is to be signed, with the + * designated hash function. The `do_sign()` method will be + * invoked with that hash value provided in the the `data` + * buffer. + * + * If the second option is used, then the SSL engine will NOT + * compute a hash on the data; instead, it will provide the + * to-be-signed data itself in `data`, i.e. the concatenation of + * the client random, server random, and encoded ECDH + * parameters. Furthermore, with TLS-1.2 and later, the 16-bit + * identifier will be used "as is" in the protocol, in the + * SignatureAndHashAlgorithm; for instance, `0x0401` stands for + * RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash + * function (the `04`). + * + * Take care that with TLS 1.0 and 1.1, the hash function is + * constrainted by the protocol: RSA signature must use + * MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1 + * (`0xFF02`). Since TLS 1.0 and 1.1 don't include a + * SignatureAndHashAlgorithm field in their ServerKeyExchange + * messages, any value below `0xFF00` will be usable to send the + * raw ServerKeyExchange data to the `do_sign()` callback, but + * that callback must still follow the protocol requirements + * when generating the signature. + */ + unsigned algo_id; + + /** + * \brief Certificate chain to send to the client. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The server + * code does not try to decode these elements. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + */ + size_t chain_len; + +} br_ssl_server_choices; + +/** + * \brief Class type for a policy handler (server side). + * + * A policy handler selects the policy parameters for a connection + * (cipher suite and other algorithms, and certificate chain to send to + * the client); it also performs the server-side computations involving + * its permanent private key. + * + * The SSL server engine will invoke first `choose()`, once the + * ClientHello message has been received, then either `do_keyx()` + * `do_sign()`, depending on the cipher suite. + */ +typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class; +struct br_ssl_server_policy_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Select algorithms and certificates for this connection. + * + * This callback function shall fill the provided `choices` + * structure with the policy choices for this connection. This + * entails selecting the cipher suite, hash function for signing + * the ServerKeyExchange (applicable only to ECDHE cipher suites), + * and certificate chain to send. + * + * The callback receives a pointer to the server context that + * contains the relevant data. In particular, the functions + * `br_ssl_server_get_client_suites()`, + * `br_ssl_server_get_client_hashes()` and + * `br_ssl_server_get_client_curves()` can be used to obtain + * the cipher suites, hash functions and elliptic curves + * supported by both the client and server, respectively. The + * `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()` + * functions yield the protocol version and requested server name + * (SNI), respectively. + * + * This function may modify its context structure (`pctx`) in + * arbitrary ways to keep track of its own choices. + * + * This function shall return 1 if appropriate policy choices + * could be made, or 0 if this connection cannot be pursued. + * + * \param pctx policy context. + * \param cc SSL server context. + * \param choices destination structure for the policy choices. + * \return 1 on success, 0 on error. + */ + int (*choose)(const br_ssl_server_policy_class **pctx, + const br_ssl_server_context *cc, + br_ssl_server_choices *choices); + + /** + * \brief Perform key exchange (server part). + * + * This callback is invoked to perform the server-side cryptographic + * operation for a key exchange that is not ECDHE. This callback + * uses the private key. + * + * **For RSA key exchange**, the provided `data` (of length `*len` + * bytes) shall be decrypted with the server's private key, and + * the 48-byte premaster secret copied back to the first 48 bytes + * of `data`. + * + * - The caller makes sure that `*len` is at least 59 bytes. + * + * - This callback MUST check that the provided length matches + * that of the key modulus; it shall report an error otherwise. + * + * - If the length matches that of the RSA key modulus, then + * processing MUST be constant-time, even if decryption fails, + * or the padding is incorrect, or the plaintext message length + * is not exactly 48 bytes. + * + * - This callback needs not check the two first bytes of the + * obtained pre-master secret (the caller will do that). + * + * - If an error is reported (0), then what the callback put + * in the first 48 bytes of `data` is unimportant (the caller + * will use random bytes instead). + * + * **For ECDH key exchange**, the provided `data` (of length `*len` + * bytes) is the elliptic curve point from the client. The + * callback shall multiply it with its private key, and store + * the resulting X coordinate in `data`, starting at offset 0, + * and set `*len` to the length of the X coordinate. + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx policy context. + * \param data key exchange data from the client. + * \param len key exchange data length (in bytes). + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (for a ServerKeyExchange message). + * + * This callback function is invoked for ECDHE cipher suites. On + * input, the hash value or message to sign is in `data`, of + * size `hv_len`; the involved hash function or algorithm is + * identified by `algo_id`. The signature shall be computed and + * written back into `data`; the total size of that buffer is + * `len` bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * The `algo_id` value matches that which was written in the + * `choices` structures by the `choose()` callback. This will be + * one of the following: + * + * - `0xFF00 + id` for a hash function identifier `id`. In + * that case, the `data` buffer contains a hash value + * already computed over the data that is to be signed, + * of length `hv_len`. The `id` may be 0 to designate the + * special MD5+SHA-1 concatenation (old-style RSA signing). + * + * - Another value, lower than `0xFF00`. The `data` buffer + * then contains the raw, non-hashed data to be signed + * (concatenation of the client and server randoms and + * ECDH parameters). The callback is responsible to apply + * any relevant hashing as part of the signing process. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx policy context. + * \param algo_id hash function / algorithm identifier. + * \param data input/output buffer (message/hash, then signature). + * \param hv_len hash value or message length (in bytes). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_server_policy_class **pctx, + unsigned algo_id, + unsigned char *data, size_t hv_len, size_t len); +}; + +/** + * \brief A single-chain RSA policy handler. + * + * This policy context uses a single certificate chain, and a RSA + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + unsigned allowed_usages; + br_rsa_private irsacore; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_server_policy_rsa_context; + +/** + * \brief A single-chain EC policy handler. + * + * This policy context uses a single certificate chain, and an EC + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Due to how TLS is defined, this context must be made aware whether + * the server certificate was itself signed with RSA or ECDSA. The code + * does not try to decode the certificate to obtain that information. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned cert_issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_server_policy_ec_context; + +/** + * \brief Class type for a session parameter cache. + * + * Session parameters are saved in the cache with `save()`, and + * retrieved with `load()`. The cache implementation can apply any + * storage and eviction strategy that it sees fit. The SSL server + * context that performs the request is provided, so that its + * functionalities may be used by the implementation (e.g. hash + * functions or random number generation). + */ +typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class; +struct br_ssl_session_cache_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Record a session. + * + * This callback should record the provided session parameters. + * The `params` structure is transient, so its contents shall + * be copied into the cache. The session ID has been randomly + * generated and always has length exactly 32 bytes. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params session parameters to save. + */ + void (*save)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + const br_ssl_session_parameters *params); + + /** + * \brief Lookup a session in the cache. + * + * The session ID to lookup is in `params` and always has length + * exactly 32 bytes. If the session parameters are found in the + * cache, then the parameters shall be copied into the `params` + * structure. Returned value is 1 on successful lookup, 0 + * otherwise. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params destination for session parameters. + * \return 1 if found, 0 otherwise. + */ + int (*load)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + br_ssl_session_parameters *params); +}; + +/** + * \brief Context for a basic cache system. + * + * The system stores session parameters in a buffer provided at + * initialisation time. Each entry uses exactly 100 bytes, and + * buffer sizes up to 4294967295 bytes are supported. + * + * Entries are evicted with a LRU (Least Recently Used) policy. A + * search tree is maintained to keep lookups fast even with large + * caches. + * + * Apart from the first field (vtable pointer), the structure + * contents are opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_session_cache_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char *store; + size_t store_len, store_ptr; + unsigned char index_key[32]; + const br_hash_class *hash; + int init_done; + uint32_t head, tail, root; +#endif +} br_ssl_session_cache_lru; + +/** + * \brief Initialise a LRU session cache with the provided storage space. + * + * The provided storage space must remain valid as long as the cache + * is used. Arbitrary lengths are supported, up to 4294967295 bytes; + * each entry uses up exactly 100 bytes. + * + * \param cc session cache context. + * \param store storage space for cached entries. + * \param store_len storage space length (in bytes). + */ +void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc, + unsigned char *store, size_t store_len); + +/** + * \brief Forget an entry in an LRU session cache. + * + * The session cache context must have been initialised. The entry + * with the provided session ID (of exactly 32 bytes) is looked for + * in the cache; if located, it is disabled. + * + * \param cc session cache context. + * \param id session ID to forget. + */ +void br_ssl_session_cache_lru_forget( + br_ssl_session_cache_lru *cc, const unsigned char *id); + +/** + * \brief Context structure for a SSL server. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_server_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Maximum version from the client. + */ + uint16_t client_max_version; + + /* + * Session cache. + */ + const br_ssl_session_cache_class **cache_vtable; + + /* + * Translated cipher suites supported by the client. The list + * is trimmed to include only the cipher suites that the + * server also supports; they are in the same order as in the + * client message. + */ + br_suite_translated client_suites[BR_MAX_CIPHER_SUITES]; + unsigned char client_suites_num; + + /* + * Hash functions supported by the client, with ECDSA and RSA + * (bit mask). For hash function with id 'x', set bit index is + * x for RSA, x+8 for ECDSA. For newer algorithms, with ID + * 0x08**, bit 16+k is set for algorithm 0x0800+k. + */ + uint32_t hashes; + + /* + * Curves supported by the client (bit mask, for named curves). + */ + uint32_t curves; + + /* + * Context for chain handler. + */ + const br_ssl_server_policy_class **policy_vtable; + uint16_t sign_hash_id; + + /* + * For the core handlers, thus avoiding (in most cases) the + * need for an externally provided policy context. + */ + union { + const br_ssl_server_policy_class *vtable; + br_ssl_server_policy_rsa_context single_rsa; + br_ssl_server_policy_ec_context single_ec; + } chain_handler; + + /* + * Buffer for the ECDHE private key. + */ + unsigned char ecdhe_key[70]; + size_t ecdhe_key_len; + + /* + * Trust anchor names for client authentication. "ta_names" and + * "tas" cannot be both non-NULL. + */ + const br_x500_name *ta_names; + const br_x509_trust_anchor *tas; + size_t num_tas; + size_t cur_dn_index; + const unsigned char *cur_dn; + size_t cur_dn_len; + + /* + * Buffer for the hash value computed over all handshake messages + * prior to CertificateVerify, and identifier for the hash function. + */ + unsigned char hash_CV[64]; + size_t hash_CV_len; + int hash_CV_id; + + /* + * Server-specific implementations. + * (none for now) + */ +#endif +}; + +/* + * Each br_ssl_server_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full_rsa all supported algorithm, server key type is RSA + * full_ec all supported algorithm, server key type is EC + * TODO: add other profiles + * + * Naming scheme for "minimal" profiles: min123 + * + * -- character 1: key exchange + * r = RSA + * e = ECDHE_RSA + * f = ECDHE_ECDSA + * u = ECDH_RSA + * v = ECDH_ECDSA + * -- character 2: version / PRF + * 0 = TLS 1.0 / 1.1 with MD5+SHA-1 + * 2 = TLS 1.2 with SHA-256 + * 3 = TLS 1.2 with SHA-384 + * -- character 3: encryption + * a = AES/CBC + * d = 3DES/CBC + * g = AES/GCM + * c = ChaCha20+Poly1305 + */ + +/** + * \brief SSL server profile: full_rsa. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on a RSA + * key pair. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_full_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: full_ec. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on an EC + * key pair. + * + * The key type of the CA that issued the server's certificate must + * be provided, since it matters for ECDH cipher suites (ECDH_RSA + * suites require a RSA-powered CA). The key type is either + * `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len chain length (number of certificates). + * \param cert_issuer_key_type certificate issuer's key type. + * \param sk EC private key. + */ +void br_ssl_server_init_full_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + unsigned cert_issuer_key_type, const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minr2g. + * + * This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is + * RSA, and RSA key exchange is used (not forward secure, but uses little + * CPU in the client). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_minr2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: mine2g. + * + * This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key + * is RSA, and ECDHE key exchange is used. This suite provides forward + * security, with a higher CPU expense on the client, and a somewhat + * larger code footprint (compared to "minr2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2g. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security, with a higher CPU expense on the client and server + * (by a factor of about 3 to 4), and a somewhat larger code footprint + * (compared to "minu2g" and "minv2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minu2g. + * + * This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * a RSA key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minu2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minv2g. + * + * This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * an EC key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minv2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: mine2c. + * + * This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is RSA, and ECDHE key exchange is used. This suite + * provides forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2c. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief Get the supported client suites. + * + * This function shall be called only after the ClientHello has been + * processed, typically from the policy engine. The returned array + * contains the cipher suites that are supported by both the client + * and the server; these suites are in client preference order, unless + * the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case + * they are in server preference order. + * + * The suites are _translated_, which means that each suite is given + * as two 16-bit integers: the standard suite identifier, and its + * translated version, broken down into its individual components, + * as explained with the `br_suite_translated` type. + * + * The returned array is allocated in the context and will be rewritten + * by each handshake. + * + * \param cc server context. + * \param num receives the array size (number of suites). + * \return the translated common cipher suites, in preference order. + */ +static __inline const br_suite_translated * +br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num) +{ + *num = cc->client_suites_num; + return cc->client_suites; +} + +/** + * \brief Get the hash functions and signature algorithms supported by + * the client. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc server context. + * \return the client-supported hash functions and signature algorithms. + */ +static __inline uint32_t +br_ssl_server_get_client_hashes(const br_ssl_server_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the elliptic curves supported by the client. + * + * This is a bit field (bit x is set if curve of ID x is supported). + * + * \param cc server context. + * \return the client-supported elliptic curves. + */ +static __inline uint32_t +br_ssl_server_get_client_curves(const br_ssl_server_context *cc) +{ + return cc->curves; +} + +/** + * \brief Clear the complete contents of a SSL server context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc server context to clear. + */ +void br_ssl_server_zero(br_ssl_server_context *cc); + +/** + * \brief Set an externally provided policy context. + * + * The policy context's methods are invoked to decide the cipher suite + * and certificate chain, and to perform operations involving the server's + * private key. + * + * \param cc server context. + * \param pctx policy context (pointer to its vtable field). + */ +static __inline void +br_ssl_server_set_policy(br_ssl_server_context *cc, + const br_ssl_server_policy_class **pctx) +{ + cc->policy_vtable = pctx; +} + +/** + * \brief Set the server certificate chain and key (single RSA case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with a RSA + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for + * key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures). + * + * \param cc server context. + * \param chain server certificate chain to send to the client. + * \param chain_len chain length (number of certificates). + * \param sk server private key (RSA). + * \param allowed_usages allowed private key usages. + * \param irsacore RSA core implementation. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_server_set_single_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, unsigned allowed_usages, + br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign); + +/** + * \brief Set the server certificate chain and key (single EC case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with an EC + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for + * key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures). + * + * In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH), + * the algorithm type of the key used by the issuing CA to sign the + * server's certificate must be provided, as `cert_issuer_key_type` + * parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`). + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_server_set_single_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Activate client certificate authentication. + * + * The trust anchor encoded X.500 names (DN) to send to the client are + * provided. A client certificate will be requested and validated through + * the X.509 validator configured in the SSL engine. If `num` is 0, then + * client certificate authentication is disabled. + * + * If the client does not send a certificate, or on validation failure, + * the handshake aborts. Unauthenticated clients can be tolerated by + * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param ta_names encoded trust anchor names. + * \param num number of encoded trust anchor names. + */ +static __inline void +br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc, + const br_x500_name *ta_names, size_t num) +{ + cc->ta_names = ta_names; + cc->tas = NULL; + cc->num_tas = num; +} + +/** + * \brief Activate client certificate authentication. + * + * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the + * trust anchor names are provided not as an array of stand-alone names + * (`br_x500_name` structures), but as an array of trust anchors + * (`br_x509_trust_anchor` structures). The server engine itself will + * only use the `dn` field of each trust anchor. This is meant to allow + * defining a single array of trust anchors, to be used here and in the + * X.509 validation engine itself. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param tas trust anchors (only names are used). + * \param num number of trust anchors. + */ +static __inline void +br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc, + const br_x509_trust_anchor *tas, size_t num) +{ + cc->ta_names = NULL; + cc->tas = tas; + cc->num_tas = num; +} + +/** + * \brief Configure the cache for session parameters. + * + * The cache context is provided as a pointer to its first field (vtable + * pointer). + * + * \param cc server context. + * \param vtable session cache context. + */ +static __inline void +br_ssl_server_set_cache(br_ssl_server_context *cc, + const br_ssl_session_cache_class **vtable) +{ + cc->cache_vtable = vtable; +} + +/** + * \brief Prepare or reset a server context for handling an incoming client. + * + * \param cc server context. + * \return 1 on success, 0 on error. + */ +int br_ssl_server_reset(br_ssl_server_context *cc); + +/* ===================================================================== */ + +/* + * Context for the simplified I/O context. The transport medium is accessed + * through the low_read() and low_write() callback functions, each with + * its own opaque context pointer. + * + * low_read() read some bytes, at most 'len' bytes, into data[]. The + * returned value is the number of read bytes, or -1 on error. + * The 'len' parameter is guaranteed never to exceed 20000, + * so the length always fits in an 'int' on all platforms. + * + * low_write() write up to 'len' bytes, to be read from data[]. The + * returned value is the number of written bytes, or -1 on + * error. The 'len' parameter is guaranteed never to exceed + * 20000, so the length always fits in an 'int' on all + * parameters. + * + * A socket closure (if the transport medium is a socket) should be reported + * as an error (-1). The callbacks shall endeavour to block until at least + * one byte can be read or written; a callback returning 0 at times is + * acceptable, but this normally leads to the callback being immediately + * called again, so the callback should at least always try to block for + * some time if no I/O can take place. + * + * The SSL engine naturally applies some buffering, so the callbacks need + * not apply buffers of their own. + */ +/** + * \brief Context structure for the simplified SSL I/O wrapper. + * + * This structure is initialised with `br_sslio_init()`. Its contents + * are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + br_ssl_engine_context *engine; + int (*low_read)(void *read_context, + unsigned char *data, size_t len); + void *read_context; + int (*low_write)(void *write_context, + const unsigned char *data, size_t len); + void *write_context; +#endif +} br_sslio_context; + +/** + * \brief Initialise a simplified I/O wrapper context. + * + * The simplified I/O wrapper offers a simpler read/write API for a SSL + * engine (client or server), using the provided callback functions for + * reading data from, or writing data to, the transport medium. + * + * The callback functions have the following semantics: + * + * - Each callback receives an opaque context value (of type `void *`) + * that the callback may use arbitrarily (or possibly ignore). + * + * - `low_read()` reads at least one byte, at most `len` bytes, from + * the transport medium. Read bytes shall be written in `data`. + * + * - `low_write()` writes at least one byte, at most `len` bytes, unto + * the transport medium. The bytes to write are read from `data`. + * + * - The `len` parameter is never zero, and is always lower than 20000. + * + * - The number of processed bytes (read or written) is returned. Since + * that number is less than 20000, it always fits on an `int`. + * + * - On error, the callbacks return -1. Reaching end-of-stream is an + * error. Errors are permanent: the SSL connection is terminated. + * + * - Callbacks SHOULD NOT return 0. This is tolerated, as long as + * callbacks endeavour to block for some non-negligible amount of + * time until at least one byte can be sent or received (if a + * callback returns 0, then the wrapper invokes it again + * immediately). + * + * - Callbacks MAY return as soon as at least one byte is processed; + * they MAY also insist on reading or writing _all_ requested bytes. + * Since SSL is a self-terminated protocol (each record has a length + * header), this does not change semantics. + * + * - Callbacks need not apply any buffering (for performance) since SSL + * itself uses buffers. + * + * \param ctx wrapper context to initialise. + * \param engine SSL engine to wrap. + * \param low_read callback for reading data from the transport. + * \param read_context context pointer for `low_read()`. + * \param low_write callback for writing data on the transport. + * \param write_context context pointer for `low_write()`. + */ +void br_sslio_init(br_sslio_context *ctx, + br_ssl_engine_context *engine, + int (*low_read)(void *read_context, + unsigned char *data, size_t len), + void *read_context, + int (*low_write)(void *write_context, + const unsigned char *data, size_t len), + void *write_context); + +/** + * \brief Read some application data from a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been obtained. + * Returned value is the number of bytes read, or -1 on error. The + * number of bytes always fits on an 'int' (data from a single SSL/TLS + * record is returned). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len maximum number of bytes to obtain. + * \return number of bytes obtained, or -1 on error. + */ +int br_sslio_read(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Read application data from a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes are read, + * or an error is reached. Returned value is 0 on success, -1 on error. + * A normal (verified) SSL closure before that many bytes are obtained + * is reported as an error by this function. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len number of bytes to obtain. + * \return 0 on success, or -1 on error. + */ +int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Write some application data unto a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been written. + * Returned value is the number of bytes written, or -1 on error. The + * number of bytes always fits on an 'int' (less than 20000). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len maximum number of bytes to write. + * \return number of bytes written, or -1 on error. + */ +int br_sslio_write(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Write application data unto a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes have been + * written, or an error is reached. Returned value is 0 on success, -1 + * on error. A normal (verified) SSL closure before that many bytes are + * written is reported as an error by this function. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len number of bytes to write. + * \return 0 on success, or -1 on error. + */ +int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Flush pending data. + * + * This call makes sure that any buffered application data in the + * provided context (including the wrapped SSL engine) has been sent + * to the transport medium (i.e. accepted by the `low_write()` callback + * method). If there is no such pending data, then this function does + * nothing (and returns a success, i.e. 0). + * + * If the underlying transport medium has its own buffers, then it is + * up to the caller to ensure the corresponding flushing. + * + * Returned value is 0 on success, -1 on error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_flush(br_sslio_context *cc); + +/** + * \brief Close the SSL connection. + * + * This call runs the SSL closure protocol (sending a `close_notify`, + * receiving the response `close_notify`). When it returns, the SSL + * connection is finished. It is still up to the caller to manage the + * possible transport-level termination, if applicable (alternatively, + * the underlying transport stream may be reused for non-SSL messages). + * + * Returned value is 0 on success, -1 on error. A failure by the peer + * to process the complete closure protocol (i.e. sending back the + * `close_notify`) is an error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_close(br_sslio_context *cc); + +/* ===================================================================== */ + +/* + * Symbolic constants for cipher suites. + */ + +/* From RFC 5246 */ +#define BR_TLS_NULL_WITH_NULL_NULL 0x0000 +#define BR_TLS_RSA_WITH_NULL_MD5 0x0001 +#define BR_TLS_RSA_WITH_NULL_SHA 0x0002 +#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B +#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004 +#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005 +#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D +#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D +#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 +#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 +#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B +#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018 +#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D + +/* From RFC 4492 */ +#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 +#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 +#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 +#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 +#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 +#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A +#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B +#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C +#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F +#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 +#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 +#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 +#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015 +#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016 +#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017 +#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 +#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 + +/* From RFC 5288 */ +#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C +#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D +#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E +#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F +#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0 +#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1 +#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2 +#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3 +#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4 +#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5 +#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6 +#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7 + +/* From RFC 5289 */ +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E +#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F +#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 +#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 +#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 + +/* From RFC 6655 and 7251 */ +#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C +#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D +#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 +#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF + +/* From RFC 7905 */ +#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 +#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 +#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA +#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB +#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC +#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD +#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE + +/* From RFC 7507 */ +#define BR_TLS_FALLBACK_SCSV 0x5600 + +/* + * Symbolic constants for alerts. + */ +#define BR_ALERT_CLOSE_NOTIFY 0 +#define BR_ALERT_UNEXPECTED_MESSAGE 10 +#define BR_ALERT_BAD_RECORD_MAC 20 +#define BR_ALERT_RECORD_OVERFLOW 22 +#define BR_ALERT_DECOMPRESSION_FAILURE 30 +#define BR_ALERT_HANDSHAKE_FAILURE 40 +#define BR_ALERT_BAD_CERTIFICATE 42 +#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43 +#define BR_ALERT_CERTIFICATE_REVOKED 44 +#define BR_ALERT_CERTIFICATE_EXPIRED 45 +#define BR_ALERT_CERTIFICATE_UNKNOWN 46 +#define BR_ALERT_ILLEGAL_PARAMETER 47 +#define BR_ALERT_UNKNOWN_CA 48 +#define BR_ALERT_ACCESS_DENIED 49 +#define BR_ALERT_DECODE_ERROR 50 +#define BR_ALERT_DECRYPT_ERROR 51 +#define BR_ALERT_PROTOCOL_VERSION 70 +#define BR_ALERT_INSUFFICIENT_SECURITY 71 +#define BR_ALERT_INTERNAL_ERROR 80 +#define BR_ALERT_USER_CANCELED 90 +#define BR_ALERT_NO_RENEGOTIATION 100 +#define BR_ALERT_UNSUPPORTED_EXTENSION 110 +#define BR_ALERT_NO_APPLICATION_PROTOCOL 120 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libcurl/lib/vtls/bearssl_xbox.cpp b/libcurl/lib/vtls/bearssl_xbox.cpp new file mode 100644 index 0000000..bd73a56 --- /dev/null +++ b/libcurl/lib/vtls/bearssl_xbox.cpp @@ -0,0 +1,150 @@ +/* + * BearSSL Xbox Integration Implementation + * C-compatible wrappers for Xbox-specific SSL functionality + */ + +#include "bearssl_xbox.h" +#include "certificates.h" +#include "ca_loader.h" +#include "session_cache.h" +#include "ssl_errors.h" +#include "cert_pinning.h" + +extern "C" { + +/* + * Trust Anchor Management + */ +void bearssl_xbox_init_trust_anchors(void) +{ + certificates::initialize_trust_anchors(); +} + +void bearssl_xbox_cleanup_trust_anchors(void) +{ + certificates::close_trust_anchors(); +} + +br_x509_trust_anchor* bearssl_xbox_get_trust_anchors(void) +{ + return certificates::get_trust_anchors(); +} + +size_t bearssl_xbox_get_trust_anchor_count(void) +{ + return (size_t)certificates::get_num_trust_anchors(); +} + +/* + * Session Cache Management + */ +void bearssl_xbox_session_init(void) +{ + session_cache::initialize(); +} + +void bearssl_xbox_session_shutdown(void) +{ + session_cache::shutdown(); +} + +int bearssl_xbox_session_get(const char* hostname, br_ssl_session_parameters* params) +{ + return session_cache::get(hostname, params) ? 1 : 0; +} + +void bearssl_xbox_session_store(const char* hostname, const br_ssl_session_parameters* params) +{ + session_cache::store(hostname, params); +} + +void bearssl_xbox_session_remove(const char* hostname) +{ + session_cache::remove(hostname); +} + +void bearssl_xbox_session_clear(void) +{ + session_cache::clear(); +} + +/* + * Error Message Utilities + */ +const char* bearssl_xbox_error_string(int error) +{ + return ssl_errors::error_to_string(error); +} + +const char* bearssl_xbox_alert_string(int alert_code) +{ + return ssl_errors::alert_to_string(alert_code); +} + +/* + * CA Loader + */ +int bearssl_xbox_load_ca_file(const char *path, + br_x509_trust_anchor **anchors_out, size_t *count_out) +{ + return ca_loader::load_pem_file(path, anchors_out, count_out); +} + +void bearssl_xbox_free_loaded_anchors(br_x509_trust_anchor *anchors, + size_t count) +{ + ca_loader::free_trust_anchors(anchors, count); +} + +int bearssl_xbox_update_trust_store(void) +{ + return ca_loader::update_trust_store( + BEARSSL_XBOX_DEFAULT_CA_FILE, + certificates::get_trust_anchors(), + (size_t)certificates::get_num_trust_anchors()); +} + +/* + * Certificate Pinning + */ +void bearssl_xbox_pin_init(void) +{ + cert_pinning::initialize(); +} + +void bearssl_xbox_pin_shutdown(void) +{ + cert_pinning::shutdown(); +} + +int bearssl_xbox_pin_add(const char* hostname, const unsigned char* sha256_hash) +{ + return cert_pinning::add_pin(hostname, sha256_hash) ? 1 : 0; +} + +void bearssl_xbox_pin_remove(const char* hostname) +{ + cert_pinning::remove_pin(hostname); +} + +void bearssl_xbox_pin_clear(void) +{ + cert_pinning::clear(); +} + +int bearssl_xbox_pin_has(const char* hostname) +{ + return cert_pinning::has_pin(hostname) ? 1 : 0; +} + +int bearssl_xbox_pin_verify_hash(const char* hostname, const unsigned char* cert_sha256) +{ + return cert_pinning::verify_hash(hostname, cert_sha256) ? 1 : 0; +} + +int bearssl_xbox_pin_get_hash(const char* hostname, unsigned char* hash_out) +{ + return cert_pinning::get_pin_hash(hostname, hash_out) ? 1 : 0; +} + +} /* extern "C" */ diff --git a/libcurl/lib/vtls/bearssl_xbox.h b/libcurl/lib/vtls/bearssl_xbox.h new file mode 100644 index 0000000..6b86866 --- /dev/null +++ b/libcurl/lib/vtls/bearssl_xbox.h @@ -0,0 +1,85 @@ +/* + * BearSSL Xbox Integration Header + * C-compatible wrappers for Xbox-specific SSL functionality + * + * This provides a C interface to the C++ classes for use by libcurl's bearssl.c + */ + +#ifndef BEARSSL_XBOX_H +#define BEARSSL_XBOX_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default CA bundle path on Xbox HDD. + * T:\ maps to E:\TDATA\\ (title-persistent storage). + * Drop cacert.pem there to use updated root CAs without recompiling. + */ +#define BEARSSL_XBOX_DEFAULT_CA_FILE "T:\\cacert.pem" + +/* + * Trust Anchor Management + * Wraps certificates.cpp functionality + */ +void bearssl_xbox_init_trust_anchors(void); +void bearssl_xbox_cleanup_trust_anchors(void); +br_x509_trust_anchor* bearssl_xbox_get_trust_anchors(void); +size_t bearssl_xbox_get_trust_anchor_count(void); + +/* + * Session Cache Management + * Wraps session_cache.cpp functionality + */ +void bearssl_xbox_session_init(void); +void bearssl_xbox_session_shutdown(void); +int bearssl_xbox_session_get(const char* hostname, br_ssl_session_parameters* params); +void bearssl_xbox_session_store(const char* hostname, const br_ssl_session_parameters* params); +void bearssl_xbox_session_remove(const char* hostname); +void bearssl_xbox_session_clear(void); + +/* + * Error Message Utilities + * Wraps ssl_errors.cpp functionality + */ +const char* bearssl_xbox_error_string(int error); +const char* bearssl_xbox_alert_string(int alert_code); + +/* + * CA Loader - Runtime PEM certificate loading + * Wraps ca_loader.cpp functionality + */ +int bearssl_xbox_load_ca_file(const char *path, + br_x509_trust_anchor **anchors_out, size_t *count_out); +void bearssl_xbox_free_loaded_anchors(br_x509_trust_anchor *anchors, + size_t count); + +/* + * CA Auto-Update + * Downloads cacert.pem from curl.se if not already present on disk. + * Uses the compiled-in trust anchors (must be initialized first). + * Returns 0 on success (file existed or was downloaded), -1 on failure. + */ +int bearssl_xbox_update_trust_store(void); + +/* + * Certificate Pinning + * Wraps cert_pinning.cpp functionality + */ +void bearssl_xbox_pin_init(void); +void bearssl_xbox_pin_shutdown(void); +int bearssl_xbox_pin_add(const char* hostname, const unsigned char* sha256_hash); +void bearssl_xbox_pin_remove(const char* hostname); +void bearssl_xbox_pin_clear(void); +int bearssl_xbox_pin_has(const char* hostname); +int bearssl_xbox_pin_verify_hash(const char* hostname, const unsigned char* cert_sha256); +int bearssl_xbox_pin_get_hash(const char* hostname, unsigned char* hash_out); + +#ifdef __cplusplus +} +#endif + +#endif /* BEARSSL_XBOX_H */ diff --git a/libcurl/lib/vtls/ca_loader.cpp b/libcurl/lib/vtls/ca_loader.cpp new file mode 100644 index 0000000..457154a --- /dev/null +++ b/libcurl/lib/vtls/ca_loader.cpp @@ -0,0 +1,861 @@ +#include "ca_loader.h" +#include "debug_utility.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DOWNLOAD_BUF_SIZE 8192 +#define CA_DNS_TIMEOUT_MS 30000 + +/* ------------------------------------------------------------------ */ +/* Inline socket/network helpers (avoids dependency on BearSSL-OG */ +/* socket_utility / network_utility which aren't in libbearssl) */ +/* ------------------------------------------------------------------ */ + +/* DNS resolution via Xbox XNet async API */ +static uint32_t ca_resolve_host(const char *host) +{ + XNDNS *dns = NULL; + WSAEVENT event_handle; + uint32_t result = 0; + + if (host == NULL || host[0] == '\0') + { + return 0; + } + + event_handle = WSACreateEvent(); + if (event_handle == NULL) + { + return 0; + } + + if (XNetDnsLookup(host, event_handle, &dns) != 0) + { + WSACloseEvent(event_handle); + return 0; + } + + if (WaitForSingleObject(event_handle, CA_DNS_TIMEOUT_MS) == WAIT_TIMEOUT) + { + WSACloseEvent(event_handle); + XNetDnsRelease(dns); + return 0; + } + + WSACloseEvent(event_handle); + + if (dns->iStatus == 0 && dns->cina > 0) + { + result = dns->aina[0].S_un.S_addr; + } + + XNetDnsRelease(dns); + return result; +} + +/* TCP connect to host:port, returns socket or INVALID_SOCKET. + * IMPORTANT: Xbox SOCKET handles are kernel pointers (e.g. 0xD001A828) + * which are negative as signed int -- never check < 0, always use + * INVALID_SOCKET. */ +static SOCKET ca_connect(uint32_t host_ip, uint16_t port) +{ + sockaddr_in addr; + SOCKET sock; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.S_un.S_addr = host_ip; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == INVALID_SOCKET) + { + return INVALID_SOCKET; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) + { + closesocket(sock); + return INVALID_SOCKET; + } + + return sock; +} + +/* BearSSL I/O callback: read from socket with 2-second select timeout */ +static int ca_sock_read(void *ctx, unsigned char *buf, size_t len) +{ + SOCKET sock = *(SOCKET *)ctx; + fd_set fds; + struct timeval tv; + int n; + + while (1) + { + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = 2; + tv.tv_usec = 0; + + if (select(0, &fds, NULL, NULL, &tv) == 0) + { + return -1; /* timeout */ + } + + n = recv(sock, (char *)buf, (len > 0x7FFFFFFF) ? 0x7FFFFFFF : (int)len, 0); + if (n == SOCKET_ERROR) + { + if (WSAGetLastError() == WSAEINTR || + WSAGetLastError() == WSAEWOULDBLOCK) + { + continue; + } + return -1; + } + return n; /* 0 = peer closed, >0 = bytes read */ + } +} + +/* BearSSL I/O callback: write to socket */ +static int ca_sock_write(void *ctx, const unsigned char *buf, size_t len) +{ + SOCKET sock = *(SOCKET *)ctx; + int n; + + while (1) + { + n = send(sock, (const char *)buf, + (len > 0x7FFFFFFF) ? 0x7FFFFFFF : (int)len, 0); + if (n == SOCKET_ERROR) + { + if (WSAGetLastError() == WSAEINTR || + WSAGetLastError() == WSAEWOULDBLOCK) + { + continue; + } + return -1; + } + return n; + } +} + +/* Dynamic byte buffer used for accumulating DER and DN data */ +struct byte_buffer +{ + unsigned char *data; + size_t len; + size_t cap; + int error; /* set to 1 if any append failed (OOM) */ +}; + +static void byte_buffer_init(byte_buffer *bb) +{ + bb->data = NULL; + bb->len = 0; + bb->cap = 0; + bb->error = 0; +} + +static void byte_buffer_reset(byte_buffer *bb) +{ + bb->len = 0; + bb->error = 0; +} + +static void byte_buffer_free(byte_buffer *bb) +{ + free(bb->data); + bb->data = NULL; + bb->len = 0; + bb->cap = 0; + bb->error = 0; +} + +static int byte_buffer_append(byte_buffer *bb, const void *src, size_t len) +{ + if (len == 0) + { + return 0; + } + if (bb->len + len > bb->cap) + { + size_t new_cap = (bb->cap == 0) ? 4096 : bb->cap * 2; + while (new_cap < bb->len + len) + { + if (new_cap > ((size_t)-1) / 2) + { + return -1; + } + new_cap *= 2; + } + unsigned char *new_data = (unsigned char *)realloc(bb->data, new_cap); + if (new_data == NULL) + { + return -1; + } + bb->data = new_data; + bb->cap = new_cap; + } + memcpy(bb->data + bb->len, src, len); + bb->len += len; + return 0; +} + +/* PEM decoder callback: accumulates decoded DER bytes */ +static void pem_dest_callback(void *dest_ctx, const void *src, size_t len) +{ + byte_buffer *bb = (byte_buffer *)dest_ctx; + if (byte_buffer_append(bb, src, len) != 0) + { + bb->error = 1; + } +} + +/* X.509 decoder callback: accumulates subject DN bytes */ +static void dn_append_callback(void *ctx, const void *buf, size_t len) +{ + byte_buffer *bb = (byte_buffer *)ctx; + if (byte_buffer_append(bb, buf, len) != 0) + { + bb->error = 1; + } +} + +/* + * Deep-copy a decoded certificate into a new trust anchor entry. + * Returns 0 on success, -1 on allocation failure. + */ +static int add_trust_anchor( + br_x509_trust_anchor **anchors, size_t *count, size_t *cap, + byte_buffer *dn, br_x509_decoder_context *dc) +{ + br_x509_pkey *pk = br_x509_decoder_get_pkey(dc); + if (pk == NULL) + { + return -1; + } + + /* Grow anchor array if needed */ + if (*count >= *cap) + { + size_t new_cap = (*cap == 0) ? 32 : *cap * 2; + br_x509_trust_anchor *new_arr = (br_x509_trust_anchor *)realloc( + *anchors, new_cap * sizeof(br_x509_trust_anchor)); + if (new_arr == NULL) + { + return -1; + } + *anchors = new_arr; + *cap = new_cap; + } + + br_x509_trust_anchor *ta = &(*anchors)[*count]; + memset(ta, 0, sizeof(*ta)); + + /* Deep-copy DN */ + ta->dn.data = (unsigned char *)malloc(dn->len); + if (ta->dn.data == NULL) + { + return -1; + } + memcpy(ta->dn.data, dn->data, dn->len); + ta->dn.len = dn->len; + + /* Set CA flag */ + ta->flags = br_x509_decoder_isCA(dc) ? BR_X509_TA_CA : 0; + + /* Deep-copy public key */ + ta->pkey.key_type = pk->key_type; + if (pk->key_type == BR_KEYTYPE_RSA) + { + ta->pkey.key.rsa.n = (unsigned char *)malloc(pk->key.rsa.nlen); + ta->pkey.key.rsa.e = (unsigned char *)malloc(pk->key.rsa.elen); + if (ta->pkey.key.rsa.n == NULL || ta->pkey.key.rsa.e == NULL) + { + free(ta->pkey.key.rsa.n); + free(ta->pkey.key.rsa.e); + free(ta->dn.data); + return -1; + } + memcpy(ta->pkey.key.rsa.n, pk->key.rsa.n, pk->key.rsa.nlen); + ta->pkey.key.rsa.nlen = pk->key.rsa.nlen; + memcpy(ta->pkey.key.rsa.e, pk->key.rsa.e, pk->key.rsa.elen); + ta->pkey.key.rsa.elen = pk->key.rsa.elen; + } + else if (pk->key_type == BR_KEYTYPE_EC) + { + ta->pkey.key.ec.q = (unsigned char *)malloc(pk->key.ec.qlen); + if (ta->pkey.key.ec.q == NULL) + { + free(ta->dn.data); + memset(ta, 0, sizeof(*ta)); + return -1; + } + memcpy(ta->pkey.key.ec.q, pk->key.ec.q, pk->key.ec.qlen); + ta->pkey.key.ec.qlen = pk->key.ec.qlen; + ta->pkey.key.ec.curve = pk->key.ec.curve; + } + else + { + /* Unknown key type */ + free(ta->dn.data); + memset(ta, 0, sizeof(*ta)); + return -1; + } + + (*count)++; + return 0; +} + +int ca_loader::load_pem_file(const char *path, + br_x509_trust_anchor **anchors_out, size_t *count_out) +{ + *anchors_out = NULL; + *count_out = 0; + + /* Read entire PEM file into memory */ + FILE *f = fopen(path, "rb"); + if (f == NULL) + { + debug_utility::debug_print("ca_loader: cannot open %s\n", path); + return -1; + } + + fseek(f, 0, SEEK_END); + long file_size = ftell(f); + fseek(f, 0, SEEK_SET); + + if (file_size <= 0 || file_size > 2 * 1024 * 1024) + { + debug_utility::debug_print("ca_loader: file too large or empty (%ld bytes)\n", file_size); + fclose(f); + return -1; + } + + unsigned char *file_data = (unsigned char *)malloc((size_t)file_size); + if (file_data == NULL) + { + debug_utility::debug_print("ca_loader: malloc failed for file data\n"); + fclose(f); + return -1; + } + + size_t bytes_read = fread(file_data, 1, (size_t)file_size, f); + fclose(f); + + if (bytes_read != (size_t)file_size) + { + debug_utility::debug_print("ca_loader: short read (%u of %ld)\n", + (unsigned)bytes_read, file_size); + free(file_data); + return -1; + } + + /* Parse PEM, collecting DER blobs for each CERTIFICATE */ + br_pem_decoder_context pem; + br_pem_decoder_init(&pem); + + br_x509_trust_anchor *anchors = NULL; + size_t anchor_count = 0; + size_t anchor_cap = 0; + + byte_buffer der_buf; + byte_buffer_init(&der_buf); + + byte_buffer dn_buf; + byte_buffer_init(&dn_buf); + + int in_cert = 0; + int certs_parsed = 0; + int certs_failed = 0; + + const unsigned char *pos = file_data; + size_t remaining = bytes_read; + + while (remaining > 0) + { + size_t consumed = br_pem_decoder_push(&pem, pos, remaining); + pos += consumed; + remaining -= consumed; + + int event = br_pem_decoder_event(&pem); + switch (event) + { + case BR_PEM_BEGIN_OBJ: + if (strcmp(br_pem_decoder_name(&pem), "CERTIFICATE") == 0) + { + in_cert = 1; + byte_buffer_reset(&der_buf); + br_pem_decoder_setdest(&pem, pem_dest_callback, &der_buf); + } + else + { + /* Skip non-certificate objects (private keys, etc.) */ + in_cert = 0; + br_pem_decoder_setdest(&pem, NULL, NULL); + } + break; + + case BR_PEM_END_OBJ: + if (in_cert && der_buf.len > 0 && !der_buf.error) + { + /* Decode the DER certificate */ + br_x509_decoder_context dc; + byte_buffer_reset(&dn_buf); + br_x509_decoder_init(&dc, dn_append_callback, &dn_buf); + br_x509_decoder_push(&dc, der_buf.data, der_buf.len); + + int err = br_x509_decoder_last_error(&dc); + if (err == 0 && !dn_buf.error) + { + if (add_trust_anchor(&anchors, &anchor_count, &anchor_cap, + &dn_buf, &dc) == 0) + { + certs_parsed++; + } + else + { + certs_failed++; + } + } + else + { + certs_failed++; + } + } + else if (in_cert && (der_buf.error || dn_buf.error)) + { + certs_failed++; + } + in_cert = 0; + break; + + case BR_PEM_ERROR: + in_cert = 0; + break; + + case 0: + /* No event yet, decoder needs more data but push returned 0. + * This shouldn't happen with complete files, but guard against + * infinite loop by breaking if no progress was made. */ + if (consumed == 0) + { + remaining = 0; + } + break; + } + } + + byte_buffer_free(&der_buf); + byte_buffer_free(&dn_buf); + free(file_data); + + debug_utility::debug_print("ca_loader: loaded %d trust anchors from %s (%d failed)\n", + certs_parsed, path, certs_failed); + + if (anchor_count == 0) + { + free(anchors); + return -1; + } + + *anchors_out = anchors; + *count_out = anchor_count; + return 0; +} + +void ca_loader::free_trust_anchors(br_x509_trust_anchor *anchors, size_t count) +{ + size_t i; + + if (anchors == NULL) + { + return; + } + + for (i = 0; i < count; i++) + { + free(anchors[i].dn.data); + if (anchors[i].pkey.key_type == BR_KEYTYPE_RSA) + { + free(anchors[i].pkey.key.rsa.n); + free(anchors[i].pkey.key.rsa.e); + } + else if (anchors[i].pkey.key_type == BR_KEYTYPE_EC) + { + free(anchors[i].pkey.key.ec.q); + } + } + free(anchors); +} + +/* ------------------------------------------------------------------ */ +/* Auto-update: download CA bundle from curl.se over HTTPS */ +/* ------------------------------------------------------------------ */ + +/* Time check callback: always returns 0 (valid). + * This lets the compiled-in CAs work even if the Xbox clock is wrong. */ +static int download_time_check(void *tctx, + uint32_t not_before_days, uint32_t not_before_seconds, + uint32_t not_after_days, uint32_t not_after_seconds) +{ + (void)tctx; + (void)not_before_days; + (void)not_before_seconds; + (void)not_after_days; + (void)not_after_seconds; + return 0; +} + +/* Find \r\n in a buffer, return offset or -1 */ +static int find_line_end(const unsigned char *buf, size_t len) +{ + size_t i; + if (len < 2) return -1; + for (i = 0; i < len - 1; i++) + { + if (buf[i] == '\r' && buf[i + 1] == '\n') + { + return (int)i; + } + } + return -1; +} + +/* Case-insensitive prefix match */ +static int prefix_icmp(const char *str, const char *prefix) +{ + while (*prefix) + { + char a = *str; + char b = *prefix; + if (a >= 'A' && a <= 'Z') a += 32; + if (b >= 'A' && b <= 'Z') b += 32; + if (a != b) return 0; + str++; + prefix++; + } + return 1; +} + +int ca_loader::download_https(const char *host, const char *path, + uint16_t port, const char *save_path, + br_x509_trust_anchor *anchors, size_t anchor_count, + int max_redirects) +{ + int result = -1; + + /* DNS resolve */ + uint32_t host_ip = ca_resolve_host(host); + if (host_ip == 0) + { + debug_utility::debug_print("ca_loader: DNS failed for %s\n", host); + return -1; + } + + /* TCP connect */ + SOCKET sock = ca_connect(host_ip, port); + if (sock == INVALID_SOCKET) + { + debug_utility::debug_print("ca_loader: connect failed to %s:%u\n", + host, (unsigned)port); + return -1; + } + + /* Allocate BearSSL I/O buffer on the heap (too large for Xbox stack) */ + unsigned char *iobuf = (unsigned char *)malloc(BR_SSL_BUFSIZE_BIDI); + if (iobuf == NULL) + { + closesocket(sock); + return -1; + } + + /* Set up BearSSL with compiled-in CAs + time check bypass */ + br_ssl_client_context sc; + br_x509_minimal_context xc; + br_ssl_client_init_full(&sc, &xc, anchors, anchor_count); + br_x509_minimal_set_time_callback(&xc, NULL, download_time_check); + br_ssl_engine_set_buffer(&sc.eng, iobuf, BR_SSL_BUFSIZE_BIDI, 1); + br_ssl_client_reset(&sc, host, 0); + + br_sslio_context ioc; + br_sslio_init(&ioc, &sc.eng, + ca_sock_read, &sock, + ca_sock_write, &sock); + + /* Send HTTP GET */ + char request[512]; + _snprintf(request, sizeof(request) - 1, + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Accept-Encoding: identity\r\n" + "Connection: close\r\n" + "\r\n", + path, host); + request[sizeof(request) - 1] = '\0'; + + br_sslio_write_all(&ioc, request, strlen(request)); + br_sslio_flush(&ioc); + + /* Read response into accumulation buffer */ + unsigned char *readbuf = (unsigned char *)malloc(DOWNLOAD_BUF_SIZE); + if (readbuf == NULL) + { + free(iobuf); + closesocket(sock); + return -1; + } + + /* Accumulate headers */ + byte_buffer hdr; + byte_buffer_init(&hdr); + + int status_code = 0; + int64_t content_length = -1; + char redirect_host[256]; + char redirect_path[512]; + int has_redirect = 0; + int headers_done = 0; + + redirect_host[0] = '\0'; + redirect_path[0] = '\0'; + + while (!headers_done) + { + int n = br_sslio_read(&ioc, readbuf, DOWNLOAD_BUF_SIZE); + if (n < 0) break; + byte_buffer_append(&hdr, readbuf, (size_t)n); + + /* Parse complete lines from the accumulated buffer */ + while (hdr.len > 0) + { + int crlf = find_line_end(hdr.data, hdr.len); + if (crlf < 0) break; + + /* Null-terminate the line for string operations */ + char *line = (char *)malloc((size_t)crlf + 1); + if (line == NULL) break; + memcpy(line, hdr.data, (size_t)crlf); + line[crlf] = '\0'; + + /* Remove the line + CRLF from the buffer */ + { + size_t remove_len = (size_t)crlf + 2; + if (remove_len < hdr.len) + { + memmove(hdr.data, hdr.data + remove_len, + hdr.len - remove_len); + } + hdr.len -= remove_len; + } + + /* Empty line = end of headers */ + if (line[0] == '\0') + { + free(line); + headers_done = 1; + break; + } + + /* Parse status line: "HTTP/1.x 200 OK" */ + if (status_code == 0 && strncmp(line, "HTTP/", 5) == 0) + { + char *sp = strchr(line, ' '); + if (sp) status_code = atoi(sp + 1); + } + + /* Parse Content-Length (cap at 10MB - CA bundles are ~250KB) */ + if (prefix_icmp(line, "content-length:")) + { + const char *val = line + 15; + while (*val == ' ') val++; + content_length = 0; + while (*val >= '0' && *val <= '9') + { + content_length = content_length * 10 + (*val - '0'); + if (content_length > 10 * 1024 * 1024) + { + content_length = -1; + break; + } + val++; + } + } + + /* Parse Location for redirects */ + if (prefix_icmp(line, "location:")) + { + const char *url = line + 9; + while (*url == ' ') url++; + + /* Parse "https://host/path" */ + if (strncmp(url, "https://", 8) == 0) + { + const char *hstart = url + 8; + const char *slash = strchr(hstart, '/'); + if (slash) + { + size_t hlen = (size_t)(slash - hstart); + if (hlen < sizeof(redirect_host)) + { + memcpy(redirect_host, hstart, hlen); + redirect_host[hlen] = '\0'; + _snprintf(redirect_path, + sizeof(redirect_path) - 1, "%s", slash); + redirect_path[sizeof(redirect_path) - 1] = '\0'; + has_redirect = 1; + } + } + } + } + + free(line); + } + } + + /* Handle redirect */ + if ((status_code == 301 || status_code == 302 || status_code == 307) + && has_redirect && max_redirects > 0) + { + debug_utility::debug_print("ca_loader: redirect %d -> %s%s\n", + status_code, redirect_host, redirect_path); + + byte_buffer_free(&hdr); + free(readbuf); + free(iobuf); + closesocket(sock); + + return download_https(redirect_host, redirect_path, port, + save_path, anchors, anchor_count, max_redirects - 1); + } + + if (status_code != 200) + { + debug_utility::debug_print("ca_loader: HTTP %d from %s%s\n", + status_code, host, path); + byte_buffer_free(&hdr); + free(readbuf); + free(iobuf); + closesocket(sock); + return -1; + } + + /* Write body to a temp file, then rename on success */ + char temp_path[280]; + _snprintf(temp_path, sizeof(temp_path) - 1, "%s.tmp", save_path); + temp_path[sizeof(temp_path) - 1] = '\0'; + + FILE *fp = fopen(temp_path, "wb"); + if (fp == NULL) + { + debug_utility::debug_print("ca_loader: cannot create %s (err=%lu)\n", + temp_path, GetLastError()); + byte_buffer_free(&hdr); + free(readbuf); + free(iobuf); + closesocket(sock); + return -1; + } + + /* Write any leftover data that was read past the headers */ + int64_t total_written = 0; + int write_error = 0; + if (hdr.len > 0) + { + if (fwrite(hdr.data, 1, hdr.len, fp) != hdr.len) + { + write_error = 1; + } + total_written += (int64_t)hdr.len; + } + byte_buffer_free(&hdr); + + /* Stream the rest of the body to disk */ + while (!write_error) + { + int n = br_sslio_read(&ioc, readbuf, DOWNLOAD_BUF_SIZE); + if (n < 0) break; + if (fwrite(readbuf, 1, (size_t)n, fp) != (size_t)n) + { + write_error = 1; + break; + } + total_written += (int64_t)n; + + if (content_length > 0 && total_written >= content_length) + { + break; + } + } + + fclose(fp); + free(readbuf); + free(iobuf); + closesocket(sock); + + /* Check for disk write errors */ + if (write_error) + { + debug_utility::debug_print("ca_loader: write error saving to %s\n", + temp_path); + remove(temp_path); + return -1; + } + + /* Sanity check: CA bundles are typically 200-300 KB */ + if (total_written < 1024) + { + debug_utility::debug_print("ca_loader: download too small (%I64d bytes)\n", + total_written); + remove(temp_path); + return -1; + } + + /* Atomic-ish replace: delete old, rename temp */ + remove(save_path); + if (rename(temp_path, save_path) != 0) + { + debug_utility::debug_print("ca_loader: rename %s -> %s failed\n", + temp_path, save_path); + remove(temp_path); + return -1; + } + + debug_utility::debug_print("ca_loader: downloaded %I64d bytes to %s\n", + total_written, save_path); + result = 0; + return result; +} + +int ca_loader::update_trust_store(const char *save_path, + br_x509_trust_anchor *anchors, size_t anchor_count) +{ + /* If the CA file already exists on disk, nothing to do */ + FILE *f = fopen(save_path, "rb"); + if (f != NULL) + { + fclose(f); + debug_utility::debug_print("ca_loader: %s already exists, skipping download\n", + save_path); + return 0; + } + + if (anchors == NULL || anchor_count == 0) + { + debug_utility::debug_print("ca_loader: no trust anchors for download\n"); + return -1; + } + + debug_utility::debug_print("ca_loader: downloading CA bundle from %s...\n", + CA_BUNDLE_HOST); + + return download_https(CA_BUNDLE_HOST, CA_BUNDLE_PATH, CA_BUNDLE_PORT, + save_path, anchors, anchor_count, 3); +} diff --git a/libcurl/lib/vtls/ca_loader.h b/libcurl/lib/vtls/ca_loader.h new file mode 100644 index 0000000..6ed4416 --- /dev/null +++ b/libcurl/lib/vtls/ca_loader.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include + +/* + * Runtime CA certificate loader. + * + * Parses PEM-encoded CA bundle files (e.g. cacert.pem from curl.se) + * into br_x509_trust_anchor arrays that BearSSL can use for certificate + * verification. + * + * Also provides auto-update: downloads a fresh CA bundle over HTTPS + * using the compiled-in trust anchors (with time validation bypassed) + * and saves it to title-persistent storage on the Xbox HDD. + */ + +/* Where to download the CA bundle from */ +#define CA_BUNDLE_HOST "curl.se" +#define CA_BUNDLE_PATH "/ca/cacert.pem" +#define CA_BUNDLE_PORT 443 + +class ca_loader +{ +public: + /* + * Load trust anchors from a PEM CA bundle file. + * Returns 0 on success, -1 on failure. + */ + static int load_pem_file(const char *path, + br_x509_trust_anchor **anchors_out, size_t *count_out); + + /* + * Free trust anchors that were loaded from a PEM file. + * Deep-frees DN data and key data, then frees the array. + */ + static void free_trust_anchors(br_x509_trust_anchor *anchors, + size_t count); + + /* + * Auto-update the trust store. + * + * If save_path does not exist, downloads a fresh CA bundle from + * curl.se over HTTPS (using the provided trust anchors with time + * validation disabled) and saves it to save_path. + * + * Returns 0 on success (file already existed or was downloaded). + * Returns -1 on failure (download failed, file I/O error, etc.). + */ + static int update_trust_store(const char *save_path, + br_x509_trust_anchor *anchors, size_t anchor_count); + +private: + /* + * Download an HTTPS resource and save to a file. + * Uses BearSSL with the given trust anchors (time check disabled). + * Follows up to max_redirects HTTP 301/302 redirects. + * Returns 0 on success, -1 on failure. + */ + static int download_https(const char *host, const char *path, + uint16_t port, const char *save_path, + br_x509_trust_anchor *anchors, size_t anchor_count, + int max_redirects); +}; diff --git a/libcurl/lib/vtls/cert_pinning.cpp b/libcurl/lib/vtls/cert_pinning.cpp new file mode 100644 index 0000000..bbc5719 --- /dev/null +++ b/libcurl/lib/vtls/cert_pinning.cpp @@ -0,0 +1,150 @@ +#include "cert_pinning.h" +#include "ssl_debug.h" + +#include +#include + +cert_pinning::pin_entry cert_pinning::pins[MAX_PINNED_HOSTS]; +bool cert_pinning::initialized = false; + +void cert_pinning::initialize() +{ + if (initialized) return; + + memset(pins, 0, sizeof(pins)); + initialized = true; + ssl_debug::log_verbose("Certificate pinning initialized\n"); +} + +void cert_pinning::shutdown() +{ + clear(); + initialized = false; +} + +int cert_pinning::find_pin(const char* hostname) +{ + for (int i = 0; i < MAX_PINNED_HOSTS; i++) { + if (pins[i].valid && strcmp(pins[i].hostname, hostname) == 0) { + return i; + } + } + return -1; +} + +bool cert_pinning::add_pin(const char* hostname, const unsigned char* sha256_hash) +{ + if (!initialized) initialize(); + + // Check if already exists + int idx = find_pin(hostname); + if (idx >= 0) { + // Update existing + memcpy(pins[idx].sha256_hash, sha256_hash, 32); + ssl_debug::log_info("Certificate pin updated for %s\n", hostname); + return true; + } + + // Find free slot + for (int i = 0; i < MAX_PINNED_HOSTS; i++) { + if (!pins[i].valid) { + strncpy(pins[i].hostname, hostname, 255); + pins[i].hostname[255] = '\0'; + memcpy(pins[i].sha256_hash, sha256_hash, 32); + pins[i].valid = true; + ssl_debug::log_info("Certificate pin added for %s\n", hostname); + return true; + } + } + + ssl_debug::log_error("Certificate pin table full, cannot add %s\n", hostname); + return false; +} + +void cert_pinning::remove_pin(const char* hostname) +{ + int idx = find_pin(hostname); + if (idx >= 0) { + pins[idx].valid = false; + ssl_debug::log_info("Certificate pin removed for %s\n", hostname); + } +} + +void cert_pinning::clear() +{ + memset(pins, 0, sizeof(pins)); + ssl_debug::log_verbose("All certificate pins cleared\n"); +} + +bool cert_pinning::has_pin(const char* hostname) +{ + return find_pin(hostname) >= 0; +} + +bool cert_pinning::get_pin_hash(const char* hostname, unsigned char* hash_out) +{ + int idx = find_pin(hostname); + if (idx < 0) { + return false; + } + memcpy(hash_out, pins[idx].sha256_hash, 32); + return true; +} + +void cert_pinning::get_cert_hash(br_ssl_engine_context* engine, unsigned char* hash_out) +{ + /* + * This legacy function is kept for API compatibility but is not the + * recommended path. Use verify_hash() with a hash captured by the + * custom X.509 callback in bearssl.c instead. + */ + (void)engine; + memset(hash_out, 0, 32); +} + +bool cert_pinning::verify_hash(const char* hostname, const unsigned char* cert_sha256) +{ + if (!initialized) initialize(); + + int idx = find_pin(hostname); + if (idx < 0) { + /* No pin for this host - allow connection */ + return true; + } + + /* Compare the captured certificate hash against the stored pin */ + if (memcmp(pins[idx].sha256_hash, cert_sha256, 32) == 0) { + ssl_debug::log_info("Certificate pin MATCH for %s\n", hostname); + return true; + } + + /* Pin mismatch */ + ssl_debug::log_error("Certificate pin MISMATCH for %s!\n", hostname); + ssl_debug::log_error(" Expected: %02X%02X%02X%02X...\n", + pins[idx].sha256_hash[0], pins[idx].sha256_hash[1], + pins[idx].sha256_hash[2], pins[idx].sha256_hash[3]); + ssl_debug::log_error(" Got: %02X%02X%02X%02X...\n", + cert_sha256[0], cert_sha256[1], cert_sha256[2], cert_sha256[3]); + return false; +} + +bool cert_pinning::verify(const char* hostname, br_ssl_engine_context* engine) +{ + if (!initialized) initialize(); + + int idx = find_pin(hostname); + if (idx < 0) { + /* No pin for this host - allow connection */ + return true; + } + + /* + * Legacy path: try to use the engine directly. + * The preferred path is verify_hash() called from the X.509 callback + * in bearssl.c, which captures the leaf cert hash during the handshake. + */ + ssl_debug::log_info("Certificate pin check for %s (via engine - use verify_hash for best results)\n", hostname); + + (void)engine; + return true; +} diff --git a/libcurl/lib/vtls/cert_pinning.h b/libcurl/lib/vtls/cert_pinning.h new file mode 100644 index 0000000..58c25b5 --- /dev/null +++ b/libcurl/lib/vtls/cert_pinning.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +#define MAX_PINNED_HOSTS 8 + +class cert_pinning +{ +public: + static void initialize(); + static void shutdown(); + + // Add a pin: hostname + SHA-256 hash of certificate + static bool add_pin(const char* hostname, const unsigned char* sha256_hash); + + // Remove a pin + static void remove_pin(const char* hostname); + + // Clear all pins + static void clear(); + + // Verify certificate hash matches pin (returns true if no pin exists or if pin matches) + static bool verify(const char* hostname, br_ssl_engine_context* engine); + + // Verify a pre-computed SHA-256 hash against stored pin + // Returns true if no pin exists for hostname, or if pin matches the hash + static bool verify_hash(const char* hostname, const unsigned char* cert_sha256); + + // Check if hostname has a pin + static bool has_pin(const char* hostname); + + // Get the stored pin hash for a hostname (returns false if no pin) + static bool get_pin_hash(const char* hostname, unsigned char* hash_out); + + // Get hash of current certificate (for setting up pins) + static void get_cert_hash(br_ssl_engine_context* engine, unsigned char* hash_out); + +private: + struct pin_entry { + char hostname[256]; + unsigned char sha256_hash[32]; + bool valid; + }; + + static pin_entry pins[MAX_PINNED_HOSTS]; + static bool initialized; + + static int find_pin(const char* hostname); +}; diff --git a/libcurl/lib/vtls/certificates.cpp b/libcurl/lib/vtls/certificates.cpp new file mode 100644 index 0000000..8c4020a --- /dev/null +++ b/libcurl/lib/vtls/certificates.cpp @@ -0,0 +1,858 @@ +#include "certificates.h" +#include "ca_loader.h" +#include +#include + +#include "trust_anchors.h" + +#define NUM_TRUST_ANCHORS 750 + +namespace +{ + br_x509_trust_anchor* trust_anchors = NULL; + int trust_anchor_count = 0; + int loaded_from_file = 0; /* 1 = heap-allocated per-anchor data */ +} + +void certificates::initialize_trust_anchors() +{ + if (trust_anchors != NULL) + { + return; + } + trust_anchors = (br_x509_trust_anchor*)malloc(NUM_TRUST_ANCHORS * sizeof br_x509_trust_anchor); + if (trust_anchors == NULL) + { + OutputDebugStringA("certificates: FATAL - malloc failed for trust anchors!\n"); + return; + } + trust_anchor_count = NUM_TRUST_ANCHORS; + loaded_from_file = 0; + trust_anchors[0] = make_rsa_trust_anchor((unsigned char *)TA0_DN, sizeof TA0_DN, (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E); + trust_anchors[1] = make_ec_trust_anchor((unsigned char *)TA1_DN, sizeof TA1_DN, BR_EC_secp384r1, (unsigned char *)TA1_EC_Q, sizeof TA1_EC_Q); + trust_anchors[2] = make_rsa_trust_anchor((unsigned char *)TA2_DN, sizeof TA2_DN, (unsigned char *)TA2_RSA_N, sizeof TA2_RSA_N, (unsigned char *)TA2_RSA_E, sizeof TA2_RSA_E); + trust_anchors[3] = make_rsa_trust_anchor((unsigned char *)TA3_DN, sizeof TA3_DN, (unsigned char *)TA3_RSA_N, sizeof TA3_RSA_N, (unsigned char *)TA3_RSA_E, sizeof TA3_RSA_E); + trust_anchors[4] = make_ec_trust_anchor((unsigned char *)TA4_DN, sizeof TA4_DN, BR_EC_secp384r1, (unsigned char *)TA4_EC_Q, sizeof TA4_EC_Q); + trust_anchors[5] = make_rsa_trust_anchor((unsigned char *)TA5_DN, sizeof TA5_DN, (unsigned char *)TA5_RSA_N, sizeof TA5_RSA_N, (unsigned char *)TA5_RSA_E, sizeof TA5_RSA_E); + trust_anchors[6] = make_rsa_trust_anchor((unsigned char *)TA6_DN, sizeof TA6_DN, (unsigned char *)TA6_RSA_N, sizeof TA6_RSA_N, (unsigned char *)TA6_RSA_E, sizeof TA6_RSA_E); + trust_anchors[7] = make_ec_trust_anchor((unsigned char *)TA7_DN, sizeof TA7_DN, BR_EC_secp384r1, (unsigned char *)TA7_EC_Q, sizeof TA7_EC_Q); + trust_anchors[8] = make_rsa_trust_anchor((unsigned char *)TA8_DN, sizeof TA8_DN, (unsigned char *)TA8_RSA_N, sizeof TA8_RSA_N, (unsigned char *)TA8_RSA_E, sizeof TA8_RSA_E); + trust_anchors[9] = make_ec_trust_anchor((unsigned char *)TA9_DN, sizeof TA9_DN, BR_EC_secp384r1, (unsigned char *)TA9_EC_Q, sizeof TA9_EC_Q); + trust_anchors[10] = make_rsa_trust_anchor((unsigned char *)TA10_DN, sizeof TA10_DN, (unsigned char *)TA10_RSA_N, sizeof TA10_RSA_N, (unsigned char *)TA10_RSA_E, sizeof TA10_RSA_E); + trust_anchors[11] = make_ec_trust_anchor((unsigned char *)TA11_DN, sizeof TA11_DN, BR_EC_secp384r1, (unsigned char *)TA11_EC_Q, sizeof TA11_EC_Q); + trust_anchors[12] = make_rsa_trust_anchor((unsigned char *)TA12_DN, sizeof TA12_DN, (unsigned char *)TA12_RSA_N, sizeof TA12_RSA_N, (unsigned char *)TA12_RSA_E, sizeof TA12_RSA_E); + trust_anchors[13] = make_ec_trust_anchor((unsigned char *)TA13_DN, sizeof TA13_DN, BR_EC_secp384r1, (unsigned char *)TA13_EC_Q, sizeof TA13_EC_Q); + trust_anchors[14] = make_ec_trust_anchor((unsigned char *)TA14_DN, sizeof TA14_DN, BR_EC_secp384r1, (unsigned char *)TA14_EC_Q, sizeof TA14_EC_Q); + trust_anchors[15] = make_ec_trust_anchor((unsigned char *)TA15_DN, sizeof TA15_DN, BR_EC_secp256r1, (unsigned char *)TA15_EC_Q, sizeof TA15_EC_Q); + trust_anchors[16] = make_rsa_trust_anchor((unsigned char *)TA16_DN, sizeof TA16_DN, (unsigned char *)TA16_RSA_N, sizeof TA16_RSA_N, (unsigned char *)TA16_RSA_E, sizeof TA16_RSA_E); + trust_anchors[17] = make_rsa_trust_anchor((unsigned char *)TA17_DN, sizeof TA17_DN, (unsigned char *)TA17_RSA_N, sizeof TA17_RSA_N, (unsigned char *)TA17_RSA_E, sizeof TA17_RSA_E); + trust_anchors[18] = make_rsa_trust_anchor((unsigned char *)TA18_DN, sizeof TA18_DN, (unsigned char *)TA18_RSA_N, sizeof TA18_RSA_N, (unsigned char *)TA18_RSA_E, sizeof TA18_RSA_E); + trust_anchors[19] = make_rsa_trust_anchor((unsigned char *)TA19_DN, sizeof TA19_DN, (unsigned char *)TA19_RSA_N, sizeof TA19_RSA_N, (unsigned char *)TA19_RSA_E, sizeof TA19_RSA_E); + trust_anchors[20] = make_ec_trust_anchor((unsigned char *)TA20_DN, sizeof TA20_DN, BR_EC_secp384r1, (unsigned char *)TA20_EC_Q, sizeof TA20_EC_Q); + trust_anchors[21] = make_rsa_trust_anchor((unsigned char *)TA21_DN, sizeof TA21_DN, (unsigned char *)TA21_RSA_N, sizeof TA21_RSA_N, (unsigned char *)TA21_RSA_E, sizeof TA21_RSA_E); + trust_anchors[22] = make_ec_trust_anchor((unsigned char *)TA22_DN, sizeof TA22_DN, BR_EC_secp384r1, (unsigned char *)TA22_EC_Q, sizeof TA22_EC_Q); + trust_anchors[23] = make_ec_trust_anchor((unsigned char *)TA23_DN, sizeof TA23_DN, BR_EC_secp256r1, (unsigned char *)TA23_EC_Q, sizeof TA23_EC_Q); + trust_anchors[24] = make_rsa_trust_anchor((unsigned char *)TA24_DN, sizeof TA24_DN, (unsigned char *)TA24_RSA_N, sizeof TA24_RSA_N, (unsigned char *)TA24_RSA_E, sizeof TA24_RSA_E); + trust_anchors[25] = make_ec_trust_anchor((unsigned char *)TA25_DN, sizeof TA25_DN, BR_EC_secp384r1, (unsigned char *)TA25_EC_Q, sizeof TA25_EC_Q); + trust_anchors[26] = make_ec_trust_anchor((unsigned char *)TA26_DN, sizeof TA26_DN, BR_EC_secp384r1, (unsigned char *)TA26_EC_Q, sizeof TA26_EC_Q); + trust_anchors[27] = make_rsa_trust_anchor((unsigned char *)TA27_DN, sizeof TA27_DN, (unsigned char *)TA27_RSA_N, sizeof TA27_RSA_N, (unsigned char *)TA27_RSA_E, sizeof TA27_RSA_E); + trust_anchors[28] = make_rsa_trust_anchor((unsigned char *)TA28_DN, sizeof TA28_DN, (unsigned char *)TA28_RSA_N, sizeof TA28_RSA_N, (unsigned char *)TA28_RSA_E, sizeof TA28_RSA_E); + trust_anchors[29] = make_rsa_trust_anchor((unsigned char *)TA29_DN, sizeof TA29_DN, (unsigned char *)TA29_RSA_N, sizeof TA29_RSA_N, (unsigned char *)TA29_RSA_E, sizeof TA29_RSA_E); + trust_anchors[30] = make_rsa_trust_anchor((unsigned char *)TA30_DN, sizeof TA30_DN, (unsigned char *)TA30_RSA_N, sizeof TA30_RSA_N, (unsigned char *)TA30_RSA_E, sizeof TA30_RSA_E); + trust_anchors[31] = make_rsa_trust_anchor((unsigned char *)TA31_DN, sizeof TA31_DN, (unsigned char *)TA31_RSA_N, sizeof TA31_RSA_N, (unsigned char *)TA31_RSA_E, sizeof TA31_RSA_E); + trust_anchors[32] = make_rsa_trust_anchor((unsigned char *)TA32_DN, sizeof TA32_DN, (unsigned char *)TA32_RSA_N, sizeof TA32_RSA_N, (unsigned char *)TA32_RSA_E, sizeof TA32_RSA_E); + trust_anchors[33] = make_rsa_trust_anchor((unsigned char *)TA33_DN, sizeof TA33_DN, (unsigned char *)TA33_RSA_N, sizeof TA33_RSA_N, (unsigned char *)TA33_RSA_E, sizeof TA33_RSA_E); + trust_anchors[34] = make_rsa_trust_anchor((unsigned char *)TA34_DN, sizeof TA34_DN, (unsigned char *)TA34_RSA_N, sizeof TA34_RSA_N, (unsigned char *)TA34_RSA_E, sizeof TA34_RSA_E); + trust_anchors[35] = make_rsa_trust_anchor((unsigned char *)TA35_DN, sizeof TA35_DN, (unsigned char *)TA35_RSA_N, sizeof TA35_RSA_N, (unsigned char *)TA35_RSA_E, sizeof TA35_RSA_E); + trust_anchors[36] = make_ec_trust_anchor((unsigned char *)TA36_DN, sizeof TA36_DN, BR_EC_secp384r1, (unsigned char *)TA36_EC_Q, sizeof TA36_EC_Q); + trust_anchors[37] = make_rsa_trust_anchor((unsigned char *)TA37_DN, sizeof TA37_DN, (unsigned char *)TA37_RSA_N, sizeof TA37_RSA_N, (unsigned char *)TA37_RSA_E, sizeof TA37_RSA_E); + trust_anchors[38] = make_rsa_trust_anchor((unsigned char *)TA38_DN, sizeof TA38_DN, (unsigned char *)TA38_RSA_N, sizeof TA38_RSA_N, (unsigned char *)TA38_RSA_E, sizeof TA38_RSA_E); + trust_anchors[39] = make_ec_trust_anchor((unsigned char *)TA39_DN, sizeof TA39_DN, BR_EC_secp384r1, (unsigned char *)TA39_EC_Q, sizeof TA39_EC_Q); + trust_anchors[40] = make_rsa_trust_anchor((unsigned char *)TA40_DN, sizeof TA40_DN, (unsigned char *)TA40_RSA_N, sizeof TA40_RSA_N, (unsigned char *)TA40_RSA_E, sizeof TA40_RSA_E); + trust_anchors[41] = make_ec_trust_anchor((unsigned char *)TA41_DN, sizeof TA41_DN, BR_EC_secp384r1, (unsigned char *)TA41_EC_Q, sizeof TA41_EC_Q); + trust_anchors[42] = make_rsa_trust_anchor((unsigned char *)TA42_DN, sizeof TA42_DN, (unsigned char *)TA42_RSA_N, sizeof TA42_RSA_N, (unsigned char *)TA42_RSA_E, sizeof TA42_RSA_E); + trust_anchors[43] = make_rsa_trust_anchor((unsigned char *)TA43_DN, sizeof TA43_DN, (unsigned char *)TA43_RSA_N, sizeof TA43_RSA_N, (unsigned char *)TA43_RSA_E, sizeof TA43_RSA_E); + trust_anchors[44] = make_rsa_trust_anchor((unsigned char *)TA44_DN, sizeof TA44_DN, (unsigned char *)TA44_RSA_N, sizeof TA44_RSA_N, (unsigned char *)TA44_RSA_E, sizeof TA44_RSA_E); + trust_anchors[45] = make_ec_trust_anchor((unsigned char *)TA45_DN, sizeof TA45_DN, BR_EC_secp384r1, (unsigned char *)TA45_EC_Q, sizeof TA45_EC_Q); + trust_anchors[46] = make_rsa_trust_anchor((unsigned char *)TA46_DN, sizeof TA46_DN, (unsigned char *)TA46_RSA_N, sizeof TA46_RSA_N, (unsigned char *)TA46_RSA_E, sizeof TA46_RSA_E); + trust_anchors[47] = make_rsa_trust_anchor((unsigned char *)TA47_DN, sizeof TA47_DN, (unsigned char *)TA47_RSA_N, sizeof TA47_RSA_N, (unsigned char *)TA47_RSA_E, sizeof TA47_RSA_E); + trust_anchors[48] = make_rsa_trust_anchor((unsigned char *)TA48_DN, sizeof TA48_DN, (unsigned char *)TA48_RSA_N, sizeof TA48_RSA_N, (unsigned char *)TA48_RSA_E, sizeof TA48_RSA_E); + trust_anchors[49] = make_rsa_trust_anchor((unsigned char *)TA49_DN, sizeof TA49_DN, (unsigned char *)TA49_RSA_N, sizeof TA49_RSA_N, (unsigned char *)TA49_RSA_E, sizeof TA49_RSA_E); + trust_anchors[50] = make_rsa_trust_anchor((unsigned char *)TA50_DN, sizeof TA50_DN, (unsigned char *)TA50_RSA_N, sizeof TA50_RSA_N, (unsigned char *)TA50_RSA_E, sizeof TA50_RSA_E); + trust_anchors[51] = make_rsa_trust_anchor((unsigned char *)TA51_DN, sizeof TA51_DN, (unsigned char *)TA51_RSA_N, sizeof TA51_RSA_N, (unsigned char *)TA51_RSA_E, sizeof TA51_RSA_E); + trust_anchors[52] = make_ec_trust_anchor((unsigned char *)TA52_DN, sizeof TA52_DN, BR_EC_secp384r1, (unsigned char *)TA52_EC_Q, sizeof TA52_EC_Q); + trust_anchors[53] = make_rsa_trust_anchor((unsigned char *)TA53_DN, sizeof TA53_DN, (unsigned char *)TA53_RSA_N, sizeof TA53_RSA_N, (unsigned char *)TA53_RSA_E, sizeof TA53_RSA_E); + trust_anchors[54] = make_rsa_trust_anchor((unsigned char *)TA54_DN, sizeof TA54_DN, (unsigned char *)TA54_RSA_N, sizeof TA54_RSA_N, (unsigned char *)TA54_RSA_E, sizeof TA54_RSA_E); + trust_anchors[55] = make_rsa_trust_anchor((unsigned char *)TA55_DN, sizeof TA55_DN, (unsigned char *)TA55_RSA_N, sizeof TA55_RSA_N, (unsigned char *)TA55_RSA_E, sizeof TA55_RSA_E); + trust_anchors[56] = make_rsa_trust_anchor((unsigned char *)TA56_DN, sizeof TA56_DN, (unsigned char *)TA56_RSA_N, sizeof TA56_RSA_N, (unsigned char *)TA56_RSA_E, sizeof TA56_RSA_E); + trust_anchors[57] = make_ec_trust_anchor((unsigned char *)TA57_DN, sizeof TA57_DN, BR_EC_secp384r1, (unsigned char *)TA57_EC_Q, sizeof TA57_EC_Q); + trust_anchors[58] = make_rsa_trust_anchor((unsigned char *)TA58_DN, sizeof TA58_DN, (unsigned char *)TA58_RSA_N, sizeof TA58_RSA_N, (unsigned char *)TA58_RSA_E, sizeof TA58_RSA_E); + trust_anchors[59] = make_rsa_trust_anchor((unsigned char *)TA59_DN, sizeof TA59_DN, (unsigned char *)TA59_RSA_N, sizeof TA59_RSA_N, (unsigned char *)TA59_RSA_E, sizeof TA59_RSA_E); + trust_anchors[60] = make_ec_trust_anchor((unsigned char *)TA60_DN, sizeof TA60_DN, BR_EC_secp384r1, (unsigned char *)TA60_EC_Q, sizeof TA60_EC_Q); + trust_anchors[61] = make_rsa_trust_anchor((unsigned char *)TA61_DN, sizeof TA61_DN, (unsigned char *)TA61_RSA_N, sizeof TA61_RSA_N, (unsigned char *)TA61_RSA_E, sizeof TA61_RSA_E); + trust_anchors[62] = make_ec_trust_anchor((unsigned char *)TA62_DN, sizeof TA62_DN, BR_EC_secp384r1, (unsigned char *)TA62_EC_Q, sizeof TA62_EC_Q); + trust_anchors[63] = make_rsa_trust_anchor((unsigned char *)TA63_DN, sizeof TA63_DN, (unsigned char *)TA63_RSA_N, sizeof TA63_RSA_N, (unsigned char *)TA63_RSA_E, sizeof TA63_RSA_E); + trust_anchors[64] = make_rsa_trust_anchor((unsigned char *)TA64_DN, sizeof TA64_DN, (unsigned char *)TA64_RSA_N, sizeof TA64_RSA_N, (unsigned char *)TA64_RSA_E, sizeof TA64_RSA_E); + trust_anchors[65] = make_rsa_trust_anchor((unsigned char *)TA65_DN, sizeof TA65_DN, (unsigned char *)TA65_RSA_N, sizeof TA65_RSA_N, (unsigned char *)TA65_RSA_E, sizeof TA65_RSA_E); + trust_anchors[66] = make_rsa_trust_anchor((unsigned char *)TA66_DN, sizeof TA66_DN, (unsigned char *)TA66_RSA_N, sizeof TA66_RSA_N, (unsigned char *)TA66_RSA_E, sizeof TA66_RSA_E); + trust_anchors[67] = make_rsa_trust_anchor((unsigned char *)TA67_DN, sizeof TA67_DN, (unsigned char *)TA67_RSA_N, sizeof TA67_RSA_N, (unsigned char *)TA67_RSA_E, sizeof TA67_RSA_E); + trust_anchors[68] = make_rsa_trust_anchor((unsigned char *)TA68_DN, sizeof TA68_DN, (unsigned char *)TA68_RSA_N, sizeof TA68_RSA_N, (unsigned char *)TA68_RSA_E, sizeof TA68_RSA_E); + trust_anchors[69] = make_ec_trust_anchor((unsigned char *)TA69_DN, sizeof TA69_DN, BR_EC_secp384r1, (unsigned char *)TA69_EC_Q, sizeof TA69_EC_Q); + trust_anchors[70] = make_rsa_trust_anchor((unsigned char *)TA70_DN, sizeof TA70_DN, (unsigned char *)TA70_RSA_N, sizeof TA70_RSA_N, (unsigned char *)TA70_RSA_E, sizeof TA70_RSA_E); + trust_anchors[71] = make_rsa_trust_anchor((unsigned char *)TA71_DN, sizeof TA71_DN, (unsigned char *)TA71_RSA_N, sizeof TA71_RSA_N, (unsigned char *)TA71_RSA_E, sizeof TA71_RSA_E); + trust_anchors[72] = make_rsa_trust_anchor((unsigned char *)TA72_DN, sizeof TA72_DN, (unsigned char *)TA72_RSA_N, sizeof TA72_RSA_N, (unsigned char *)TA72_RSA_E, sizeof TA72_RSA_E); + trust_anchors[73] = make_rsa_trust_anchor((unsigned char *)TA73_DN, sizeof TA73_DN, (unsigned char *)TA73_RSA_N, sizeof TA73_RSA_N, (unsigned char *)TA73_RSA_E, sizeof TA73_RSA_E); + trust_anchors[74] = make_ec_trust_anchor((unsigned char *)TA74_DN, sizeof TA74_DN, BR_EC_secp384r1, (unsigned char *)TA74_EC_Q, sizeof TA74_EC_Q); + trust_anchors[75] = make_rsa_trust_anchor((unsigned char *)TA75_DN, sizeof TA75_DN, (unsigned char *)TA75_RSA_N, sizeof TA75_RSA_N, (unsigned char *)TA75_RSA_E, sizeof TA75_RSA_E); + trust_anchors[76] = make_rsa_trust_anchor((unsigned char *)TA76_DN, sizeof TA76_DN, (unsigned char *)TA76_RSA_N, sizeof TA76_RSA_N, (unsigned char *)TA76_RSA_E, sizeof TA76_RSA_E); + trust_anchors[77] = make_ec_trust_anchor((unsigned char *)TA77_DN, sizeof TA77_DN, BR_EC_secp384r1, (unsigned char *)TA77_EC_Q, sizeof TA77_EC_Q); + trust_anchors[78] = make_rsa_trust_anchor((unsigned char *)TA78_DN, sizeof TA78_DN, (unsigned char *)TA78_RSA_N, sizeof TA78_RSA_N, (unsigned char *)TA78_RSA_E, sizeof TA78_RSA_E); + trust_anchors[79] = make_rsa_trust_anchor((unsigned char *)TA79_DN, sizeof TA79_DN, (unsigned char *)TA79_RSA_N, sizeof TA79_RSA_N, (unsigned char *)TA79_RSA_E, sizeof TA79_RSA_E); + trust_anchors[80] = make_rsa_trust_anchor((unsigned char *)TA80_DN, sizeof TA80_DN, (unsigned char *)TA80_RSA_N, sizeof TA80_RSA_N, (unsigned char *)TA80_RSA_E, sizeof TA80_RSA_E); + trust_anchors[81] = make_rsa_trust_anchor((unsigned char *)TA81_DN, sizeof TA81_DN, (unsigned char *)TA81_RSA_N, sizeof TA81_RSA_N, (unsigned char *)TA81_RSA_E, sizeof TA81_RSA_E); + trust_anchors[82] = make_rsa_trust_anchor((unsigned char *)TA82_DN, sizeof TA82_DN, (unsigned char *)TA82_RSA_N, sizeof TA82_RSA_N, (unsigned char *)TA82_RSA_E, sizeof TA82_RSA_E); + trust_anchors[83] = make_rsa_trust_anchor((unsigned char *)TA83_DN, sizeof TA83_DN, (unsigned char *)TA83_RSA_N, sizeof TA83_RSA_N, (unsigned char *)TA83_RSA_E, sizeof TA83_RSA_E); + trust_anchors[84] = make_rsa_trust_anchor((unsigned char *)TA84_DN, sizeof TA84_DN, (unsigned char *)TA84_RSA_N, sizeof TA84_RSA_N, (unsigned char *)TA84_RSA_E, sizeof TA84_RSA_E); + trust_anchors[85] = make_ec_trust_anchor((unsigned char *)TA85_DN, sizeof TA85_DN, BR_EC_secp384r1, (unsigned char *)TA85_EC_Q, sizeof TA85_EC_Q); + trust_anchors[86] = make_ec_trust_anchor((unsigned char *)TA86_DN, sizeof TA86_DN, BR_EC_secp384r1, (unsigned char *)TA86_EC_Q, sizeof TA86_EC_Q); + trust_anchors[87] = make_ec_trust_anchor((unsigned char *)TA87_DN, sizeof TA87_DN, BR_EC_secp384r1, (unsigned char *)TA87_EC_Q, sizeof TA87_EC_Q); + trust_anchors[88] = make_rsa_trust_anchor((unsigned char *)TA88_DN, sizeof TA88_DN, (unsigned char *)TA88_RSA_N, sizeof TA88_RSA_N, (unsigned char *)TA88_RSA_E, sizeof TA88_RSA_E); + trust_anchors[89] = make_ec_trust_anchor((unsigned char *)TA89_DN, sizeof TA89_DN, BR_EC_secp384r1, (unsigned char *)TA89_EC_Q, sizeof TA89_EC_Q); + trust_anchors[90] = make_rsa_trust_anchor((unsigned char *)TA90_DN, sizeof TA90_DN, (unsigned char *)TA90_RSA_N, sizeof TA90_RSA_N, (unsigned char *)TA90_RSA_E, sizeof TA90_RSA_E); + trust_anchors[91] = make_rsa_trust_anchor((unsigned char *)TA91_DN, sizeof TA91_DN, (unsigned char *)TA91_RSA_N, sizeof TA91_RSA_N, (unsigned char *)TA91_RSA_E, sizeof TA91_RSA_E); + trust_anchors[92] = make_rsa_trust_anchor((unsigned char *)TA92_DN, sizeof TA92_DN, (unsigned char *)TA92_RSA_N, sizeof TA92_RSA_N, (unsigned char *)TA92_RSA_E, sizeof TA92_RSA_E); + trust_anchors[93] = make_rsa_trust_anchor((unsigned char *)TA93_DN, sizeof TA93_DN, (unsigned char *)TA93_RSA_N, sizeof TA93_RSA_N, (unsigned char *)TA93_RSA_E, sizeof TA93_RSA_E); + trust_anchors[94] = make_rsa_trust_anchor((unsigned char *)TA94_DN, sizeof TA94_DN, (unsigned char *)TA94_RSA_N, sizeof TA94_RSA_N, (unsigned char *)TA94_RSA_E, sizeof TA94_RSA_E); + trust_anchors[95] = make_rsa_trust_anchor((unsigned char *)TA95_DN, sizeof TA95_DN, (unsigned char *)TA95_RSA_N, sizeof TA95_RSA_N, (unsigned char *)TA95_RSA_E, sizeof TA95_RSA_E); + trust_anchors[96] = make_ec_trust_anchor((unsigned char *)TA96_DN, sizeof TA96_DN, BR_EC_secp384r1, (unsigned char *)TA96_EC_Q, sizeof TA96_EC_Q); + trust_anchors[97] = make_ec_trust_anchor((unsigned char *)TA97_DN, sizeof TA97_DN, BR_EC_secp384r1, (unsigned char *)TA97_EC_Q, sizeof TA97_EC_Q); + trust_anchors[98] = make_rsa_trust_anchor((unsigned char *)TA98_DN, sizeof TA98_DN, (unsigned char *)TA98_RSA_N, sizeof TA98_RSA_N, (unsigned char *)TA98_RSA_E, sizeof TA98_RSA_E); + trust_anchors[99] = make_rsa_trust_anchor((unsigned char *)TA99_DN, sizeof TA99_DN, (unsigned char *)TA99_RSA_N, sizeof TA99_RSA_N, (unsigned char *)TA99_RSA_E, sizeof TA99_RSA_E); + trust_anchors[100] = make_rsa_trust_anchor((unsigned char *)TA100_DN, sizeof TA100_DN, (unsigned char *)TA100_RSA_N, sizeof TA100_RSA_N, (unsigned char *)TA100_RSA_E, sizeof TA100_RSA_E); + trust_anchors[101] = make_rsa_trust_anchor((unsigned char *)TA101_DN, sizeof TA101_DN, (unsigned char *)TA101_RSA_N, sizeof TA101_RSA_N, (unsigned char *)TA101_RSA_E, sizeof TA101_RSA_E); + trust_anchors[102] = make_rsa_trust_anchor((unsigned char *)TA102_DN, sizeof TA102_DN, (unsigned char *)TA102_RSA_N, sizeof TA102_RSA_N, (unsigned char *)TA102_RSA_E, sizeof TA102_RSA_E); + trust_anchors[103] = make_rsa_trust_anchor((unsigned char *)TA103_DN, sizeof TA103_DN, (unsigned char *)TA103_RSA_N, sizeof TA103_RSA_N, (unsigned char *)TA103_RSA_E, sizeof TA103_RSA_E); + trust_anchors[104] = make_rsa_trust_anchor((unsigned char *)TA104_DN, sizeof TA104_DN, (unsigned char *)TA104_RSA_N, sizeof TA104_RSA_N, (unsigned char *)TA104_RSA_E, sizeof TA104_RSA_E); + trust_anchors[105] = make_rsa_trust_anchor((unsigned char *)TA105_DN, sizeof TA105_DN, (unsigned char *)TA105_RSA_N, sizeof TA105_RSA_N, (unsigned char *)TA105_RSA_E, sizeof TA105_RSA_E); + trust_anchors[106] = make_rsa_trust_anchor((unsigned char *)TA106_DN, sizeof TA106_DN, (unsigned char *)TA106_RSA_N, sizeof TA106_RSA_N, (unsigned char *)TA106_RSA_E, sizeof TA106_RSA_E); + trust_anchors[107] = make_ec_trust_anchor((unsigned char *)TA107_DN, sizeof TA107_DN, BR_EC_secp384r1, (unsigned char *)TA107_EC_Q, sizeof TA107_EC_Q); + trust_anchors[108] = make_ec_trust_anchor((unsigned char *)TA108_DN, sizeof TA108_DN, BR_EC_secp384r1, (unsigned char *)TA108_EC_Q, sizeof TA108_EC_Q); + trust_anchors[109] = make_ec_trust_anchor((unsigned char *)TA109_DN, sizeof TA109_DN, BR_EC_secp384r1, (unsigned char *)TA109_EC_Q, sizeof TA109_EC_Q); + trust_anchors[110] = make_rsa_trust_anchor((unsigned char *)TA110_DN, sizeof TA110_DN, (unsigned char *)TA110_RSA_N, sizeof TA110_RSA_N, (unsigned char *)TA110_RSA_E, sizeof TA110_RSA_E); + trust_anchors[111] = make_rsa_trust_anchor((unsigned char *)TA111_DN, sizeof TA111_DN, (unsigned char *)TA111_RSA_N, sizeof TA111_RSA_N, (unsigned char *)TA111_RSA_E, sizeof TA111_RSA_E); + trust_anchors[112] = make_rsa_trust_anchor((unsigned char *)TA112_DN, sizeof TA112_DN, (unsigned char *)TA112_RSA_N, sizeof TA112_RSA_N, (unsigned char *)TA112_RSA_E, sizeof TA112_RSA_E); + trust_anchors[113] = make_rsa_trust_anchor((unsigned char *)TA113_DN, sizeof TA113_DN, (unsigned char *)TA113_RSA_N, sizeof TA113_RSA_N, (unsigned char *)TA113_RSA_E, sizeof TA113_RSA_E); + trust_anchors[114] = make_rsa_trust_anchor((unsigned char *)TA114_DN, sizeof TA114_DN, (unsigned char *)TA114_RSA_N, sizeof TA114_RSA_N, (unsigned char *)TA114_RSA_E, sizeof TA114_RSA_E); + trust_anchors[115] = make_rsa_trust_anchor((unsigned char *)TA115_DN, sizeof TA115_DN, (unsigned char *)TA115_RSA_N, sizeof TA115_RSA_N, (unsigned char *)TA115_RSA_E, sizeof TA115_RSA_E); + trust_anchors[116] = make_rsa_trust_anchor((unsigned char *)TA116_DN, sizeof TA116_DN, (unsigned char *)TA116_RSA_N, sizeof TA116_RSA_N, (unsigned char *)TA116_RSA_E, sizeof TA116_RSA_E); + trust_anchors[117] = make_rsa_trust_anchor((unsigned char *)TA117_DN, sizeof TA117_DN, (unsigned char *)TA117_RSA_N, sizeof TA117_RSA_N, (unsigned char *)TA117_RSA_E, sizeof TA117_RSA_E); + trust_anchors[118] = make_rsa_trust_anchor((unsigned char *)TA118_DN, sizeof TA118_DN, (unsigned char *)TA118_RSA_N, sizeof TA118_RSA_N, (unsigned char *)TA118_RSA_E, sizeof TA118_RSA_E); + trust_anchors[119] = make_rsa_trust_anchor((unsigned char *)TA119_DN, sizeof TA119_DN, (unsigned char *)TA119_RSA_N, sizeof TA119_RSA_N, (unsigned char *)TA119_RSA_E, sizeof TA119_RSA_E); + trust_anchors[120] = make_ec_trust_anchor((unsigned char *)TA120_DN, sizeof TA120_DN, BR_EC_secp384r1, (unsigned char *)TA120_EC_Q, sizeof TA120_EC_Q); + trust_anchors[121] = make_ec_trust_anchor((unsigned char *)TA121_DN, sizeof TA121_DN, BR_EC_secp384r1, (unsigned char *)TA121_EC_Q, sizeof TA121_EC_Q); + trust_anchors[122] = make_ec_trust_anchor((unsigned char *)TA122_DN, sizeof TA122_DN, BR_EC_secp384r1, (unsigned char *)TA122_EC_Q, sizeof TA122_EC_Q); + trust_anchors[123] = make_rsa_trust_anchor((unsigned char *)TA123_DN, sizeof TA123_DN, (unsigned char *)TA123_RSA_N, sizeof TA123_RSA_N, (unsigned char *)TA123_RSA_E, sizeof TA123_RSA_E); + trust_anchors[124] = make_rsa_trust_anchor((unsigned char *)TA124_DN, sizeof TA124_DN, (unsigned char *)TA124_RSA_N, sizeof TA124_RSA_N, (unsigned char *)TA124_RSA_E, sizeof TA124_RSA_E); + trust_anchors[125] = make_ec_trust_anchor((unsigned char *)TA125_DN, sizeof TA125_DN, BR_EC_secp384r1, (unsigned char *)TA125_EC_Q, sizeof TA125_EC_Q); + trust_anchors[126] = make_rsa_trust_anchor((unsigned char *)TA126_DN, sizeof TA126_DN, (unsigned char *)TA126_RSA_N, sizeof TA126_RSA_N, (unsigned char *)TA126_RSA_E, sizeof TA126_RSA_E); + trust_anchors[127] = make_ec_trust_anchor((unsigned char *)TA127_DN, sizeof TA127_DN, BR_EC_secp384r1, (unsigned char *)TA127_EC_Q, sizeof TA127_EC_Q); + trust_anchors[128] = make_ec_trust_anchor((unsigned char *)TA128_DN, sizeof TA128_DN, BR_EC_secp384r1, (unsigned char *)TA128_EC_Q, sizeof TA128_EC_Q); + trust_anchors[129] = make_rsa_trust_anchor((unsigned char *)TA129_DN, sizeof TA129_DN, (unsigned char *)TA129_RSA_N, sizeof TA129_RSA_N, (unsigned char *)TA129_RSA_E, sizeof TA129_RSA_E); + trust_anchors[130] = make_rsa_trust_anchor((unsigned char *)TA130_DN, sizeof TA130_DN, (unsigned char *)TA130_RSA_N, sizeof TA130_RSA_N, (unsigned char *)TA130_RSA_E, sizeof TA130_RSA_E); + trust_anchors[131] = make_rsa_trust_anchor((unsigned char *)TA131_DN, sizeof TA131_DN, (unsigned char *)TA131_RSA_N, sizeof TA131_RSA_N, (unsigned char *)TA131_RSA_E, sizeof TA131_RSA_E); + trust_anchors[132] = make_ec_trust_anchor((unsigned char *)TA132_DN, sizeof TA132_DN, BR_EC_secp384r1, (unsigned char *)TA132_EC_Q, sizeof TA132_EC_Q); + trust_anchors[133] = make_rsa_trust_anchor((unsigned char *)TA133_DN, sizeof TA133_DN, (unsigned char *)TA133_RSA_N, sizeof TA133_RSA_N, (unsigned char *)TA133_RSA_E, sizeof TA133_RSA_E); + trust_anchors[134] = make_rsa_trust_anchor((unsigned char *)TA134_DN, sizeof TA134_DN, (unsigned char *)TA134_RSA_N, sizeof TA134_RSA_N, (unsigned char *)TA134_RSA_E, sizeof TA134_RSA_E); + trust_anchors[135] = make_ec_trust_anchor((unsigned char *)TA135_DN, sizeof TA135_DN, BR_EC_secp384r1, (unsigned char *)TA135_EC_Q, sizeof TA135_EC_Q); + trust_anchors[136] = make_ec_trust_anchor((unsigned char *)TA136_DN, sizeof TA136_DN, BR_EC_secp384r1, (unsigned char *)TA136_EC_Q, sizeof TA136_EC_Q); + trust_anchors[137] = make_rsa_trust_anchor((unsigned char *)TA137_DN, sizeof TA137_DN, (unsigned char *)TA137_RSA_N, sizeof TA137_RSA_N, (unsigned char *)TA137_RSA_E, sizeof TA137_RSA_E); + trust_anchors[138] = make_rsa_trust_anchor((unsigned char *)TA138_DN, sizeof TA138_DN, (unsigned char *)TA138_RSA_N, sizeof TA138_RSA_N, (unsigned char *)TA138_RSA_E, sizeof TA138_RSA_E); + trust_anchors[139] = make_ec_trust_anchor((unsigned char *)TA139_DN, sizeof TA139_DN, BR_EC_secp384r1, (unsigned char *)TA139_EC_Q, sizeof TA139_EC_Q); + trust_anchors[140] = make_ec_trust_anchor((unsigned char *)TA140_DN, sizeof TA140_DN, BR_EC_secp384r1, (unsigned char *)TA140_EC_Q, sizeof TA140_EC_Q); + trust_anchors[141] = make_rsa_trust_anchor((unsigned char *)TA141_DN, sizeof TA141_DN, (unsigned char *)TA141_RSA_N, sizeof TA141_RSA_N, (unsigned char *)TA141_RSA_E, sizeof TA141_RSA_E); + trust_anchors[142] = make_rsa_trust_anchor((unsigned char *)TA142_DN, sizeof TA142_DN, (unsigned char *)TA142_RSA_N, sizeof TA142_RSA_N, (unsigned char *)TA142_RSA_E, sizeof TA142_RSA_E); + trust_anchors[143] = make_ec_trust_anchor((unsigned char *)TA143_DN, sizeof TA143_DN, BR_EC_secp384r1, (unsigned char *)TA143_EC_Q, sizeof TA143_EC_Q); + trust_anchors[144] = make_rsa_trust_anchor((unsigned char *)TA144_DN, sizeof TA144_DN, (unsigned char *)TA144_RSA_N, sizeof TA144_RSA_N, (unsigned char *)TA144_RSA_E, sizeof TA144_RSA_E); + trust_anchors[145] = make_ec_trust_anchor((unsigned char *)TA145_DN, sizeof TA145_DN, BR_EC_secp384r1, (unsigned char *)TA145_EC_Q, sizeof TA145_EC_Q); + trust_anchors[146] = make_ec_trust_anchor((unsigned char *)TA146_DN, sizeof TA146_DN, BR_EC_secp384r1, (unsigned char *)TA146_EC_Q, sizeof TA146_EC_Q); + trust_anchors[147] = make_ec_trust_anchor((unsigned char *)TA147_DN, sizeof TA147_DN, BR_EC_secp256r1, (unsigned char *)TA147_EC_Q, sizeof TA147_EC_Q); + trust_anchors[148] = make_rsa_trust_anchor((unsigned char *)TA148_DN, sizeof TA148_DN, (unsigned char *)TA148_RSA_N, sizeof TA148_RSA_N, (unsigned char *)TA148_RSA_E, sizeof TA148_RSA_E); + trust_anchors[149] = make_rsa_trust_anchor((unsigned char *)TA149_DN, sizeof TA149_DN, (unsigned char *)TA149_RSA_N, sizeof TA149_RSA_N, (unsigned char *)TA149_RSA_E, sizeof TA149_RSA_E); + trust_anchors[150] = make_rsa_trust_anchor((unsigned char *)TA150_DN, sizeof TA150_DN, (unsigned char *)TA150_RSA_N, sizeof TA150_RSA_N, (unsigned char *)TA150_RSA_E, sizeof TA150_RSA_E); + trust_anchors[151] = make_ec_trust_anchor((unsigned char *)TA151_DN, sizeof TA151_DN, BR_EC_secp384r1, (unsigned char *)TA151_EC_Q, sizeof TA151_EC_Q); + trust_anchors[152] = make_rsa_trust_anchor((unsigned char *)TA152_DN, sizeof TA152_DN, (unsigned char *)TA152_RSA_N, sizeof TA152_RSA_N, (unsigned char *)TA152_RSA_E, sizeof TA152_RSA_E); + trust_anchors[153] = make_ec_trust_anchor((unsigned char *)TA153_DN, sizeof TA153_DN, BR_EC_secp384r1, (unsigned char *)TA153_EC_Q, sizeof TA153_EC_Q); + trust_anchors[154] = make_rsa_trust_anchor((unsigned char *)TA154_DN, sizeof TA154_DN, (unsigned char *)TA154_RSA_N, sizeof TA154_RSA_N, (unsigned char *)TA154_RSA_E, sizeof TA154_RSA_E); + trust_anchors[155] = make_rsa_trust_anchor((unsigned char *)TA155_DN, sizeof TA155_DN, (unsigned char *)TA155_RSA_N, sizeof TA155_RSA_N, (unsigned char *)TA155_RSA_E, sizeof TA155_RSA_E); + trust_anchors[156] = make_rsa_trust_anchor((unsigned char *)TA156_DN, sizeof TA156_DN, (unsigned char *)TA156_RSA_N, sizeof TA156_RSA_N, (unsigned char *)TA156_RSA_E, sizeof TA156_RSA_E); + trust_anchors[157] = make_rsa_trust_anchor((unsigned char *)TA157_DN, sizeof TA157_DN, (unsigned char *)TA157_RSA_N, sizeof TA157_RSA_N, (unsigned char *)TA157_RSA_E, sizeof TA157_RSA_E); + trust_anchors[158] = make_rsa_trust_anchor((unsigned char *)TA158_DN, sizeof TA158_DN, (unsigned char *)TA158_RSA_N, sizeof TA158_RSA_N, (unsigned char *)TA158_RSA_E, sizeof TA158_RSA_E); + trust_anchors[159] = make_rsa_trust_anchor((unsigned char *)TA159_DN, sizeof TA159_DN, (unsigned char *)TA159_RSA_N, sizeof TA159_RSA_N, (unsigned char *)TA159_RSA_E, sizeof TA159_RSA_E); + trust_anchors[160] = make_rsa_trust_anchor((unsigned char *)TA160_DN, sizeof TA160_DN, (unsigned char *)TA160_RSA_N, sizeof TA160_RSA_N, (unsigned char *)TA160_RSA_E, sizeof TA160_RSA_E); + trust_anchors[161] = make_ec_trust_anchor((unsigned char *)TA161_DN, sizeof TA161_DN, BR_EC_secp384r1, (unsigned char *)TA161_EC_Q, sizeof TA161_EC_Q); + trust_anchors[162] = make_ec_trust_anchor((unsigned char *)TA162_DN, sizeof TA162_DN, BR_EC_secp384r1, (unsigned char *)TA162_EC_Q, sizeof TA162_EC_Q); + trust_anchors[163] = make_rsa_trust_anchor((unsigned char *)TA163_DN, sizeof TA163_DN, (unsigned char *)TA163_RSA_N, sizeof TA163_RSA_N, (unsigned char *)TA163_RSA_E, sizeof TA163_RSA_E); + trust_anchors[164] = make_rsa_trust_anchor((unsigned char *)TA164_DN, sizeof TA164_DN, (unsigned char *)TA164_RSA_N, sizeof TA164_RSA_N, (unsigned char *)TA164_RSA_E, sizeof TA164_RSA_E); + trust_anchors[165] = make_rsa_trust_anchor((unsigned char *)TA165_DN, sizeof TA165_DN, (unsigned char *)TA165_RSA_N, sizeof TA165_RSA_N, (unsigned char *)TA165_RSA_E, sizeof TA165_RSA_E); + trust_anchors[166] = make_ec_trust_anchor((unsigned char *)TA166_DN, sizeof TA166_DN, BR_EC_secp384r1, (unsigned char *)TA166_EC_Q, sizeof TA166_EC_Q); + trust_anchors[167] = make_rsa_trust_anchor((unsigned char *)TA167_DN, sizeof TA167_DN, (unsigned char *)TA167_RSA_N, sizeof TA167_RSA_N, (unsigned char *)TA167_RSA_E, sizeof TA167_RSA_E); + trust_anchors[168] = make_rsa_trust_anchor((unsigned char *)TA168_DN, sizeof TA168_DN, (unsigned char *)TA168_RSA_N, sizeof TA168_RSA_N, (unsigned char *)TA168_RSA_E, sizeof TA168_RSA_E); + trust_anchors[169] = make_rsa_trust_anchor((unsigned char *)TA169_DN, sizeof TA169_DN, (unsigned char *)TA169_RSA_N, sizeof TA169_RSA_N, (unsigned char *)TA169_RSA_E, sizeof TA169_RSA_E); + trust_anchors[170] = make_rsa_trust_anchor((unsigned char *)TA170_DN, sizeof TA170_DN, (unsigned char *)TA170_RSA_N, sizeof TA170_RSA_N, (unsigned char *)TA170_RSA_E, sizeof TA170_RSA_E); + trust_anchors[171] = make_ec_trust_anchor((unsigned char *)TA171_DN, sizeof TA171_DN, BR_EC_secp384r1, (unsigned char *)TA171_EC_Q, sizeof TA171_EC_Q); + trust_anchors[172] = make_rsa_trust_anchor((unsigned char *)TA172_DN, sizeof TA172_DN, (unsigned char *)TA172_RSA_N, sizeof TA172_RSA_N, (unsigned char *)TA172_RSA_E, sizeof TA172_RSA_E); + trust_anchors[173] = make_ec_trust_anchor((unsigned char *)TA173_DN, sizeof TA173_DN, BR_EC_secp256r1, (unsigned char *)TA173_EC_Q, sizeof TA173_EC_Q); + trust_anchors[174] = make_rsa_trust_anchor((unsigned char *)TA174_DN, sizeof TA174_DN, (unsigned char *)TA174_RSA_N, sizeof TA174_RSA_N, (unsigned char *)TA174_RSA_E, sizeof TA174_RSA_E); + trust_anchors[175] = make_ec_trust_anchor((unsigned char *)TA175_DN, sizeof TA175_DN, BR_EC_secp384r1, (unsigned char *)TA175_EC_Q, sizeof TA175_EC_Q); + trust_anchors[176] = make_rsa_trust_anchor((unsigned char *)TA176_DN, sizeof TA176_DN, (unsigned char *)TA176_RSA_N, sizeof TA176_RSA_N, (unsigned char *)TA176_RSA_E, sizeof TA176_RSA_E); + trust_anchors[177] = make_rsa_trust_anchor((unsigned char *)TA177_DN, sizeof TA177_DN, (unsigned char *)TA177_RSA_N, sizeof TA177_RSA_N, (unsigned char *)TA177_RSA_E, sizeof TA177_RSA_E); + trust_anchors[178] = make_ec_trust_anchor((unsigned char *)TA178_DN, sizeof TA178_DN, BR_EC_secp384r1, (unsigned char *)TA178_EC_Q, sizeof TA178_EC_Q); + trust_anchors[179] = make_rsa_trust_anchor((unsigned char *)TA179_DN, sizeof TA179_DN, (unsigned char *)TA179_RSA_N, sizeof TA179_RSA_N, (unsigned char *)TA179_RSA_E, sizeof TA179_RSA_E); + trust_anchors[180] = make_rsa_trust_anchor((unsigned char *)TA180_DN, sizeof TA180_DN, (unsigned char *)TA180_RSA_N, sizeof TA180_RSA_N, (unsigned char *)TA180_RSA_E, sizeof TA180_RSA_E); + trust_anchors[181] = make_rsa_trust_anchor((unsigned char *)TA181_DN, sizeof TA181_DN, (unsigned char *)TA181_RSA_N, sizeof TA181_RSA_N, (unsigned char *)TA181_RSA_E, sizeof TA181_RSA_E); + trust_anchors[182] = make_ec_trust_anchor((unsigned char *)TA182_DN, sizeof TA182_DN, BR_EC_secp384r1, (unsigned char *)TA182_EC_Q, sizeof TA182_EC_Q); + trust_anchors[183] = make_ec_trust_anchor((unsigned char *)TA183_DN, sizeof TA183_DN, BR_EC_secp384r1, (unsigned char *)TA183_EC_Q, sizeof TA183_EC_Q); + trust_anchors[184] = make_rsa_trust_anchor((unsigned char *)TA184_DN, sizeof TA184_DN, (unsigned char *)TA184_RSA_N, sizeof TA184_RSA_N, (unsigned char *)TA184_RSA_E, sizeof TA184_RSA_E); + trust_anchors[185] = make_rsa_trust_anchor((unsigned char *)TA185_DN, sizeof TA185_DN, (unsigned char *)TA185_RSA_N, sizeof TA185_RSA_N, (unsigned char *)TA185_RSA_E, sizeof TA185_RSA_E); + trust_anchors[186] = make_rsa_trust_anchor((unsigned char *)TA186_DN, sizeof TA186_DN, (unsigned char *)TA186_RSA_N, sizeof TA186_RSA_N, (unsigned char *)TA186_RSA_E, sizeof TA186_RSA_E); + trust_anchors[187] = make_rsa_trust_anchor((unsigned char *)TA187_DN, sizeof TA187_DN, (unsigned char *)TA187_RSA_N, sizeof TA187_RSA_N, (unsigned char *)TA187_RSA_E, sizeof TA187_RSA_E); + trust_anchors[188] = make_rsa_trust_anchor((unsigned char *)TA188_DN, sizeof TA188_DN, (unsigned char *)TA188_RSA_N, sizeof TA188_RSA_N, (unsigned char *)TA188_RSA_E, sizeof TA188_RSA_E); + trust_anchors[189] = make_rsa_trust_anchor((unsigned char *)TA189_DN, sizeof TA189_DN, (unsigned char *)TA189_RSA_N, sizeof TA189_RSA_N, (unsigned char *)TA189_RSA_E, sizeof TA189_RSA_E); + trust_anchors[190] = make_rsa_trust_anchor((unsigned char *)TA190_DN, sizeof TA190_DN, (unsigned char *)TA190_RSA_N, sizeof TA190_RSA_N, (unsigned char *)TA190_RSA_E, sizeof TA190_RSA_E); + trust_anchors[191] = make_ec_trust_anchor((unsigned char *)TA191_DN, sizeof TA191_DN, BR_EC_secp384r1, (unsigned char *)TA191_EC_Q, sizeof TA191_EC_Q); + trust_anchors[192] = make_rsa_trust_anchor((unsigned char *)TA192_DN, sizeof TA192_DN, (unsigned char *)TA192_RSA_N, sizeof TA192_RSA_N, (unsigned char *)TA192_RSA_E, sizeof TA192_RSA_E); + trust_anchors[193] = make_rsa_trust_anchor((unsigned char *)TA193_DN, sizeof TA193_DN, (unsigned char *)TA193_RSA_N, sizeof TA193_RSA_N, (unsigned char *)TA193_RSA_E, sizeof TA193_RSA_E); + trust_anchors[194] = make_rsa_trust_anchor((unsigned char *)TA194_DN, sizeof TA194_DN, (unsigned char *)TA194_RSA_N, sizeof TA194_RSA_N, (unsigned char *)TA194_RSA_E, sizeof TA194_RSA_E); + trust_anchors[195] = make_rsa_trust_anchor((unsigned char *)TA195_DN, sizeof TA195_DN, (unsigned char *)TA195_RSA_N, sizeof TA195_RSA_N, (unsigned char *)TA195_RSA_E, sizeof TA195_RSA_E); + trust_anchors[196] = make_ec_trust_anchor((unsigned char *)TA196_DN, sizeof TA196_DN, BR_EC_secp384r1, (unsigned char *)TA196_EC_Q, sizeof TA196_EC_Q); + trust_anchors[197] = make_rsa_trust_anchor((unsigned char *)TA197_DN, sizeof TA197_DN, (unsigned char *)TA197_RSA_N, sizeof TA197_RSA_N, (unsigned char *)TA197_RSA_E, sizeof TA197_RSA_E); + trust_anchors[198] = make_rsa_trust_anchor((unsigned char *)TA198_DN, sizeof TA198_DN, (unsigned char *)TA198_RSA_N, sizeof TA198_RSA_N, (unsigned char *)TA198_RSA_E, sizeof TA198_RSA_E); + trust_anchors[199] = make_rsa_trust_anchor((unsigned char *)TA199_DN, sizeof TA199_DN, (unsigned char *)TA199_RSA_N, sizeof TA199_RSA_N, (unsigned char *)TA199_RSA_E, sizeof TA199_RSA_E); + trust_anchors[200] = make_ec_trust_anchor((unsigned char *)TA200_DN, sizeof TA200_DN, BR_EC_secp256r1, (unsigned char *)TA200_EC_Q, sizeof TA200_EC_Q); + trust_anchors[201] = make_ec_trust_anchor((unsigned char *)TA201_DN, sizeof TA201_DN, BR_EC_secp384r1, (unsigned char *)TA201_EC_Q, sizeof TA201_EC_Q); + trust_anchors[202] = make_rsa_trust_anchor((unsigned char *)TA202_DN, sizeof TA202_DN, (unsigned char *)TA202_RSA_N, sizeof TA202_RSA_N, (unsigned char *)TA202_RSA_E, sizeof TA202_RSA_E); + trust_anchors[203] = make_rsa_trust_anchor((unsigned char *)TA203_DN, sizeof TA203_DN, (unsigned char *)TA203_RSA_N, sizeof TA203_RSA_N, (unsigned char *)TA203_RSA_E, sizeof TA203_RSA_E); + trust_anchors[204] = make_ec_trust_anchor((unsigned char *)TA204_DN, sizeof TA204_DN, BR_EC_secp384r1, (unsigned char *)TA204_EC_Q, sizeof TA204_EC_Q); + trust_anchors[205] = make_rsa_trust_anchor((unsigned char *)TA205_DN, sizeof TA205_DN, (unsigned char *)TA205_RSA_N, sizeof TA205_RSA_N, (unsigned char *)TA205_RSA_E, sizeof TA205_RSA_E); + trust_anchors[206] = make_rsa_trust_anchor((unsigned char *)TA206_DN, sizeof TA206_DN, (unsigned char *)TA206_RSA_N, sizeof TA206_RSA_N, (unsigned char *)TA206_RSA_E, sizeof TA206_RSA_E); + trust_anchors[207] = make_ec_trust_anchor((unsigned char *)TA207_DN, sizeof TA207_DN, BR_EC_secp256r1, (unsigned char *)TA207_EC_Q, sizeof TA207_EC_Q); + trust_anchors[208] = make_rsa_trust_anchor((unsigned char *)TA208_DN, sizeof TA208_DN, (unsigned char *)TA208_RSA_N, sizeof TA208_RSA_N, (unsigned char *)TA208_RSA_E, sizeof TA208_RSA_E); + trust_anchors[209] = make_rsa_trust_anchor((unsigned char *)TA209_DN, sizeof TA209_DN, (unsigned char *)TA209_RSA_N, sizeof TA209_RSA_N, (unsigned char *)TA209_RSA_E, sizeof TA209_RSA_E); + trust_anchors[210] = make_rsa_trust_anchor((unsigned char *)TA210_DN, sizeof TA210_DN, (unsigned char *)TA210_RSA_N, sizeof TA210_RSA_N, (unsigned char *)TA210_RSA_E, sizeof TA210_RSA_E); + trust_anchors[211] = make_ec_trust_anchor((unsigned char *)TA211_DN, sizeof TA211_DN, BR_EC_secp384r1, (unsigned char *)TA211_EC_Q, sizeof TA211_EC_Q); + trust_anchors[212] = make_ec_trust_anchor((unsigned char *)TA212_DN, sizeof TA212_DN, BR_EC_secp384r1, (unsigned char *)TA212_EC_Q, sizeof TA212_EC_Q); + trust_anchors[213] = make_rsa_trust_anchor((unsigned char *)TA213_DN, sizeof TA213_DN, (unsigned char *)TA213_RSA_N, sizeof TA213_RSA_N, (unsigned char *)TA213_RSA_E, sizeof TA213_RSA_E); + trust_anchors[214] = make_rsa_trust_anchor((unsigned char *)TA214_DN, sizeof TA214_DN, (unsigned char *)TA214_RSA_N, sizeof TA214_RSA_N, (unsigned char *)TA214_RSA_E, sizeof TA214_RSA_E); + trust_anchors[215] = make_rsa_trust_anchor((unsigned char *)TA215_DN, sizeof TA215_DN, (unsigned char *)TA215_RSA_N, sizeof TA215_RSA_N, (unsigned char *)TA215_RSA_E, sizeof TA215_RSA_E); + trust_anchors[216] = make_ec_trust_anchor((unsigned char *)TA216_DN, sizeof TA216_DN, BR_EC_secp256r1, (unsigned char *)TA216_EC_Q, sizeof TA216_EC_Q); + trust_anchors[217] = make_rsa_trust_anchor((unsigned char *)TA217_DN, sizeof TA217_DN, (unsigned char *)TA217_RSA_N, sizeof TA217_RSA_N, (unsigned char *)TA217_RSA_E, sizeof TA217_RSA_E); + trust_anchors[218] = make_rsa_trust_anchor((unsigned char *)TA218_DN, sizeof TA218_DN, (unsigned char *)TA218_RSA_N, sizeof TA218_RSA_N, (unsigned char *)TA218_RSA_E, sizeof TA218_RSA_E); + trust_anchors[219] = make_ec_trust_anchor((unsigned char *)TA219_DN, sizeof TA219_DN, BR_EC_secp384r1, (unsigned char *)TA219_EC_Q, sizeof TA219_EC_Q); + trust_anchors[220] = make_rsa_trust_anchor((unsigned char *)TA220_DN, sizeof TA220_DN, (unsigned char *)TA220_RSA_N, sizeof TA220_RSA_N, (unsigned char *)TA220_RSA_E, sizeof TA220_RSA_E); + trust_anchors[221] = make_rsa_trust_anchor((unsigned char *)TA221_DN, sizeof TA221_DN, (unsigned char *)TA221_RSA_N, sizeof TA221_RSA_N, (unsigned char *)TA221_RSA_E, sizeof TA221_RSA_E); + trust_anchors[222] = make_rsa_trust_anchor((unsigned char *)TA222_DN, sizeof TA222_DN, (unsigned char *)TA222_RSA_N, sizeof TA222_RSA_N, (unsigned char *)TA222_RSA_E, sizeof TA222_RSA_E); + trust_anchors[223] = make_rsa_trust_anchor((unsigned char *)TA223_DN, sizeof TA223_DN, (unsigned char *)TA223_RSA_N, sizeof TA223_RSA_N, (unsigned char *)TA223_RSA_E, sizeof TA223_RSA_E); + trust_anchors[224] = make_ec_trust_anchor((unsigned char *)TA224_DN, sizeof TA224_DN, BR_EC_secp384r1, (unsigned char *)TA224_EC_Q, sizeof TA224_EC_Q); + trust_anchors[225] = make_rsa_trust_anchor((unsigned char *)TA225_DN, sizeof TA225_DN, (unsigned char *)TA225_RSA_N, sizeof TA225_RSA_N, (unsigned char *)TA225_RSA_E, sizeof TA225_RSA_E); + trust_anchors[226] = make_rsa_trust_anchor((unsigned char *)TA226_DN, sizeof TA226_DN, (unsigned char *)TA226_RSA_N, sizeof TA226_RSA_N, (unsigned char *)TA226_RSA_E, sizeof TA226_RSA_E); + trust_anchors[227] = make_rsa_trust_anchor((unsigned char *)TA227_DN, sizeof TA227_DN, (unsigned char *)TA227_RSA_N, sizeof TA227_RSA_N, (unsigned char *)TA227_RSA_E, sizeof TA227_RSA_E); + trust_anchors[228] = make_rsa_trust_anchor((unsigned char *)TA228_DN, sizeof TA228_DN, (unsigned char *)TA228_RSA_N, sizeof TA228_RSA_N, (unsigned char *)TA228_RSA_E, sizeof TA228_RSA_E); + trust_anchors[229] = make_rsa_trust_anchor((unsigned char *)TA229_DN, sizeof TA229_DN, (unsigned char *)TA229_RSA_N, sizeof TA229_RSA_N, (unsigned char *)TA229_RSA_E, sizeof TA229_RSA_E); + trust_anchors[230] = make_rsa_trust_anchor((unsigned char *)TA230_DN, sizeof TA230_DN, (unsigned char *)TA230_RSA_N, sizeof TA230_RSA_N, (unsigned char *)TA230_RSA_E, sizeof TA230_RSA_E); + trust_anchors[231] = make_rsa_trust_anchor((unsigned char *)TA231_DN, sizeof TA231_DN, (unsigned char *)TA231_RSA_N, sizeof TA231_RSA_N, (unsigned char *)TA231_RSA_E, sizeof TA231_RSA_E); + trust_anchors[232] = make_ec_trust_anchor((unsigned char *)TA232_DN, sizeof TA232_DN, BR_EC_secp384r1, (unsigned char *)TA232_EC_Q, sizeof TA232_EC_Q); + trust_anchors[233] = make_rsa_trust_anchor((unsigned char *)TA233_DN, sizeof TA233_DN, (unsigned char *)TA233_RSA_N, sizeof TA233_RSA_N, (unsigned char *)TA233_RSA_E, sizeof TA233_RSA_E); + trust_anchors[234] = make_rsa_trust_anchor((unsigned char *)TA234_DN, sizeof TA234_DN, (unsigned char *)TA234_RSA_N, sizeof TA234_RSA_N, (unsigned char *)TA234_RSA_E, sizeof TA234_RSA_E); + trust_anchors[235] = make_rsa_trust_anchor((unsigned char *)TA235_DN, sizeof TA235_DN, (unsigned char *)TA235_RSA_N, sizeof TA235_RSA_N, (unsigned char *)TA235_RSA_E, sizeof TA235_RSA_E); + trust_anchors[236] = make_rsa_trust_anchor((unsigned char *)TA236_DN, sizeof TA236_DN, (unsigned char *)TA236_RSA_N, sizeof TA236_RSA_N, (unsigned char *)TA236_RSA_E, sizeof TA236_RSA_E); + trust_anchors[237] = make_rsa_trust_anchor((unsigned char *)TA237_DN, sizeof TA237_DN, (unsigned char *)TA237_RSA_N, sizeof TA237_RSA_N, (unsigned char *)TA237_RSA_E, sizeof TA237_RSA_E); + trust_anchors[238] = make_ec_trust_anchor((unsigned char *)TA238_DN, sizeof TA238_DN, BR_EC_secp384r1, (unsigned char *)TA238_EC_Q, sizeof TA238_EC_Q); + trust_anchors[239] = make_rsa_trust_anchor((unsigned char *)TA239_DN, sizeof TA239_DN, (unsigned char *)TA239_RSA_N, sizeof TA239_RSA_N, (unsigned char *)TA239_RSA_E, sizeof TA239_RSA_E); + trust_anchors[240] = make_ec_trust_anchor((unsigned char *)TA240_DN, sizeof TA240_DN, BR_EC_secp384r1, (unsigned char *)TA240_EC_Q, sizeof TA240_EC_Q); + trust_anchors[241] = make_rsa_trust_anchor((unsigned char *)TA241_DN, sizeof TA241_DN, (unsigned char *)TA241_RSA_N, sizeof TA241_RSA_N, (unsigned char *)TA241_RSA_E, sizeof TA241_RSA_E); + trust_anchors[242] = make_rsa_trust_anchor((unsigned char *)TA242_DN, sizeof TA242_DN, (unsigned char *)TA242_RSA_N, sizeof TA242_RSA_N, (unsigned char *)TA242_RSA_E, sizeof TA242_RSA_E); + trust_anchors[243] = make_rsa_trust_anchor((unsigned char *)TA243_DN, sizeof TA243_DN, (unsigned char *)TA243_RSA_N, sizeof TA243_RSA_N, (unsigned char *)TA243_RSA_E, sizeof TA243_RSA_E); + trust_anchors[244] = make_rsa_trust_anchor((unsigned char *)TA244_DN, sizeof TA244_DN, (unsigned char *)TA244_RSA_N, sizeof TA244_RSA_N, (unsigned char *)TA244_RSA_E, sizeof TA244_RSA_E); + trust_anchors[245] = make_ec_trust_anchor((unsigned char *)TA245_DN, sizeof TA245_DN, BR_EC_secp384r1, (unsigned char *)TA245_EC_Q, sizeof TA245_EC_Q); + trust_anchors[246] = make_rsa_trust_anchor((unsigned char *)TA246_DN, sizeof TA246_DN, (unsigned char *)TA246_RSA_N, sizeof TA246_RSA_N, (unsigned char *)TA246_RSA_E, sizeof TA246_RSA_E); + trust_anchors[247] = make_rsa_trust_anchor((unsigned char *)TA247_DN, sizeof TA247_DN, (unsigned char *)TA247_RSA_N, sizeof TA247_RSA_N, (unsigned char *)TA247_RSA_E, sizeof TA247_RSA_E); + trust_anchors[248] = make_rsa_trust_anchor((unsigned char *)TA248_DN, sizeof TA248_DN, (unsigned char *)TA248_RSA_N, sizeof TA248_RSA_N, (unsigned char *)TA248_RSA_E, sizeof TA248_RSA_E); + trust_anchors[249] = make_rsa_trust_anchor((unsigned char *)TA249_DN, sizeof TA249_DN, (unsigned char *)TA249_RSA_N, sizeof TA249_RSA_N, (unsigned char *)TA249_RSA_E, sizeof TA249_RSA_E); + trust_anchors[250] = make_rsa_trust_anchor((unsigned char *)TA250_DN, sizeof TA250_DN, (unsigned char *)TA250_RSA_N, sizeof TA250_RSA_N, (unsigned char *)TA250_RSA_E, sizeof TA250_RSA_E); + trust_anchors[251] = make_ec_trust_anchor((unsigned char *)TA251_DN, sizeof TA251_DN, BR_EC_secp384r1, (unsigned char *)TA251_EC_Q, sizeof TA251_EC_Q); + trust_anchors[252] = make_rsa_trust_anchor((unsigned char *)TA252_DN, sizeof TA252_DN, (unsigned char *)TA252_RSA_N, sizeof TA252_RSA_N, (unsigned char *)TA252_RSA_E, sizeof TA252_RSA_E); + trust_anchors[253] = make_rsa_trust_anchor((unsigned char *)TA253_DN, sizeof TA253_DN, (unsigned char *)TA253_RSA_N, sizeof TA253_RSA_N, (unsigned char *)TA253_RSA_E, sizeof TA253_RSA_E); + trust_anchors[254] = make_ec_trust_anchor((unsigned char *)TA254_DN, sizeof TA254_DN, BR_EC_secp256r1, (unsigned char *)TA254_EC_Q, sizeof TA254_EC_Q); + trust_anchors[255] = make_ec_trust_anchor((unsigned char *)TA255_DN, sizeof TA255_DN, BR_EC_secp384r1, (unsigned char *)TA255_EC_Q, sizeof TA255_EC_Q); + trust_anchors[256] = make_rsa_trust_anchor((unsigned char *)TA256_DN, sizeof TA256_DN, (unsigned char *)TA256_RSA_N, sizeof TA256_RSA_N, (unsigned char *)TA256_RSA_E, sizeof TA256_RSA_E); + trust_anchors[257] = make_ec_trust_anchor((unsigned char *)TA257_DN, sizeof TA257_DN, BR_EC_secp384r1, (unsigned char *)TA257_EC_Q, sizeof TA257_EC_Q); + trust_anchors[258] = make_rsa_trust_anchor((unsigned char *)TA258_DN, sizeof TA258_DN, (unsigned char *)TA258_RSA_N, sizeof TA258_RSA_N, (unsigned char *)TA258_RSA_E, sizeof TA258_RSA_E); + trust_anchors[259] = make_rsa_trust_anchor((unsigned char *)TA259_DN, sizeof TA259_DN, (unsigned char *)TA259_RSA_N, sizeof TA259_RSA_N, (unsigned char *)TA259_RSA_E, sizeof TA259_RSA_E); + trust_anchors[260] = make_rsa_trust_anchor((unsigned char *)TA260_DN, sizeof TA260_DN, (unsigned char *)TA260_RSA_N, sizeof TA260_RSA_N, (unsigned char *)TA260_RSA_E, sizeof TA260_RSA_E); + trust_anchors[261] = make_ec_trust_anchor((unsigned char *)TA261_DN, sizeof TA261_DN, BR_EC_secp384r1, (unsigned char *)TA261_EC_Q, sizeof TA261_EC_Q); + trust_anchors[262] = make_rsa_trust_anchor((unsigned char *)TA262_DN, sizeof TA262_DN, (unsigned char *)TA262_RSA_N, sizeof TA262_RSA_N, (unsigned char *)TA262_RSA_E, sizeof TA262_RSA_E); + trust_anchors[263] = make_rsa_trust_anchor((unsigned char *)TA263_DN, sizeof TA263_DN, (unsigned char *)TA263_RSA_N, sizeof TA263_RSA_N, (unsigned char *)TA263_RSA_E, sizeof TA263_RSA_E); + trust_anchors[264] = make_rsa_trust_anchor((unsigned char *)TA264_DN, sizeof TA264_DN, (unsigned char *)TA264_RSA_N, sizeof TA264_RSA_N, (unsigned char *)TA264_RSA_E, sizeof TA264_RSA_E); + trust_anchors[265] = make_rsa_trust_anchor((unsigned char *)TA265_DN, sizeof TA265_DN, (unsigned char *)TA265_RSA_N, sizeof TA265_RSA_N, (unsigned char *)TA265_RSA_E, sizeof TA265_RSA_E); + trust_anchors[266] = make_rsa_trust_anchor((unsigned char *)TA266_DN, sizeof TA266_DN, (unsigned char *)TA266_RSA_N, sizeof TA266_RSA_N, (unsigned char *)TA266_RSA_E, sizeof TA266_RSA_E); + trust_anchors[267] = make_rsa_trust_anchor((unsigned char *)TA267_DN, sizeof TA267_DN, (unsigned char *)TA267_RSA_N, sizeof TA267_RSA_N, (unsigned char *)TA267_RSA_E, sizeof TA267_RSA_E); + trust_anchors[268] = make_ec_trust_anchor((unsigned char *)TA268_DN, sizeof TA268_DN, BR_EC_secp384r1, (unsigned char *)TA268_EC_Q, sizeof TA268_EC_Q); + trust_anchors[269] = make_rsa_trust_anchor((unsigned char *)TA269_DN, sizeof TA269_DN, (unsigned char *)TA269_RSA_N, sizeof TA269_RSA_N, (unsigned char *)TA269_RSA_E, sizeof TA269_RSA_E); + trust_anchors[270] = make_ec_trust_anchor((unsigned char *)TA270_DN, sizeof TA270_DN, BR_EC_secp384r1, (unsigned char *)TA270_EC_Q, sizeof TA270_EC_Q); + trust_anchors[271] = make_rsa_trust_anchor((unsigned char *)TA271_DN, sizeof TA271_DN, (unsigned char *)TA271_RSA_N, sizeof TA271_RSA_N, (unsigned char *)TA271_RSA_E, sizeof TA271_RSA_E); + trust_anchors[272] = make_rsa_trust_anchor((unsigned char *)TA272_DN, sizeof TA272_DN, (unsigned char *)TA272_RSA_N, sizeof TA272_RSA_N, (unsigned char *)TA272_RSA_E, sizeof TA272_RSA_E); + trust_anchors[273] = make_rsa_trust_anchor((unsigned char *)TA273_DN, sizeof TA273_DN, (unsigned char *)TA273_RSA_N, sizeof TA273_RSA_N, (unsigned char *)TA273_RSA_E, sizeof TA273_RSA_E); + trust_anchors[274] = make_ec_trust_anchor((unsigned char *)TA274_DN, sizeof TA274_DN, BR_EC_secp384r1, (unsigned char *)TA274_EC_Q, sizeof TA274_EC_Q); + trust_anchors[275] = make_rsa_trust_anchor((unsigned char *)TA275_DN, sizeof TA275_DN, (unsigned char *)TA275_RSA_N, sizeof TA275_RSA_N, (unsigned char *)TA275_RSA_E, sizeof TA275_RSA_E); + trust_anchors[276] = make_rsa_trust_anchor((unsigned char *)TA276_DN, sizeof TA276_DN, (unsigned char *)TA276_RSA_N, sizeof TA276_RSA_N, (unsigned char *)TA276_RSA_E, sizeof TA276_RSA_E); + trust_anchors[277] = make_rsa_trust_anchor((unsigned char *)TA277_DN, sizeof TA277_DN, (unsigned char *)TA277_RSA_N, sizeof TA277_RSA_N, (unsigned char *)TA277_RSA_E, sizeof TA277_RSA_E); + trust_anchors[278] = make_ec_trust_anchor((unsigned char *)TA278_DN, sizeof TA278_DN, BR_EC_secp384r1, (unsigned char *)TA278_EC_Q, sizeof TA278_EC_Q); + trust_anchors[279] = make_ec_trust_anchor((unsigned char *)TA279_DN, sizeof TA279_DN, BR_EC_secp384r1, (unsigned char *)TA279_EC_Q, sizeof TA279_EC_Q); + trust_anchors[280] = make_rsa_trust_anchor((unsigned char *)TA280_DN, sizeof TA280_DN, (unsigned char *)TA280_RSA_N, sizeof TA280_RSA_N, (unsigned char *)TA280_RSA_E, sizeof TA280_RSA_E); + trust_anchors[281] = make_rsa_trust_anchor((unsigned char *)TA281_DN, sizeof TA281_DN, (unsigned char *)TA281_RSA_N, sizeof TA281_RSA_N, (unsigned char *)TA281_RSA_E, sizeof TA281_RSA_E); + trust_anchors[282] = make_rsa_trust_anchor((unsigned char *)TA282_DN, sizeof TA282_DN, (unsigned char *)TA282_RSA_N, sizeof TA282_RSA_N, (unsigned char *)TA282_RSA_E, sizeof TA282_RSA_E); + trust_anchors[283] = make_ec_trust_anchor((unsigned char *)TA283_DN, sizeof TA283_DN, BR_EC_secp384r1, (unsigned char *)TA283_EC_Q, sizeof TA283_EC_Q); + trust_anchors[284] = make_rsa_trust_anchor((unsigned char *)TA284_DN, sizeof TA284_DN, (unsigned char *)TA284_RSA_N, sizeof TA284_RSA_N, (unsigned char *)TA284_RSA_E, sizeof TA284_RSA_E); + trust_anchors[285] = make_ec_trust_anchor((unsigned char *)TA285_DN, sizeof TA285_DN, BR_EC_secp384r1, (unsigned char *)TA285_EC_Q, sizeof TA285_EC_Q); + trust_anchors[286] = make_rsa_trust_anchor((unsigned char *)TA286_DN, sizeof TA286_DN, (unsigned char *)TA286_RSA_N, sizeof TA286_RSA_N, (unsigned char *)TA286_RSA_E, sizeof TA286_RSA_E); + trust_anchors[287] = make_rsa_trust_anchor((unsigned char *)TA287_DN, sizeof TA287_DN, (unsigned char *)TA287_RSA_N, sizeof TA287_RSA_N, (unsigned char *)TA287_RSA_E, sizeof TA287_RSA_E); + trust_anchors[288] = make_rsa_trust_anchor((unsigned char *)TA288_DN, sizeof TA288_DN, (unsigned char *)TA288_RSA_N, sizeof TA288_RSA_N, (unsigned char *)TA288_RSA_E, sizeof TA288_RSA_E); + trust_anchors[289] = make_rsa_trust_anchor((unsigned char *)TA289_DN, sizeof TA289_DN, (unsigned char *)TA289_RSA_N, sizeof TA289_RSA_N, (unsigned char *)TA289_RSA_E, sizeof TA289_RSA_E); + trust_anchors[290] = make_rsa_trust_anchor((unsigned char *)TA290_DN, sizeof TA290_DN, (unsigned char *)TA290_RSA_N, sizeof TA290_RSA_N, (unsigned char *)TA290_RSA_E, sizeof TA290_RSA_E); + trust_anchors[291] = make_ec_trust_anchor((unsigned char *)TA291_DN, sizeof TA291_DN, BR_EC_secp384r1, (unsigned char *)TA291_EC_Q, sizeof TA291_EC_Q); + trust_anchors[292] = make_rsa_trust_anchor((unsigned char *)TA292_DN, sizeof TA292_DN, (unsigned char *)TA292_RSA_N, sizeof TA292_RSA_N, (unsigned char *)TA292_RSA_E, sizeof TA292_RSA_E); + trust_anchors[293] = make_rsa_trust_anchor((unsigned char *)TA293_DN, sizeof TA293_DN, (unsigned char *)TA293_RSA_N, sizeof TA293_RSA_N, (unsigned char *)TA293_RSA_E, sizeof TA293_RSA_E); + trust_anchors[294] = make_ec_trust_anchor((unsigned char *)TA294_DN, sizeof TA294_DN, BR_EC_secp384r1, (unsigned char *)TA294_EC_Q, sizeof TA294_EC_Q); + trust_anchors[295] = make_rsa_trust_anchor((unsigned char *)TA295_DN, sizeof TA295_DN, (unsigned char *)TA295_RSA_N, sizeof TA295_RSA_N, (unsigned char *)TA295_RSA_E, sizeof TA295_RSA_E); + trust_anchors[296] = make_ec_trust_anchor((unsigned char *)TA296_DN, sizeof TA296_DN, BR_EC_secp384r1, (unsigned char *)TA296_EC_Q, sizeof TA296_EC_Q); + trust_anchors[297] = make_rsa_trust_anchor((unsigned char *)TA297_DN, sizeof TA297_DN, (unsigned char *)TA297_RSA_N, sizeof TA297_RSA_N, (unsigned char *)TA297_RSA_E, sizeof TA297_RSA_E); + trust_anchors[298] = make_rsa_trust_anchor((unsigned char *)TA298_DN, sizeof TA298_DN, (unsigned char *)TA298_RSA_N, sizeof TA298_RSA_N, (unsigned char *)TA298_RSA_E, sizeof TA298_RSA_E); + trust_anchors[299] = make_rsa_trust_anchor((unsigned char *)TA299_DN, sizeof TA299_DN, (unsigned char *)TA299_RSA_N, sizeof TA299_RSA_N, (unsigned char *)TA299_RSA_E, sizeof TA299_RSA_E); + trust_anchors[300] = make_rsa_trust_anchor((unsigned char *)TA300_DN, sizeof TA300_DN, (unsigned char *)TA300_RSA_N, sizeof TA300_RSA_N, (unsigned char *)TA300_RSA_E, sizeof TA300_RSA_E); + trust_anchors[301] = make_ec_trust_anchor((unsigned char *)TA301_DN, sizeof TA301_DN, BR_EC_secp384r1, (unsigned char *)TA301_EC_Q, sizeof TA301_EC_Q); + trust_anchors[302] = make_rsa_trust_anchor((unsigned char *)TA302_DN, sizeof TA302_DN, (unsigned char *)TA302_RSA_N, sizeof TA302_RSA_N, (unsigned char *)TA302_RSA_E, sizeof TA302_RSA_E); + trust_anchors[303] = make_ec_trust_anchor((unsigned char *)TA303_DN, sizeof TA303_DN, BR_EC_secp384r1, (unsigned char *)TA303_EC_Q, sizeof TA303_EC_Q); + trust_anchors[304] = make_rsa_trust_anchor((unsigned char *)TA304_DN, sizeof TA304_DN, (unsigned char *)TA304_RSA_N, sizeof TA304_RSA_N, (unsigned char *)TA304_RSA_E, sizeof TA304_RSA_E); + trust_anchors[305] = make_rsa_trust_anchor((unsigned char *)TA305_DN, sizeof TA305_DN, (unsigned char *)TA305_RSA_N, sizeof TA305_RSA_N, (unsigned char *)TA305_RSA_E, sizeof TA305_RSA_E); + trust_anchors[306] = make_rsa_trust_anchor((unsigned char *)TA306_DN, sizeof TA306_DN, (unsigned char *)TA306_RSA_N, sizeof TA306_RSA_N, (unsigned char *)TA306_RSA_E, sizeof TA306_RSA_E); + trust_anchors[307] = make_rsa_trust_anchor((unsigned char *)TA307_DN, sizeof TA307_DN, (unsigned char *)TA307_RSA_N, sizeof TA307_RSA_N, (unsigned char *)TA307_RSA_E, sizeof TA307_RSA_E); + trust_anchors[308] = make_ec_trust_anchor((unsigned char *)TA308_DN, sizeof TA308_DN, BR_EC_secp384r1, (unsigned char *)TA308_EC_Q, sizeof TA308_EC_Q); + trust_anchors[309] = make_ec_trust_anchor((unsigned char *)TA309_DN, sizeof TA309_DN, BR_EC_secp384r1, (unsigned char *)TA309_EC_Q, sizeof TA309_EC_Q); + trust_anchors[310] = make_ec_trust_anchor((unsigned char *)TA310_DN, sizeof TA310_DN, BR_EC_secp256r1, (unsigned char *)TA310_EC_Q, sizeof TA310_EC_Q); + trust_anchors[311] = make_ec_trust_anchor((unsigned char *)TA311_DN, sizeof TA311_DN, BR_EC_secp384r1, (unsigned char *)TA311_EC_Q, sizeof TA311_EC_Q); + trust_anchors[312] = make_rsa_trust_anchor((unsigned char *)TA312_DN, sizeof TA312_DN, (unsigned char *)TA312_RSA_N, sizeof TA312_RSA_N, (unsigned char *)TA312_RSA_E, sizeof TA312_RSA_E); + trust_anchors[313] = make_rsa_trust_anchor((unsigned char *)TA313_DN, sizeof TA313_DN, (unsigned char *)TA313_RSA_N, sizeof TA313_RSA_N, (unsigned char *)TA313_RSA_E, sizeof TA313_RSA_E); + trust_anchors[314] = make_rsa_trust_anchor((unsigned char *)TA314_DN, sizeof TA314_DN, (unsigned char *)TA314_RSA_N, sizeof TA314_RSA_N, (unsigned char *)TA314_RSA_E, sizeof TA314_RSA_E); + trust_anchors[315] = make_ec_trust_anchor((unsigned char *)TA315_DN, sizeof TA315_DN, BR_EC_secp384r1, (unsigned char *)TA315_EC_Q, sizeof TA315_EC_Q); + trust_anchors[316] = make_rsa_trust_anchor((unsigned char *)TA316_DN, sizeof TA316_DN, (unsigned char *)TA316_RSA_N, sizeof TA316_RSA_N, (unsigned char *)TA316_RSA_E, sizeof TA316_RSA_E); + trust_anchors[317] = make_rsa_trust_anchor((unsigned char *)TA317_DN, sizeof TA317_DN, (unsigned char *)TA317_RSA_N, sizeof TA317_RSA_N, (unsigned char *)TA317_RSA_E, sizeof TA317_RSA_E); + trust_anchors[318] = make_rsa_trust_anchor((unsigned char *)TA318_DN, sizeof TA318_DN, (unsigned char *)TA318_RSA_N, sizeof TA318_RSA_N, (unsigned char *)TA318_RSA_E, sizeof TA318_RSA_E); + trust_anchors[319] = make_ec_trust_anchor((unsigned char *)TA319_DN, sizeof TA319_DN, BR_EC_secp384r1, (unsigned char *)TA319_EC_Q, sizeof TA319_EC_Q); + trust_anchors[320] = make_rsa_trust_anchor((unsigned char *)TA320_DN, sizeof TA320_DN, (unsigned char *)TA320_RSA_N, sizeof TA320_RSA_N, (unsigned char *)TA320_RSA_E, sizeof TA320_RSA_E); + trust_anchors[321] = make_ec_trust_anchor((unsigned char *)TA321_DN, sizeof TA321_DN, BR_EC_secp384r1, (unsigned char *)TA321_EC_Q, sizeof TA321_EC_Q); + trust_anchors[322] = make_rsa_trust_anchor((unsigned char *)TA322_DN, sizeof TA322_DN, (unsigned char *)TA322_RSA_N, sizeof TA322_RSA_N, (unsigned char *)TA322_RSA_E, sizeof TA322_RSA_E); + trust_anchors[323] = make_rsa_trust_anchor((unsigned char *)TA323_DN, sizeof TA323_DN, (unsigned char *)TA323_RSA_N, sizeof TA323_RSA_N, (unsigned char *)TA323_RSA_E, sizeof TA323_RSA_E); + trust_anchors[324] = make_rsa_trust_anchor((unsigned char *)TA324_DN, sizeof TA324_DN, (unsigned char *)TA324_RSA_N, sizeof TA324_RSA_N, (unsigned char *)TA324_RSA_E, sizeof TA324_RSA_E); + trust_anchors[325] = make_rsa_trust_anchor((unsigned char *)TA325_DN, sizeof TA325_DN, (unsigned char *)TA325_RSA_N, sizeof TA325_RSA_N, (unsigned char *)TA325_RSA_E, sizeof TA325_RSA_E); + trust_anchors[326] = make_ec_trust_anchor((unsigned char *)TA326_DN, sizeof TA326_DN, BR_EC_secp384r1, (unsigned char *)TA326_EC_Q, sizeof TA326_EC_Q); + trust_anchors[327] = make_rsa_trust_anchor((unsigned char *)TA327_DN, sizeof TA327_DN, (unsigned char *)TA327_RSA_N, sizeof TA327_RSA_N, (unsigned char *)TA327_RSA_E, sizeof TA327_RSA_E); + trust_anchors[328] = make_rsa_trust_anchor((unsigned char *)TA328_DN, sizeof TA328_DN, (unsigned char *)TA328_RSA_N, sizeof TA328_RSA_N, (unsigned char *)TA328_RSA_E, sizeof TA328_RSA_E); + trust_anchors[329] = make_rsa_trust_anchor((unsigned char *)TA329_DN, sizeof TA329_DN, (unsigned char *)TA329_RSA_N, sizeof TA329_RSA_N, (unsigned char *)TA329_RSA_E, sizeof TA329_RSA_E); + trust_anchors[330] = make_rsa_trust_anchor((unsigned char *)TA330_DN, sizeof TA330_DN, (unsigned char *)TA330_RSA_N, sizeof TA330_RSA_N, (unsigned char *)TA330_RSA_E, sizeof TA330_RSA_E); + trust_anchors[331] = make_ec_trust_anchor((unsigned char *)TA331_DN, sizeof TA331_DN, BR_EC_secp384r1, (unsigned char *)TA331_EC_Q, sizeof TA331_EC_Q); + trust_anchors[332] = make_rsa_trust_anchor((unsigned char *)TA332_DN, sizeof TA332_DN, (unsigned char *)TA332_RSA_N, sizeof TA332_RSA_N, (unsigned char *)TA332_RSA_E, sizeof TA332_RSA_E); + trust_anchors[333] = make_rsa_trust_anchor((unsigned char *)TA333_DN, sizeof TA333_DN, (unsigned char *)TA333_RSA_N, sizeof TA333_RSA_N, (unsigned char *)TA333_RSA_E, sizeof TA333_RSA_E); + trust_anchors[334] = make_rsa_trust_anchor((unsigned char *)TA334_DN, sizeof TA334_DN, (unsigned char *)TA334_RSA_N, sizeof TA334_RSA_N, (unsigned char *)TA334_RSA_E, sizeof TA334_RSA_E); + trust_anchors[335] = make_rsa_trust_anchor((unsigned char *)TA335_DN, sizeof TA335_DN, (unsigned char *)TA335_RSA_N, sizeof TA335_RSA_N, (unsigned char *)TA335_RSA_E, sizeof TA335_RSA_E); + trust_anchors[336] = make_ec_trust_anchor((unsigned char *)TA336_DN, sizeof TA336_DN, BR_EC_secp384r1, (unsigned char *)TA336_EC_Q, sizeof TA336_EC_Q); + trust_anchors[337] = make_rsa_trust_anchor((unsigned char *)TA337_DN, sizeof TA337_DN, (unsigned char *)TA337_RSA_N, sizeof TA337_RSA_N, (unsigned char *)TA337_RSA_E, sizeof TA337_RSA_E); + trust_anchors[338] = make_rsa_trust_anchor((unsigned char *)TA338_DN, sizeof TA338_DN, (unsigned char *)TA338_RSA_N, sizeof TA338_RSA_N, (unsigned char *)TA338_RSA_E, sizeof TA338_RSA_E); + trust_anchors[339] = make_rsa_trust_anchor((unsigned char *)TA339_DN, sizeof TA339_DN, (unsigned char *)TA339_RSA_N, sizeof TA339_RSA_N, (unsigned char *)TA339_RSA_E, sizeof TA339_RSA_E); + trust_anchors[340] = make_rsa_trust_anchor((unsigned char *)TA340_DN, sizeof TA340_DN, (unsigned char *)TA340_RSA_N, sizeof TA340_RSA_N, (unsigned char *)TA340_RSA_E, sizeof TA340_RSA_E); + trust_anchors[341] = make_rsa_trust_anchor((unsigned char *)TA341_DN, sizeof TA341_DN, (unsigned char *)TA341_RSA_N, sizeof TA341_RSA_N, (unsigned char *)TA341_RSA_E, sizeof TA341_RSA_E); + trust_anchors[342] = make_ec_trust_anchor((unsigned char *)TA342_DN, sizeof TA342_DN, BR_EC_secp384r1, (unsigned char *)TA342_EC_Q, sizeof TA342_EC_Q); + trust_anchors[343] = make_rsa_trust_anchor((unsigned char *)TA343_DN, sizeof TA343_DN, (unsigned char *)TA343_RSA_N, sizeof TA343_RSA_N, (unsigned char *)TA343_RSA_E, sizeof TA343_RSA_E); + trust_anchors[344] = make_ec_trust_anchor((unsigned char *)TA344_DN, sizeof TA344_DN, BR_EC_secp384r1, (unsigned char *)TA344_EC_Q, sizeof TA344_EC_Q); + trust_anchors[345] = make_rsa_trust_anchor((unsigned char *)TA345_DN, sizeof TA345_DN, (unsigned char *)TA345_RSA_N, sizeof TA345_RSA_N, (unsigned char *)TA345_RSA_E, sizeof TA345_RSA_E); + trust_anchors[346] = make_ec_trust_anchor((unsigned char *)TA346_DN, sizeof TA346_DN, BR_EC_secp384r1, (unsigned char *)TA346_EC_Q, sizeof TA346_EC_Q); + trust_anchors[347] = make_rsa_trust_anchor((unsigned char *)TA347_DN, sizeof TA347_DN, (unsigned char *)TA347_RSA_N, sizeof TA347_RSA_N, (unsigned char *)TA347_RSA_E, sizeof TA347_RSA_E); + trust_anchors[348] = make_rsa_trust_anchor((unsigned char *)TA348_DN, sizeof TA348_DN, (unsigned char *)TA348_RSA_N, sizeof TA348_RSA_N, (unsigned char *)TA348_RSA_E, sizeof TA348_RSA_E); + trust_anchors[349] = make_ec_trust_anchor((unsigned char *)TA349_DN, sizeof TA349_DN, BR_EC_secp384r1, (unsigned char *)TA349_EC_Q, sizeof TA349_EC_Q); + trust_anchors[350] = make_rsa_trust_anchor((unsigned char *)TA350_DN, sizeof TA350_DN, (unsigned char *)TA350_RSA_N, sizeof TA350_RSA_N, (unsigned char *)TA350_RSA_E, sizeof TA350_RSA_E); + trust_anchors[351] = make_rsa_trust_anchor((unsigned char *)TA351_DN, sizeof TA351_DN, (unsigned char *)TA351_RSA_N, sizeof TA351_RSA_N, (unsigned char *)TA351_RSA_E, sizeof TA351_RSA_E); + trust_anchors[352] = make_rsa_trust_anchor((unsigned char *)TA352_DN, sizeof TA352_DN, (unsigned char *)TA352_RSA_N, sizeof TA352_RSA_N, (unsigned char *)TA352_RSA_E, sizeof TA352_RSA_E); + trust_anchors[353] = make_ec_trust_anchor((unsigned char *)TA353_DN, sizeof TA353_DN, BR_EC_secp384r1, (unsigned char *)TA353_EC_Q, sizeof TA353_EC_Q); + trust_anchors[354] = make_rsa_trust_anchor((unsigned char *)TA354_DN, sizeof TA354_DN, (unsigned char *)TA354_RSA_N, sizeof TA354_RSA_N, (unsigned char *)TA354_RSA_E, sizeof TA354_RSA_E); + trust_anchors[355] = make_rsa_trust_anchor((unsigned char *)TA355_DN, sizeof TA355_DN, (unsigned char *)TA355_RSA_N, sizeof TA355_RSA_N, (unsigned char *)TA355_RSA_E, sizeof TA355_RSA_E); + trust_anchors[356] = make_ec_trust_anchor((unsigned char *)TA356_DN, sizeof TA356_DN, BR_EC_secp384r1, (unsigned char *)TA356_EC_Q, sizeof TA356_EC_Q); + trust_anchors[357] = make_rsa_trust_anchor((unsigned char *)TA357_DN, sizeof TA357_DN, (unsigned char *)TA357_RSA_N, sizeof TA357_RSA_N, (unsigned char *)TA357_RSA_E, sizeof TA357_RSA_E); + trust_anchors[358] = make_rsa_trust_anchor((unsigned char *)TA358_DN, sizeof TA358_DN, (unsigned char *)TA358_RSA_N, sizeof TA358_RSA_N, (unsigned char *)TA358_RSA_E, sizeof TA358_RSA_E); + trust_anchors[359] = make_rsa_trust_anchor((unsigned char *)TA359_DN, sizeof TA359_DN, (unsigned char *)TA359_RSA_N, sizeof TA359_RSA_N, (unsigned char *)TA359_RSA_E, sizeof TA359_RSA_E); + trust_anchors[360] = make_rsa_trust_anchor((unsigned char *)TA360_DN, sizeof TA360_DN, (unsigned char *)TA360_RSA_N, sizeof TA360_RSA_N, (unsigned char *)TA360_RSA_E, sizeof TA360_RSA_E); + trust_anchors[361] = make_rsa_trust_anchor((unsigned char *)TA361_DN, sizeof TA361_DN, (unsigned char *)TA361_RSA_N, sizeof TA361_RSA_N, (unsigned char *)TA361_RSA_E, sizeof TA361_RSA_E); + trust_anchors[362] = make_rsa_trust_anchor((unsigned char *)TA362_DN, sizeof TA362_DN, (unsigned char *)TA362_RSA_N, sizeof TA362_RSA_N, (unsigned char *)TA362_RSA_E, sizeof TA362_RSA_E); + trust_anchors[363] = make_rsa_trust_anchor((unsigned char *)TA363_DN, sizeof TA363_DN, (unsigned char *)TA363_RSA_N, sizeof TA363_RSA_N, (unsigned char *)TA363_RSA_E, sizeof TA363_RSA_E); + trust_anchors[364] = make_rsa_trust_anchor((unsigned char *)TA364_DN, sizeof TA364_DN, (unsigned char *)TA364_RSA_N, sizeof TA364_RSA_N, (unsigned char *)TA364_RSA_E, sizeof TA364_RSA_E); + trust_anchors[365] = make_rsa_trust_anchor((unsigned char *)TA365_DN, sizeof TA365_DN, (unsigned char *)TA365_RSA_N, sizeof TA365_RSA_N, (unsigned char *)TA365_RSA_E, sizeof TA365_RSA_E); + trust_anchors[366] = make_rsa_trust_anchor((unsigned char *)TA366_DN, sizeof TA366_DN, (unsigned char *)TA366_RSA_N, sizeof TA366_RSA_N, (unsigned char *)TA366_RSA_E, sizeof TA366_RSA_E); + trust_anchors[367] = make_rsa_trust_anchor((unsigned char *)TA367_DN, sizeof TA367_DN, (unsigned char *)TA367_RSA_N, sizeof TA367_RSA_N, (unsigned char *)TA367_RSA_E, sizeof TA367_RSA_E); + trust_anchors[368] = make_ec_trust_anchor((unsigned char *)TA368_DN, sizeof TA368_DN, BR_EC_secp384r1, (unsigned char *)TA368_EC_Q, sizeof TA368_EC_Q); + trust_anchors[369] = make_rsa_trust_anchor((unsigned char *)TA369_DN, sizeof TA369_DN, (unsigned char *)TA369_RSA_N, sizeof TA369_RSA_N, (unsigned char *)TA369_RSA_E, sizeof TA369_RSA_E); + trust_anchors[370] = make_rsa_trust_anchor((unsigned char *)TA370_DN, sizeof TA370_DN, (unsigned char *)TA370_RSA_N, sizeof TA370_RSA_N, (unsigned char *)TA370_RSA_E, sizeof TA370_RSA_E); + trust_anchors[371] = make_rsa_trust_anchor((unsigned char *)TA371_DN, sizeof TA371_DN, (unsigned char *)TA371_RSA_N, sizeof TA371_RSA_N, (unsigned char *)TA371_RSA_E, sizeof TA371_RSA_E); + trust_anchors[372] = make_rsa_trust_anchor((unsigned char *)TA372_DN, sizeof TA372_DN, (unsigned char *)TA372_RSA_N, sizeof TA372_RSA_N, (unsigned char *)TA372_RSA_E, sizeof TA372_RSA_E); + trust_anchors[373] = make_ec_trust_anchor((unsigned char *)TA373_DN, sizeof TA373_DN, BR_EC_secp384r1, (unsigned char *)TA373_EC_Q, sizeof TA373_EC_Q); + trust_anchors[374] = make_rsa_trust_anchor((unsigned char *)TA374_DN, sizeof TA374_DN, (unsigned char *)TA374_RSA_N, sizeof TA374_RSA_N, (unsigned char *)TA374_RSA_E, sizeof TA374_RSA_E); + trust_anchors[375] = make_ec_trust_anchor((unsigned char *)TA375_DN, sizeof TA375_DN, BR_EC_secp256r1, (unsigned char *)TA375_EC_Q, sizeof TA375_EC_Q); + trust_anchors[376] = make_ec_trust_anchor((unsigned char *)TA376_DN, sizeof TA376_DN, BR_EC_secp384r1, (unsigned char *)TA376_EC_Q, sizeof TA376_EC_Q); + trust_anchors[377] = make_rsa_trust_anchor((unsigned char *)TA377_DN, sizeof TA377_DN, (unsigned char *)TA377_RSA_N, sizeof TA377_RSA_N, (unsigned char *)TA377_RSA_E, sizeof TA377_RSA_E); + trust_anchors[378] = make_rsa_trust_anchor((unsigned char *)TA378_DN, sizeof TA378_DN, (unsigned char *)TA378_RSA_N, sizeof TA378_RSA_N, (unsigned char *)TA378_RSA_E, sizeof TA378_RSA_E); + trust_anchors[379] = make_rsa_trust_anchor((unsigned char *)TA379_DN, sizeof TA379_DN, (unsigned char *)TA379_RSA_N, sizeof TA379_RSA_N, (unsigned char *)TA379_RSA_E, sizeof TA379_RSA_E); + trust_anchors[380] = make_ec_trust_anchor((unsigned char *)TA380_DN, sizeof TA380_DN, BR_EC_secp384r1, (unsigned char *)TA380_EC_Q, sizeof TA380_EC_Q); + trust_anchors[381] = make_rsa_trust_anchor((unsigned char *)TA381_DN, sizeof TA381_DN, (unsigned char *)TA381_RSA_N, sizeof TA381_RSA_N, (unsigned char *)TA381_RSA_E, sizeof TA381_RSA_E); + trust_anchors[382] = make_rsa_trust_anchor((unsigned char *)TA382_DN, sizeof TA382_DN, (unsigned char *)TA382_RSA_N, sizeof TA382_RSA_N, (unsigned char *)TA382_RSA_E, sizeof TA382_RSA_E); + trust_anchors[383] = make_rsa_trust_anchor((unsigned char *)TA383_DN, sizeof TA383_DN, (unsigned char *)TA383_RSA_N, sizeof TA383_RSA_N, (unsigned char *)TA383_RSA_E, sizeof TA383_RSA_E); + trust_anchors[384] = make_rsa_trust_anchor((unsigned char *)TA384_DN, sizeof TA384_DN, (unsigned char *)TA384_RSA_N, sizeof TA384_RSA_N, (unsigned char *)TA384_RSA_E, sizeof TA384_RSA_E); + trust_anchors[385] = make_ec_trust_anchor((unsigned char *)TA385_DN, sizeof TA385_DN, BR_EC_secp256r1, (unsigned char *)TA385_EC_Q, sizeof TA385_EC_Q); + trust_anchors[386] = make_rsa_trust_anchor((unsigned char *)TA386_DN, sizeof TA386_DN, (unsigned char *)TA386_RSA_N, sizeof TA386_RSA_N, (unsigned char *)TA386_RSA_E, sizeof TA386_RSA_E); + trust_anchors[387] = make_ec_trust_anchor((unsigned char *)TA387_DN, sizeof TA387_DN, BR_EC_secp384r1, (unsigned char *)TA387_EC_Q, sizeof TA387_EC_Q); + trust_anchors[388] = make_ec_trust_anchor((unsigned char *)TA388_DN, sizeof TA388_DN, BR_EC_secp384r1, (unsigned char *)TA388_EC_Q, sizeof TA388_EC_Q); + trust_anchors[389] = make_rsa_trust_anchor((unsigned char *)TA389_DN, sizeof TA389_DN, (unsigned char *)TA389_RSA_N, sizeof TA389_RSA_N, (unsigned char *)TA389_RSA_E, sizeof TA389_RSA_E); + trust_anchors[390] = make_rsa_trust_anchor((unsigned char *)TA390_DN, sizeof TA390_DN, (unsigned char *)TA390_RSA_N, sizeof TA390_RSA_N, (unsigned char *)TA390_RSA_E, sizeof TA390_RSA_E); + trust_anchors[391] = make_ec_trust_anchor((unsigned char *)TA391_DN, sizeof TA391_DN, BR_EC_secp384r1, (unsigned char *)TA391_EC_Q, sizeof TA391_EC_Q); + trust_anchors[392] = make_rsa_trust_anchor((unsigned char *)TA392_DN, sizeof TA392_DN, (unsigned char *)TA392_RSA_N, sizeof TA392_RSA_N, (unsigned char *)TA392_RSA_E, sizeof TA392_RSA_E); + trust_anchors[393] = make_rsa_trust_anchor((unsigned char *)TA393_DN, sizeof TA393_DN, (unsigned char *)TA393_RSA_N, sizeof TA393_RSA_N, (unsigned char *)TA393_RSA_E, sizeof TA393_RSA_E); + trust_anchors[394] = make_rsa_trust_anchor((unsigned char *)TA394_DN, sizeof TA394_DN, (unsigned char *)TA394_RSA_N, sizeof TA394_RSA_N, (unsigned char *)TA394_RSA_E, sizeof TA394_RSA_E); + trust_anchors[395] = make_ec_trust_anchor((unsigned char *)TA395_DN, sizeof TA395_DN, BR_EC_secp384r1, (unsigned char *)TA395_EC_Q, sizeof TA395_EC_Q); + trust_anchors[396] = make_rsa_trust_anchor((unsigned char *)TA396_DN, sizeof TA396_DN, (unsigned char *)TA396_RSA_N, sizeof TA396_RSA_N, (unsigned char *)TA396_RSA_E, sizeof TA396_RSA_E); + trust_anchors[397] = make_rsa_trust_anchor((unsigned char *)TA397_DN, sizeof TA397_DN, (unsigned char *)TA397_RSA_N, sizeof TA397_RSA_N, (unsigned char *)TA397_RSA_E, sizeof TA397_RSA_E); + trust_anchors[398] = make_rsa_trust_anchor((unsigned char *)TA398_DN, sizeof TA398_DN, (unsigned char *)TA398_RSA_N, sizeof TA398_RSA_N, (unsigned char *)TA398_RSA_E, sizeof TA398_RSA_E); + trust_anchors[399] = make_rsa_trust_anchor((unsigned char *)TA399_DN, sizeof TA399_DN, (unsigned char *)TA399_RSA_N, sizeof TA399_RSA_N, (unsigned char *)TA399_RSA_E, sizeof TA399_RSA_E); + trust_anchors[400] = make_rsa_trust_anchor((unsigned char *)TA400_DN, sizeof TA400_DN, (unsigned char *)TA400_RSA_N, sizeof TA400_RSA_N, (unsigned char *)TA400_RSA_E, sizeof TA400_RSA_E); + trust_anchors[401] = make_ec_trust_anchor((unsigned char *)TA401_DN, sizeof TA401_DN, BR_EC_secp384r1, (unsigned char *)TA401_EC_Q, sizeof TA401_EC_Q); + trust_anchors[402] = make_rsa_trust_anchor((unsigned char *)TA402_DN, sizeof TA402_DN, (unsigned char *)TA402_RSA_N, sizeof TA402_RSA_N, (unsigned char *)TA402_RSA_E, sizeof TA402_RSA_E); + trust_anchors[403] = make_rsa_trust_anchor((unsigned char *)TA403_DN, sizeof TA403_DN, (unsigned char *)TA403_RSA_N, sizeof TA403_RSA_N, (unsigned char *)TA403_RSA_E, sizeof TA403_RSA_E); + trust_anchors[404] = make_ec_trust_anchor((unsigned char *)TA404_DN, sizeof TA404_DN, BR_EC_secp256r1, (unsigned char *)TA404_EC_Q, sizeof TA404_EC_Q); + trust_anchors[405] = make_ec_trust_anchor((unsigned char *)TA405_DN, sizeof TA405_DN, BR_EC_secp384r1, (unsigned char *)TA405_EC_Q, sizeof TA405_EC_Q); + trust_anchors[406] = make_rsa_trust_anchor((unsigned char *)TA406_DN, sizeof TA406_DN, (unsigned char *)TA406_RSA_N, sizeof TA406_RSA_N, (unsigned char *)TA406_RSA_E, sizeof TA406_RSA_E); + trust_anchors[407] = make_ec_trust_anchor((unsigned char *)TA407_DN, sizeof TA407_DN, BR_EC_secp384r1, (unsigned char *)TA407_EC_Q, sizeof TA407_EC_Q); + trust_anchors[408] = make_rsa_trust_anchor((unsigned char *)TA408_DN, sizeof TA408_DN, (unsigned char *)TA408_RSA_N, sizeof TA408_RSA_N, (unsigned char *)TA408_RSA_E, sizeof TA408_RSA_E); + trust_anchors[409] = make_rsa_trust_anchor((unsigned char *)TA409_DN, sizeof TA409_DN, (unsigned char *)TA409_RSA_N, sizeof TA409_RSA_N, (unsigned char *)TA409_RSA_E, sizeof TA409_RSA_E); + trust_anchors[410] = make_rsa_trust_anchor((unsigned char *)TA410_DN, sizeof TA410_DN, (unsigned char *)TA410_RSA_N, sizeof TA410_RSA_N, (unsigned char *)TA410_RSA_E, sizeof TA410_RSA_E); + trust_anchors[411] = make_ec_trust_anchor((unsigned char *)TA411_DN, sizeof TA411_DN, BR_EC_secp384r1, (unsigned char *)TA411_EC_Q, sizeof TA411_EC_Q); + trust_anchors[412] = make_rsa_trust_anchor((unsigned char *)TA412_DN, sizeof TA412_DN, (unsigned char *)TA412_RSA_N, sizeof TA412_RSA_N, (unsigned char *)TA412_RSA_E, sizeof TA412_RSA_E); + trust_anchors[413] = make_rsa_trust_anchor((unsigned char *)TA413_DN, sizeof TA413_DN, (unsigned char *)TA413_RSA_N, sizeof TA413_RSA_N, (unsigned char *)TA413_RSA_E, sizeof TA413_RSA_E); + trust_anchors[414] = make_rsa_trust_anchor((unsigned char *)TA414_DN, sizeof TA414_DN, (unsigned char *)TA414_RSA_N, sizeof TA414_RSA_N, (unsigned char *)TA414_RSA_E, sizeof TA414_RSA_E); + trust_anchors[415] = make_rsa_trust_anchor((unsigned char *)TA415_DN, sizeof TA415_DN, (unsigned char *)TA415_RSA_N, sizeof TA415_RSA_N, (unsigned char *)TA415_RSA_E, sizeof TA415_RSA_E); + trust_anchors[416] = make_rsa_trust_anchor((unsigned char *)TA416_DN, sizeof TA416_DN, (unsigned char *)TA416_RSA_N, sizeof TA416_RSA_N, (unsigned char *)TA416_RSA_E, sizeof TA416_RSA_E); + trust_anchors[417] = make_rsa_trust_anchor((unsigned char *)TA417_DN, sizeof TA417_DN, (unsigned char *)TA417_RSA_N, sizeof TA417_RSA_N, (unsigned char *)TA417_RSA_E, sizeof TA417_RSA_E); + trust_anchors[418] = make_ec_trust_anchor((unsigned char *)TA418_DN, sizeof TA418_DN, BR_EC_secp384r1, (unsigned char *)TA418_EC_Q, sizeof TA418_EC_Q); + trust_anchors[419] = make_rsa_trust_anchor((unsigned char *)TA419_DN, sizeof TA419_DN, (unsigned char *)TA419_RSA_N, sizeof TA419_RSA_N, (unsigned char *)TA419_RSA_E, sizeof TA419_RSA_E); + trust_anchors[420] = make_ec_trust_anchor((unsigned char *)TA420_DN, sizeof TA420_DN, BR_EC_secp384r1, (unsigned char *)TA420_EC_Q, sizeof TA420_EC_Q); + trust_anchors[421] = make_rsa_trust_anchor((unsigned char *)TA421_DN, sizeof TA421_DN, (unsigned char *)TA421_RSA_N, sizeof TA421_RSA_N, (unsigned char *)TA421_RSA_E, sizeof TA421_RSA_E); + trust_anchors[422] = make_rsa_trust_anchor((unsigned char *)TA422_DN, sizeof TA422_DN, (unsigned char *)TA422_RSA_N, sizeof TA422_RSA_N, (unsigned char *)TA422_RSA_E, sizeof TA422_RSA_E); + trust_anchors[423] = make_rsa_trust_anchor((unsigned char *)TA423_DN, sizeof TA423_DN, (unsigned char *)TA423_RSA_N, sizeof TA423_RSA_N, (unsigned char *)TA423_RSA_E, sizeof TA423_RSA_E); + trust_anchors[424] = make_ec_trust_anchor((unsigned char *)TA424_DN, sizeof TA424_DN, BR_EC_secp384r1, (unsigned char *)TA424_EC_Q, sizeof TA424_EC_Q); + trust_anchors[425] = make_rsa_trust_anchor((unsigned char *)TA425_DN, sizeof TA425_DN, (unsigned char *)TA425_RSA_N, sizeof TA425_RSA_N, (unsigned char *)TA425_RSA_E, sizeof TA425_RSA_E); + trust_anchors[426] = make_rsa_trust_anchor((unsigned char *)TA426_DN, sizeof TA426_DN, (unsigned char *)TA426_RSA_N, sizeof TA426_RSA_N, (unsigned char *)TA426_RSA_E, sizeof TA426_RSA_E); + trust_anchors[427] = make_rsa_trust_anchor((unsigned char *)TA427_DN, sizeof TA427_DN, (unsigned char *)TA427_RSA_N, sizeof TA427_RSA_N, (unsigned char *)TA427_RSA_E, sizeof TA427_RSA_E); + trust_anchors[428] = make_ec_trust_anchor((unsigned char *)TA428_DN, sizeof TA428_DN, BR_EC_secp384r1, (unsigned char *)TA428_EC_Q, sizeof TA428_EC_Q); + trust_anchors[429] = make_ec_trust_anchor((unsigned char *)TA429_DN, sizeof TA429_DN, BR_EC_secp384r1, (unsigned char *)TA429_EC_Q, sizeof TA429_EC_Q); + trust_anchors[430] = make_rsa_trust_anchor((unsigned char *)TA430_DN, sizeof TA430_DN, (unsigned char *)TA430_RSA_N, sizeof TA430_RSA_N, (unsigned char *)TA430_RSA_E, sizeof TA430_RSA_E); + trust_anchors[431] = make_rsa_trust_anchor((unsigned char *)TA431_DN, sizeof TA431_DN, (unsigned char *)TA431_RSA_N, sizeof TA431_RSA_N, (unsigned char *)TA431_RSA_E, sizeof TA431_RSA_E); + trust_anchors[432] = make_rsa_trust_anchor((unsigned char *)TA432_DN, sizeof TA432_DN, (unsigned char *)TA432_RSA_N, sizeof TA432_RSA_N, (unsigned char *)TA432_RSA_E, sizeof TA432_RSA_E); + trust_anchors[433] = make_ec_trust_anchor((unsigned char *)TA433_DN, sizeof TA433_DN, BR_EC_secp384r1, (unsigned char *)TA433_EC_Q, sizeof TA433_EC_Q); + trust_anchors[434] = make_rsa_trust_anchor((unsigned char *)TA434_DN, sizeof TA434_DN, (unsigned char *)TA434_RSA_N, sizeof TA434_RSA_N, (unsigned char *)TA434_RSA_E, sizeof TA434_RSA_E); + trust_anchors[435] = make_ec_trust_anchor((unsigned char *)TA435_DN, sizeof TA435_DN, BR_EC_secp384r1, (unsigned char *)TA435_EC_Q, sizeof TA435_EC_Q); + trust_anchors[436] = make_rsa_trust_anchor((unsigned char *)TA436_DN, sizeof TA436_DN, (unsigned char *)TA436_RSA_N, sizeof TA436_RSA_N, (unsigned char *)TA436_RSA_E, sizeof TA436_RSA_E); + trust_anchors[437] = make_rsa_trust_anchor((unsigned char *)TA437_DN, sizeof TA437_DN, (unsigned char *)TA437_RSA_N, sizeof TA437_RSA_N, (unsigned char *)TA437_RSA_E, sizeof TA437_RSA_E); + trust_anchors[438] = make_rsa_trust_anchor((unsigned char *)TA438_DN, sizeof TA438_DN, (unsigned char *)TA438_RSA_N, sizeof TA438_RSA_N, (unsigned char *)TA438_RSA_E, sizeof TA438_RSA_E); + trust_anchors[439] = make_rsa_trust_anchor((unsigned char *)TA439_DN, sizeof TA439_DN, (unsigned char *)TA439_RSA_N, sizeof TA439_RSA_N, (unsigned char *)TA439_RSA_E, sizeof TA439_RSA_E); + trust_anchors[440] = make_rsa_trust_anchor((unsigned char *)TA440_DN, sizeof TA440_DN, (unsigned char *)TA440_RSA_N, sizeof TA440_RSA_N, (unsigned char *)TA440_RSA_E, sizeof TA440_RSA_E); + trust_anchors[441] = make_ec_trust_anchor((unsigned char *)TA441_DN, sizeof TA441_DN, BR_EC_secp384r1, (unsigned char *)TA441_EC_Q, sizeof TA441_EC_Q); + trust_anchors[442] = make_rsa_trust_anchor((unsigned char *)TA442_DN, sizeof TA442_DN, (unsigned char *)TA442_RSA_N, sizeof TA442_RSA_N, (unsigned char *)TA442_RSA_E, sizeof TA442_RSA_E); + trust_anchors[443] = make_rsa_trust_anchor((unsigned char *)TA443_DN, sizeof TA443_DN, (unsigned char *)TA443_RSA_N, sizeof TA443_RSA_N, (unsigned char *)TA443_RSA_E, sizeof TA443_RSA_E); + trust_anchors[444] = make_ec_trust_anchor((unsigned char *)TA444_DN, sizeof TA444_DN, BR_EC_secp384r1, (unsigned char *)TA444_EC_Q, sizeof TA444_EC_Q); + trust_anchors[445] = make_rsa_trust_anchor((unsigned char *)TA445_DN, sizeof TA445_DN, (unsigned char *)TA445_RSA_N, sizeof TA445_RSA_N, (unsigned char *)TA445_RSA_E, sizeof TA445_RSA_E); + trust_anchors[446] = make_ec_trust_anchor((unsigned char *)TA446_DN, sizeof TA446_DN, BR_EC_secp384r1, (unsigned char *)TA446_EC_Q, sizeof TA446_EC_Q); + trust_anchors[447] = make_rsa_trust_anchor((unsigned char *)TA447_DN, sizeof TA447_DN, (unsigned char *)TA447_RSA_N, sizeof TA447_RSA_N, (unsigned char *)TA447_RSA_E, sizeof TA447_RSA_E); + trust_anchors[448] = make_rsa_trust_anchor((unsigned char *)TA448_DN, sizeof TA448_DN, (unsigned char *)TA448_RSA_N, sizeof TA448_RSA_N, (unsigned char *)TA448_RSA_E, sizeof TA448_RSA_E); + trust_anchors[449] = make_rsa_trust_anchor((unsigned char *)TA449_DN, sizeof TA449_DN, (unsigned char *)TA449_RSA_N, sizeof TA449_RSA_N, (unsigned char *)TA449_RSA_E, sizeof TA449_RSA_E); + trust_anchors[450] = make_rsa_trust_anchor((unsigned char *)TA450_DN, sizeof TA450_DN, (unsigned char *)TA450_RSA_N, sizeof TA450_RSA_N, (unsigned char *)TA450_RSA_E, sizeof TA450_RSA_E); + trust_anchors[451] = make_ec_trust_anchor((unsigned char *)TA451_DN, sizeof TA451_DN, BR_EC_secp384r1, (unsigned char *)TA451_EC_Q, sizeof TA451_EC_Q); + trust_anchors[452] = make_rsa_trust_anchor((unsigned char *)TA452_DN, sizeof TA452_DN, (unsigned char *)TA452_RSA_N, sizeof TA452_RSA_N, (unsigned char *)TA452_RSA_E, sizeof TA452_RSA_E); + trust_anchors[453] = make_ec_trust_anchor((unsigned char *)TA453_DN, sizeof TA453_DN, BR_EC_secp384r1, (unsigned char *)TA453_EC_Q, sizeof TA453_EC_Q); + trust_anchors[454] = make_rsa_trust_anchor((unsigned char *)TA454_DN, sizeof TA454_DN, (unsigned char *)TA454_RSA_N, sizeof TA454_RSA_N, (unsigned char *)TA454_RSA_E, sizeof TA454_RSA_E); + trust_anchors[455] = make_rsa_trust_anchor((unsigned char *)TA455_DN, sizeof TA455_DN, (unsigned char *)TA455_RSA_N, sizeof TA455_RSA_N, (unsigned char *)TA455_RSA_E, sizeof TA455_RSA_E); + trust_anchors[456] = make_rsa_trust_anchor((unsigned char *)TA456_DN, sizeof TA456_DN, (unsigned char *)TA456_RSA_N, sizeof TA456_RSA_N, (unsigned char *)TA456_RSA_E, sizeof TA456_RSA_E); + trust_anchors[457] = make_rsa_trust_anchor((unsigned char *)TA457_DN, sizeof TA457_DN, (unsigned char *)TA457_RSA_N, sizeof TA457_RSA_N, (unsigned char *)TA457_RSA_E, sizeof TA457_RSA_E); + trust_anchors[458] = make_ec_trust_anchor((unsigned char *)TA458_DN, sizeof TA458_DN, BR_EC_secp384r1, (unsigned char *)TA458_EC_Q, sizeof TA458_EC_Q); + trust_anchors[459] = make_ec_trust_anchor((unsigned char *)TA459_DN, sizeof TA459_DN, BR_EC_secp384r1, (unsigned char *)TA459_EC_Q, sizeof TA459_EC_Q); + trust_anchors[460] = make_ec_trust_anchor((unsigned char *)TA460_DN, sizeof TA460_DN, BR_EC_secp256r1, (unsigned char *)TA460_EC_Q, sizeof TA460_EC_Q); + trust_anchors[461] = make_ec_trust_anchor((unsigned char *)TA461_DN, sizeof TA461_DN, BR_EC_secp384r1, (unsigned char *)TA461_EC_Q, sizeof TA461_EC_Q); + trust_anchors[462] = make_rsa_trust_anchor((unsigned char *)TA462_DN, sizeof TA462_DN, (unsigned char *)TA462_RSA_N, sizeof TA462_RSA_N, (unsigned char *)TA462_RSA_E, sizeof TA462_RSA_E); + trust_anchors[463] = make_rsa_trust_anchor((unsigned char *)TA463_DN, sizeof TA463_DN, (unsigned char *)TA463_RSA_N, sizeof TA463_RSA_N, (unsigned char *)TA463_RSA_E, sizeof TA463_RSA_E); + trust_anchors[464] = make_rsa_trust_anchor((unsigned char *)TA464_DN, sizeof TA464_DN, (unsigned char *)TA464_RSA_N, sizeof TA464_RSA_N, (unsigned char *)TA464_RSA_E, sizeof TA464_RSA_E); + trust_anchors[465] = make_ec_trust_anchor((unsigned char *)TA465_DN, sizeof TA465_DN, BR_EC_secp384r1, (unsigned char *)TA465_EC_Q, sizeof TA465_EC_Q); + trust_anchors[466] = make_rsa_trust_anchor((unsigned char *)TA466_DN, sizeof TA466_DN, (unsigned char *)TA466_RSA_N, sizeof TA466_RSA_N, (unsigned char *)TA466_RSA_E, sizeof TA466_RSA_E); + trust_anchors[467] = make_rsa_trust_anchor((unsigned char *)TA467_DN, sizeof TA467_DN, (unsigned char *)TA467_RSA_N, sizeof TA467_RSA_N, (unsigned char *)TA467_RSA_E, sizeof TA467_RSA_E); + trust_anchors[468] = make_rsa_trust_anchor((unsigned char *)TA468_DN, sizeof TA468_DN, (unsigned char *)TA468_RSA_N, sizeof TA468_RSA_N, (unsigned char *)TA468_RSA_E, sizeof TA468_RSA_E); + trust_anchors[469] = make_ec_trust_anchor((unsigned char *)TA469_DN, sizeof TA469_DN, BR_EC_secp384r1, (unsigned char *)TA469_EC_Q, sizeof TA469_EC_Q); + trust_anchors[470] = make_rsa_trust_anchor((unsigned char *)TA470_DN, sizeof TA470_DN, (unsigned char *)TA470_RSA_N, sizeof TA470_RSA_N, (unsigned char *)TA470_RSA_E, sizeof TA470_RSA_E); + trust_anchors[471] = make_ec_trust_anchor((unsigned char *)TA471_DN, sizeof TA471_DN, BR_EC_secp384r1, (unsigned char *)TA471_EC_Q, sizeof TA471_EC_Q); + trust_anchors[472] = make_rsa_trust_anchor((unsigned char *)TA472_DN, sizeof TA472_DN, (unsigned char *)TA472_RSA_N, sizeof TA472_RSA_N, (unsigned char *)TA472_RSA_E, sizeof TA472_RSA_E); + trust_anchors[473] = make_rsa_trust_anchor((unsigned char *)TA473_DN, sizeof TA473_DN, (unsigned char *)TA473_RSA_N, sizeof TA473_RSA_N, (unsigned char *)TA473_RSA_E, sizeof TA473_RSA_E); + trust_anchors[474] = make_rsa_trust_anchor((unsigned char *)TA474_DN, sizeof TA474_DN, (unsigned char *)TA474_RSA_N, sizeof TA474_RSA_N, (unsigned char *)TA474_RSA_E, sizeof TA474_RSA_E); + trust_anchors[475] = make_rsa_trust_anchor((unsigned char *)TA475_DN, sizeof TA475_DN, (unsigned char *)TA475_RSA_N, sizeof TA475_RSA_N, (unsigned char *)TA475_RSA_E, sizeof TA475_RSA_E); + trust_anchors[476] = make_ec_trust_anchor((unsigned char *)TA476_DN, sizeof TA476_DN, BR_EC_secp384r1, (unsigned char *)TA476_EC_Q, sizeof TA476_EC_Q); + trust_anchors[477] = make_rsa_trust_anchor((unsigned char *)TA477_DN, sizeof TA477_DN, (unsigned char *)TA477_RSA_N, sizeof TA477_RSA_N, (unsigned char *)TA477_RSA_E, sizeof TA477_RSA_E); + trust_anchors[478] = make_rsa_trust_anchor((unsigned char *)TA478_DN, sizeof TA478_DN, (unsigned char *)TA478_RSA_N, sizeof TA478_RSA_N, (unsigned char *)TA478_RSA_E, sizeof TA478_RSA_E); + trust_anchors[479] = make_rsa_trust_anchor((unsigned char *)TA479_DN, sizeof TA479_DN, (unsigned char *)TA479_RSA_N, sizeof TA479_RSA_N, (unsigned char *)TA479_RSA_E, sizeof TA479_RSA_E); + trust_anchors[480] = make_rsa_trust_anchor((unsigned char *)TA480_DN, sizeof TA480_DN, (unsigned char *)TA480_RSA_N, sizeof TA480_RSA_N, (unsigned char *)TA480_RSA_E, sizeof TA480_RSA_E); + trust_anchors[481] = make_ec_trust_anchor((unsigned char *)TA481_DN, sizeof TA481_DN, BR_EC_secp384r1, (unsigned char *)TA481_EC_Q, sizeof TA481_EC_Q); + trust_anchors[482] = make_rsa_trust_anchor((unsigned char *)TA482_DN, sizeof TA482_DN, (unsigned char *)TA482_RSA_N, sizeof TA482_RSA_N, (unsigned char *)TA482_RSA_E, sizeof TA482_RSA_E); + trust_anchors[483] = make_rsa_trust_anchor((unsigned char *)TA483_DN, sizeof TA483_DN, (unsigned char *)TA483_RSA_N, sizeof TA483_RSA_N, (unsigned char *)TA483_RSA_E, sizeof TA483_RSA_E); + trust_anchors[484] = make_rsa_trust_anchor((unsigned char *)TA484_DN, sizeof TA484_DN, (unsigned char *)TA484_RSA_N, sizeof TA484_RSA_N, (unsigned char *)TA484_RSA_E, sizeof TA484_RSA_E); + trust_anchors[485] = make_rsa_trust_anchor((unsigned char *)TA485_DN, sizeof TA485_DN, (unsigned char *)TA485_RSA_N, sizeof TA485_RSA_N, (unsigned char *)TA485_RSA_E, sizeof TA485_RSA_E); + trust_anchors[486] = make_ec_trust_anchor((unsigned char *)TA486_DN, sizeof TA486_DN, BR_EC_secp384r1, (unsigned char *)TA486_EC_Q, sizeof TA486_EC_Q); + trust_anchors[487] = make_rsa_trust_anchor((unsigned char *)TA487_DN, sizeof TA487_DN, (unsigned char *)TA487_RSA_N, sizeof TA487_RSA_N, (unsigned char *)TA487_RSA_E, sizeof TA487_RSA_E); + trust_anchors[488] = make_rsa_trust_anchor((unsigned char *)TA488_DN, sizeof TA488_DN, (unsigned char *)TA488_RSA_N, sizeof TA488_RSA_N, (unsigned char *)TA488_RSA_E, sizeof TA488_RSA_E); + trust_anchors[489] = make_rsa_trust_anchor((unsigned char *)TA489_DN, sizeof TA489_DN, (unsigned char *)TA489_RSA_N, sizeof TA489_RSA_N, (unsigned char *)TA489_RSA_E, sizeof TA489_RSA_E); + trust_anchors[490] = make_rsa_trust_anchor((unsigned char *)TA490_DN, sizeof TA490_DN, (unsigned char *)TA490_RSA_N, sizeof TA490_RSA_N, (unsigned char *)TA490_RSA_E, sizeof TA490_RSA_E); + trust_anchors[491] = make_rsa_trust_anchor((unsigned char *)TA491_DN, sizeof TA491_DN, (unsigned char *)TA491_RSA_N, sizeof TA491_RSA_N, (unsigned char *)TA491_RSA_E, sizeof TA491_RSA_E); + trust_anchors[492] = make_ec_trust_anchor((unsigned char *)TA492_DN, sizeof TA492_DN, BR_EC_secp384r1, (unsigned char *)TA492_EC_Q, sizeof TA492_EC_Q); + trust_anchors[493] = make_rsa_trust_anchor((unsigned char *)TA493_DN, sizeof TA493_DN, (unsigned char *)TA493_RSA_N, sizeof TA493_RSA_N, (unsigned char *)TA493_RSA_E, sizeof TA493_RSA_E); + trust_anchors[494] = make_ec_trust_anchor((unsigned char *)TA494_DN, sizeof TA494_DN, BR_EC_secp384r1, (unsigned char *)TA494_EC_Q, sizeof TA494_EC_Q); + trust_anchors[495] = make_rsa_trust_anchor((unsigned char *)TA495_DN, sizeof TA495_DN, (unsigned char *)TA495_RSA_N, sizeof TA495_RSA_N, (unsigned char *)TA495_RSA_E, sizeof TA495_RSA_E); + trust_anchors[496] = make_ec_trust_anchor((unsigned char *)TA496_DN, sizeof TA496_DN, BR_EC_secp384r1, (unsigned char *)TA496_EC_Q, sizeof TA496_EC_Q); + trust_anchors[497] = make_rsa_trust_anchor((unsigned char *)TA497_DN, sizeof TA497_DN, (unsigned char *)TA497_RSA_N, sizeof TA497_RSA_N, (unsigned char *)TA497_RSA_E, sizeof TA497_RSA_E); + trust_anchors[498] = make_rsa_trust_anchor((unsigned char *)TA498_DN, sizeof TA498_DN, (unsigned char *)TA498_RSA_N, sizeof TA498_RSA_N, (unsigned char *)TA498_RSA_E, sizeof TA498_RSA_E); + trust_anchors[499] = make_ec_trust_anchor((unsigned char *)TA499_DN, sizeof TA499_DN, BR_EC_secp384r1, (unsigned char *)TA499_EC_Q, sizeof TA499_EC_Q); + trust_anchors[500] = make_rsa_trust_anchor((unsigned char *)TA500_DN, sizeof TA500_DN, (unsigned char *)TA500_RSA_N, sizeof TA500_RSA_N, (unsigned char *)TA500_RSA_E, sizeof TA500_RSA_E); + trust_anchors[501] = make_rsa_trust_anchor((unsigned char *)TA501_DN, sizeof TA501_DN, (unsigned char *)TA501_RSA_N, sizeof TA501_RSA_N, (unsigned char *)TA501_RSA_E, sizeof TA501_RSA_E); + trust_anchors[502] = make_rsa_trust_anchor((unsigned char *)TA502_DN, sizeof TA502_DN, (unsigned char *)TA502_RSA_N, sizeof TA502_RSA_N, (unsigned char *)TA502_RSA_E, sizeof TA502_RSA_E); + trust_anchors[503] = make_ec_trust_anchor((unsigned char *)TA503_DN, sizeof TA503_DN, BR_EC_secp384r1, (unsigned char *)TA503_EC_Q, sizeof TA503_EC_Q); + trust_anchors[504] = make_rsa_trust_anchor((unsigned char *)TA504_DN, sizeof TA504_DN, (unsigned char *)TA504_RSA_N, sizeof TA504_RSA_N, (unsigned char *)TA504_RSA_E, sizeof TA504_RSA_E); + trust_anchors[505] = make_rsa_trust_anchor((unsigned char *)TA505_DN, sizeof TA505_DN, (unsigned char *)TA505_RSA_N, sizeof TA505_RSA_N, (unsigned char *)TA505_RSA_E, sizeof TA505_RSA_E); + trust_anchors[506] = make_ec_trust_anchor((unsigned char *)TA506_DN, sizeof TA506_DN, BR_EC_secp384r1, (unsigned char *)TA506_EC_Q, sizeof TA506_EC_Q); + trust_anchors[507] = make_rsa_trust_anchor((unsigned char *)TA507_DN, sizeof TA507_DN, (unsigned char *)TA507_RSA_N, sizeof TA507_RSA_N, (unsigned char *)TA507_RSA_E, sizeof TA507_RSA_E); + trust_anchors[508] = make_rsa_trust_anchor((unsigned char *)TA508_DN, sizeof TA508_DN, (unsigned char *)TA508_RSA_N, sizeof TA508_RSA_N, (unsigned char *)TA508_RSA_E, sizeof TA508_RSA_E); + trust_anchors[509] = make_rsa_trust_anchor((unsigned char *)TA509_DN, sizeof TA509_DN, (unsigned char *)TA509_RSA_N, sizeof TA509_RSA_N, (unsigned char *)TA509_RSA_E, sizeof TA509_RSA_E); + trust_anchors[510] = make_rsa_trust_anchor((unsigned char *)TA510_DN, sizeof TA510_DN, (unsigned char *)TA510_RSA_N, sizeof TA510_RSA_N, (unsigned char *)TA510_RSA_E, sizeof TA510_RSA_E); + trust_anchors[511] = make_rsa_trust_anchor((unsigned char *)TA511_DN, sizeof TA511_DN, (unsigned char *)TA511_RSA_N, sizeof TA511_RSA_N, (unsigned char *)TA511_RSA_E, sizeof TA511_RSA_E); + trust_anchors[512] = make_rsa_trust_anchor((unsigned char *)TA512_DN, sizeof TA512_DN, (unsigned char *)TA512_RSA_N, sizeof TA512_RSA_N, (unsigned char *)TA512_RSA_E, sizeof TA512_RSA_E); + trust_anchors[513] = make_rsa_trust_anchor((unsigned char *)TA513_DN, sizeof TA513_DN, (unsigned char *)TA513_RSA_N, sizeof TA513_RSA_N, (unsigned char *)TA513_RSA_E, sizeof TA513_RSA_E); + trust_anchors[514] = make_rsa_trust_anchor((unsigned char *)TA514_DN, sizeof TA514_DN, (unsigned char *)TA514_RSA_N, sizeof TA514_RSA_N, (unsigned char *)TA514_RSA_E, sizeof TA514_RSA_E); + trust_anchors[515] = make_rsa_trust_anchor((unsigned char *)TA515_DN, sizeof TA515_DN, (unsigned char *)TA515_RSA_N, sizeof TA515_RSA_N, (unsigned char *)TA515_RSA_E, sizeof TA515_RSA_E); + trust_anchors[516] = make_rsa_trust_anchor((unsigned char *)TA516_DN, sizeof TA516_DN, (unsigned char *)TA516_RSA_N, sizeof TA516_RSA_N, (unsigned char *)TA516_RSA_E, sizeof TA516_RSA_E); + trust_anchors[517] = make_rsa_trust_anchor((unsigned char *)TA517_DN, sizeof TA517_DN, (unsigned char *)TA517_RSA_N, sizeof TA517_RSA_N, (unsigned char *)TA517_RSA_E, sizeof TA517_RSA_E); + trust_anchors[518] = make_ec_trust_anchor((unsigned char *)TA518_DN, sizeof TA518_DN, BR_EC_secp384r1, (unsigned char *)TA518_EC_Q, sizeof TA518_EC_Q); + trust_anchors[519] = make_rsa_trust_anchor((unsigned char *)TA519_DN, sizeof TA519_DN, (unsigned char *)TA519_RSA_N, sizeof TA519_RSA_N, (unsigned char *)TA519_RSA_E, sizeof TA519_RSA_E); + trust_anchors[520] = make_rsa_trust_anchor((unsigned char *)TA520_DN, sizeof TA520_DN, (unsigned char *)TA520_RSA_N, sizeof TA520_RSA_N, (unsigned char *)TA520_RSA_E, sizeof TA520_RSA_E); + trust_anchors[521] = make_rsa_trust_anchor((unsigned char *)TA521_DN, sizeof TA521_DN, (unsigned char *)TA521_RSA_N, sizeof TA521_RSA_N, (unsigned char *)TA521_RSA_E, sizeof TA521_RSA_E); + trust_anchors[522] = make_rsa_trust_anchor((unsigned char *)TA522_DN, sizeof TA522_DN, (unsigned char *)TA522_RSA_N, sizeof TA522_RSA_N, (unsigned char *)TA522_RSA_E, sizeof TA522_RSA_E); + trust_anchors[523] = make_ec_trust_anchor((unsigned char *)TA523_DN, sizeof TA523_DN, BR_EC_secp384r1, (unsigned char *)TA523_EC_Q, sizeof TA523_EC_Q); + trust_anchors[524] = make_rsa_trust_anchor((unsigned char *)TA524_DN, sizeof TA524_DN, (unsigned char *)TA524_RSA_N, sizeof TA524_RSA_N, (unsigned char *)TA524_RSA_E, sizeof TA524_RSA_E); + trust_anchors[525] = make_ec_trust_anchor((unsigned char *)TA525_DN, sizeof TA525_DN, BR_EC_secp256r1, (unsigned char *)TA525_EC_Q, sizeof TA525_EC_Q); + trust_anchors[526] = make_ec_trust_anchor((unsigned char *)TA526_DN, sizeof TA526_DN, BR_EC_secp384r1, (unsigned char *)TA526_EC_Q, sizeof TA526_EC_Q); + trust_anchors[527] = make_rsa_trust_anchor((unsigned char *)TA527_DN, sizeof TA527_DN, (unsigned char *)TA527_RSA_N, sizeof TA527_RSA_N, (unsigned char *)TA527_RSA_E, sizeof TA527_RSA_E); + trust_anchors[528] = make_rsa_trust_anchor((unsigned char *)TA528_DN, sizeof TA528_DN, (unsigned char *)TA528_RSA_N, sizeof TA528_RSA_N, (unsigned char *)TA528_RSA_E, sizeof TA528_RSA_E); + trust_anchors[529] = make_rsa_trust_anchor((unsigned char *)TA529_DN, sizeof TA529_DN, (unsigned char *)TA529_RSA_N, sizeof TA529_RSA_N, (unsigned char *)TA529_RSA_E, sizeof TA529_RSA_E); + trust_anchors[530] = make_ec_trust_anchor((unsigned char *)TA530_DN, sizeof TA530_DN, BR_EC_secp384r1, (unsigned char *)TA530_EC_Q, sizeof TA530_EC_Q); + trust_anchors[531] = make_rsa_trust_anchor((unsigned char *)TA531_DN, sizeof TA531_DN, (unsigned char *)TA531_RSA_N, sizeof TA531_RSA_N, (unsigned char *)TA531_RSA_E, sizeof TA531_RSA_E); + trust_anchors[532] = make_rsa_trust_anchor((unsigned char *)TA532_DN, sizeof TA532_DN, (unsigned char *)TA532_RSA_N, sizeof TA532_RSA_N, (unsigned char *)TA532_RSA_E, sizeof TA532_RSA_E); + trust_anchors[533] = make_rsa_trust_anchor((unsigned char *)TA533_DN, sizeof TA533_DN, (unsigned char *)TA533_RSA_N, sizeof TA533_RSA_N, (unsigned char *)TA533_RSA_E, sizeof TA533_RSA_E); + trust_anchors[534] = make_rsa_trust_anchor((unsigned char *)TA534_DN, sizeof TA534_DN, (unsigned char *)TA534_RSA_N, sizeof TA534_RSA_N, (unsigned char *)TA534_RSA_E, sizeof TA534_RSA_E); + trust_anchors[535] = make_ec_trust_anchor((unsigned char *)TA535_DN, sizeof TA535_DN, BR_EC_secp256r1, (unsigned char *)TA535_EC_Q, sizeof TA535_EC_Q); + trust_anchors[536] = make_rsa_trust_anchor((unsigned char *)TA536_DN, sizeof TA536_DN, (unsigned char *)TA536_RSA_N, sizeof TA536_RSA_N, (unsigned char *)TA536_RSA_E, sizeof TA536_RSA_E); + trust_anchors[537] = make_ec_trust_anchor((unsigned char *)TA537_DN, sizeof TA537_DN, BR_EC_secp384r1, (unsigned char *)TA537_EC_Q, sizeof TA537_EC_Q); + trust_anchors[538] = make_ec_trust_anchor((unsigned char *)TA538_DN, sizeof TA538_DN, BR_EC_secp384r1, (unsigned char *)TA538_EC_Q, sizeof TA538_EC_Q); + trust_anchors[539] = make_rsa_trust_anchor((unsigned char *)TA539_DN, sizeof TA539_DN, (unsigned char *)TA539_RSA_N, sizeof TA539_RSA_N, (unsigned char *)TA539_RSA_E, sizeof TA539_RSA_E); + trust_anchors[540] = make_rsa_trust_anchor((unsigned char *)TA540_DN, sizeof TA540_DN, (unsigned char *)TA540_RSA_N, sizeof TA540_RSA_N, (unsigned char *)TA540_RSA_E, sizeof TA540_RSA_E); + trust_anchors[541] = make_ec_trust_anchor((unsigned char *)TA541_DN, sizeof TA541_DN, BR_EC_secp384r1, (unsigned char *)TA541_EC_Q, sizeof TA541_EC_Q); + trust_anchors[542] = make_rsa_trust_anchor((unsigned char *)TA542_DN, sizeof TA542_DN, (unsigned char *)TA542_RSA_N, sizeof TA542_RSA_N, (unsigned char *)TA542_RSA_E, sizeof TA542_RSA_E); + trust_anchors[543] = make_rsa_trust_anchor((unsigned char *)TA543_DN, sizeof TA543_DN, (unsigned char *)TA543_RSA_N, sizeof TA543_RSA_N, (unsigned char *)TA543_RSA_E, sizeof TA543_RSA_E); + trust_anchors[544] = make_rsa_trust_anchor((unsigned char *)TA544_DN, sizeof TA544_DN, (unsigned char *)TA544_RSA_N, sizeof TA544_RSA_N, (unsigned char *)TA544_RSA_E, sizeof TA544_RSA_E); + trust_anchors[545] = make_ec_trust_anchor((unsigned char *)TA545_DN, sizeof TA545_DN, BR_EC_secp384r1, (unsigned char *)TA545_EC_Q, sizeof TA545_EC_Q); + trust_anchors[546] = make_rsa_trust_anchor((unsigned char *)TA546_DN, sizeof TA546_DN, (unsigned char *)TA546_RSA_N, sizeof TA546_RSA_N, (unsigned char *)TA546_RSA_E, sizeof TA546_RSA_E); + trust_anchors[547] = make_rsa_trust_anchor((unsigned char *)TA547_DN, sizeof TA547_DN, (unsigned char *)TA547_RSA_N, sizeof TA547_RSA_N, (unsigned char *)TA547_RSA_E, sizeof TA547_RSA_E); + trust_anchors[548] = make_ec_trust_anchor((unsigned char *)TA548_DN, sizeof TA548_DN, BR_EC_secp384r1, (unsigned char *)TA548_EC_Q, sizeof TA548_EC_Q); + trust_anchors[549] = make_rsa_trust_anchor((unsigned char *)TA549_DN, sizeof TA549_DN, (unsigned char *)TA549_RSA_N, sizeof TA549_RSA_N, (unsigned char *)TA549_RSA_E, sizeof TA549_RSA_E); + trust_anchors[550] = make_rsa_trust_anchor((unsigned char *)TA550_DN, sizeof TA550_DN, (unsigned char *)TA550_RSA_N, sizeof TA550_RSA_N, (unsigned char *)TA550_RSA_E, sizeof TA550_RSA_E); + trust_anchors[551] = make_rsa_trust_anchor((unsigned char *)TA551_DN, sizeof TA551_DN, (unsigned char *)TA551_RSA_N, sizeof TA551_RSA_N, (unsigned char *)TA551_RSA_E, sizeof TA551_RSA_E); + trust_anchors[552] = make_ec_trust_anchor((unsigned char *)TA552_DN, sizeof TA552_DN, BR_EC_secp384r1, (unsigned char *)TA552_EC_Q, sizeof TA552_EC_Q); + trust_anchors[553] = make_rsa_trust_anchor((unsigned char *)TA553_DN, sizeof TA553_DN, (unsigned char *)TA553_RSA_N, sizeof TA553_RSA_N, (unsigned char *)TA553_RSA_E, sizeof TA553_RSA_E); + trust_anchors[554] = make_rsa_trust_anchor((unsigned char *)TA554_DN, sizeof TA554_DN, (unsigned char *)TA554_RSA_N, sizeof TA554_RSA_N, (unsigned char *)TA554_RSA_E, sizeof TA554_RSA_E); + trust_anchors[555] = make_rsa_trust_anchor((unsigned char *)TA555_DN, sizeof TA555_DN, (unsigned char *)TA555_RSA_N, sizeof TA555_RSA_N, (unsigned char *)TA555_RSA_E, sizeof TA555_RSA_E); + trust_anchors[556] = make_rsa_trust_anchor((unsigned char *)TA556_DN, sizeof TA556_DN, (unsigned char *)TA556_RSA_N, sizeof TA556_RSA_N, (unsigned char *)TA556_RSA_E, sizeof TA556_RSA_E); + trust_anchors[557] = make_rsa_trust_anchor((unsigned char *)TA557_DN, sizeof TA557_DN, (unsigned char *)TA557_RSA_N, sizeof TA557_RSA_N, (unsigned char *)TA557_RSA_E, sizeof TA557_RSA_E); + trust_anchors[558] = make_ec_trust_anchor((unsigned char *)TA558_DN, sizeof TA558_DN, BR_EC_secp384r1, (unsigned char *)TA558_EC_Q, sizeof TA558_EC_Q); + trust_anchors[559] = make_rsa_trust_anchor((unsigned char *)TA559_DN, sizeof TA559_DN, (unsigned char *)TA559_RSA_N, sizeof TA559_RSA_N, (unsigned char *)TA559_RSA_E, sizeof TA559_RSA_E); + trust_anchors[560] = make_rsa_trust_anchor((unsigned char *)TA560_DN, sizeof TA560_DN, (unsigned char *)TA560_RSA_N, sizeof TA560_RSA_N, (unsigned char *)TA560_RSA_E, sizeof TA560_RSA_E); + trust_anchors[561] = make_rsa_trust_anchor((unsigned char *)TA561_DN, sizeof TA561_DN, (unsigned char *)TA561_RSA_N, sizeof TA561_RSA_N, (unsigned char *)TA561_RSA_E, sizeof TA561_RSA_E); + trust_anchors[562] = make_rsa_trust_anchor((unsigned char *)TA562_DN, sizeof TA562_DN, (unsigned char *)TA562_RSA_N, sizeof TA562_RSA_N, (unsigned char *)TA562_RSA_E, sizeof TA562_RSA_E); + trust_anchors[563] = make_rsa_trust_anchor((unsigned char *)TA563_DN, sizeof TA563_DN, (unsigned char *)TA563_RSA_N, sizeof TA563_RSA_N, (unsigned char *)TA563_RSA_E, sizeof TA563_RSA_E); + trust_anchors[564] = make_ec_trust_anchor((unsigned char *)TA564_DN, sizeof TA564_DN, BR_EC_secp384r1, (unsigned char *)TA564_EC_Q, sizeof TA564_EC_Q); + trust_anchors[565] = make_ec_trust_anchor((unsigned char *)TA565_DN, sizeof TA565_DN, BR_EC_secp384r1, (unsigned char *)TA565_EC_Q, sizeof TA565_EC_Q); + trust_anchors[566] = make_rsa_trust_anchor((unsigned char *)TA566_DN, sizeof TA566_DN, (unsigned char *)TA566_RSA_N, sizeof TA566_RSA_N, (unsigned char *)TA566_RSA_E, sizeof TA566_RSA_E); + trust_anchors[567] = make_rsa_trust_anchor((unsigned char *)TA567_DN, sizeof TA567_DN, (unsigned char *)TA567_RSA_N, sizeof TA567_RSA_N, (unsigned char *)TA567_RSA_E, sizeof TA567_RSA_E); + trust_anchors[568] = make_rsa_trust_anchor((unsigned char *)TA568_DN, sizeof TA568_DN, (unsigned char *)TA568_RSA_N, sizeof TA568_RSA_N, (unsigned char *)TA568_RSA_E, sizeof TA568_RSA_E); + trust_anchors[569] = make_rsa_trust_anchor((unsigned char *)TA569_DN, sizeof TA569_DN, (unsigned char *)TA569_RSA_N, sizeof TA569_RSA_N, (unsigned char *)TA569_RSA_E, sizeof TA569_RSA_E); + trust_anchors[570] = make_ec_trust_anchor((unsigned char *)TA570_DN, sizeof TA570_DN, BR_EC_secp384r1, (unsigned char *)TA570_EC_Q, sizeof TA570_EC_Q); + trust_anchors[571] = make_rsa_trust_anchor((unsigned char *)TA571_DN, sizeof TA571_DN, (unsigned char *)TA571_RSA_N, sizeof TA571_RSA_N, (unsigned char *)TA571_RSA_E, sizeof TA571_RSA_E); + trust_anchors[572] = make_rsa_trust_anchor((unsigned char *)TA572_DN, sizeof TA572_DN, (unsigned char *)TA572_RSA_N, sizeof TA572_RSA_N, (unsigned char *)TA572_RSA_E, sizeof TA572_RSA_E); + trust_anchors[573] = make_rsa_trust_anchor((unsigned char *)TA573_DN, sizeof TA573_DN, (unsigned char *)TA573_RSA_N, sizeof TA573_RSA_N, (unsigned char *)TA573_RSA_E, sizeof TA573_RSA_E); + trust_anchors[574] = make_rsa_trust_anchor((unsigned char *)TA574_DN, sizeof TA574_DN, (unsigned char *)TA574_RSA_N, sizeof TA574_RSA_N, (unsigned char *)TA574_RSA_E, sizeof TA574_RSA_E); + trust_anchors[575] = make_rsa_trust_anchor((unsigned char *)TA575_DN, sizeof TA575_DN, (unsigned char *)TA575_RSA_N, sizeof TA575_RSA_N, (unsigned char *)TA575_RSA_E, sizeof TA575_RSA_E); + trust_anchors[576] = make_ec_trust_anchor((unsigned char *)TA576_DN, sizeof TA576_DN, BR_EC_secp384r1, (unsigned char *)TA576_EC_Q, sizeof TA576_EC_Q); + trust_anchors[577] = make_rsa_trust_anchor((unsigned char *)TA577_DN, sizeof TA577_DN, (unsigned char *)TA577_RSA_N, sizeof TA577_RSA_N, (unsigned char *)TA577_RSA_E, sizeof TA577_RSA_E); + trust_anchors[578] = make_rsa_trust_anchor((unsigned char *)TA578_DN, sizeof TA578_DN, (unsigned char *)TA578_RSA_N, sizeof TA578_RSA_N, (unsigned char *)TA578_RSA_E, sizeof TA578_RSA_E); + trust_anchors[579] = make_rsa_trust_anchor((unsigned char *)TA579_DN, sizeof TA579_DN, (unsigned char *)TA579_RSA_N, sizeof TA579_RSA_N, (unsigned char *)TA579_RSA_E, sizeof TA579_RSA_E); + trust_anchors[580] = make_rsa_trust_anchor((unsigned char *)TA580_DN, sizeof TA580_DN, (unsigned char *)TA580_RSA_N, sizeof TA580_RSA_N, (unsigned char *)TA580_RSA_E, sizeof TA580_RSA_E); + trust_anchors[581] = make_rsa_trust_anchor((unsigned char *)TA581_DN, sizeof TA581_DN, (unsigned char *)TA581_RSA_N, sizeof TA581_RSA_N, (unsigned char *)TA581_RSA_E, sizeof TA581_RSA_E); + trust_anchors[582] = make_rsa_trust_anchor((unsigned char *)TA582_DN, sizeof TA582_DN, (unsigned char *)TA582_RSA_N, sizeof TA582_RSA_N, (unsigned char *)TA582_RSA_E, sizeof TA582_RSA_E); + trust_anchors[583] = make_rsa_trust_anchor((unsigned char *)TA583_DN, sizeof TA583_DN, (unsigned char *)TA583_RSA_N, sizeof TA583_RSA_N, (unsigned char *)TA583_RSA_E, sizeof TA583_RSA_E); + trust_anchors[584] = make_ec_trust_anchor((unsigned char *)TA584_DN, sizeof TA584_DN, BR_EC_secp384r1, (unsigned char *)TA584_EC_Q, sizeof TA584_EC_Q); + trust_anchors[585] = make_rsa_trust_anchor((unsigned char *)TA585_DN, sizeof TA585_DN, (unsigned char *)TA585_RSA_N, sizeof TA585_RSA_N, (unsigned char *)TA585_RSA_E, sizeof TA585_RSA_E); + trust_anchors[586] = make_ec_trust_anchor((unsigned char *)TA586_DN, sizeof TA586_DN, BR_EC_secp384r1, (unsigned char *)TA586_EC_Q, sizeof TA586_EC_Q); + trust_anchors[587] = make_rsa_trust_anchor((unsigned char *)TA587_DN, sizeof TA587_DN, (unsigned char *)TA587_RSA_N, sizeof TA587_RSA_N, (unsigned char *)TA587_RSA_E, sizeof TA587_RSA_E); + trust_anchors[588] = make_rsa_trust_anchor((unsigned char *)TA588_DN, sizeof TA588_DN, (unsigned char *)TA588_RSA_N, sizeof TA588_RSA_N, (unsigned char *)TA588_RSA_E, sizeof TA588_RSA_E); + trust_anchors[589] = make_rsa_trust_anchor((unsigned char *)TA589_DN, sizeof TA589_DN, (unsigned char *)TA589_RSA_N, sizeof TA589_RSA_N, (unsigned char *)TA589_RSA_E, sizeof TA589_RSA_E); + trust_anchors[590] = make_rsa_trust_anchor((unsigned char *)TA590_DN, sizeof TA590_DN, (unsigned char *)TA590_RSA_N, sizeof TA590_RSA_N, (unsigned char *)TA590_RSA_E, sizeof TA590_RSA_E); + trust_anchors[591] = make_rsa_trust_anchor((unsigned char *)TA591_DN, sizeof TA591_DN, (unsigned char *)TA591_RSA_N, sizeof TA591_RSA_N, (unsigned char *)TA591_RSA_E, sizeof TA591_RSA_E); + trust_anchors[592] = make_ec_trust_anchor((unsigned char *)TA592_DN, sizeof TA592_DN, BR_EC_secp384r1, (unsigned char *)TA592_EC_Q, sizeof TA592_EC_Q); + trust_anchors[593] = make_ec_trust_anchor((unsigned char *)TA593_DN, sizeof TA593_DN, BR_EC_secp384r1, (unsigned char *)TA593_EC_Q, sizeof TA593_EC_Q); + trust_anchors[594] = make_ec_trust_anchor((unsigned char *)TA594_DN, sizeof TA594_DN, BR_EC_secp384r1, (unsigned char *)TA594_EC_Q, sizeof TA594_EC_Q); + trust_anchors[595] = make_rsa_trust_anchor((unsigned char *)TA595_DN, sizeof TA595_DN, (unsigned char *)TA595_RSA_N, sizeof TA595_RSA_N, (unsigned char *)TA595_RSA_E, sizeof TA595_RSA_E); + trust_anchors[596] = make_rsa_trust_anchor((unsigned char *)TA596_DN, sizeof TA596_DN, (unsigned char *)TA596_RSA_N, sizeof TA596_RSA_N, (unsigned char *)TA596_RSA_E, sizeof TA596_RSA_E); + trust_anchors[597] = make_rsa_trust_anchor((unsigned char *)TA597_DN, sizeof TA597_DN, (unsigned char *)TA597_RSA_N, sizeof TA597_RSA_N, (unsigned char *)TA597_RSA_E, sizeof TA597_RSA_E); + trust_anchors[598] = make_ec_trust_anchor((unsigned char *)TA598_DN, sizeof TA598_DN, BR_EC_secp384r1, (unsigned char *)TA598_EC_Q, sizeof TA598_EC_Q); + trust_anchors[599] = make_rsa_trust_anchor((unsigned char *)TA599_DN, sizeof TA599_DN, (unsigned char *)TA599_RSA_N, sizeof TA599_RSA_N, (unsigned char *)TA599_RSA_E, sizeof TA599_RSA_E); + trust_anchors[600] = make_rsa_trust_anchor((unsigned char *)TA600_DN, sizeof TA600_DN, (unsigned char *)TA600_RSA_N, sizeof TA600_RSA_N, (unsigned char *)TA600_RSA_E, sizeof TA600_RSA_E); + trust_anchors[601] = make_ec_trust_anchor((unsigned char *)TA601_DN, sizeof TA601_DN, BR_EC_secp384r1, (unsigned char *)TA601_EC_Q, sizeof TA601_EC_Q); + trust_anchors[602] = make_rsa_trust_anchor((unsigned char *)TA602_DN, sizeof TA602_DN, (unsigned char *)TA602_RSA_N, sizeof TA602_RSA_N, (unsigned char *)TA602_RSA_E, sizeof TA602_RSA_E); + trust_anchors[603] = make_ec_trust_anchor((unsigned char *)TA603_DN, sizeof TA603_DN, BR_EC_secp384r1, (unsigned char *)TA603_EC_Q, sizeof TA603_EC_Q); + trust_anchors[604] = make_rsa_trust_anchor((unsigned char *)TA604_DN, sizeof TA604_DN, (unsigned char *)TA604_RSA_N, sizeof TA604_RSA_N, (unsigned char *)TA604_RSA_E, sizeof TA604_RSA_E); + trust_anchors[605] = make_rsa_trust_anchor((unsigned char *)TA605_DN, sizeof TA605_DN, (unsigned char *)TA605_RSA_N, sizeof TA605_RSA_N, (unsigned char *)TA605_RSA_E, sizeof TA605_RSA_E); + trust_anchors[606] = make_ec_trust_anchor((unsigned char *)TA606_DN, sizeof TA606_DN, BR_EC_secp384r1, (unsigned char *)TA606_EC_Q, sizeof TA606_EC_Q); + trust_anchors[607] = make_rsa_trust_anchor((unsigned char *)TA607_DN, sizeof TA607_DN, (unsigned char *)TA607_RSA_N, sizeof TA607_RSA_N, (unsigned char *)TA607_RSA_E, sizeof TA607_RSA_E); + trust_anchors[608] = make_ec_trust_anchor((unsigned char *)TA608_DN, sizeof TA608_DN, BR_EC_secp384r1, (unsigned char *)TA608_EC_Q, sizeof TA608_EC_Q); + trust_anchors[609] = make_rsa_trust_anchor((unsigned char *)TA609_DN, sizeof TA609_DN, (unsigned char *)TA609_RSA_N, sizeof TA609_RSA_N, (unsigned char *)TA609_RSA_E, sizeof TA609_RSA_E); + trust_anchors[610] = make_rsa_trust_anchor((unsigned char *)TA610_DN, sizeof TA610_DN, (unsigned char *)TA610_RSA_N, sizeof TA610_RSA_N, (unsigned char *)TA610_RSA_E, sizeof TA610_RSA_E); + trust_anchors[611] = make_rsa_trust_anchor((unsigned char *)TA611_DN, sizeof TA611_DN, (unsigned char *)TA611_RSA_N, sizeof TA611_RSA_N, (unsigned char *)TA611_RSA_E, sizeof TA611_RSA_E); + trust_anchors[612] = make_rsa_trust_anchor((unsigned char *)TA612_DN, sizeof TA612_DN, (unsigned char *)TA612_RSA_N, sizeof TA612_RSA_N, (unsigned char *)TA612_RSA_E, sizeof TA612_RSA_E); + trust_anchors[613] = make_rsa_trust_anchor((unsigned char *)TA613_DN, sizeof TA613_DN, (unsigned char *)TA613_RSA_N, sizeof TA613_RSA_N, (unsigned char *)TA613_RSA_E, sizeof TA613_RSA_E); + trust_anchors[614] = make_rsa_trust_anchor((unsigned char *)TA614_DN, sizeof TA614_DN, (unsigned char *)TA614_RSA_N, sizeof TA614_RSA_N, (unsigned char *)TA614_RSA_E, sizeof TA614_RSA_E); + trust_anchors[615] = make_rsa_trust_anchor((unsigned char *)TA615_DN, sizeof TA615_DN, (unsigned char *)TA615_RSA_N, sizeof TA615_RSA_N, (unsigned char *)TA615_RSA_E, sizeof TA615_RSA_E); + trust_anchors[616] = make_rsa_trust_anchor((unsigned char *)TA616_DN, sizeof TA616_DN, (unsigned char *)TA616_RSA_N, sizeof TA616_RSA_N, (unsigned char *)TA616_RSA_E, sizeof TA616_RSA_E); + trust_anchors[617] = make_rsa_trust_anchor((unsigned char *)TA617_DN, sizeof TA617_DN, (unsigned char *)TA617_RSA_N, sizeof TA617_RSA_N, (unsigned char *)TA617_RSA_E, sizeof TA617_RSA_E); + trust_anchors[618] = make_rsa_trust_anchor((unsigned char *)TA618_DN, sizeof TA618_DN, (unsigned char *)TA618_RSA_N, sizeof TA618_RSA_N, (unsigned char *)TA618_RSA_E, sizeof TA618_RSA_E); + trust_anchors[619] = make_rsa_trust_anchor((unsigned char *)TA619_DN, sizeof TA619_DN, (unsigned char *)TA619_RSA_N, sizeof TA619_RSA_N, (unsigned char *)TA619_RSA_E, sizeof TA619_RSA_E); + trust_anchors[620] = make_rsa_trust_anchor((unsigned char *)TA620_DN, sizeof TA620_DN, (unsigned char *)TA620_RSA_N, sizeof TA620_RSA_N, (unsigned char *)TA620_RSA_E, sizeof TA620_RSA_E); + trust_anchors[621] = make_ec_trust_anchor((unsigned char *)TA621_DN, sizeof TA621_DN, BR_EC_secp384r1, (unsigned char *)TA621_EC_Q, sizeof TA621_EC_Q); + trust_anchors[622] = make_rsa_trust_anchor((unsigned char *)TA622_DN, sizeof TA622_DN, (unsigned char *)TA622_RSA_N, sizeof TA622_RSA_N, (unsigned char *)TA622_RSA_E, sizeof TA622_RSA_E); + trust_anchors[623] = make_rsa_trust_anchor((unsigned char *)TA623_DN, sizeof TA623_DN, (unsigned char *)TA623_RSA_N, sizeof TA623_RSA_N, (unsigned char *)TA623_RSA_E, sizeof TA623_RSA_E); + trust_anchors[624] = make_ec_trust_anchor((unsigned char *)TA624_DN, sizeof TA624_DN, BR_EC_secp256r1, (unsigned char *)TA624_EC_Q, sizeof TA624_EC_Q); + trust_anchors[625] = make_rsa_trust_anchor((unsigned char *)TA625_DN, sizeof TA625_DN, (unsigned char *)TA625_RSA_N, sizeof TA625_RSA_N, (unsigned char *)TA625_RSA_E, sizeof TA625_RSA_E); + trust_anchors[626] = make_ec_trust_anchor((unsigned char *)TA626_DN, sizeof TA626_DN, BR_EC_secp384r1, (unsigned char *)TA626_EC_Q, sizeof TA626_EC_Q); + trust_anchors[627] = make_ec_trust_anchor((unsigned char *)TA627_DN, sizeof TA627_DN, BR_EC_secp384r1, (unsigned char *)TA627_EC_Q, sizeof TA627_EC_Q); + trust_anchors[628] = make_ec_trust_anchor((unsigned char *)TA628_DN, sizeof TA628_DN, BR_EC_secp384r1, (unsigned char *)TA628_EC_Q, sizeof TA628_EC_Q); + trust_anchors[629] = make_rsa_trust_anchor((unsigned char *)TA629_DN, sizeof TA629_DN, (unsigned char *)TA629_RSA_N, sizeof TA629_RSA_N, (unsigned char *)TA629_RSA_E, sizeof TA629_RSA_E); + trust_anchors[630] = make_rsa_trust_anchor((unsigned char *)TA630_DN, sizeof TA630_DN, (unsigned char *)TA630_RSA_N, sizeof TA630_RSA_N, (unsigned char *)TA630_RSA_E, sizeof TA630_RSA_E); + trust_anchors[631] = make_ec_trust_anchor((unsigned char *)TA631_DN, sizeof TA631_DN, BR_EC_secp384r1, (unsigned char *)TA631_EC_Q, sizeof TA631_EC_Q); + trust_anchors[632] = make_rsa_trust_anchor((unsigned char *)TA632_DN, sizeof TA632_DN, (unsigned char *)TA632_RSA_N, sizeof TA632_RSA_N, (unsigned char *)TA632_RSA_E, sizeof TA632_RSA_E); + trust_anchors[633] = make_ec_trust_anchor((unsigned char *)TA633_DN, sizeof TA633_DN, BR_EC_secp384r1, (unsigned char *)TA633_EC_Q, sizeof TA633_EC_Q); + trust_anchors[634] = make_rsa_trust_anchor((unsigned char *)TA634_DN, sizeof TA634_DN, (unsigned char *)TA634_RSA_N, sizeof TA634_RSA_N, (unsigned char *)TA634_RSA_E, sizeof TA634_RSA_E); + trust_anchors[635] = make_ec_trust_anchor((unsigned char *)TA635_DN, sizeof TA635_DN, BR_EC_secp384r1, (unsigned char *)TA635_EC_Q, sizeof TA635_EC_Q); + trust_anchors[636] = make_ec_trust_anchor((unsigned char *)TA636_DN, sizeof TA636_DN, BR_EC_secp384r1, (unsigned char *)TA636_EC_Q, sizeof TA636_EC_Q); + trust_anchors[637] = make_rsa_trust_anchor((unsigned char *)TA637_DN, sizeof TA637_DN, (unsigned char *)TA637_RSA_N, sizeof TA637_RSA_N, (unsigned char *)TA637_RSA_E, sizeof TA637_RSA_E); + trust_anchors[638] = make_rsa_trust_anchor((unsigned char *)TA638_DN, sizeof TA638_DN, (unsigned char *)TA638_RSA_N, sizeof TA638_RSA_N, (unsigned char *)TA638_RSA_E, sizeof TA638_RSA_E); + trust_anchors[639] = make_rsa_trust_anchor((unsigned char *)TA639_DN, sizeof TA639_DN, (unsigned char *)TA639_RSA_N, sizeof TA639_RSA_N, (unsigned char *)TA639_RSA_E, sizeof TA639_RSA_E); + trust_anchors[640] = make_ec_trust_anchor((unsigned char *)TA640_DN, sizeof TA640_DN, BR_EC_secp384r1, (unsigned char *)TA640_EC_Q, sizeof TA640_EC_Q); + trust_anchors[641] = make_rsa_trust_anchor((unsigned char *)TA641_DN, sizeof TA641_DN, (unsigned char *)TA641_RSA_N, sizeof TA641_RSA_N, (unsigned char *)TA641_RSA_E, sizeof TA641_RSA_E); + trust_anchors[642] = make_rsa_trust_anchor((unsigned char *)TA642_DN, sizeof TA642_DN, (unsigned char *)TA642_RSA_N, sizeof TA642_RSA_N, (unsigned char *)TA642_RSA_E, sizeof TA642_RSA_E); + trust_anchors[643] = make_rsa_trust_anchor((unsigned char *)TA643_DN, sizeof TA643_DN, (unsigned char *)TA643_RSA_N, sizeof TA643_RSA_N, (unsigned char *)TA643_RSA_E, sizeof TA643_RSA_E); + trust_anchors[644] = make_ec_trust_anchor((unsigned char *)TA644_DN, sizeof TA644_DN, BR_EC_secp256r1, (unsigned char *)TA644_EC_Q, sizeof TA644_EC_Q); + trust_anchors[645] = make_rsa_trust_anchor((unsigned char *)TA645_DN, sizeof TA645_DN, (unsigned char *)TA645_RSA_N, sizeof TA645_RSA_N, (unsigned char *)TA645_RSA_E, sizeof TA645_RSA_E); + trust_anchors[646] = make_rsa_trust_anchor((unsigned char *)TA646_DN, sizeof TA646_DN, (unsigned char *)TA646_RSA_N, sizeof TA646_RSA_N, (unsigned char *)TA646_RSA_E, sizeof TA646_RSA_E); + trust_anchors[647] = make_rsa_trust_anchor((unsigned char *)TA647_DN, sizeof TA647_DN, (unsigned char *)TA647_RSA_N, sizeof TA647_RSA_N, (unsigned char *)TA647_RSA_E, sizeof TA647_RSA_E); + trust_anchors[648] = make_ec_trust_anchor((unsigned char *)TA648_DN, sizeof TA648_DN, BR_EC_secp384r1, (unsigned char *)TA648_EC_Q, sizeof TA648_EC_Q); + trust_anchors[649] = make_rsa_trust_anchor((unsigned char *)TA649_DN, sizeof TA649_DN, (unsigned char *)TA649_RSA_N, sizeof TA649_RSA_N, (unsigned char *)TA649_RSA_E, sizeof TA649_RSA_E); + trust_anchors[650] = make_ec_trust_anchor((unsigned char *)TA650_DN, sizeof TA650_DN, BR_EC_secp384r1, (unsigned char *)TA650_EC_Q, sizeof TA650_EC_Q); + trust_anchors[651] = make_rsa_trust_anchor((unsigned char *)TA651_DN, sizeof TA651_DN, (unsigned char *)TA651_RSA_N, sizeof TA651_RSA_N, (unsigned char *)TA651_RSA_E, sizeof TA651_RSA_E); + trust_anchors[652] = make_rsa_trust_anchor((unsigned char *)TA652_DN, sizeof TA652_DN, (unsigned char *)TA652_RSA_N, sizeof TA652_RSA_N, (unsigned char *)TA652_RSA_E, sizeof TA652_RSA_E); + trust_anchors[653] = make_rsa_trust_anchor((unsigned char *)TA653_DN, sizeof TA653_DN, (unsigned char *)TA653_RSA_N, sizeof TA653_RSA_N, (unsigned char *)TA653_RSA_E, sizeof TA653_RSA_E); + trust_anchors[654] = make_rsa_trust_anchor((unsigned char *)TA654_DN, sizeof TA654_DN, (unsigned char *)TA654_RSA_N, sizeof TA654_RSA_N, (unsigned char *)TA654_RSA_E, sizeof TA654_RSA_E); + trust_anchors[655] = make_rsa_trust_anchor((unsigned char *)TA655_DN, sizeof TA655_DN, (unsigned char *)TA655_RSA_N, sizeof TA655_RSA_N, (unsigned char *)TA655_RSA_E, sizeof TA655_RSA_E); + trust_anchors[656] = make_rsa_trust_anchor((unsigned char *)TA656_DN, sizeof TA656_DN, (unsigned char *)TA656_RSA_N, sizeof TA656_RSA_N, (unsigned char *)TA656_RSA_E, sizeof TA656_RSA_E); + trust_anchors[657] = make_rsa_trust_anchor((unsigned char *)TA657_DN, sizeof TA657_DN, (unsigned char *)TA657_RSA_N, sizeof TA657_RSA_N, (unsigned char *)TA657_RSA_E, sizeof TA657_RSA_E); + trust_anchors[658] = make_ec_trust_anchor((unsigned char *)TA658_DN, sizeof TA658_DN, BR_EC_secp384r1, (unsigned char *)TA658_EC_Q, sizeof TA658_EC_Q); + trust_anchors[659] = make_rsa_trust_anchor((unsigned char *)TA659_DN, sizeof TA659_DN, (unsigned char *)TA659_RSA_N, sizeof TA659_RSA_N, (unsigned char *)TA659_RSA_E, sizeof TA659_RSA_E); + trust_anchors[660] = make_rsa_trust_anchor((unsigned char *)TA660_DN, sizeof TA660_DN, (unsigned char *)TA660_RSA_N, sizeof TA660_RSA_N, (unsigned char *)TA660_RSA_E, sizeof TA660_RSA_E); + trust_anchors[661] = make_rsa_trust_anchor((unsigned char *)TA661_DN, sizeof TA661_DN, (unsigned char *)TA661_RSA_N, sizeof TA661_RSA_N, (unsigned char *)TA661_RSA_E, sizeof TA661_RSA_E); + trust_anchors[662] = make_rsa_trust_anchor((unsigned char *)TA662_DN, sizeof TA662_DN, (unsigned char *)TA662_RSA_N, sizeof TA662_RSA_N, (unsigned char *)TA662_RSA_E, sizeof TA662_RSA_E); + trust_anchors[663] = make_rsa_trust_anchor((unsigned char *)TA663_DN, sizeof TA663_DN, (unsigned char *)TA663_RSA_N, sizeof TA663_RSA_N, (unsigned char *)TA663_RSA_E, sizeof TA663_RSA_E); + trust_anchors[664] = make_ec_trust_anchor((unsigned char *)TA664_DN, sizeof TA664_DN, BR_EC_secp384r1, (unsigned char *)TA664_EC_Q, sizeof TA664_EC_Q); + trust_anchors[665] = make_rsa_trust_anchor((unsigned char *)TA665_DN, sizeof TA665_DN, (unsigned char *)TA665_RSA_N, sizeof TA665_RSA_N, (unsigned char *)TA665_RSA_E, sizeof TA665_RSA_E); + trust_anchors[666] = make_rsa_trust_anchor((unsigned char *)TA666_DN, sizeof TA666_DN, (unsigned char *)TA666_RSA_N, sizeof TA666_RSA_N, (unsigned char *)TA666_RSA_E, sizeof TA666_RSA_E); + trust_anchors[667] = make_rsa_trust_anchor((unsigned char *)TA667_DN, sizeof TA667_DN, (unsigned char *)TA667_RSA_N, sizeof TA667_RSA_N, (unsigned char *)TA667_RSA_E, sizeof TA667_RSA_E); + trust_anchors[668] = make_ec_trust_anchor((unsigned char *)TA668_DN, sizeof TA668_DN, BR_EC_secp384r1, (unsigned char *)TA668_EC_Q, sizeof TA668_EC_Q); + trust_anchors[669] = make_rsa_trust_anchor((unsigned char *)TA669_DN, sizeof TA669_DN, (unsigned char *)TA669_RSA_N, sizeof TA669_RSA_N, (unsigned char *)TA669_RSA_E, sizeof TA669_RSA_E); + trust_anchors[670] = make_ec_trust_anchor((unsigned char *)TA670_DN, sizeof TA670_DN, BR_EC_secp256r1, (unsigned char *)TA670_EC_Q, sizeof TA670_EC_Q); + trust_anchors[671] = make_ec_trust_anchor((unsigned char *)TA671_DN, sizeof TA671_DN, BR_EC_secp384r1, (unsigned char *)TA671_EC_Q, sizeof TA671_EC_Q); + trust_anchors[672] = make_rsa_trust_anchor((unsigned char *)TA672_DN, sizeof TA672_DN, (unsigned char *)TA672_RSA_N, sizeof TA672_RSA_N, (unsigned char *)TA672_RSA_E, sizeof TA672_RSA_E); + trust_anchors[673] = make_rsa_trust_anchor((unsigned char *)TA673_DN, sizeof TA673_DN, (unsigned char *)TA673_RSA_N, sizeof TA673_RSA_N, (unsigned char *)TA673_RSA_E, sizeof TA673_RSA_E); + trust_anchors[674] = make_rsa_trust_anchor((unsigned char *)TA674_DN, sizeof TA674_DN, (unsigned char *)TA674_RSA_N, sizeof TA674_RSA_N, (unsigned char *)TA674_RSA_E, sizeof TA674_RSA_E); + trust_anchors[675] = make_ec_trust_anchor((unsigned char *)TA675_DN, sizeof TA675_DN, BR_EC_secp384r1, (unsigned char *)TA675_EC_Q, sizeof TA675_EC_Q); + trust_anchors[676] = make_rsa_trust_anchor((unsigned char *)TA676_DN, sizeof TA676_DN, (unsigned char *)TA676_RSA_N, sizeof TA676_RSA_N, (unsigned char *)TA676_RSA_E, sizeof TA676_RSA_E); + trust_anchors[677] = make_rsa_trust_anchor((unsigned char *)TA677_DN, sizeof TA677_DN, (unsigned char *)TA677_RSA_N, sizeof TA677_RSA_N, (unsigned char *)TA677_RSA_E, sizeof TA677_RSA_E); + trust_anchors[678] = make_rsa_trust_anchor((unsigned char *)TA678_DN, sizeof TA678_DN, (unsigned char *)TA678_RSA_N, sizeof TA678_RSA_N, (unsigned char *)TA678_RSA_E, sizeof TA678_RSA_E); + trust_anchors[679] = make_rsa_trust_anchor((unsigned char *)TA679_DN, sizeof TA679_DN, (unsigned char *)TA679_RSA_N, sizeof TA679_RSA_N, (unsigned char *)TA679_RSA_E, sizeof TA679_RSA_E); + trust_anchors[680] = make_rsa_trust_anchor((unsigned char *)TA680_DN, sizeof TA680_DN, (unsigned char *)TA680_RSA_N, sizeof TA680_RSA_N, (unsigned char *)TA680_RSA_E, sizeof TA680_RSA_E); + trust_anchors[681] = make_rsa_trust_anchor((unsigned char *)TA681_DN, sizeof TA681_DN, (unsigned char *)TA681_RSA_N, sizeof TA681_RSA_N, (unsigned char *)TA681_RSA_E, sizeof TA681_RSA_E); + trust_anchors[682] = make_ec_trust_anchor((unsigned char *)TA682_DN, sizeof TA682_DN, BR_EC_secp384r1, (unsigned char *)TA682_EC_Q, sizeof TA682_EC_Q); + trust_anchors[683] = make_ec_trust_anchor((unsigned char *)TA683_DN, sizeof TA683_DN, BR_EC_secp384r1, (unsigned char *)TA683_EC_Q, sizeof TA683_EC_Q); + trust_anchors[684] = make_ec_trust_anchor((unsigned char *)TA684_DN, sizeof TA684_DN, BR_EC_secp384r1, (unsigned char *)TA684_EC_Q, sizeof TA684_EC_Q); + trust_anchors[685] = make_rsa_trust_anchor((unsigned char *)TA685_DN, sizeof TA685_DN, (unsigned char *)TA685_RSA_N, sizeof TA685_RSA_N, (unsigned char *)TA685_RSA_E, sizeof TA685_RSA_E); + trust_anchors[686] = make_ec_trust_anchor((unsigned char *)TA686_DN, sizeof TA686_DN, BR_EC_secp384r1, (unsigned char *)TA686_EC_Q, sizeof TA686_EC_Q); + trust_anchors[687] = make_rsa_trust_anchor((unsigned char *)TA687_DN, sizeof TA687_DN, (unsigned char *)TA687_RSA_N, sizeof TA687_RSA_N, (unsigned char *)TA687_RSA_E, sizeof TA687_RSA_E); + trust_anchors[688] = make_rsa_trust_anchor((unsigned char *)TA688_DN, sizeof TA688_DN, (unsigned char *)TA688_RSA_N, sizeof TA688_RSA_N, (unsigned char *)TA688_RSA_E, sizeof TA688_RSA_E); + trust_anchors[689] = make_rsa_trust_anchor((unsigned char *)TA689_DN, sizeof TA689_DN, (unsigned char *)TA689_RSA_N, sizeof TA689_RSA_N, (unsigned char *)TA689_RSA_E, sizeof TA689_RSA_E); + trust_anchors[690] = make_rsa_trust_anchor((unsigned char *)TA690_DN, sizeof TA690_DN, (unsigned char *)TA690_RSA_N, sizeof TA690_RSA_N, (unsigned char *)TA690_RSA_E, sizeof TA690_RSA_E); + trust_anchors[691] = make_rsa_trust_anchor((unsigned char *)TA691_DN, sizeof TA691_DN, (unsigned char *)TA691_RSA_N, sizeof TA691_RSA_N, (unsigned char *)TA691_RSA_E, sizeof TA691_RSA_E); + trust_anchors[692] = make_rsa_trust_anchor((unsigned char *)TA692_DN, sizeof TA692_DN, (unsigned char *)TA692_RSA_N, sizeof TA692_RSA_N, (unsigned char *)TA692_RSA_E, sizeof TA692_RSA_E); + trust_anchors[693] = make_ec_trust_anchor((unsigned char *)TA693_DN, sizeof TA693_DN, BR_EC_secp384r1, (unsigned char *)TA693_EC_Q, sizeof TA693_EC_Q); + trust_anchors[694] = make_rsa_trust_anchor((unsigned char *)TA694_DN, sizeof TA694_DN, (unsigned char *)TA694_RSA_N, sizeof TA694_RSA_N, (unsigned char *)TA694_RSA_E, sizeof TA694_RSA_E); + trust_anchors[695] = make_rsa_trust_anchor((unsigned char *)TA695_DN, sizeof TA695_DN, (unsigned char *)TA695_RSA_N, sizeof TA695_RSA_N, (unsigned char *)TA695_RSA_E, sizeof TA695_RSA_E); + trust_anchors[696] = make_ec_trust_anchor((unsigned char *)TA696_DN, sizeof TA696_DN, BR_EC_secp384r1, (unsigned char *)TA696_EC_Q, sizeof TA696_EC_Q); + trust_anchors[697] = make_rsa_trust_anchor((unsigned char *)TA697_DN, sizeof TA697_DN, (unsigned char *)TA697_RSA_N, sizeof TA697_RSA_N, (unsigned char *)TA697_RSA_E, sizeof TA697_RSA_E); + trust_anchors[698] = make_rsa_trust_anchor((unsigned char *)TA698_DN, sizeof TA698_DN, (unsigned char *)TA698_RSA_N, sizeof TA698_RSA_N, (unsigned char *)TA698_RSA_E, sizeof TA698_RSA_E); + trust_anchors[699] = make_rsa_trust_anchor((unsigned char *)TA699_DN, sizeof TA699_DN, (unsigned char *)TA699_RSA_N, sizeof TA699_RSA_N, (unsigned char *)TA699_RSA_E, sizeof TA699_RSA_E); + trust_anchors[700] = make_rsa_trust_anchor((unsigned char *)TA700_DN, sizeof TA700_DN, (unsigned char *)TA700_RSA_N, sizeof TA700_RSA_N, (unsigned char *)TA700_RSA_E, sizeof TA700_RSA_E); + trust_anchors[701] = make_ec_trust_anchor((unsigned char *)TA701_DN, sizeof TA701_DN, BR_EC_secp384r1, (unsigned char *)TA701_EC_Q, sizeof TA701_EC_Q); + trust_anchors[702] = make_rsa_trust_anchor((unsigned char *)TA702_DN, sizeof TA702_DN, (unsigned char *)TA702_RSA_N, sizeof TA702_RSA_N, (unsigned char *)TA702_RSA_E, sizeof TA702_RSA_E); + trust_anchors[703] = make_rsa_trust_anchor((unsigned char *)TA703_DN, sizeof TA703_DN, (unsigned char *)TA703_RSA_N, sizeof TA703_RSA_N, (unsigned char *)TA703_RSA_E, sizeof TA703_RSA_E); + trust_anchors[704] = make_rsa_trust_anchor((unsigned char *)TA704_DN, sizeof TA704_DN, (unsigned char *)TA704_RSA_N, sizeof TA704_RSA_N, (unsigned char *)TA704_RSA_E, sizeof TA704_RSA_E); + trust_anchors[705] = make_rsa_trust_anchor((unsigned char *)TA705_DN, sizeof TA705_DN, (unsigned char *)TA705_RSA_N, sizeof TA705_RSA_N, (unsigned char *)TA705_RSA_E, sizeof TA705_RSA_E); + trust_anchors[706] = make_rsa_trust_anchor((unsigned char *)TA706_DN, sizeof TA706_DN, (unsigned char *)TA706_RSA_N, sizeof TA706_RSA_N, (unsigned char *)TA706_RSA_E, sizeof TA706_RSA_E); + trust_anchors[707] = make_ec_trust_anchor((unsigned char *)TA707_DN, sizeof TA707_DN, BR_EC_secp384r1, (unsigned char *)TA707_EC_Q, sizeof TA707_EC_Q); + trust_anchors[708] = make_rsa_trust_anchor((unsigned char *)TA708_DN, sizeof TA708_DN, (unsigned char *)TA708_RSA_N, sizeof TA708_RSA_N, (unsigned char *)TA708_RSA_E, sizeof TA708_RSA_E); + trust_anchors[709] = make_rsa_trust_anchor((unsigned char *)TA709_DN, sizeof TA709_DN, (unsigned char *)TA709_RSA_N, sizeof TA709_RSA_N, (unsigned char *)TA709_RSA_E, sizeof TA709_RSA_E); + trust_anchors[710] = make_rsa_trust_anchor((unsigned char *)TA710_DN, sizeof TA710_DN, (unsigned char *)TA710_RSA_N, sizeof TA710_RSA_N, (unsigned char *)TA710_RSA_E, sizeof TA710_RSA_E); + trust_anchors[711] = make_rsa_trust_anchor((unsigned char *)TA711_DN, sizeof TA711_DN, (unsigned char *)TA711_RSA_N, sizeof TA711_RSA_N, (unsigned char *)TA711_RSA_E, sizeof TA711_RSA_E); + trust_anchors[712] = make_ec_trust_anchor((unsigned char *)TA712_DN, sizeof TA712_DN, BR_EC_secp384r1, (unsigned char *)TA712_EC_Q, sizeof TA712_EC_Q); + trust_anchors[713] = make_rsa_trust_anchor((unsigned char *)TA713_DN, sizeof TA713_DN, (unsigned char *)TA713_RSA_N, sizeof TA713_RSA_N, (unsigned char *)TA713_RSA_E, sizeof TA713_RSA_E); + trust_anchors[714] = make_ec_trust_anchor((unsigned char *)TA714_DN, sizeof TA714_DN, BR_EC_secp384r1, (unsigned char *)TA714_EC_Q, sizeof TA714_EC_Q); + trust_anchors[715] = make_rsa_trust_anchor((unsigned char *)TA715_DN, sizeof TA715_DN, (unsigned char *)TA715_RSA_N, sizeof TA715_RSA_N, (unsigned char *)TA715_RSA_E, sizeof TA715_RSA_E); + trust_anchors[716] = make_ec_trust_anchor((unsigned char *)TA716_DN, sizeof TA716_DN, BR_EC_secp384r1, (unsigned char *)TA716_EC_Q, sizeof TA716_EC_Q); + trust_anchors[717] = make_rsa_trust_anchor((unsigned char *)TA717_DN, sizeof TA717_DN, (unsigned char *)TA717_RSA_N, sizeof TA717_RSA_N, (unsigned char *)TA717_RSA_E, sizeof TA717_RSA_E); + trust_anchors[718] = make_ec_trust_anchor((unsigned char *)TA718_DN, sizeof TA718_DN, BR_EC_secp384r1, (unsigned char *)TA718_EC_Q, sizeof TA718_EC_Q); + trust_anchors[719] = make_rsa_trust_anchor((unsigned char *)TA719_DN, sizeof TA719_DN, (unsigned char *)TA719_RSA_N, sizeof TA719_RSA_N, (unsigned char *)TA719_RSA_E, sizeof TA719_RSA_E); + trust_anchors[720] = make_ec_trust_anchor((unsigned char *)TA720_DN, sizeof TA720_DN, BR_EC_secp384r1, (unsigned char *)TA720_EC_Q, sizeof TA720_EC_Q); + trust_anchors[721] = make_rsa_trust_anchor((unsigned char *)TA721_DN, sizeof TA721_DN, (unsigned char *)TA721_RSA_N, sizeof TA721_RSA_N, (unsigned char *)TA721_RSA_E, sizeof TA721_RSA_E); + trust_anchors[722] = make_rsa_trust_anchor((unsigned char *)TA722_DN, sizeof TA722_DN, (unsigned char *)TA722_RSA_N, sizeof TA722_RSA_N, (unsigned char *)TA722_RSA_E, sizeof TA722_RSA_E); + trust_anchors[723] = make_rsa_trust_anchor((unsigned char *)TA723_DN, sizeof TA723_DN, (unsigned char *)TA723_RSA_N, sizeof TA723_RSA_N, (unsigned char *)TA723_RSA_E, sizeof TA723_RSA_E); + trust_anchors[724] = make_rsa_trust_anchor((unsigned char *)TA724_DN, sizeof TA724_DN, (unsigned char *)TA724_RSA_N, sizeof TA724_RSA_N, (unsigned char *)TA724_RSA_E, sizeof TA724_RSA_E); + trust_anchors[725] = make_rsa_trust_anchor((unsigned char *)TA725_DN, sizeof TA725_DN, (unsigned char *)TA725_RSA_N, sizeof TA725_RSA_N, (unsigned char *)TA725_RSA_E, sizeof TA725_RSA_E); + trust_anchors[726] = make_rsa_trust_anchor((unsigned char *)TA726_DN, sizeof TA726_DN, (unsigned char *)TA726_RSA_N, sizeof TA726_RSA_N, (unsigned char *)TA726_RSA_E, sizeof TA726_RSA_E); + trust_anchors[727] = make_ec_trust_anchor((unsigned char *)TA727_DN, sizeof TA727_DN, BR_EC_secp384r1, (unsigned char *)TA727_EC_Q, sizeof TA727_EC_Q); + trust_anchors[728] = make_rsa_trust_anchor((unsigned char *)TA728_DN, sizeof TA728_DN, (unsigned char *)TA728_RSA_N, sizeof TA728_RSA_N, (unsigned char *)TA728_RSA_E, sizeof TA728_RSA_E); + trust_anchors[729] = make_rsa_trust_anchor((unsigned char *)TA729_DN, sizeof TA729_DN, (unsigned char *)TA729_RSA_N, sizeof TA729_RSA_N, (unsigned char *)TA729_RSA_E, sizeof TA729_RSA_E); + trust_anchors[730] = make_rsa_trust_anchor((unsigned char *)TA730_DN, sizeof TA730_DN, (unsigned char *)TA730_RSA_N, sizeof TA730_RSA_N, (unsigned char *)TA730_RSA_E, sizeof TA730_RSA_E); + trust_anchors[731] = make_rsa_trust_anchor((unsigned char *)TA731_DN, sizeof TA731_DN, (unsigned char *)TA731_RSA_N, sizeof TA731_RSA_N, (unsigned char *)TA731_RSA_E, sizeof TA731_RSA_E); + trust_anchors[732] = make_ec_trust_anchor((unsigned char *)TA732_DN, sizeof TA732_DN, BR_EC_secp384r1, (unsigned char *)TA732_EC_Q, sizeof TA732_EC_Q); + trust_anchors[733] = make_rsa_trust_anchor((unsigned char *)TA733_DN, sizeof TA733_DN, (unsigned char *)TA733_RSA_N, sizeof TA733_RSA_N, (unsigned char *)TA733_RSA_E, sizeof TA733_RSA_E); + trust_anchors[734] = make_ec_trust_anchor((unsigned char *)TA734_DN, sizeof TA734_DN, BR_EC_secp256r1, (unsigned char *)TA734_EC_Q, sizeof TA734_EC_Q); + trust_anchors[735] = make_ec_trust_anchor((unsigned char *)TA735_DN, sizeof TA735_DN, BR_EC_secp384r1, (unsigned char *)TA735_EC_Q, sizeof TA735_EC_Q); + trust_anchors[736] = make_rsa_trust_anchor((unsigned char *)TA736_DN, sizeof TA736_DN, (unsigned char *)TA736_RSA_N, sizeof TA736_RSA_N, (unsigned char *)TA736_RSA_E, sizeof TA736_RSA_E); + trust_anchors[737] = make_rsa_trust_anchor((unsigned char *)TA737_DN, sizeof TA737_DN, (unsigned char *)TA737_RSA_N, sizeof TA737_RSA_N, (unsigned char *)TA737_RSA_E, sizeof TA737_RSA_E); + trust_anchors[738] = make_rsa_trust_anchor((unsigned char *)TA738_DN, sizeof TA738_DN, (unsigned char *)TA738_RSA_N, sizeof TA738_RSA_N, (unsigned char *)TA738_RSA_E, sizeof TA738_RSA_E); + trust_anchors[739] = make_rsa_trust_anchor((unsigned char *)TA739_DN, sizeof TA739_DN, (unsigned char *)TA739_RSA_N, sizeof TA739_RSA_N, (unsigned char *)TA739_RSA_E, sizeof TA739_RSA_E); + trust_anchors[740] = make_rsa_trust_anchor((unsigned char *)TA740_DN, sizeof TA740_DN, (unsigned char *)TA740_RSA_N, sizeof TA740_RSA_N, (unsigned char *)TA740_RSA_E, sizeof TA740_RSA_E); + trust_anchors[741] = make_rsa_trust_anchor((unsigned char *)TA741_DN, sizeof TA741_DN, (unsigned char *)TA741_RSA_N, sizeof TA741_RSA_N, (unsigned char *)TA741_RSA_E, sizeof TA741_RSA_E); + trust_anchors[742] = make_rsa_trust_anchor((unsigned char *)TA742_DN, sizeof TA742_DN, (unsigned char *)TA742_RSA_N, sizeof TA742_RSA_N, (unsigned char *)TA742_RSA_E, sizeof TA742_RSA_E); + trust_anchors[743] = make_rsa_trust_anchor((unsigned char *)TA743_DN, sizeof TA743_DN, (unsigned char *)TA743_RSA_N, sizeof TA743_RSA_N, (unsigned char *)TA743_RSA_E, sizeof TA743_RSA_E); + trust_anchors[744] = make_rsa_trust_anchor((unsigned char *)TA744_DN, sizeof TA744_DN, (unsigned char *)TA744_RSA_N, sizeof TA744_RSA_N, (unsigned char *)TA744_RSA_E, sizeof TA744_RSA_E); + trust_anchors[745] = make_ec_trust_anchor((unsigned char *)TA745_DN, sizeof TA745_DN, BR_EC_secp384r1, (unsigned char *)TA745_EC_Q, sizeof TA745_EC_Q); + trust_anchors[746] = make_rsa_trust_anchor((unsigned char *)TA746_DN, sizeof TA746_DN, (unsigned char *)TA746_RSA_N, sizeof TA746_RSA_N, (unsigned char *)TA746_RSA_E, sizeof TA746_RSA_E); + trust_anchors[747] = make_ec_trust_anchor((unsigned char *)TA747_DN, sizeof TA747_DN, BR_EC_secp384r1, (unsigned char *)TA747_EC_Q, sizeof TA747_EC_Q); + trust_anchors[748] = make_rsa_trust_anchor((unsigned char *)TA748_DN, sizeof TA748_DN, (unsigned char *)TA748_RSA_N, sizeof TA748_RSA_N, (unsigned char *)TA748_RSA_E, sizeof TA748_RSA_E); + trust_anchors[749] = make_rsa_trust_anchor((unsigned char *)TA749_DN, sizeof TA749_DN, (unsigned char *)TA749_RSA_N, sizeof TA749_RSA_N, (unsigned char *)TA749_RSA_E, sizeof TA749_RSA_E); +} + +void certificates::close_trust_anchors() +{ + if (trust_anchors == NULL) + { + return; + } + if (loaded_from_file) + { + ca_loader::free_trust_anchors(trust_anchors, (size_t)trust_anchor_count); + } + else + { + free(trust_anchors); + } + trust_anchors = NULL; + trust_anchor_count = 0; + loaded_from_file = 0; +} + +br_x509_trust_anchor* certificates::get_trust_anchors() +{ + return trust_anchors; +} + +int certificates::get_num_trust_anchors() +{ + return trust_anchor_count; +} + +int certificates::load_from_file(const char *path) +{ + br_x509_trust_anchor *file_anchors = NULL; + size_t file_count = 0; + + if (ca_loader::load_pem_file(path, &file_anchors, &file_count) != 0) + { + return -1; + } + + /* Release any existing trust anchors */ + close_trust_anchors(); + + trust_anchors = file_anchors; + trust_anchor_count = (int)file_count; + loaded_from_file = 1; + return 0; +} + +// Private + +br_x509_trust_anchor certificates::make_rsa_trust_anchor(unsigned char *dn, size_t dn_len, unsigned char *n, size_t n_len, unsigned char *e, size_t e_len) +{ + br_x509_trust_anchor ta; + ta.dn.data = dn; + ta.dn.len = dn_len; + ta.flags = BR_X509_TA_CA; + ta.pkey.key_type = BR_KEYTYPE_RSA; + ta.pkey.key.rsa.n = n; + ta.pkey.key.rsa.nlen = n_len; + ta.pkey.key.rsa.e = e; + ta.pkey.key.rsa.elen = e_len; + return ta; +} + +br_x509_trust_anchor certificates::make_ec_trust_anchor(unsigned char *dn, size_t dn_len, int curve, unsigned char *q, size_t q_len) +{ + br_x509_trust_anchor ta; + ta.dn.data = dn; + ta.dn.len = dn_len; + ta.flags = BR_X509_TA_CA; + ta.pkey.key_type = BR_KEYTYPE_EC; + ta.pkey.key.ec.curve = curve; + ta.pkey.key.ec.q = q; + ta.pkey.key.ec.qlen = q_len; + return ta; +} diff --git a/libcurl/lib/vtls/certificates.h b/libcurl/lib/vtls/certificates.h new file mode 100644 index 0000000..def3705 --- /dev/null +++ b/libcurl/lib/vtls/certificates.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +class certificates +{ +public: + static void initialize_trust_anchors(); + static void close_trust_anchors(); + static br_x509_trust_anchor* get_trust_anchors(); + static int get_num_trust_anchors(); + + /* + * Try to load trust anchors from a PEM CA bundle file. + * If successful, replaces the compiled-in trust store. + * Returns 0 on success, -1 on failure (compiled-in CAs unchanged). + */ + static int load_from_file(const char *path); + +private: + static br_x509_trust_anchor make_rsa_trust_anchor(unsigned char *dn, size_t dn_len, unsigned char *n, size_t n_len, unsigned char *e, size_t e_len); + static br_x509_trust_anchor make_ec_trust_anchor(unsigned char *dn, size_t dn_len, int curve, unsigned char *q, size_t q_len); +}; diff --git a/libcurl/lib/vtls/cyassl.c b/libcurl/lib/vtls/cyassl.c new file mode 100644 index 0000000..01bfdab --- /dev/null +++ b/libcurl/lib/vtls/cyassl.c @@ -0,0 +1,954 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "curl_setup.h" + +#ifdef USE_CYASSL + +#define WOLFSSL_OPTIONS_IGNORE_SYS +/* CyaSSL's version.h, which should contain only the version, should come +before all other CyaSSL includes and be immediately followed by build config +aka options.h. https://curl.haxx.se/mail/lib-2015-04/0069.html */ +#include +#if defined(HAVE_CYASSL_OPTIONS_H) && (LIBCYASSL_VERSION_HEX > 0x03004008) +#if defined(CYASSL_API) || defined(WOLFSSL_API) +/* Safety measure. If either is defined some API include was already included +and that's a problem since options.h hasn't been included yet. */ +#error "CyaSSL API was included before the CyaSSL build options." +#endif +#include +#endif + +/* To determine what functions are available we rely on one or both of: + - the user's options.h generated by CyaSSL/wolfSSL + - the symbols detected by curl's configure + Since they are markedly different from one another, and one or the other may + not be available, we do some checking below to bring things in sync. */ + +/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */ +#ifndef HAVE_ALPN +#ifdef HAVE_WOLFSSL_USEALPN +#define HAVE_ALPN +#endif +#endif + +/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in + options.h, but is only seen in >= 3.6.6 since that's when they started + disabling SSLv3 by default. */ +#ifndef WOLFSSL_ALLOW_SSLV3 +#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \ + defined(HAVE_WOLFSSLV3_CLIENT_METHOD) +#define WOLFSSL_ALLOW_SSLV3 +#endif +#endif + +/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC + supported curve extension in options.h. Note ECC is enabled separately. */ +#ifndef HAVE_SUPPORTED_CURVES +#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \ + defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE) +#define HAVE_SUPPORTED_CURVES +#endif +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "x509asn1.h" +#include "curl_printf.h" + +#include +#ifdef HAVE_CYASSL_ERROR_SSL_H +#include +#else +#include +#endif +#include +#include + +#include "cyassl.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#if LIBCYASSL_VERSION_HEX < 0x02007002 /* < 2.7.2 */ +#define CYASSL_MAX_ERROR_SZ 80 +#endif + +static Curl_recv cyassl_recv; +static Curl_send cyassl_send; + + +static int do_file_type(const char *type) +{ + if(!type || !type[0]) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "PEM")) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "DER")) + return SSL_FILETYPE_ASN1; + return -1; +} + +/* + * This function loads all the client/CA certificates and CRLs. Setup the TLS + * layer and do all necessary magic. + */ +static CURLcode +cyassl_connect_step1(struct connectdata *conn, + int sockindex) +{ + char error_buffer[CYASSL_MAX_ERROR_SZ]; + char *ciphers; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* conssl = &conn->ssl[sockindex]; + SSL_METHOD* req_method = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; +#ifdef HAVE_SNI + bool sni = FALSE; +#define use_sni(x) sni = (x) +#else +#define use_sni(x) Curl_nop_stmt +#endif + + if(conssl->state == ssl_connection_complete) + return CURLE_OK; + + if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { + failf(data, "CyaSSL does not support to set maximum SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* check to see if we've been told to use an explicit SSL/TLS version */ + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: +#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ + /* minimum protocol version is set later after the CTX object is created */ + req_method = SSLv23_client_method(); +#else + infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, " + "TLS 1.0 is used exclusively\n"); + req_method = TLSv1_client_method(); +#endif + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_0: + req_method = TLSv1_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_1: + req_method = TLSv1_1_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_2: + req_method = TLSv1_2_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "CyaSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv3: +#ifdef WOLFSSL_ALLOW_SSLV3 + req_method = SSLv3_client_method(); + use_sni(FALSE); +#else + failf(data, "CyaSSL does not support SSLv3"); + return CURLE_NOT_BUILT_IN; +#endif + break; + case CURL_SSLVERSION_SSLv2: + failf(data, "CyaSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(!req_method) { + failf(data, "SSL: couldn't create a method!"); + return CURLE_OUT_OF_MEMORY; + } + + if(conssl->ctx) + SSL_CTX_free(conssl->ctx); + conssl->ctx = SSL_CTX_new(req_method); + + if(!conssl->ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: +#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ + /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is whatever + minimum version of TLS was built in and at least TLS 1.0. For later library + versions that could change (eg TLS 1.0 built in but defaults to TLS 1.1) so + we have this short circuit evaluation to find the minimum supported TLS + version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion + because only the former will work before the user's CTX callback is called. + */ + if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) && + (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) && + (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) { + failf(data, "SSL: couldn't set the minimum protocol version"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + break; + } + + ciphers = SSL_CONN_CONFIG(cipher_list); + if(ciphers) { + if(!SSL_CTX_set_cipher_list(conssl->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s\n", ciphers); + } + +#ifndef NO_FILESYSTEM + /* load trusted cacert */ + if(SSL_CONN_CONFIG(CAfile)) { + if(1 != SSL_CTX_load_verify_locations(conssl->ctx, + SSL_CONN_CONFIG(CAfile), + SSL_CONN_CONFIG(CApath))) { + if(SSL_CONN_CONFIG(verifypeer)) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + SSL_CONN_CONFIG(CAfile)? + SSL_CONN_CONFIG(CAfile): "none", + SSL_CONN_CONFIG(CApath)? + SSL_CONN_CONFIG(CApath) : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate + verification is required. */ + infof(data, "error setting certificate verify locations," + " continuing anyway:\n"); + } + } + else { + /* Everything is fine. */ + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): + "none", + SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): + "none"); + } + + /* Load the client certificate, and private key */ + if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { + int file_type = do_file_type(SSL_SET_OPTION(cert_type)); + + if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert), + file_type) != 1) { + failf(data, "unable to use client certificate (no key or wrong pass" + " phrase?)"); + return CURLE_SSL_CONNECT_ERROR; + } + + file_type = do_file_type(SSL_SET_OPTION(key_type)); + if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key), + file_type) != 1) { + failf(data, "unable to set private key"); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* !NO_FILESYSTEM */ + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ + SSL_CTX_set_verify(conssl->ctx, + SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER: + SSL_VERIFY_NONE, + NULL); + +#ifdef HAVE_SNI + if(sni) { + struct in_addr addr4; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + size_t hostname_len = strlen(hostname); + if((hostname_len < USHRT_MAX) && + (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) && +#endif + (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname, + (unsigned short)hostname_len) != 1)) { + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + } + } +#endif + +#ifdef HAVE_SUPPORTED_CURVES + /* CyaSSL/wolfSSL does not send the supported ECC curves ext automatically: + https://github.com/wolfSSL/wolfssl/issues/366 + The supported curves below are those also supported by OpenSSL 1.0.2 and + in the same order. */ + CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x17); /* secp256r1 */ + CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x19); /* secp521r1 */ + CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x18); /* secp384r1 */ +#endif + + /* give application a chance to interfere with SSL set up. */ + if(data->set.ssl.fsslctx) { + CURLcode result = CURLE_OK; + result = (*data->set.ssl.fsslctx)(data, conssl->ctx, + data->set.ssl.fsslctxp); + if(result) { + failf(data, "error signaled by ssl ctx callback"); + return result; + } + } +#ifdef NO_FILESYSTEM + else if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built" + " with \"no filesystem\". Either disable peer verification" + " (insecure) or if you are building an application with libcurl you" + " can load certificates via CURLOPT_SSL_CTX_FUNCTION."); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + + /* Let's make an SSL structure */ + if(conssl->handle) + SSL_free(conssl->handle); + conssl->handle = SSL_new(conssl->ctx); + if(!conssl->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + +#ifdef HAVE_ALPN + if(conn->bits.tls_enable_alpn) { + char protocols[128]; + *protocols = '\0'; + + /* wolfSSL's ALPN protocol name list format is a comma separated string of + protocols in descending order of preference, eg: "h2,http/1.1" */ + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ","); + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + if(wolfSSL_UseALPN(conssl->handle, protocols, + (unsigned)strlen(protocols), + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { + failf(data, "SSL: failed setting ALPN protocols"); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* HAVE_ALPN */ + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(conssl->handle, ssl_sessionid)) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSL_set_session failed: %s", + ERR_error_string(SSL_get_error(conssl->handle, 0), + error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + /* pass the raw socket into the SSL layer */ + if(!SSL_set_fd(conssl->handle, (int)sockfd)) { + failf(data, "SSL: SSL_set_fd failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + conssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + + +static CURLcode +cyassl_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* conssl = &conn->ssl[sockindex]; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + conn->recv[sockindex] = cyassl_recv; + conn->send[sockindex] = cyassl_send; + + /* Enable RFC2818 checks */ + if(SSL_CONN_CONFIG(verifyhost)) { + ret = CyaSSL_check_domain_name(conssl->handle, hostname); + if(ret == SSL_FAILURE) + return CURLE_OUT_OF_MEMORY; + } + + ret = SSL_connect(conssl->handle); + if(ret != 1) { + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int detail = SSL_get_error(conssl->handle, ret); + + if(SSL_ERROR_WANT_READ == detail) { + conssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else if(SSL_ERROR_WANT_WRITE == detail) { + conssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } + /* There is no easy way to override only the CN matching. + * This will enable the override of both mismatching SubjectAltNames + * as also mismatching CN fields */ + else if(DOMAIN_NAME_MISMATCH == detail) { +#if 1 + failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", + dispname); + return CURLE_PEER_FAILED_VERIFICATION; +#else + /* When the CyaSSL_check_domain_name() is used and you desire to continue + * on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0', + * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only + * way to do this is currently to switch the CyaSSL_check_domain_name() + * in and out based on the 'conn->ssl_config.verifyhost' value. */ + if(SSL_CONN_CONFIG(verifyhost)) { + failf(data, + "\tsubject alt name(s) or common name do not match \"%s\"\n", + dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, + "\tsubject alt name(s) and/or common name do not match \"%s\"\n", + dispname); + return CURLE_OK; + } +#endif + } +#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ + else if(ASN_NO_SIGNER_E == detail) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "\tCA signer not available for verification\n"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate + verification is required. */ + infof(data, "CA signer not available for verification, " + "continuing anyway\n"); + } + } +#endif + else { + failf(data, "SSL_connect failed with error %d: %s", detail, + ERR_error_string(detail, error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + } + + if(pinnedpubkey) { +#ifdef KEEP_PEER_CERT + X509 *x509; + const char *x509_der; + int x509_der_len; + curl_X509certificate x509_parsed; + curl_asn1Element *pubkey; + CURLcode result; + + x509 = SSL_get_peer_certificate(conssl->handle); + if(!x509) { + failf(data, "SSL: failed retrieving server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + x509_der = (const char *)CyaSSL_X509_get_der(x509, &x509_der_len); + if(!x509_der) { + failf(data, "SSL: failed retrieving ASN.1 server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + memset(&x509_parsed, 0, sizeof x509_parsed); + if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + pubkey = &x509_parsed.subjectPublicKeyInfo; + if(!pubkey->header || pubkey->end <= pubkey->header) { + failf(data, "SSL: failed retrieving public key from server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + (const unsigned char *)pubkey->header, + (size_t)(pubkey->end - pubkey->header)); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } +#else + failf(data, "Library lacks pinning support built-in"); + return CURLE_NOT_BUILT_IN; +#endif + } + +#ifdef HAVE_ALPN + if(conn->bits.tls_enable_alpn) { + int rc; + char *protocol = NULL; + unsigned short protocol_len = 0; + + rc = wolfSSL_ALPN_GetProtocol(conssl->handle, &protocol, &protocol_len); + + if(rc == SSL_SUCCESS) { + infof(data, "ALPN, server accepted to use %.*s\n", protocol_len, + protocol); + + if(protocol_len == ALPN_HTTP_1_1_LENGTH && + !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) + conn->negnpn = CURL_HTTP_VERSION_1_1; +#ifdef USE_NGHTTP2 + else if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) + conn->negnpn = CURL_HTTP_VERSION_2; +#endif + else + infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len, + protocol); + } + else if(rc == SSL_ALPN_NOT_FOUND) + infof(data, "ALPN, server did not agree to a protocol\n"); + else { + failf(data, "ALPN, failure getting protocol, error %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* HAVE_ALPN */ + + conssl->connecting_state = ssl_connect_3; +#if (LIBCYASSL_VERSION_HEX >= 0x03009010) + infof(data, "SSL connection using %s / %s\n", + wolfSSL_get_version(conssl->handle), + wolfSSL_get_cipher_name(conssl->handle)); +#else + infof(data, "SSL connected\n"); +#endif + + return CURLE_OK; +} + + +static CURLcode +cyassl_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + SSL_SESSION *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = SSL_get_session(connssl->handle); + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, + 0 /* unknown size */, sockindex); + if(result) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "failed to store ssl session"); + return result; + } + } + Curl_ssl_sessionid_unlock(conn); + } + + connssl->connecting_state = ssl_connect_done; + + return result; +} + + +static ssize_t cyassl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen); + + if(rc < 0) { + int err = SSL_get_error(conn->ssl[sockindex].handle, rc); + + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_write() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, "SSL write: %s, errno %d", + ERR_error_string(err, error_buffer), + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + } + return rc; +} + +void Curl_cyassl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *conssl = &conn->ssl[sockindex]; + + if(conssl->handle) { + (void)SSL_shutdown(conssl->handle); + SSL_free(conssl->handle); + conssl->handle = NULL; + } + if(conssl->ctx) { + SSL_CTX_free(conssl->ctx); + conssl->ctx = NULL; + } +} + +static ssize_t cyassl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + char error_buffer[CYASSL_MAX_ERROR_SZ]; + int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + int nread = SSL_read(conn->ssl[num].handle, buf, buffsize); + + if(nread < 0) { + int err = SSL_get_error(conn->ssl[num].handle, nread); + + switch(err) { + case SSL_ERROR_ZERO_RETURN: /* no more data */ + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, "SSL read: %s, errno %d", + ERR_error_string(err, error_buffer), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + return nread; +} + + +void Curl_cyassl_session_free(void *ptr) +{ + (void)ptr; + /* CyaSSL reuses sessions on own, no free */ +} + + +size_t Curl_cyassl_version(char *buffer, size_t size) +{ +#if LIBCYASSL_VERSION_HEX >= 0x03006000 + return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); +#elif defined(WOLFSSL_VERSION) + return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); +#elif defined(CYASSL_VERSION) + return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION); +#else + return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8"); +#endif +} + + +int Curl_cyassl_init(void) +{ + return (CyaSSL_Init() == SSL_SUCCESS); +} + + +bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex) +{ + if(conn->ssl[connindex].handle) /* SSL is in use */ + return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE; + else + return FALSE; +} + + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->handle) { + SSL_free(connssl->handle); + connssl->handle = NULL; + } + return retval; +} + + +static CURLcode +cyassl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1==connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = cyassl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading== + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = cyassl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = cyassl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = cyassl_recv; + conn->send[sockindex] = cyassl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + + +CURLcode +Curl_cyassl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return cyassl_connect_common(conn, sockindex, TRUE, done); +} + + +CURLcode +Curl_cyassl_connect(struct connectdata *conn, + int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = cyassl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +CURLcode Curl_cyassl_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) +{ + RNG rng; + (void)data; + if(InitRng(&rng)) + return CURLE_FAILED_INIT; + if(length > UINT_MAX) + return CURLE_FAILED_INIT; + if(RNG_GenerateBlock(&rng, entropy, (unsigned)length)) + return CURLE_FAILED_INIT; + return CURLE_OK; +} + +void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) +{ + Sha256 SHA256pw; + (void)unused; + InitSha256(&SHA256pw); + Sha256Update(&SHA256pw, tmp, (word32)tmplen); + Sha256Final(&SHA256pw, sha256sum); +} + +#endif diff --git a/libcurl/lib/vtls/cyassl.h b/libcurl/lib/vtls/cyassl.h new file mode 100644 index 0000000..f47719e --- /dev/null +++ b/libcurl/lib/vtls/cyassl.h @@ -0,0 +1,92 @@ +#ifndef HEADER_CURL_CYASSL_H +#define HEADER_CURL_CYASSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_CYASSL + +/* KEEP_PEER_CERT is a product of the presence of build time symbol + OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is + in wolfSSL's settings.h, and the latter two are build time symbols in + options.h. */ +#ifndef KEEP_PEER_CERT +#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \ + defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \ + (defined(OPENSSL_EXTRA) && !defined(NO_CERTS)) +#define KEEP_PEER_CERT +#endif +#endif + +CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex); +bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex); +int Curl_cyassl_shutdown(struct connectdata* conn, int sockindex); + + /* close a SSL connection */ +void Curl_cyassl_close(struct connectdata *conn, int sockindex); + +void Curl_cyassl_session_free(void *ptr); +size_t Curl_cyassl_version(char *buffer, size_t size); +int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex); +int Curl_cyassl_init(void); +CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +CURLcode Curl_cyassl_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length); +void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t unused); + +/* Set the API backend definition to CyaSSL */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL + +/* this backend supports CURLOPT_SSL_CTX_* */ +#define have_curlssl_ssl_ctx 1 + +#ifdef KEEP_PEER_CERT +/* this backend supports CURLOPT_PINNEDPUBLICKEY */ +#define have_curlssl_pinnedpubkey 1 +#endif + +/* API setup for CyaSSL */ +#define curlssl_init Curl_cyassl_init +#define curlssl_cleanup() Curl_nop_stmt +#define curlssl_connect Curl_cyassl_connect +#define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking +#define curlssl_session_free(x) Curl_cyassl_session_free(x) +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_cyassl_close +#define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y) +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_cyassl_version +#define curlssl_check_cxn(x) ((void)x, -1) +#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y) +#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z) +#define curlssl_sha256sum(a,b,c,d) Curl_cyassl_sha256sum(a,b,c,d) + +#endif /* USE_CYASSL */ +#endif /* HEADER_CURL_CYASSL_H */ diff --git a/libcurl/lib/vtls/darwinssl.c b/libcurl/lib/vtls/darwinssl.c new file mode 100644 index 0000000..6f9c601 --- /dev/null +++ b/libcurl/lib/vtls/darwinssl.c @@ -0,0 +1,2858 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all iOS and Mac OS X SecureTransport-specific code for the + * TLS/SSL layer. No code but vtls.c should ever call or use these functions. + */ + +#include "curl_setup.h" + +#include "urldata.h" /* for the Curl_easy definition */ +#include "curl_base64.h" +#include "strtok.h" + +#ifdef USE_DARWINSSL + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtautological-pointer-compare" +#endif /* __clang__ */ + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include +#include +#include +#include + +/* The Security framework has changed greatly between iOS and different OS X + versions, and we will try to support as many of them as we can (back to + Leopard and iOS 5) by using macros and weak-linking. + + IMPORTANT: If TLS 1.1 and 1.2 support are important for you on OS X, then + you must build this project against the 10.8 SDK or later. */ +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 +#error "The darwinssl back-end requires Leopard or later." +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ + +#define CURL_BUILD_IOS 0 +#define CURL_BUILD_IOS_7 0 +#define CURL_BUILD_MAC 1 +/* This is the maximum API level we are allowed to use when building: */ +#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 +#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 +#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 +/* These macros mean "the following code is present to allow runtime backward + compatibility with at least this cat or earlier": + (You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET + environmental variable.) */ +#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050 +#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060 +#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 +#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 +#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090 + +#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE +#define CURL_BUILD_IOS 1 +#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +#define CURL_BUILD_MAC 0 +#define CURL_BUILD_MAC_10_5 0 +#define CURL_BUILD_MAC_10_6 0 +#define CURL_BUILD_MAC_10_7 0 +#define CURL_BUILD_MAC_10_8 0 +#define CURL_SUPPORT_MAC_10_5 0 +#define CURL_SUPPORT_MAC_10_6 0 +#define CURL_SUPPORT_MAC_10_7 0 +#define CURL_SUPPORT_MAC_10_8 0 +#define CURL_SUPPORT_MAC_10_9 0 + +#else +#error "The darwinssl back-end requires iOS or OS X." +#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ + +#if CURL_BUILD_MAC +#include +#endif /* CURL_BUILD_MAC */ + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "connect.h" +#include "select.h" +#include "vtls.h" +#include "darwinssl.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* From MacTypes.h (which we can't include because it isn't present in iOS: */ +#define ioErr -36 +#define paramErr -50 + +#ifdef DARWIN_SSL_PINNEDPUBKEY +/* both new and old APIs return rsa keys missing the spki header (not DER) */ +static const unsigned char rsa4096SpkiHeader[] = { + 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00}; + +static const unsigned char rsa2048SpkiHeader[] = { + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; +#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 +/* the *new* version doesn't return DER encoded ecdsa certs like the old... */ +static const unsigned char ecDsaSecp256r1SpkiHeader[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00}; + +static const unsigned char ecDsaSecp384r1SpkiHeader[] = { + 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, + 0x00, 0x22, 0x03, 0x62, 0x00}; +#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */ +#endif /* DARWIN_SSL_PINNEDPUBKEY */ + +/* The following two functions were ripped from Apple sample code, + * with some modifications: */ +static OSStatus SocketRead(SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesToGo = *dataLength; + size_t initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = connssl->ssl_sockfd; + OSStatus rtn = noErr; + size_t bytesRead; + ssize_t rrtn; + int theErr; + + *dataLength = 0; + + for(;;) { + bytesRead = 0; + rrtn = read(sock, currData, bytesToGo); + if(rrtn <= 0) { + /* this is guesswork... */ + theErr = errno; + if(rrtn == 0) { /* EOF = server hung up */ + /* the framework will turn this into errSSLClosedNoNotify */ + rtn = errSSLClosedGraceful; + } + else /* do the switch */ + switch(theErr) { + case ENOENT: + /* connection closed */ + rtn = errSSLClosedGraceful; + break; + case ECONNRESET: + rtn = errSSLClosedAbort; + break; + case EAGAIN: + rtn = errSSLWouldBlock; + connssl->ssl_direction = false; + break; + default: + rtn = ioErr; + break; + } + break; + } + else { + bytesRead = rrtn; + } + bytesToGo -= bytesRead; + currData += bytesRead; + + if(bytesToGo == 0) { + /* filled buffer with incoming data, done */ + break; + } + } + *dataLength = initLen - bytesToGo; + + return rtn; +} + +static OSStatus SocketWrite(SSLConnectionRef connection, + const void *data, + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesSent = 0; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = connssl->ssl_sockfd; + ssize_t length; + size_t dataLen = *dataLength; + const UInt8 *dataPtr = (UInt8 *)data; + OSStatus ortn; + int theErr; + + *dataLength = 0; + + do { + length = write(sock, + (char *)dataPtr + bytesSent, + dataLen - bytesSent); + } while((length > 0) && + ( (bytesSent += length) < dataLen) ); + + if(length <= 0) { + theErr = errno; + if(theErr == EAGAIN) { + ortn = errSSLWouldBlock; + connssl->ssl_direction = true; + } + else { + ortn = ioErr; + } + } + else { + ortn = noErr; + } + *dataLength = bytesSent; + return ortn; +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { + /* SSL version 3.0 */ + case SSL_RSA_WITH_NULL_MD5: + return "SSL_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "SSL_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "SSL_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "SSL_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_SHA: + return "SSL_RSA_WITH_IDEA_CBC_SHA"; + break; + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_RSA_WITH_DES_CBC_SHA: + return "SSL_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_DES_CBC_SHA: + return "SSL_DH_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_DES_CBC_SHA: + return "SSL_DH_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "SSL_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_anon_WITH_DES_CBC_SHA: + return "SSL_DH_anon_WITH_DES_CBC_SHA"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; + break; + /* TLS 1.0 with AES (RFC 3268) + (Apparently these are used in SSLv3 implementations as well.) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; + /* SSL version 2.0 */ + case SSL_RSA_WITH_RC2_CBC_MD5: + return "SSL_RSA_WITH_RC2_CBC_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_MD5: + return "SSL_RSA_WITH_IDEA_CBC_MD5"; + break; + case SSL_RSA_WITH_DES_CBC_MD5: + return "SSL_RSA_WITH_DES_CBC_MD5"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_MD5: + return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; + break; + } + return "SSL_NULL_WITH_NULL_NULL"; +} + +CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { + /* TLS 1.0 with AES (RFC 3268) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* TLS 1.0 with ECDSA (RFC 4492) */ + case TLS_ECDH_ECDSA_WITH_NULL_SHA: + return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_NULL_SHA: + return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_NULL_SHA: + return "TLS_ECDH_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_NULL_SHA: + return "TLS_ECDHE_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_NULL_SHA: + return "TLS_ECDH_anon_WITH_NULL_SHA"; + break; + case TLS_ECDH_anon_WITH_RC4_128_SHA: + return "TLS_ECDH_anon_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* TLS 1.2 (RFC 5246) */ + case TLS_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case TLS_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case TLS_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case TLS_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_WITH_NULL_SHA256: + return "TLS_RSA_WITH_NULL_SHA256"; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; + break; + /* TLS 1.2 with AES GCM (RFC 5288) */ + case TLS_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_anon_WITH_AES_128_GCM_SHA256: + return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: + return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; + break; + /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: + return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; + break; +#else + case SSL_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* TLS PSK (RFC 4279): */ + case TLS_PSK_WITH_RC4_128_SHA: + return "TLS_PSK_WITH_RC4_128_SHA"; + break; + case TLS_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA: + return "TLS_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA: + return "TLS_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_RC4_128_SHA: + return "TLS_DHE_PSK_WITH_RC4_128_SHA"; + break; + case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_RC4_128_SHA: + return "TLS_RSA_PSK_WITH_RC4_128_SHA"; + break; + case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; + break; + /* More TLS PSK (RFC 4785): */ + case TLS_PSK_WITH_NULL_SHA: + return "TLS_PSK_WITH_NULL_SHA"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA: + return "TLS_DHE_PSK_WITH_NULL_SHA"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA: + return "TLS_RSA_PSK_WITH_NULL_SHA"; + break; + /* Even more TLS PSK (RFC 5487): */ + case TLS_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_PSK_WITH_NULL_SHA256: + return "TLS_PSK_WITH_NULL_SHA256"; + break; + case TLS_PSK_WITH_NULL_SHA384: + return "TLS_PSK_WITH_NULL_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA256: + return "TLS_DHE_PSK_WITH_NULL_SHA256"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA256: + return "TLS_RSA_PSK_WITH_NULL_SHA256"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + } + return "TLS_NULL_WITH_NULL_NULL"; +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +#if CURL_BUILD_MAC +CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) +{ + int mib[2]; + char *os_version; + size_t os_version_len; + char *os_version_major, *os_version_minor; + char *tok_buf; + + /* Get the Darwin kernel version from the kernel using sysctl(): */ + mib[0] = CTL_KERN; + mib[1] = KERN_OSRELEASE; + if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1) + return; + os_version = malloc(os_version_len*sizeof(char)); + if(!os_version) + return; + if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) { + free(os_version); + return; + } + + /* Parse the version: */ + os_version_major = strtok_r(os_version, ".", &tok_buf); + os_version_minor = strtok_r(NULL, ".", &tok_buf); + *major = atoi(os_version_major); + *minor = atoi(os_version_minor); + free(os_version); +} +#endif /* CURL_BUILD_MAC */ + +/* Apple provides a myriad of ways of getting information about a certificate + into a string. Some aren't available under iOS or newer cats. So here's + a unified function for getting a string describing the certificate that + ought to work in all cats starting with Leopard. */ +CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert) +{ + CFStringRef server_cert_summary = CFSTR("(null)"); + +#if CURL_BUILD_IOS + /* iOS: There's only one way to do this. */ + server_cert_summary = SecCertificateCopySubjectSummary(cert); +#else +#if CURL_BUILD_MAC_10_7 + /* Lion & later: Get the long description if we can. */ + if(SecCertificateCopyLongDescription != NULL) + server_cert_summary = + SecCertificateCopyLongDescription(NULL, cert, NULL); + else +#endif /* CURL_BUILD_MAC_10_7 */ +#if CURL_BUILD_MAC_10_6 + /* Snow Leopard: Get the certificate summary. */ + if(SecCertificateCopySubjectSummary != NULL) + server_cert_summary = SecCertificateCopySubjectSummary(cert); + else +#endif /* CURL_BUILD_MAC_10_6 */ + /* Leopard is as far back as we go... */ + (void)SecCertificateCopyCommonName(cert, &server_cert_summary); +#endif /* CURL_BUILD_IOS */ + return server_cert_summary; +} + +#if CURL_SUPPORT_MAC_10_6 +/* The SecKeychainSearch API was deprecated in Lion, and using it will raise + deprecation warnings, so let's not compile this unless it's necessary: */ +static OSStatus CopyIdentityWithLabelOldSchool(char *label, + SecIdentityRef *out_c_a_k) +{ + OSStatus status = errSecItemNotFound; + SecKeychainAttributeList attr_list; + SecKeychainAttribute attr; + SecKeychainSearchRef search = NULL; + SecCertificateRef cert = NULL; + + /* Set up the attribute list: */ + attr_list.count = 1L; + attr_list.attr = &attr; + + /* Set up our lone search criterion: */ + attr.tag = kSecLabelItemAttr; + attr.data = label; + attr.length = (UInt32)strlen(label); + + /* Start searching: */ + status = SecKeychainSearchCreateFromAttributes(NULL, + kSecCertificateItemClass, + &attr_list, + &search); + if(status == noErr) { + status = SecKeychainSearchCopyNext(search, + (SecKeychainItemRef *)&cert); + if(status == noErr && cert) { + /* If we found a certificate, does it have a private key? */ + status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k); + CFRelease(cert); + } + } + + if(search) + CFRelease(search); + return status; +} +#endif /* CURL_SUPPORT_MAC_10_6 */ + +static OSStatus CopyIdentityWithLabel(char *label, + SecIdentityRef *out_cert_and_key) +{ + OSStatus status = errSecItemNotFound; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS + CFArrayRef keys_list; + CFIndex keys_list_count; + CFIndex i; + CFStringRef common_name; + + /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. + kSecClassIdentity was introduced in Lion. If both exist, let's use them + to find the certificate. */ + if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { + CFTypeRef keys[5]; + CFTypeRef values[5]; + CFDictionaryRef query_dict; + CFStringRef label_cf = CFStringCreateWithCString(NULL, label, + kCFStringEncodingUTF8); + + /* Set up our search criteria and expected results: */ + values[0] = kSecClassIdentity; /* we want a certificate and a key */ + keys[0] = kSecClass; + values[1] = kCFBooleanTrue; /* we want a reference */ + keys[1] = kSecReturnRef; + values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the + * label matching below worked correctly */ + keys[2] = kSecMatchLimit; + /* identity searches need a SecPolicyRef in order to work */ + values[3] = SecPolicyCreateSSL(false, NULL); + keys[3] = kSecMatchPolicy; + /* match the name of the certificate (doesn't work in macOS 10.12.1) */ + values[4] = label_cf; + keys[4] = kSecAttrLabel; + query_dict = CFDictionaryCreate(NULL, (const void **)keys, + (const void **)values, 5L, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease(values[3]); + + /* Do we have a match? */ + status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list); + + /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity, + * we need to find the correct identity ourselves */ + if(status == noErr) { + keys_list_count = CFArrayGetCount(keys_list); + *out_cert_and_key = NULL; + status = 1; + for(i=0; idata; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + ssl_version_max = ssl_version << 16; + break; + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + SSLProtocol darwin_ver_min = kTLSProtocol1; + SSLProtocol darwin_ver_max = kTLSProtocol1; + CURLcode result = darwinssl_version_from_curl(&darwin_ver_min, + ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = darwinssl_version_from_curl(&darwin_ver_max, + ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max); + return result; + } + else { +#if CURL_SUPPORT_MAC_10_8 + long i = ssl_version; + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocolAll, + false); + for(; i <= (ssl_version_max >> 16); i++) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol11, + true); + break; + case CURL_SSLVERSION_TLSv1_2: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "DarwinSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + failf(data, "DarwinSSL: cannot set SSL protocol"); + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode darwinssl_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif /* ENABLE_IPV6 */ + size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; + SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + OSStatus err = noErr; +#if CURL_BUILD_MAC + int darwinver_maj = 0, darwinver_min = 0; + + GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); +#endif /* CURL_BUILD_MAC */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) { /* use the newer API if avaialble */ + if(connssl->ssl_ctx) + CFRelease(connssl->ssl_ctx); + connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); + if(!connssl->ssl_ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + } + else { + /* The old ST API does not exist under iOS, so don't compile it: */ +#if CURL_SUPPORT_MAC_10_8 + if(connssl->ssl_ctx) + (void)SSLDisposeContext(connssl->ssl_ctx); + err = SSLNewContext(false, &(connssl->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(connssl->ssl_ctx) + (void)SSLDisposeContext(connssl->ssl_ctx); + err = SSLNewContext(false, &(connssl->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */ + + /* check to see if we've been told to use an explicit SSL/TLS version */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocolAll, + false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol11, + true); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) { + failf(data, "Your version of the OS does not support to set maximum" + " SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + failf(data, "Your version of the OS does not support TLSv1.1"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_2: + failf(data, "Your version of the OS does not support TLSv1.2"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + + if(SSL_SET_OPTION(key)) { + infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " + "Transport. The private key must be in the Keychain.\n"); + } + + if(ssl_cert) { + SecIdentityRef cert_and_key = NULL; + bool is_cert_file = is_file(ssl_cert); + + /* User wants to authenticate with a client cert. Look for it: + If we detect that this is a file on disk, then let's load it. + Otherwise, assume that the user wants to use an identity loaded + from the Keychain. */ + if(is_cert_file) { + if(!SSL_SET_OPTION(cert_type)) + infof(data, "WARNING: SSL: Certificate type not set, assuming " + "PKCS#12 format.\n"); + else if(strncmp(SSL_SET_OPTION(cert_type), "P12", + strlen(SSL_SET_OPTION(cert_type))) != 0) + infof(data, "WARNING: SSL: The Security framework only supports " + "loading identities that are in PKCS#12 format.\n"); + + err = CopyIdentityFromPKCS12File(ssl_cert, + SSL_SET_OPTION(key_passwd), &cert_and_key); + } + else + err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); + + if(err == noErr && cert_and_key) { + SecCertificateRef cert = NULL; + CFTypeRef certs_c[1]; + CFArrayRef certs; + + /* If we found one, print it out: */ + err = SecIdentityCopyCertificate(cert_and_key, &cert); + if(err == noErr) { + CFStringRef cert_summary = CopyCertSubject(cert); + char cert_summary_c[128]; + + if(cert_summary) { + memset(cert_summary_c, 0, 128); + if(CFStringGetCString(cert_summary, + cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Client certificate: %s\n", cert_summary_c); + } + CFRelease(cert_summary); + CFRelease(cert); + } + } + certs_c[0] = cert_and_key; + certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, + &kCFTypeArrayCallBacks); + err = SSLSetCertificate(connssl->ssl_ctx, certs); + if(certs) + CFRelease(certs); + if(err != noErr) { + failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err); + return CURLE_SSL_CERTPROBLEM; + } + CFRelease(cert_and_key); + } + else { + switch(err) { + case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ + failf(data, "SSL: Incorrect password for the certificate \"%s\" " + "and its private key.", ssl_cert); + break; + case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ + failf(data, "SSL: Couldn't make sense of the data in the " + "certificate \"%s\" and its private key.", + ssl_cert); + break; + case -25260: /* errSecPassphraseRequired */ + failf(data, "SSL The certificate \"%s\" requires a password.", + ssl_cert); + break; + case errSecItemNotFound: + failf(data, "SSL: Can't find the certificate \"%s\" and its private " + "key in the Keychain.", ssl_cert); + break; + default: + failf(data, "SSL: Can't load the certificate \"%s\" and its private " + "key: OSStatus %d", ssl_cert, err); + break; + } + return CURLE_SSL_CERTPROBLEM; + } + } + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* Snow Leopard introduced the SSLSetSessionOption() function, but due to + a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag + works, it doesn't work as expected under Snow Leopard, Lion or + Mountain Lion. + So we need to call SSLSetEnableCertVerify() on those older cats in order + to disable certificate validation if the user turned that off. + (SecureTransport will always validate the certificate chain by + default.) + Note: + Darwin 11.x.x is Lion (10.7) + Darwin 12.x.x is Mountain Lion (10.8) + Darwin 13.x.x is Mavericks (10.9) + Darwin 14.x.x is Yosemite (10.10) + Darwin 15.x.x is El Capitan (10.11) + */ +#if CURL_BUILD_MAC + if(SSLSetSessionOption != NULL && darwinver_maj >= 13) { +#else + if(SSLSetSessionOption != NULL) { +#endif /* CURL_BUILD_MAC */ + bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; + err = SSLSetSessionOption(connssl->ssl_ctx, + kSSLSessionOptionBreakOnServerAuth, + break_on_auth); + if(err != noErr) { + failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLSetEnableCertVerify(connssl->ssl_ctx, + conn->ssl_config.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + err = SSLSetEnableCertVerify(connssl->ssl_ctx, + conn->ssl_config.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ + + if(ssl_cafile && verifypeer) { + bool is_cert_file = is_file(ssl_cafile); + + if(!is_cert_file) { + failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Configure hostname check. SNI is used if available. + * Both hostname check and SNI require SSLSetPeerDomainName(). + * Also: the verifyhost setting influences SNI usage */ + if(conn->ssl_config.verifyhost) { + err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname, + strlen(hostname)); + + if(err != noErr) { + infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", + err); + } + + if((Curl_inet_pton(AF_INET, hostname, &addr)) + #ifdef ENABLE_IPV6 + || (Curl_inet_pton(AF_INET6, hostname, &addr)) + #endif + ) { + infof(data, "WARNING: using IP address, SNI is being disabled by " + "the OS.\n"); + } + } + else { + infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); + } + + /* Disable cipher suites that ST supports but are not safe. These ciphers + are unlikely to be used in any case since ST gives other ciphers a much + higher priority, but it's probably better that we not connect at all than + to give the user a false sense of security if the server only supports + insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ + (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count); + all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(all_ciphers && allowed_ciphers && + SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers, + &all_ciphers_count) == noErr) { + for(i = 0UL ; i < all_ciphers_count ; i++) { +#if CURL_BUILD_MAC + /* There's a known bug in early versions of Mountain Lion where ST's ECC + ciphers (cipher suite 0xC001 through 0xC032) simply do not work. + Work around the problem here by disabling those ciphers if we are + running in an affected version of OS X. */ + if(darwinver_maj == 12 && darwinver_min <= 3 && + all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { + continue; + } +#endif /* CURL_BUILD_MAC */ + switch(all_ciphers[i]) { + /* Disable NULL ciphersuites: */ + case SSL_NULL_WITH_NULL_NULL: + case SSL_RSA_WITH_NULL_MD5: + case SSL_RSA_WITH_NULL_SHA: + case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ + case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ + case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ + case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ + case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ + case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ + case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ + case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ + case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ + case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ + case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ + case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ + case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ + /* Disable anonymous ciphersuites: */ + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + case SSL_DH_anon_WITH_RC4_128_MD5: + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_anon_WITH_DES_CBC_SHA: + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ + case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ + case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ + case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ + case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ + case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ + case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ + case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ + case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ + /* Disable weak key ciphersuites: */ + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_RSA_WITH_DES_CBC_SHA: + case SSL_DH_DSS_WITH_DES_CBC_SHA: + case SSL_DH_RSA_WITH_DES_CBC_SHA: + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + /* Disable IDEA: */ + case SSL_RSA_WITH_IDEA_CBC_SHA: + case SSL_RSA_WITH_IDEA_CBC_MD5: + /* Disable RC4: */ + case SSL_RSA_WITH_RC4_128_MD5: + case SSL_RSA_WITH_RC4_128_SHA: + case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ + case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/ + case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ + case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ + case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */ + case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */ + case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */ + break; + default: /* enable everything else */ + allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; + break; + } + } + err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers, + allowed_ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + failf(data, "SSL: Failed to allocate memory for allowed ciphers"); + return CURLE_OUT_OF_MEMORY; + } + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* We want to enable 1/n-1 when using a CBC cipher unless the user + specifically doesn't want us doing that: */ + if(SSLSetSessionOption != NULL) { + /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */ + SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord, + !data->set.ssl.enable_beast); + SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart, + data->set.ssl.falsestart); /* false start support */ + } +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + char *ssl_sessionid; + size_t ssl_sessionid_len; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, + &ssl_sessionid_len, sockindex)) { + /* we got a session id, use it! */ + err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + Curl_ssl_sessionid_unlock(conn); + if(err != noErr) { + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + /* If there isn't one, then let's make one up! This has to be done prior + to starting the handshake. */ + else { + CURLcode result; + ssl_sessionid = + aprintf("%s:%d:%d:%s:%hu", ssl_cafile, + verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); + ssl_sessionid_len = strlen(ssl_sessionid); + + err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + if(err != noErr) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, + sockindex); + Curl_ssl_sessionid_unlock(conn); + if(result) { + failf(data, "failed to store ssl session"); + return result; + } + } + } + + err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite); + if(err != noErr) { + failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + /* pass the raw socket into the SSL layers */ + /* We need to store the FD in a constant memory address, because + * SSLSetConnection() will not copy that address. I've found that + * conn->sock[sockindex] may change on its own. */ + connssl->ssl_sockfd = sockfd; + err = SSLSetConnection(connssl->ssl_ctx, connssl); + if(err != noErr) { + failf(data, "SSL: SSLSetConnection() failed: %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) +{ + char *sep_start, *sep_end, *cert_start, *cert_end; + size_t i, j, err; + size_t len; + unsigned char *b64; + + /* Jump through the separators at the beginning of the certificate. */ + sep_start = strstr(in, "-----"); + if(sep_start == NULL) + return 0; + cert_start = strstr(sep_start + 1, "-----"); + if(cert_start == NULL) + return -1; + + cert_start += 5; + + /* Find separator after the end of the certificate. */ + cert_end = strstr(cert_start, "-----"); + if(cert_end == NULL) + return -1; + + sep_end = strstr(cert_end + 1, "-----"); + if(sep_end == NULL) + return -1; + sep_end += 5; + + len = cert_end - cert_start; + b64 = malloc(len + 1); + if(!b64) + return -1; + + /* Create base64 string without linefeeds. */ + for(i = 0, j = 0; i < len; i++) { + if(cert_start[i] != '\r' && cert_start[i] != '\n') + b64[j++] = cert_start[i]; + } + b64[j] = '\0'; + + err = Curl_base64_decode((const char *)b64, out, outlen); + free(b64); + if(err) { + free(*out); + return -1; + } + + return sep_end - in; +} + +static int read_cert(const char *file, unsigned char **out, size_t *outlen) +{ + int fd; + ssize_t n, len = 0, cap = 512; + unsigned char buf[cap], *data; + + fd = open(file, 0); + if(fd < 0) + return -1; + + data = malloc(cap); + if(!data) { + close(fd); + return -1; + } + + for(;;) { + n = read(fd, buf, sizeof(buf)); + if(n < 0) { + close(fd); + free(data); + return -1; + } + else if(n == 0) { + close(fd); + break; + } + + if(len + n >= cap) { + cap *= 2; + data = realloc(data, cap); + if(!data) { + close(fd); + return -1; + } + } + + memcpy(data + len, buf, n); + len += n; + } + data[len] = '\0'; + + *out = data; + *outlen = len; + + return 0; +} + +static int sslerr_to_curlerr(struct Curl_easy *data, int err) +{ + switch(err) { + case errSSLXCertChainInvalid: + failf(data, "SSL certificate problem: Invalid certificate chain"); + return CURLE_SSL_CACERT; + case errSSLUnknownRootCert: + failf(data, "SSL certificate problem: Untrusted root certificate"); + return CURLE_SSL_CACERT; + case errSSLNoRootCert: + failf(data, "SSL certificate problem: No root certificate"); + return CURLE_SSL_CACERT; + case errSSLCertExpired: + failf(data, "SSL certificate problem: Certificate chain had an " + "expired certificate"); + return CURLE_SSL_CACERT; + case errSSLBadCert: + failf(data, "SSL certificate problem: Couldn't understand the server " + "certificate format"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLHostNameMismatch: + failf(data, "SSL certificate peer hostname mismatch"); + return CURLE_PEER_FAILED_VERIFICATION; + default: + failf(data, "SSL unexpected certificate error %d", err); + return CURLE_SSL_CACERT; + } +} + +static int append_cert_to_array(struct Curl_easy *data, + unsigned char *buf, size_t buflen, + CFMutableArrayRef array) +{ + CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); + if(!certdata) { + failf(data, "SSL: failed to allocate array for CA certificate"); + return CURLE_OUT_OF_MEMORY; + } + + SecCertificateRef cacert = + SecCertificateCreateWithData(kCFAllocatorDefault, certdata); + CFRelease(certdata); + if(!cacert) { + failf(data, "SSL: failed to create SecCertificate from CA certificate"); + return CURLE_SSL_CACERT; + } + + /* Check if cacert is valid. */ + CFStringRef subject = CopyCertSubject(cacert); + if(subject) { + char subject_cbuf[128]; + memset(subject_cbuf, 0, 128); + if(!CFStringGetCString(subject, + subject_cbuf, + 128, + kCFStringEncodingUTF8)) { + CFRelease(cacert); + failf(data, "SSL: invalid CA certificate subject"); + return CURLE_SSL_CACERT; + } + CFRelease(subject); + } + else { + CFRelease(cacert); + failf(data, "SSL: invalid CA certificate"); + return CURLE_SSL_CACERT; + } + + CFArrayAppendValue(array, cacert); + CFRelease(cacert); + + return CURLE_OK; +} + +static int verify_cert(const char *cafile, struct Curl_easy *data, + SSLContextRef ctx) +{ + int n = 0, rc; + long res; + unsigned char *certbuf, *der; + size_t buflen, derlen, offset = 0; + + if(read_cert(cafile, &certbuf, &buflen) < 0) { + failf(data, "SSL: failed to read or invalid CA certificate"); + return CURLE_SSL_CACERT; + } + + /* + * Certbuf now contains the contents of the certificate file, which can be + * - a single DER certificate, + * - a single PEM certificate or + * - a bunch of PEM certificates (certificate bundle). + * + * Go through certbuf, and convert any PEM certificate in it into DER + * format. + */ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + if(array == NULL) { + free(certbuf); + failf(data, "SSL: out of memory creating CA certificate array"); + return CURLE_OUT_OF_MEMORY; + } + + while(offset < buflen) { + n++; + + /* + * Check if the certificate is in PEM format, and convert it to DER. If + * this fails, we assume the certificate is in DER format. + */ + res = pem_to_der((const char *)certbuf + offset, &der, &derlen); + if(res < 0) { + free(certbuf); + CFRelease(array); + failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle", + n, offset); + return CURLE_SSL_CACERT; + } + offset += res; + + if(res == 0 && offset == 0) { + /* This is not a PEM file, probably a certificate in DER format. */ + rc = append_cert_to_array(data, certbuf, buflen, array); + free(certbuf); + if(rc != CURLE_OK) { + CFRelease(array); + return rc; + } + break; + } + else if(res == 0) { + /* No more certificates in the bundle. */ + free(certbuf); + break; + } + + rc = append_cert_to_array(data, der, derlen, array); + free(der); + if(rc != CURLE_OK) { + free(certbuf); + CFRelease(array); + return rc; + } + } + + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(trust == NULL) { + failf(data, "SSL: error getting certificate chain"); + CFRelease(array); + return CURLE_OUT_OF_MEMORY; + } + else if(ret != noErr) { + CFRelease(array); + return sslerr_to_curlerr(data, ret); + } + + ret = SecTrustSetAnchorCertificates(trust, array); + if(ret != noErr) { + CFRelease(trust); + return sslerr_to_curlerr(data, ret); + } + ret = SecTrustSetAnchorCertificatesOnly(trust, true); + if(ret != noErr) { + CFRelease(trust); + return sslerr_to_curlerr(data, ret); + } + + SecTrustResultType trust_eval = 0; + ret = SecTrustEvaluate(trust, &trust_eval); + CFRelease(array); + CFRelease(trust); + if(ret != noErr) { + return sslerr_to_curlerr(data, ret); + } + + switch(trust_eval) { + case kSecTrustResultUnspecified: + case kSecTrustResultProceed: + return CURLE_OK; + + case kSecTrustResultRecoverableTrustFailure: + case kSecTrustResultDeny: + default: + failf(data, "SSL: certificate verification failed (result: %d)", + trust_eval); + return CURLE_PEER_FAILED_VERIFICATION; + } +} + +#ifdef DARWIN_SSL_PINNEDPUBKEY +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, + SSLContextRef ctx, + const char *pinnedpubkey) +{ /* Scratch */ + size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24; + unsigned char *pubkey = NULL, *realpubkey = NULL; + const unsigned char *spkiHeader = NULL; + CFDataRef publicKeyBits = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + + if(!ctx) + return result; + + do { + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(ret != noErr || trust == NULL) + break; + + SecKeyRef keyRef = SecTrustCopyPublicKey(trust); + CFRelease(trust); + if(keyRef == NULL) + break; + +#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 + + publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); + CFRelease(keyRef); + if(publicKeyBits == NULL) + break; + +#elif DARWIN_SSL_PINNEDPUBKEY_V2 + + OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, + &publicKeyBits); + CFRelease(keyRef); + if(success != errSecSuccess || publicKeyBits == NULL) + break; + +#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ + + pubkeylen = CFDataGetLength(publicKeyBits); + pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits); + + switch(pubkeylen) { + case 526: + /* 4096 bit RSA pubkeylen == 526 */ + spkiHeader = rsa4096SpkiHeader; + break; + case 270: + /* 2048 bit RSA pubkeylen == 270 */ + spkiHeader = rsa2048SpkiHeader; + break; +#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 + case 65: + /* ecDSA secp256r1 pubkeylen == 65 */ + spkiHeader = ecDsaSecp256r1SpkiHeader; + spkiHeaderLength = 26; + break; + case 97: + /* ecDSA secp384r1 pubkeylen == 97 */ + spkiHeader = ecDsaSecp384r1SpkiHeader; + spkiHeaderLength = 23; + break; + default: + infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); +#elif DARWIN_SSL_PINNEDPUBKEY_V2 + default: + /* ecDSA secp256r1 pubkeylen == 91 header already included? + * ecDSA secp384r1 header already included too + * we assume rest of algorithms do same, so do nothing + */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, + pubkeylen); +#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ + continue; /* break from loop */ + } + + realpubkeylen = pubkeylen + spkiHeaderLength; + realpubkey = malloc(realpubkeylen); + if(!realpubkey) + break; + + memcpy(realpubkey, spkiHeader, spkiHeaderLength); + memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen); + + result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey, + realpubkeylen); + + } while(0); + + Curl_safefree(realpubkey); + if(publicKeyBits != NULL) + CFRelease(publicKeyBits); + + return result; +} +#endif /* DARWIN_SSL_PINNEDPUBKEY */ + +static CURLcode +darwinssl_connect_step2(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + OSStatus err; + SSLCipherSuite cipher; + SSLProtocol protocol = 0; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + DEBUGASSERT(ssl_connect_2 == connssl->connecting_state + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); + + /* Here goes nothing: */ + err = SSLHandshake(connssl->ssl_ctx); + + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: /* they're not done with us yet */ + connssl->connecting_state = connssl->ssl_direction ? + ssl_connect_2_writing : ssl_connect_2_reading; + return CURLE_OK; + + /* The below is errSSLServerAuthCompleted; it's not defined in + Leopard's headers */ + case -9841: + if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { + int res = verify_cert(SSL_CONN_CONFIG(CAfile), data, + connssl->ssl_ctx); + if(res != CURLE_OK) + return res; + } + /* the documentation says we need to call SSLHandshake() again */ + return darwinssl_connect_step2(conn, sockindex); + + /* These are all certificate problems with the server: */ + case errSSLXCertChainInvalid: + failf(data, "SSL certificate problem: Invalid certificate chain"); + return CURLE_SSL_CACERT; + case errSSLUnknownRootCert: + failf(data, "SSL certificate problem: Untrusted root certificate"); + return CURLE_SSL_CACERT; + case errSSLNoRootCert: + failf(data, "SSL certificate problem: No root certificate"); + return CURLE_SSL_CACERT; + case errSSLCertExpired: + failf(data, "SSL certificate problem: Certificate chain had an " + "expired certificate"); + return CURLE_SSL_CACERT; + case errSSLBadCert: + failf(data, "SSL certificate problem: Couldn't understand the server " + "certificate format"); + return CURLE_SSL_CONNECT_ERROR; + + /* These are all certificate problems with the client: */ + case errSecAuthFailed: + failf(data, "SSL authentication failed"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLPeerHandshakeFail: + failf(data, "SSL peer handshake failed, the server most likely " + "requires a client certificate to connect"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLPeerUnknownCA: + failf(data, "SSL server rejected the client certificate due to " + "the certificate being signed by an unknown certificate " + "authority"); + return CURLE_SSL_CONNECT_ERROR; + + /* This error is raised if the server's cert didn't match the server's + host name: */ + case errSSLHostNameMismatch: + failf(data, "SSL certificate peer verification failed, the " + "certificate did not match \"%s\"\n", conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + + /* Generic handshake errors: */ + case errSSLConnectionRefused: + failf(data, "Server dropped the connection during the SSL handshake"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLClosedAbort: + failf(data, "Server aborted the SSL handshake"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLNegotiation: + failf(data, "Could not negotiate an SSL cipher suite with the server"); + return CURLE_SSL_CONNECT_ERROR; + /* Sometimes paramErr happens with buggy ciphers: */ + case paramErr: case errSSLInternal: + failf(data, "Internal SSL engine error encountered during the " + "SSL handshake"); + return CURLE_SSL_CONNECT_ERROR; + case errSSLFatalAlert: + failf(data, "Fatal SSL engine error encountered during the SSL " + "handshake"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unknown SSL protocol error in connection to %s:%d", + hostname, err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { + /* we have been connected fine, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_3; + +#ifdef DARWIN_SSL_PINNEDPUBKEY + if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { + CURLcode result = pkp_pin_peer_pubkey(data, connssl->ssl_ctx, + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } +#endif /* DARWIN_SSL_PINNEDPUBKEY */ + + /* Informational message */ + (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher); + (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol); + switch(protocol) { + case kSSLProtocol2: + infof(data, "SSL 2.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kSSLProtocol3: + infof(data, "SSL 3.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kTLSProtocol1: + infof(data, "TLS 1.0 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + case kTLSProtocol11: + infof(data, "TLS 1.1 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; + case kTLSProtocol12: + infof(data, "TLS 1.2 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#endif + default: + infof(data, "Unknown protocol connection\n"); + break; + } + + return CURLE_OK; + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* This should be called during step3 of the connection at the earliest */ +static void +show_verbose_server_cert(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CFStringRef server_cert_summary; + char server_cert_summary_c[128]; + CFArrayRef server_certs = NULL; + SecCertificateRef server_cert; + OSStatus err; + CFIndex i, count; + SecTrustRef trust = NULL; + + if(!connssl->ssl_ctx) + return; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS +#if CURL_BUILD_IOS +#pragma unused(server_certs) + err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + server_cert = SecTrustGetCertificateAtIndex(trust, i); + server_cert_summary = CopyCertSubject(server_cert); + memset(server_cert_summary_c, 0, 128); + if(CFStringGetCString(server_cert_summary, + server_cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Server certificate: %s\n", server_cert_summary_c); + } + CFRelease(server_cert_summary); + } + CFRelease(trust); + } +#else + /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion. + The function SecTrustGetCertificateAtIndex() is officially present + in Lion, but it is unfortunately also present in Snow Leopard as + private API and doesn't work as expected. So we have to look for + a different symbol to make sure this code is only executed under + Lion or later. */ + if(SecTrustEvaluateAsync != NULL) { +#pragma unused(server_certs) + err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + server_cert = SecTrustGetCertificateAtIndex(trust, i); + server_cert_summary = CopyCertSubject(server_cert); + memset(server_cert_summary_c, 0, 128); + if(CFStringGetCString(server_cert_summary, + server_cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Server certificate: %s\n", server_cert_summary_c); + } + CFRelease(server_cert_summary); + } + CFRelease(trust); + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); + /* Just in case SSLCopyPeerCertificates() returns null too... */ + if(err == noErr && server_certs) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, + i); + + server_cert_summary = CopyCertSubject(server_cert); + memset(server_cert_summary_c, 0, 128); + if(CFStringGetCString(server_cert_summary, + server_cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Server certificate: %s\n", server_cert_summary_c); + } + CFRelease(server_cert_summary); + } + CFRelease(server_certs); + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_IOS */ +#else +#pragma unused(trust) + err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs); + if(err == noErr) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); + server_cert_summary = CopyCertSubject(server_cert); + memset(server_cert_summary_c, 0, 128); + if(CFStringGetCString(server_cert_summary, + server_cert_summary_c, + 128, + kCFStringEncodingUTF8)) { + infof(data, "Server certificate: %s\n", server_cert_summary_c); + } + CFRelease(server_cert_summary); + } + CFRelease(server_certs); + } +#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +static CURLcode +darwinssl_connect_step3(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + /* There is no step 3! + * Well, okay, if verbose mode is on, let's print the details of the + * server certificates. */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + if(data->set.verbose) + show_verbose_server_cert(conn, sockindex); +#endif + + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; +} + +static Curl_recv darwinssl_recv; +static Curl_send darwinssl_send; + +static CURLcode +darwinssl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1==connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = darwinssl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if this + * connection is done nonblocking and this loop would execute again. This + * permits the owner of a multi handle to abort a connection attempt + * before step2 has completed while ensuring that a client using select() + * or epoll() will always have a valid fdset to wait on. + */ + result = darwinssl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + + if(ssl_connect_3 == connssl->connecting_state) { + result = darwinssl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = darwinssl_recv; + conn->send[sockindex] = darwinssl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +CURLcode +Curl_darwinssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return darwinssl_connect_common(conn, sockindex, TRUE, done); +} + +CURLcode +Curl_darwinssl_connect(struct connectdata *conn, + int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = darwinssl_connect_common(conn, sockindex, FALSE, &done); + + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +void Curl_darwinssl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->ssl_ctx) { + (void)SSLClose(connssl->ssl_ctx); +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) + CFRelease(connssl->ssl_ctx); +#if CURL_SUPPORT_MAC_10_8 + else + (void)SSLDisposeContext(connssl->ssl_ctx); +#endif /* CURL_SUPPORT_MAC_10_8 */ +#else + (void)SSLDisposeContext(connssl->ssl_ctx); +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + connssl->ssl_ctx = NULL; + } + connssl->ssl_sockfd = 0; +} + +int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + ssize_t nread; + int what; + int rc; + char buf[120]; + + if(!connssl->ssl_ctx) + return 0; + + if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) + return 0; + + Curl_darwinssl_close(conn, sockindex); + + rc = 0; + + what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); + + for(;;) { + if(what < 0) { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + rc = -1; + break; + } + + if(!what) { /* timeout */ + failf(data, "SSL shutdown timeout"); + break; + } + + /* Something to read, let's do it and hope that it is the close + notify alert from the server. No way to SSL_Read now, so use read(). */ + + nread = read(conn->sock[sockindex], buf, sizeof(buf)); + + if(nread < 0) { + failf(data, "read: %s", strerror(errno)); + rc = -1; + } + + if(nread <= 0) + break; + + what = SOCKET_READABLE(conn->sock[sockindex], 0); + } + + return rc; +} + +void Curl_darwinssl_session_free(void *ptr) +{ + /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a + cached session ID inside the Security framework. There is a private + function that does this, but I don't want to have to explain to you why I + got your application rejected from the App Store due to the use of a + private API, so the best we can do is free up our own char array that we + created way back in darwinssl_connect_step1... */ + Curl_safefree(ptr); +} + +size_t Curl_darwinssl_version(char *buffer, size_t size) +{ + return snprintf(buffer, size, "SecureTransport"); +} + +/* + * This function uses SSLGetSessionState to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +int Curl_darwinssl_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + OSStatus err; + SSLSessionState state; + + if(connssl->ssl_ctx) { + err = SSLGetSessionState(connssl->ssl_ctx, &state); + if(err == noErr) + return state == kSSLConnected || state == kSSLHandshake; + return -1; + } + return 0; +} + +bool Curl_darwinssl_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + OSStatus err; + size_t buffer; + + if(connssl->ssl_ctx) { /* SSL is in use */ + err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer); + if(err == noErr) + return buffer > 0UL; + return false; + } + else + return false; +} + +CURLcode Curl_darwinssl_random(unsigned char *entropy, + size_t length) +{ + /* arc4random_buf() isn't available on cats older than Lion, so let's + do this manually for the benefit of the older cats. */ + size_t i; + u_int32_t random_number = 0; + + for(i = 0 ; i < length ; i++) { + if(i % sizeof(u_int32_t) == 0) + random_number = arc4random(); + entropy[i] = random_number & 0xFF; + random_number >>= 8; + } + i = random_number = 0; + return CURLE_OK; +} + +void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + (void)md5len; + (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); +} + +void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ + assert(sha256len >= SHA256_DIGEST_LENGTH); + (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum); +} + +bool Curl_darwinssl_false_start(void) +{ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + if(SSLSetSessionOption != NULL) + return TRUE; +#endif + return FALSE; +} + +static ssize_t darwinssl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + /*struct Curl_easy *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + size_t processed = 0UL; + OSStatus err; + + /* The SSLWrite() function works a little differently than expected. The + fourth argument (processed) is currently documented in Apple's + documentation as: "On return, the length, in bytes, of the data actually + written." + + Now, one could interpret that as "written to the socket," but actually, + it returns the amount of data that was written to a buffer internal to + the SSLContextRef instead. So it's possible for SSLWrite() to return + errSSLWouldBlock and a number of bytes "written" because those bytes were + encrypted and written to a buffer, not to the socket. + + So if this happens, then we need to keep calling SSLWrite() over and + over again with no new data until it quits returning errSSLWouldBlock. */ + + /* Do we have buffered data to write from the last time we were called? */ + if(connssl->ssl_write_buffered_length) { + /* Write the buffered data: */ + err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed); + switch(err) { + case noErr: + /* processed is always going to be 0 because we didn't write to + the buffer, so return how much was written to the socket */ + processed = connssl->ssl_write_buffered_length; + connssl->ssl_write_buffered_length = 0UL; + break; + case errSSLWouldBlock: /* argh, try again */ + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + else { + /* We've got new data to write: */ + err = SSLWrite(connssl->ssl_ctx, mem, len, &processed); + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: + /* Data was buffered but not sent, we have to tell the caller + to try sending again, and remember how much was buffered */ + connssl->ssl_write_buffered_length = len; + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + } + return (ssize_t)processed; +} + +static ssize_t darwinssl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + /*struct Curl_easy *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[num]; + size_t processed = 0UL; + OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed); + + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: /* return how much we read (if anything) */ + if(processed) + return (ssize_t)processed; + *curlcode = CURLE_AGAIN; + return -1L; + break; + + /* errSSLClosedGraceful - server gracefully shut down the SSL session + errSSLClosedNoNotify - server hung up on us instead of sending a + closure alert notice, read() is returning 0 + Either way, inform the caller that the server disconnected. */ + case errSSLClosedGraceful: + case errSSLClosedNoNotify: + *curlcode = CURLE_OK; + return -1L; + break; + + default: + failf(conn->data, "SSLRead() return error %d", err); + *curlcode = CURLE_RECV_ERROR; + return -1L; + break; + } + } + return (ssize_t)processed; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif /* USE_DARWINSSL */ diff --git a/libcurl/lib/vtls/darwinssl.h b/libcurl/lib/vtls/darwinssl.h new file mode 100644 index 0000000..13e7851 --- /dev/null +++ b/libcurl/lib/vtls/darwinssl.h @@ -0,0 +1,101 @@ +#ifndef HEADER_CURL_DARWINSSL_H +#define HEADER_CURL_DARWINSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_DARWINSSL + +CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex); + +CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); + +/* close a SSL connection */ +void Curl_darwinssl_close(struct connectdata *conn, int sockindex); + +void Curl_darwinssl_session_free(void *ptr); +size_t Curl_darwinssl_version(char *buffer, size_t size); +int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex); +int Curl_darwinssl_check_cxn(struct connectdata *conn); +bool Curl_darwinssl_data_pending(const struct connectdata *conn, + int connindex); + +CURLcode Curl_darwinssl_random(unsigned char *entropy, + size_t length); +void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); +void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len); +bool Curl_darwinssl_false_start(void); + +/* Set the API backend definition to SecureTransport */ +#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL + +/* pinned public key support tests */ + +/* version 1 supports macOS 10.12+ and iOS 10+ */ +#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ + (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) +#define DARWIN_SSL_PINNEDPUBKEY_V1 1 +#endif + +/* version 2 supports MacOSX 10.7+ */ +#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) +#define DARWIN_SSL_PINNEDPUBKEY_V2 1 +#endif + +#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2) +/* this backend supports CURLOPT_PINNEDPUBLICKEY */ +#define DARWIN_SSL_PINNEDPUBKEY 1 +#define have_curlssl_pinnedpubkey 1 +#endif /* DARWIN_SSL_PINNEDPUBKEY */ + +/* API setup for SecureTransport */ +#define curlssl_init() (1) +#define curlssl_cleanup() Curl_nop_stmt +#define curlssl_connect Curl_darwinssl_connect +#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking +#define curlssl_session_free(x) Curl_darwinssl_session_free(x) +#define curlssl_close_all(x) ((void)x) +#define curlssl_close Curl_darwinssl_close +#define curlssl_shutdown(x,y) 0 +#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN) +#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN) +#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) +#define curlssl_version Curl_darwinssl_version +#define curlssl_check_cxn Curl_darwinssl_check_cxn +#define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y) +#define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z)) +#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d) +#define curlssl_sha256sum(a,b,c,d) \ + Curl_darwinssl_sha256sum((unsigned char *)a, b, c, d) +#define curlssl_false_start() Curl_darwinssl_false_start() + +#endif /* USE_DARWINSSL */ +#endif /* HEADER_CURL_DARWINSSL_H */ diff --git a/libcurl/lib/vtls/debug_utility.cpp b/libcurl/lib/vtls/debug_utility.cpp new file mode 100644 index 0000000..6ba3c4b --- /dev/null +++ b/libcurl/lib/vtls/debug_utility.cpp @@ -0,0 +1,28 @@ +#include "debug_utility.h" + +#include +#include +#include + +int debug_utility::debug_print(const char* format, ...) +{ + /* Use a fixed buffer since VS2003 doesn't support va_copy */ + char message[512]; + va_list args; + int length; + + va_start(args, format); + length = _vsnprintf(message, sizeof(message) - 1, format, args); + va_end(args); + + /* Ensure null termination */ + if (length < 0 || length >= (int)sizeof(message)) { + message[sizeof(message) - 1] = '\0'; + length = (int)sizeof(message) - 1; + } else { + message[length] = '\0'; + } + + OutputDebugStringA(message); + return length; +} \ No newline at end of file diff --git a/libcurl/lib/vtls/debug_utility.h b/libcurl/lib/vtls/debug_utility.h new file mode 100644 index 0000000..62c7817 --- /dev/null +++ b/libcurl/lib/vtls/debug_utility.h @@ -0,0 +1,7 @@ +#pragma once + +class debug_utility +{ +public: + static int debug_print(const char* format, ...); +}; diff --git a/libcurl/lib/vtls/gskit.c b/libcurl/lib/vtls/gskit.c new file mode 100644 index 0000000..b93ff5d --- /dev/null +++ b/libcurl/lib/vtls/gskit.c @@ -0,0 +1,1381 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_GSKIT + +#include +#include + +/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */ +#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST +#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230 +#endif + +#ifndef GSK_TLSV10_CIPHER_SPECS +#define GSK_TLSV10_CIPHER_SPECS 236 +#endif + +#ifndef GSK_TLSV11_CIPHER_SPECS +#define GSK_TLSV11_CIPHER_SPECS 237 +#endif + +#ifndef GSK_TLSV12_CIPHER_SPECS +#define GSK_TLSV12_CIPHER_SPECS 238 +#endif + +#ifndef GSK_PROTOCOL_TLSV11 +#define GSK_PROTOCOL_TLSV11 437 +#endif + +#ifndef GSK_PROTOCOL_TLSV12 +#define GSK_PROTOCOL_TLSV12 438 +#endif + +#ifndef GSK_FALSE +#define GSK_FALSE 0 +#endif + +#ifndef GSK_TRUE +#define GSK_TRUE 1 +#endif + + +#include + +#include +#include "urldata.h" +#include "sendf.h" +#include "gskit.h" +#include "vtls.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "x509asn1.h" +#include "curl_printf.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + + +/* Directions. */ +#define SOS_READ 0x01 +#define SOS_WRITE 0x02 + +/* SSL version flags. */ +#define CURL_GSKPROTO_SSLV2 0 +#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2) +#define CURL_GSKPROTO_SSLV3 1 +#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3) +#define CURL_GSKPROTO_TLSV10 2 +#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10) +#define CURL_GSKPROTO_TLSV11 3 +#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11) +#define CURL_GSKPROTO_TLSV12 4 +#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12) +#define CURL_GSKPROTO_LAST 5 + +struct ssl_backend_data { + gsk_handle handle; + int iocport; + int localfd; + int remotefd; +}; + +#define BACKEND connssl->backend + +/* Supported ciphers. */ +typedef struct { + const char *name; /* Cipher name. */ + const char *gsktoken; /* Corresponding token for GSKit String. */ + unsigned int versions; /* SSL version flags. */ +} gskit_cipher; + +static const gskit_cipher ciphertable[] = { + { "null-md5", "01", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "null-sha", "02", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "exp-rc4-md5", "03", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, + { "rc4-md5", "04", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "rc4-sha", "05", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "exp-rc2-cbc-md5", "06", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, + { "exp-des-cbc-sha", "09", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK }, + { "des-cbc3-sha", "0A", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-sha", "2F", + CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-sha", "35", + CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK }, + { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-gcm-sha256", + "9C", CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-gcm-sha384", + "9D", CURL_GSKPROTO_TLSV12_MASK }, + { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK }, + { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK }, + { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK }, + { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK }, + { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK }, + { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK }, + { (const char *) NULL, (const char *) NULL, 0 } +}; + + +static bool is_separator(char c) +{ + /* Return whether character is a cipher list separator. */ + switch(c) { + case ' ': + case '\t': + case ':': + case ',': + case ';': + return true; + } + return false; +} + + +static CURLcode gskit_status(struct Curl_easy *data, int rc, + const char *procname, CURLcode defcode) +{ + /* Process GSKit status and map it to a CURLcode. */ + switch(rc) { + case GSK_OK: + case GSK_OS400_ASYNCHRONOUS_SOC_INIT: + return CURLE_OK; + case GSK_KEYRING_OPEN_ERROR: + case GSK_OS400_ERROR_NO_ACCESS: + return CURLE_SSL_CACERT_BADFILE; + case GSK_INSUFFICIENT_STORAGE: + return CURLE_OUT_OF_MEMORY; + case GSK_ERROR_BAD_V2_CIPHER: + case GSK_ERROR_BAD_V3_CIPHER: + case GSK_ERROR_NO_CIPHERS: + return CURLE_SSL_CIPHER; + case GSK_OS400_ERROR_NOT_TRUSTED_ROOT: + case GSK_ERROR_CERT_VALIDATION: + return CURLE_PEER_FAILED_VERIFICATION; + case GSK_OS400_ERROR_TIMED_OUT: + return CURLE_OPERATION_TIMEDOUT; + case GSK_WOULD_BLOCK: + return CURLE_AGAIN; + case GSK_OS400_ERROR_NOT_REGISTERED: + break; + case GSK_ERROR_IO: + switch(errno) { + case ENOMEM: + return CURLE_OUT_OF_MEMORY; + default: + failf(data, "%s I/O error: %s", procname, strerror(errno)); + break; + } + break; + default: + failf(data, "%s: %s", procname, gsk_strerror(rc)); + break; + } + return defcode; +} + + +static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, + GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok) +{ + int rc = gsk_attribute_set_enum(h, id, value); + + switch(rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); + break; + case GSK_ATTRIBUTE_INVALID_ID: + if(unsupported_ok) + return CURLE_UNSUPPORTED_PROTOCOL; + default: + failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, + GSK_BUF_ID id, const char *buffer, bool unsupported_ok) +{ + int rc = gsk_attribute_set_buffer(h, id, buffer, 0); + + switch(rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); + break; + case GSK_ATTRIBUTE_INVALID_ID: + if(unsupported_ok) + return CURLE_UNSUPPORTED_PROTOCOL; + default: + failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_numeric(struct Curl_easy *data, + gsk_handle h, GSK_NUM_ID id, int value) +{ + int rc = gsk_attribute_set_numeric_value(h, id, value); + + switch(rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_numeric_value() I/O error: %s", + strerror(errno)); + break; + default: + failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_callback(struct Curl_easy *data, + gsk_handle h, GSK_CALLBACK_ID id, void *info) +{ + int rc = gsk_attribute_set_callback(h, id, info); + + switch(rc) { + case GSK_OK: + return CURLE_OK; + case GSK_ERROR_IO: + failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno)); + break; + default: + failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc)); + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode set_ciphers(struct connectdata *conn, + gsk_handle h, unsigned int *protoflags) +{ + struct Curl_easy *data = conn->data; + const char *cipherlist = SSL_CONN_CONFIG(cipher_list); + const char *clp; + const gskit_cipher *ctp; + int i; + int l; + bool unsupported; + CURLcode result; + struct { + char *buf; + char *ptr; + } ciphers[CURL_GSKPROTO_LAST]; + + /* Compile cipher list into GSKit-compatible cipher lists. */ + + if(!cipherlist) + return CURLE_OK; + while(is_separator(*cipherlist)) /* Skip initial separators. */ + cipherlist++; + if(!*cipherlist) + return CURLE_OK; + + /* We allocate GSKit buffers of the same size as the input string: since + GSKit tokens are always shorter than their cipher names, allocated buffers + will always be large enough to accommodate the result. */ + l = strlen(cipherlist) + 1; + memset((char *) ciphers, 0, sizeof(ciphers)); + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + ciphers[i].buf = malloc(l); + if(!ciphers[i].buf) { + while(i--) + free(ciphers[i].buf); + return CURLE_OUT_OF_MEMORY; + } + ciphers[i].ptr = ciphers[i].buf; + *ciphers[i].ptr = '\0'; + } + + /* Process each cipher in input string. */ + unsupported = FALSE; + result = CURLE_OK; + for(;;) { + for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);) + cipherlist++; + l = cipherlist - clp; + if(!l) + break; + /* Search the cipher in our table. */ + for(ctp = ciphertable; ctp->name; ctp++) + if(strncasecompare(ctp->name, clp, l) && !ctp->name[l]) + break; + if(!ctp->name) { + failf(data, "Unknown cipher %.*s", l, clp); + result = CURLE_SSL_CIPHER; + } + else { + unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK | + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK)); + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + if(ctp->versions & (1 << i)) { + strcpy(ciphers[i].ptr, ctp->gsktoken); + ciphers[i].ptr += strlen(ctp->gsktoken); + } + } + } + + /* Advance to next cipher name or end of string. */ + while(is_separator(*cipherlist)) + cipherlist++; + } + + /* Disable protocols with empty cipher lists. */ + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) { + *protoflags &= ~(1 << i); + ciphers[i].buf[0] = '\0'; + } + } + + /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */ + if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) { + result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(unsupported) { + failf(data, "TLSv1.1-only ciphers are not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) { + result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(unsupported) { + failf(data, "TLSv1.2-only ciphers are not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + + /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to + the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */ + if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) { + result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr, + ciphers[CURL_GSKPROTO_TLSV10].ptr); + } + } + + /* Set-up other ciphers. */ + if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK)) + result = set_buffer(data, h, GSK_V3_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE); + if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK)) + result = set_buffer(data, h, GSK_V2_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE); + + /* Clean-up. */ + for(i = 0; i < CURL_GSKPROTO_LAST; i++) + free(ciphers[i].buf); + + return result; +} + + +static int Curl_gskit_init(void) +{ + /* No initialisation needed. */ + + return 1; +} + + +static void Curl_gskit_cleanup(void) +{ + /* Nothing to do. */ +} + + +static CURLcode init_environment(struct Curl_easy *data, + gsk_handle *envir, const char *appid, + const char *file, const char *label, + const char *password) +{ + int rc; + CURLcode result; + gsk_handle h; + + /* Creates the GSKit environment. */ + + rc = gsk_environment_open(&h); + switch(rc) { + case GSK_OK: + break; + case GSK_INSUFFICIENT_STORAGE: + return CURLE_OUT_OF_MEMORY; + default: + failf(data, "gsk_environment_open(): %s", gsk_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + + result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE); + if(!result && appid) + result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE); + if(!result && file) + result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE); + if(!result && label) + result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE); + if(!result && password) + result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE); + + if(!result) { + /* Locate CAs, Client certificate and key according to our settings. + Note: this call may be blocking for some tenths of seconds. */ + result = gskit_status(data, gsk_environment_init(h), + "gsk_environment_init()", CURLE_SSL_CERTPROBLEM); + if(!result) { + *envir = h; + return result; + } + } + /* Error: rollback. */ + gsk_environment_close(&h); + return result; +} + + +static void cancel_async_handshake(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + Qso_OverlappedIO_t cstat; + + if(QsoCancelOperation(conn->sock[sockindex], 0) > 0) + QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL); +} + + +static void close_async_handshake(struct ssl_connect_data *connssl) +{ + QsoDestroyIOCompletionPort(BACKEND->iocport); + BACKEND->iocport = -1; +} + +/* SSL over SSL + * Problems: + * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To + * pipe an SSL stream into another, it is therefore needed to have a pair + * of such communicating sockets and handle the pipelining explicitly. + * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot + * be used to produce the pipeline. + * The solution is to simulate socketpair() for AF_INET with low-level API + * listen(), bind() and connect(). + */ + +static int +inetsocketpair(int sv[2]) +{ + int lfd; /* Listening socket. */ + int sfd; /* Server socket. */ + int cfd; /* Client socket. */ + int len; + struct sockaddr_in addr1; + struct sockaddr_in addr2; + + /* Create listening socket on a local dynamic port. */ + lfd = socket(AF_INET, SOCK_STREAM, 0); + if(lfd < 0) + return -1; + memset((char *) &addr1, 0, sizeof(addr1)); + addr1.sin_family = AF_INET; + addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr1.sin_port = 0; + if(bind(lfd, (struct sockaddr *) &addr1, sizeof(addr1)) || + listen(lfd, 2) < 0) { + close(lfd); + return -1; + } + + /* Get the allocated port. */ + len = sizeof(addr1); + if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) { + close(lfd); + return -1; + } + + /* Create the client socket. */ + cfd = socket(AF_INET, SOCK_STREAM, 0); + if(cfd < 0) { + close(lfd); + return -1; + } + + /* Request unblocking connection to the listening socket. */ + curlx_nonblock(cfd, TRUE); + if(connect(cfd, (struct sockaddr *) &addr1, sizeof(addr1)) < 0 && + errno != EINPROGRESS) { + close(lfd); + close(cfd); + return -1; + } + + /* Get the client dynamic port for intrusion check below. */ + len = sizeof(addr2); + if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) { + close(lfd); + close(cfd); + return -1; + } + + /* Accept the incoming connection and get the server socket. */ + curlx_nonblock(lfd, TRUE); + for(;;) { + len = sizeof(addr1); + sfd = accept(lfd, (struct sockaddr *) &addr1, &len); + if(sfd < 0) { + close(lfd); + close(cfd); + return -1; + } + + /* Check for possible intrusion from an external process. */ + if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr && + addr1.sin_port == addr2.sin_port) + break; + + /* Intrusion: reject incoming connection. */ + close(sfd); + } + + /* Done, return sockets and succeed. */ + close(lfd); + curlx_nonblock(cfd, FALSE); + sv[0] = cfd; + sv[1] = sfd; + return 0; +} + +static int pipe_ssloverssl(struct connectdata *conn, int sockindex, + int directions) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex]; + fd_set fds_read; + fd_set fds_write; + int n; + int m; + int i; + int ret = 0; + struct timeval tv = {0, 0}; + char buf[CURL_MAX_WRITE_SIZE]; + + if(!connssl->use || !connproxyssl->use) + return 0; /* No SSL over SSL: OK. */ + + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + n = -1; + if(directions & SOS_READ) { + FD_SET(BACKEND->remotefd, &fds_write); + n = BACKEND->remotefd; + } + if(directions & SOS_WRITE) { + FD_SET(BACKEND->remotefd, &fds_read); + n = BACKEND->remotefd; + FD_SET(conn->sock[sockindex], &fds_write); + if(n < conn->sock[sockindex]) + n = conn->sock[sockindex]; + } + i = select(n + 1, &fds_read, &fds_write, NULL, &tv); + if(i < 0) + return -1; /* Select error. */ + + if(FD_ISSET(BACKEND->remotefd, &fds_write)) { + /* Try getting data from HTTPS proxy and pipe it upstream. */ + n = 0; + i = gsk_secure_soc_read(connproxyssl->backend->handle, + buf, sizeof(buf), &n); + switch(i) { + case GSK_OK: + if(n) { + i = write(BACKEND->remotefd, buf, n); + if(i < 0) + return -1; + ret = 1; + } + break; + case GSK_OS400_ERROR_TIMED_OUT: + case GSK_WOULD_BLOCK: + break; + default: + return -1; + } + } + + if(FD_ISSET(BACKEND->remotefd, &fds_read) && + FD_ISSET(conn->sock[sockindex], &fds_write)) { + /* Pipe data to HTTPS proxy. */ + n = read(BACKEND->remotefd, buf, sizeof(buf)); + if(n < 0) + return -1; + if(n) { + i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m); + if(i != GSK_OK || n != m) + return -1; + ret = 1; + } + } + + return ret; /* OK */ +} + + +static void close_one(struct ssl_connect_data *connssl, + struct connectdata *conn, int sockindex) +{ + if(BACKEND->handle) { + gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle), + "gsk_secure_soc_close()", 0); + /* Last chance to drain output. */ + while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) + ; + BACKEND->handle = (gsk_handle) NULL; + if(BACKEND->localfd >= 0) { + close(BACKEND->localfd); + BACKEND->localfd = -1; + } + if(BACKEND->remotefd >= 0) { + close(BACKEND->remotefd); + BACKEND->remotefd = -1; + } + } + if(BACKEND->iocport >= 0) + close_async_handshake(connssl); +} + + +static ssize_t gskit_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + CURLcode cc = CURLE_SEND_ERROR; + int written; + + if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) { + cc = gskit_status(data, + gsk_secure_soc_write(BACKEND->handle, + (char *) mem, (int) len, &written), + "gsk_secure_soc_write()", CURLE_SEND_ERROR); + if(cc == CURLE_OK) + if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0) + cc = CURLE_SEND_ERROR; + } + if(cc != CURLE_OK) { + *curlcode = cc; + written = -1; + } + return (ssize_t) written; /* number of bytes */ +} + + +static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, + size_t buffersize, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + struct Curl_easy *data = conn->data; + int nread; + CURLcode cc = CURLE_RECV_ERROR; + + if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) { + int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; + cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle, + buf, buffsize, &nread), + "gsk_secure_soc_read()", CURLE_RECV_ERROR); + } + switch(cc) { + case CURLE_OK: + break; + case CURLE_OPERATION_TIMEDOUT: + cc = CURLE_AGAIN; + default: + *curlcode = cc; + nread = -1; + break; + } + return (ssize_t) nread; +} + +static CURLcode +set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long i = ssl_version; + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_TLSv1_2; + break; + } + for(; i <= (ssl_version_max >> 16); ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + *protoflags |= CURL_GSKPROTO_TLSV10_MASK; + break; + case CURL_SSLVERSION_TLSv1_1: + *protoflags |= CURL_GSKPROTO_TLSV11_MASK; + break; + case CURL_SSLVERSION_TLSv1_2: + *protoflags |= CURL_GSKPROTO_TLSV11_MASK; + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "GSKit: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + + return CURLE_OK; +} + +static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + gsk_handle envir; + CURLcode result; + int rc; + const char * const keyringfile = SSL_CONN_CONFIG(CAfile); + const char * const keyringpwd = SSL_SET_OPTION(key_passwd); + const char * const keyringlabel = SSL_SET_OPTION(cert); + const long int ssl_version = SSL_CONN_CONFIG(version); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: + conn->host.name; + const char *sni; + unsigned int protoflags = 0; + Qso_OverlappedIO_t commarea; + int sockpair[2]; + static const int sobufsize = CURL_MAX_WRITE_SIZE; + + /* Create SSL environment, start (preferably asynchronous) handshake. */ + + BACKEND->handle = (gsk_handle) NULL; + BACKEND->iocport = -1; + BACKEND->localfd = -1; + BACKEND->remotefd = -1; + + /* GSKit supports two ways of specifying an SSL context: either by + * application identifier (that should have been defined at the system + * level) or by keyring file, password and certificate label. + * Local certificate name (CURLOPT_SSLCERT) is used to hold either the + * application identifier of the certificate label. + * Key password (CURLOPT_KEYPASSWD) holds the keyring password. + * It is not possible to have different keyrings for the CAs and the + * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify + * the keyring file. + * If no key password is given and the keyring is the system keyring, + * application identifier mode is tried first, as recommended in IBM doc. + */ + + envir = (gsk_handle) NULL; + + if(keyringlabel && *keyringlabel && !keyringpwd && + !strcmp(keyringfile, CURL_CA_BUNDLE)) { + /* Try application identifier mode. */ + init_environment(data, &envir, keyringlabel, (const char *) NULL, + (const char *) NULL, (const char *) NULL); + } + + if(!envir) { + /* Use keyring mode. */ + result = init_environment(data, &envir, (const char *) NULL, + keyringfile, keyringlabel, keyringpwd); + if(result) + return result; + } + + /* Create secure session. */ + result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle), + "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR); + gsk_environment_close(&envir); + if(result) + return result; + + /* Establish a pipelining socket pair for SSL over SSL. */ + if(conn->proxy_ssl[sockindex].use) { + if(inetsocketpair(sockpair)) + return CURLE_SSL_CONNECT_ERROR; + BACKEND->localfd = sockpair[0]; + BACKEND->remotefd = sockpair[1]; + setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF, + (void *) sobufsize, sizeof(sobufsize)); + setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF, + (void *) sobufsize, sizeof(sobufsize)); + setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF, + (void *) sobufsize, sizeof(sobufsize)); + setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF, + (void *) sobufsize, sizeof(sobufsize)); + curlx_nonblock(BACKEND->localfd, TRUE); + curlx_nonblock(BACKEND->remotefd, TRUE); + } + + /* Determine which SSL/TLS version should be enabled. */ + sni = hostname; + switch(ssl_version) { + case CURL_SSLVERSION_SSLv2: + protoflags = CURL_GSKPROTO_SSLV2_MASK; + sni = NULL; + break; + case CURL_SSLVERSION_SSLv3: + protoflags = CURL_GSKPROTO_SSLV3_MASK; + sni = NULL; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + protoflags = CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + result = set_ssl_version_min_max(&protoflags, conn); + if(result != CURLE_OK) + return result; + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ + if(sni) { + result = set_buffer(data, BACKEND->handle, + GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) + result = CURLE_OK; + } + + /* Set session parameters. */ + if(!result) { + /* Compute the handshake timeout. Since GSKit granularity is 1 second, + we round up the required value. */ + long timeout = Curl_timeleft(data, NULL, TRUE); + if(timeout < 0) + result = CURLE_OPERATION_TIMEDOUT; + else + result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT, + (timeout + 999) / 1000); + } + if(!result) + result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1); + if(!result) + result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0? + BACKEND->localfd: conn->sock[sockindex]); + if(!result) + result = set_ciphers(conn, BACKEND->handle, &protoflags); + if(!protoflags) { + failf(data, "No SSL protocol/cipher combination enabled"); + result = CURLE_SSL_CIPHER; + } + if(!result) + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2, + (protoflags & CURL_GSKPROTO_SSLV2_MASK)? + GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); + if(!result) + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3, + (protoflags & CURL_GSKPROTO_SSLV3_MASK)? + GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); + if(!result) + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1, + (protoflags & CURL_GSKPROTO_TLSV10_MASK)? + GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); + if(!result) { + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11, + (protoflags & CURL_GSKPROTO_TLSV11_MASK)? + GSK_TRUE: GSK_FALSE, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { + failf(data, "TLS 1.1 not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result) { + result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12, + (protoflags & CURL_GSKPROTO_TLSV12_MASK)? + GSK_TRUE: GSK_FALSE, TRUE); + if(result == CURLE_UNSUPPORTED_PROTOCOL) { + result = CURLE_OK; + if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { + failf(data, "TLS 1.2 not yet supported"); + result = CURLE_SSL_CIPHER; + } + } + } + if(!result) + result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE, + verifypeer? GSK_SERVER_AUTH_FULL: + GSK_SERVER_AUTH_PASSTHRU, FALSE); + + if(!result) { + /* Start handshake. Try asynchronous first. */ + memset(&commarea, 0, sizeof(commarea)); + BACKEND->iocport = QsoCreateIOCompletionPort(); + if(BACKEND->iocport != -1) { + result = gskit_status(data, + gsk_secure_soc_startInit(BACKEND->handle, + BACKEND->iocport, + &commarea), + "gsk_secure_soc_startInit()", + CURLE_SSL_CONNECT_ERROR); + if(!result) { + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; + } + else + close_async_handshake(connssl); + } + else if(errno != ENOBUFS) + result = gskit_status(data, GSK_ERROR_IO, + "QsoCreateIOCompletionPort()", 0); + else if(conn->proxy_ssl[sockindex].use) { + /* Cannot pipeline while handshaking synchronously. */ + result = CURLE_SSL_CONNECT_ERROR; + } + else { + /* No more completion port available. Use synchronous IO. */ + result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle), + "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); + if(!result) { + connssl->connecting_state = ssl_connect_3; + return CURLE_OK; + } + } + } + + /* Error: rollback. */ + close_one(connssl, conn, sockindex); + return result; +} + + +static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, + bool nonblocking) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + Qso_OverlappedIO_t cstat; + struct timeval stmv; + CURLcode result; + + /* Poll or wait for end of SSL asynchronous handshake. */ + + for(;;) { + long timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE); + if(timeout_ms < 0) + timeout_ms = 0; + stmv.tv_sec = timeout_ms / 1000; + stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000; + switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat, &stmv)) { + case 1: /* Operation complete. */ + break; + case -1: /* An error occurred: handshake still in progress. */ + if(errno == EINTR) { + if(nonblocking) + return CURLE_OK; + continue; /* Retry. */ + } + if(errno != ETIME) { + failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno)); + cancel_async_handshake(conn, sockindex); + close_async_handshake(connssl); + return CURLE_SSL_CONNECT_ERROR; + } + /* FALL INTO... */ + case 0: /* Handshake in progress, timeout occurred. */ + if(nonblocking) + return CURLE_OK; + cancel_async_handshake(conn, sockindex); + close_async_handshake(connssl); + return CURLE_OPERATION_TIMEDOUT; + } + break; + } + result = gskit_status(data, cstat.returnValue, "SSL handshake", + CURLE_SSL_CONNECT_ERROR); + if(!result) + connssl->connecting_state = ssl_connect_3; + close_async_handshake(connssl); + return result; +} + + +static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const gsk_cert_data_elem *cdev; + int cdec; + const gsk_cert_data_elem *p; + const char *cert = (const char *) NULL; + const char *certend; + const char *ptr; + CURLcode result; + + /* SSL handshake done: gather certificate info and verify host. */ + + if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle, + GSK_PARTNER_CERT_INFO, + &cdev, &cdec), + "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) == + CURLE_OK) { + int i; + + infof(data, "Server certificate:\n"); + p = cdev; + for(i = 0; i++ < cdec; p++) + switch(p->cert_data_id) { + case CERT_BODY_DER: + cert = p->cert_data_p; + certend = cert + cdev->cert_data_l; + break; + case CERT_DN_PRINTABLE: + infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_ISSUER_DN_PRINTABLE: + infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_VALID_FROM: + infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + case CERT_VALID_TO: + infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p); + break; + } + } + + /* Verify host. */ + result = Curl_verifyhost(conn, cert, certend); + if(result) + return result; + + /* The only place GSKit can get the whole CA chain is a validation + callback where no user data pointer is available. Therefore it's not + possible to copy this chain into our structures for CAINFO. + However the server certificate may be available, thus we can return + info about it. */ + if(data->set.ssl.certinfo) { + result = Curl_ssl_init_certinfo(data, 1); + if(result) + return result; + + if(cert) { + result = Curl_extract_certinfo(conn, 0, cert, certend); + if(result) + return result; + } + } + + /* Check pinned public key. */ + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + if(!result && ptr) { + curl_X509certificate x509; + curl_asn1Element *p; + + if(Curl_parseX509(&x509, cert, certend)) + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + p = &x509.subjectPublicKeyInfo; + result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } + + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; +} + + +static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long timeout_ms; + CURLcode result = CURLE_OK; + + *done = connssl->state == ssl_connection_complete; + if(*done) + return CURLE_OK; + + /* Step 1: create session, start handshake. */ + if(connssl->connecting_state == ssl_connect_1) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + result = CURLE_OPERATION_TIMEDOUT; + } + else + result = gskit_connect_step1(conn, sockindex); + } + + /* Handle handshake pipelining. */ + if(!result) + if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + result = CURLE_SSL_CONNECT_ERROR; + + /* Step 2: check if handshake is over. */ + if(!result && connssl->connecting_state == ssl_connect_2) { + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + result = CURLE_OPERATION_TIMEDOUT; + } + else + result = gskit_connect_step2(conn, sockindex, nonblocking); + } + + /* Handle handshake pipelining. */ + if(!result) + if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + result = CURLE_SSL_CONNECT_ERROR; + + /* Step 3: gather certificate info, verify host. */ + if(!result && connssl->connecting_state == ssl_connect_3) + result = gskit_connect_step3(conn, sockindex); + + if(result) + close_one(connssl, conn, sockindex); + else if(connssl->connecting_state == ssl_connect_done) { + connssl->state = ssl_connection_complete; + connssl->connecting_state = ssl_connect_1; + conn->recv[sockindex] = gskit_recv; + conn->send[sockindex] = gskit_send; + *done = TRUE; + } + + return result; +} + + +static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + CURLcode result; + + result = gskit_connect_common(conn, sockindex, TRUE, done); + if(*done || result) + conn->ssl[sockindex].connecting_state = ssl_connect_1; + return result; +} + + +static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done; + + conn->ssl[sockindex].connecting_state = ssl_connect_1; + result = gskit_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + + +static void Curl_gskit_close(struct connectdata *conn, int sockindex) +{ + close_one(&conn->ssl[sockindex], conn, sockindex); + close_one(&conn->proxy_ssl[sockindex], conn, sockindex); +} + + +static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + int what; + int rc; + char buf[120]; + + if(!BACKEND->handle) + return 0; + +#ifndef CURL_DISABLE_FTP + if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) + return 0; +#endif + + close_one(connssl, conn, sockindex); + rc = 0; + what = SOCKET_READABLE(conn->sock[sockindex], + SSL_SHUTDOWN_TIMEOUT); + + for(;;) { + ssize_t nread; + + if(what < 0) { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + rc = -1; + break; + } + + if(!what) { /* timeout */ + failf(data, "SSL shutdown timeout"); + break; + } + + /* Something to read, let's do it and hope that it is the close + notify alert from the server. No way to gsk_secure_soc_read() now, so + use read(). */ + + nread = read(conn->sock[sockindex], buf, sizeof(buf)); + + if(nread < 0) { + failf(data, "read: %s", strerror(errno)); + rc = -1; + } + + if(nread <= 0) + break; + + what = SOCKET_READABLE(conn->sock[sockindex], 0); + } + + return rc; +} + + +static size_t Curl_gskit_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "GSKit"); +} + + +static int Curl_gskit_check_cxn(struct connectdata *cxn) +{ + struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET]; + int err; + int errlen; + + /* The only thing that can be tested here is at the socket level. */ + + if(!BACKEND->handle) + return 0; /* connection has been closed */ + + err = 0; + errlen = sizeof(err); + + if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR, + (unsigned char *) &err, &errlen) || + errlen != sizeof(err) || err) + return 0; /* connection has been closed */ + + return -1; /* connection status unknown */ +} + +static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_gskit = { + { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */ + + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY, + + sizeof(struct ssl_backend_data), + + Curl_gskit_init, /* init */ + Curl_gskit_cleanup, /* cleanup */ + Curl_gskit_version, /* version */ + Curl_gskit_check_cxn, /* check_cxn */ + Curl_gskit_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_gskit_connect, /* connect */ + Curl_gskit_connect_nonblocking, /* connect_nonblocking */ + Curl_gskit_get_internals, /* get_internals */ + Curl_gskit_close, /* close_one */ + Curl_none_close_all, /* close_all */ + /* No session handling for GSKit */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + NULL /* sha256sum */ +}; + +#endif /* USE_GSKIT */ diff --git a/libcurl/lib/vtls/gskit.h b/libcurl/lib/vtls/gskit.h new file mode 100644 index 0000000..466ee4d --- /dev/null +++ b/libcurl/lib/vtls/gskit.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_GSKIT_H +#define HEADER_CURL_GSKIT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* + * This header should only be needed to get included by vtls.c and gskit.c + */ + +#include "urldata.h" + +#ifdef USE_GSKIT + +extern const struct Curl_ssl Curl_ssl_gskit; + +#endif /* USE_GSKIT */ + +#endif /* HEADER_CURL_GSKIT_H */ diff --git a/libcurl/lib/vtls/gtls.c b/libcurl/lib/vtls/gtls.c new file mode 100644 index 0000000..8693cdc --- /dev/null +++ b/libcurl/lib/vtls/gtls.c @@ -0,0 +1,1881 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + * Note: don't use the GnuTLS' *_t variable type names in this source code, + * since they were not present in 1.0.X. + */ + +#include "curl_setup.h" + +#ifdef USE_GNUTLS + +#include +#include +#include + +#ifdef USE_GNUTLS_NETTLE +#include +#include +#include +#else +#include +#endif + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "gtls.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "warnless.h" +#include "x509asn1.h" +#include "multiif.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* Enable GnuTLS debugging by defining GTLSDEBUG */ +/*#define GTLSDEBUG */ + +#ifdef GTLSDEBUG +static void tls_log_func(int level, const char *str) +{ + fprintf(stderr, "|<%d>| %s", level, str); +} +#endif +static bool gtls_inited = FALSE; + +#if defined(GNUTLS_VERSION_NUMBER) +# if (GNUTLS_VERSION_NUMBER >= 0x020c00) +# undef gnutls_transport_set_lowat +# define gnutls_transport_set_lowat(A,B) Curl_nop_stmt +# define USE_GNUTLS_PRIORITY_SET_DIRECT 1 +# endif +# if (GNUTLS_VERSION_NUMBER >= 0x020c03) +# define GNUTLS_MAPS_WINSOCK_ERRORS 1 +# endif + +# if HAVE_GNUTLS_ALPN_SET_PROTOCOLS +# define HAS_ALPN +# endif + +# if HAVE_GNUTLS_OCSP_REQ_INIT +# define HAS_OCSP +# endif + +# if (GNUTLS_VERSION_NUMBER >= 0x030306) +# define HAS_CAPATH +# endif +#endif + +#if (GNUTLS_VERSION_NUMBER >= 0x030603) +#define HAS_TLS13 +#endif + +#ifdef HAS_OCSP +# include +#endif + +struct ssl_backend_data { + gnutls_session_t session; + gnutls_certificate_credentials_t cred; +#ifdef USE_TLS_SRP + gnutls_srp_client_credentials_t srp_client_cred; +#endif +}; + +#define BACKEND connssl->backend + +/* + * Custom push and pull callback functions used by GNU TLS to read and write + * to the socket. These functions are simple wrappers to send() and recv() + * (although here using the sread/swrite macros as defined by + * curl_setup_once.h). + * We use custom functions rather than the GNU TLS defaults because it allows + * us to get specific about the fourth "flags" argument, and to use arbitrary + * private data with gnutls_transport_set_ptr if we wish. + * + * When these custom push and pull callbacks fail, GNU TLS checks its own + * session-specific error variable, and when not set also its own global + * errno variable, in order to take appropriate action. GNU TLS does not + * require that the transport is actually a socket. This implies that for + * Windows builds these callbacks should ideally set the session-specific + * error variable using function gnutls_transport_set_errno or as a last + * resort global errno variable using gnutls_transport_set_global_errno, + * with a transport agnostic error value. This implies that some winsock + * error translation must take place in these callbacks. + * + * Paragraph above applies to GNU TLS versions older than 2.12.3, since + * this version GNU TLS does its own internal winsock error translation + * using system_errno() function. + */ + +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) +# define gtls_EINTR 4 +# define gtls_EIO 5 +# define gtls_EAGAIN 11 +static int gtls_mapped_sockerrno(void) +{ + switch(SOCKERRNO) { + case WSAEWOULDBLOCK: + return gtls_EAGAIN; + case WSAEINTR: + return gtls_EINTR; + default: + break; + } + return gtls_EIO; +} +#endif + +static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len) +{ + curl_socket_t sock = *(curl_socket_t *)s; + ssize_t ret = swrite(sock, buf, len); +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) + if(ret < 0) + gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); +#endif + return ret; +} + +static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) +{ + curl_socket_t sock = *(curl_socket_t *)s; + ssize_t ret = sread(sock, buf, len); +#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) + if(ret < 0) + gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); +#endif + return ret; +} + +static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len) +{ + return gnutls_record_send((gnutls_session_t) s, buf, len); +} + +static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len) +{ + return gnutls_record_recv((gnutls_session_t) s, buf, len); +} + +/* Curl_gtls_init() + * + * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that + * are not thread-safe and thus this function itself is not thread-safe and + * must only be called from within curl_global_init() to keep the thread + * situation under control! + */ +static int Curl_gtls_init(void) +{ + int ret = 1; + if(!gtls_inited) { + ret = gnutls_global_init()?0:1; +#ifdef GTLSDEBUG + gnutls_global_set_log_function(tls_log_func); + gnutls_global_set_log_level(2); +#endif + gtls_inited = TRUE; + } + return ret; +} + +static void Curl_gtls_cleanup(void) +{ + if(gtls_inited) { + gnutls_global_deinit(); + gtls_inited = FALSE; + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void showtime(struct Curl_easy *data, + const char *text, + time_t stamp) +{ + struct tm buffer; + const struct tm *tm = &buffer; + char str[96]; + CURLcode result = Curl_gmtime(stamp, &buffer); + if(result) + return; + + msnprintf(str, + sizeof(str), + "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT", + text, + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + infof(data, "%s\n", str); +} +#endif + +static gnutls_datum_t load_file(const char *file) +{ + FILE *f; + gnutls_datum_t loaded_file = { NULL, 0 }; + long filelen; + void *ptr; + + f = fopen(file, "rb"); + if(!f) + return loaded_file; + if(fseek(f, 0, SEEK_END) != 0 + || (filelen = ftell(f)) < 0 + || fseek(f, 0, SEEK_SET) != 0 + || !(ptr = malloc((size_t)filelen))) + goto out; + if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) { + free(ptr); + goto out; + } + + loaded_file.data = ptr; + loaded_file.size = (unsigned int)filelen; +out: + fclose(f); + return loaded_file; +} + +static void unload_file(gnutls_datum_t data) +{ + free(data.data); +} + + +/* this function does a SSL/TLS (re-)handshake */ +static CURLcode handshake(struct connectdata *conn, + int sockindex, + bool duringconnect, + bool nonblocking) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + gnutls_session_t session = BACKEND->session; + curl_socket_t sockfd = conn->sock[sockindex]; + + for(;;) { + time_t timeout_ms; + int rc; + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, duringconnect); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + int what; + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0: + timeout_ms?timeout_ms:1000); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) + return CURLE_OK; + else if(timeout_ms) { + /* timeout */ + failf(data, "SSL connection timeout at %ld", (long)timeout_ms); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + rc = gnutls_handshake(session); + + if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) { + connssl->connecting_state = + gnutls_record_get_direction(session)? + ssl_connect_2_writing:ssl_connect_2_reading; + continue; + } + else if((rc < 0) && !gnutls_error_is_fatal(rc)) { + const char *strerr = NULL; + + if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { + int alert = gnutls_alert_get(session); + strerr = gnutls_alert_get_name(alert); + } + + if(strerr == NULL) + strerr = gnutls_strerror(rc); + + infof(data, "gnutls_handshake() warning: %s\n", strerr); + continue; + } + else if(rc < 0) { + const char *strerr = NULL; + + if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { + int alert = gnutls_alert_get(session); + strerr = gnutls_alert_get_name(alert); + } + + if(strerr == NULL) + strerr = gnutls_strerror(rc); + + failf(data, "gnutls_handshake() failed: %s", strerr); + return CURLE_SSL_CONNECT_ERROR; + } + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + return CURLE_OK; + } +} + +static gnutls_x509_crt_fmt_t do_file_type(const char *type) +{ + if(!type || !type[0]) + return GNUTLS_X509_FMT_PEM; + if(strcasecompare(type, "PEM")) + return GNUTLS_X509_FMT_PEM; + if(strcasecompare(type, "DER")) + return GNUTLS_X509_FMT_DER; + return -1; +} + +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT +static CURLcode +set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long i = ssl_version; + long protocol_priority_idx = 0; + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: +#ifdef HAS_TLS13 + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3; +#endif + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + for(; i <= (ssl_version_max >> 16) && + protocol_priority_idx < list_size; ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0; + break; + case CURL_SSLVERSION_TLSv1_1: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1; + break; + case CURL_SSLVERSION_TLSv1_2: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2; + break; + case CURL_SSLVERSION_TLSv1_3: +#ifdef HAS_TLS13 + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_3; + break; +#else + failf(data, "GnuTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; +#endif + } + } + return CURLE_OK; +} +#else +#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" +/* If GnuTLS was compiled without support for SRP it will error out if SRP is + requested in the priority string, so treat it specially + */ +#define GNUTLS_SRP "+SRP" + +static CURLcode +set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + + if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) { + ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT; + } + switch(ssl_version | ssl_version_max) { + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3: +#ifdef HAS_TLS13 + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.3:" GNUTLS_SRP; + return CURLE_OK; +#else + failf(data, "GnuTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; +#endif + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:+VERS-TLS1.2:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + return CURLE_OK; + } + + failf(data, "GnuTLS: cannot set ssl protocol"); + return CURLE_SSL_CONNECT_ERROR; +} +#endif + +static CURLcode +gtls_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned int init_flags; + gnutls_session_t session; + int rc; + bool sni = TRUE; /* default is SNI enabled */ + void *transport_ptr = NULL; + gnutls_push_func gnutls_transport_push = NULL; + gnutls_pull_func gnutls_transport_pull = NULL; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT + static const int cipher_priority[] = { + /* These two ciphers were added to GnuTLS as late as ver. 3.0.1, + but this code path is only ever used for ver. < 2.12.0. + GNUTLS_CIPHER_AES_128_GCM, + GNUTLS_CIPHER_AES_256_GCM, + */ + GNUTLS_CIPHER_AES_128_CBC, + GNUTLS_CIPHER_AES_256_CBC, + GNUTLS_CIPHER_CAMELLIA_128_CBC, + GNUTLS_CIPHER_CAMELLIA_256_CBC, + GNUTLS_CIPHER_3DES_CBC, + }; + static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; + int protocol_priority[] = { 0, 0, 0, 0 }; +#else + const char *prioritylist; + const char *err = NULL; +#endif + + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + if(connssl->state == ssl_connection_complete) + /* to make us tolerant against being called more than once for the + same connection */ + return CURLE_OK; + + if(!gtls_inited) + Curl_gtls_init(); + + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) + sni = FALSE; /* SSLv3 has no SNI */ + + /* allocate a cred struct */ + rc = gnutls_certificate_allocate_credentials(&BACKEND->cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef USE_TLS_SRP + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { + infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username)); + + rc = gnutls_srp_allocate_client_credentials( + &BACKEND->srp_client_cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_srp_allocate_client_cred() failed: %s", + gnutls_strerror(rc)); + return CURLE_OUT_OF_MEMORY; + } + + rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred, + SSL_SET_OPTION(username), + SSL_SET_OPTION(password)); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_srp_set_client_cred() failed: %s", + gnutls_strerror(rc)); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } +#endif + + if(SSL_CONN_CONFIG(CAfile)) { + /* set the trusted CA cert bundle file */ + gnutls_certificate_set_verify_flags(BACKEND->cred, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); + + rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred, + SSL_CONN_CONFIG(CAfile), + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)\n", + SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc)); + if(SSL_CONN_CONFIG(verifypeer)) + return CURLE_SSL_CACERT_BADFILE; + } + else + infof(data, "found %d certificates in %s\n", rc, + SSL_CONN_CONFIG(CAfile)); + } + +#ifdef HAS_CAPATH + if(SSL_CONN_CONFIG(CApath)) { + /* set the trusted CA cert directory */ + rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred, + SSL_CONN_CONFIG(CApath), + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)\n", + SSL_CONN_CONFIG(CApath), gnutls_strerror(rc)); + if(SSL_CONN_CONFIG(verifypeer)) + return CURLE_SSL_CACERT_BADFILE; + } + else + infof(data, "found %d certificates in %s\n", + rc, SSL_CONN_CONFIG(CApath)); + } +#endif + +#ifdef CURL_CA_FALLBACK + /* use system ca certificate store as fallback */ + if(SSL_CONN_CONFIG(verifypeer) && + !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) { + gnutls_certificate_set_x509_system_trust(BACKEND->cred); + } +#endif + + if(SSL_SET_OPTION(CRLfile)) { + /* set the CRL list file */ + rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred, + SSL_SET_OPTION(CRLfile), + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + failf(data, "error reading crl file %s (%s)", + SSL_SET_OPTION(CRLfile), gnutls_strerror(rc)); + return CURLE_SSL_CRL_BADFILE; + } + else + infof(data, "found %d CRL in %s\n", + rc, SSL_SET_OPTION(CRLfile)); + } + + /* Initialize TLS session as a client */ + init_flags = GNUTLS_CLIENT; + +#if defined(GNUTLS_NO_TICKETS) + /* Disable TLS session tickets */ + init_flags |= GNUTLS_NO_TICKETS; +#endif + + rc = gnutls_init(&BACKEND->session, init_flags); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_init() failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + + /* convenient assign */ + session = BACKEND->session; + + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && +#endif + sni && + (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, + strlen(hostname)) < 0)) + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + + /* Use default priorities */ + rc = gnutls_set_default_priority(session); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT + rc = gnutls_cipher_set_priority(session, cipher_priority); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + + /* Sets the priority on the certificate types supported by gnutls. Priority + is higher for types specified before others. After specifying the types + you want, you must append a 0. */ + rc = gnutls_certificate_type_set_priority(session, cert_type_priority); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; + + if(SSL_CONN_CONFIG(cipher_list) != NULL) { + failf(data, "can't pass a custom cipher list to older GnuTLS" + " versions"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_SSLv3: + protocol_priority[0] = GNUTLS_SSL3; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + protocol_priority[0] = GNUTLS_TLS1_0; + protocol_priority[1] = GNUTLS_TLS1_1; + protocol_priority[2] = GNUTLS_TLS1_2; +#ifdef HAS_TLS13 + protocol_priority[3] = GNUTLS_TLS1_3; +#endif + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(protocol_priority, + sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv2: + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + rc = gnutls_protocol_set_priority(session, protocol_priority); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "Did you pass a valid GnuTLS cipher list?"); + return CURLE_SSL_CONNECT_ERROR; + } + +#else + /* Ensure +SRP comes at the *end* of all relevant strings so that it can be + * removed if a run-time error indicates that SRP is not supported by this + * GnuTLS version */ + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_SSLv3: + prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" +#ifdef HAS_TLS13 + "+VERS-TLS1.3:" +#endif + GNUTLS_SRP; + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(&prioritylist, conn); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv2: + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + rc = gnutls_priority_set_direct(session, prioritylist, &err); + if((rc == GNUTLS_E_INVALID_REQUEST) && err) { + if(!strcmp(err, GNUTLS_SRP)) { + /* This GnuTLS was probably compiled without support for SRP. + * Note that fact and try again without it. */ + int validprioritylen = curlx_uztosi(err - prioritylist); + char *prioritycopy = strdup(prioritylist); + if(!prioritycopy) + return CURLE_OUT_OF_MEMORY; + + infof(data, "This GnuTLS does not support SRP\n"); + if(validprioritylen) + /* Remove the :+SRP */ + prioritycopy[validprioritylen - 1] = 0; + rc = gnutls_priority_set_direct(session, prioritycopy, &err); + free(prioritycopy); + } + } + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "Error %d setting GnuTLS cipher list starting with %s", + rc, err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + int cur = 0; + gnutls_datum_t protocols[2]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; + protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; + cur++; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1; + protocols[cur].size = ALPN_HTTP_1_1_LENGTH; + cur++; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + gnutls_alpn_set_protocols(session, protocols, cur, 0); + } +#endif + + if(SSL_SET_OPTION(cert)) { + if(SSL_SET_OPTION(key_passwd)) { +#if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 + const unsigned int supported_key_encryption_algorithms = + GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR | + GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES | + GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 | + GNUTLS_PKCS_USE_PBES2_AES_256; + rc = gnutls_certificate_set_x509_key_file2( + BACKEND->cred, + SSL_SET_OPTION(cert), + SSL_SET_OPTION(key) ? + SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), + do_file_type(SSL_SET_OPTION(cert_type)), + SSL_SET_OPTION(key_passwd), + supported_key_encryption_algorithms); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, + "error reading X.509 potentially-encrypted key file: %s", + gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } +#else + failf(data, "gnutls lacks support for encrypted key files"); + return CURLE_SSL_CONNECT_ERROR; +#endif + } + else { + if(gnutls_certificate_set_x509_key_file( + BACKEND->cred, + SSL_SET_OPTION(cert), + SSL_SET_OPTION(key) ? + SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), + do_file_type(SSL_SET_OPTION(cert_type)) ) != + GNUTLS_E_SUCCESS) { + failf(data, "error reading X.509 key or certificate file"); + return CURLE_SSL_CONNECT_ERROR; + } + } + } + +#ifdef USE_TLS_SRP + /* put the credentials to the current session */ + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { + rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, + BACKEND->srp_client_cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + } + else +#endif + { + rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, + BACKEND->cred); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); + return CURLE_SSL_CONNECT_ERROR; + } + } + + if(conn->proxy_ssl[sockindex].use) { + transport_ptr = conn->proxy_ssl[sockindex].backend->session; + gnutls_transport_push = Curl_gtls_push_ssl; + gnutls_transport_pull = Curl_gtls_pull_ssl; + } + else { + /* file descriptor for the socket */ + transport_ptr = &conn->sock[sockindex]; + gnutls_transport_push = Curl_gtls_push; + gnutls_transport_pull = Curl_gtls_pull; + } + + /* set the connection handle */ + gnutls_transport_set_ptr(session, transport_ptr); + + /* register callback functions to send and receive data. */ + gnutls_transport_set_push_function(session, gnutls_transport_push); + gnutls_transport_set_pull_function(session, gnutls_transport_pull); + + /* lowat must be set to zero when using custom push and pull functions. */ + gnutls_transport_set_lowat(session, 0); + +#ifdef HAS_OCSP + if(SSL_CONN_CONFIG(verifystatus)) { + rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif + + /* This might be a reconnect, so we check for a session ID in the cache + to speed up things */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid; + size_t ssl_idsize; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) { + /* we got a session id, use it! */ + gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); + + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + return CURLE_OK; +} + +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, + gnutls_x509_crt_t cert, + const char *pinnedpubkey) +{ + /* Scratch */ + size_t len1 = 0, len2 = 0; + unsigned char *buff1 = NULL; + + gnutls_pubkey_t key = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(NULL == pinnedpubkey) + return CURLE_OK; + + if(NULL == cert) + return result; + + do { + int ret; + + /* Begin Gyrations to get the public key */ + gnutls_pubkey_init(&key); + + ret = gnutls_pubkey_import_x509(key, cert, 0); + if(ret < 0) + break; /* failed */ + + ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1); + if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0) + break; /* failed */ + + buff1 = malloc(len1); + if(NULL == buff1) + break; /* failed */ + + len2 = len1; + + ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2); + if(ret < 0 || len1 != len2) + break; /* failed */ + + /* End Gyrations */ + + /* The one good exit point */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1); + } while(0); + + if(NULL != key) + gnutls_pubkey_deinit(key); + + Curl_safefree(buff1); + + return result; +} + +static Curl_recv gtls_recv; +static Curl_send gtls_send; + +static CURLcode +gtls_connect_step3(struct connectdata *conn, + int sockindex) +{ + unsigned int cert_list_size; + const gnutls_datum_t *chainp; + unsigned int verify_status = 0; + gnutls_x509_crt_t x509_cert, x509_issuer; + gnutls_datum_t issuerp; + char certbuf[256] = ""; /* big enough? */ + size_t size; + time_t certclock; + const char *ptr; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + gnutls_session_t session = BACKEND->session; + int rc; +#ifdef HAS_ALPN + gnutls_datum_t proto; +#endif + CURLcode result = CURLE_OK; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + unsigned int algo; + unsigned int bits; + gnutls_protocol_t version = gnutls_protocol_get_version(session); +#endif + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */ + ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session), + gnutls_cipher_get(session), + gnutls_mac_get(session)); + + infof(data, "SSL connection using %s / %s\n", + gnutls_protocol_get_name(version), ptr); + + /* This function will return the peer's raw certificate (chain) as sent by + the peer. These certificates are in raw format (DER encoded for + X.509). In case of a X.509 then a certificate list may be present. The + first certificate in the list is the peer's certificate, following the + issuer's certificate, then the issuer's issuer etc. */ + + chainp = gnutls_certificate_get_peers(session, &cert_list_size); + if(!chainp) { + if(SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost) || + SSL_SET_OPTION(issuercert)) { +#ifdef USE_TLS_SRP + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL + && !SSL_CONN_CONFIG(verifypeer) + && gnutls_cipher_get(session)) { + /* no peer cert, but auth is ok if we have SRP user and cipher and no + peer verify */ + } + else { +#endif + failf(data, "failed to get server cert"); + return CURLE_PEER_FAILED_VERIFICATION; +#ifdef USE_TLS_SRP + } +#endif + } + infof(data, "\t common name: WARNING couldn't obtain\n"); + } + + if(data->set.ssl.certinfo && chainp) { + unsigned int i; + + result = Curl_ssl_init_certinfo(data, cert_list_size); + if(result) + return result; + + for(i = 0; i < cert_list_size; i++) { + const char *beg = (const char *) chainp[i].data; + const char *end = beg + chainp[i].size; + + result = Curl_extract_certinfo(conn, i, beg, end); + if(result) + return result; + } + } + + if(SSL_CONN_CONFIG(verifypeer)) { + /* This function will try to verify the peer's certificate and return its + status (trusted, invalid etc.). The value of status should be one or + more of the gnutls_certificate_status_t enumerated elements bitwise + or'd. To avoid denial of service attacks some default upper limits + regarding the certificate key size and chain size are set. To override + them use gnutls_certificate_set_verify_limits(). */ + + rc = gnutls_certificate_verify_peers2(session, &verify_status); + if(rc < 0) { + failf(data, "server cert verify failed: %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + + /* verify_status is a bitmask of gnutls_certificate_status bits */ + if(verify_status & GNUTLS_CERT_INVALID) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server certificate verification failed. CAfile: %s " + "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): + "none", + SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none"); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t server certificate verification FAILED\n"); + } + else + infof(data, "\t server certificate verification OK\n"); + } + else + infof(data, "\t server certificate verification SKIPPED\n"); + +#ifdef HAS_OCSP + if(SSL_CONN_CONFIG(verifystatus)) { + if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { + gnutls_datum_t status_request; + gnutls_ocsp_resp_t ocsp_resp; + + gnutls_ocsp_cert_status_t status; + gnutls_x509_crl_reason_t reason; + + rc = gnutls_ocsp_status_request_get(session, &status_request); + + infof(data, "\t server certificate status verification FAILED\n"); + + if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { + failf(data, "No OCSP response received"); + return CURLE_SSL_INVALIDCERTSTATUS; + } + + if(rc < 0) { + failf(data, "Invalid OCSP response received"); + return CURLE_SSL_INVALIDCERTSTATUS; + } + + gnutls_ocsp_resp_init(&ocsp_resp); + + rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request); + if(rc < 0) { + failf(data, "Invalid OCSP response received"); + return CURLE_SSL_INVALIDCERTSTATUS; + } + + (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL, + &status, NULL, NULL, NULL, &reason); + + switch(status) { + case GNUTLS_OCSP_CERT_GOOD: + break; + + case GNUTLS_OCSP_CERT_REVOKED: { + const char *crl_reason; + + switch(reason) { + default: + case GNUTLS_X509_CRLREASON_UNSPECIFIED: + crl_reason = "unspecified reason"; + break; + + case GNUTLS_X509_CRLREASON_KEYCOMPROMISE: + crl_reason = "private key compromised"; + break; + + case GNUTLS_X509_CRLREASON_CACOMPROMISE: + crl_reason = "CA compromised"; + break; + + case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED: + crl_reason = "affiliation has changed"; + break; + + case GNUTLS_X509_CRLREASON_SUPERSEDED: + crl_reason = "certificate superseded"; + break; + + case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION: + crl_reason = "operation has ceased"; + break; + + case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD: + crl_reason = "certificate is on hold"; + break; + + case GNUTLS_X509_CRLREASON_REMOVEFROMCRL: + crl_reason = "will be removed from delta CRL"; + break; + + case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN: + crl_reason = "privilege withdrawn"; + break; + + case GNUTLS_X509_CRLREASON_AACOMPROMISE: + crl_reason = "AA compromised"; + break; + } + + failf(data, "Server certificate was revoked: %s", crl_reason); + break; + } + + default: + case GNUTLS_OCSP_CERT_UNKNOWN: + failf(data, "Server certificate status is unknown"); + break; + } + + gnutls_ocsp_resp_deinit(ocsp_resp); + + return CURLE_SSL_INVALIDCERTSTATUS; + } + else + infof(data, "\t server certificate status verification OK\n"); + } + else + infof(data, "\t server certificate status verification SKIPPED\n"); +#endif + + /* initialize an X.509 certificate structure. */ + gnutls_x509_crt_init(&x509_cert); + + if(chainp) + /* convert the given DER or PEM encoded Certificate to the native + gnutls_x509_crt_t format */ + gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); + + if(SSL_SET_OPTION(issuercert)) { + gnutls_x509_crt_init(&x509_issuer); + issuerp = load_file(SSL_SET_OPTION(issuercert)); + gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); + rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer); + gnutls_x509_crt_deinit(x509_issuer); + unload_file(issuerp); + if(rc <= 0) { + failf(data, "server certificate issuer check failed (IssuerCert: %s)", + SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_ISSUER_ERROR; + } + infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n", + SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); + } + + size = sizeof(certbuf); + rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME, + 0, /* the first and only one */ + FALSE, + certbuf, + &size); + if(rc) { + infof(data, "error fetching CN from cert:%s\n", + gnutls_strerror(rc)); + } + + /* This function will check if the given certificate's subject matches the + given hostname. This is a basic implementation of the matching described + in RFC2818 (HTTPS), which takes into account wildcards, and the subject + alternative name PKIX extension. Returns non zero on success, and zero on + failure. */ + rc = gnutls_x509_crt_check_hostname(x509_cert, hostname); +#if GNUTLS_VERSION_NUMBER < 0x030306 + /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP + addresses. */ + if(!rc) { +#ifdef ENABLE_IPV6 + #define use_addr in6_addr +#else + #define use_addr in_addr +#endif + unsigned char addrbuf[sizeof(struct use_addr)]; + size_t addrlen = 0; + + if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0) + addrlen = 4; +#ifdef ENABLE_IPV6 + else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0) + addrlen = 16; +#endif + + if(addrlen) { + unsigned char certaddr[sizeof(struct use_addr)]; + int i; + + for(i = 0; ; i++) { + size_t certaddrlen = sizeof(certaddr); + int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr, + &certaddrlen, NULL); + /* If this happens, it wasn't an IP address. */ + if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) + continue; + if(ret < 0) + break; + if(ret != GNUTLS_SAN_IPADDRESS) + continue; + if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) { + rc = 1; + break; + } + } + } + } +#endif + if(!rc) { + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + + if(SSL_CONN_CONFIG(verifyhost)) { + failf(data, "SSL: certificate subject name (%s) does not match " + "target host name '%s'", certbuf, dispname); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t common name: %s (does not match '%s')\n", + certbuf, dispname); + } + else + infof(data, "\t common name: %s (matched)\n", certbuf); + + /* Check for time-based validity */ + certclock = gnutls_x509_crt_get_expiration_time(x509_cert); + + if(certclock == (time_t)-1) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server cert expiration date verify failed"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_CONNECT_ERROR; + } + else + infof(data, "\t server certificate expiration date verify FAILED\n"); + } + else { + if(certclock < time(NULL)) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server certificate expiration date has passed."); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t server certificate expiration date FAILED\n"); + } + else + infof(data, "\t server certificate expiration date OK\n"); + } + + certclock = gnutls_x509_crt_get_activation_time(x509_cert); + + if(certclock == (time_t)-1) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server cert activation date verify failed"); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_SSL_CONNECT_ERROR; + } + else + infof(data, "\t server certificate activation date verify FAILED\n"); + } + else { + if(certclock > time(NULL)) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "server certificate not activated yet."); + gnutls_x509_crt_deinit(x509_cert); + return CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, "\t server certificate activation date FAILED\n"); + } + else + infof(data, "\t server certificate activation date OK\n"); + } + + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + if(ptr) { + result = pkp_pin_peer_pubkey(data, x509_cert, ptr); + if(result != CURLE_OK) { + failf(data, "SSL: public key does not match pinned public key!"); + gnutls_x509_crt_deinit(x509_cert); + return result; + } + } + + /* Show: + + - subject + - start date + - expire date + - common name + - issuer + + */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + /* public key algorithm's parameters */ + algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); + infof(data, "\t certificate public key: %s\n", + gnutls_pk_algorithm_get_name(algo)); + + /* version of the X.509 certificate. */ + infof(data, "\t certificate version: #%d\n", + gnutls_x509_crt_get_version(x509_cert)); + + + size = sizeof(certbuf); + gnutls_x509_crt_get_dn(x509_cert, certbuf, &size); + infof(data, "\t subject: %s\n", certbuf); + + certclock = gnutls_x509_crt_get_activation_time(x509_cert); + showtime(data, "start date", certclock); + + certclock = gnutls_x509_crt_get_expiration_time(x509_cert); + showtime(data, "expire date", certclock); + + size = sizeof(certbuf); + gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); + infof(data, "\t issuer: %s\n", certbuf); +#endif + + gnutls_x509_crt_deinit(x509_cert); + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + rc = gnutls_alpn_get_selected_protocol(session, &proto); + if(rc == 0) { + infof(data, "ALPN, server accepted to use %.*s\n", proto.size, + proto.data); + +#ifdef USE_NGHTTP2 + if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(proto.size == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + conn->ssl[sockindex].state = ssl_connection_complete; + conn->recv[sockindex] = gtls_recv; + conn->send[sockindex] = gtls_send; + + if(SSL_SET_OPTION(primary.sessionid)) { + /* we always unconditionally get the session id here, as even if we + already got it from the cache and asked to use it in the connection, it + might've been rejected and then a new one is in use now and we need to + detect that. */ + void *connect_sessionid; + size_t connect_idsize = 0; + + /* get the session ID data size */ + gnutls_session_get_data(session, NULL, &connect_idsize); + connect_sessionid = malloc(connect_idsize); /* get a buffer for it */ + + if(connect_sessionid) { + bool incache; + void *ssl_sessionid; + + /* extract session ID to the allocated buffer */ + gnutls_session_get_data(session, connect_sessionid, &connect_idsize); + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, + sockindex)); + if(incache) { + /* there was one before in the cache, so instead of risking that the + previous one was rejected, we just kill that and store the new */ + Curl_ssl_delsessionid(conn, ssl_sessionid); + } + + /* store this session id */ + result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize, + sockindex); + Curl_ssl_sessionid_unlock(conn); + if(result) { + free(connect_sessionid); + result = CURLE_OUT_OF_MEMORY; + } + } + else + result = CURLE_OUT_OF_MEMORY; + } + + return result; +} + + +/* + * This function is called after the TCP connect has completed. Setup the TLS + * layer and do all necessary magic. + */ +/* We use connssl->connecting_state to keep track of the connection status; + there are three states: 'ssl_connect_1' (not started yet or complete), + 'ssl_connect_2_reading' (waiting for data from server), and + 'ssl_connect_2_writing' (waiting to be able to write). + */ +static CURLcode +gtls_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + int rc; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + /* Initiate the connection, if not already done */ + if(ssl_connect_1 == connssl->connecting_state) { + rc = gtls_connect_step1(conn, sockindex); + if(rc) + return rc; + } + + rc = handshake(conn, sockindex, TRUE, nonblocking); + if(rc) + /* handshake() sets its own error message with failf() */ + return rc; + + /* Finish connecting once the handshake is done */ + if(ssl_connect_1 == connssl->connecting_state) { + rc = gtls_connect_step3(conn, sockindex); + if(rc) + return rc; + } + + *done = ssl_connect_1 == connssl->connecting_state; + + return CURLE_OK; +} + +static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return gtls_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = gtls_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static bool Curl_gtls_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + bool res = FALSE; + if(BACKEND->session && + 0 != gnutls_record_check_pending(BACKEND->session)) + res = TRUE; + + connssl = &conn->proxy_ssl[connindex]; + if(BACKEND->session && + 0 != gnutls_record_check_pending(BACKEND->session)) + res = TRUE; + + return res; +} + +static ssize_t gtls_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ssize_t rc = gnutls_record_send(BACKEND->session, mem, len); + + if(rc < 0) { + *curlcode = (rc == GNUTLS_E_AGAIN) + ? CURLE_AGAIN + : CURLE_SEND_ERROR; + + rc = -1; + } + + return rc; +} + +static void close_one(struct ssl_connect_data *connssl) +{ + if(BACKEND->session) { + gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR); + gnutls_deinit(BACKEND->session); + BACKEND->session = NULL; + } + if(BACKEND->cred) { + gnutls_certificate_free_credentials(BACKEND->cred); + BACKEND->cred = NULL; + } +#ifdef USE_TLS_SRP + if(BACKEND->srp_client_cred) { + gnutls_srp_free_client_credentials(BACKEND->srp_client_cred); + BACKEND->srp_client_cred = NULL; + } +#endif +} + +static void Curl_gtls_close(struct connectdata *conn, int sockindex) +{ + close_one(&conn->ssl[sockindex]); + close_one(&conn->proxy_ssl[sockindex]); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int retval = 0; + struct Curl_easy *data = conn->data; + +#ifndef CURL_DISABLE_FTP + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR); +#endif + + if(BACKEND->session) { + ssize_t result; + bool done = FALSE; + char buf[120]; + + while(!done) { + int what = SOCKET_READABLE(conn->sock[sockindex], + SSL_SHUTDOWN_TIMEOUT); + if(what > 0) { + /* Something to read, let's do it and hope that it is the close + notify alert from the server */ + result = gnutls_record_recv(BACKEND->session, + buf, sizeof(buf)); + switch(result) { + case 0: + /* This is the expected response. There was no data but only + the close notify alert */ + done = TRUE; + break; + case GNUTLS_E_AGAIN: + case GNUTLS_E_INTERRUPTED: + infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n"); + break; + default: + retval = -1; + done = TRUE; + break; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + done = TRUE; + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + done = TRUE; + } + } + gnutls_deinit(BACKEND->session); + } + gnutls_certificate_free_credentials(BACKEND->cred); + +#ifdef USE_TLS_SRP + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL) + gnutls_srp_free_client_credentials(BACKEND->srp_client_cred); +#endif + + BACKEND->cred = NULL; + BACKEND->session = NULL; + + return retval; +} + +static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + ssize_t ret; + + ret = gnutls_record_recv(BACKEND->session, buf, buffersize); + if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { + *curlcode = CURLE_AGAIN; + return -1; + } + + if(ret == GNUTLS_E_REHANDSHAKE) { + /* BLOCKING call, this is bad but a work-around for now. Fixing this "the + proper way" takes a whole lot of work. */ + CURLcode result = handshake(conn, num, FALSE, FALSE); + if(result) + /* handshake() writes error message on its own */ + *curlcode = result; + else + *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */ + return -1; + } + + if(ret < 0) { + failf(conn->data, "GnuTLS recv error (%d): %s", + + (int)ret, gnutls_strerror((int)ret)); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + + return ret; +} + +static void Curl_gtls_session_free(void *ptr) +{ + free(ptr); +} + +static size_t Curl_gtls_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); +} + +#ifndef USE_GNUTLS_NETTLE +static int Curl_gtls_seed(struct Curl_easy *data) +{ + /* we have the "SSL is seeded" boolean static to prevent multiple + time-consuming seedings in vain */ + static bool ssl_seeded = FALSE; + + /* Quickly add a bit of entropy */ + gcry_fast_random_poll(); + + if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || + data->set.str[STRING_SSL_EGDSOCKET]) { + ssl_seeded = TRUE; + } + return 0; +} +#endif + +/* data might be NULL! */ +static CURLcode Curl_gtls_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ +#if defined(USE_GNUTLS_NETTLE) + int rc; + (void)data; + rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length); + return rc?CURLE_FAILED_INIT:CURLE_OK; +#elif defined(USE_GNUTLS) + if(data) + Curl_gtls_seed(data); /* Initiate the seed if not already done */ + gcry_randomize(entropy, length, GCRY_STRONG_RANDOM); +#endif + return CURLE_OK; +} + +static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ +#if defined(USE_GNUTLS_NETTLE) + struct md5_ctx MD5pw; + md5_init(&MD5pw); + md5_update(&MD5pw, (unsigned int)tmplen, tmp); + md5_digest(&MD5pw, (unsigned int)md5len, md5sum); +#elif defined(USE_GNUTLS) + gcry_md_hd_t MD5pw; + gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); + gcry_md_write(MD5pw, tmp, tmplen); + memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len); + gcry_md_close(MD5pw); +#endif + return CURLE_OK; +} + +static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ +#if defined(USE_GNUTLS_NETTLE) + struct sha256_ctx SHA256pw; + sha256_init(&SHA256pw); + sha256_update(&SHA256pw, (unsigned int)tmplen, tmp); + sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum); +#elif defined(USE_GNUTLS) + gcry_md_hd_t SHA256pw; + gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0); + gcry_md_write(SHA256pw, tmp, tmplen); + memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len); + gcry_md_close(SHA256pw); +#endif + return CURLE_OK; +} + +static bool Curl_gtls_cert_status_request(void) +{ +#ifdef HAS_OCSP + return TRUE; +#else + return FALSE; +#endif +} + +static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->session; +} + +const struct Curl_ssl Curl_ssl_gnutls = { + { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY | + SSLSUPP_HTTPS_PROXY, + + sizeof(struct ssl_backend_data), + + Curl_gtls_init, /* init */ + Curl_gtls_cleanup, /* cleanup */ + Curl_gtls_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_gtls_shutdown, /* shutdown */ + Curl_gtls_data_pending, /* data_pending */ + Curl_gtls_random, /* random */ + Curl_gtls_cert_status_request, /* cert_status_request */ + Curl_gtls_connect, /* connect */ + Curl_gtls_connect_nonblocking, /* connect_nonblocking */ + Curl_gtls_get_internals, /* get_internals */ + Curl_gtls_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_gtls_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_gtls_md5sum, /* md5sum */ + Curl_gtls_sha256sum /* sha256sum */ +}; + +#endif /* USE_GNUTLS */ diff --git a/libcurl/lib/vtls/gtls.h b/libcurl/lib/vtls/gtls.h new file mode 100644 index 0000000..780fc10 --- /dev/null +++ b/libcurl/lib/vtls/gtls.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_GTLS_H +#define HEADER_CURL_GTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_GNUTLS + +#include "urldata.h" + +extern const struct Curl_ssl Curl_ssl_gnutls; + +#endif /* USE_GNUTLS */ +#endif /* HEADER_CURL_GTLS_H */ diff --git a/libcurl/lib/vtls/mbedtls.c b/libcurl/lib/vtls/mbedtls.c new file mode 100644 index 0000000..63d1f4c --- /dev/null +++ b/libcurl/lib/vtls/mbedtls.c @@ -0,0 +1,1086 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2011, Hoi-Ho Chan, + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "curl_setup.h" + +#ifdef USE_MBEDTLS + +#include +#if MBEDTLS_VERSION_NUMBER >= 0x02040000 +#include +#else +#include +#endif +#include +#include +#include + +#include +#include +#include +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "mbedtls.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "multiif.h" +#include "polarssl_threadlock.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +struct ssl_backend_data { + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + mbedtls_ssl_context ssl; + int server_fd; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + mbedtls_x509_crl crl; + mbedtls_pk_context pk; + mbedtls_ssl_config config; + const char *protocols[3]; +}; + +#define BACKEND connssl->backend + +/* apply threading? */ +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +#define THREADING_SUPPORT +#endif + +#if defined(THREADING_SUPPORT) +static mbedtls_entropy_context ts_entropy; + +static int entropy_init_initialized = 0; + +/* start of entropy_init_mutex() */ +static void entropy_init_mutex(mbedtls_entropy_context *ctx) +{ + /* lock 0 = entropy_init_mutex() */ + Curl_polarsslthreadlock_lock_function(0); + if(entropy_init_initialized == 0) { + mbedtls_entropy_init(ctx); + entropy_init_initialized = 1; + } + Curl_polarsslthreadlock_unlock_function(0); +} +/* end of entropy_init_mutex() */ + +/* start of entropy_func_mutex() */ +static int entropy_func_mutex(void *data, unsigned char *output, size_t len) +{ + int ret; + /* lock 1 = entropy_func_mutex() */ + Curl_polarsslthreadlock_lock_function(1); + ret = mbedtls_entropy_func(data, output, len); + Curl_polarsslthreadlock_unlock_function(1); + + return ret; +} +/* end of entropy_func_mutex() */ + +#endif /* THREADING_SUPPORT */ + +/* Define this to enable lots of debugging for mbedTLS */ +#undef MBEDTLS_DEBUG + +#ifdef MBEDTLS_DEBUG +static void mbed_debug(void *context, int level, const char *f_name, + int line_nb, const char *line) +{ + struct Curl_easy *data = NULL; + + if(!context) + return; + + data = (struct Curl_easy *)context; + + infof(data, "%s", line); + (void) level; +} +#else +#endif + +/* ALPN for http2? */ +#ifdef USE_NGHTTP2 +# undef HAS_ALPN +# ifdef MBEDTLS_SSL_ALPN +# define HAS_ALPN +# endif +#endif + + +/* + * profile + */ +static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = +{ + /* Hashes from SHA-1 and above */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 1024, /* RSA min key len */ +}; + +/* See https://tls.mbed.org/discussions/generic/ + howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der +*/ +#define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) +#define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) + +#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) + +static Curl_recv mbed_recv; +static Curl_send mbed_send; + +static CURLcode mbedtls_version_from_curl(int *mbedver, long version) +{ + switch(version) { + case CURL_SSLVERSION_TLSv1_0: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_2; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3: + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + +static CURLcode +set_ssl_version_min_max(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; + int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + CURLcode result = CURLE_OK; + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ver_min); + mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ver_max); + + return result; +} + +static CURLcode +mbed_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; + int ret = -1; + char errorbuf[128]; + errorbuf[0] = 0; + + /* mbedTLS only supports SSLv3 and TLSv1 */ + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { + failf(data, "mbedTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef THREADING_SUPPORT + entropy_init_mutex(&ts_entropy); + mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); + + ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex, + &ts_entropy, NULL, 0); + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#else + mbedtls_entropy_init(&BACKEND->entropy); + mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); + + ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func, + &BACKEND->entropy, NULL, 0); + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#endif /* THREADING_SUPPORT */ + + /* Load the trusted CA */ + mbedtls_x509_crt_init(&BACKEND->cacert); + + if(ssl_cafile) { + ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile); + + if(ret<0) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", + ssl_cafile, -ret, errorbuf); + + if(verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + } + + if(ssl_capath) { + ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath); + + if(ret<0) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", + ssl_capath, -ret, errorbuf); + + if(verifypeer) + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Load the client certificate */ + mbedtls_x509_crt_init(&BACKEND->clicert); + + if(ssl_cert) { + ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert); + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", + ssl_cert, -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the client private key */ + mbedtls_pk_init(&BACKEND->pk); + + if(SSL_SET_OPTION(key)) { + ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); + if(ret == 0 && !(mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA) || + mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_ECKEY))) + ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", + SSL_SET_OPTION(key), -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the CRL */ + mbedtls_x509_crl_init(&BACKEND->crl); + + if(ssl_crlfile) { + ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile); + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", + ssl_crlfile, -ret, errorbuf); + + return CURLE_SSL_CRL_BADFILE; + } + } + + infof(data, "mbedTLS: Connecting to %s:%ld\n", hostname, port); + + mbedtls_ssl_config_init(&BACKEND->config); + + mbedtls_ssl_init(&BACKEND->ssl); + if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) { + failf(data, "mbedTLS: ssl_init failed"); + return CURLE_SSL_CONNECT_ERROR; + } + ret = mbedtls_ssl_config_defaults(&BACKEND->config, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if(ret) { + failf(data, "mbedTLS: ssl_config failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* new profile with RSA min key len = 1024 ... */ + mbedtls_ssl_conf_cert_profile(&BACKEND->config, + &mbedtls_x509_crt_profile_fr); + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_1); + infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); + break; + case CURL_SSLVERSION_SSLv3: + mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_0); + mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_0); + infof(data, "mbedTLS: Set SSL version to SSLv3\n"); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL); + + mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random, + &BACKEND->ctr_drbg); + mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex], + mbedtls_net_send, + mbedtls_net_recv, + NULL /* rev_timeout() */); + + mbedtls_ssl_conf_ciphersuites(&BACKEND->config, + mbedtls_ssl_list_ciphersuites()); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation(&BACKEND->config, + MBEDTLS_SSL_RENEGOTIATION_ENABLED); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_session_tickets(&BACKEND->config, + MBEDTLS_SSL_SESSION_TICKETS_DISABLED); +#endif + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *old_session = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { + ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session); + if(ret) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); + return CURLE_SSL_CONNECT_ERROR; + } + infof(data, "mbedTLS re-using session\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + mbedtls_ssl_conf_ca_chain(&BACKEND->config, + &BACKEND->cacert, + &BACKEND->crl); + + if(SSL_SET_OPTION(key)) { + mbedtls_ssl_conf_own_cert(&BACKEND->config, + &BACKEND->clicert, &BACKEND->pk); + } + if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) { + /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and* + the name to set in the SNI extension. So even if curl connects to a + host specified as an IP address, this function must be used. */ + failf(data, "couldn't set hostname in mbedTLS"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + const char **p = &BACKEND->protocols[0]; +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) + *p++ = NGHTTP2_PROTO_VERSION_ID; +#endif + *p++ = ALPN_HTTP_1_1; + *p = NULL; + /* this function doesn't clone the protocols array, which is why we need + to keep it around */ + if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config, + &BACKEND->protocols[0])) { + failf(data, "Failed setting ALPN protocols"); + return CURLE_SSL_CONNECT_ERROR; + } + for(p = &BACKEND->protocols[0]; *p; ++p) + infof(data, "ALPN, offering %s\n", *p); + } +#endif + +#ifdef MBEDTLS_DEBUG + /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ + mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data); + /* - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ + mbedtls_debug_set_threshold(4); +#endif + + /* give application a chance to interfere with mbedTLS set up. */ + if(data->set.ssl.fsslctx) { + ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config, + data->set.ssl.fsslctxp); + if(ret) { + failf(data, "error signaled by ssl ctx callback"); + return ret; + } + } + + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +mbed_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const mbedtls_x509_crt *peercert; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + conn->recv[sockindex] = mbed_recv; + conn->send[sockindex] = mbed_send; + + ret = mbedtls_ssl_handshake(&BACKEND->ssl); + + if(ret == MBEDTLS_ERR_SSL_WANT_READ) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } + else if(ret) { + char errorbuf[128]; + errorbuf[0] = 0; +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", + -ret, errorbuf); + return CURLE_SSL_CONNECT_ERROR; + } + + infof(data, "mbedTLS: Handshake complete, cipher is %s\n", + mbedtls_ssl_get_ciphersuite(&BACKEND->ssl) + ); + + ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl); + + if(!SSL_CONN_CONFIG(verifyhost)) + /* Ignore hostname errors if verifyhost is disabled */ + ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; + + if(ret && SSL_CONN_CONFIG(verifypeer)) { + if(ret & MBEDTLS_X509_BADCERT_EXPIRED) + failf(data, "Cert verify failed: BADCERT_EXPIRED"); + + else if(ret & MBEDTLS_X509_BADCERT_REVOKED) + failf(data, "Cert verify failed: BADCERT_REVOKED"); + + else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) + failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); + + else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) + failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); + + return CURLE_PEER_FAILED_VERIFICATION; + } + + peercert = mbedtls_ssl_get_peer_cert(&BACKEND->ssl); + + if(peercert && data->set.verbose) { + const size_t bufsize = 16384; + char *buffer = malloc(bufsize); + + if(!buffer) + return CURLE_OUT_OF_MEMORY; + + if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0) + infof(data, "Dumping cert info:\n%s\n", buffer); + else + infof(data, "Unable to dump certificate information.\n"); + + free(buffer); + } + + if(pinnedpubkey) { + int size; + CURLcode result; + mbedtls_x509_crt *p; + unsigned char pubkey[PUB_DER_MAX_BYTES]; + + if(!peercert || !peercert->raw.p || !peercert->raw.len) { + failf(data, "Failed due to missing peer certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + p = calloc(1, sizeof(*p)); + + if(!p) + return CURLE_OUT_OF_MEMORY; + + mbedtls_x509_crt_init(p); + + /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der + needs a non-const key, for now. + https://github.com/ARMmbed/mbedtls/issues/396 */ + if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { + failf(data, "Failed copying peer certificate"); + mbedtls_x509_crt_free(p); + free(p); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); + + if(size <= 0) { + failf(data, "Failed copying public key from peer certificate"); + mbedtls_x509_crt_free(p); + free(p); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + &pubkey[PUB_DER_MAX_BYTES - size], size); + if(result) { + mbedtls_x509_crt_free(p); + free(p); + return result; + } + + mbedtls_x509_crt_free(p); + free(p); + } + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl); + + if(next_protocol) { + infof(data, "ALPN, server accepted to use %s\n", next_protocol); +#ifdef USE_NGHTTP2 + if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN) && + !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) && + !next_protocol[ALPN_HTTP_1_1_LENGTH]) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else { + infof(data, "ALPN, server did not agree to a protocol\n"); + } + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + connssl->connecting_state = ssl_connect_3; + infof(data, "SSL connected\n"); + + return CURLE_OK; +} + +static CURLcode +mbed_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode retcode = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + if(SSL_SET_OPTION(primary.sessionid)) { + int ret; + mbedtls_ssl_session *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session)); + if(!our_ssl_sessionid) + return CURLE_OUT_OF_MEMORY; + + mbedtls_ssl_session_init(our_ssl_sessionid); + + ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid); + if(ret) { + if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) + mbedtls_ssl_session_free(our_ssl_sessionid); + free(our_ssl_sessionid); + failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); + return CURLE_SSL_CONNECT_ERROR; + } + + /* If there's already a matching session in the cache, delete it */ + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + + retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); + Curl_ssl_sessionid_unlock(conn); + if(retcode) { + mbedtls_ssl_session_free(our_ssl_sessionid); + free(our_ssl_sessionid); + failf(data, "failed to store ssl session"); + return retcode; + } + } + + connssl->connecting_state = ssl_connect_done; + + return CURLE_OK; +} + +static ssize_t mbed_send(struct connectdata *conn, int sockindex, + const void *mem, size_t len, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int ret = -1; + + ret = mbedtls_ssl_write(&BACKEND->ssl, + (unsigned char *)mem, len); + + if(ret < 0) { + *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? + CURLE_AGAIN : CURLE_SEND_ERROR; + ret = -1; + } + + return ret; +} + +static void Curl_mbedtls_close_all(struct Curl_easy *data) +{ + (void)data; +} + +static void Curl_mbedtls_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + mbedtls_pk_free(&BACKEND->pk); + mbedtls_x509_crt_free(&BACKEND->clicert); + mbedtls_x509_crt_free(&BACKEND->cacert); + mbedtls_x509_crl_free(&BACKEND->crl); + mbedtls_ssl_config_free(&BACKEND->config); + mbedtls_ssl_free(&BACKEND->ssl); + mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg); +#ifndef THREADING_SUPPORT + mbedtls_entropy_free(&BACKEND->entropy); +#endif /* THREADING_SUPPORT */ +} + +static ssize_t mbed_recv(struct connectdata *conn, int num, + char *buf, size_t buffersize, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + int ret = -1; + ssize_t len = -1; + + memset(buf, 0, buffersize); + ret = mbedtls_ssl_read(&BACKEND->ssl, (unsigned char *)buf, + buffersize); + + if(ret <= 0) { + if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) + return 0; + + *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ? + CURLE_AGAIN : CURLE_RECV_ERROR; + return -1; + } + + len = ret; + + return len; +} + +static void Curl_mbedtls_session_free(void *ptr) +{ + mbedtls_ssl_session_free(ptr); + free(ptr); +} + +static size_t Curl_mbedtls_version(char *buffer, size_t size) +{ +#ifdef MBEDTLS_VERSION_C + /* if mbedtls_version_get_number() is available it is better */ + unsigned int version = mbedtls_version_get_number(); + return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, + (version>>16)&0xff, (version>>8)&0xff); +#else + return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING); +#endif +} + +static CURLcode Curl_mbedtls_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ +#if defined(MBEDTLS_CTR_DRBG_C) + int ret = -1; + char errorbuf[128]; + mbedtls_entropy_context ctr_entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_init(&ctr_entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + errorbuf[0] = 0; + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, + &ctr_entropy, NULL, 0); + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n", + -ret, errorbuf); + } + else { + ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); + + if(ret) { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); +#endif /* MBEDTLS_ERROR_C */ + failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } + } + + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&ctr_entropy); + + return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT; +#elif defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state hs; + mbedtls_havege_init(&hs); + mbedtls_havege_random(&hs, entropy, length); + mbedtls_havege_free(&hs); + return CURLE_OK; +#else + return CURLE_NOT_BUILT_IN; +#endif +} + +static CURLcode +mbed_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode retcode; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + retcode = mbed_connect_step1(conn, sockindex); + if(retcode) + return retcode; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking ? 0 : timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + retcode = mbed_connect_step2(conn, sockindex); + if(retcode || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return retcode; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + retcode = mbed_connect_step3(conn, sockindex); + if(retcode) + return retcode; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = mbed_recv; + conn->send[sockindex] = mbed_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return mbed_connect_common(conn, sockindex, TRUE, done); +} + + +static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex) +{ + CURLcode retcode; + bool done = FALSE; + + retcode = mbed_connect_common(conn, sockindex, FALSE, &done); + if(retcode) + return retcode; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +/* + * return 0 error initializing SSL + * return 1 SSL initialized successfully + */ +static int Curl_mbedtls_init(void) +{ + return Curl_polarsslthreadlock_thread_setup(); +} + +static void Curl_mbedtls_cleanup(void) +{ + (void)Curl_polarsslthreadlock_thread_cleanup(); +} + +static bool Curl_mbedtls_data_pending(const struct connectdata *conn, + int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0; +} + +static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len UNUSED_PARAM) +{ + (void)sha256len; +#if MBEDTLS_VERSION_NUMBER < 0x02070000 + mbedtls_sha256(input, inputlen, sha256sum, 0); +#else + /* returns 0 on success, otherwise failure */ + if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) + return CURLE_BAD_FUNCTION_ARGUMENT; +#endif + return CURLE_OK; +} + +static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return &BACKEND->ssl; +} + +const struct Curl_ssl Curl_ssl_mbedtls = { + { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_PINNEDPUBKEY | + SSLSUPP_SSL_CTX, + + sizeof(struct ssl_backend_data), + + Curl_mbedtls_init, /* init */ + Curl_mbedtls_cleanup, /* cleanup */ + Curl_mbedtls_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + Curl_mbedtls_data_pending, /* data_pending */ + Curl_mbedtls_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_mbedtls_connect, /* connect */ + Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */ + Curl_mbedtls_get_internals, /* get_internals */ + Curl_mbedtls_close, /* close_one */ + Curl_mbedtls_close_all, /* close_all */ + Curl_mbedtls_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + Curl_mbedtls_sha256sum /* sha256sum */ +}; + +#endif /* USE_MBEDTLS */ diff --git a/libcurl/lib/vtls/mbedtls.h b/libcurl/lib/vtls/mbedtls.h new file mode 100644 index 0000000..4a93860 --- /dev/null +++ b/libcurl/lib/vtls/mbedtls.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_MBEDTLS_H +#define HEADER_CURL_MBEDTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MBEDTLS + +extern const struct Curl_ssl Curl_ssl_mbedtls; + +#endif /* USE_MBEDTLS */ +#endif /* HEADER_CURL_MBEDTLS_H */ diff --git a/libcurl/lib/vtls/mesalink.c b/libcurl/lib/vtls/mesalink.c new file mode 100644 index 0000000..7ca4f0e --- /dev/null +++ b/libcurl/lib/vtls/mesalink.c @@ -0,0 +1,627 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2017 - 2018, Yiming Jing, + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all MesaLink-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +/* + * Based upon the CyaSSL implementation in cyassl.c and cyassl.h: + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * Thanks for code and inspiration! + */ + +#include "curl_setup.h" + +#ifdef USE_MESALINK + +#include +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "x509asn1.h" +#include "curl_printf.h" + +#include "mesalink.h" +#include +#include + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define MESALINK_MAX_ERROR_SZ 80 + +struct ssl_backend_data +{ + SSL_CTX *ctx; + SSL *handle; +}; + +#define BACKEND connssl->backend + +static Curl_recv mesalink_recv; +static Curl_send mesalink_send; + +/* + * This function loads all the client/CA certificates and CRLs. Setup the TLS + * layer and do all necessary magic. + */ +static CURLcode +mesalink_connect_step1(struct connectdata *conn, int sockindex) +{ + char *ciphers; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char *const ssl_capath = SSL_CONN_CONFIG(CApath); + struct in_addr addr4; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + const char *const hostname = + SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; + size_t hostname_len = strlen(hostname); + + SSL_METHOD *req_method = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; + + if(connssl->state == ssl_connection_complete) + return CURLE_OK; + + if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { + failf(data, "MesaLink does not support to set maximum SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_SSLv3: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + failf(data, "MesaLink does not support SSL 3.0, TLS 1.0, or TLS 1.1"); + return CURLE_NOT_BUILT_IN; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1_2: + req_method = TLSv1_2_client_method(); + break; + case CURL_SSLVERSION_TLSv1_3: + req_method = TLSv1_3_client_method(); + break; + case CURL_SSLVERSION_SSLv2: + failf(data, "MesaLink does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(!req_method) { + failf(data, "SSL: couldn't create a method!"); + return CURLE_OUT_OF_MEMORY; + } + + if(BACKEND->ctx) + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = SSL_CTX_new(req_method); + + if(!BACKEND->ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + + SSL_CTX_set_verify( + BACKEND->ctx, verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); + + if(ssl_cafile || ssl_capath) { + if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) { + if(verifypeer) { + failf(data, + "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + infof(data, + "error setting certificate verify locations," + " continuing anyway:\n"); + } + else { + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + } + + ciphers = SSL_CONN_CONFIG(cipher_list); + if(ciphers) { +#ifdef MESALINK_HAVE_CIPHER + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } +#endif + infof(data, "Cipher selection: %s\n", ciphers); + } + + if(BACKEND->handle) + SSL_free(BACKEND->handle); + BACKEND->handle = SSL_new(BACKEND->ctx); + if(!BACKEND->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + + if((hostname_len < USHRT_MAX) && + (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) +#ifdef ENABLE_IPV6 + && (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) +#endif + ) { + /* hostname is not a valid IP address */ + if(SSL_set_tlsext_host_name(BACKEND->handle, hostname) != SSL_SUCCESS) { + failf(data, + "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#ifdef CURLDEBUG + /* Check if the hostname is 127.0.0.1 or [::1]; + * otherwise reject because MesaLink always wants a valid DNS Name + * specified in RFC 5280 Section 7.2 */ + if(strncmp(hostname, "127.0.0.1", 9) == 0 +#ifdef ENABLE_IPV6 + || strncmp(hostname, "[::1]", 5) == 0 +#endif + ) { + SSL_set_tlsext_host_name(BACKEND->handle, "localhost"); + } + else +#endif + { + failf(data, + "ERROR: MesaLink does not accept an IP address as a hostname\n"); + return CURLE_SSL_CONNECT_ERROR; + } + } + +#ifdef MESALINK_HAVE_SESSION + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { + Curl_ssl_sessionid_unlock(conn); + failf( + data, + "SSL: SSL_set_session failed: %s", + ERR_error_string(SSL_get_error(BACKEND->handle, 0), error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } +#endif /* MESALINK_HAVE_SESSION */ + + if(SSL_set_fd(BACKEND->handle, (int)sockfd) != SSL_SUCCESS) { + failf(data, "SSL: SSL_set_fd failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static CURLcode +mesalink_connect_step2(struct connectdata *conn, int sockindex) +{ + int ret = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + conn->recv[sockindex] = mesalink_recv; + conn->send[sockindex] = mesalink_send; + + ret = SSL_connect(BACKEND->handle); + if(ret != SSL_SUCCESS) { + int detail = SSL_get_error(BACKEND->handle, ret); + + if(SSL_ERROR_WANT_CONNECT == detail || SSL_ERROR_WANT_READ == detail) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else { + char error_buffer[MESALINK_MAX_ERROR_SZ]; + failf(data, + "SSL_connect failed with error %d: %s", + detail, + ERR_error_string_n(detail, error_buffer, sizeof(error_buffer))); + ERR_print_errors_fp(stderr); + if(detail && SSL_CONN_CONFIG(verifypeer)) { + detail &= ~0xFF; + if(detail == TLS_ERROR_WEBPKI_ERRORS) { + failf(data, "Cert verify failed"); + return CURLE_PEER_FAILED_VERIFICATION; + } + } + return CURLE_SSL_CONNECT_ERROR; + } + } + + connssl->connecting_state = ssl_connect_3; + infof(data, + "SSL connection using %s / %s\n", + SSL_get_version(BACKEND->handle), + SSL_get_cipher_name(BACKEND->handle)); + + return CURLE_OK; +} + +static CURLcode +mesalink_connect_step3(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + +#ifdef MESALINK_HAVE_SESSION + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + SSL_SESSION *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = SSL_get_session(BACKEND->handle); + + Curl_ssl_sessionid_lock(conn); + incache = + !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + result = Curl_ssl_addsessionid( + conn, our_ssl_sessionid, 0 /* unknown size */, sockindex); + if(result) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "failed to store ssl session"); + return result; + } + } + Curl_ssl_sessionid_unlock(conn); + } +#endif /* MESALINK_HAVE_SESSION */ + + connssl->connecting_state = ssl_connect_done; + + return result; +} + +static ssize_t +mesalink_send(struct connectdata *conn, int sockindex, const void *mem, + size_t len, CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + char error_buffer[MESALINK_MAX_ERROR_SZ]; + int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + int rc = SSL_write(BACKEND->handle, mem, memlen); + + if(rc < 0) { + int err = SSL_get_error(BACKEND->handle, rc); + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_write() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, + "SSL write: %s, errno %d", + ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + } + return rc; +} + +static void +Curl_mesalink_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->handle) { + (void)SSL_shutdown(BACKEND->handle); + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + if(BACKEND->ctx) { + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = NULL; + } +} + +static ssize_t +mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + char error_buffer[MESALINK_MAX_ERROR_SZ]; + int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + int nread = SSL_read(BACKEND->handle, buf, buffsize); + + if(nread <= 0) { + int err = SSL_get_error(BACKEND->handle, nread); + + switch(err) { + case SSL_ERROR_ZERO_RETURN: /* no more data */ + case IO_ERROR_CONNECTION_ABORTED: + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, + "SSL read: %s, errno %d", + ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + return nread; +} + +static size_t +Curl_mesalink_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING); +} + +static int +Curl_mesalink_init(void) +{ + return (SSL_library_init() == SSL_SUCCESS); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +static int +Curl_mesalink_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->handle) { + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + return retval; +} + +static CURLcode +mesalink_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = mesalink_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = + ssl_connect_2_writing == connssl->connecting_state ? sockfd + : CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == connssl->connecting_state + ? sockfd + : CURL_SOCKET_BAD; + + what = Curl_socket_check( + readfd, CURL_SOCKET_BAD, writefd, nonblocking ? 0 : timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = mesalink_connect_step2(conn, sockindex); + + if(result || + (nonblocking && (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) { + return result; + } + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = mesalink_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = mesalink_recv; + conn->send[sockindex] = mesalink_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode +Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + return mesalink_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode +Curl_mesalink_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = mesalink_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static void * +Curl_mesalink_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_mesalink = { + { CURLSSLBACKEND_MESALINK, "MesaLink" }, /* info */ + + SSLSUPP_SSL_CTX, + + sizeof(struct ssl_backend_data), + + Curl_mesalink_init, /* init */ + Curl_none_cleanup, /* cleanup */ + Curl_mesalink_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_mesalink_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_mesalink_connect, /* connect */ + Curl_mesalink_connect_nonblocking, /* connect_nonblocking */ + Curl_mesalink_get_internals, /* get_internals */ + Curl_mesalink_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + NULL /* sha256sum */ +}; + +#endif diff --git a/libcurl/lib/vtls/mesalink.h b/libcurl/lib/vtls/mesalink.h new file mode 100644 index 0000000..54cb94a --- /dev/null +++ b/libcurl/lib/vtls/mesalink.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_MESALINK_H +#define HEADER_CURL_MESALINK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2017-2018, Yiming Jing, + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MESALINK + +extern const struct Curl_ssl Curl_ssl_mesalink; + +#endif /* USE_MESALINK */ +#endif /* HEADER_CURL_MESALINK_H */ diff --git a/libcurl/lib/vtls/nss.c b/libcurl/lib/vtls/nss.c new file mode 100644 index 0000000..482fd5e --- /dev/null +++ b/libcurl/lib/vtls/nss.c @@ -0,0 +1,2452 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all NSS-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +#include "curl_setup.h" + +#ifdef USE_NSS + +#include "urldata.h" +#include "sendf.h" +#include "formdata.h" /* for the boundary function */ +#include "url.h" /* for the ssl config check function */ +#include "connect.h" +#include "strcase.h" +#include "select.h" +#include "vtls.h" +#include "llist.h" +#include "multiif.h" +#include "curl_printf.h" +#include "nssg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for SECKEY_DestroyPublicKey() */ +#include /* for PR_ImportTCPSocket */ + +#define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH) + +#if NSSVERNUM >= 0x030f00 /* 3.15.0 */ +#include +#endif + +#include "strcase.h" +#include "warnless.h" +#include "x509asn1.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define SSL_DIR "/etc/pki/nssdb" + +/* enough to fit the string "PEM Token #[0|1]" */ +#define SLOTSIZE 13 + +struct ssl_backend_data { + PRFileDesc *handle; + char *client_nickname; + struct Curl_easy *data; + struct curl_llist obj_list; + PK11GenericObject *obj_clicert; +}; + +#define BACKEND connssl->backend + +static PRLock *nss_initlock = NULL; +static PRLock *nss_crllock = NULL; +static PRLock *nss_findslot_lock = NULL; +static PRLock *nss_trustload_lock = NULL; +static struct curl_llist nss_crl_list; +static NSSInitContext *nss_context = NULL; +static volatile int initialized = 0; + +/* type used to wrap pointers as list nodes */ +struct ptr_list_wrap { + void *ptr; + struct curl_llist_element node; +}; + +typedef struct { + const char *name; + int num; +} cipher_s; + +#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \ + CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \ + ptr->type = (_type); \ + ptr->pValue = (_val); \ + ptr->ulValueLen = (_len); \ +} WHILE_FALSE + +#define CERT_NewTempCertificate __CERT_NewTempCertificate + +#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0]) +static const cipher_s cipherlist[] = { + /* SSL2 cipher suites */ + {"rc4", SSL_EN_RC4_128_WITH_MD5}, + {"rc4-md5", SSL_EN_RC4_128_WITH_MD5}, + {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5}, + {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5}, + {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5}, + {"des", SSL_EN_DES_64_CBC_WITH_MD5}, + {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5}, + /* SSL3/TLS cipher suites */ + {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5}, + {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA}, + {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA}, + {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA}, + {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5}, + {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5}, + {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, + {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, + {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA}, + {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, + {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA}, + {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA}, + {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA}, + /* TLS 1.0: Exportable 56-bit Cipher Suites. */ + {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, + {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, + /* AES ciphers. */ + {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, + {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, + {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, + {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, + {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, + {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, + /* ECC ciphers. */ + {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA}, + {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA}, + {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA}, + {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA}, + {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA}, + {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA}, + {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}, + {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, + {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA}, + {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA}, + {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA}, + {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA}, + {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA}, + {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA}, + {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, + {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, + {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA}, + {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA}, + {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA}, + {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA}, +#ifdef TLS_RSA_WITH_NULL_SHA256 + /* new HMAC-SHA256 cipher suites specified in RFC */ + {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256}, + {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256}, + {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256}, + {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256}, + {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256}, + {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, + {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, +#endif +#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256 + /* AES GCM cipher suites in RFC 5288 and RFC 5289 */ + {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256}, + {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, + {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256}, + {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256}, + {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256}, +#endif +#ifdef TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + /* cipher suites using SHA384 */ + {"rsa_aes_256_gcm_sha_384", TLS_RSA_WITH_AES_256_GCM_SHA384}, + {"dhe_rsa_aes_256_gcm_sha_384", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384}, + {"dhe_dss_aes_256_gcm_sha_384", TLS_DHE_DSS_WITH_AES_256_GCM_SHA384}, + {"ecdhe_ecdsa_aes_256_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384}, + {"ecdhe_rsa_aes_256_sha_384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384}, + {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, + {"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, +#endif +#ifdef TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + /* chacha20-poly1305 cipher suites */ + {"ecdhe_rsa_chacha20_poly1305_sha_256", + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, + {"ecdhe_ecdsa_chacha20_poly1305_sha_256", + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256}, + {"dhe_rsa_chacha20_poly1305_sha_256", + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, +#endif +#ifdef TLS_AES_256_GCM_SHA384 + {"aes_128_gcm_sha_256", TLS_AES_128_GCM_SHA256}, + {"aes_256_gcm_sha_384", TLS_AES_256_GCM_SHA384}, + {"chacha20_poly1305_sha_256", TLS_CHACHA20_POLY1305_SHA256}, +#endif +}; + +#if defined(WIN32) +static const char *pem_library = "nsspem.dll"; +static const char *trust_library = "nssckbi.dll"; +#elif defined(__APPLE__) +static const char *pem_library = "libnsspem.dylib"; +static const char *trust_library = "libnssckbi.dylib"; +#else +static const char *pem_library = "libnsspem.so"; +static const char *trust_library = "libnssckbi.so"; +#endif + +static SECMODModule *pem_module = NULL; +static SECMODModule *trust_module = NULL; + +/* NSPR I/O layer we use to detect blocking direction during SSL handshake */ +static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER; +static PRIOMethods nspr_io_methods; + +static const char *nss_error_to_name(PRErrorCode code) +{ + const char *name = PR_ErrorToName(code); + if(name) + return name; + + return "unknown error"; +} + +static void nss_print_error_message(struct Curl_easy *data, PRUint32 err) +{ + failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); +} + +static char *nss_sslver_to_name(PRUint16 nssver) +{ + switch(nssver) { + case SSL_LIBRARY_VERSION_2: + return strdup("SSLv2"); + case SSL_LIBRARY_VERSION_3_0: + return strdup("SSLv3"); + case SSL_LIBRARY_VERSION_TLS_1_0: + return strdup("TLSv1.0"); +#ifdef SSL_LIBRARY_VERSION_TLS_1_1 + case SSL_LIBRARY_VERSION_TLS_1_1: + return strdup("TLSv1.1"); +#endif +#ifdef SSL_LIBRARY_VERSION_TLS_1_2 + case SSL_LIBRARY_VERSION_TLS_1_2: + return strdup("TLSv1.2"); +#endif +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + case SSL_LIBRARY_VERSION_TLS_1_3: + return strdup("TLSv1.3"); +#endif + default: + return curl_maprintf("0x%04x", nssver); + } +} + +static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, + char *cipher_list) +{ + unsigned int i; + PRBool cipher_state[NUM_OF_CIPHERS]; + PRBool found; + char *cipher; + + /* use accessors to avoid dynamic linking issues after an update of NSS */ + const PRUint16 num_implemented_ciphers = SSL_GetNumImplementedCiphers(); + const PRUint16 *implemented_ciphers = SSL_GetImplementedCiphers(); + if(!implemented_ciphers) + return SECFailure; + + /* First disable all ciphers. This uses a different max value in case + * NSS adds more ciphers later we don't want them available by + * accident + */ + for(i = 0; i < num_implemented_ciphers; i++) { + SSL_CipherPrefSet(model, implemented_ciphers[i], PR_FALSE); + } + + /* Set every entry in our list to false */ + for(i = 0; i < NUM_OF_CIPHERS; i++) { + cipher_state[i] = PR_FALSE; + } + + cipher = cipher_list; + + while(cipher_list && (cipher_list[0])) { + while((*cipher) && (ISSPACE(*cipher))) + ++cipher; + + cipher_list = strchr(cipher, ','); + if(cipher_list) { + *cipher_list++ = '\0'; + } + + found = PR_FALSE; + + for(i = 0; i. + */ +static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name) +{ + PK11SlotInfo *slot; + PR_Lock(nss_findslot_lock); + slot = PK11_FindSlotByName(slot_name); + PR_Unlock(nss_findslot_lock); + return slot; +} + +/* wrap 'ptr' as list node and tail-insert into 'list' */ +static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr) +{ + struct ptr_list_wrap *wrap = malloc(sizeof(*wrap)); + if(!wrap) + return CURLE_OUT_OF_MEMORY; + + wrap->ptr = ptr; + Curl_llist_insert_next(list, list->tail, wrap, &wrap->node); + return CURLE_OK; +} + +/* Call PK11_CreateGenericObject() with the given obj_class and filename. If + * the call succeeds, append the object handle to the list of objects so that + * the object can be destroyed in Curl_nss_close(). */ +static CURLcode nss_create_object(struct ssl_connect_data *connssl, + CK_OBJECT_CLASS obj_class, + const char *filename, bool cacert) +{ + PK11SlotInfo *slot; + PK11GenericObject *obj; + CK_BBOOL cktrue = CK_TRUE; + CK_BBOOL ckfalse = CK_FALSE; + CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; + int attr_cnt = 0; + CURLcode result = (cacert) + ? CURLE_SSL_CACERT_BADFILE + : CURLE_SSL_CERTPROBLEM; + + const int slot_id = (cacert) ? 0 : 1; + char *slot_name = aprintf("PEM Token #%d", slot_id); + if(!slot_name) + return CURLE_OUT_OF_MEMORY; + + slot = nss_find_slot_by_name(slot_name); + free(slot_name); + if(!slot) + return result; + + PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); + PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); + PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename, + (CK_ULONG)strlen(filename) + 1); + + if(CKO_CERTIFICATE == obj_class) { + CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse); + PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval)); + } + + /* PK11_CreateManagedGenericObject() was introduced in NSS 3.34 because + * PK11_DestroyGenericObject() does not release resources allocated by + * PK11_CreateGenericObject() early enough. */ + obj = +#ifdef HAVE_PK11_CREATEMANAGEDGENERICOBJECT + PK11_CreateManagedGenericObject +#else + PK11_CreateGenericObject +#endif + (slot, attrs, attr_cnt, PR_FALSE); + + PK11_FreeSlot(slot); + if(!obj) + return result; + + if(insert_wrapped_ptr(&BACKEND->obj_list, obj) != CURLE_OK) { + PK11_DestroyGenericObject(obj); + return CURLE_OUT_OF_MEMORY; + } + + if(!cacert && CKO_CERTIFICATE == obj_class) + /* store reference to a client certificate */ + BACKEND->obj_clicert = obj; + + return CURLE_OK; +} + +/* Destroy the NSS object whose handle is given by ptr. This function is + * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy + * NSS objects in Curl_nss_close() */ +static void nss_destroy_object(void *user, void *ptr) +{ + struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr; + PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr; + (void) user; + PK11_DestroyGenericObject(obj); + free(wrap); +} + +/* same as nss_destroy_object() but for CRL items */ +static void nss_destroy_crl_item(void *user, void *ptr) +{ + struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr; + SECItem *crl_der = (SECItem *) wrap->ptr; + (void) user; + SECITEM_FreeItem(crl_der, PR_TRUE); + free(wrap); +} + +static CURLcode nss_load_cert(struct ssl_connect_data *ssl, + const char *filename, PRBool cacert) +{ + CURLcode result = (cacert) + ? CURLE_SSL_CACERT_BADFILE + : CURLE_SSL_CERTPROBLEM; + + /* libnsspem.so leaks memory if the requested file does not exist. For more + * details, go to . */ + if(is_file(filename)) + result = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert); + + if(!result && !cacert) { + /* we have successfully loaded a client certificate */ + CERTCertificate *cert; + char *nickname = NULL; + char *n = strrchr(filename, '/'); + if(n) + n++; + + /* The following undocumented magic helps to avoid a SIGSEGV on call + * of PK11_ReadRawAttribute() from SelectClientCert() when using an + * immature version of libnsspem.so. For more details, go to + * . */ + nickname = aprintf("PEM Token #1:%s", n); + if(nickname) { + cert = PK11_FindCertFromNickname(nickname, NULL); + if(cert) + CERT_DestroyCertificate(cert); + + free(nickname); + } + } + + return result; +} + +/* add given CRL to cache if it is not already there */ +static CURLcode nss_cache_crl(SECItem *crl_der) +{ + CERTCertDBHandle *db = CERT_GetDefaultCertDB(); + CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0); + if(crl) { + /* CRL already cached */ + SEC_DestroyCrl(crl); + SECITEM_FreeItem(crl_der, PR_TRUE); + return CURLE_OK; + } + + /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */ + PR_Lock(nss_crllock); + + if(SECSuccess != CERT_CacheCRL(db, crl_der)) { + /* unable to cache CRL */ + SECITEM_FreeItem(crl_der, PR_TRUE); + PR_Unlock(nss_crllock); + return CURLE_SSL_CRL_BADFILE; + } + + /* store the CRL item so that we can free it in Curl_nss_cleanup() */ + if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) { + if(SECSuccess == CERT_UncacheCRL(db, crl_der)) + SECITEM_FreeItem(crl_der, PR_TRUE); + PR_Unlock(nss_crllock); + return CURLE_OUT_OF_MEMORY; + } + + /* we need to clear session cache, so that the CRL could take effect */ + SSL_ClearSessionCache(); + PR_Unlock(nss_crllock); + return CURLE_OK; +} + +static CURLcode nss_load_crl(const char *crlfilename) +{ + PRFileDesc *infile; + PRFileInfo info; + SECItem filedata = { 0, NULL, 0 }; + SECItem *crl_der = NULL; + char *body; + + infile = PR_Open(crlfilename, PR_RDONLY, 0); + if(!infile) + return CURLE_SSL_CRL_BADFILE; + + if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info)) + goto fail; + + if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1)) + goto fail; + + if(info.size != PR_Read(infile, filedata.data, info.size)) + goto fail; + + crl_der = SECITEM_AllocItem(NULL, NULL, 0U); + if(!crl_der) + goto fail; + + /* place a trailing zero right after the visible data */ + body = (char *)filedata.data; + body[--filedata.len] = '\0'; + + body = strstr(body, "-----BEGIN"); + if(body) { + /* assume ASCII */ + char *trailer; + char *begin = PORT_Strchr(body, '\n'); + if(!begin) + begin = PORT_Strchr(body, '\r'); + if(!begin) + goto fail; + + trailer = strstr(++begin, "-----END"); + if(!trailer) + goto fail; + + /* retrieve DER from ASCII */ + *trailer = '\0'; + if(ATOB_ConvertAsciiToItem(crl_der, begin)) + goto fail; + + SECITEM_FreeItem(&filedata, PR_FALSE); + } + else + /* assume DER */ + *crl_der = filedata; + + PR_Close(infile); + return nss_cache_crl(crl_der); + +fail: + PR_Close(infile); + SECITEM_FreeItem(crl_der, PR_TRUE); + SECITEM_FreeItem(&filedata, PR_FALSE); + return CURLE_SSL_CRL_BADFILE; +} + +static CURLcode nss_load_key(struct connectdata *conn, int sockindex, + char *key_file) +{ + PK11SlotInfo *slot, *tmp; + SECStatus status; + CURLcode result; + struct ssl_connect_data *ssl = conn->ssl; + struct Curl_easy *data = conn->data; + + (void)sockindex; /* unused */ + + result = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); + if(result) { + PR_SetError(SEC_ERROR_BAD_KEY, 0); + return result; + } + + slot = nss_find_slot_by_name("PEM Token #1"); + if(!slot) + return CURLE_SSL_CERTPROBLEM; + + /* This will force the token to be seen as re-inserted */ + tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0); + if(tmp) + PK11_FreeSlot(tmp); + if(!PK11_IsPresent(slot)) { + PK11_FreeSlot(slot); + return CURLE_SSL_CERTPROBLEM; + } + + status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd)); + PK11_FreeSlot(slot); + + return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; +} + +static int display_error(struct connectdata *conn, PRInt32 err, + const char *filename) +{ + switch(err) { + case SEC_ERROR_BAD_PASSWORD: + failf(conn->data, "Unable to load client key: Incorrect password"); + return 1; + case SEC_ERROR_UNKNOWN_CERT: + failf(conn->data, "Unable to load certificate %s", filename); + return 1; + default: + break; + } + return 0; /* The caller will print a generic error */ +} + +static CURLcode cert_stuff(struct connectdata *conn, int sockindex, + char *cert_file, char *key_file) +{ + struct Curl_easy *data = conn->data; + CURLcode result; + + if(cert_file) { + result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE); + if(result) { + const PRErrorCode err = PR_GetError(); + if(!display_error(conn, err, cert_file)) { + const char *err_name = nss_error_to_name(err); + failf(data, "unable to load client cert: %d (%s)", err, err_name); + } + + return result; + } + } + + if(key_file || (is_file(cert_file))) { + if(key_file) + result = nss_load_key(conn, sockindex, key_file); + else + /* In case the cert file also has the key */ + result = nss_load_key(conn, sockindex, cert_file); + if(result) { + const PRErrorCode err = PR_GetError(); + if(!display_error(conn, err, key_file)) { + const char *err_name = nss_error_to_name(err); + failf(data, "unable to load client key: %d (%s)", err, err_name); + } + + return result; + } + } + + return CURLE_OK; +} + +static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg) +{ + (void)slot; /* unused */ + + if(retry || NULL == arg) + return NULL; + else + return (char *)PORT_Strdup((char *)arg); +} + +/* bypass the default SSL_AuthCertificate() hook in case we do not want to + * verify peer */ +static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, + PRBool isServer) +{ + struct connectdata *conn = (struct connectdata *)arg; + +#ifdef SSL_ENABLE_OCSP_STAPLING + if(SSL_CONN_CONFIG(verifystatus)) { + SECStatus cacheResult; + + const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd); + if(!csa) { + failf(conn->data, "Invalid OCSP response"); + return SECFailure; + } + + if(csa->len == 0) { + failf(conn->data, "No OCSP response received"); + return SECFailure; + } + + cacheResult = CERT_CacheOCSPResponseFromSideChannel( + CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd), + PR_Now(), &csa->items[0], arg + ); + + if(cacheResult != SECSuccess) { + failf(conn->data, "Invalid OCSP response"); + return cacheResult; + } + } +#endif + + if(!SSL_CONN_CONFIG(verifypeer)) { + infof(conn->data, "skipping SSL peer certificate verification\n"); + return SECSuccess; + } + + return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer); +} + +/** + * Inform the application that the handshake is complete. + */ +static void HandshakeCallback(PRFileDesc *sock, void *arg) +{ + struct connectdata *conn = (struct connectdata*) arg; + unsigned int buflenmax = 50; + unsigned char buf[50]; + unsigned int buflen; + SSLNextProtoState state; + + if(!conn->bits.tls_enable_npn && !conn->bits.tls_enable_alpn) { + return; + } + + if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) { + + switch(state) { +#if NSSVERNUM >= 0x031a00 /* 3.26.0 */ + /* used by NSS internally to implement 0-RTT */ + case SSL_NEXT_PROTO_EARLY_VALUE: + /* fall through! */ +#endif + case SSL_NEXT_PROTO_NO_SUPPORT: + case SSL_NEXT_PROTO_NO_OVERLAP: + infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n"); + return; +#ifdef SSL_ENABLE_ALPN + case SSL_NEXT_PROTO_SELECTED: + infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf); + break; +#endif + case SSL_NEXT_PROTO_NEGOTIATED: + infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf); + break; + } + +#ifdef USE_NGHTTP2 + if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(buflen == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +} + +#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ +static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data, + PRBool *canFalseStart) +{ + struct connectdata *conn = client_data; + struct Curl_easy *data = conn->data; + + SSLChannelInfo channelInfo; + SSLCipherSuiteInfo cipherInfo; + + SECStatus rv; + PRBool negotiatedExtension; + + *canFalseStart = PR_FALSE; + + if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess) + return SECFailure; + + if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, + sizeof(cipherInfo)) != SECSuccess) + return SECFailure; + + /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for + * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310 + */ + if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2) + goto end; + + /* Only allow ECDHE key exchange algorithm. + * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */ + if(cipherInfo.keaType != ssl_kea_ecdh) + goto end; + + /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC + * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt + * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */ + if(cipherInfo.symCipher != ssl_calg_aes_gcm) + goto end; + + /* Enforce ALPN or NPN to do False Start, as an indicator of server + * compatibility. */ + rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn, + &negotiatedExtension); + if(rv != SECSuccess || !negotiatedExtension) { + rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn, + &negotiatedExtension); + } + + if(rv != SECSuccess || !negotiatedExtension) + goto end; + + *canFalseStart = PR_TRUE; + + infof(data, "Trying TLS False Start\n"); + +end: + return SECSuccess; +} +#endif + +static void display_cert_info(struct Curl_easy *data, + CERTCertificate *cert) +{ + char *subject, *issuer, *common_name; + PRExplodedTime printableTime; + char timeString[256]; + PRTime notBefore, notAfter; + + subject = CERT_NameToAscii(&cert->subject); + issuer = CERT_NameToAscii(&cert->issuer); + common_name = CERT_GetCommonName(&cert->subject); + infof(data, "\tsubject: %s\n", subject); + + CERT_GetCertTimes(cert, ¬Before, ¬After); + PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime); + PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); + infof(data, "\tstart date: %s\n", timeString); + PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime); + PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); + infof(data, "\texpire date: %s\n", timeString); + infof(data, "\tcommon name: %s\n", common_name); + infof(data, "\tissuer: %s\n", issuer); + + PR_Free(subject); + PR_Free(issuer); + PR_Free(common_name); +} + +static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock) +{ + CURLcode result = CURLE_OK; + SSLChannelInfo channel; + SSLCipherSuiteInfo suite; + CERTCertificate *cert; + CERTCertificate *cert2; + CERTCertificate *cert3; + PRTime now; + int i; + + if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) == + SECSuccess && channel.length == sizeof(channel) && + channel.cipherSuite) { + if(SSL_GetCipherSuiteInfo(channel.cipherSuite, + &suite, sizeof(suite)) == SECSuccess) { + infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName); + } + } + + cert = SSL_PeerCertificate(sock); + if(cert) { + infof(conn->data, "Server certificate:\n"); + + if(!conn->data->set.ssl.certinfo) { + display_cert_info(conn->data, cert); + CERT_DestroyCertificate(cert); + } + else { + /* Count certificates in chain. */ + now = PR_Now(); + i = 1; + if(!cert->isRoot) { + cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); + while(cert2) { + i++; + if(cert2->isRoot) { + CERT_DestroyCertificate(cert2); + break; + } + cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA); + CERT_DestroyCertificate(cert2); + cert2 = cert3; + } + } + + result = Curl_ssl_init_certinfo(conn->data, i); + if(!result) { + for(i = 0; cert; cert = cert2) { + result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data, + (char *)cert->derCert.data + + cert->derCert.len); + if(result) + break; + + if(cert->isRoot) { + CERT_DestroyCertificate(cert); + break; + } + + cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); + CERT_DestroyCertificate(cert); + } + } + } + } + + return result; +} + +static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) +{ + struct connectdata *conn = (struct connectdata *)arg; + struct Curl_easy *data = conn->data; + PRErrorCode err = PR_GetError(); + CERTCertificate *cert; + + /* remember the cert verification result */ + if(SSL_IS_PROXY()) + data->set.proxy_ssl.certverifyresult = err; + else + data->set.ssl.certverifyresult = err; + + if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost)) + /* we are asked not to verify the host name */ + return SECSuccess; + + /* print only info about the cert, the error is printed off the callback */ + cert = SSL_PeerCertificate(sock); + if(cert) { + infof(data, "Server certificate:\n"); + display_cert_info(data, cert); + CERT_DestroyCertificate(cert); + } + + return SECFailure; +} + +/** + * + * Check that the Peer certificate's issuer certificate matches the one found + * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the + * issuer check, so we provide comments that mimic the OpenSSL + * X509_check_issued function (in x509v3/v3_purp.c) + */ +static SECStatus check_issuer_cert(PRFileDesc *sock, + char *issuer_nickname) +{ + CERTCertificate *cert, *cert_issuer, *issuer; + SECStatus res = SECSuccess; + void *proto_win = NULL; + + cert = SSL_PeerCertificate(sock); + cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner); + + proto_win = SSL_RevealPinArg(sock); + issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); + + if((!cert_issuer) || (!issuer)) + res = SECFailure; + else if(SECITEM_CompareItem(&cert_issuer->derCert, + &issuer->derCert) != SECEqual) + res = SECFailure; + + CERT_DestroyCertificate(cert); + CERT_DestroyCertificate(issuer); + CERT_DestroyCertificate(cert_issuer); + return res; +} + +static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, + const char *pinnedpubkey) +{ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + struct Curl_easy *data = BACKEND->data; + CERTCertificate *cert; + + if(!pinnedpubkey) + /* no pinned public key specified */ + return CURLE_OK; + + /* get peer certificate */ + cert = SSL_PeerCertificate(BACKEND->handle); + if(cert) { + /* extract public key from peer certificate */ + SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); + if(pubkey) { + /* encode the public key as DER */ + SECItem *cert_der = PK11_DEREncodePublicKey(pubkey); + if(cert_der) { + /* compare the public key with the pinned public key */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, cert_der->data, + cert_der->len); + SECITEM_FreeItem(cert_der, PR_TRUE); + } + SECKEY_DestroyPublicKey(pubkey); + } + CERT_DestroyCertificate(cert); + } + + /* report the resulting status */ + switch(result) { + case CURLE_OK: + infof(data, "pinned public key verified successfully!\n"); + break; + case CURLE_SSL_PINNEDPUBKEYNOTMATCH: + failf(data, "failed to verify pinned public key"); + break; + default: + /* OOM, etc. */ + break; + } + + return result; +} + +/** + * + * Callback to pick the SSL client certificate. + */ +static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, + struct CERTDistNamesStr *caNames, + struct CERTCertificateStr **pRetCert, + struct SECKEYPrivateKeyStr **pRetKey) +{ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; + struct Curl_easy *data = BACKEND->data; + const char *nickname = BACKEND->client_nickname; + static const char pem_slotname[] = "PEM Token #1"; + + if(BACKEND->obj_clicert) { + /* use the cert/key provided by PEM reader */ + SECItem cert_der = { 0, NULL, 0 }; + void *proto_win = SSL_RevealPinArg(sock); + struct CERTCertificateStr *cert; + struct SECKEYPrivateKeyStr *key; + + PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname); + if(NULL == slot) { + failf(data, "NSS: PK11 slot not found: %s", pem_slotname); + return SECFailure; + } + + if(PK11_ReadRawAttribute(PK11_TypeGeneric, BACKEND->obj_clicert, CKA_VALUE, + &cert_der) != SECSuccess) { + failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); + PK11_FreeSlot(slot); + return SECFailure; + } + + cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win); + SECITEM_FreeItem(&cert_der, PR_FALSE); + if(NULL == cert) { + failf(data, "NSS: client certificate from file not found"); + PK11_FreeSlot(slot); + return SECFailure; + } + + key = PK11_FindPrivateKeyFromCert(slot, cert, NULL); + PK11_FreeSlot(slot); + if(NULL == key) { + failf(data, "NSS: private key from file not found"); + CERT_DestroyCertificate(cert); + return SECFailure; + } + + infof(data, "NSS: client certificate from file\n"); + display_cert_info(data, cert); + + *pRetCert = cert; + *pRetKey = key; + return SECSuccess; + } + + /* use the default NSS hook */ + if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, + pRetCert, pRetKey) + || NULL == *pRetCert) { + + if(NULL == nickname) + failf(data, "NSS: client certificate not found (nickname not " + "specified)"); + else + failf(data, "NSS: client certificate not found: %s", nickname); + + return SECFailure; + } + + /* get certificate nickname if any */ + nickname = (*pRetCert)->nickname; + if(NULL == nickname) + nickname = "[unknown]"; + + if(!strncmp(nickname, pem_slotname, sizeof(pem_slotname) - 1U)) { + failf(data, "NSS: refusing previously loaded certificate from file: %s", + nickname); + return SECFailure; + } + + if(NULL == *pRetKey) { + failf(data, "NSS: private key not found for certificate: %s", nickname); + return SECFailure; + } + + infof(data, "NSS: using client certificate: %s\n", nickname); + display_cert_info(data, *pRetCert); + return SECSuccess; +} + +/* update blocking direction in case of PR_WOULD_BLOCK_ERROR */ +static void nss_update_connecting_state(ssl_connect_state state, void *secret) +{ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret; + if(PR_GetError() != PR_WOULD_BLOCK_ERROR) + /* an unrelated error is passing by */ + return; + + switch(connssl->connecting_state) { + case ssl_connect_2: + case ssl_connect_2_reading: + case ssl_connect_2_writing: + break; + default: + /* we are not called from an SSL handshake */ + return; + } + + /* update the state accordingly */ + connssl->connecting_state = state; +} + +/* recv() wrapper we use to detect blocking direction during SSL handshake */ +static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, + PRIntn flags, PRIntervalTime timeout) +{ + const PRRecvFN recv_fn = fd->lower->methods->recv; + const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout); + if(rv < 0) + /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ + nss_update_connecting_state(ssl_connect_2_reading, fd->secret); + return rv; +} + +/* send() wrapper we use to detect blocking direction during SSL handshake */ +static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, + PRIntn flags, PRIntervalTime timeout) +{ + const PRSendFN send_fn = fd->lower->methods->send; + const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout); + if(rv < 0) + /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ + nss_update_connecting_state(ssl_connect_2_writing, fd->secret); + return rv; +} + +/* close() wrapper to avoid assertion failure due to fd->secret != NULL */ +static PRStatus nspr_io_close(PRFileDesc *fd) +{ + const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close; + fd->secret = NULL; + return close_fn(fd); +} + +/* load a PKCS #11 module */ +static CURLcode nss_load_module(SECMODModule **pmod, const char *library, + const char *name) +{ + char *config_string; + SECMODModule *module = *pmod; + if(module) + /* already loaded */ + return CURLE_OK; + + config_string = aprintf("library=%s name=%s", library, name); + if(!config_string) + return CURLE_OUT_OF_MEMORY; + + module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE); + free(config_string); + + if(module && module->loaded) { + /* loaded successfully */ + *pmod = module; + return CURLE_OK; + } + + if(module) + SECMOD_DestroyModule(module); + return CURLE_FAILED_INIT; +} + +/* unload a PKCS #11 module */ +static void nss_unload_module(SECMODModule **pmod) +{ + SECMODModule *module = *pmod; + if(!module) + /* not loaded */ + return; + + if(SECMOD_UnloadUserModule(module) != SECSuccess) + /* unload failed */ + return; + + SECMOD_DestroyModule(module); + *pmod = NULL; +} + +/* data might be NULL */ +static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) +{ + NSSInitParameters initparams; + PRErrorCode err; + const char *err_name; + + if(nss_context != NULL) + return CURLE_OK; + + memset((void *) &initparams, '\0', sizeof(initparams)); + initparams.length = sizeof(initparams); + + if(cert_dir) { + char *certpath = aprintf("sql:%s", cert_dir); + if(!certpath) + return CURLE_OUT_OF_MEMORY; + + infof(data, "Initializing NSS with certpath: %s\n", certpath); + nss_context = NSS_InitContext(certpath, "", "", "", &initparams, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); + free(certpath); + + if(nss_context != NULL) + return CURLE_OK; + + err = PR_GetError(); + err_name = nss_error_to_name(err); + infof(data, "Unable to initialize NSS database: %d (%s)\n", err, err_name); + } + + infof(data, "Initializing NSS with certpath: none\n"); + nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY + | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN + | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); + if(nss_context != NULL) + return CURLE_OK; + + err = PR_GetError(); + err_name = nss_error_to_name(err); + failf(data, "Unable to initialize NSS: %d (%s)", err, err_name); + return CURLE_SSL_CACERT_BADFILE; +} + +/* data might be NULL */ +static CURLcode nss_init(struct Curl_easy *data) +{ + char *cert_dir; + struct_stat st; + CURLcode result; + + if(initialized) + return CURLE_OK; + + /* list of all CRL items we need to destroy in Curl_nss_cleanup() */ + Curl_llist_init(&nss_crl_list, nss_destroy_crl_item); + + /* First we check if $SSL_DIR points to a valid dir */ + cert_dir = getenv("SSL_DIR"); + if(cert_dir) { + if((stat(cert_dir, &st) != 0) || + (!S_ISDIR(st.st_mode))) { + cert_dir = NULL; + } + } + + /* Now we check if the default location is a valid dir */ + if(!cert_dir) { + if((stat(SSL_DIR, &st) == 0) && + (S_ISDIR(st.st_mode))) { + cert_dir = (char *)SSL_DIR; + } + } + + if(nspr_io_identity == PR_INVALID_IO_LAYER) { + /* allocate an identity for our own NSPR I/O layer */ + nspr_io_identity = PR_GetUniqueIdentity("libcurl"); + if(nspr_io_identity == PR_INVALID_IO_LAYER) + return CURLE_OUT_OF_MEMORY; + + /* the default methods just call down to the lower I/O layer */ + memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), + sizeof(nspr_io_methods)); + + /* override certain methods in the table by our wrappers */ + nspr_io_methods.recv = nspr_io_recv; + nspr_io_methods.send = nspr_io_send; + nspr_io_methods.close = nspr_io_close; + } + + result = nss_init_core(data, cert_dir); + if(result) + return result; + + if(!any_cipher_enabled()) + NSS_SetDomesticPolicy(); + + initialized = 1; + + return CURLE_OK; +} + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +static int Curl_nss_init(void) +{ + /* curl_global_init() is not thread-safe so this test is ok */ + if(nss_initlock == NULL) { + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); + nss_initlock = PR_NewLock(); + nss_crllock = PR_NewLock(); + nss_findslot_lock = PR_NewLock(); + nss_trustload_lock = PR_NewLock(); + } + + /* We will actually initialize NSS later */ + + return 1; +} + +/* data might be NULL */ +CURLcode Curl_nss_force_init(struct Curl_easy *data) +{ + CURLcode result; + if(!nss_initlock) { + if(data) + failf(data, "unable to initialize NSS, curl_global_init() should have " + "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); + return CURLE_FAILED_INIT; + } + + PR_Lock(nss_initlock); + result = nss_init(data); + PR_Unlock(nss_initlock); + + return result; +} + +/* Global cleanup */ +static void Curl_nss_cleanup(void) +{ + /* This function isn't required to be threadsafe and this is only done + * as a safety feature. + */ + PR_Lock(nss_initlock); + if(initialized) { + /* Free references to client certificates held in the SSL session cache. + * Omitting this hampers destruction of the security module owning + * the certificates. */ + SSL_ClearSessionCache(); + + nss_unload_module(&pem_module); + nss_unload_module(&trust_module); + NSS_ShutdownContext(nss_context); + nss_context = NULL; + } + + /* destroy all CRL items */ + Curl_llist_destroy(&nss_crl_list, NULL); + + PR_Unlock(nss_initlock); + + PR_DestroyLock(nss_initlock); + PR_DestroyLock(nss_crllock); + PR_DestroyLock(nss_findslot_lock); + PR_DestroyLock(nss_trustload_lock); + nss_initlock = NULL; + + initialized = 0; +} + +/* + * This function uses SSL_peek to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +static int Curl_nss_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + int rc; + char buf; + + rc = + PR_Recv(BACKEND->handle, (void *)&buf, 1, PR_MSG_PEEK, + PR_SecondsToInterval(1)); + if(rc > 0) + return 1; /* connection still in place */ + + if(rc == 0) + return 0; /* connection has been closed */ + + return -1; /* connection status unknown */ +} + +static void nss_close(struct ssl_connect_data *connssl) +{ + /* before the cleanup, check whether we are using a client certificate */ + const bool client_cert = (BACKEND->client_nickname != NULL) + || (BACKEND->obj_clicert != NULL); + + free(BACKEND->client_nickname); + BACKEND->client_nickname = NULL; + + /* destroy all NSS objects in order to avoid failure of NSS shutdown */ + Curl_llist_destroy(&BACKEND->obj_list, NULL); + BACKEND->obj_clicert = NULL; + + if(BACKEND->handle) { + if(client_cert) + /* A server might require different authentication based on the + * particular path being requested by the client. To support this + * scenario, we must ensure that a connection will never reuse the + * authentication data from a previous connection. */ + SSL_InvalidateSession(BACKEND->handle); + + PR_Close(BACKEND->handle); + BACKEND->handle = NULL; + } +} + +/* + * This function is called when an SSL connection is closed. + */ +static void Curl_nss_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; + + if(BACKEND->handle || connssl_proxy->backend->handle) { + /* NSS closes the socket we previously handed to it, so we must mark it + as closed to avoid double close */ + fake_sclose(conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + } + + if(BACKEND->handle) + /* nss_close(connssl) will transitively close also + connssl_proxy->backend->handle if both are used. Clear it to avoid + a double close leading to crash. */ + connssl_proxy->backend->handle = NULL; + + nss_close(connssl); + nss_close(connssl_proxy); +} + +/* return true if NSS can provide error code (and possibly msg) for the + error */ +static bool is_nss_error(CURLcode err) +{ + switch(err) { + case CURLE_PEER_FAILED_VERIFICATION: + case CURLE_SSL_CERTPROBLEM: + case CURLE_SSL_CONNECT_ERROR: + case CURLE_SSL_ISSUER_ERROR: + return true; + + default: + return false; + } +} + +/* return true if the given error code is related to a client certificate */ +static bool is_cc_error(PRInt32 err) +{ + switch(err) { + case SSL_ERROR_BAD_CERT_ALERT: + case SSL_ERROR_EXPIRED_CERT_ALERT: + case SSL_ERROR_REVOKED_CERT_ALERT: + return true; + + default: + return false; + } +} + +static Curl_recv nss_recv; +static Curl_send nss_send; + +static CURLcode nss_load_ca_certificates(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + const char *cafile = SSL_CONN_CONFIG(CAfile); + const char *capath = SSL_CONN_CONFIG(CApath); + bool use_trust_module; + CURLcode result = CURLE_OK; + + /* treat empty string as unset */ + if(cafile && !cafile[0]) + cafile = NULL; + if(capath && !capath[0]) + capath = NULL; + + infof(data, " CAfile: %s\n CApath: %s\n", + cafile ? cafile : "none", + capath ? capath : "none"); + + /* load libnssckbi.so if no other trust roots were specified */ + use_trust_module = !cafile && !capath; + + PR_Lock(nss_trustload_lock); + if(use_trust_module && !trust_module) { + /* libnssckbi.so needed but not yet loaded --> load it! */ + result = nss_load_module(&trust_module, trust_library, "trust"); + infof(data, "%s %s\n", (result) ? "failed to load" : "loaded", + trust_library); + if(result == CURLE_FAILED_INIT) + /* If libnssckbi.so is not available (or fails to load), one can still + use CA certificates stored in NSS database. Ignore the failure. */ + result = CURLE_OK; + } + else if(!use_trust_module && trust_module) { + /* libnssckbi.so not needed but already loaded --> unload it! */ + infof(data, "unloading %s\n", trust_library); + nss_unload_module(&trust_module); + } + PR_Unlock(nss_trustload_lock); + + if(cafile) + result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); + + if(result) + return result; + + if(capath) { + struct_stat st; + if(stat(capath, &st) == -1) + return CURLE_SSL_CACERT_BADFILE; + + if(S_ISDIR(st.st_mode)) { + PRDirEntry *entry; + PRDir *dir = PR_OpenDir(capath); + if(!dir) + return CURLE_SSL_CACERT_BADFILE; + + while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) { + char *fullpath = aprintf("%s/%s", capath, entry->name); + if(!fullpath) { + PR_CloseDir(dir); + return CURLE_OUT_OF_MEMORY; + } + + if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) + /* This is purposefully tolerant of errors so non-PEM files can + * be in the same directory */ + infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath); + + free(fullpath); + } + + PR_CloseDir(dir); + } + else + infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath); + } + + return CURLE_OK; +} + +static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version) +{ + switch(version) { + case CURL_SSLVERSION_SSLv2: + *nssver = SSL_LIBRARY_VERSION_2; + return CURLE_OK; + + case CURL_SSLVERSION_SSLv3: + *nssver = SSL_LIBRARY_VERSION_3_0; + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1_0: + *nssver = SSL_LIBRARY_VERSION_TLS_1_0; + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1_1: +#ifdef SSL_LIBRARY_VERSION_TLS_1_1 + *nssver = SSL_LIBRARY_VERSION_TLS_1_1; + return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; +#endif + + case CURL_SSLVERSION_TLSv1_2: +#ifdef SSL_LIBRARY_VERSION_TLS_1_2 + *nssver = SSL_LIBRARY_VERSION_TLS_1_2; + return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; +#endif + + case CURL_SSLVERSION_TLSv1_3: +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + *nssver = SSL_LIBRARY_VERSION_TLS_1_3; + return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; +#endif + + default: + return CURLE_SSL_CONNECT_ERROR; + } +} + +static CURLcode nss_init_sslver(SSLVersionRange *sslver, + struct Curl_easy *data, + struct connectdata *conn) +{ + CURLcode result; + const long min = SSL_CONN_CONFIG(version); + const long max = SSL_CONN_CONFIG(version_max); + + /* map CURL_SSLVERSION_DEFAULT to NSS default */ + if(min == CURL_SSLVERSION_DEFAULT || max == CURL_SSLVERSION_MAX_DEFAULT) { + /* map CURL_SSLVERSION_DEFAULT to NSS default */ + if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess) + return CURLE_SSL_CONNECT_ERROR; + /* ... but make sure we use at least TLSv1.0 according to libcurl API */ + if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0) + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + } + + switch(min) { + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_DEFAULT: + break; + default: + result = nss_sslver_from_curl(&sslver->min, min); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + } + + switch(max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + break; + default: + result = nss_sslver_from_curl(&sslver->max, max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + } + + return CURLE_OK; +} + +static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, + struct Curl_easy *data, + CURLcode curlerr) +{ + PRErrorCode err = 0; + + if(is_nss_error(curlerr)) { + /* read NSPR error code */ + err = PR_GetError(); + if(is_cc_error(err)) + curlerr = CURLE_SSL_CERTPROBLEM; + + /* print the error number and error string */ + infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(data, err); + } + + /* cleanup on connection failure */ + Curl_llist_destroy(&BACKEND->obj_list, NULL); + + return curlerr; +} + +/* Switch the SSL socket into blocking or non-blocking mode. */ +static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, + struct Curl_easy *data, + bool blocking) +{ + static PRSocketOptionData sock_opt; + sock_opt.option = PR_SockOpt_Nonblocking; + sock_opt.value.non_blocking = !blocking; + + if(PR_SetSocketOption(BACKEND->handle, &sock_opt) != PR_SUCCESS) + return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); + + return CURLE_OK; +} + +static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) +{ + PRFileDesc *model = NULL; + PRFileDesc *nspr_io = NULL; + PRFileDesc *nspr_io_stub = NULL; + PRBool ssl_no_cache; + PRBool ssl_cbc_random_iv; + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CURLcode result; + bool second_layer = FALSE; + SSLVersionRange sslver_supported; + + SSLVersionRange sslver = { + SSL_LIBRARY_VERSION_TLS_1_0, /* min */ +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + SSL_LIBRARY_VERSION_TLS_1_3 /* max */ +#elif defined SSL_LIBRARY_VERSION_TLS_1_2 + SSL_LIBRARY_VERSION_TLS_1_2 +#elif defined SSL_LIBRARY_VERSION_TLS_1_1 + SSL_LIBRARY_VERSION_TLS_1_1 +#else + SSL_LIBRARY_VERSION_TLS_1_0 +#endif + }; + + BACKEND->data = data; + + /* list of all NSS objects we need to destroy in Curl_nss_close() */ + Curl_llist_init(&BACKEND->obj_list, nss_destroy_object); + + PR_Lock(nss_initlock); + result = nss_init(conn->data); + if(result) { + PR_Unlock(nss_initlock); + goto error; + } + + PK11_SetPasswordFunc(nss_get_password); + + result = nss_load_module(&pem_module, pem_library, "PEM"); + PR_Unlock(nss_initlock); + if(result == CURLE_FAILED_INIT) + infof(data, "WARNING: failed to load NSS PEM library %s. Using " + "OpenSSL PEM certificates will not work.\n", pem_library); + else if(result) + goto error; + + result = CURLE_SSL_CONNECT_ERROR; + + model = PR_NewTCPSocket(); + if(!model) + goto error; + model = SSL_ImportFD(NULL, model); + + if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess) + goto error; + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess) + goto error; + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess) + goto error; + + /* do not use SSL cache if disabled or we are not going to verify peer */ + ssl_no_cache = (SSL_SET_OPTION(primary.sessionid) + && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE; + if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) + goto error; + + /* enable/disable the requested SSL version(s) */ + if(nss_init_sslver(&sslver, data, conn) != CURLE_OK) + goto error; + if(SSL_VersionRangeGetSupported(ssl_variant_stream, + &sslver_supported) != SECSuccess) + goto error; + if(sslver_supported.max < sslver.max && sslver_supported.max >= sslver.min) { + char *sslver_req_str, *sslver_supp_str; + sslver_req_str = nss_sslver_to_name(sslver.max); + sslver_supp_str = nss_sslver_to_name(sslver_supported.max); + if(sslver_req_str && sslver_supp_str) + infof(data, "Falling back from %s to max supported SSL version (%s)\n", + sslver_req_str, sslver_supp_str); + free(sslver_req_str); + free(sslver_supp_str); + sslver.max = sslver_supported.max; + } + if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) + goto error; + + ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast); +#ifdef SSL_CBC_RANDOM_IV + /* unless the user explicitly asks to allow the protocol vulnerability, we + use the work-around */ + if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess) + infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n", + ssl_cbc_random_iv); +#else + if(ssl_cbc_random_iv) + infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n"); +#endif + + if(SSL_CONN_CONFIG(cipher_list)) { + if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) { + result = CURLE_SSL_CIPHER; + goto error; + } + } + + if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost)) + infof(data, "warning: ignoring value of ssl.verifyhost\n"); + + /* bypass the default SSL_AuthCertificate() hook in case we do not want to + * verify peer */ + if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess) + goto error; + + /* not checked yet */ + if(SSL_IS_PROXY()) + data->set.proxy_ssl.certverifyresult = 0; + else + data->set.ssl.certverifyresult = 0; + + if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess) + goto error; + + if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess) + goto error; + + { + const CURLcode rv = nss_load_ca_certificates(conn, sockindex); + if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer)) + /* not a fatal error because we are not going to verify the peer */ + infof(data, "warning: CA certificates failed to load\n"); + else if(rv) { + result = rv; + goto error; + } + } + + if(SSL_SET_OPTION(CRLfile)) { + const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile)); + if(rv) { + result = rv; + goto error; + } + infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile)); + } + + if(SSL_SET_OPTION(cert)) { + char *nickname = dup_nickname(data, SSL_SET_OPTION(cert)); + if(nickname) { + /* we are not going to use libnsspem.so to read the client cert */ + BACKEND->obj_clicert = NULL; + } + else { + CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert), + SSL_SET_OPTION(key)); + if(rv) { + /* failf() is already done in cert_stuff() */ + result = rv; + goto error; + } + } + + /* store the nickname for SelectClientCert() called during handshake */ + BACKEND->client_nickname = nickname; + } + else + BACKEND->client_nickname = NULL; + + if(SSL_GetClientAuthDataHook(model, SelectClientCert, + (void *)connssl) != SECSuccess) { + result = CURLE_SSL_CERTPROBLEM; + goto error; + } + + if(conn->proxy_ssl[sockindex].use) { + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL); + nspr_io = conn->proxy_ssl[sockindex].backend->handle; + second_layer = TRUE; + } + else { + /* wrap OS file descriptor by NSPR's file descriptor abstraction */ + nspr_io = PR_ImportTCPSocket(sockfd); + if(!nspr_io) + goto error; + } + + /* create our own NSPR I/O layer */ + nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods); + if(!nspr_io_stub) { + if(!second_layer) + PR_Close(nspr_io); + goto error; + } + + /* make the per-connection data accessible from NSPR I/O callbacks */ + nspr_io_stub->secret = (void *)connssl; + + /* push our new layer to the NSPR I/O stack */ + if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) { + if(!second_layer) + PR_Close(nspr_io); + PR_Close(nspr_io_stub); + goto error; + } + + /* import our model socket onto the current I/O stack */ + BACKEND->handle = SSL_ImportFD(model, nspr_io); + if(!BACKEND->handle) { + if(!second_layer) + PR_Close(nspr_io); + goto error; + } + + PR_Close(model); /* We don't need this any more */ + model = NULL; + + /* This is the password associated with the cert that we're using */ + if(SSL_SET_OPTION(key_passwd)) { + SSL_SetPKCS11PinArg(BACKEND->handle, SSL_SET_OPTION(key_passwd)); + } + +#ifdef SSL_ENABLE_OCSP_STAPLING + if(SSL_CONN_CONFIG(verifystatus)) { + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) + != SECSuccess) + goto error; + } +#endif + +#ifdef SSL_ENABLE_NPN + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn + ? PR_TRUE : PR_FALSE) != SECSuccess) + goto error; +#endif + +#ifdef SSL_ENABLE_ALPN + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn + ? PR_TRUE : PR_FALSE) != SECSuccess) + goto error; +#endif + +#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ + if(data->set.ssl.falsestart) { + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_FALSE_START, PR_TRUE) + != SECSuccess) + goto error; + + if(SSL_SetCanFalseStartCallback(BACKEND->handle, CanFalseStartCallback, + conn) != SECSuccess) + goto error; + } +#endif + +#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) + if(conn->bits.tls_enable_npn || conn->bits.tls_enable_alpn) { + int cur = 0; + unsigned char protocols[128]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN); + cur += NGHTTP2_PROTO_VERSION_ID_LEN; + } +#endif + protocols[cur++] = ALPN_HTTP_1_1_LENGTH; + memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + cur += ALPN_HTTP_1_1_LENGTH; + + if(SSL_SetNextProtoNego(BACKEND->handle, protocols, cur) != SECSuccess) + goto error; + } +#endif + + + /* Force handshake on next I/O */ + if(SSL_ResetHandshake(BACKEND->handle, /* asServer */ PR_FALSE) + != SECSuccess) + goto error; + + /* propagate hostname to the TLS layer */ + if(SSL_SetURL(BACKEND->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name) != SECSuccess) + goto error; + + /* prevent NSS from re-using the session for a different hostname */ + if(SSL_SetSockPeerID(BACKEND->handle, SSL_IS_PROXY() ? + conn->http_proxy.host.name : conn->host.name) + != SECSuccess) + goto error; + + return CURLE_OK; + +error: + if(model) + PR_Close(model); + + return nss_fail_connect(connssl, data, result); +} + +static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_SSL_CONNECT_ERROR; + PRUint32 timeout; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + + /* check timeout situation */ + const time_t time_left = Curl_timeleft(data, NULL, TRUE); + if(time_left < 0) { + failf(data, "timed out before SSL handshake"); + result = CURLE_OPERATION_TIMEDOUT; + goto error; + } + + /* Force the handshake now */ + timeout = PR_MillisecondsToInterval((PRUint32) time_left); + if(SSL_ForceHandshakeWithTimeout(BACKEND->handle, timeout) != SECSuccess) { + if(PR_GetError() == PR_WOULD_BLOCK_ERROR) + /* blocking direction is updated by nss_update_connecting_state() */ + return CURLE_AGAIN; + else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) + result = CURLE_PEER_FAILED_VERIFICATION; + else if(*certverifyresult != 0) + result = CURLE_PEER_FAILED_VERIFICATION; + goto error; + } + + result = display_conn_info(conn, BACKEND->handle); + if(result) + goto error; + + if(SSL_SET_OPTION(issuercert)) { + SECStatus ret = SECFailure; + char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert)); + if(nickname) { + /* we support only nicknames in case of issuercert for now */ + ret = check_issuer_cert(BACKEND->handle, nickname); + free(nickname); + } + + if(SECFailure == ret) { + infof(data, "SSL certificate issuer check failed\n"); + result = CURLE_SSL_ISSUER_ERROR; + goto error; + } + else { + infof(data, "SSL certificate issuer check ok\n"); + } + } + + result = cmp_peer_pubkey(connssl, pinnedpubkey); + if(result) + /* status already printed */ + goto error; + + return CURLE_OK; + +error: + return nss_fail_connect(connssl, data, result); +} + +static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, + bool *done) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + const bool blocking = (done == NULL); + CURLcode result; + + if(connssl->state == ssl_connection_complete) { + if(!blocking) + *done = TRUE; + return CURLE_OK; + } + + if(connssl->connecting_state == ssl_connect_1) { + result = nss_setup_connect(conn, sockindex); + if(result) + /* we do not expect CURLE_AGAIN from nss_setup_connect() */ + return result; + + connssl->connecting_state = ssl_connect_2; + } + + /* enable/disable blocking mode before handshake */ + result = nss_set_blocking(connssl, data, blocking); + if(result) + return result; + + result = nss_do_connect(conn, sockindex); + switch(result) { + case CURLE_OK: + break; + case CURLE_AGAIN: + if(!blocking) + /* CURLE_AGAIN in non-blocking mode is not an error */ + return CURLE_OK; + /* FALLTHROUGH */ + default: + return result; + } + + if(blocking) { + /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */ + result = nss_set_blocking(connssl, data, /* blocking */ FALSE); + if(result) + return result; + } + else + /* signal completed SSL handshake */ + *done = TRUE; + + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = nss_recv; + conn->send[sockindex] = nss_send; + + /* ssl_connect_done is never used outside, go back to the initial state */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) +{ + return nss_connect_common(conn, sockindex, /* blocking */ NULL); +} + +static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return nss_connect_common(conn, sockindex, done); +} + +static ssize_t nss_send(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + const void *mem, /* send this data */ + size_t len, /* amount to write */ + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ssize_t rc; + + /* The SelectClientCert() hook uses this for infof() and failf() but the + handle stored in nss_setup_connect() could have already been freed. */ + BACKEND->data = conn->data; + + rc = PR_Send(BACKEND->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT); + if(rc < 0) { + PRInt32 err = PR_GetError(); + if(err == PR_WOULD_BLOCK_ERROR) + *curlcode = CURLE_AGAIN; + else { + /* print the error number and error string */ + const char *err_name = nss_error_to_name(err); + infof(conn->data, "SSL write: error %d (%s)\n", err, err_name); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(conn->data, err); + + *curlcode = (is_cc_error(err)) + ? CURLE_SSL_CERTPROBLEM + : CURLE_SEND_ERROR; + } + + return -1; + } + + return rc; /* number of bytes */ +} + +static ssize_t nss_recv(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ssize_t nread; + + /* The SelectClientCert() hook uses this for infof() and failf() but the + handle stored in nss_setup_connect() could have already been freed. */ + BACKEND->data = conn->data; + + nread = PR_Recv(BACKEND->handle, buf, (int)buffersize, 0, + PR_INTERVAL_NO_WAIT); + if(nread < 0) { + /* failed SSL read */ + PRInt32 err = PR_GetError(); + + if(err == PR_WOULD_BLOCK_ERROR) + *curlcode = CURLE_AGAIN; + else { + /* print the error number and error string */ + const char *err_name = nss_error_to_name(err); + infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(conn->data, err); + + *curlcode = (is_cc_error(err)) + ? CURLE_SSL_CERTPROBLEM + : CURLE_RECV_ERROR; + } + + return -1; + } + + return nread; +} + +static size_t Curl_nss_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "NSS/%s", NSS_VERSION); +} + +/* data might be NULL */ +static int Curl_nss_seed(struct Curl_easy *data) +{ + /* make sure that NSS is initialized */ + return !!Curl_nss_force_init(data); +} + +/* data might be NULL */ +static CURLcode Curl_nss_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) +{ + Curl_nss_seed(data); /* Initiate the seed if not already done */ + + if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) + /* signal a failure */ + return CURLE_FAILED_INIT; + + return CURLE_OK; +} + +static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); + unsigned int MD5out; + + PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen)); + PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len)); + PK11_DestroyContext(MD5pw, PR_TRUE); + + return CURLE_OK; +} + +static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ + PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256); + unsigned int SHA256out; + + PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen)); + PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len)); + PK11_DestroyContext(SHA256pw, PR_TRUE); + + return CURLE_OK; +} + +static bool Curl_nss_cert_status_request(void) +{ +#ifdef SSL_ENABLE_OCSP_STAPLING + return TRUE; +#else + return FALSE; +#endif +} + +static bool Curl_nss_false_start(void) +{ +#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ + return TRUE; +#else + return FALSE; +#endif +} + +static void *Curl_nss_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_nss = { + { CURLSSLBACKEND_NSS, "nss" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY | + SSLSUPP_HTTPS_PROXY, + + sizeof(struct ssl_backend_data), + + Curl_nss_init, /* init */ + Curl_nss_cleanup, /* cleanup */ + Curl_nss_version, /* version */ + Curl_nss_check_cxn, /* check_cxn */ + /* NSS has no shutdown function provided and thus always fail */ + Curl_none_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_nss_random, /* random */ + Curl_nss_cert_status_request, /* cert_status_request */ + Curl_nss_connect, /* connect */ + Curl_nss_connect_nonblocking, /* connect_nonblocking */ + Curl_nss_get_internals, /* get_internals */ + Curl_nss_close, /* close_one */ + Curl_none_close_all, /* close_all */ + /* NSS has its own session ID cache */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_nss_false_start, /* false_start */ + Curl_nss_md5sum, /* md5sum */ + Curl_nss_sha256sum /* sha256sum */ +}; + +#endif /* USE_NSS */ diff --git a/libcurl/lib/vtls/nssg.h b/libcurl/lib/vtls/nssg.h new file mode 100644 index 0000000..41e51b0 --- /dev/null +++ b/libcurl/lib/vtls/nssg.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_NSSG_H +#define HEADER_CURL_NSSG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_NSS +/* + * This header should only be needed to get included by vtls.c and nss.c + */ + +#include "urldata.h" + +/* initialize NSS library if not already */ +CURLcode Curl_nss_force_init(struct Curl_easy *data); + +extern const struct Curl_ssl Curl_ssl_nss; + +#endif /* USE_NSS */ +#endif /* HEADER_CURL_NSSG_H */ diff --git a/libcurl/lib/vtls/openssl.c b/libcurl/lib/vtls/openssl.c new file mode 100644 index 0000000..fb9f271 --- /dev/null +++ b/libcurl/lib/vtls/openssl.c @@ -0,0 +1,3954 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +/* + * The original SSLeay-using code for curl was written by Linas Vepstas and + * Sampo Kellomaki 1998. + */ + +#include "curl_setup.h" + +#ifdef USE_OPENSSL + +#include + +#include "urldata.h" +#include "sendf.h" +#include "formdata.h" /* for the boundary function */ +#include "url.h" /* for the ssl config check function */ +#include "inet_pton.h" +#include "openssl.h" +#include "connect.h" +#include "slist.h" +#include "select.h" +#include "vtls.h" +#include "strcase.h" +#include "hostcheck.h" +#include "multiif.h" +#include "curl_printf.h" +#include +#include +#include +#ifndef OPENSSL_NO_DSA +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_AMISSL +#include "amigaos.h" +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP) +#include +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x0090700fL) && /* 0.9.7 or later */ \ + !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_UI_CONSOLE) +#define USE_OPENSSL_ENGINE +#include +#endif + +#include "warnless.h" +#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */ + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS + renegotiations when built with BoringSSL. Renegotiating is non-compliant + with HTTP/2 and "an extremely dangerous protocol feature". Beware. + +#define ALLOW_RENEG 1 + */ + +#ifndef OPENSSL_VERSION_NUMBER +#error "OPENSSL_VERSION_NUMBER not defined" +#endif + +#ifdef USE_OPENSSL_ENGINE +#include +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x00909000L +#define SSL_METHOD_QUAL const +#else +#define SSL_METHOD_QUAL +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) +#define HAVE_ERR_REMOVE_THREAD_STATE 1 +#endif + +#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \ + OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0+ has no SSLv2 */ +#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */ +#define OPENSSL_NO_SSL2 +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER +#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */ +#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */ +#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */ +#define CONST_EXTS const +#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1 + +/* funny typecast define due to difference in API */ +#ifdef LIBRESSL_VERSION_NUMBER +#define ARG2_X509_signature_print (X509_ALGOR *) +#else +#define ARG2_X509_signature_print +#endif + +#else +/* For OpenSSL before 1.1.0 */ +#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x) +#define X509_get0_notBefore(x) X509_get_notBefore(x) +#define X509_get0_notAfter(x) X509_get_notAfter(x) +#define CONST_EXTS /* nope */ +#ifndef LIBRESSL_VERSION_NUMBER +#define OpenSSL_version_num() SSLeay() +#endif +#endif + +#ifdef LIBRESSL_VERSION_NUMBER +#define OpenSSL_version_num() LIBRESSL_VERSION_NUMBER +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +#define HAVE_X509_GET0_SIGNATURE 1 +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) /* 1.0.2 or later */ +#define HAVE_SSL_GET_SHUTDOWN 1 +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10002003L && \ + OPENSSL_VERSION_NUMBER <= 0x10002FFFL && \ + !defined(OPENSSL_NO_COMP) +#define HAVE_SSL_COMP_FREE_COMPRESSION_METHODS 1 +#endif + +#if (OPENSSL_VERSION_NUMBER < 0x0090808fL) +/* not present in older OpenSSL */ +#define OPENSSL_load_builtin_modules(x) +#endif + +/* + * Whether SSL_CTX_set_keylog_callback is available. + * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287 + * BoringSSL: supported since d28f59c27bac (committed 2015-11-19) + * LibreSSL: unsupported in at least 2.7.2 (explicitly check for it since it + * lies and pretends to be OpenSSL 2.0.0). + */ +#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \ + !defined(LIBRESSL_VERSION_NUMBER)) || \ + defined(OPENSSL_IS_BORINGSSL) +#define HAVE_KEYLOG_CALLBACK +#endif + +/* Whether SSL_CTX_set_ciphersuites is available. + * OpenSSL: supported since 1.1.1 (commit a53b5be6a05) + * BoringSSL: no + * LibreSSL: no + */ +#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L) && \ + !defined(LIBRESSL_VERSION_NUMBER) && \ + !defined(OPENSSL_IS_BORINGSSL)) +#define HAVE_SSL_CTX_SET_CIPHERSUITES +#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH +#endif + +#if defined(LIBRESSL_VERSION_NUMBER) +#define OSSL_PACKAGE "LibreSSL" +#elif defined(OPENSSL_IS_BORINGSSL) +#define OSSL_PACKAGE "BoringSSL" +#else +#define OSSL_PACKAGE "OpenSSL" +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +/* up2date versions of OpenSSL maintain the default reasonably secure without + * breaking compatibility, so it is better not to override the default by curl + */ +#define DEFAULT_CIPHER_SELECTION NULL +#else +/* ... but it is not the case with old versions of OpenSSL */ +#define DEFAULT_CIPHER_SELECTION \ + "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH" +#endif + +#define ENABLE_SSLKEYLOGFILE + +#ifdef ENABLE_SSLKEYLOGFILE +typedef struct ssl_tap_state { + int master_key_length; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char client_random[SSL3_RANDOM_SIZE]; +} ssl_tap_state_t; +#endif /* ENABLE_SSLKEYLOGFILE */ + +struct ssl_backend_data { + /* these ones requires specific SSL-types */ + SSL_CTX* ctx; + SSL* handle; + X509* server_cert; +#ifdef ENABLE_SSLKEYLOGFILE + /* tap_state holds the last seen master key if we're logging them */ + ssl_tap_state_t tap_state; +#endif +}; + +#define BACKEND connssl->backend + +/* + * Number of bytes to read from the random number seed file. This must be + * a finite value (because some entropy "files" like /dev/urandom have + * an infinite length), but must be large enough to provide enough + * entropy to properly seed OpenSSL's PRNG. + */ +#define RAND_LOAD_LENGTH 1024 + +#ifdef ENABLE_SSLKEYLOGFILE +/* The fp for the open SSLKEYLOGFILE, or NULL if not open */ +static FILE *keylog_file_fp; + +#ifdef HAVE_KEYLOG_CALLBACK +static void ossl_keylog_callback(const SSL *ssl, const char *line) +{ + (void)ssl; + + /* Using fputs here instead of fprintf since libcurl's fprintf replacement + may not be thread-safe. */ + if(keylog_file_fp && line && *line) { + char stackbuf[256]; + char *buf; + size_t linelen = strlen(line); + + if(linelen <= sizeof(stackbuf) - 2) + buf = stackbuf; + else { + buf = malloc(linelen + 2); + if(!buf) + return; + } + memcpy(buf, line, linelen); + buf[linelen] = '\n'; + buf[linelen + 1] = '\0'; + + fputs(buf, keylog_file_fp); + if(buf != stackbuf) + free(buf); + } +} +#else +#define KEYLOG_PREFIX "CLIENT_RANDOM " +#define KEYLOG_PREFIX_LEN (sizeof(KEYLOG_PREFIX) - 1) +/* + * tap_ssl_key is called by libcurl to make the CLIENT_RANDOMs if the OpenSSL + * being used doesn't have native support for doing that. + */ +static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state) +{ + const char *hex = "0123456789ABCDEF"; + int pos, i; + char line[KEYLOG_PREFIX_LEN + 2 * SSL3_RANDOM_SIZE + 1 + + 2 * SSL_MAX_MASTER_KEY_LENGTH + 1 + 1]; + const SSL_SESSION *session = SSL_get_session(ssl); + unsigned char client_random[SSL3_RANDOM_SIZE]; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + int master_key_length = 0; + + if(!session || !keylog_file_fp) + return; + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) + /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that + * we have a valid SSL context if we have a non-NULL session. */ + SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE); + master_key_length = (int) + SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH); +#else + if(ssl->s3 && session->master_key_length > 0) { + master_key_length = session->master_key_length; + memcpy(master_key, session->master_key, session->master_key_length); + memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE); + } +#endif + + if(master_key_length <= 0) + return; + + /* Skip writing keys if there is no key or it did not change. */ + if(state->master_key_length == master_key_length && + !memcmp(state->master_key, master_key, master_key_length) && + !memcmp(state->client_random, client_random, SSL3_RANDOM_SIZE)) { + return; + } + + state->master_key_length = master_key_length; + memcpy(state->master_key, master_key, master_key_length); + memcpy(state->client_random, client_random, SSL3_RANDOM_SIZE); + + memcpy(line, KEYLOG_PREFIX, KEYLOG_PREFIX_LEN); + pos = KEYLOG_PREFIX_LEN; + + /* Client Random for SSLv3/TLS */ + for(i = 0; i < SSL3_RANDOM_SIZE; i++) { + line[pos++] = hex[client_random[i] >> 4]; + line[pos++] = hex[client_random[i] & 0xF]; + } + line[pos++] = ' '; + + /* Master Secret (size is at most SSL_MAX_MASTER_KEY_LENGTH) */ + for(i = 0; i < master_key_length; i++) { + line[pos++] = hex[master_key[i] >> 4]; + line[pos++] = hex[master_key[i] & 0xF]; + } + line[pos++] = '\n'; + line[pos] = '\0'; + + /* Using fputs here instead of fprintf since libcurl's fprintf replacement + may not be thread-safe. */ + fputs(line, keylog_file_fp); +} +#endif /* !HAVE_KEYLOG_CALLBACK */ +#endif /* ENABLE_SSLKEYLOGFILE */ + +static const char *SSL_ERROR_to_str(int err) +{ + switch(err) { + case SSL_ERROR_NONE: + return "SSL_ERROR_NONE"; + case SSL_ERROR_SSL: + return "SSL_ERROR_SSL"; + case SSL_ERROR_WANT_READ: + return "SSL_ERROR_WANT_READ"; + case SSL_ERROR_WANT_WRITE: + return "SSL_ERROR_WANT_WRITE"; + case SSL_ERROR_WANT_X509_LOOKUP: + return "SSL_ERROR_WANT_X509_LOOKUP"; + case SSL_ERROR_SYSCALL: + return "SSL_ERROR_SYSCALL"; + case SSL_ERROR_ZERO_RETURN: + return "SSL_ERROR_ZERO_RETURN"; + case SSL_ERROR_WANT_CONNECT: + return "SSL_ERROR_WANT_CONNECT"; + case SSL_ERROR_WANT_ACCEPT: + return "SSL_ERROR_WANT_ACCEPT"; +#if defined(SSL_ERROR_WANT_ASYNC) + case SSL_ERROR_WANT_ASYNC: + return "SSL_ERROR_WANT_ASYNC"; +#endif +#if defined(SSL_ERROR_WANT_ASYNC_JOB) + case SSL_ERROR_WANT_ASYNC_JOB: + return "SSL_ERROR_WANT_ASYNC_JOB"; +#endif +#if defined(SSL_ERROR_WANT_EARLY) + case SSL_ERROR_WANT_EARLY: + return "SSL_ERROR_WANT_EARLY"; +#endif + default: + return "SSL_ERROR unknown"; + } +} + +/* Return error string for last OpenSSL error + */ +static char *ossl_strerror(unsigned long error, char *buf, size_t size) +{ + ERR_error_string_n(error, buf, size); + return buf; +} + +/* Return an extra data index for the connection data. + * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). + */ +static int ossl_get_ssl_conn_index(void) +{ + static int ssl_ex_data_conn_index = -1; + if(ssl_ex_data_conn_index < 0) { + ssl_ex_data_conn_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + } + return ssl_ex_data_conn_index; +} + +/* Return an extra data index for the sockindex. + * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). + */ +static int ossl_get_ssl_sockindex_index(void) +{ + static int ssl_ex_data_sockindex_index = -1; + if(ssl_ex_data_sockindex_index < 0) { + ssl_ex_data_sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + } + return ssl_ex_data_sockindex_index; +} + +static int passwd_callback(char *buf, int num, int encrypting, + void *global_passwd) +{ + DEBUGASSERT(0 == encrypting); + + if(!encrypting) { + int klen = curlx_uztosi(strlen((char *)global_passwd)); + if(num > klen) { + memcpy(buf, global_passwd, klen + 1); + return klen; + } + } + return 0; +} + +/* + * rand_enough() returns TRUE if we have seeded the random engine properly. + */ +static bool rand_enough(void) +{ + return (0 != RAND_status()) ? TRUE : FALSE; +} + +static CURLcode Curl_ossl_seed(struct Curl_easy *data) +{ + /* we have the "SSL is seeded" boolean static to prevent multiple + time-consuming seedings in vain */ + static bool ssl_seeded = FALSE; + char fname[256]; + + if(ssl_seeded) + return CURLE_OK; + + if(rand_enough()) { + /* OpenSSL 1.1.0+ will return here */ + ssl_seeded = TRUE; + return CURLE_OK; + } + +#ifndef RANDOM_FILE + /* if RANDOM_FILE isn't defined, we only perform this if an option tells + us to! */ + if(data->set.str[STRING_SSL_RANDOM_FILE]) +#define RANDOM_FILE "" /* doesn't matter won't be used */ +#endif + { + /* let the option override the define */ + RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]? + data->set.str[STRING_SSL_RANDOM_FILE]: + RANDOM_FILE), + RAND_LOAD_LENGTH); + if(rand_enough()) + return CURLE_OK; + } + +#if defined(HAVE_RAND_EGD) + /* only available in OpenSSL 0.9.5 and later */ + /* EGD_SOCKET is set at configure time or not at all */ +#ifndef EGD_SOCKET + /* If we don't have the define set, we only do this if the egd-option + is set */ + if(data->set.str[STRING_SSL_EGDSOCKET]) +#define EGD_SOCKET "" /* doesn't matter won't be used */ +#endif + { + /* If there's an option and a define, the option overrides the + define */ + int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]? + data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET); + if(-1 != ret) { + if(rand_enough()) + return CURLE_OK; + } + } +#endif + + /* fallback to a custom seeding of the PRNG using a hash based on a current + time */ + do { + unsigned char randb[64]; + size_t len = sizeof(randb); + size_t i, i_max; + for(i = 0, i_max = len / sizeof(struct curltime); i < i_max; ++i) { + struct curltime tv = Curl_now(); + Curl_wait_ms(1); + tv.tv_sec *= i + 1; + tv.tv_usec *= (unsigned int)i + 2; + tv.tv_sec ^= ((Curl_now().tv_sec + Curl_now().tv_usec) * + (i + 3)) << 8; + tv.tv_usec ^= (unsigned int) ((Curl_now().tv_sec + + Curl_now().tv_usec) * + (i + 4)) << 16; + memcpy(&randb[i * sizeof(struct curltime)], &tv, + sizeof(struct curltime)); + } + RAND_add(randb, (int)len, (double)len/2); + } while(!rand_enough()); + + /* generates a default path for the random seed file */ + fname[0] = 0; /* blank it first */ + RAND_file_name(fname, sizeof(fname)); + if(fname[0]) { + /* we got a file name to try */ + RAND_load_file(fname, RAND_LOAD_LENGTH); + if(rand_enough()) + return CURLE_OK; + } + + infof(data, "libcurl is now using a weak random seed!\n"); + return (rand_enough() ? CURLE_OK : + CURLE_SSL_CONNECT_ERROR /* confusing error code */); +} + +#ifndef SSL_FILETYPE_ENGINE +#define SSL_FILETYPE_ENGINE 42 +#endif +#ifndef SSL_FILETYPE_PKCS12 +#define SSL_FILETYPE_PKCS12 43 +#endif +static int do_file_type(const char *type) +{ + if(!type || !type[0]) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "PEM")) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "DER")) + return SSL_FILETYPE_ASN1; + if(strcasecompare(type, "ENG")) + return SSL_FILETYPE_ENGINE; + if(strcasecompare(type, "P12")) + return SSL_FILETYPE_PKCS12; + return -1; +} + +#ifdef USE_OPENSSL_ENGINE +/* + * Supply default password to the engine user interface conversation. + * The password is passed by OpenSSL engine from ENGINE_load_private_key() + * last argument to the ui and can be obtained by UI_get0_user_data(ui) here. + */ +static int ssl_ui_reader(UI *ui, UI_STRING *uis) +{ + const char *password; + switch(UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + password = (const char *)UI_get0_user_data(ui); + if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { + UI_set_result(ui, uis, password); + return 1; + } + default: + break; + } + return (UI_method_get_reader(UI_OpenSSL()))(ui, uis); +} + +/* + * Suppress interactive request for a default password if available. + */ +static int ssl_ui_writer(UI *ui, UI_STRING *uis) +{ + switch(UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + if(UI_get0_user_data(ui) && + (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { + return 1; + } + default: + break; + } + return (UI_method_get_writer(UI_OpenSSL()))(ui, uis); +} + +/* + * Check if a given string is a PKCS#11 URI + */ +static bool is_pkcs11_uri(const char *string) +{ + return (string && strncasecompare(string, "pkcs11:", 7)); +} + +#endif + +static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, + const char *engine); + +static +int cert_stuff(struct connectdata *conn, + SSL_CTX* ctx, + char *cert_file, + const char *cert_type, + char *key_file, + const char *key_type, + char *key_passwd) +{ + struct Curl_easy *data = conn->data; + char error_buffer[256]; + bool check_privkey = TRUE; + + int file_type = do_file_type(cert_type); + + if(cert_file || (file_type == SSL_FILETYPE_ENGINE)) { + SSL *ssl; + X509 *x509; + int cert_done = 0; + + if(key_passwd) { + /* set the password in the callback userdata */ + SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd); + /* Set passwd callback: */ + SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); + } + + + switch(file_type) { + case SSL_FILETYPE_PEM: + /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ + if(SSL_CTX_use_certificate_chain_file(ctx, + cert_file) != 1) { + failf(data, + "could not load PEM client certificate, " OSSL_PACKAGE + " error %s, " + "(no key found, wrong pass phrase, or wrong file format?)", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + return 0; + } + break; + + case SSL_FILETYPE_ASN1: + /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but + we use the case above for PEM so this can only be performed with + ASN1 files. */ + if(SSL_CTX_use_certificate_file(ctx, + cert_file, + file_type) != 1) { + failf(data, + "could not load ASN1 client certificate, " OSSL_PACKAGE + " error %s, " + "(no key found, wrong pass phrase, or wrong file format?)", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + return 0; + } + break; + case SSL_FILETYPE_ENGINE: +#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME) + { + /* Implicitly use pkcs11 engine if none was provided and the + * cert_file is a PKCS#11 URI */ + if(!data->state.engine) { + if(is_pkcs11_uri(cert_file)) { + if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) { + return 0; + } + } + } + + if(data->state.engine) { + const char *cmd_name = "LOAD_CERT_CTRL"; + struct { + const char *cert_id; + X509 *cert; + } params; + + params.cert_id = cert_file; + params.cert = NULL; + + /* Does the engine supports LOAD_CERT_CTRL ? */ + if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME, + 0, (void *)cmd_name, NULL)) { + failf(data, "ssl engine does not support loading certificates"); + return 0; + } + + /* Load the certificate from the engine */ + if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name, + 0, ¶ms, NULL, 1)) { + failf(data, "ssl engine cannot load client cert with id" + " '%s' [%s]", cert_file, + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return 0; + } + + if(!params.cert) { + failf(data, "ssl engine didn't initialized the certificate " + "properly."); + return 0; + } + + if(SSL_CTX_use_certificate(ctx, params.cert) != 1) { + failf(data, "unable to set client certificate"); + X509_free(params.cert); + return 0; + } + X509_free(params.cert); /* we don't need the handle any more... */ + } + else { + failf(data, "crypto engine not set, can't load certificate"); + return 0; + } + } + break; +#else + failf(data, "file type ENG for certificate not implemented"); + return 0; +#endif + + case SSL_FILETYPE_PKCS12: + { + BIO *fp = NULL; + PKCS12 *p12 = NULL; + EVP_PKEY *pri; + STACK_OF(X509) *ca = NULL; + + fp = BIO_new(BIO_s_file()); + if(fp == NULL) { + failf(data, + "BIO_new return NULL, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + return 0; + } + + if(BIO_read_filename(fp, cert_file) <= 0) { + failf(data, "could not open PKCS12 file '%s'", cert_file); + BIO_free(fp); + return 0; + } + p12 = d2i_PKCS12_bio(fp, NULL); + BIO_free(fp); + + if(!p12) { + failf(data, "error reading PKCS12 file '%s'", cert_file); + return 0; + } + + PKCS12_PBE_add(); + + if(!PKCS12_parse(p12, key_passwd, &pri, &x509, + &ca)) { + failf(data, + "could not parse PKCS12 file, check password, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + PKCS12_free(p12); + return 0; + } + + PKCS12_free(p12); + + if(SSL_CTX_use_certificate(ctx, x509) != 1) { + failf(data, + "could not load PKCS12 client certificate, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + goto fail; + } + + if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { + failf(data, "unable to use private key from PKCS12 file '%s'", + cert_file); + goto fail; + } + + if(!SSL_CTX_check_private_key (ctx)) { + failf(data, "private key from PKCS12 file '%s' " + "does not match certificate in same file", cert_file); + goto fail; + } + /* Set Certificate Verification chain */ + if(ca) { + while(sk_X509_num(ca)) { + /* + * Note that sk_X509_pop() is used below to make sure the cert is + * removed from the stack properly before getting passed to + * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously + * we used sk_X509_value() instead, but then we'd clean it in the + * subsequent sk_X509_pop_free() call. + */ + X509 *x = sk_X509_pop(ca); + if(!SSL_CTX_add_client_CA(ctx, x)) { + X509_free(x); + failf(data, "cannot add certificate to client CA list"); + goto fail; + } + if(!SSL_CTX_add_extra_chain_cert(ctx, x)) { + X509_free(x); + failf(data, "cannot add certificate to certificate chain"); + goto fail; + } + } + } + + cert_done = 1; + fail: + EVP_PKEY_free(pri); + X509_free(x509); +#ifdef USE_AMISSL + sk_X509_pop_free(ca, Curl_amiga_X509_free); +#else + sk_X509_pop_free(ca, X509_free); +#endif + if(!cert_done) + return 0; /* failure! */ + break; + } + default: + failf(data, "not supported file type '%s' for certificate", cert_type); + return 0; + } + + if(!key_file) + key_file = cert_file; + else + file_type = do_file_type(key_type); + + switch(file_type) { + case SSL_FILETYPE_PEM: + if(cert_done) + break; + /* FALLTHROUGH */ + case SSL_FILETYPE_ASN1: + if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { + failf(data, "unable to set private key file: '%s' type %s", + key_file, key_type?key_type:"PEM"); + return 0; + } + break; + case SSL_FILETYPE_ENGINE: +#ifdef USE_OPENSSL_ENGINE + { /* XXXX still needs some work */ + EVP_PKEY *priv_key = NULL; + + /* Implicitly use pkcs11 engine if none was provided and the + * key_file is a PKCS#11 URI */ + if(!data->state.engine) { + if(is_pkcs11_uri(key_file)) { + if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) { + return 0; + } + } + } + + if(data->state.engine) { + UI_METHOD *ui_method = + UI_create_method((char *)"curl user interface"); + if(!ui_method) { + failf(data, "unable do create " OSSL_PACKAGE + " user-interface method"); + return 0; + } + UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL())); + UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL())); + UI_method_set_reader(ui_method, ssl_ui_reader); + UI_method_set_writer(ui_method, ssl_ui_writer); + /* the typecast below was added to please mingw32 */ + priv_key = (EVP_PKEY *) + ENGINE_load_private_key(data->state.engine, key_file, + ui_method, + key_passwd); + UI_destroy_method(ui_method); + if(!priv_key) { + failf(data, "failed to load private key from crypto engine"); + return 0; + } + if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { + failf(data, "unable to set private key"); + EVP_PKEY_free(priv_key); + return 0; + } + EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ + } + else { + failf(data, "crypto engine not set, can't load private key"); + return 0; + } + } + break; +#else + failf(data, "file type ENG for private key not supported"); + return 0; +#endif + case SSL_FILETYPE_PKCS12: + if(!cert_done) { + failf(data, "file type P12 for private key not supported"); + return 0; + } + break; + default: + failf(data, "not supported file type for private key"); + return 0; + } + + ssl = SSL_new(ctx); + if(!ssl) { + failf(data, "unable to create an SSL structure"); + return 0; + } + + x509 = SSL_get_certificate(ssl); + + /* This version was provided by Evan Jordan and is supposed to not + leak memory as the previous version: */ + if(x509) { + EVP_PKEY *pktmp = X509_get_pubkey(x509); + EVP_PKEY_copy_parameters(pktmp, SSL_get_privatekey(ssl)); + EVP_PKEY_free(pktmp); + } + +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_IS_BORINGSSL) + { + /* If RSA is used, don't check the private key if its flags indicate + * it doesn't support it. */ + EVP_PKEY *priv_key = SSL_get_privatekey(ssl); + int pktype; +#ifdef HAVE_OPAQUE_EVP_PKEY + pktype = EVP_PKEY_id(priv_key); +#else + pktype = priv_key->type; +#endif + if(pktype == EVP_PKEY_RSA) { + RSA *rsa = EVP_PKEY_get1_RSA(priv_key); + if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK) + check_privkey = FALSE; + RSA_free(rsa); /* Decrement reference count */ + } + } +#endif + + SSL_free(ssl); + + /* If we are using DSA, we can copy the parameters from + * the private key */ + + if(check_privkey == TRUE) { + /* Now we know that a key and cert have been set against + * the SSL context */ + if(!SSL_CTX_check_private_key(ctx)) { + failf(data, "Private key does not match the certificate public key"); + return 0; + } + } + } + return 1; +} + +/* returns non-zero on failure */ +static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) +{ +#if 0 + return X509_NAME_oneline(a, buf, size); +#else + BIO *bio_out = BIO_new(BIO_s_mem()); + BUF_MEM *biomem; + int rc; + + if(!bio_out) + return 1; /* alloc failed! */ + + rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC); + BIO_get_mem_ptr(bio_out, &biomem); + + if((size_t)biomem->length < size) + size = biomem->length; + else + size--; /* don't overwrite the buffer end */ + + memcpy(buf, biomem->data, size); + buf[size] = 0; + + BIO_free(bio_out); + + return !rc; +#endif +} + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +static int Curl_ossl_init(void) +{ +#ifdef ENABLE_SSLKEYLOGFILE + char *keylog_file_name; +#endif + + OPENSSL_load_builtin_modules(); + +#ifdef USE_OPENSSL_ENGINE + ENGINE_load_builtin_engines(); +#endif + +/* CONF_MFLAGS_DEFAULT_SECTION was introduced some time between 0.9.8b and + 0.9.8e */ +#ifndef CONF_MFLAGS_DEFAULT_SECTION +#define CONF_MFLAGS_DEFAULT_SECTION 0x0 +#endif + +#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG + CONF_modules_load_file(NULL, NULL, + CONF_MFLAGS_DEFAULT_SECTION| + CONF_MFLAGS_IGNORE_MISSING_FILE); +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ + !defined(LIBRESSL_VERSION_NUMBER) + /* OpenSSL 1.1.0+ takes care of initialization itself */ +#else + /* Lets get nice error messages */ + SSL_load_error_strings(); + + /* Init the global ciphers and digests */ + if(!SSLeay_add_ssl_algorithms()) + return 0; + + OpenSSL_add_all_algorithms(); +#endif + +#ifdef ENABLE_SSLKEYLOGFILE + if(!keylog_file_fp) { + keylog_file_name = curl_getenv("SSLKEYLOGFILE"); + if(keylog_file_name) { + keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT); + if(keylog_file_fp) { +#ifdef WIN32 + if(setvbuf(keylog_file_fp, NULL, _IONBF, 0)) +#else + if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) +#endif + { + fclose(keylog_file_fp); + keylog_file_fp = NULL; + } + } + Curl_safefree(keylog_file_name); + } + } +#endif + + /* Initialize the extra data indexes */ + if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0) + return 0; + + return 1; +} + +/* Global cleanup */ +static void Curl_ossl_cleanup(void) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ + !defined(LIBRESSL_VERSION_NUMBER) + /* OpenSSL 1.1 deprecates all these cleanup functions and + turns them into no-ops in OpenSSL 1.0 compatibility mode */ +#else + /* Free ciphers and digests lists */ + EVP_cleanup(); + +#ifdef USE_OPENSSL_ENGINE + /* Free engine list */ + ENGINE_cleanup(); +#endif + + /* Free OpenSSL error strings */ + ERR_free_strings(); + + /* Free thread local error state, destroying hash upon zero refcount */ +#ifdef HAVE_ERR_REMOVE_THREAD_STATE + ERR_remove_thread_state(NULL); +#else + ERR_remove_state(0); +#endif + + /* Free all memory allocated by all configuration modules */ + CONF_modules_free(); + +#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS + SSL_COMP_free_compression_methods(); +#endif +#endif + +#ifdef ENABLE_SSLKEYLOGFILE + if(keylog_file_fp) { + fclose(keylog_file_fp); + keylog_file_fp = NULL; + } +#endif +} + +/* + * This function is used to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +static int Curl_ossl_check_cxn(struct connectdata *conn) +{ + /* SSL_peek takes data out of the raw recv buffer without peeking so we use + recv MSG_PEEK instead. Bug #795 */ +#ifdef MSG_PEEK + char buf; + ssize_t nread; + nread = recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK); + if(nread == 0) + return 0; /* connection has been closed */ + if(nread == 1) + return 1; /* connection still in place */ + else if(nread == -1) { + int err = SOCKERRNO; + if(err == EINPROGRESS || +#if defined(EAGAIN) && (EAGAIN != EWOULDBLOCK) + err == EAGAIN || +#endif + err == EWOULDBLOCK) + return 1; /* connection still in place */ + if(err == ECONNRESET || +#ifdef ECONNABORTED + err == ECONNABORTED || +#endif +#ifdef ENETDOWN + err == ENETDOWN || +#endif +#ifdef ENETRESET + err == ENETRESET || +#endif +#ifdef ESHUTDOWN + err == ESHUTDOWN || +#endif +#ifdef ETIMEDOUT + err == ETIMEDOUT || +#endif + err == ENOTCONN) + return 0; /* connection has been closed */ + } +#endif + return -1; /* connection status unknown */ +} + +/* Selects an OpenSSL crypto engine + */ +static CURLcode Curl_ossl_set_engine(struct Curl_easy *data, + const char *engine) +{ +#ifdef USE_OPENSSL_ENGINE + ENGINE *e; + +#if OPENSSL_VERSION_NUMBER >= 0x00909000L + e = ENGINE_by_id(engine); +#else + /* avoid memory leak */ + for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { + const char *e_id = ENGINE_get_id(e); + if(!strcmp(engine, e_id)) + break; + } +#endif + + if(!e) { + failf(data, "SSL Engine '%s' not found", engine); + return CURLE_SSL_ENGINE_NOTFOUND; + } + + if(data->state.engine) { + ENGINE_finish(data->state.engine); + ENGINE_free(data->state.engine); + data->state.engine = NULL; + } + if(!ENGINE_init(e)) { + char buf[256]; + + ENGINE_free(e); + failf(data, "Failed to initialise SSL Engine '%s':\n%s", + engine, ossl_strerror(ERR_get_error(), buf, sizeof(buf))); + return CURLE_SSL_ENGINE_INITFAILED; + } + data->state.engine = e; + return CURLE_OK; +#else + (void)engine; + failf(data, "SSL Engine not supported"); + return CURLE_SSL_ENGINE_NOTFOUND; +#endif +} + +/* Sets engine as default for all SSL operations + */ +static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data) +{ +#ifdef USE_OPENSSL_ENGINE + if(data->state.engine) { + if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) { + infof(data, "set default crypto engine '%s'\n", + ENGINE_get_id(data->state.engine)); + } + else { + failf(data, "set default crypto engine '%s' failed", + ENGINE_get_id(data->state.engine)); + return CURLE_SSL_ENGINE_SETFAILED; + } + } +#else + (void) data; +#endif + return CURLE_OK; +} + +/* Return list of OpenSSL crypto engine names. + */ +static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) +{ + struct curl_slist *list = NULL; +#ifdef USE_OPENSSL_ENGINE + struct curl_slist *beg; + ENGINE *e; + + for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { + beg = curl_slist_append(list, ENGINE_get_id(e)); + if(!beg) { + curl_slist_free_all(list); + return NULL; + } + list = beg; + } +#endif + (void) data; + return list; +} + + +static void ossl_close(struct ssl_connect_data *connssl) +{ + if(BACKEND->handle) { + (void)SSL_shutdown(BACKEND->handle); + SSL_set_connect_state(BACKEND->handle); + + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + if(BACKEND->ctx) { + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = NULL; + } +} + +/* + * This function is called when an SSL connection is closed. + */ +static void Curl_ossl_close(struct connectdata *conn, int sockindex) +{ + ossl_close(&conn->ssl[sockindex]); + ossl_close(&conn->proxy_ssl[sockindex]); +} + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + char buf[256]; /* We will use this for the OpenSSL error buffer, so it has + to be at least 256 bytes long. */ + unsigned long sslerror; + ssize_t nread; + int buffsize; + int err; + bool done = FALSE; + +#ifndef CURL_DISABLE_FTP + /* This has only been tested on the proftpd server, and the mod_tls code + sends a close notify alert without waiting for a close notify alert in + response. Thus we wait for a close notify alert from the server, but + we do not send one. Let's hope other servers do the same... */ + + if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) + (void)SSL_shutdown(BACKEND->handle); +#endif + + if(BACKEND->handle) { + buffsize = (int)sizeof(buf); + while(!done) { + int what = SOCKET_READABLE(conn->sock[sockindex], + SSL_SHUTDOWN_TIMEOUT); + if(what > 0) { + ERR_clear_error(); + + /* Something to read, let's do it and hope that it is the close + notify alert from the server */ + nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize); + err = SSL_get_error(BACKEND->handle, (int)nread); + + switch(err) { + case SSL_ERROR_NONE: /* this is not an error */ + case SSL_ERROR_ZERO_RETURN: /* no more data */ + /* This is the expected response. There was no data but only + the close notify alert */ + done = TRUE; + break; + case SSL_ERROR_WANT_READ: + /* there's data pending, re-invoke SSL_read() */ + infof(data, "SSL_ERROR_WANT_READ\n"); + break; + case SSL_ERROR_WANT_WRITE: + /* SSL wants a write. Really odd. Let's bail out. */ + infof(data, "SSL_ERROR_WANT_WRITE\n"); + done = TRUE; + break; + default: + /* openssl/ssl.h says "look at error stack/return value/errno" */ + sslerror = ERR_get_error(); + failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d", + (sslerror ? + ossl_strerror(sslerror, buf, sizeof(buf)) : + SSL_ERROR_to_str(err)), + SOCKERRNO); + done = TRUE; + break; + } + } + else if(0 == what) { + /* timeout */ + failf(data, "SSL shutdown timeout"); + done = TRUE; + } + else { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + retval = -1; + done = TRUE; + } + } /* while()-loop for the select() */ + + if(data->set.verbose) { +#ifdef HAVE_SSL_GET_SHUTDOWN + switch(SSL_get_shutdown(BACKEND->handle)) { + case SSL_SENT_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n"); + break; + case SSL_RECEIVED_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n"); + break; + case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN: + infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|" + "SSL_RECEIVED__SHUTDOWN\n"); + break; + } +#endif + } + + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + return retval; +} + +static void Curl_ossl_session_free(void *ptr) +{ + /* free the ID */ + SSL_SESSION_free(ptr); +} + +/* + * This function is called when the 'data' struct is going away. Close + * down everything and free all resources! + */ +static void Curl_ossl_close_all(struct Curl_easy *data) +{ +#ifdef USE_OPENSSL_ENGINE + if(data->state.engine) { + ENGINE_finish(data->state.engine); + ENGINE_free(data->state.engine); + data->state.engine = NULL; + } +#else + (void)data; +#endif +#if !defined(HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED) && \ + defined(HAVE_ERR_REMOVE_THREAD_STATE) + /* OpenSSL 1.0.1 and 1.0.2 build an error queue that is stored per-thread + so we need to clean it here in case the thread will be killed. All OpenSSL + code should extract the error in association with the error so clearing + this queue here should be harmless at worst. */ + ERR_remove_thread_state(NULL); +#endif +} + +/* ====================================================== */ + +/* + * Match subjectAltName against the host name. This requires a conversion + * in CURL_DOES_CONVERSIONS builds. + */ +static bool subj_alt_hostcheck(struct Curl_easy *data, + const char *match_pattern, const char *hostname, + const char *dispname) +#ifdef CURL_DOES_CONVERSIONS +{ + bool res = FALSE; + + /* Curl_cert_hostcheck uses host encoding, but we get ASCII from + OpenSSl. + */ + char *match_pattern2 = strdup(match_pattern); + + if(match_pattern2) { + if(Curl_convert_from_network(data, match_pattern2, + strlen(match_pattern2)) == CURLE_OK) { + if(Curl_cert_hostcheck(match_pattern2, hostname)) { + res = TRUE; + infof(data, + " subjectAltName: host \"%s\" matched cert's \"%s\"\n", + dispname, match_pattern2); + } + } + free(match_pattern2); + } + else { + failf(data, + "SSL: out of memory when allocating temporary for subjectAltName"); + } + return res; +} +#else +{ +#ifdef CURL_DISABLE_VERBOSE_STRINGS + (void)dispname; + (void)data; +#endif + if(Curl_cert_hostcheck(match_pattern, hostname)) { + infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n", + dispname, match_pattern); + return TRUE; + } + return FALSE; +} +#endif + + +/* Quote from RFC2818 section 3.1 "Server Identity" + + If a subjectAltName extension of type dNSName is present, that MUST + be used as the identity. Otherwise, the (most specific) Common Name + field in the Subject field of the certificate MUST be used. Although + the use of the Common Name is existing practice, it is deprecated and + Certification Authorities are encouraged to use the dNSName instead. + + Matching is performed using the matching rules specified by + [RFC2459]. If more than one identity of a given type is present in + the certificate (e.g., more than one dNSName name, a match in any one + of the set is considered acceptable.) Names may contain the wildcard + character * which is considered to match any single domain name + component or component fragment. E.g., *.a.com matches foo.a.com but + not bar.foo.a.com. f*.com matches foo.com but not bar.com. + + In some cases, the URI is specified as an IP address rather than a + hostname. In this case, the iPAddress subjectAltName must be present + in the certificate and must exactly match the IP in the URI. + +*/ +static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) +{ + bool matched = FALSE; + int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */ + size_t addrlen = 0; + struct Curl_easy *data = conn->data; + STACK_OF(GENERAL_NAME) *altnames; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + CURLcode result = CURLE_OK; + bool dNSName = FALSE; /* if a dNSName field exists in the cert */ + bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */ + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + +#ifdef ENABLE_IPV6 + if(conn->bits.ipv6_ip && + Curl_inet_pton(AF_INET6, hostname, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in6_addr); + } + else +#endif + if(Curl_inet_pton(AF_INET, hostname, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in_addr); + } + + /* get a "list" of alternative names */ + altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL); + + if(altnames) { + int numalts; + int i; + bool dnsmatched = FALSE; + bool ipmatched = FALSE; + + /* get amount of alternatives, RFC2459 claims there MUST be at least + one, but we don't depend on it... */ + numalts = sk_GENERAL_NAME_num(altnames); + + /* loop through all alternatives - until a dnsmatch */ + for(i = 0; (i < numalts) && !dnsmatched; i++) { + /* get a handle to alternative name number i */ + const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i); + + if(check->type == GEN_DNS) + dNSName = TRUE; + else if(check->type == GEN_IPADD) + iPAddress = TRUE; + + /* only check alternatives of the same type the target is */ + if(check->type == target) { + /* get data and length */ + const char *altptr = (char *)ASN1_STRING_get0_data(check->d.ia5); + size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5); + + switch(target) { + case GEN_DNS: /* name/pattern comparison */ + /* The OpenSSL man page explicitly says: "In general it cannot be + assumed that the data returned by ASN1_STRING_data() is null + terminated or does not contain embedded nulls." But also that + "The actual format of the data will depend on the actual string + type itself: for example for and IA5String the data will be ASCII" + + Gisle researched the OpenSSL sources: + "I checked the 0.9.6 and 0.9.8 sources before my patch and + it always 0-terminates an IA5String." + */ + if((altlen == strlen(altptr)) && + /* if this isn't true, there was an embedded zero in the name + string and we cannot match it. */ + subj_alt_hostcheck(data, altptr, hostname, dispname)) { + dnsmatched = TRUE; + } + break; + + case GEN_IPADD: /* IP address comparison */ + /* compare alternative IP address if the data chunk is the same size + our server IP address is */ + if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) { + ipmatched = TRUE; + infof(data, + " subjectAltName: host \"%s\" matched cert's IP address!\n", + dispname); + } + break; + } + } + } + GENERAL_NAMES_free(altnames); + + if(dnsmatched || ipmatched) + matched = TRUE; + } + + if(matched) + /* an alternative name matched */ + ; + else if(dNSName || iPAddress) { + infof(data, " subjectAltName does not match %s\n", dispname); + failf(data, "SSL: no alternative certificate subject name matches " + "target host name '%s'", dispname); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else { + /* we have to look to the last occurrence of a commonName in the + distinguished one to get the most significant one. */ + int j, i = -1; + + /* The following is done because of a bug in 0.9.6b */ + + unsigned char *nulstr = (unsigned char *)""; + unsigned char *peer_CN = nulstr; + + X509_NAME *name = X509_get_subject_name(server_cert); + if(name) + while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0) + i = j; + + /* we have the name entry and we will now convert this to a string + that we can use for comparison. Doing this we support BMPstring, + UTF8 etc. */ + + if(i >= 0) { + ASN1_STRING *tmp = + X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + + /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input + is already UTF-8 encoded. We check for this case and copy the raw + string manually to avoid the problem. This code can be made + conditional in the future when OpenSSL has been fixed. Work-around + brought by Alexis S. L. Carvalho. */ + if(tmp) { + if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) { + j = ASN1_STRING_length(tmp); + if(j >= 0) { + peer_CN = OPENSSL_malloc(j + 1); + if(peer_CN) { + memcpy(peer_CN, ASN1_STRING_get0_data(tmp), j); + peer_CN[j] = '\0'; + } + } + } + else /* not a UTF8 name */ + j = ASN1_STRING_to_UTF8(&peer_CN, tmp); + + if(peer_CN && (curlx_uztosi(strlen((char *)peer_CN)) != j)) { + /* there was a terminating zero before the end of string, this + cannot match and we return failure! */ + failf(data, "SSL: illegal cert name field"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + } + } + + if(peer_CN == nulstr) + peer_CN = NULL; + else { + /* convert peer_CN from UTF8 */ + CURLcode rc = Curl_convert_from_utf8(data, (char *)peer_CN, + strlen((char *)peer_CN)); + /* Curl_convert_from_utf8 calls failf if unsuccessful */ + if(rc) { + OPENSSL_free(peer_CN); + return rc; + } + } + + if(result) + /* error already detected, pass through */ + ; + else if(!peer_CN) { + failf(data, + "SSL: unable to obtain common name from peer certificate"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { + failf(data, "SSL: certificate subject name '%s' does not match " + "target host name '%s'", peer_CN, dispname); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, " common name: %s (matched)\n", peer_CN); + } + if(peer_CN) + OPENSSL_free(peer_CN); + } + + return result; +} + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_NO_OCSP) +static CURLcode verifystatus(struct connectdata *conn, + struct ssl_connect_data *connssl) +{ + int i, ocsp_status; + unsigned char *status; + const unsigned char *p; + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + OCSP_RESPONSE *rsp = NULL; + OCSP_BASICRESP *br = NULL; + X509_STORE *st = NULL; + STACK_OF(X509) *ch = NULL; + + long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &status); + + if(!status) { + failf(data, "No OCSP response received"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + p = status; + rsp = d2i_OCSP_RESPONSE(NULL, &p, len); + if(!rsp) { + failf(data, "Invalid OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + ocsp_status = OCSP_response_status(rsp); + if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + failf(data, "Invalid OCSP response status: %s (%d)", + OCSP_response_status_str(ocsp_status), ocsp_status); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + br = OCSP_response_get1_basic(rsp); + if(!br) { + failf(data, "Invalid OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + ch = SSL_get_peer_cert_chain(BACKEND->handle); + st = SSL_CTX_get_cert_store(BACKEND->ctx); + +#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER <= 0x2040200fL)) + /* The authorized responder cert in the OCSP response MUST be signed by the + peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert, + no problem, but if it's an intermediate cert OpenSSL has a bug where it + expects this issuer to be present in the chain embedded in the OCSP + response. So we add it if necessary. */ + + /* First make sure the peer cert chain includes both a peer and an issuer, + and the OCSP response contains a responder cert. */ + if(sk_X509_num(ch) >= 2 && sk_X509_num(br->certs) >= 1) { + X509 *responder = sk_X509_value(br->certs, sk_X509_num(br->certs) - 1); + + /* Find issuer of responder cert and add it to the OCSP response chain */ + for(i = 0; i < sk_X509_num(ch); i++) { + X509 *issuer = sk_X509_value(ch, i); + if(X509_check_issued(issuer, responder) == X509_V_OK) { + if(!OCSP_basic_add1_cert(br, issuer)) { + failf(data, "Could not add issuer cert to OCSP response"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + } + } + } +#endif + + if(OCSP_basic_verify(br, ch, st, 0) <= 0) { + failf(data, "OCSP response verification failed"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + for(i = 0; i < OCSP_resp_count(br); i++) { + int cert_status, crl_reason; + OCSP_SINGLERESP *single = NULL; + + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + + single = OCSP_resp_get0(br, i); + if(!single) + continue; + + cert_status = OCSP_single_get0_status(single, &crl_reason, &rev, + &thisupd, &nextupd); + + if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { + failf(data, "OCSP response has expired"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + + infof(data, "SSL certificate status: %s (%d)\n", + OCSP_cert_status_str(cert_status), cert_status); + + switch(cert_status) { + case V_OCSP_CERTSTATUS_GOOD: + break; + + case V_OCSP_CERTSTATUS_REVOKED: + result = CURLE_SSL_INVALIDCERTSTATUS; + + failf(data, "SSL certificate revocation reason: %s (%d)", + OCSP_crl_reason_str(crl_reason), crl_reason); + goto end; + + case V_OCSP_CERTSTATUS_UNKNOWN: + result = CURLE_SSL_INVALIDCERTSTATUS; + goto end; + } + } + +end: + if(br) OCSP_BASICRESP_free(br); + OCSP_RESPONSE_free(rsp); + + return result; +} +#endif + +#endif /* USE_OPENSSL */ + +/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions + and thus this cannot be done there. */ +#ifdef SSL_CTRL_SET_MSG_CALLBACK + +static const char *ssl_msg_type(int ssl_ver, int msg) +{ +#ifdef SSL2_VERSION_MAJOR + if(ssl_ver == SSL2_VERSION_MAJOR) { + switch(msg) { + case SSL2_MT_ERROR: + return "Error"; + case SSL2_MT_CLIENT_HELLO: + return "Client hello"; + case SSL2_MT_CLIENT_MASTER_KEY: + return "Client key"; + case SSL2_MT_CLIENT_FINISHED: + return "Client finished"; + case SSL2_MT_SERVER_HELLO: + return "Server hello"; + case SSL2_MT_SERVER_VERIFY: + return "Server verify"; + case SSL2_MT_SERVER_FINISHED: + return "Server finished"; + case SSL2_MT_REQUEST_CERTIFICATE: + return "Request CERT"; + case SSL2_MT_CLIENT_CERTIFICATE: + return "Client CERT"; + } + } + else +#endif + if(ssl_ver == SSL3_VERSION_MAJOR) { + switch(msg) { + case SSL3_MT_HELLO_REQUEST: + return "Hello request"; + case SSL3_MT_CLIENT_HELLO: + return "Client hello"; + case SSL3_MT_SERVER_HELLO: + return "Server hello"; +#ifdef SSL3_MT_NEWSESSION_TICKET + case SSL3_MT_NEWSESSION_TICKET: + return "Newsession Ticket"; +#endif + case SSL3_MT_CERTIFICATE: + return "Certificate"; + case SSL3_MT_SERVER_KEY_EXCHANGE: + return "Server key exchange"; + case SSL3_MT_CLIENT_KEY_EXCHANGE: + return "Client key exchange"; + case SSL3_MT_CERTIFICATE_REQUEST: + return "Request CERT"; + case SSL3_MT_SERVER_DONE: + return "Server finished"; + case SSL3_MT_CERTIFICATE_VERIFY: + return "CERT verify"; + case SSL3_MT_FINISHED: + return "Finished"; +#ifdef SSL3_MT_CERTIFICATE_STATUS + case SSL3_MT_CERTIFICATE_STATUS: + return "Certificate Status"; +#endif +#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS + case SSL3_MT_ENCRYPTED_EXTENSIONS: + return "Encrypted Extensions"; +#endif +#ifdef SSL3_MT_END_OF_EARLY_DATA + case SSL3_MT_END_OF_EARLY_DATA: + return "End of early data"; +#endif +#ifdef SSL3_MT_KEY_UPDATE + case SSL3_MT_KEY_UPDATE: + return "Key update"; +#endif +#ifdef SSL3_MT_NEXT_PROTO + case SSL3_MT_NEXT_PROTO: + return "Next protocol"; +#endif +#ifdef SSL3_MT_MESSAGE_HASH + case SSL3_MT_MESSAGE_HASH: + return "Message hash"; +#endif + } + } + return "Unknown"; +} + +static const char *tls_rt_type(int type) +{ + switch(type) { +#ifdef SSL3_RT_HEADER + case SSL3_RT_HEADER: + return "TLS header"; +#endif + case SSL3_RT_CHANGE_CIPHER_SPEC: + return "TLS change cipher"; + case SSL3_RT_ALERT: + return "TLS alert"; + case SSL3_RT_HANDSHAKE: + return "TLS handshake"; + case SSL3_RT_APPLICATION_DATA: + return "TLS app data"; + default: + return "TLS Unknown"; + } +} + + +/* + * Our callback from the SSL/TLS layers. + */ +static void ssl_tls_trace(int direction, int ssl_ver, int content_type, + const void *buf, size_t len, SSL *ssl, + void *userp) +{ + struct Curl_easy *data; + char unknown[32]; + const char *verstr = NULL; + struct connectdata *conn = userp; + + if(!conn || !conn->data || !conn->data->set.fdebug || + (direction != 0 && direction != 1)) + return; + + data = conn->data; + + switch(ssl_ver) { +#ifdef SSL2_VERSION /* removed in recent versions */ + case SSL2_VERSION: + verstr = "SSLv2"; + break; +#endif +#ifdef SSL3_VERSION + case SSL3_VERSION: + verstr = "SSLv3"; + break; +#endif + case TLS1_VERSION: + verstr = "TLSv1.0"; + break; +#ifdef TLS1_1_VERSION + case TLS1_1_VERSION: + verstr = "TLSv1.1"; + break; +#endif +#ifdef TLS1_2_VERSION + case TLS1_2_VERSION: + verstr = "TLSv1.2"; + break; +#endif +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + verstr = "TLSv1.3"; + break; +#endif + case 0: + break; + default: + msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver); + verstr = unknown; + break; + } + + /* Log progress for interesting records only (like Handshake or Alert), skip + * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0). + * For TLS 1.3, skip notification of the decrypted inner Content Type. + */ + if(ssl_ver +#ifdef SSL3_RT_INNER_CONTENT_TYPE + && content_type != SSL3_RT_INNER_CONTENT_TYPE +#endif + ) { + const char *msg_name, *tls_rt_name; + char ssl_buf[1024]; + int msg_type, txt_len; + + /* the info given when the version is zero is not that useful for us */ + + ssl_ver >>= 8; /* check the upper 8 bits only below */ + + /* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL + * always pass-up content-type as 0. But the interesting message-type + * is at 'buf[0]'. + */ + if(ssl_ver == SSL3_VERSION_MAJOR && content_type) + tls_rt_name = tls_rt_type(content_type); + else + tls_rt_name = ""; + + if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + msg_type = *(char *)buf; + msg_name = "Change cipher spec"; + } + else if(content_type == SSL3_RT_ALERT) { + msg_type = (((char *)buf)[0] << 8) + ((char *)buf)[1]; + msg_name = SSL_alert_desc_string_long(msg_type); + } + else { + msg_type = *(char *)buf; + msg_name = ssl_msg_type(ssl_ver, msg_type); + } + + txt_len = msnprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n", + verstr, direction?"OUT":"IN", + tls_rt_name, msg_name, msg_type); + if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) { + Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len); + } + } + + Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT : + CURLINFO_SSL_DATA_IN, (char *)buf, len); + (void) ssl; +} +#endif + +#ifdef USE_OPENSSL +/* ====================================================== */ + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME +# define use_sni(x) sni = (x) +#else +# define use_sni(x) Curl_nop_stmt +#endif + +/* Check for OpenSSL 1.0.2 which has ALPN support. */ +#undef HAS_ALPN +#if OPENSSL_VERSION_NUMBER >= 0x10002000L \ + && !defined(OPENSSL_NO_TLSEXT) +# define HAS_ALPN 1 +#endif + +/* Check for OpenSSL 1.0.1 which has NPN support. */ +#undef HAS_NPN +#if OPENSSL_VERSION_NUMBER >= 0x10001000L \ + && !defined(OPENSSL_NO_TLSEXT) \ + && !defined(OPENSSL_NO_NEXTPROTONEG) +# define HAS_NPN 1 +#endif + +#ifdef HAS_NPN + +/* + * in is a list of length prefixed strings. this function has to select + * the protocol we want to use from the list and write its string into out. + */ + +static int +select_next_protocol(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const char *key, unsigned int keylen) +{ + unsigned int i; + for(i = 0; i + keylen <= inlen; i += in[i] + 1) { + if(memcmp(&in[i + 1], key, keylen) == 0) { + *out = (unsigned char *) &in[i + 1]; + *outlen = in[i]; + return 0; + } + } + return -1; +} + +static int +select_next_proto_cb(SSL *ssl, + unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + void *arg) +{ + struct connectdata *conn = (struct connectdata*) arg; + + (void)ssl; + +#ifdef USE_NGHTTP2 + if(conn->data->set.httpversion >= CURL_HTTP_VERSION_2 && + !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + infof(conn->data, "NPN, negotiated HTTP2 (%s)\n", + NGHTTP2_PROTO_VERSION_ID); + conn->negnpn = CURL_HTTP_VERSION_2; + return SSL_TLSEXT_ERR_OK; + } +#endif + + if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1, + ALPN_HTTP_1_1_LENGTH)) { + infof(conn->data, "NPN, negotiated HTTP1.1\n"); + conn->negnpn = CURL_HTTP_VERSION_1_1; + return SSL_TLSEXT_ERR_OK; + } + + infof(conn->data, "NPN, no overlap, use HTTP1.1\n"); + *out = (unsigned char *)ALPN_HTTP_1_1; + *outlen = ALPN_HTTP_1_1_LENGTH; + conn->negnpn = CURL_HTTP_VERSION_1_1; + + return SSL_TLSEXT_ERR_OK; +} +#endif /* HAS_NPN */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static const char * +get_ssl_version_txt(SSL *ssl) +{ + if(!ssl) + return ""; + + switch(SSL_version(ssl)) { +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + return "TLSv1.3"; +#endif +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + case TLS1_2_VERSION: + return "TLSv1.2"; + case TLS1_1_VERSION: + return "TLSv1.1"; +#endif + case TLS1_VERSION: + return "TLSv1.0"; + case SSL3_VERSION: + return "SSLv3"; + case SSL2_VERSION: + return "SSLv2"; + } + return "unknown"; +} +#endif + +static CURLcode +set_ssl_version_min_max(long *ctx_options, struct connectdata *conn, + int sockindex) +{ +#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION) + /* convoluted #if condition just to avoid compiler warnings on unused + variable */ + struct Curl_easy *data = conn->data; +#endif + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + + switch(ssl_version) { + case CURL_SSLVERSION_TLSv1_3: +#ifdef TLS1_3_VERSION + { + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SSL_CTX_set_max_proto_version(BACKEND->ctx, TLS1_3_VERSION); + *ctx_options |= SSL_OP_NO_TLSv1_2; + } +#else + (void)sockindex; + (void)ctx_options; + failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); + return CURLE_NOT_BUILT_IN; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_TLSv1_2: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_1; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.2 support"); + return CURLE_NOT_BUILT_IN; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_TLSv1_1: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.1 support"); + return CURLE_NOT_BUILT_IN; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1: + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_TLSv1_0: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_1; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_MAX_TLSv1_1: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_2; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_MAX_TLSv1_2: +#ifdef TLS1_3_VERSION + *ctx_options |= SSL_OP_NO_TLSv1_3; +#endif + break; + case CURL_SSLVERSION_MAX_TLSv1_3: +#ifdef TLS1_3_VERSION + break; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); + return CURLE_NOT_BUILT_IN; +#endif + } + return CURLE_OK; +} + +/* The "new session" callback must return zero if the session can be removed + * or non-zero if the session has been put into the session cache. + */ +static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) +{ + int res = 0; + struct connectdata *conn; + struct Curl_easy *data; + int sockindex; + curl_socket_t *sockindex_ptr; + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + + if(connectdata_idx < 0 || sockindex_idx < 0) + return 0; + + conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx); + if(!conn) + return 0; + + data = conn->data; + + /* The sockindex has been stored as a pointer to an array element */ + sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx); + sockindex = (int)(sockindex_ptr - conn->sock); + + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + void *old_ssl_sessionid = NULL; + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); + if(incache) { + if(old_ssl_sessionid != ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + if(!Curl_ssl_addsessionid(conn, ssl_sessionid, + 0 /* unknown size */, sockindex)) { + /* the session has been put into the session cache */ + res = 1; + } + else + failf(data, "failed to store ssl session"); + } + Curl_ssl_sessionid_unlock(conn); + } + + return res; +} + +static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + char *ciphers; + struct Curl_easy *data = conn->data; + SSL_METHOD_QUAL SSL_METHOD *req_method = NULL; + X509_LOOKUP *lookup = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long ctx_options = 0; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + bool sni; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif +#endif + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + const long int ssl_version = SSL_CONN_CONFIG(version); +#ifdef USE_TLS_SRP + const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); +#endif + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + char error_buffer[256]; + + DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); + + /* Make funny stuff to get random input */ + result = Curl_ossl_seed(data); + if(result) + return result; + + *certverifyresult = !X509_V_OK; + + /* check to see if we've been told to use an explicit SSL/TLS version */ + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + /* it will be handled later with the context options */ +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) + req_method = TLS_client_method(); +#else + req_method = SSLv23_client_method(); +#endif + use_sni(TRUE); + break; + case CURL_SSLVERSION_SSLv2: +#ifdef OPENSSL_NO_SSL2 + failf(data, OSSL_PACKAGE " was built without SSLv2 support"); + return CURLE_NOT_BUILT_IN; +#else +#ifdef USE_TLS_SRP + if(ssl_authtype == CURL_TLSAUTH_SRP) + return CURLE_SSL_CONNECT_ERROR; +#endif + req_method = SSLv2_client_method(); + use_sni(FALSE); + break; +#endif + case CURL_SSLVERSION_SSLv3: +#ifdef OPENSSL_NO_SSL3_METHOD + failf(data, OSSL_PACKAGE " was built without SSLv3 support"); + return CURLE_NOT_BUILT_IN; +#else +#ifdef USE_TLS_SRP + if(ssl_authtype == CURL_TLSAUTH_SRP) + return CURLE_SSL_CONNECT_ERROR; +#endif + req_method = SSLv3_client_method(); + use_sni(FALSE); + break; +#endif + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(BACKEND->ctx) + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = SSL_CTX_new(req_method); + + if(!BACKEND->ctx) { + failf(data, "SSL: couldn't create a context: %s", + ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); + return CURLE_OUT_OF_MEMORY; + } + +#ifdef SSL_MODE_RELEASE_BUFFERS + SSL_CTX_set_mode(BACKEND->ctx, SSL_MODE_RELEASE_BUFFERS); +#endif + +#ifdef SSL_CTRL_SET_MSG_CALLBACK + if(data->set.fdebug && data->set.verbose) { + /* the SSL trace callback is only used for verbose logging */ + SSL_CTX_set_msg_callback(BACKEND->ctx, ssl_tls_trace); + SSL_CTX_set_msg_callback_arg(BACKEND->ctx, conn); + } +#endif + + /* OpenSSL contains code to work-around lots of bugs and flaws in various + SSL-implementations. SSL_CTX_set_options() is used to enabled those + work-arounds. The man page for this option states that SSL_OP_ALL enables + all the work-arounds and that "It is usually safe to use SSL_OP_ALL to + enable the bug workaround options if compatibility with somewhat broken + implementations is desired." + + The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to + disable "rfc4507bis session ticket support". rfc4507bis was later turned + into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077 + + The enabled extension concerns the session management. I wonder how often + libcurl stops a connection and then resumes a TLS session. also, sending + the session data is some overhead. .I suggest that you just use your + proposed patch (which explicitly disables TICKET). + + If someone writes an application with libcurl and openssl who wants to + enable the feature, one can do this in the SSL callback. + + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper + interoperability with web server Netscape Enterprise Server 2.0.1 which + was released back in 1996. + + Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has + become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate + CVE-2010-4180 when using previous OpenSSL versions we no longer enable + this option regardless of OpenSSL version and SSL_OP_ALL definition. + + OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability + (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to + SSL_OP_ALL that _disables_ that work-around despite the fact that + SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to + keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit + must not be set. + */ + + ctx_options = SSL_OP_ALL; + +#ifdef SSL_OP_NO_TICKET + ctx_options |= SSL_OP_NO_TICKET; +#endif + +#ifdef SSL_OP_NO_COMPRESSION + ctx_options |= SSL_OP_NO_COMPRESSION; +#endif + +#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + /* mitigate CVE-2010-4180 */ + ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; +#endif + +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + /* unless the user explicitly ask to allow the protocol vulnerability we + use the work-around */ + if(!SSL_SET_OPTION(enable_beast)) + ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; +#endif + + switch(ssl_version) { + case CURL_SSLVERSION_SSLv3: + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_TLSv1; +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + ctx_options |= SSL_OP_NO_TLSv1_1; + ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif +#endif + break; + + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + /* asking for any TLS version as the minimum, means no SSL versions + allowed */ + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_SSLv3; + result = set_ssl_version_min_max(&ctx_options, conn, sockindex); + if(result != CURLE_OK) + return result; + break; + + case CURL_SSLVERSION_SSLv2: + ctx_options |= SSL_OP_NO_SSLv3; + ctx_options |= SSL_OP_NO_TLSv1; +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + ctx_options |= SSL_OP_NO_TLSv1_1; + ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif +#endif + break; + + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + SSL_CTX_set_options(BACKEND->ctx, ctx_options); + +#ifdef HAS_NPN + if(conn->bits.tls_enable_npn) + SSL_CTX_set_next_proto_select_cb(BACKEND->ctx, select_next_proto_cb, conn); +#endif + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + int cur = 0; + unsigned char protocols[128]; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + + memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN); + cur += NGHTTP2_PROTO_VERSION_ID_LEN; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur++] = ALPN_HTTP_1_1_LENGTH; + memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + cur += ALPN_HTTP_1_1_LENGTH; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + /* expects length prefixed preference ordered list of protocols in wire + * format + */ + SSL_CTX_set_alpn_protos(BACKEND->ctx, protocols, cur); + } +#endif + + if(ssl_cert || ssl_cert_type) { + if(!cert_stuff(conn, BACKEND->ctx, ssl_cert, ssl_cert_type, + SSL_SET_OPTION(key), SSL_SET_OPTION(key_type), + SSL_SET_OPTION(key_passwd))) { + /* failf() is already done in cert_stuff() */ + return CURLE_SSL_CERTPROBLEM; + } + } + + ciphers = SSL_CONN_CONFIG(cipher_list); + if(!ciphers) + ciphers = (char *)DEFAULT_CIPHER_SELECTION; + if(ciphers) { + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s\n", ciphers); + } + +#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES + { + char *ciphers13 = SSL_CONN_CONFIG(cipher_list13); + if(ciphers13) { + if(!SSL_CTX_set_ciphersuites(BACKEND->ctx, ciphers13)) { + failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13); + return CURLE_SSL_CIPHER; + } + infof(data, "TLS 1.3 cipher selection: %s\n", ciphers13); + } + } +#endif + +#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH + /* OpenSSL 1.1.1 requires clients to opt-in for PHA */ + SSL_CTX_set_post_handshake_auth(BACKEND->ctx, 1); +#endif + +#ifdef USE_TLS_SRP + if(ssl_authtype == CURL_TLSAUTH_SRP) { + char * const ssl_username = SSL_SET_OPTION(username); + + infof(data, "Using TLS-SRP username: %s\n", ssl_username); + + if(!SSL_CTX_set_srp_username(BACKEND->ctx, ssl_username)) { + failf(data, "Unable to set SRP user name"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + if(!SSL_CTX_set_srp_password(BACKEND->ctx, SSL_SET_OPTION(password))) { + failf(data, "failed setting SRP password"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + if(!SSL_CONN_CONFIG(cipher_list)) { + infof(data, "Setting cipher list SRP\n"); + + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, "SRP")) { + failf(data, "failed setting SRP cipher list"); + return CURLE_SSL_CIPHER; + } + } + } +#endif + + if(ssl_cafile || ssl_capath) { + /* tell SSL where to find CA certificates that are used to verify + the servers certificate. */ + if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) { + if(verifypeer) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + /* Just continue with a warning if no strict certificate verification + is required. */ + infof(data, "error setting certificate verify locations," + " continuing anyway:\n"); + } + else { + /* Everything is fine. */ + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + } +#ifdef CURL_CA_FALLBACK + else if(verifypeer) { + /* verifying the peer without any CA certificates won't + work so use openssl's built in default as fallback */ + SSL_CTX_set_default_verify_paths(BACKEND->ctx); + } +#endif + + if(ssl_crlfile) { + /* tell SSL where to find CRL file that is used to check certificate + * revocation */ + lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_LOOKUP_file()); + if(!lookup || + (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { + failf(data, "error loading CRL file: %s", ssl_crlfile); + return CURLE_SSL_CRL_BADFILE; + } + /* Everything is fine. */ + infof(data, "successfully load CRL file:\n"); + X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); + + infof(data, " CRLfile: %s\n", ssl_crlfile); + } + + /* Try building a chain using issuers in the trusted store first to avoid + problems with server-sent legacy intermediates. + Newer versions of OpenSSL do alternate chain checking by default which + gives us the same fix without as much of a performance hit (slight), so we + prefer that if available. + https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest + */ +#if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS) + if(verifypeer) { + X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx), + X509_V_FLAG_TRUSTED_FIRST); + } +#endif + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ + SSL_CTX_set_verify(BACKEND->ctx, + verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); + + /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */ +#if defined(ENABLE_SSLKEYLOGFILE) && defined(HAVE_KEYLOG_CALLBACK) + if(keylog_file_fp) { + SSL_CTX_set_keylog_callback(BACKEND->ctx, ossl_keylog_callback); + } +#endif + + /* Enable the session cache because it's a prerequisite for the "new session" + * callback. Use the "external storage" mode to avoid that OpenSSL creates + * an internal session cache. + */ + SSL_CTX_set_session_cache_mode(BACKEND->ctx, + SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL); + SSL_CTX_sess_set_new_cb(BACKEND->ctx, ossl_new_session_cb); + + /* give application a chance to interfere with SSL set up. */ + if(data->set.ssl.fsslctx) { + result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, + data->set.ssl.fsslctxp); + if(result) { + failf(data, "error signaled by ssl ctx callback"); + return result; + } + } + + /* Lets make an SSL structure */ + if(BACKEND->handle) + SSL_free(BACKEND->handle); + BACKEND->handle = SSL_new(BACKEND->ctx); + if(!BACKEND->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_NO_OCSP) + if(SSL_CONN_CONFIG(verifystatus)) + SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp); +#endif + +#if defined(OPENSSL_IS_BORINGSSL) && defined(ALLOW_RENEG) + SSL_set_renegotiate_mode(BACKEND->handle, ssl_renegotiate_freely); +#endif + + SSL_set_connect_state(BACKEND->handle); + + BACKEND->server_cert = 0x0; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && +#endif + sni && + !SSL_set_tlsext_host_name(BACKEND->handle, hostname)) + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); +#endif + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid = NULL; + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + + if(connectdata_idx >= 0 && sockindex_idx >= 0) { + /* Store the data needed for the "new session" callback. + * The sockindex is stored as a pointer to an array element. */ + SSL_set_ex_data(BACKEND->handle, connectdata_idx, conn); + SSL_set_ex_data(BACKEND->handle, sockindex_idx, conn->sock + sockindex); + } + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSL_set_session failed: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + if(conn->proxy_ssl[sockindex].use) { + BIO *const bio = BIO_new(BIO_f_ssl()); + SSL *handle = conn->proxy_ssl[sockindex].backend->handle; + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(handle != NULL); + DEBUGASSERT(bio != NULL); + BIO_set_ssl(bio, handle, FALSE); + SSL_set_bio(BACKEND->handle, bio, bio); + } + else if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) { + /* pass the raw socket into the SSL layers */ + failf(data, "SSL: SSL_set_fd failed: %s", + ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + int err; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + DEBUGASSERT(ssl_connect_2 == connssl->connecting_state + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); + + ERR_clear_error(); + + err = SSL_connect(BACKEND->handle); + /* If keylogging is enabled but the keylog callback is not supported then log + secrets here, immediately after SSL_connect by using tap_ssl_key. */ +#if defined(ENABLE_SSLKEYLOGFILE) && !defined(HAVE_KEYLOG_CALLBACK) + tap_ssl_key(BACKEND->handle, &BACKEND->tap_state); +#endif + + /* 1 is fine + 0 is "not successful but was shut down controlled" + <0 is "handshake was not successful, because a fatal error occurred" */ + if(1 != err) { + int detail = SSL_get_error(BACKEND->handle, err); + + if(SSL_ERROR_WANT_READ == detail) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + if(SSL_ERROR_WANT_WRITE == detail) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } +#ifdef SSL_ERROR_WANT_ASYNC + if(SSL_ERROR_WANT_ASYNC == detail) { + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; + } +#endif + else { + /* untreated error */ + unsigned long errdetail; + char error_buffer[256]=""; + CURLcode result; + long lerr; + int lib; + int reason; + + /* the connection failed, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_2; + + /* Get the earliest error code from the thread's error queue and removes + the entry. */ + errdetail = ERR_get_error(); + + /* Extract which lib and reason */ + lib = ERR_GET_LIB(errdetail); + reason = ERR_GET_REASON(errdetail); + + if((lib == ERR_LIB_SSL) && + (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) { + result = CURLE_PEER_FAILED_VERIFICATION; + + lerr = SSL_get_verify_result(BACKEND->handle); + if(lerr != X509_V_OK) { + *certverifyresult = lerr; + msnprintf(error_buffer, sizeof(error_buffer), + "SSL certificate problem: %s", + X509_verify_cert_error_string(lerr)); + } + else + /* strcpy() is fine here as long as the string fits within + error_buffer */ + strcpy(error_buffer, "SSL certificate verification failed"); + } + else { + result = CURLE_SSL_CONNECT_ERROR; + ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)); + } + + /* detail is already set to the SSL error above */ + + /* If we e.g. use SSLv2 request-method and the server doesn't like us + * (RST connection etc.), OpenSSL gives no explanation whatsoever and + * the SO_ERROR is also lost. + */ + if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { + const char * const hostname = SSL_IS_PROXY() ? + conn->http_proxy.host.name : conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; + failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%ld ", + SSL_ERROR_to_str(detail), hostname, port); + return result; + } + + /* Could be a CERT problem */ + failf(data, "%s", error_buffer); + + return result; + } + } + else { + /* we have been connected fine, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_3; + + /* Informational message */ + infof(data, "SSL connection using %s / %s\n", + get_ssl_version_txt(BACKEND->handle), + SSL_get_cipher(BACKEND->handle)); + +#ifdef HAS_ALPN + /* Sets data and len to negotiated protocol, len is 0 if no protocol was + * negotiated + */ + if(conn->bits.tls_enable_alpn) { + const unsigned char *neg_protocol; + unsigned int len; + SSL_get0_alpn_selected(BACKEND->handle, &neg_protocol, &len); + if(len != 0) { + infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); + +#ifdef USE_NGHTTP2 + if(len == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(len == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + return CURLE_OK; + } +} + +static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len) +{ + int i, ilen; + + ilen = (int)len; + if(ilen < 0) + return 1; /* buffer too big */ + + i = i2t_ASN1_OBJECT(buf, ilen, a); + + if(i >= ilen) + return 1; /* buffer too small */ + + return 0; +} + +#define push_certinfo(_label, _num) \ +do { \ + long info_len = BIO_get_mem_data(mem, &ptr); \ + Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \ + if(1 != BIO_reset(mem)) \ + break; \ +} WHILE_FALSE + +static void pubkey_show(struct Curl_easy *data, + BIO *mem, + int num, + const char *type, + const char *name, +#ifdef HAVE_OPAQUE_RSA_DSA_DH + const +#endif + BIGNUM *bn) +{ + char *ptr; + char namebuf[32]; + + msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name); + + if(bn) + BN_print(mem, bn); + push_certinfo(namebuf, num); +} + +#ifdef HAVE_OPAQUE_RSA_DSA_DH +#define print_pubkey_BN(_type, _name, _num) \ + pubkey_show(data, mem, _num, #_type, #_name, _name) + +#else +#define print_pubkey_BN(_type, _name, _num) \ +do { \ + if(_type->_name) { \ + pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \ + } \ +} WHILE_FALSE +#endif + +static int X509V3_ext(struct Curl_easy *data, + int certnum, + CONST_EXTS STACK_OF(X509_EXTENSION) *exts) +{ + int i; + size_t j; + + if((int)sk_X509_EXTENSION_num(exts) <= 0) + /* no extensions, bail out */ + return 1; + + for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); + BUF_MEM *biomem; + char buf[512]; + char *ptr = buf; + char namebuf[128]; + BIO *bio_out = BIO_new(BIO_s_mem()); + + if(!bio_out) + return 1; + + obj = X509_EXTENSION_get_object(ext); + + asn1_object_dump(obj, namebuf, sizeof(namebuf)); + + if(!X509V3_EXT_print(bio_out, ext, 0, 0)) + ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext)); + + BIO_get_mem_ptr(bio_out, &biomem); + + for(j = 0; j < (size_t)biomem->length; j++) { + const char *sep = ""; + if(biomem->data[j] == '\n') { + sep = ", "; + j++; /* skip the newline */ + }; + while((j<(size_t)biomem->length) && (biomem->data[j] == ' ')) + j++; + if(j<(size_t)biomem->length) + ptr += msnprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep, + biomem->data[j]); + } + + Curl_ssl_push_certinfo(data, certnum, namebuf, buf); + + BIO_free(bio_out); + + } + return 0; /* all is fine */ +} + +static CURLcode get_cert_chain(struct connectdata *conn, + struct ssl_connect_data *connssl) + +{ + CURLcode result; + STACK_OF(X509) *sk; + int i; + struct Curl_easy *data = conn->data; + int numcerts; + BIO *mem; + + sk = SSL_get_peer_cert_chain(BACKEND->handle); + if(!sk) { + return CURLE_OUT_OF_MEMORY; + } + + numcerts = sk_X509_num(sk); + + result = Curl_ssl_init_certinfo(data, numcerts); + if(result) { + return result; + } + + mem = BIO_new(BIO_s_mem()); + + for(i = 0; i < numcerts; i++) { + ASN1_INTEGER *num; + X509 *x = sk_X509_value(sk, i); + EVP_PKEY *pubkey = NULL; + int j; + char *ptr; + const ASN1_BIT_STRING *psig = NULL; + + X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); + push_certinfo("Subject", i); + + X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE); + push_certinfo("Issuer", i); + + BIO_printf(mem, "%lx", X509_get_version(x)); + push_certinfo("Version", i); + + num = X509_get_serialNumber(x); + if(num->type == V_ASN1_NEG_INTEGER) + BIO_puts(mem, "-"); + for(j = 0; j < num->length; j++) + BIO_printf(mem, "%02x", num->data[j]); + push_certinfo("Serial Number", i); + +#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS) + { + const X509_ALGOR *sigalg = NULL; + X509_PUBKEY *xpubkey = NULL; + ASN1_OBJECT *pubkeyoid = NULL; + + X509_get0_signature(&psig, &sigalg, x); + if(sigalg) { + i2a_ASN1_OBJECT(mem, sigalg->algorithm); + push_certinfo("Signature Algorithm", i); + } + + xpubkey = X509_get_X509_PUBKEY(x); + if(xpubkey) { + X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey); + if(pubkeyoid) { + i2a_ASN1_OBJECT(mem, pubkeyoid); + push_certinfo("Public Key Algorithm", i); + } + } + + X509V3_ext(data, i, X509_get0_extensions(x)); + } +#else + { + /* before OpenSSL 1.0.2 */ + X509_CINF *cinf = x->cert_info; + + i2a_ASN1_OBJECT(mem, cinf->signature->algorithm); + push_certinfo("Signature Algorithm", i); + + i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm); + push_certinfo("Public Key Algorithm", i); + + X509V3_ext(data, i, cinf->extensions); + + psig = x->signature; + } +#endif + + ASN1_TIME_print(mem, X509_get0_notBefore(x)); + push_certinfo("Start date", i); + + ASN1_TIME_print(mem, X509_get0_notAfter(x)); + push_certinfo("Expire date", i); + + pubkey = X509_get_pubkey(x); + if(!pubkey) + infof(data, " Unable to load public key\n"); + else { + int pktype; +#ifdef HAVE_OPAQUE_EVP_PKEY + pktype = EVP_PKEY_id(pubkey); +#else + pktype = pubkey->type; +#endif + switch(pktype) { + case EVP_PKEY_RSA: + { + RSA *rsa; +#ifdef HAVE_OPAQUE_EVP_PKEY + rsa = EVP_PKEY_get0_RSA(pubkey); +#else + rsa = pubkey->pkey.rsa; +#endif + +#ifdef HAVE_OPAQUE_RSA_DSA_DH + { + const BIGNUM *n; + const BIGNUM *e; + + RSA_get0_key(rsa, &n, &e, NULL); + BIO_printf(mem, "%d", BN_num_bits(n)); + push_certinfo("RSA Public Key", i); + print_pubkey_BN(rsa, n, i); + print_pubkey_BN(rsa, e, i); + } +#else + BIO_printf(mem, "%d", BN_num_bits(rsa->n)); + push_certinfo("RSA Public Key", i); + print_pubkey_BN(rsa, n, i); + print_pubkey_BN(rsa, e, i); +#endif + + break; + } + case EVP_PKEY_DSA: + { +#ifndef OPENSSL_NO_DSA + DSA *dsa; +#ifdef HAVE_OPAQUE_EVP_PKEY + dsa = EVP_PKEY_get0_DSA(pubkey); +#else + dsa = pubkey->pkey.dsa; +#endif +#ifdef HAVE_OPAQUE_RSA_DSA_DH + { + const BIGNUM *p; + const BIGNUM *q; + const BIGNUM *g; + const BIGNUM *pub_key; + + DSA_get0_pqg(dsa, &p, &q, &g); + DSA_get0_key(dsa, &pub_key, NULL); + + print_pubkey_BN(dsa, p, i); + print_pubkey_BN(dsa, q, i); + print_pubkey_BN(dsa, g, i); + print_pubkey_BN(dsa, pub_key, i); + } +#else + print_pubkey_BN(dsa, p, i); + print_pubkey_BN(dsa, q, i); + print_pubkey_BN(dsa, g, i); + print_pubkey_BN(dsa, pub_key, i); +#endif +#endif /* !OPENSSL_NO_DSA */ + break; + } + case EVP_PKEY_DH: + { + DH *dh; +#ifdef HAVE_OPAQUE_EVP_PKEY + dh = EVP_PKEY_get0_DH(pubkey); +#else + dh = pubkey->pkey.dh; +#endif +#ifdef HAVE_OPAQUE_RSA_DSA_DH + { + const BIGNUM *p; + const BIGNUM *q; + const BIGNUM *g; + const BIGNUM *pub_key; + DH_get0_pqg(dh, &p, &q, &g); + DH_get0_key(dh, &pub_key, NULL); + print_pubkey_BN(dh, p, i); + print_pubkey_BN(dh, q, i); + print_pubkey_BN(dh, g, i); + print_pubkey_BN(dh, pub_key, i); + } +#else + print_pubkey_BN(dh, p, i); + print_pubkey_BN(dh, g, i); + print_pubkey_BN(dh, pub_key, i); +#endif + break; + } + } + EVP_PKEY_free(pubkey); + } + + if(psig) { + for(j = 0; j < psig->length; j++) + BIO_printf(mem, "%02x:", psig->data[j]); + push_certinfo("Signature", i); + } + + PEM_write_bio_X509(mem, x); + push_certinfo("Cert", i); + } + + BIO_free(mem); + + return CURLE_OK; +} + +/* + * Heavily modified from: + * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL + */ +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, + const char *pinnedpubkey) +{ + /* Scratch */ + int len1 = 0, len2 = 0; + unsigned char *buff1 = NULL, *temp = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + if(!cert) + return result; + + do { + /* Begin Gyrations to get the subjectPublicKeyInfo */ + /* Thanks to Viktor Dukhovni on the OpenSSL mailing list */ + + /* https://groups.google.com/group/mailing.openssl.users/browse_thread + /thread/d61858dae102c6c7 */ + len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL); + if(len1 < 1) + break; /* failed */ + + buff1 = temp = malloc(len1); + if(!buff1) + break; /* failed */ + + /* https://www.openssl.org/docs/crypto/d2i_X509.html */ + len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp); + + /* + * These checks are verifying we got back the same values as when we + * sized the buffer. It's pretty weak since they should always be the + * same. But it gives us something to test. + */ + if((len1 != len2) || !temp || ((temp - buff1) != len1)) + break; /* failed */ + + /* End Gyrations */ + + /* The one good exit point */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1); + } while(0); + + if(buff1) + free(buff1); + + return result; +} + +/* + * Get the server cert, verify it and show it etc, only call failf() if the + * 'strict' argument is TRUE as otherwise all this is for informational + * purposes only! + * + * We check certificates to authenticate the server; otherwise we risk + * man-in-the-middle attack. + */ +static CURLcode servercert(struct connectdata *conn, + struct ssl_connect_data *connssl, + bool strict) +{ + CURLcode result = CURLE_OK; + int rc; + long lerr; + struct Curl_easy *data = conn->data; + X509 *issuer; + BIO *fp = NULL; + char error_buffer[256]=""; + char buffer[2048]; + const char *ptr; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + BIO *mem = BIO_new(BIO_s_mem()); + + if(data->set.ssl.certinfo) + /* we've been asked to gather certificate info! */ + (void)get_cert_chain(conn, connssl); + + BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle); + if(!BACKEND->server_cert) { + BIO_free(mem); + if(!strict) + return CURLE_OK; + + failf(data, "SSL: couldn't get peer certificate!"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); + + rc = x509_name_oneline(X509_get_subject_name(BACKEND->server_cert), + buffer, sizeof(buffer)); + infof(data, " subject: %s\n", rc?"[NONE]":buffer); + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + { + long len; + ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert)); + len = BIO_get_mem_data(mem, (char **) &ptr); + infof(data, " start date: %.*s\n", len, ptr); + (void)BIO_reset(mem); + + ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert)); + len = BIO_get_mem_data(mem, (char **) &ptr); + infof(data, " expire date: %.*s\n", len, ptr); + (void)BIO_reset(mem); + } +#endif + + BIO_free(mem); + + if(SSL_CONN_CONFIG(verifyhost)) { + result = verifyhost(conn, BACKEND->server_cert); + if(result) { + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return result; + } + } + + rc = x509_name_oneline(X509_get_issuer_name(BACKEND->server_cert), + buffer, sizeof(buffer)); + if(rc) { + if(strict) + failf(data, "SSL: couldn't get X509-issuer name!"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, " issuer: %s\n", buffer); + + /* We could do all sorts of certificate verification stuff here before + deallocating the certificate. */ + + /* e.g. match issuer name with provided issuer certificate */ + if(SSL_SET_OPTION(issuercert)) { + fp = BIO_new(BIO_s_file()); + if(fp == NULL) { + failf(data, + "BIO_new return NULL, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_OUT_OF_MEMORY; + } + + if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) { + if(strict) + failf(data, "SSL: Unable to open issuer cert (%s)", + SSL_SET_OPTION(issuercert)); + BIO_free(fp); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_SSL_ISSUER_ERROR; + } + + issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL); + if(!issuer) { + if(strict) + failf(data, "SSL: Unable to read issuer cert (%s)", + SSL_SET_OPTION(issuercert)); + BIO_free(fp); + X509_free(issuer); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_SSL_ISSUER_ERROR; + } + + if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) { + if(strict) + failf(data, "SSL: Certificate issuer check failed (%s)", + SSL_SET_OPTION(issuercert)); + BIO_free(fp); + X509_free(issuer); + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return CURLE_SSL_ISSUER_ERROR; + } + + infof(data, " SSL certificate issuer check ok (%s)\n", + SSL_SET_OPTION(issuercert)); + BIO_free(fp); + X509_free(issuer); + } + + lerr = *certverifyresult = SSL_get_verify_result(BACKEND->handle); + + if(*certverifyresult != X509_V_OK) { + if(SSL_CONN_CONFIG(verifypeer)) { + /* We probably never reach this, because SSL_connect() will fail + and we return earlier if verifypeer is set? */ + if(strict) + failf(data, "SSL certificate verify result: %s (%ld)", + X509_verify_cert_error_string(lerr), lerr); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else + infof(data, " SSL certificate verify result: %s (%ld)," + " continuing anyway.\n", + X509_verify_cert_error_string(lerr), lerr); + } + else + infof(data, " SSL certificate verify ok.\n"); + } + +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_NO_OCSP) + if(SSL_CONN_CONFIG(verifystatus)) { + result = verifystatus(conn, connssl); + if(result) { + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + return result; + } + } +#endif + + if(!strict) + /* when not strict, we don't bother about the verify cert problems */ + result = CURLE_OK; + + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + if(!result && ptr) { + result = pkp_pin_peer_pubkey(data, BACKEND->server_cert, ptr); + if(result) + failf(data, "SSL: public key does not match pinned public key!"); + } + + X509_free(BACKEND->server_cert); + BACKEND->server_cert = NULL; + connssl->connecting_state = ssl_connect_done; + + return result; +} + +static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + /* + * We check certificates to authenticate the server; otherwise we risk + * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to + * verify the peer ignore faults and failures from the server cert + * operations. + */ + + result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost))); + + if(!result) + connssl->connecting_state = ssl_connect_done; + + return result; +} + +static Curl_recv ossl_recv; +static Curl_send ossl_send; + +static CURLcode ossl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = ossl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if this + * connection is done nonblocking and this loop would execute again. This + * permits the owner of a multi handle to abort a connection attempt + * before step2 has completed while ensuring that a client using select() + * or epoll() will always have a valid fdset to wait on. + */ + result = ossl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = ossl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = ossl_recv; + conn->send[sockindex] = ossl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done) +{ + return ossl_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = ossl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static bool Curl_ossl_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex]; + + if(connssl->backend->handle && SSL_pending(connssl->backend->handle)) + return TRUE; + + if(proxyssl->backend->handle && SSL_pending(proxyssl->backend->handle)) + return TRUE; + + return FALSE; +} + +static size_t Curl_ossl_version(char *buffer, size_t size); + +static ssize_t ossl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + /* SSL_write() is said to return 'int' while write() and send() returns + 'size_t' */ + int err; + char error_buffer[256]; + unsigned long sslerror; + int memlen; + int rc; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + ERR_clear_error(); + + memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + rc = SSL_write(BACKEND->handle, mem, memlen); + + if(rc <= 0) { + err = SSL_get_error(BACKEND->handle, rc); + + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* The operation did not complete; the same TLS/SSL I/O function + should be called again later. This is basically an EWOULDBLOCK + equivalent. */ + *curlcode = CURLE_AGAIN; + return -1; + case SSL_ERROR_SYSCALL: + failf(conn->data, "SSL_write() returned SYSCALL, errno = %d", + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + case SSL_ERROR_SSL: + /* A failure in the SSL library occurred, usually a protocol error. + The OpenSSL error queue contains more information on the error. */ + sslerror = ERR_get_error(); + if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL && + ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET && + conn->ssl[sockindex].state == ssl_connection_complete && + conn->proxy_ssl[sockindex].state == ssl_connection_complete) { + char ver[120]; + Curl_ossl_version(ver, 120); + failf(conn->data, "Error: %s does not support double SSL tunneling.", + ver); + } + else + failf(conn->data, "SSL_write() error: %s", + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + /* a true error */ + failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d", + SSL_ERROR_to_str(err), SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + *curlcode = CURLE_OK; + return (ssize_t)rc; /* number of bytes */ +} + +static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ + int num, /* socketindex */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + CURLcode *curlcode) +{ + char error_buffer[256]; + unsigned long sslerror; + ssize_t nread; + int buffsize; + struct ssl_connect_data *connssl = &conn->ssl[num]; + + ERR_clear_error(); + + buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize); + if(nread <= 0) { + /* failed SSL_read */ + int err = SSL_get_error(BACKEND->handle, (int)nread); + + switch(err) { + case SSL_ERROR_NONE: /* this is not an error */ + break; + case SSL_ERROR_ZERO_RETURN: /* no more data */ + /* close_notify alert */ + connclose(conn, "TLS close_notify"); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return + value/errno" */ + /* https://www.openssl.org/docs/crypto/ERR_get_error.html */ + sslerror = ERR_get_error(); + if((nread < 0) || sslerror) { + /* If the return code was negative or there actually is an error in the + queue */ + failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d", + (sslerror ? + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)) : + SSL_ERROR_to_str(err)), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + } + return nread; +} + +static size_t Curl_ossl_version(char *buffer, size_t size) +{ +#ifdef OPENSSL_IS_BORINGSSL + return msnprintf(buffer, size, OSSL_PACKAGE); +#elif defined(HAVE_OPENSSL_VERSION) && defined(OPENSSL_VERSION_STRING) + return msnprintf(buffer, size, "%s/%s", + OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING)); +#else + /* not BoringSSL and not using OpenSSL_version */ + + char sub[3]; + unsigned long ssleay_value; + sub[2]='\0'; + sub[1]='\0'; + ssleay_value = OpenSSL_version_num(); + if(ssleay_value < 0x906000) { + ssleay_value = SSLEAY_VERSION_NUMBER; + sub[0]='\0'; + } + else { + if(ssleay_value&0xff0) { + int minor_ver = (ssleay_value >> 4) & 0xff; + if(minor_ver > 26) { + /* handle extended version introduced for 0.9.8za */ + sub[1] = (char) ((minor_ver - 1) % 26 + 'a' + 1); + sub[0] = 'z'; + } + else { + sub[0] = (char) (minor_ver + 'a' - 1); + } + } + else + sub[0]='\0'; + } + + return msnprintf(buffer, size, "%s/%lx.%lx.%lx%s" +#ifdef OPENSSL_FIPS + "-fips" +#endif + , + OSSL_PACKAGE, + (ssleay_value>>28)&0xf, + (ssleay_value>>20)&0xff, + (ssleay_value>>12)&0xff, + sub); +#endif /* OPENSSL_IS_BORINGSSL */ +} + +/* can be called with data == NULL */ +static CURLcode Curl_ossl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ + int rc; + if(data) { + if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */ + return CURLE_FAILED_INIT; /* couldn't seed for some reason */ + } + else { + if(!rand_enough()) + return CURLE_FAILED_INIT; + } + /* RAND_bytes() returns 1 on success, 0 otherwise. */ + rc = RAND_bytes(entropy, curlx_uztosi(length)); + return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT); +} + +static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum /* output */, + size_t unused) +{ + EVP_MD_CTX *mdctx; + unsigned int len = 0; + (void) unused; + + mdctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(mdctx, EVP_md5(), NULL); + EVP_DigestUpdate(mdctx, tmp, tmplen); + EVP_DigestFinal_ex(mdctx, md5sum, &len); + EVP_MD_CTX_destroy(mdctx); + return CURLE_OK; +} + +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) +static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) +{ + EVP_MD_CTX *mdctx; + unsigned int len = 0; + (void) unused; + + mdctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); + EVP_DigestUpdate(mdctx, tmp, tmplen); + EVP_DigestFinal_ex(mdctx, sha256sum, &len); + EVP_MD_CTX_destroy(mdctx); + return CURLE_OK; +} +#endif + +static bool Curl_ossl_cert_status_request(void) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ + !defined(OPENSSL_NO_OCSP) + return TRUE; +#else + return FALSE; +#endif +} + +static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) +{ + /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */ + return info == CURLINFO_TLS_SESSION ? + (void *)BACKEND->ctx : (void *)BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_openssl = { + { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY | + SSLSUPP_SSL_CTX | +#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES + SSLSUPP_TLS13_CIPHERSUITES | +#endif + SSLSUPP_HTTPS_PROXY, + + sizeof(struct ssl_backend_data), + + Curl_ossl_init, /* init */ + Curl_ossl_cleanup, /* cleanup */ + Curl_ossl_version, /* version */ + Curl_ossl_check_cxn, /* check_cxn */ + Curl_ossl_shutdown, /* shutdown */ + Curl_ossl_data_pending, /* data_pending */ + Curl_ossl_random, /* random */ + Curl_ossl_cert_status_request, /* cert_status_request */ + Curl_ossl_connect, /* connect */ + Curl_ossl_connect_nonblocking, /* connect_nonblocking */ + Curl_ossl_get_internals, /* get_internals */ + Curl_ossl_close, /* close_one */ + Curl_ossl_close_all, /* close_all */ + Curl_ossl_session_free, /* session_free */ + Curl_ossl_set_engine, /* set_engine */ + Curl_ossl_set_engine_default, /* set_engine_default */ + Curl_ossl_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_ossl_md5sum, /* md5sum */ +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) + Curl_ossl_sha256sum /* sha256sum */ +#else + NULL /* sha256sum */ +#endif +}; + +#endif /* USE_OPENSSL */ diff --git a/libcurl/lib/vtls/openssl.h b/libcurl/lib/vtls/openssl.h new file mode 100644 index 0000000..114dc4b --- /dev/null +++ b/libcurl/lib/vtls/openssl.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_SSLUSE_H +#define HEADER_CURL_SSLUSE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_OPENSSL +/* + * This header should only be needed to get included by vtls.c and openssl.c + */ + +#include "urldata.h" + +extern const struct Curl_ssl Curl_ssl_openssl; + +#endif /* USE_OPENSSL */ +#endif /* HEADER_CURL_SSLUSE_H */ diff --git a/libcurl/lib/vtls/polarssl.c b/libcurl/lib/vtls/polarssl.c new file mode 100644 index 0000000..7ea26b4 --- /dev/null +++ b/libcurl/lib/vtls/polarssl.c @@ -0,0 +1,931 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * Copyright (C) 2010 - 2011, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "curl_setup.h" + +#ifdef USE_POLARSSL +#include +#include +#include +#include +#include +#include + +#if POLARSSL_VERSION_NUMBER < 0x01030000 +#error too old PolarSSL +#endif + +#include +#include +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "polarssl.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "polarssl_threadlock.h" +#include "multiif.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* See https://tls.mbed.org/discussions/generic/ + howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der +*/ +#define RSA_PUB_DER_MAX_BYTES (38 + 2 * POLARSSL_MPI_MAX_SIZE) +#define ECP_PUB_DER_MAX_BYTES (30 + 2 * POLARSSL_ECP_MAX_BYTES) + +#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) + +struct ssl_backend_data { + ctr_drbg_context ctr_drbg; + entropy_context entropy; + ssl_context ssl; + int server_fd; + x509_crt cacert; + x509_crt clicert; + x509_crl crl; + rsa_context rsa; +}; + +#define BACKEND connssl->backend + +/* apply threading? */ +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +#define THREADING_SUPPORT +#endif + +#ifndef POLARSSL_ERROR_C +#define error_strerror(x,y,z) +#endif /* POLARSSL_ERROR_C */ + + +#if defined(THREADING_SUPPORT) +static entropy_context entropy; + +static int entropy_init_initialized = 0; + +/* start of entropy_init_mutex() */ +static void entropy_init_mutex(entropy_context *ctx) +{ + /* lock 0 = entropy_init_mutex() */ + Curl_polarsslthreadlock_lock_function(0); + if(entropy_init_initialized == 0) { + entropy_init(ctx); + entropy_init_initialized = 1; + } + Curl_polarsslthreadlock_unlock_function(0); +} +/* end of entropy_init_mutex() */ + +/* start of entropy_func_mutex() */ +static int entropy_func_mutex(void *data, unsigned char *output, size_t len) +{ + int ret; + /* lock 1 = entropy_func_mutex() */ + Curl_polarsslthreadlock_lock_function(1); + ret = entropy_func(data, output, len); + Curl_polarsslthreadlock_unlock_function(1); + + return ret; +} +/* end of entropy_func_mutex() */ + +#endif /* THREADING_SUPPORT */ + +/* Define this to enable lots of debugging for PolarSSL */ +#undef POLARSSL_DEBUG + +#ifdef POLARSSL_DEBUG +static void polarssl_debug(void *context, int level, const char *line) +{ + struct Curl_easy *data = NULL; + + if(!context) + return; + + data = (struct Curl_easy *)context; + + infof(data, "%s", line); + (void) level; +} +#else +#endif + +/* ALPN for http2? */ +#ifdef POLARSSL_SSL_ALPN +# define HAS_ALPN +#endif + +static Curl_recv polarssl_recv; +static Curl_send polarssl_send; + +static CURLcode polarssl_version_from_curl(int *polarver, long ssl_version) +{ + switch(ssl_version) { + case CURL_SSLVERSION_TLSv1_0: + *polarver = SSL_MINOR_VERSION_1; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1: + *polarver = SSL_MINOR_VERSION_2; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2: + *polarver = SSL_MINOR_VERSION_3; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3: + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + +static CURLcode +set_ssl_version_min_max(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + int ssl_min_ver = SSL_MINOR_VERSION_1; + int ssl_max_ver = SSL_MINOR_VERSION_1; + CURLcode result = CURLE_OK; + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + result = polarssl_version_from_curl(&ssl_min_ver, ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver); + ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver); + + return result; +} + +static CURLcode +polarssl_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const char *capath = SSL_CONN_CONFIG(CApath); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; + int ret = -1; + char errorbuf[128]; + errorbuf[0] = 0; + + /* PolarSSL only supports SSLv3 and TLSv1 */ + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { + failf(data, "PolarSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef THREADING_SUPPORT + entropy_init_mutex(&entropy); + + if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy, + NULL, 0)) != 0) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#else + entropy_init(&BACKEND->entropy); + + if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy, + NULL, 0)) != 0) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", + -ret, errorbuf); + } +#endif /* THREADING_SUPPORT */ + + /* Load the trusted CA */ + memset(&BACKEND->cacert, 0, sizeof(x509_crt)); + + if(SSL_CONN_CONFIG(CAfile)) { + ret = x509_crt_parse_file(&BACKEND->cacert, + SSL_CONN_CONFIG(CAfile)); + + if(ret<0) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", + SSL_CONN_CONFIG(CAfile), -ret, errorbuf); + + if(SSL_CONN_CONFIG(verifypeer)) + return CURLE_SSL_CACERT_BADFILE; + } + } + + if(capath) { + ret = x509_crt_parse_path(&BACKEND->cacert, capath); + + if(ret<0) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", + capath, -ret, errorbuf); + + if(SSL_CONN_CONFIG(verifypeer)) + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Load the client certificate */ + memset(&BACKEND->clicert, 0, sizeof(x509_crt)); + + if(SSL_SET_OPTION(cert)) { + ret = x509_crt_parse_file(&BACKEND->clicert, + SSL_SET_OPTION(cert)); + + if(ret) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", + SSL_SET_OPTION(cert), -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the client private key */ + if(SSL_SET_OPTION(key)) { + pk_context pk; + pk_init(&pk); + ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); + if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if(ret == 0) + rsa_copy(&BACKEND->rsa, pk_rsa(pk)); + else + rsa_free(&BACKEND->rsa); + pk_free(&pk); + + if(ret) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", + SSL_SET_OPTION(key), -ret, errorbuf); + + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Load the CRL */ + memset(&BACKEND->crl, 0, sizeof(x509_crl)); + + if(SSL_SET_OPTION(CRLfile)) { + ret = x509_crl_parse_file(&BACKEND->crl, + SSL_SET_OPTION(CRLfile)); + + if(ret) { + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", + SSL_SET_OPTION(CRLfile), -ret, errorbuf); + + return CURLE_SSL_CRL_BADFILE; + } + } + + infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port); + + if(ssl_init(&BACKEND->ssl)) { + failf(data, "PolarSSL: ssl_init failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_1); + break; + case CURL_SSLVERSION_SSLv3: + ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_0); + ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, + SSL_MINOR_VERSION_0); + infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT); + ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL); + + ssl_set_rng(&BACKEND->ssl, ctr_drbg_random, + &BACKEND->ctr_drbg); + ssl_set_bio(&BACKEND->ssl, + net_recv, &conn->sock[sockindex], + net_send, &conn->sock[sockindex]); + + ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites()); + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *old_session = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { + ret = ssl_set_session(&BACKEND->ssl, old_session); + if(ret) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "ssl_set_session returned -0x%x", -ret); + return CURLE_SSL_CONNECT_ERROR; + } + infof(data, "PolarSSL re-using session\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + ssl_set_ca_chain(&BACKEND->ssl, + &BACKEND->cacert, + &BACKEND->crl, + hostname); + + ssl_set_own_cert_rsa(&BACKEND->ssl, + &BACKEND->clicert, &BACKEND->rsa); + + if(ssl_set_hostname(&BACKEND->ssl, hostname)) { + /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name + to set in the SNI extension. So even if curl connects to a host + specified as an IP address, this function must be used. */ + failf(data, "couldn't set hostname in PolarSSL"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + static const char *protocols[3]; + int cur = 0; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + protocols[cur++] = ALPN_HTTP_1_1; + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + protocols[cur] = NULL; + + ssl_set_alpn_protocols(&BACKEND->ssl, protocols); + } +#endif + +#ifdef POLARSSL_DEBUG + ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data); +#endif + + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +polarssl_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + char buffer[1024]; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + + char errorbuf[128]; + errorbuf[0] = 0; + + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; + + ret = ssl_handshake(&BACKEND->ssl); + + switch(ret) { + case 0: + break; + + case POLARSSL_ERR_NET_WANT_READ: + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + + case POLARSSL_ERR_NET_WANT_WRITE: + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + + default: + error_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s", + -ret, errorbuf); + return CURLE_SSL_CONNECT_ERROR; + } + + infof(data, "PolarSSL: Handshake complete, cipher is %s\n", + ssl_get_ciphersuite(&BACKEND->ssl) ); + + ret = ssl_get_verify_result(&BACKEND->ssl); + + if(ret && SSL_CONN_CONFIG(verifypeer)) { + if(ret & BADCERT_EXPIRED) + failf(data, "Cert verify failed: BADCERT_EXPIRED"); + + if(ret & BADCERT_REVOKED) { + failf(data, "Cert verify failed: BADCERT_REVOKED"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + if(ret & BADCERT_CN_MISMATCH) + failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); + + if(ret & BADCERT_NOT_TRUSTED) + failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); + + return CURLE_PEER_FAILED_VERIFICATION; + } + + if(ssl_get_peer_cert(&(BACKEND->ssl))) { + /* If the session was resumed, there will be no peer certs */ + memset(buffer, 0, sizeof(buffer)); + + if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ", + ssl_get_peer_cert(&(BACKEND->ssl))) != -1) + infof(data, "Dumping cert info:\n%s\n", buffer); + } + + /* adapted from mbedtls.c */ + if(pinnedpubkey) { + int size; + CURLcode result; + x509_crt *p; + unsigned char pubkey[PUB_DER_MAX_BYTES]; + const x509_crt *peercert; + + peercert = ssl_get_peer_cert(&BACKEND->ssl); + + if(!peercert || !peercert->raw.p || !peercert->raw.len) { + failf(data, "Failed due to missing peer certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + p = calloc(1, sizeof(*p)); + + if(!p) + return CURLE_OUT_OF_MEMORY; + + x509_crt_init(p); + + /* Make a copy of our const peercert because pk_write_pubkey_der + needs a non-const key, for now. + https://github.com/ARMmbed/mbedtls/issues/396 */ + if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { + failf(data, "Failed copying peer certificate"); + x509_crt_free(p); + free(p); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); + + if(size <= 0) { + failf(data, "Failed copying public key from peer certificate"); + x509_crt_free(p); + free(p); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + /* pk_write_pubkey_der writes data at the end of the buffer. */ + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + &pubkey[PUB_DER_MAX_BYTES - size], size); + if(result) { + x509_crt_free(p); + free(p); + return result; + } + + x509_crt_free(p); + free(p); + } + +#ifdef HAS_ALPN + if(conn->bits.tls_enable_alpn) { + const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl); + + if(next_protocol != NULL) { + infof(data, "ALPN, server accepted to use %s\n", next_protocol); + +#ifdef USE_NGHTTP2 + if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + connssl->connecting_state = ssl_connect_3; + infof(data, "SSL connected\n"); + + return CURLE_OK; +} + +static CURLcode +polarssl_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode retcode = CURLE_OK; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + if(SSL_SET_OPTION(primary.sessionid)) { + int ret; + ssl_session *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = calloc(1, sizeof(ssl_session)); + if(!our_ssl_sessionid) + return CURLE_OUT_OF_MEMORY; + + ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid); + if(ret) { + failf(data, "ssl_get_session returned -0x%x", -ret); + return CURLE_SSL_CONNECT_ERROR; + } + + /* If there's already a matching session in the cache, delete it */ + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + + retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); + Curl_ssl_sessionid_unlock(conn); + if(retcode) { + free(our_ssl_sessionid); + failf(data, "failed to store ssl session"); + return retcode; + } + } + + connssl->connecting_state = ssl_connect_done; + + return CURLE_OK; +} + +static ssize_t polarssl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int ret = -1; + + ret = ssl_write(&BACKEND->ssl, + (unsigned char *)mem, len); + + if(ret < 0) { + *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ? + CURLE_AGAIN : CURLE_SEND_ERROR; + ret = -1; + } + + return ret; +} + +static void Curl_polarssl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + rsa_free(&BACKEND->rsa); + x509_crt_free(&BACKEND->clicert); + x509_crt_free(&BACKEND->cacert); + x509_crl_free(&BACKEND->crl); + ssl_free(&BACKEND->ssl); +} + +static ssize_t polarssl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + int ret = -1; + ssize_t len = -1; + + memset(buf, 0, buffersize); + ret = ssl_read(&BACKEND->ssl, (unsigned char *)buf, buffersize); + + if(ret <= 0) { + if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) + return 0; + + *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ? + CURLE_AGAIN : CURLE_RECV_ERROR; + return -1; + } + + len = ret; + + return len; +} + +static void Curl_polarssl_session_free(void *ptr) +{ + ssl_session_free(ptr); + free(ptr); +} + +/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and + higher) will be mbed TLS branded.. */ + +static size_t Curl_polarssl_version(char *buffer, size_t size) +{ + unsigned int version = version_get_number(); + return msnprintf(buffer, size, "%s/%d.%d.%d", + version >= 0x01030A00?"mbedTLS":"PolarSSL", + version>>24, (version>>16)&0xff, (version>>8)&0xff); +} + +static CURLcode +polarssl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = polarssl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = polarssl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = polarssl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = polarssl_recv; + conn->send[sockindex] = polarssl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return polarssl_connect_common(conn, sockindex, TRUE, done); +} + + +static CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = polarssl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +/* + * return 0 error initializing SSL + * return 1 SSL initialized successfully + */ +static int Curl_polarssl_init(void) +{ + return Curl_polarsslthreadlock_thread_setup(); +} + +static void Curl_polarssl_cleanup(void) +{ + (void)Curl_polarsslthreadlock_thread_cleanup(); +} + +static bool Curl_polarssl_data_pending(const struct connectdata *conn, + int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + return ssl_get_bytes_avail(&BACKEND->ssl) != 0; +} + +static CURLcode Curl_polarssl_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len UNUSED_PARAM) +{ + (void)sha256len; + sha256(input, inputlen, sha256sum, 0); + return CURLE_OK; +} + +static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return &BACKEND->ssl; +} + +const struct Curl_ssl Curl_ssl_polarssl = { + { CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */ + + SSLSUPP_CA_PATH | + SSLSUPP_PINNEDPUBKEY, + + sizeof(struct ssl_backend_data), + + Curl_polarssl_init, /* init */ + Curl_polarssl_cleanup, /* cleanup */ + Curl_polarssl_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + Curl_polarssl_data_pending, /* data_pending */ + /* This might cause libcurl to use a weeker random! */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_polarssl_connect, /* connect */ + Curl_polarssl_connect_nonblocking, /* connect_nonblocking */ + Curl_polarssl_get_internals, /* get_internals */ + Curl_polarssl_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_polarssl_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + Curl_polarssl_sha256sum /* sha256sum */ +}; + +#endif /* USE_POLARSSL */ diff --git a/libcurl/lib/vtls/polarssl.h b/libcurl/lib/vtls/polarssl.h new file mode 100644 index 0000000..23c3636 --- /dev/null +++ b/libcurl/lib/vtls/polarssl.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_POLARSSL_H +#define HEADER_CURL_POLARSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_POLARSSL + +extern const struct Curl_ssl Curl_ssl_polarssl; + +#endif /* USE_POLARSSL */ +#endif /* HEADER_CURL_POLARSSL_H */ diff --git a/libcurl/lib/vtls/polarssl_threadlock.c b/libcurl/lib/vtls/polarssl_threadlock.c new file mode 100644 index 0000000..27c94b1 --- /dev/null +++ b/libcurl/lib/vtls/polarssl_threadlock.c @@ -0,0 +1,144 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013-2017, Daniel Stenberg, , et al. + * Copyright (C) 2010, 2011, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if (defined(USE_POLARSSL) || defined(USE_MBEDTLS)) && \ + ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ + (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H))) + +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) +# include +# define POLARSSL_MUTEX_T pthread_mutex_t +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) +# include +# define POLARSSL_MUTEX_T HANDLE +#endif + +#include "polarssl_threadlock.h" +#include "curl_printf.h" +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* number of thread locks */ +#define NUMT 2 + +/* This array will store all of the mutexes available to PolarSSL. */ +static POLARSSL_MUTEX_T *mutex_buf = NULL; + +int Curl_polarsslthreadlock_thread_setup(void) +{ + int i; + + mutex_buf = calloc(NUMT * sizeof(POLARSSL_MUTEX_T), 1); + if(!mutex_buf) + return 0; /* error, no number of threads defined */ + + for(i = 0; i < NUMT; i++) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_init(&mutex_buf[i], NULL); + if(ret) + return 0; /* pthread_mutex_init failed */ +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + mutex_buf[i] = CreateMutex(0, FALSE, 0); + if(mutex_buf[i] == 0) + return 0; /* CreateMutex failed */ +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + + return 1; /* OK */ +} + +int Curl_polarsslthreadlock_thread_cleanup(void) +{ + int i; + + if(!mutex_buf) + return 0; /* error, no threads locks defined */ + + for(i = 0; i < NUMT; i++) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_destroy(&mutex_buf[i]); + if(ret) + return 0; /* pthread_mutex_destroy failed */ +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = CloseHandle(mutex_buf[i]); + if(!ret) + return 0; /* CloseHandle failed */ +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + free(mutex_buf); + mutex_buf = NULL; + + return 1; /* OK */ +} + +int Curl_polarsslthreadlock_lock_function(int n) +{ + if(n < NUMT) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_lock(&mutex_buf[n]); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_lock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_lock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + return 1; /* OK */ +} + +int Curl_polarsslthreadlock_unlock_function(int n) +{ + if(n < NUMT) { + int ret; +#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) + ret = pthread_mutex_unlock(&mutex_buf[n]); + if(ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_unlock_function failed\n")); + return 0; /* pthread_mutex_unlock failed */ + } +#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) + ret = ReleaseMutex(mutex_buf[n]); + if(!ret) { + DEBUGF(fprintf(stderr, + "Error: polarsslthreadlock_unlock_function failed\n")); + return 0; /* pthread_mutex_lock failed */ + } +#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ + } + return 1; /* OK */ +} + +#endif /* USE_POLARSSL || USE_MBEDTLS */ diff --git a/libcurl/lib/vtls/polarssl_threadlock.h b/libcurl/lib/vtls/polarssl_threadlock.h new file mode 100644 index 0000000..1226475 --- /dev/null +++ b/libcurl/lib/vtls/polarssl_threadlock.h @@ -0,0 +1,48 @@ +#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H +#define HEADER_CURL_POLARSSL_THREADLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013-2015, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if (defined USE_POLARSSL) || (defined USE_MBEDTLS) + +#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ + (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)) + +int Curl_polarsslthreadlock_thread_setup(void); +int Curl_polarsslthreadlock_thread_cleanup(void); +int Curl_polarsslthreadlock_lock_function(int n); +int Curl_polarsslthreadlock_unlock_function(int n); + +#else + +#define Curl_polarsslthreadlock_thread_setup() 1 +#define Curl_polarsslthreadlock_thread_cleanup() 1 +#define Curl_polarsslthreadlock_lock_function(x) 1 +#define Curl_polarsslthreadlock_unlock_function(x) 1 + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* USE_POLARSSL */ + +#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */ diff --git a/libcurl/lib/vtls/schannel.c b/libcurl/lib/vtls/schannel.c new file mode 100644 index 0000000..0f6f734 --- /dev/null +++ b/libcurl/lib/vtls/schannel.c @@ -0,0 +1,2302 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Marc Hoersken, + * Copyright (C) 2012, Mark Salisbury, + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all Schannel-specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + */ + +/* + * Based upon the PolarSSL implementation in polarssl.c and polarssl.h: + * Copyright (C) 2010, 2011, Hoi-Ho Chan, + * + * Based upon the CyaSSL implementation in cyassl.c and cyassl.h: + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * Thanks for code and inspiration! + */ + +#include "curl_setup.h" + +#ifdef USE_SCHANNEL + +#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS + +#ifndef USE_WINDOWS_SSPI +# error "Can't compile SCHANNEL support without SSPI." +#endif + +#include "schannel.h" +#include "vtls.h" +#include "sendf.h" +#include "connect.h" /* for the connect timeout */ +#include "strerror.h" +#include "select.h" /* for the socket readyness */ +#include "inet_pton.h" /* for IP addr SNI check */ +#include "curl_multibyte.h" +#include "warnless.h" +#include "x509asn1.h" +#include "curl_printf.h" +#include "multiif.h" +#include "system_win32.h" + + /* The last #include file should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* ALPN requires version 8.1 of the Windows SDK, which was + shipped with Visual Studio 2013, aka _MSC_VER 1800: + + https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_) +# define HAS_ALPN 1 +#endif + +#ifndef UNISP_NAME_A +#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider" +#endif + +#ifndef UNISP_NAME_W +#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider" +#endif + +#ifndef UNISP_NAME +#ifdef UNICODE +#define UNISP_NAME UNISP_NAME_W +#else +#define UNISP_NAME UNISP_NAME_A +#endif +#endif + +#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) +#define HAS_CLIENT_CERT_PATH +#endif + +#ifdef HAS_CLIENT_CERT_PATH +#ifdef UNICODE +#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W +#else +#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A +#endif +#endif + +#ifndef SP_PROT_SSL2_CLIENT +#define SP_PROT_SSL2_CLIENT 0x00000008 +#endif + +#ifndef SP_PROT_SSL3_CLIENT +#define SP_PROT_SSL3_CLIENT 0x00000008 +#endif + +#ifndef SP_PROT_TLS1_CLIENT +#define SP_PROT_TLS1_CLIENT 0x00000080 +#endif + +#ifndef SP_PROT_TLS1_0_CLIENT +#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT +#endif + +#ifndef SP_PROT_TLS1_1_CLIENT +#define SP_PROT_TLS1_1_CLIENT 0x00000200 +#endif + +#ifndef SP_PROT_TLS1_2_CLIENT +#define SP_PROT_TLS1_2_CLIENT 0x00000800 +#endif + +#ifndef SECBUFFER_ALERT +#define SECBUFFER_ALERT 17 +#endif + +/* Both schannel buffer sizes must be > 0 */ +#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096 +#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024 + +#define CERT_THUMBPRINT_STR_LEN 40 +#define CERT_THUMBPRINT_DATA_LEN 20 + +/* Uncomment to force verbose output + * #define infof(x, y, ...) printf(y, __VA_ARGS__) + * #define failf(x, y, ...) printf(y, __VA_ARGS__) + */ + +#ifndef CALG_SHA_256 +# define CALG_SHA_256 0x0000800c +#endif + +#define BACKEND connssl->backend + +static Curl_recv schannel_recv; +static Curl_send schannel_send; + +static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, + const char *pinnedpubkey); + +static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType, + void *BufDataPtr, unsigned long BufByteSize) +{ + buffer->cbBuffer = BufByteSize; + buffer->BufferType = BufType; + buffer->pvBuffer = BufDataPtr; +} + +static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, + unsigned long NumArrElem) +{ + desc->ulVersion = SECBUFFER_VERSION; + desc->pBuffers = BufArr; + desc->cBuffers = NumArrElem; +} + +static CURLcode +set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long i = ssl_version; + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + for(; i <= (ssl_version_max >> 16); ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_1: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_2: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "schannel: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +} + +/*longest is 26, buffer is slightly bigger*/ +#define LONGEST_ALG_ID 32 +#define CIPHEROPTION(X) \ +if(strcmp(#X, tmp) == 0) \ + return X + +static int +get_alg_id_by_name(char *name) +{ + char tmp[LONGEST_ALG_ID] = { 0 }; + char *nameEnd = strchr(name, ':'); + size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \ + min(strlen(name), LONGEST_ALG_ID - 1); + strncpy(tmp, name, n); + tmp[n] = 0; + CIPHEROPTION(CALG_MD2); + CIPHEROPTION(CALG_MD4); + CIPHEROPTION(CALG_MD5); + CIPHEROPTION(CALG_SHA); + CIPHEROPTION(CALG_SHA1); + CIPHEROPTION(CALG_MAC); + CIPHEROPTION(CALG_RSA_SIGN); + CIPHEROPTION(CALG_DSS_SIGN); +/*ifdefs for the options that are defined conditionally in wincrypt.h*/ +#ifdef CALG_NO_SIGN + CIPHEROPTION(CALG_NO_SIGN); +#endif + CIPHEROPTION(CALG_RSA_KEYX); + CIPHEROPTION(CALG_DES); +#ifdef CALG_3DES_112 + CIPHEROPTION(CALG_3DES_112); +#endif + CIPHEROPTION(CALG_3DES); + CIPHEROPTION(CALG_DESX); + CIPHEROPTION(CALG_RC2); + CIPHEROPTION(CALG_RC4); + CIPHEROPTION(CALG_SEAL); +#ifdef CALG_DH_SF + CIPHEROPTION(CALG_DH_SF); +#endif + CIPHEROPTION(CALG_DH_EPHEM); +#ifdef CALG_AGREEDKEY_ANY + CIPHEROPTION(CALG_AGREEDKEY_ANY); +#endif +#ifdef CALG_HUGHES_MD5 + CIPHEROPTION(CALG_HUGHES_MD5); +#endif + CIPHEROPTION(CALG_SKIPJACK); +#ifdef CALG_TEK + CIPHEROPTION(CALG_TEK); +#endif + CIPHEROPTION(CALG_CYLINK_MEK); + CIPHEROPTION(CALG_SSL3_SHAMD5); +#ifdef CALG_SSL3_MASTER + CIPHEROPTION(CALG_SSL3_MASTER); +#endif +#ifdef CALG_SCHANNEL_MASTER_HASH + CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH); +#endif +#ifdef CALG_SCHANNEL_MAC_KEY + CIPHEROPTION(CALG_SCHANNEL_MAC_KEY); +#endif +#ifdef CALG_SCHANNEL_ENC_KEY + CIPHEROPTION(CALG_SCHANNEL_ENC_KEY); +#endif +#ifdef CALG_PCT1_MASTER + CIPHEROPTION(CALG_PCT1_MASTER); +#endif +#ifdef CALG_SSL2_MASTER + CIPHEROPTION(CALG_SSL2_MASTER); +#endif +#ifdef CALG_TLS1_MASTER + CIPHEROPTION(CALG_TLS1_MASTER); +#endif +#ifdef CALG_RC5 + CIPHEROPTION(CALG_RC5); +#endif +#ifdef CALG_HMAC + CIPHEROPTION(CALG_HMAC); +#endif +#if !defined(__W32API_MAJOR_VERSION) || \ + !defined(__W32API_MINOR_VERSION) || \ + defined(__MINGW64_VERSION_MAJOR) || \ + (__W32API_MAJOR_VERSION > 5) || \ + ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0)) + /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0, + see https://osdn.net/projects/mingw/ticket/38391 */ + CIPHEROPTION(CALG_TLS1PRF); +#endif +#ifdef CALG_HASH_REPLACE_OWF + CIPHEROPTION(CALG_HASH_REPLACE_OWF); +#endif +#ifdef CALG_AES_128 + CIPHEROPTION(CALG_AES_128); +#endif +#ifdef CALG_AES_192 + CIPHEROPTION(CALG_AES_192); +#endif +#ifdef CALG_AES_256 + CIPHEROPTION(CALG_AES_256); +#endif +#ifdef CALG_AES + CIPHEROPTION(CALG_AES); +#endif +#ifdef CALG_SHA_256 + CIPHEROPTION(CALG_SHA_256); +#endif +#ifdef CALG_SHA_384 + CIPHEROPTION(CALG_SHA_384); +#endif +#ifdef CALG_SHA_512 + CIPHEROPTION(CALG_SHA_512); +#endif +#ifdef CALG_ECDH + CIPHEROPTION(CALG_ECDH); +#endif +#ifdef CALG_ECMQV + CIPHEROPTION(CALG_ECMQV); +#endif +#ifdef CALG_ECDSA + CIPHEROPTION(CALG_ECDSA); +#endif +#ifdef CALG_ECDH_EPHEM + CIPHEROPTION(CALG_ECDH_EPHEM); +#endif + return 0; +} + +static CURLcode +set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers) +{ + char *startCur = ciphers; + int algCount = 0; + static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/ + while(startCur && (0 != *startCur) && (algCount < 45)) { + long alg = strtol(startCur, 0, 0); + if(!alg) + alg = get_alg_id_by_name(startCur); + if(alg) + algIds[algCount++] = alg; + else + return CURLE_SSL_CIPHER; + startCur = strchr(startCur, ':'); + if(startCur) + startCur++; + } + schannel_cred->palgSupportedAlgs = algIds; + schannel_cred->cSupportedAlgs = algCount; + return CURLE_OK; +} + +#ifdef HAS_CLIENT_CERT_PATH +static CURLcode +get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, + TCHAR **thumbprint) +{ + TCHAR *sep; + TCHAR *store_path_start; + size_t store_name_len; + + sep = _tcschr(path, TEXT('\\')); + if(sep == NULL) + return CURLE_SSL_CERTPROBLEM; + + store_name_len = sep - path; + + if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_CURRENT_USER; + else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE; + else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE; + else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_SERVICES; + else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_USERS; + else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"), + store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY; + else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"), + store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY; + else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"), + store_name_len) == 0) + *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE; + else + return CURLE_SSL_CERTPROBLEM; + + store_path_start = sep + 1; + + sep = _tcschr(store_path_start, TEXT('\\')); + if(sep == NULL) + return CURLE_SSL_CERTPROBLEM; + + *sep = TEXT('\0'); + *store_path = _tcsdup(store_path_start); + *sep = TEXT('\\'); + if(*store_path == NULL) + return CURLE_OUT_OF_MEMORY; + + *thumbprint = sep + 1; + if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN) + return CURLE_SSL_CERTPROBLEM; + + return CURLE_OK; +} +#endif + +static CURLcode +schannel_connect_step1(struct connectdata *conn, int sockindex) +{ + ssize_t written = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SecBuffer outbuf; + SecBufferDesc outbuf_desc; + SecBuffer inbuf; + SecBufferDesc inbuf_desc; +#ifdef HAS_ALPN + unsigned char alpn_buffer[128]; +#endif + SCHANNEL_CRED schannel_cred; + PCCERT_CONTEXT client_certs[1] = { NULL }; + SECURITY_STATUS sspi_status = SEC_E_OK; + struct curl_schannel_cred *old_cred = NULL; + struct in_addr addr; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + TCHAR *host_name; + CURLcode result; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", + hostname, conn->remote_port)); + + if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, + VERSION_LESS_THAN_EQUAL)) { + /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and + algorithms that may not be supported by all servers. */ + infof(data, "schannel: Windows version is old and may not be able to " + "connect to some servers due to lack of SNI, algorithms, etc.\n"); + } + +#ifdef HAS_ALPN + /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. + Also it doesn't seem to be supported for Wine, see curl bug #983. */ + BACKEND->use_alpn = conn->bits.tls_enable_alpn && + !GetProcAddress(GetModuleHandleA("ntdll"), + "wine_get_version") && + Curl_verify_windows_version(6, 3, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL); +#else + BACKEND->use_alpn = false; +#endif + +#ifdef _WIN32_WCE +#ifdef HAS_MANUAL_VERIFY_API + /* certificate validation on CE doesn't seem to work right; we'll + * do it following a more manual process. */ + BACKEND->use_manual_cred_validation = true; +#else +#error "compiler too old to support requisite manual cert verify for Win CE" +#endif +#else +#ifdef HAS_MANUAL_VERIFY_API + if(SSL_CONN_CONFIG(CAfile)) { + if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { + BACKEND->use_manual_cred_validation = true; + } + else { + failf(data, "schannel: this version of Windows is too old to support " + "certificate verification via CA bundle file."); + return CURLE_SSL_CACERT_BADFILE; + } + } + else + BACKEND->use_manual_cred_validation = false; +#else + if(SSL_CONN_CONFIG(CAfile)) { + failf(data, "schannel: CA cert support not built in"); + return CURLE_NOT_BUILT_IN; + } +#endif +#endif + + BACKEND->cred = NULL; + + /* check for an existing re-usable credential handle */ + if(SSL_SET_OPTION(primary.sessionid)) { + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { + BACKEND->cred = old_cred; + DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); + + /* increment the reference counter of the credential/session handle */ + BACKEND->cred->refcount++; + DEBUGF(infof(data, + "schannel: incremented credential handle refcount = %d\n", + BACKEND->cred->refcount)); + } + Curl_ssl_sessionid_unlock(conn); + } + + if(!BACKEND->cred) { + /* setup Schannel API options */ + memset(&schannel_cred, 0, sizeof(schannel_cred)); + schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; + + if(conn->ssl_config.verifypeer) { +#ifdef HAS_MANUAL_VERIFY_API + if(BACKEND->use_manual_cred_validation) + schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; + else +#endif + schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; + + if(data->set.ssl.no_revoke) { + schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + + DEBUGF(infof(data, "schannel: disabled server certificate revocation " + "checks\n")); + } + else { + schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + DEBUGF(infof(data, + "schannel: checking server certificate revocation\n")); + } + } + else { + schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | + SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + DEBUGF(infof(data, + "schannel: disabled server cert revocation checks\n")); + } + + if(!conn->ssl_config.verifyhost) { + schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " + "comparing the supplied target name with the subject " + "names in server certificates.\n")); + } + + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | + SP_PROT_TLS1_1_CLIENT | + SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + result = set_ssl_version_min_max(&schannel_cred, conn); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; + break; + case CURL_SSLVERSION_SSLv2: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(SSL_CONN_CONFIG(cipher_list)) { + result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list)); + if(CURLE_OK != result) { + failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG"); + return result; + } + } + + +#ifdef HAS_CLIENT_CERT_PATH + /* client certificate */ + if(data->set.ssl.cert) { + DWORD cert_store_name; + TCHAR *cert_store_path; + TCHAR *cert_thumbprint_str; + CRYPT_HASH_BLOB cert_thumbprint; + BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN]; + HCERTSTORE cert_store; + + TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert); + if(!cert_path) + return CURLE_OUT_OF_MEMORY; + + result = get_cert_location(cert_path, &cert_store_name, + &cert_store_path, &cert_thumbprint_str); + if(result != CURLE_OK) { + failf(data, "schannel: Failed to get certificate location for %s", + cert_path); + Curl_unicodefree(cert_path); + return result; + } + + cert_store = + CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0, + (HCRYPTPROV)NULL, + CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name, + cert_store_path); + if(!cert_store) { + failf(data, "schannel: Failed to open cert store %x %s, " + "last error is %x", + cert_store_name, cert_store_path, GetLastError()); + free(cert_store_path); + Curl_unicodefree(cert_path); + return CURLE_SSL_CERTPROBLEM; + } + free(cert_store_path); + + cert_thumbprint.pbData = cert_thumbprint_data; + cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; + + if(!CryptStringToBinary(cert_thumbprint_str, CERT_THUMBPRINT_STR_LEN, + CRYPT_STRING_HEX, + cert_thumbprint_data, &cert_thumbprint.cbData, + NULL, NULL)) { + Curl_unicodefree(cert_path); + return CURLE_SSL_CERTPROBLEM; + } + + client_certs[0] = CertFindCertificateInStore( + cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, + CERT_FIND_HASH, &cert_thumbprint, NULL); + + Curl_unicodefree(cert_path); + + if(client_certs[0]) { + schannel_cred.cCreds = 1; + schannel_cred.paCred = client_certs; + } + else { + /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ + return CURLE_SSL_CERTPROBLEM; + } + + CertCloseStore(cert_store, 0); + } +#else + if(data->set.ssl.cert) { + failf(data, "schannel: client cert support not built in"); + return CURLE_NOT_BUILT_IN; + } +#endif + + /* allocate memory for the re-usable credential handle */ + BACKEND->cred = (struct curl_schannel_cred *) + calloc(1, sizeof(struct curl_schannel_cred)); + if(!BACKEND->cred) { + failf(data, "schannel: unable to allocate memory"); + + if(client_certs[0]) + CertFreeCertificateContext(client_certs[0]); + + return CURLE_OUT_OF_MEMORY; + } + BACKEND->cred->refcount = 1; + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx + */ + sspi_status = + s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, + SECPKG_CRED_OUTBOUND, NULL, + &schannel_cred, NULL, NULL, + &BACKEND->cred->cred_handle, + &BACKEND->cred->time_stamp); + + if(client_certs[0]) + CertFreeCertificateContext(client_certs[0]); + + if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: AcquireCredentialsHandle failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + Curl_safefree(BACKEND->cred); + switch(sspi_status) { + case SEC_E_INSUFFICIENT_MEMORY: + return CURLE_OUT_OF_MEMORY; + case SEC_E_NO_CREDENTIALS: + case SEC_E_SECPKG_NOT_FOUND: + case SEC_E_NOT_OWNER: + case SEC_E_UNKNOWN_CREDENTIALS: + case SEC_E_INTERNAL_ERROR: + default: + return CURLE_SSL_CONNECT_ERROR; + } + } + } + + /* Warn if SNI is disabled due to use of an IP address */ + if(Curl_inet_pton(AF_INET, hostname, &addr) +#ifdef ENABLE_IPV6 + || Curl_inet_pton(AF_INET6, hostname, &addr6) +#endif + ) { + infof(data, "schannel: using IP address, SNI is not supported by OS.\n"); + } + +#ifdef HAS_ALPN + if(BACKEND->use_alpn) { + int cur = 0; + int list_start_index = 0; + unsigned int *extension_len = NULL; + unsigned short* list_len = NULL; + + /* The first four bytes will be an unsigned int indicating number + of bytes of data in the rest of the the buffer. */ + extension_len = (unsigned int *)(&alpn_buffer[cur]); + cur += sizeof(unsigned int); + + /* The next four bytes are an indicator that this buffer will contain + ALPN data, as opposed to NPN, for example. */ + *(unsigned int *)&alpn_buffer[cur] = + SecApplicationProtocolNegotiationExt_ALPN; + cur += sizeof(unsigned int); + + /* The next two bytes will be an unsigned short indicating the number + of bytes used to list the preferred protocols. */ + list_len = (unsigned short*)(&alpn_buffer[cur]); + cur += sizeof(unsigned short); + + list_start_index = cur; + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN); + cur += NGHTTP2_PROTO_ALPN_LEN; + infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH; + memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + cur += ALPN_HTTP_1_1_LENGTH; + infof(data, "schannel: ALPN, offering %s\n", ALPN_HTTP_1_1); + + *list_len = curlx_uitous(cur - list_start_index); + *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short); + + InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur); + InitSecBufferDesc(&inbuf_desc, &inbuf, 1); + } + else { + InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, &inbuf, 1); + } +#else /* HAS_ALPN */ + InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, &inbuf, 1); +#endif + + /* setup output buffer */ + InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, &outbuf, 1); + + /* setup request flags */ + BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | + ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_STREAM; + + /* allocate memory for the security context handle */ + BACKEND->ctxt = (struct curl_schannel_ctxt *) + calloc(1, sizeof(struct curl_schannel_ctxt)); + if(!BACKEND->ctxt) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + + host_name = Curl_convert_UTF8_to_tchar(hostname); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* Schannel InitializeSecurityContext: + https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx + + At the moment we don't pass inbuf unless we're using ALPN since we only + use it for that, and Wine (for which we currently disable ALPN) is giving + us problems with inbuf regardless. https://github.com/curl/curl/issues/983 + */ + sspi_status = s_pSecFn->InitializeSecurityContext( + &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0, + (BACKEND->use_alpn ? &inbuf_desc : NULL), + 0, &BACKEND->ctxt->ctxt_handle, + &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + if(sspi_status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; + Curl_safefree(BACKEND->ctxt); + switch(sspi_status) { + case SEC_E_INSUFFICIENT_MEMORY: + failf(data, "schannel: initial InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_OUT_OF_MEMORY; + case SEC_E_WRONG_PRINCIPAL: + failf(data, "schannel: SNI or certificate check failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_PEER_FAILED_VERIFICATION; + /* + case SEC_E_INVALID_HANDLE: + case SEC_E_INVALID_TOKEN: + case SEC_E_LOGON_DENIED: + case SEC_E_TARGET_UNKNOWN: + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + case SEC_E_INTERNAL_ERROR: + case SEC_E_NO_CREDENTIALS: + case SEC_E_UNSUPPORTED_FUNCTION: + case SEC_E_APPLICATION_PROTOCOL_MISMATCH: + */ + default: + failf(data, "schannel: initial InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_SSL_CONNECT_ERROR; + } + } + + DEBUGF(infof(data, "schannel: sending initial handshake data: " + "sending %lu bytes...\n", outbuf.cbBuffer)); + + /* send initial handshake data which is now stored in output buffer */ + result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + outbuf.cbBuffer, &written); + s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); + if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { + failf(data, "schannel: failed to send initial handshake data: " + "sent %zd of %lu bytes", written, outbuf.cbBuffer); + return CURLE_SSL_CONNECT_ERROR; + } + + DEBUGF(infof(data, "schannel: sent initial handshake data: " + "sent %zd bytes\n", written)); + + BACKEND->recv_unrecoverable_err = CURLE_OK; + BACKEND->recv_sspi_close_notify = false; + BACKEND->recv_connection_closed = false; + BACKEND->encdata_is_incomplete = false; + + /* continue to second handshake step */ + connssl->connecting_state = ssl_connect_2; + + return CURLE_OK; +} + +static CURLcode +schannel_connect_step2(struct connectdata *conn, int sockindex) +{ + int i; + ssize_t nread = -1, written = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned char *reallocated_buffer; + SecBuffer outbuf[3]; + SecBufferDesc outbuf_desc; + SecBuffer inbuf[2]; + SecBufferDesc inbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + CURLcode result; + bool doread; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char *pubkey_ptr; + + doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; + + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", + hostname, conn->remote_port)); + + if(!BACKEND->cred || !BACKEND->ctxt) + return CURLE_SSL_CONNECT_ERROR; + + /* buffer to store previously received and decrypted data */ + if(BACKEND->decdata_buffer == NULL) { + BACKEND->decdata_offset = 0; + BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; + BACKEND->decdata_buffer = malloc(BACKEND->decdata_length); + if(BACKEND->decdata_buffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + } + + /* buffer to store previously received and encrypted data */ + if(BACKEND->encdata_buffer == NULL) { + BACKEND->encdata_is_incomplete = false; + BACKEND->encdata_offset = 0; + BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; + BACKEND->encdata_buffer = malloc(BACKEND->encdata_length); + if(BACKEND->encdata_buffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + } + + /* if we need a bigger buffer to read a full message, increase buffer now */ + if(BACKEND->encdata_length - BACKEND->encdata_offset < + CURL_SCHANNEL_BUFFER_FREE_SIZE) { + /* increase internal encrypted data buffer */ + size_t reallocated_length = BACKEND->encdata_offset + + CURL_SCHANNEL_BUFFER_FREE_SIZE; + reallocated_buffer = realloc(BACKEND->encdata_buffer, + reallocated_length); + + if(reallocated_buffer == NULL) { + failf(data, "schannel: unable to re-allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + else { + BACKEND->encdata_buffer = reallocated_buffer; + BACKEND->encdata_length = reallocated_length; + } + } + + for(;;) { + TCHAR *host_name; + if(doread) { + /* read encrypted handshake data from socket */ + result = Curl_read_plain(conn->sock[sockindex], + (char *) (BACKEND->encdata_buffer + + BACKEND->encdata_offset), + BACKEND->encdata_length - + BACKEND->encdata_offset, + &nread); + if(result == CURLE_AGAIN) { + if(connssl->connecting_state != ssl_connect_2_writing) + connssl->connecting_state = ssl_connect_2_reading; + DEBUGF(infof(data, "schannel: failed to receive handshake, " + "need more data\n")); + return CURLE_OK; + } + else if((result != CURLE_OK) || (nread == 0)) { + failf(data, "schannel: failed to receive handshake, " + "SSL/TLS connection failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* increase encrypted data buffer offset */ + BACKEND->encdata_offset += nread; + BACKEND->encdata_is_incomplete = false; + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); + } + + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + + /* setup input buffers */ + InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset), + curlx_uztoul(BACKEND->encdata_offset)); + InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, inbuf, 2); + + /* setup output buffers */ + InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0); + InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0); + InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, outbuf, 3); + + if(inbuf[0].pvBuffer == NULL) { + failf(data, "schannel: unable to allocate memory"); + return CURLE_OUT_OF_MEMORY; + } + + /* copy received handshake data into input buffer */ + memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer, + BACKEND->encdata_offset); + + host_name = Curl_convert_UTF8_to_tchar(hostname); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx + */ + sspi_status = s_pSecFn->InitializeSecurityContext( + &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle, + host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL, + &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + /* free buffer for received handshake data */ + Curl_safefree(inbuf[0].pvBuffer); + + /* check if the handshake was incomplete */ + if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + BACKEND->encdata_is_incomplete = true; + connssl->connecting_state = ssl_connect_2_reading; + DEBUGF(infof(data, + "schannel: received incomplete message, need more data\n")); + return CURLE_OK; + } + + /* If the server has requested a client certificate, attempt to continue + the handshake without one. This will allow connections to servers which + request a client certificate but do not require it. */ + if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS && + !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { + BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; + connssl->connecting_state = ssl_connect_2_writing; + DEBUGF(infof(data, + "schannel: a client certificate has been requested\n")); + return CURLE_OK; + } + + /* check if the handshake needs to be continued */ + if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) { + for(i = 0; i < 3; i++) { + /* search for handshake tokens that need to be send */ + if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { + DEBUGF(infof(data, "schannel: sending next handshake data: " + "sending %lu bytes...\n", outbuf[i].cbBuffer)); + + /* send handshake token to server */ + result = Curl_write_plain(conn, conn->sock[sockindex], + outbuf[i].pvBuffer, outbuf[i].cbBuffer, + &written); + if((result != CURLE_OK) || + (outbuf[i].cbBuffer != (size_t) written)) { + failf(data, "schannel: failed to send next handshake data: " + "sent %zd of %lu bytes", written, outbuf[i].cbBuffer); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* free obsolete buffer */ + if(outbuf[i].pvBuffer != NULL) { + s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer); + } + } + } + else { + char buffer[STRERROR_LEN]; + switch(sspi_status) { + case SEC_E_INSUFFICIENT_MEMORY: + failf(data, "schannel: next InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_OUT_OF_MEMORY; + case SEC_E_WRONG_PRINCIPAL: + failf(data, "schannel: SNI or certificate check failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_PEER_FAILED_VERIFICATION; + /* + case SEC_E_INVALID_HANDLE: + case SEC_E_INVALID_TOKEN: + case SEC_E_LOGON_DENIED: + case SEC_E_TARGET_UNKNOWN: + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + case SEC_E_INTERNAL_ERROR: + case SEC_E_NO_CREDENTIALS: + case SEC_E_UNSUPPORTED_FUNCTION: + case SEC_E_APPLICATION_PROTOCOL_MISMATCH: + */ + default: + failf(data, "schannel: next InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_SSL_CONNECT_ERROR; + } + } + + /* check if there was additional remaining encrypted data */ + if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[1].cbBuffer)); + /* + There are two cases where we could be getting extra data here: + 1) If we're renegotiating a connection and the handshake is already + complete (from the server perspective), it can encrypted app data + (not handshake data) in an extra buffer at this point. + 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a + connection and this extra data is part of the handshake. + We should process the data immediately; waiting for the socket to + be ready may fail since the server is done sending handshake data. + */ + /* check if the remaining data is less than the total amount + and therefore begins after the already processed data */ + if(BACKEND->encdata_offset > inbuf[1].cbBuffer) { + memmove(BACKEND->encdata_buffer, + (BACKEND->encdata_buffer + BACKEND->encdata_offset) - + inbuf[1].cbBuffer, inbuf[1].cbBuffer); + BACKEND->encdata_offset = inbuf[1].cbBuffer; + if(sspi_status == SEC_I_CONTINUE_NEEDED) { + doread = FALSE; + continue; + } + } + } + else { + BACKEND->encdata_offset = 0; + } + break; + } + + /* check if the handshake needs to be continued */ + if(sspi_status == SEC_I_CONTINUE_NEEDED) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + + /* check if the handshake is complete */ + if(sspi_status == SEC_E_OK) { + connssl->connecting_state = ssl_connect_3; + DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); + } + + pubkey_ptr = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + if(pubkey_ptr) { + result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } + +#ifdef HAS_MANUAL_VERIFY_API + if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) { + return Curl_verify_certificate(conn, sockindex); + } +#endif + + return CURLE_OK; +} + +static bool +valid_cert_encoding(const CERT_CONTEXT *cert_context) +{ + return (cert_context != NULL) && + ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && + (cert_context->pbCertEncoded != NULL) && + (cert_context->cbCertEncoded > 0); +} + +typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg); + +static void +traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func, + void *arg) +{ + const CERT_CONTEXT *current_context = NULL; + bool should_continue = true; + while(should_continue && + (current_context = CertEnumCertificatesInStore( + context->hCertStore, + current_context)) != NULL) + should_continue = func(current_context, arg); + + if(current_context) + CertFreeCertificateContext(current_context); +} + +static bool +cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count) +{ + if(valid_cert_encoding(ccert_context)) + (*(int *)certs_count)++; + return true; +} + +struct Adder_args +{ + struct connectdata *conn; + CURLcode result; + int idx; +}; + +static bool +add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg) +{ + struct Adder_args *args = (struct Adder_args*)raw_arg; + args->result = CURLE_OK; + if(valid_cert_encoding(ccert_context)) { + const char *beg = (const char *) ccert_context->pbCertEncoded; + const char *end = beg + ccert_context->cbCertEncoded; + args->result = Curl_extract_certinfo(args->conn, (args->idx)++, beg, end); + } + return args->result == CURLE_OK; +} + +static CURLcode +schannel_connect_step3(struct connectdata *conn, int sockindex) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SECURITY_STATUS sspi_status = SEC_E_OK; + CERT_CONTEXT *ccert_context = NULL; +#ifdef DEBUGBUILD + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; +#endif +#ifdef HAS_ALPN + SecPkgContext_ApplicationProtocol alpn_result; +#endif + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", + hostname, conn->remote_port)); + + if(!BACKEND->cred) + return CURLE_SSL_CONNECT_ERROR; + + /* check if the required context attributes are met */ + if(BACKEND->ret_flags != BACKEND->req_flags) { + if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT)) + failf(data, "schannel: failed to setup sequence detection"); + if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT)) + failf(data, "schannel: failed to setup replay detection"); + if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY)) + failf(data, "schannel: failed to setup confidentiality"); + if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY)) + failf(data, "schannel: failed to setup memory allocation"); + if(!(BACKEND->ret_flags & ISC_RET_STREAM)) + failf(data, "schannel: failed to setup stream orientation"); + return CURLE_SSL_CONNECT_ERROR; + } + +#ifdef HAS_ALPN + if(BACKEND->use_alpn) { + sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result); + + if(sspi_status != SEC_E_OK) { + failf(data, "schannel: failed to retrieve ALPN result"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(alpn_result.ProtoNegoStatus == + SecApplicationProtocolNegotiationStatus_Success) { + + infof(data, "schannel: ALPN, server accepted to use %.*s\n", + alpn_result.ProtocolIdSize, alpn_result.ProtocolId); + +#ifdef USE_NGHTTP2 + if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId, + NGHTTP2_PROTO_VERSION_ID_LEN)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH && + !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId, + ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } +#endif + + /* save the current session data for possible re-use */ + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + struct curl_schannel_cred *old_cred = NULL; + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, + sockindex)); + if(incache) { + if(old_cred != BACKEND->cred) { + DEBUGF(infof(data, + "schannel: old credential handle is stale, removing\n")); + /* we're not taking old_cred ownership here, no refcount++ is needed */ + Curl_ssl_delsessionid(conn, (void *)old_cred); + incache = FALSE; + } + } + if(!incache) { + result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred, + sizeof(struct curl_schannel_cred), + sockindex); + if(result) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "schannel: failed to store credential handle"); + return result; + } + else { + /* this cred session is now also referenced by sessionid cache */ + BACKEND->cred->refcount++; + DEBUGF(infof(data, + "schannel: stored credential handle in session cache\n")); + } + } + Curl_ssl_sessionid_unlock(conn); + } + + if(data->set.ssl.certinfo) { + int certs_count = 0; + sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context); + + if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { + failf(data, "schannel: failed to retrieve remote cert context"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + traverse_cert_store(ccert_context, cert_counter_callback, &certs_count); + + result = Curl_ssl_init_certinfo(data, certs_count); + if(!result) { + struct Adder_args args; + args.conn = conn; + args.idx = 0; + traverse_cert_store(ccert_context, add_cert_to_certinfo, &args); + result = args.result; + } + CertFreeCertificateContext(ccert_context); + if(result) + return result; + } + + connssl->connecting_state = ssl_connect_done; + + return CURLE_OK; +} + +static CURLcode +schannel_connect_common(struct connectdata *conn, int sockindex, + bool nonblocking, bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* check out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = schannel_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state ? sockfd : CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking ? 0 : timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL/TLS connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = schannel_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = schannel_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = schannel_recv; + conn->send[sockindex] = schannel_send; + +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + /* When SSPI is used in combination with Schannel + * we need the Schannel context to create the Schannel + * binding to pass the IIS extended protection checks. + * Available on Windows 7 or later. + */ + conn->sslContext = &BACKEND->ctxt->ctxt_handle; +#endif + + *done = TRUE; + } + else + *done = FALSE; + + /* reset our connection state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static ssize_t +schannel_send(struct connectdata *conn, int sockindex, + const void *buf, size_t len, CURLcode *err) +{ + ssize_t written = -1; + size_t data_len = 0; + unsigned char *data = NULL; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SecBuffer outbuf[4]; + SecBufferDesc outbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + CURLcode result; + + /* check if the maximum stream sizes were queried */ + if(BACKEND->stream_sizes.cbMaximumMessage == 0) { + sspi_status = s_pSecFn->QueryContextAttributes( + &BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_STREAM_SIZES, + &BACKEND->stream_sizes); + if(sspi_status != SEC_E_OK) { + *err = CURLE_SEND_ERROR; + return -1; + } + } + + /* check if the buffer is longer than the maximum message length */ + if(len > BACKEND->stream_sizes.cbMaximumMessage) { + len = BACKEND->stream_sizes.cbMaximumMessage; + } + + /* calculate the complete message length and allocate a buffer for it */ + data_len = BACKEND->stream_sizes.cbHeader + len + + BACKEND->stream_sizes.cbTrailer; + data = (unsigned char *) malloc(data_len); + if(data == NULL) { + *err = CURLE_OUT_OF_MEMORY; + return -1; + } + + /* setup output buffers (header, data, trailer, empty) */ + InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER, + data, BACKEND->stream_sizes.cbHeader); + InitSecBuffer(&outbuf[1], SECBUFFER_DATA, + data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len)); + InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, + data + BACKEND->stream_sizes.cbHeader + len, + BACKEND->stream_sizes.cbTrailer); + InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, outbuf, 4); + + /* copy data into output buffer */ + memcpy(outbuf[1].pvBuffer, buf, len); + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */ + sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0, + &outbuf_desc, 0); + + /* check if the message was encrypted */ + if(sspi_status == SEC_E_OK) { + written = 0; + + /* send the encrypted message including header, data and trailer */ + len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; + + /* + It's important to send the full message which includes the header, + encrypted payload, and trailer. Until the client receives all the + data a coherent message has not been delivered and the client + can't read any of it. + + If we wanted to buffer the unwritten encrypted bytes, we would + tell the client that all data it has requested to be sent has been + sent. The unwritten encrypted bytes would be the first bytes to + send on the next invocation. + Here's the catch with this - if we tell the client that all the + bytes have been sent, will the client call this method again to + send the buffered data? Looking at who calls this function, it + seems the answer is NO. + */ + + /* send entire message or fail */ + while(len > (size_t)written) { + ssize_t this_write; + time_t timeleft; + int what; + + this_write = 0; + + timeleft = Curl_timeleft(conn->data, NULL, FALSE); + if(timeleft < 0) { + /* we already got the timeout */ + failf(conn->data, "schannel: timed out sending data " + "(bytes sent: %zd)", written); + *err = CURLE_OPERATION_TIMEDOUT; + written = -1; + break; + } + + what = SOCKET_WRITABLE(conn->sock[sockindex], timeleft); + if(what < 0) { + /* fatal error */ + failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + *err = CURLE_SEND_ERROR; + written = -1; + break; + } + else if(0 == what) { + failf(conn->data, "schannel: timed out sending data " + "(bytes sent: %zd)", written); + *err = CURLE_OPERATION_TIMEDOUT; + written = -1; + break; + } + /* socket is writable */ + + result = Curl_write_plain(conn, conn->sock[sockindex], data + written, + len - written, &this_write); + if(result == CURLE_AGAIN) + continue; + else if(result != CURLE_OK) { + *err = result; + written = -1; + break; + } + + written += this_write; + } + } + else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) { + *err = CURLE_OUT_OF_MEMORY; + } + else{ + *err = CURLE_SEND_ERROR; + } + + Curl_safefree(data); + + if(len == (size_t)written) + /* Encrypted message including header, data and trailer entirely sent. + The return value is the number of unencrypted bytes that were sent. */ + written = outbuf[1].cbBuffer; + + return written; +} + +static ssize_t +schannel_recv(struct connectdata *conn, int sockindex, + char *buf, size_t len, CURLcode *err) +{ + size_t size = 0; + ssize_t nread = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + unsigned char *reallocated_buffer; + size_t reallocated_length; + bool done = FALSE; + SecBuffer inbuf[4]; + SecBufferDesc inbuf_desc; + SECURITY_STATUS sspi_status = SEC_E_OK; + /* we want the length of the encrypted buffer to be at least large enough + that it can hold all the bytes requested and some TLS record overhead. */ + size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE; + + /**************************************************************************** + * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup. + * The pattern for return error is set *err, optional infof, goto cleanup. + * + * Our priority is to always return as much decrypted data to the caller as + * possible, even if an error occurs. The state of the decrypted buffer must + * always be valid. Transfer of decrypted data to the caller's buffer is + * handled in the cleanup. + */ + + DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len)); + *err = CURLE_OK; + + if(len && len <= BACKEND->decdata_offset) { + infof(data, "schannel: enough decrypted data is already available\n"); + goto cleanup; + } + else if(BACKEND->recv_unrecoverable_err) { + *err = BACKEND->recv_unrecoverable_err; + infof(data, "schannel: an unrecoverable error occurred in a prior call\n"); + goto cleanup; + } + else if(BACKEND->recv_sspi_close_notify) { + /* once a server has indicated shutdown there is no more encrypted data */ + infof(data, "schannel: server indicated shutdown in a prior call\n"); + goto cleanup; + } + else if(!len) { + /* It's debatable what to return when !len. Regardless we can't return + immediately because there may be data to decrypt (in the case we want to + decrypt all encrypted cached data) so handle !len later in cleanup. + */ + ; /* do nothing */ + } + else if(!BACKEND->recv_connection_closed) { + /* increase enc buffer in order to fit the requested amount of data */ + size = BACKEND->encdata_length - BACKEND->encdata_offset; + if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE || + BACKEND->encdata_length < min_encdata_length) { + reallocated_length = BACKEND->encdata_offset + + CURL_SCHANNEL_BUFFER_FREE_SIZE; + if(reallocated_length < min_encdata_length) { + reallocated_length = min_encdata_length; + } + reallocated_buffer = realloc(BACKEND->encdata_buffer, + reallocated_length); + if(reallocated_buffer == NULL) { + *err = CURLE_OUT_OF_MEMORY; + failf(data, "schannel: unable to re-allocate memory"); + goto cleanup; + } + + BACKEND->encdata_buffer = reallocated_buffer; + BACKEND->encdata_length = reallocated_length; + size = BACKEND->encdata_length - BACKEND->encdata_offset; + DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n", + BACKEND->encdata_length)); + } + + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + + /* read encrypted data from socket */ + *err = Curl_read_plain(conn->sock[sockindex], + (char *)(BACKEND->encdata_buffer + + BACKEND->encdata_offset), + size, &nread); + if(*err) { + nread = -1; + if(*err == CURLE_AGAIN) + DEBUGF(infof(data, + "schannel: Curl_read_plain returned CURLE_AGAIN\n")); + else if(*err == CURLE_RECV_ERROR) + infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); + else + infof(data, "schannel: Curl_read_plain returned error %d\n", *err); + } + else if(nread == 0) { + BACKEND->recv_connection_closed = true; + DEBUGF(infof(data, "schannel: server closed the connection\n")); + } + else if(nread > 0) { + BACKEND->encdata_offset += (size_t)nread; + BACKEND->encdata_is_incomplete = false; + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); + } + } + + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + + /* decrypt loop */ + while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK && + (!len || BACKEND->decdata_offset < len || + BACKEND->recv_connection_closed)) { + /* prepare data buffer for DecryptMessage call */ + InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer, + curlx_uztoul(BACKEND->encdata_offset)); + + /* we need 3 more empty input buffers for possible output */ + InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); + InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0); + InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&inbuf_desc, inbuf, 4); + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx + */ + sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle, + &inbuf_desc, 0, NULL); + + /* check if everything went fine (server may want to renegotiate + or shutdown the connection context) */ + if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE || + sspi_status == SEC_I_CONTEXT_EXPIRED) { + /* check for successfully decrypted data, even before actual + renegotiation or shutdown of the connection context */ + if(inbuf[1].BufferType == SECBUFFER_DATA) { + DEBUGF(infof(data, "schannel: decrypted data length: %lu\n", + inbuf[1].cbBuffer)); + + /* increase buffer in order to fit the received amount of data */ + size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? + inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE; + if(BACKEND->decdata_length - BACKEND->decdata_offset < size || + BACKEND->decdata_length < len) { + /* increase internal decrypted data buffer */ + reallocated_length = BACKEND->decdata_offset + size; + /* make sure that the requested amount of data fits */ + if(reallocated_length < len) { + reallocated_length = len; + } + reallocated_buffer = realloc(BACKEND->decdata_buffer, + reallocated_length); + if(reallocated_buffer == NULL) { + *err = CURLE_OUT_OF_MEMORY; + failf(data, "schannel: unable to re-allocate memory"); + goto cleanup; + } + BACKEND->decdata_buffer = reallocated_buffer; + BACKEND->decdata_length = reallocated_length; + } + + /* copy decrypted data to internal buffer */ + size = inbuf[1].cbBuffer; + if(size) { + memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset, + inbuf[1].pvBuffer, size); + BACKEND->decdata_offset += size; + } + + DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted cached: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); + } + + /* check for remaining encrypted data */ + if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[3].cbBuffer)); + + /* check if the remaining data is less than the total amount + * and therefore begins after the already processed data + */ + if(BACKEND->encdata_offset > inbuf[3].cbBuffer) { + /* move remaining encrypted data forward to the beginning of + buffer */ + memmove(BACKEND->encdata_buffer, + (BACKEND->encdata_buffer + BACKEND->encdata_offset) - + inbuf[3].cbBuffer, inbuf[3].cbBuffer); + BACKEND->encdata_offset = inbuf[3].cbBuffer; + } + + DEBUGF(infof(data, + "schannel: encrypted cached: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + } + else { + /* reset encrypted buffer offset, because there is no data remaining */ + BACKEND->encdata_offset = 0; + } + + /* check if server wants to renegotiate the connection context */ + if(sspi_status == SEC_I_RENEGOTIATE) { + infof(data, "schannel: remote party requests renegotiation\n"); + if(*err && *err != CURLE_AGAIN) { + infof(data, "schannel: can't renogotiate, an error is pending\n"); + goto cleanup; + } + if(BACKEND->encdata_offset) { + *err = CURLE_RECV_ERROR; + infof(data, "schannel: can't renogotiate, " + "encrypted data available\n"); + goto cleanup; + } + /* begin renegotiation */ + infof(data, "schannel: renegotiating SSL/TLS connection\n"); + connssl->state = ssl_connection_negotiating; + connssl->connecting_state = ssl_connect_2_writing; + *err = schannel_connect_common(conn, sockindex, FALSE, &done); + if(*err) { + infof(data, "schannel: renegotiation failed\n"); + goto cleanup; + } + /* now retry receiving data */ + sspi_status = SEC_E_OK; + infof(data, "schannel: SSL/TLS connection renegotiated\n"); + continue; + } + /* check if the server closed the connection */ + else if(sspi_status == SEC_I_CONTEXT_EXPIRED) { + /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not + returned so we have to work around that in cleanup. */ + BACKEND->recv_sspi_close_notify = true; + if(!BACKEND->recv_connection_closed) { + BACKEND->recv_connection_closed = true; + infof(data, "schannel: server closed the connection\n"); + } + goto cleanup; + } + } + else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + BACKEND->encdata_is_incomplete = true; + if(!*err) + *err = CURLE_AGAIN; + infof(data, "schannel: failed to decrypt data, need more data\n"); + goto cleanup; + } + else { + char buffer[STRERROR_LEN]; + *err = CURLE_RECV_ERROR; + infof(data, "schannel: failed to read data from server: %s\n", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + goto cleanup; + } + } + + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); + + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); + +cleanup: + /* Warning- there is no guarantee the encdata state is valid at this point */ + DEBUGF(infof(data, "schannel: schannel_recv cleanup\n")); + + /* Error if the connection has closed without a close_notify. + Behavior here is a matter of debate. We don't want to be vulnerable to a + truncation attack however there's some browser precedent for ignoring the + close_notify for compatibility reasons. + Additionally, Windows 2000 (v5.0) is a special case since it seems it doesn't + return close_notify. In that case if the connection was closed we assume it + was graceful (close_notify) since there doesn't seem to be a way to tell. + */ + if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed && + !BACKEND->recv_sspi_close_notify) { + bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT, + VERSION_EQUAL); + + if(isWin2k && sspi_status == SEC_E_OK) + BACKEND->recv_sspi_close_notify = true; + else { + *err = CURLE_RECV_ERROR; + infof(data, "schannel: server closed abruptly (missing close_notify)\n"); + } + } + + /* Any error other than CURLE_AGAIN is an unrecoverable error. */ + if(*err && *err != CURLE_AGAIN) + BACKEND->recv_unrecoverable_err = *err; + + size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset; + if(size) { + memcpy(buf, BACKEND->decdata_buffer, size); + memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size, + BACKEND->decdata_offset - size); + BACKEND->decdata_offset -= size; + DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); + *err = CURLE_OK; + return (ssize_t)size; + } + + if(!*err && !BACKEND->recv_connection_closed) + *err = CURLE_AGAIN; + + /* It's debatable what to return when !len. We could return whatever error we + got from decryption but instead we override here so the return is consistent. + */ + if(!len) + *err = CURLE_OK; + + return *err ? -1 : 0; +} + +static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return schannel_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = schannel_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static bool Curl_schannel_data_pending(const struct connectdata *conn, + int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(connssl->use) /* SSL/TLS is in use */ + return (BACKEND->decdata_offset > 0 || + (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete)); + else + return FALSE; +} + +static void Curl_schannel_close(struct connectdata *conn, int sockindex) +{ + if(conn->ssl[sockindex].use) + /* if the SSL/TLS channel hasn't been shut down yet, do that now. */ + Curl_ssl_shutdown(conn, sockindex); +} + +static void Curl_schannel_session_free(void *ptr) +{ + /* this is expected to be called under sessionid lock */ + struct curl_schannel_cred *cred = ptr; + + cred->refcount--; + if(cred->refcount == 0) { + s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); + Curl_safefree(cred); + } +} + +static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) +{ + /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx + * Shutting Down an Schannel Connection + */ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + DEBUGASSERT(data); + + infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", + hostname, conn->remote_port); + + if(BACKEND->cred && BACKEND->ctxt) { + SecBufferDesc BuffDesc; + SecBuffer Buffer; + SECURITY_STATUS sspi_status; + SecBuffer outbuf; + SecBufferDesc outbuf_desc; + CURLcode result; + TCHAR *host_name; + DWORD dwshut = SCHANNEL_SHUTDOWN; + + InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); + InitSecBufferDesc(&BuffDesc, &Buffer, 1); + + sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle, + &BuffDesc); + + if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: ApplyControlToken failure: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + } + + host_name = Curl_convert_UTF8_to_tchar(hostname); + if(!host_name) + return CURLE_OUT_OF_MEMORY; + + /* setup output buffer */ + InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); + InitSecBufferDesc(&outbuf_desc, &outbuf, 1); + + sspi_status = s_pSecFn->InitializeSecurityContext( + &BACKEND->cred->cred_handle, + &BACKEND->ctxt->ctxt_handle, + host_name, + BACKEND->req_flags, + 0, + 0, + NULL, + 0, + &BACKEND->ctxt->ctxt_handle, + &outbuf_desc, + &BACKEND->ret_flags, + &BACKEND->ctxt->time_stamp); + + Curl_unicodefree(host_name); + + if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { + /* send close message which is in output buffer */ + ssize_t written; + result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, + outbuf.cbBuffer, &written); + + s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); + if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { + infof(data, "schannel: failed to send close msg: %s" + " (bytes written: %zd)\n", curl_easy_strerror(result), written); + } + } + } + + /* free SSPI Schannel API security context handle */ + if(BACKEND->ctxt) { + DEBUGF(infof(data, "schannel: clear security context handle\n")); + s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle); + Curl_safefree(BACKEND->ctxt); + } + + /* free SSPI Schannel API credential handle */ + if(BACKEND->cred) { + /* + * When this function is called from Curl_schannel_close() the connection + * might not have an associated transfer so the check for conn->data is + * necessary. + */ + Curl_ssl_sessionid_lock(conn); + Curl_schannel_session_free(BACKEND->cred); + Curl_ssl_sessionid_unlock(conn); + BACKEND->cred = NULL; + } + + /* free internal buffer for received encrypted data */ + if(BACKEND->encdata_buffer != NULL) { + Curl_safefree(BACKEND->encdata_buffer); + BACKEND->encdata_length = 0; + BACKEND->encdata_offset = 0; + BACKEND->encdata_is_incomplete = false; + } + + /* free internal buffer for received decrypted data */ + if(BACKEND->decdata_buffer != NULL) { + Curl_safefree(BACKEND->decdata_buffer); + BACKEND->decdata_length = 0; + BACKEND->decdata_offset = 0; + } + + return CURLE_OK; +} + +static int Curl_schannel_init(void) +{ + return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0); +} + +static void Curl_schannel_cleanup(void) +{ + Curl_sspi_global_cleanup(); +} + +static size_t Curl_schannel_version(char *buffer, size_t size) +{ + size = msnprintf(buffer, size, "Schannel"); + + return size; +} + +static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy, size_t length) +{ + HCRYPTPROV hCryptProv = 0; + + (void)data; + + if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + return CURLE_FAILED_INIT; + + if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) { + CryptReleaseContext(hCryptProv, 0UL); + return CURLE_FAILED_INIT; + } + + CryptReleaseContext(hCryptProv, 0UL); + return CURLE_OK; +} + +static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, + const char *pinnedpubkey) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CERT_CONTEXT *pCertContextServer = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + do { + SECURITY_STATUS sspi_status; + const char *x509_der; + DWORD x509_der_len; + curl_X509certificate x509_parsed; + curl_asn1Element *pubkey; + + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); + + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: Failed to read remote certificate context: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + break; /* failed */ + } + + + if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) && + (pCertContextServer->cbCertEncoded > 0))) + break; + + x509_der = (const char *)pCertContextServer->pbCertEncoded; + x509_der_len = pCertContextServer->cbCertEncoded; + memset(&x509_parsed, 0, sizeof(x509_parsed)); + if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) + break; + + pubkey = &x509_parsed.subjectPublicKeyInfo; + if(!pubkey->header || pubkey->end <= pubkey->header) { + failf(data, "SSL: failed retrieving public key from server certificate"); + break; + } + + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + (const unsigned char *)pubkey->header, + (size_t)(pubkey->end - pubkey->header)); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + } + } while(0); + + if(pCertContextServer) + CertFreeCertificateContext(pCertContextServer); + + return result; +} + +static void Curl_schannel_checksum(const unsigned char *input, + size_t inputlen, + unsigned char *checksum, + size_t checksumlen, + DWORD provType, + const unsigned int algId) +{ + HCRYPTPROV hProv = 0; + HCRYPTHASH hHash = 0; + DWORD cbHashSize = 0; + DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize); + DWORD dwChecksumLen = (DWORD)checksumlen; + + /* since this can fail in multiple ways, zero memory first so we never + * return old data + */ + memset(checksum, 0, checksumlen); + + if(!CryptAcquireContext(&hProv, NULL, NULL, provType, + CRYPT_VERIFYCONTEXT)) + return; /* failed */ + + do { + if(!CryptCreateHash(hProv, algId, 0, 0, &hHash)) + break; /* failed */ + + /* workaround for original MinGW, should be (const BYTE*) */ + if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0)) + break; /* failed */ + + /* get hash size */ + if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize, + &dwHashSizeLen, 0)) + break; /* failed */ + + /* check hash size */ + if(checksumlen < cbHashSize) + break; /* failed */ + + if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0)) + break; /* failed */ + } while(0); + + if(hHash) + CryptDestroyHash(hHash); + + if(hProv) + CryptReleaseContext(hProv, 0); +} + +static CURLcode Curl_schannel_md5sum(unsigned char *input, + size_t inputlen, + unsigned char *md5sum, + size_t md5len) +{ + Curl_schannel_checksum(input, inputlen, md5sum, md5len, + PROV_RSA_FULL, CALG_MD5); + return CURLE_OK; +} + +static CURLcode Curl_schannel_sha256sum(const unsigned char *input, + size_t inputlen, + unsigned char *sha256sum, + size_t sha256len) +{ + Curl_schannel_checksum(input, inputlen, sha256sum, sha256len, + PROV_RSA_AES, CALG_SHA_256); + return CURLE_OK; +} + +static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return &BACKEND->ctxt->ctxt_handle; +} + +const struct Curl_ssl Curl_ssl_schannel = { + { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ + + SSLSUPP_CERTINFO | + SSLSUPP_PINNEDPUBKEY, + + sizeof(struct ssl_backend_data), + + Curl_schannel_init, /* init */ + Curl_schannel_cleanup, /* cleanup */ + Curl_schannel_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_schannel_shutdown, /* shutdown */ + Curl_schannel_data_pending, /* data_pending */ + Curl_schannel_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_schannel_connect, /* connect */ + Curl_schannel_connect_nonblocking, /* connect_nonblocking */ + Curl_schannel_get_internals, /* get_internals */ + Curl_schannel_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_schannel_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_schannel_md5sum, /* md5sum */ + Curl_schannel_sha256sum /* sha256sum */ +}; + +#endif /* USE_SCHANNEL */ diff --git a/libcurl/lib/vtls/schannel.h b/libcurl/lib/vtls/schannel.h new file mode 100644 index 0000000..ee8d7d4 --- /dev/null +++ b/libcurl/lib/vtls/schannel.h @@ -0,0 +1,108 @@ +#ifndef HEADER_CURL_SCHANNEL_H +#define HEADER_CURL_SCHANNEL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Marc Hoersken, , et al. + * Copyright (C) 2012 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_SCHANNEL + +#include +#include +#include "curl_sspi.h" + +#include "urldata.h" + +/* has been included via the above . + * Or in case of ldap.c, it was included via . + * And since has this: + * #define X509_NAME ((LPCSTR) 7) + * + * And in BoringSSL's there is: + * typedef struct X509_name_st X509_NAME; + * etc. + * + * this will cause all kinds of C-preprocessing paste errors in + * BoringSSL's : So just undefine those defines here + * (and only here). + */ +#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL) +# undef X509_NAME +# undef X509_CERT_PAIR +# undef X509_EXTENSIONS +#endif + +extern const struct Curl_ssl Curl_ssl_schannel; + +CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex); + +/* structs to expose only in schannel.c and schannel_verify.c */ +#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS + +#ifdef __MINGW32__ +#include <_mingw.h> +#ifdef __MINGW64_VERSION_MAJOR +#define HAS_MANUAL_VERIFY_API +#endif +#else +#include +#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN +#define HAS_MANUAL_VERIFY_API +#endif +#endif + +struct curl_schannel_cred { + CredHandle cred_handle; + TimeStamp time_stamp; + int refcount; +}; + +struct curl_schannel_ctxt { + CtxtHandle ctxt_handle; + TimeStamp time_stamp; +}; + +struct ssl_backend_data { + struct curl_schannel_cred *cred; + struct curl_schannel_ctxt *ctxt; + SecPkgContext_StreamSizes stream_sizes; + size_t encdata_length, decdata_length; + size_t encdata_offset, decdata_offset; + unsigned char *encdata_buffer, *decdata_buffer; + /* encdata_is_incomplete: if encdata contains only a partial record that + can't be decrypted without another Curl_read_plain (that is, status is + SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes + more bytes into encdata then set this back to false. */ + bool encdata_is_incomplete; + unsigned long req_flags, ret_flags; + CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */ + bool recv_sspi_close_notify; /* true if connection closed by close_notify */ + bool recv_connection_closed; /* true if connection closed, regardless how */ + bool use_alpn; /* true if ALPN is used for this connection */ +#ifdef HAS_MANUAL_VERIFY_API + bool use_manual_cred_validation; /* true if manual cred validation is used */ +#endif +}; +#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */ + +#endif /* USE_SCHANNEL */ +#endif /* HEADER_CURL_SCHANNEL_H */ diff --git a/libcurl/lib/vtls/schannel_verify.c b/libcurl/lib/vtls/schannel_verify.c new file mode 100644 index 0000000..5a09e96 --- /dev/null +++ b/libcurl/lib/vtls/schannel_verify.c @@ -0,0 +1,572 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Marc Hoersken, + * Copyright (C) 2012, Mark Salisbury, + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for Schannel-specific certificate verification. This code should + * only be invoked by code in schannel.c. + */ + +#include "curl_setup.h" + +#ifdef USE_SCHANNEL +#ifndef USE_WINDOWS_SSPI +# error "Can't compile SCHANNEL support without SSPI." +#endif + +#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS +#include "schannel.h" + +#ifdef HAS_MANUAL_VERIFY_API + +#include "vtls.h" +#include "sendf.h" +#include "strerror.h" +#include "curl_multibyte.h" +#include "curl_printf.h" +#include "hostcheck.h" +#include "system_win32.h" + +/* The last #include file should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +#define BACKEND connssl->backend + +#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */ +#define BEGIN_CERT "-----BEGIN CERTIFICATE-----" +#define END_CERT "\n-----END CERTIFICATE-----" + +typedef struct { + DWORD cbSize; + HCERTSTORE hRestrictedRoot; + HCERTSTORE hRestrictedTrust; + HCERTSTORE hRestrictedOther; + DWORD cAdditionalStore; + HCERTSTORE *rghAdditionalStore; + DWORD dwFlags; + DWORD dwUrlRetrievalTimeout; + DWORD MaximumCachedCertificates; + DWORD CycleDetectionModulus; + HCERTSTORE hExclusiveRoot; + HCERTSTORE hExclusiveTrustedPeople; +} CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7; + +static int is_cr_or_lf(char c) +{ + return c == '\r' || c == '\n'; +} + +static CURLcode add_certs_to_store(HCERTSTORE trust_store, + const char *ca_file, + struct connectdata *conn) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + HANDLE ca_file_handle = INVALID_HANDLE_VALUE; + LARGE_INTEGER file_size; + char *ca_file_buffer = NULL; + char *current_ca_file_ptr = NULL; + TCHAR *ca_file_tstr = NULL; + size_t ca_file_bufsize = 0; + DWORD total_bytes_read = 0; + bool more_certs = 0; + int num_certs = 0; + size_t END_CERT_LEN; + + ca_file_tstr = Curl_convert_UTF8_to_tchar((char *)ca_file); + if(!ca_file_tstr) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: invalid path name for CA file '%s': %s", + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + + /* + * Read the CA file completely into memory before parsing it. This + * optimizes for the common case where the CA file will be relatively + * small ( < 1 MiB ). + */ + ca_file_handle = CreateFile(ca_file_tstr, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(ca_file_handle == INVALID_HANDLE_VALUE) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to open CA file '%s': %s", + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + + if(!GetFileSizeEx(ca_file_handle, &file_size)) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to determine size of CA file '%s': %s", + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + + if(file_size.QuadPart > MAX_CAFILE_SIZE) { + failf(data, + "schannel: CA file exceeds max size of %u bytes", + MAX_CAFILE_SIZE); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + + ca_file_bufsize = (size_t)file_size.QuadPart; + ca_file_buffer = (char *)malloc(ca_file_bufsize + 1); + if(!ca_file_buffer) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + + result = CURLE_OK; + while(total_bytes_read < ca_file_bufsize) { + DWORD bytes_to_read = (DWORD)(ca_file_bufsize - total_bytes_read); + DWORD bytes_read = 0; + + if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read, + bytes_to_read, &bytes_read, NULL)) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to read from CA file '%s': %s", + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } + if(bytes_read == 0) { + /* Premature EOF -- adjust the bufsize to the new value */ + ca_file_bufsize = total_bytes_read; + } + else { + total_bytes_read += bytes_read; + } + } + + /* Null terminate the buffer */ + ca_file_buffer[ca_file_bufsize] = '\0'; + + if(result != CURLE_OK) { + goto cleanup; + } + + END_CERT_LEN = strlen(END_CERT); + + more_certs = 1; + current_ca_file_ptr = ca_file_buffer; + while(more_certs && *current_ca_file_ptr != '\0') { + char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT); + if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[strlen(BEGIN_CERT)])) { + more_certs = 0; + } + else { + char *end_cert_ptr = strstr(begin_cert_ptr, END_CERT); + if(!end_cert_ptr) { + failf(data, + "schannel: CA file '%s' is not correctly formatted", + ca_file); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + CERT_BLOB cert_blob; + CERT_CONTEXT *cert_context = NULL; + BOOL add_cert_result = FALSE; + DWORD actual_content_type = 0; + DWORD cert_size = (DWORD) + ((end_cert_ptr + END_CERT_LEN) - begin_cert_ptr); + + cert_blob.pbData = (BYTE *)begin_cert_ptr; + cert_blob.cbData = cert_size; + if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, + &cert_blob, + CERT_QUERY_CONTENT_FLAG_CERT, + CERT_QUERY_FORMAT_FLAG_ALL, + 0, + NULL, + &actual_content_type, + NULL, + NULL, + NULL, + (const void **)&cert_context)) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to extract certificate from CA file " + "'%s': %s", + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + current_ca_file_ptr = begin_cert_ptr + cert_size; + + /* Sanity check that the cert_context object is the right type */ + if(CERT_QUERY_CONTENT_CERT != actual_content_type) { + failf(data, + "schannel: unexpected content type '%d' when extracting " + "certificate from CA file '%s'", + actual_content_type, ca_file); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + add_cert_result = + CertAddCertificateContextToStore(trust_store, + cert_context, + CERT_STORE_ADD_ALWAYS, + NULL); + CertFreeCertificateContext(cert_context); + if(!add_cert_result) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to add certificate from CA file '%s' " + "to certificate store: %s", + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + more_certs = 0; + } + else { + num_certs++; + } + } + } + } + } + } + + if(result == CURLE_OK) { + if(!num_certs) { + infof(data, + "schannel: did not add any certificates from CA file '%s'\n", + ca_file); + } + else { + infof(data, + "schannel: added %d certificate(s) from CA file '%s'\n", + num_certs, ca_file); + } + } + +cleanup: + if(ca_file_handle != INVALID_HANDLE_VALUE) { + CloseHandle(ca_file_handle); + } + Curl_safefree(ca_file_buffer); + Curl_unicodefree(ca_file_tstr); + + return result; +} + +static CURLcode verify_host(struct Curl_easy *data, + CERT_CONTEXT *pCertContextServer, + const char * const conn_hostname) +{ + CURLcode result = CURLE_PEER_FAILED_VERIFICATION; + TCHAR *cert_hostname_buff = NULL; + size_t cert_hostname_buff_index = 0; + DWORD len = 0; + DWORD actual_len = 0; + + /* CertGetNameString will provide the 8-bit character string without + * any decoding */ + DWORD name_flags = CERT_NAME_DISABLE_IE4_UTF8_FLAG; + +#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG + name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG; +#endif + + /* Determine the size of the string needed for the cert hostname */ + len = CertGetNameString(pCertContextServer, + CERT_NAME_DNS_TYPE, + name_flags, + NULL, + NULL, + 0); + if(len == 0) { + failf(data, + "schannel: CertGetNameString() returned no " + "certificate name information"); + result = CURLE_PEER_FAILED_VERIFICATION; + goto cleanup; + } + + /* CertGetNameString guarantees that the returned name will not contain + * embedded null bytes. This appears to be undocumented behavior. + */ + cert_hostname_buff = (LPTSTR)malloc(len * sizeof(TCHAR)); + if(!cert_hostname_buff) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + actual_len = CertGetNameString(pCertContextServer, + CERT_NAME_DNS_TYPE, + name_flags, + NULL, + (LPTSTR) cert_hostname_buff, + len); + + /* Sanity check */ + if(actual_len != len) { + failf(data, + "schannel: CertGetNameString() returned certificate " + "name information of unexpected size"); + result = CURLE_PEER_FAILED_VERIFICATION; + goto cleanup; + } + + /* If HAVE_CERT_NAME_SEARCH_ALL_NAMES is available, the output + * will contain all DNS names, where each name is null-terminated + * and the last DNS name is double null-terminated. Due to this + * encoding, use the length of the buffer to iterate over all names. + */ + result = CURLE_PEER_FAILED_VERIFICATION; + while(cert_hostname_buff_index < len && + cert_hostname_buff[cert_hostname_buff_index] != TEXT('\0') && + result == CURLE_PEER_FAILED_VERIFICATION) { + + char *cert_hostname; + + /* Comparing the cert name and the connection hostname encoded as UTF-8 + * is acceptable since both values are assumed to use ASCII + * (or some equivalent) encoding + */ + cert_hostname = Curl_convert_tchar_to_UTF8( + &cert_hostname_buff[cert_hostname_buff_index]); + if(!cert_hostname) { + result = CURLE_OUT_OF_MEMORY; + } + else { + int match_result; + + match_result = Curl_cert_hostcheck(cert_hostname, conn_hostname); + if(match_result == CURL_HOST_MATCH) { + infof(data, + "schannel: connection hostname (%s) validated " + "against certificate name (%s)\n", + conn_hostname, cert_hostname); + result = CURLE_OK; + } + else { + size_t cert_hostname_len; + + infof(data, + "schannel: connection hostname (%s) did not match " + "against certificate name (%s)\n", + conn_hostname, cert_hostname); + + cert_hostname_len = _tcslen( + &cert_hostname_buff[cert_hostname_buff_index]); + + /* Move on to next cert name */ + cert_hostname_buff_index += cert_hostname_len + 1; + + result = CURLE_PEER_FAILED_VERIFICATION; + } + Curl_unicodefree(cert_hostname); + } + } + + if(result == CURLE_PEER_FAILED_VERIFICATION) { + failf(data, + "schannel: CertGetNameString() failed to match " + "connection hostname (%s) against server certificate names", + conn_hostname); + } + else if(result != CURLE_OK) + failf(data, "schannel: server certificate name verification failed"); + +cleanup: + Curl_unicodefree(cert_hostname_buff); + + return result; +} + +CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) +{ + SECURITY_STATUS sspi_status; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CURLcode result = CURLE_OK; + CERT_CONTEXT *pCertContextServer = NULL; + const CERT_CHAIN_CONTEXT *pChainContext = NULL; + HCERTCHAINENGINE cert_chain_engine = NULL; + HCERTSTORE trust_store = NULL; + const char * const conn_hostname = SSL_IS_PROXY() ? + conn->http_proxy.host.name : + conn->host.name; + + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); + + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: Failed to read remote certificate context: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + result = CURLE_PEER_FAILED_VERIFICATION; + } + + if(result == CURLE_OK && SSL_CONN_CONFIG(CAfile) && + BACKEND->use_manual_cred_validation) { + /* + * Create a chain engine that uses the certificates in the CA file as + * trusted certificates. This is only supported on Windows 7+. + */ + + if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) { + failf(data, "schannel: this version of Windows is too old to support " + "certificate verification via CA bundle file."); + result = CURLE_SSL_CACERT_BADFILE; + } + else { + /* Open the certificate store */ + trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY, + 0, + (HCRYPTPROV)NULL, + CERT_STORE_CREATE_NEW_FLAG, + NULL); + if(!trust_store) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: failed to create certificate store: %s", + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + } + else { + result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile), + conn); + } + } + + if(result == CURLE_OK) { + CERT_CHAIN_ENGINE_CONFIG_WIN7 engine_config; + BOOL create_engine_result; + + memset(&engine_config, 0, sizeof(engine_config)); + engine_config.cbSize = sizeof(engine_config); + engine_config.hExclusiveRoot = trust_store; + + /* CertCreateCertificateChainEngine will check the expected size of the + * CERT_CHAIN_ENGINE_CONFIG structure and fail if the specified size + * does not match the expected size. When this occurs, it indicates that + * CAINFO is not supported on the version of Windows in use. + */ + create_engine_result = + CertCreateCertificateChainEngine( + (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine); + if(!create_engine_result) { + char buffer[STRERROR_LEN]; + failf(data, + "schannel: failed to create certificate chain engine: %s", + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; + } + } + } + + if(result == CURLE_OK) { + CERT_CHAIN_PARA ChainPara; + + memset(&ChainPara, 0, sizeof(ChainPara)); + ChainPara.cbSize = sizeof(ChainPara); + + if(!CertGetCertificateChain(cert_chain_engine, + pCertContextServer, + NULL, + pCertContextServer->hCertStore, + &ChainPara, + (data->set.ssl.no_revoke ? 0 : + CERT_CHAIN_REVOCATION_CHECK_CHAIN), + NULL, + &pChainContext)) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: CertGetCertificateChain failed: %s", + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); + pChainContext = NULL; + result = CURLE_PEER_FAILED_VERIFICATION; + } + + if(result == CURLE_OK) { + CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0]; + DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED); + dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; + if(dwTrustErrorMask) { + if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_REVOKED"); + else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_PARTIAL_CHAIN"); + else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_UNTRUSTED_ROOT"); + else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_IS_NOT_TIME_VALID"); + else if(dwTrustErrorMask & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) + failf(data, "schannel: CertGetCertificateChain trust error" + " CERT_TRUST_REVOCATION_STATUS_UNKNOWN"); + else + failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x", + dwTrustErrorMask); + result = CURLE_PEER_FAILED_VERIFICATION; + } + } + } + + if(result == CURLE_OK) { + if(SSL_CONN_CONFIG(verifyhost)) { + result = verify_host(conn->data, pCertContextServer, conn_hostname); + } + } + + if(cert_chain_engine) { + CertFreeCertificateChainEngine(cert_chain_engine); + } + + if(trust_store) { + CertCloseStore(trust_store, 0); + } + + if(pChainContext) + CertFreeCertificateChain(pChainContext); + + if(pCertContextServer) + CertFreeCertificateContext(pCertContextServer); + + return result; +} + +#endif /* HAS_MANUAL_VERIFY_API */ +#endif /* USE_SCHANNEL */ diff --git a/libcurl/lib/vtls/sectransp.c b/libcurl/lib/vtls/sectransp.c new file mode 100644 index 0000000..3fb125a --- /dev/null +++ b/libcurl/lib/vtls/sectransp.c @@ -0,0 +1,3277 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2017, Nick Zitzmann, . + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all iOS and macOS SecureTransport-specific code for the + * TLS/SSL layer. No code but vtls.c should ever call or use these functions. + */ + +#include "curl_setup.h" + +#include "urldata.h" /* for the Curl_easy definition */ +#include "curl_base64.h" +#include "strtok.h" +#include "multiif.h" + +#ifdef USE_SECTRANSP + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtautological-pointer-compare" +#endif /* __clang__ */ + +#include + +#include +/* For some reason, when building for iOS, the omnibus header above does + * not include SecureTransport.h as of iOS SDK 5.1. */ +#include +#include +#include + +/* The Security framework has changed greatly between iOS and different macOS + versions, and we will try to support as many of them as we can (back to + Leopard and iOS 5) by using macros and weak-linking. + + In general, you want to build this using the most recent OS SDK, since some + features require curl to be built against the latest SDK. TLS 1.1 and 1.2 + support, for instance, require the macOS 10.8 SDK or later. TLS 1.3 + requires the macOS 10.13 or iOS 11 SDK or later. */ +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 +#error "The Secure Transport back-end requires Leopard or later." +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ + +#define CURL_BUILD_IOS 0 +#define CURL_BUILD_IOS_7 0 +#define CURL_BUILD_IOS_9 0 +#define CURL_BUILD_IOS_11 0 +#define CURL_BUILD_MAC 1 +/* This is the maximum API level we are allowed to use when building: */ +#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 +#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 +#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 +#define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 +#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +/* These macros mean "the following code is present to allow runtime backward + compatibility with at least this cat or earlier": + (You set this at build-time using the compiler command line option + "-mmacos-version-min.") */ +#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050 +#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060 +#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 +#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 +#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090 + +#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE +#define CURL_BUILD_IOS 1 +#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +#define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 +#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 +#define CURL_BUILD_MAC 0 +#define CURL_BUILD_MAC_10_5 0 +#define CURL_BUILD_MAC_10_6 0 +#define CURL_BUILD_MAC_10_7 0 +#define CURL_BUILD_MAC_10_8 0 +#define CURL_BUILD_MAC_10_9 0 +#define CURL_BUILD_MAC_10_11 0 +#define CURL_BUILD_MAC_10_13 0 +#define CURL_SUPPORT_MAC_10_5 0 +#define CURL_SUPPORT_MAC_10_6 0 +#define CURL_SUPPORT_MAC_10_7 0 +#define CURL_SUPPORT_MAC_10_8 0 +#define CURL_SUPPORT_MAC_10_9 0 + +#else +#error "The Secure Transport back-end requires iOS or macOS." +#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ + +#if CURL_BUILD_MAC +#include +#endif /* CURL_BUILD_MAC */ + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "connect.h" +#include "select.h" +#include "vtls.h" +#include "sectransp.h" +#include "curl_printf.h" +#include "strdup.h" + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* From MacTypes.h (which we can't include because it isn't present in iOS: */ +#define ioErr -36 +#define paramErr -50 + +struct ssl_backend_data { + SSLContextRef ssl_ctx; + curl_socket_t ssl_sockfd; + bool ssl_direction; /* true if writing, false if reading */ + size_t ssl_write_buffered_length; +}; + +#define BACKEND connssl->backend + +/* pinned public key support tests */ + +/* version 1 supports macOS 10.12+ and iOS 10+ */ +#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ + (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) +#define SECTRANSP_PINNEDPUBKEY_V1 1 +#endif + +/* version 2 supports MacOSX 10.7+ */ +#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) +#define SECTRANSP_PINNEDPUBKEY_V2 1 +#endif + +#if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2) +/* this backend supports CURLOPT_PINNEDPUBLICKEY */ +#define SECTRANSP_PINNEDPUBKEY 1 +#endif /* SECTRANSP_PINNEDPUBKEY */ + +#ifdef SECTRANSP_PINNEDPUBKEY +/* both new and old APIs return rsa keys missing the spki header (not DER) */ +static const unsigned char rsa4096SpkiHeader[] = { + 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00}; + +static const unsigned char rsa2048SpkiHeader[] = { + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; +#ifdef SECTRANSP_PINNEDPUBKEY_V1 +/* the *new* version doesn't return DER encoded ecdsa certs like the old... */ +static const unsigned char ecDsaSecp256r1SpkiHeader[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00}; + +static const unsigned char ecDsaSecp384r1SpkiHeader[] = { + 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, + 0x00, 0x22, 0x03, 0x62, 0x00}; +#endif /* SECTRANSP_PINNEDPUBKEY_V1 */ +#endif /* SECTRANSP_PINNEDPUBKEY */ + +/* The following two functions were ripped from Apple sample code, + * with some modifications: */ +static OSStatus SocketRead(SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesToGo = *dataLength; + size_t initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = BACKEND->ssl_sockfd; + OSStatus rtn = noErr; + size_t bytesRead; + ssize_t rrtn; + int theErr; + + *dataLength = 0; + + for(;;) { + bytesRead = 0; + rrtn = read(sock, currData, bytesToGo); + if(rrtn <= 0) { + /* this is guesswork... */ + theErr = errno; + if(rrtn == 0) { /* EOF = server hung up */ + /* the framework will turn this into errSSLClosedNoNotify */ + rtn = errSSLClosedGraceful; + } + else /* do the switch */ + switch(theErr) { + case ENOENT: + /* connection closed */ + rtn = errSSLClosedGraceful; + break; + case ECONNRESET: + rtn = errSSLClosedAbort; + break; + case EAGAIN: + rtn = errSSLWouldBlock; + BACKEND->ssl_direction = false; + break; + default: + rtn = ioErr; + break; + } + break; + } + else { + bytesRead = rrtn; + } + bytesToGo -= bytesRead; + currData += bytesRead; + + if(bytesToGo == 0) { + /* filled buffer with incoming data, done */ + break; + } + } + *dataLength = initLen - bytesToGo; + + return rtn; +} + +static OSStatus SocketWrite(SSLConnectionRef connection, + const void *data, + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesSent = 0; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = BACKEND->ssl_sockfd; + ssize_t length; + size_t dataLen = *dataLength; + const UInt8 *dataPtr = (UInt8 *)data; + OSStatus ortn; + int theErr; + + *dataLength = 0; + + do { + length = write(sock, + (char *)dataPtr + bytesSent, + dataLen - bytesSent); + } while((length > 0) && + ( (bytesSent += length) < dataLen) ); + + if(length <= 0) { + theErr = errno; + if(theErr == EAGAIN) { + ortn = errSSLWouldBlock; + BACKEND->ssl_direction = true; + } + else { + ortn = ioErr; + } + } + else { + ortn = noErr; + } + *dataLength = bytesSent; + return ortn; +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { + /* SSL version 3.0 */ + case SSL_RSA_WITH_NULL_MD5: + return "SSL_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "SSL_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "SSL_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "SSL_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_SHA: + return "SSL_RSA_WITH_IDEA_CBC_SHA"; + break; + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_RSA_WITH_DES_CBC_SHA: + return "SSL_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_DES_CBC_SHA: + return "SSL_DH_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_DES_CBC_SHA: + return "SSL_DH_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; + break; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "SSL_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; + break; + case SSL_DH_anon_WITH_DES_CBC_SHA: + return "SSL_DH_anon_WITH_DES_CBC_SHA"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; + break; + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; + break; + /* TLS 1.0 with AES (RFC 3268) + (Apparently these are used in SSLv3 implementations as well.) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; + /* SSL version 2.0 */ + case SSL_RSA_WITH_RC2_CBC_MD5: + return "SSL_RSA_WITH_RC2_CBC_MD5"; + break; + case SSL_RSA_WITH_IDEA_CBC_MD5: + return "SSL_RSA_WITH_IDEA_CBC_MD5"; + break; + case SSL_RSA_WITH_DES_CBC_MD5: + return "SSL_RSA_WITH_DES_CBC_MD5"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_MD5: + return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; + break; + } + return "SSL_NULL_WITH_NULL_NULL"; +} + +CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { + /* TLS 1.0 with AES (RFC 3268) */ + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + break; +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* TLS 1.0 with ECDSA (RFC 4492) */ + case TLS_ECDH_ECDSA_WITH_NULL_SHA: + return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_NULL_SHA: + return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_NULL_SHA: + return "TLS_ECDH_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_NULL_SHA: + return "TLS_ECDHE_RSA_WITH_NULL_SHA"; + break; + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; + break; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_NULL_SHA: + return "TLS_ECDH_anon_WITH_NULL_SHA"; + break; + case TLS_ECDH_anon_WITH_RC4_128_SHA: + return "TLS_ECDH_anon_WITH_RC4_128_SHA"; + break; + case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; + break; + case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* TLS 1.2 (RFC 5246) */ + case TLS_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case TLS_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case TLS_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case TLS_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_WITH_NULL_SHA256: + return "TLS_RSA_WITH_NULL_SHA256"; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_CBC_SHA256: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; + break; + /* TLS 1.2 with AES GCM (RFC 5288) */ + case TLS_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DH_anon_WITH_AES_128_GCM_SHA256: + return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: + return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; + break; + /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; + break; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; + break; + case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: + return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; + break; +#else + case SSL_RSA_WITH_NULL_MD5: + return "TLS_RSA_WITH_NULL_MD5"; + break; + case SSL_RSA_WITH_NULL_SHA: + return "TLS_RSA_WITH_NULL_SHA"; + break; + case SSL_RSA_WITH_RC4_128_MD5: + return "TLS_RSA_WITH_RC4_128_MD5"; + break; + case SSL_RSA_WITH_RC4_128_SHA: + return "TLS_RSA_WITH_RC4_128_SHA"; + break; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + break; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "TLS_DH_anon_WITH_RC4_128_MD5"; + break; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + break; +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* TLS PSK (RFC 4279): */ + case TLS_PSK_WITH_RC4_128_SHA: + return "TLS_PSK_WITH_RC4_128_SHA"; + break; + case TLS_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA: + return "TLS_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA: + return "TLS_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_RC4_128_SHA: + return "TLS_DHE_PSK_WITH_RC4_128_SHA"; + break; + case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_RC4_128_SHA: + return "TLS_RSA_PSK_WITH_RC4_128_SHA"; + break; + case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; + break; + /* More TLS PSK (RFC 4785): */ + case TLS_PSK_WITH_NULL_SHA: + return "TLS_PSK_WITH_NULL_SHA"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA: + return "TLS_DHE_PSK_WITH_NULL_SHA"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA: + return "TLS_RSA_PSK_WITH_NULL_SHA"; + break; + /* Even more TLS PSK (RFC 5487): */ + case TLS_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_PSK_WITH_NULL_SHA256: + return "TLS_PSK_WITH_NULL_SHA256"; + break; + case TLS_PSK_WITH_NULL_SHA384: + return "TLS_PSK_WITH_NULL_SHA384"; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA256: + return "TLS_DHE_PSK_WITH_NULL_SHA256"; + break; + case TLS_DHE_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; + case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; + break; + case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA256: + return "TLS_RSA_PSK_WITH_NULL_SHA256"; + break; + case TLS_RSA_PSK_WITH_NULL_SHA384: + return "TLS_RSA_PSK_WITH_NULL_SHA384"; + break; +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */ + case TLS_AES_128_GCM_SHA256: + return "TLS_AES_128_GCM_SHA256"; + break; + case TLS_AES_256_GCM_SHA384: + return "TLS_AES_256_GCM_SHA384"; + break; + case TLS_CHACHA20_POLY1305_SHA256: + return "TLS_CHACHA20_POLY1305_SHA256"; + break; + case TLS_AES_128_CCM_SHA256: + return "TLS_AES_128_CCM_SHA256"; + break; + case TLS_AES_128_CCM_8_SHA256: + return "TLS_AES_128_CCM_8_SHA256"; + break; + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; + break; + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; + break; +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + } + return "TLS_NULL_WITH_NULL_NULL"; +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +#if CURL_BUILD_MAC +CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) +{ + int mib[2]; + char *os_version; + size_t os_version_len; + char *os_version_major, *os_version_minor; + char *tok_buf; + + /* Get the Darwin kernel version from the kernel using sysctl(): */ + mib[0] = CTL_KERN; + mib[1] = KERN_OSRELEASE; + if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1) + return; + os_version = malloc(os_version_len*sizeof(char)); + if(!os_version) + return; + if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) { + free(os_version); + return; + } + + /* Parse the version: */ + os_version_major = strtok_r(os_version, ".", &tok_buf); + os_version_minor = strtok_r(NULL, ".", &tok_buf); + *major = atoi(os_version_major); + *minor = atoi(os_version_minor); + free(os_version); +} +#endif /* CURL_BUILD_MAC */ + +/* Apple provides a myriad of ways of getting information about a certificate + into a string. Some aren't available under iOS or newer cats. So here's + a unified function for getting a string describing the certificate that + ought to work in all cats starting with Leopard. */ +CF_INLINE CFStringRef getsubject(SecCertificateRef cert) +{ + CFStringRef server_cert_summary = CFSTR("(null)"); + +#if CURL_BUILD_IOS + /* iOS: There's only one way to do this. */ + server_cert_summary = SecCertificateCopySubjectSummary(cert); +#else +#if CURL_BUILD_MAC_10_7 + /* Lion & later: Get the long description if we can. */ + if(SecCertificateCopyLongDescription != NULL) + server_cert_summary = + SecCertificateCopyLongDescription(NULL, cert, NULL); + else +#endif /* CURL_BUILD_MAC_10_7 */ +#if CURL_BUILD_MAC_10_6 + /* Snow Leopard: Get the certificate summary. */ + if(SecCertificateCopySubjectSummary != NULL) + server_cert_summary = SecCertificateCopySubjectSummary(cert); + else +#endif /* CURL_BUILD_MAC_10_6 */ + /* Leopard is as far back as we go... */ + (void)SecCertificateCopyCommonName(cert, &server_cert_summary); +#endif /* CURL_BUILD_IOS */ + return server_cert_summary; +} + +static CURLcode CopyCertSubject(struct Curl_easy *data, + SecCertificateRef cert, char **certp) +{ + CFStringRef c = getsubject(cert); + CURLcode result = CURLE_OK; + const char *direct; + char *cbuf = NULL; + *certp = NULL; + + if(!c) { + failf(data, "SSL: invalid CA certificate subject"); + return CURLE_PEER_FAILED_VERIFICATION; + } + + /* If the subject is already available as UTF-8 encoded (ie 'direct') then + use that, else convert it. */ + direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8); + if(direct) { + *certp = strdup(direct); + if(!*certp) { + failf(data, "SSL: out of memory"); + result = CURLE_OUT_OF_MEMORY; + } + } + else { + size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1; + cbuf = calloc(cbuf_size, 1); + if(cbuf) { + if(!CFStringGetCString(c, cbuf, cbuf_size, + kCFStringEncodingUTF8)) { + failf(data, "SSL: invalid CA certificate subject"); + result = CURLE_PEER_FAILED_VERIFICATION; + } + else + /* pass back the buffer */ + *certp = cbuf; + } + else { + failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size); + result = CURLE_OUT_OF_MEMORY; + } + } + if(result) + free(cbuf); + CFRelease(c); + return result; +} + +#if CURL_SUPPORT_MAC_10_6 +/* The SecKeychainSearch API was deprecated in Lion, and using it will raise + deprecation warnings, so let's not compile this unless it's necessary: */ +static OSStatus CopyIdentityWithLabelOldSchool(char *label, + SecIdentityRef *out_c_a_k) +{ + OSStatus status = errSecItemNotFound; + SecKeychainAttributeList attr_list; + SecKeychainAttribute attr; + SecKeychainSearchRef search = NULL; + SecCertificateRef cert = NULL; + + /* Set up the attribute list: */ + attr_list.count = 1L; + attr_list.attr = &attr; + + /* Set up our lone search criterion: */ + attr.tag = kSecLabelItemAttr; + attr.data = label; + attr.length = (UInt32)strlen(label); + + /* Start searching: */ + status = SecKeychainSearchCreateFromAttributes(NULL, + kSecCertificateItemClass, + &attr_list, + &search); + if(status == noErr) { + status = SecKeychainSearchCopyNext(search, + (SecKeychainItemRef *)&cert); + if(status == noErr && cert) { + /* If we found a certificate, does it have a private key? */ + status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k); + CFRelease(cert); + } + } + + if(search) + CFRelease(search); + return status; +} +#endif /* CURL_SUPPORT_MAC_10_6 */ + +static OSStatus CopyIdentityWithLabel(char *label, + SecIdentityRef *out_cert_and_key) +{ + OSStatus status = errSecItemNotFound; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS + CFArrayRef keys_list; + CFIndex keys_list_count; + CFIndex i; + CFStringRef common_name; + + /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. + kSecClassIdentity was introduced in Lion. If both exist, let's use them + to find the certificate. */ + if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { + CFTypeRef keys[5]; + CFTypeRef values[5]; + CFDictionaryRef query_dict; + CFStringRef label_cf = CFStringCreateWithCString(NULL, label, + kCFStringEncodingUTF8); + + /* Set up our search criteria and expected results: */ + values[0] = kSecClassIdentity; /* we want a certificate and a key */ + keys[0] = kSecClass; + values[1] = kCFBooleanTrue; /* we want a reference */ + keys[1] = kSecReturnRef; + values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the + * label matching below worked correctly */ + keys[2] = kSecMatchLimit; + /* identity searches need a SecPolicyRef in order to work */ + values[3] = SecPolicyCreateSSL(false, NULL); + keys[3] = kSecMatchPolicy; + /* match the name of the certificate (doesn't work in macOS 10.12.1) */ + values[4] = label_cf; + keys[4] = kSecAttrLabel; + query_dict = CFDictionaryCreate(NULL, (const void **)keys, + (const void **)values, 5L, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease(values[3]); + + /* Do we have a match? */ + status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list); + + /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity, + * we need to find the correct identity ourselves */ + if(status == noErr) { + keys_list_count = CFArrayGetCount(keys_list); + *out_cert_and_key = NULL; + status = 1; + for(i = 0; idata; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + long max_supported_version_by_os; + + /* macOS 10.5-10.7 supported TLS 1.0 only. + macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2. + macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */ +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(__builtin_available(macOS 10.13, iOS 11.0, *)) { + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3; + } + else { + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; + } +#else + max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; +#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && + HAVE_BUILTIN_AVAILABLE == 1 */ + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = max_supported_version_by_os; + break; + } + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + SSLProtocol darwin_ver_min = kTLSProtocol1; + SSLProtocol darwin_ver_max = kTLSProtocol1; + CURLcode result = sectransp_version_from_curl(&darwin_ver_min, + ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = sectransp_version_from_curl(&darwin_ver_max, + ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min); + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max); + return result; + } + else { +#if CURL_SUPPORT_MAC_10_8 + long i = ssl_version; + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocolAll, + false); + for(; i <= (ssl_version_max >> 16); i++) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol11, + true); + break; + case CURL_SSLVERSION_TLSv1_2: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + failf(data, "Secure Transport: cannot set SSL protocol"); + return CURLE_SSL_CONNECT_ERROR; +} + + +static CURLcode sectransp_connect_step1(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif /* ENABLE_IPV6 */ + size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; + SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + OSStatus err = noErr; +#if CURL_BUILD_MAC + int darwinver_maj = 0, darwinver_min = 0; + + GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); +#endif /* CURL_BUILD_MAC */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) { /* use the newer API if available */ + if(BACKEND->ssl_ctx) + CFRelease(BACKEND->ssl_ctx); + BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); + if(!BACKEND->ssl_ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + } + else { + /* The old ST API does not exist under iOS, so don't compile it: */ +#if CURL_SUPPORT_MAC_10_8 + if(BACKEND->ssl_ctx) + (void)SSLDisposeContext(BACKEND->ssl_ctx); + err = SSLNewContext(false, &(BACKEND->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(BACKEND->ssl_ctx) + (void)SSLDisposeContext(BACKEND->ssl_ctx); + err = SSLNewContext(false, &(BACKEND->ssl_ctx)); + if(err != noErr) { + failf(data, "SSL: couldn't create a context: OSStatus %d", err); + return CURLE_OUT_OF_MEMORY; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + BACKEND->ssl_write_buffered_length = 0UL; /* reset buffered write length */ + + /* check to see if we've been told to use an explicit SSL/TLS version */ +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1); +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(__builtin_available(macOS 10.13, iOS 11.0, *)) { + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13); + } + else { + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); + } +#else + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12); +#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && + HAVE_BUILTIN_AVAILABLE == 1 */ + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3); + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol2); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2); + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocolAll, + false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol11, + true); + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) { + failf(data, "Your version of the OS does not support to set maximum" + " SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + failf(data, "Your version of the OS does not support TLSv1.1"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_2: + failf(data, "Your version of the OS does not support TLSv1.2"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(conn->bits.tls_enable_alpn) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { + CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, + &kCFTypeArrayCallBacks); + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID)); + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1)); + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + /* expects length prefixed preference ordered list of protocols in wire + * format + */ + err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr); + if(err != noErr) + infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n", + err); + CFRelease(alpnArr); + } + } +#endif + + if(SSL_SET_OPTION(key)) { + infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " + "Transport. The private key must be in the Keychain.\n"); + } + + if(ssl_cert) { + SecIdentityRef cert_and_key = NULL; + bool is_cert_file = is_file(ssl_cert); + + /* User wants to authenticate with a client cert. Look for it: + If we detect that this is a file on disk, then let's load it. + Otherwise, assume that the user wants to use an identity loaded + from the Keychain. */ + if(is_cert_file) { + if(!SSL_SET_OPTION(cert_type)) + infof(data, "WARNING: SSL: Certificate type not set, assuming " + "PKCS#12 format.\n"); + else if(strncmp(SSL_SET_OPTION(cert_type), "P12", + strlen(SSL_SET_OPTION(cert_type))) != 0) + infof(data, "WARNING: SSL: The Security framework only supports " + "loading identities that are in PKCS#12 format.\n"); + + err = CopyIdentityFromPKCS12File(ssl_cert, + SSL_SET_OPTION(key_passwd), &cert_and_key); + } + else + err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); + + if(err == noErr && cert_and_key) { + SecCertificateRef cert = NULL; + CFTypeRef certs_c[1]; + CFArrayRef certs; + + /* If we found one, print it out: */ + err = SecIdentityCopyCertificate(cert_and_key, &cert); + if(err == noErr) { + char *certp; + CURLcode result = CopyCertSubject(data, cert, &certp); + if(!result) { + infof(data, "Client certificate: %s\n", certp); + free(certp); + } + + CFRelease(cert); + if(result == CURLE_PEER_FAILED_VERIFICATION) + return CURLE_SSL_CERTPROBLEM; + if(result) + return result; + } + certs_c[0] = cert_and_key; + certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, + &kCFTypeArrayCallBacks); + err = SSLSetCertificate(BACKEND->ssl_ctx, certs); + if(certs) + CFRelease(certs); + if(err != noErr) { + failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err); + return CURLE_SSL_CERTPROBLEM; + } + CFRelease(cert_and_key); + } + else { + switch(err) { + case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ + failf(data, "SSL: Incorrect password for the certificate \"%s\" " + "and its private key.", ssl_cert); + break; + case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ + failf(data, "SSL: Couldn't make sense of the data in the " + "certificate \"%s\" and its private key.", + ssl_cert); + break; + case -25260: /* errSecPassphraseRequired */ + failf(data, "SSL The certificate \"%s\" requires a password.", + ssl_cert); + break; + case errSecItemNotFound: + failf(data, "SSL: Can't find the certificate \"%s\" and its private " + "key in the Keychain.", ssl_cert); + break; + default: + failf(data, "SSL: Can't load the certificate \"%s\" and its private " + "key: OSStatus %d", ssl_cert, err); + break; + } + return CURLE_SSL_CERTPROBLEM; + } + } + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* Snow Leopard introduced the SSLSetSessionOption() function, but due to + a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag + works, it doesn't work as expected under Snow Leopard, Lion or + Mountain Lion. + So we need to call SSLSetEnableCertVerify() on those older cats in order + to disable certificate validation if the user turned that off. + (SecureTransport will always validate the certificate chain by + default.) + Note: + Darwin 11.x.x is Lion (10.7) + Darwin 12.x.x is Mountain Lion (10.8) + Darwin 13.x.x is Mavericks (10.9) + Darwin 14.x.x is Yosemite (10.10) + Darwin 15.x.x is El Capitan (10.11) + */ +#if CURL_BUILD_MAC + if(SSLSetSessionOption != NULL && darwinver_maj >= 13) { +#else + if(SSLSetSessionOption != NULL) { +#endif /* CURL_BUILD_MAC */ + bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; + err = SSLSetSessionOption(BACKEND->ssl_ctx, + kSSLSessionOptionBreakOnServerAuth, + break_on_auth); + if(err != noErr) { + failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, + conn->ssl_config.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + err = SSLSetEnableCertVerify(BACKEND->ssl_ctx, + conn->ssl_config.verifypeer?true:false); + if(err != noErr) { + failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ + + if(ssl_cafile && verifypeer) { + bool is_cert_file = is_file(ssl_cafile); + + if(!is_cert_file) { + failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); + return CURLE_SSL_CACERT_BADFILE; + } + } + + /* Configure hostname check. SNI is used if available. + * Both hostname check and SNI require SSLSetPeerDomainName(). + * Also: the verifyhost setting influences SNI usage */ + if(conn->ssl_config.verifyhost) { + err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname, + strlen(hostname)); + + if(err != noErr) { + infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", + err); + } + + if((Curl_inet_pton(AF_INET, hostname, &addr)) + #ifdef ENABLE_IPV6 + || (Curl_inet_pton(AF_INET6, hostname, &addr)) + #endif + ) { + infof(data, "WARNING: using IP address, SNI is being disabled by " + "the OS.\n"); + } + } + else { + infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); + } + + /* Disable cipher suites that ST supports but are not safe. These ciphers + are unlikely to be used in any case since ST gives other ciphers a much + higher priority, but it's probably better that we not connect at all than + to give the user a false sense of security if the server only supports + insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ + err = SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", + err); + return CURLE_SSL_CIPHER; + } + all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!all_ciphers) { + failf(data, "SSL: Failed to allocate memory for all ciphers"); + return CURLE_OUT_OF_MEMORY; + } + allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!allowed_ciphers) { + Curl_safefree(all_ciphers); + failf(data, "SSL: Failed to allocate memory for allowed ciphers"); + return CURLE_OUT_OF_MEMORY; + } + err = SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers, + &all_ciphers_count); + if(err != noErr) { + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + return CURLE_SSL_CIPHER; + } + for(i = 0UL ; i < all_ciphers_count ; i++) { +#if CURL_BUILD_MAC + /* There's a known bug in early versions of Mountain Lion where ST's ECC + ciphers (cipher suite 0xC001 through 0xC032) simply do not work. + Work around the problem here by disabling those ciphers if we are + running in an affected version of OS X. */ + if(darwinver_maj == 12 && darwinver_min <= 3 && + all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { + continue; + } +#endif /* CURL_BUILD_MAC */ + switch(all_ciphers[i]) { + /* Disable NULL ciphersuites: */ + case SSL_NULL_WITH_NULL_NULL: + case SSL_RSA_WITH_NULL_MD5: + case SSL_RSA_WITH_NULL_SHA: + case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ + case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ + case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ + case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ + case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ + case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ + case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ + case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ + case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ + case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ + case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ + case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ + case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ + /* Disable anonymous ciphersuites: */ + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + case SSL_DH_anon_WITH_RC4_128_MD5: + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_anon_WITH_DES_CBC_SHA: + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ + case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ + case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ + case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ + case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ + case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ + case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ + case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ + case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ + /* Disable weak key ciphersuites: */ + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + case SSL_RSA_WITH_DES_CBC_SHA: + case SSL_DH_DSS_WITH_DES_CBC_SHA: + case SSL_DH_RSA_WITH_DES_CBC_SHA: + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + /* Disable IDEA: */ + case SSL_RSA_WITH_IDEA_CBC_SHA: + case SSL_RSA_WITH_IDEA_CBC_MD5: + /* Disable RC4: */ + case SSL_RSA_WITH_RC4_128_MD5: + case SSL_RSA_WITH_RC4_128_SHA: + case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ + case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/ + case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ + case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ + case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */ + case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */ + case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */ + break; + default: /* enable everything else */ + allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; + break; + } + } + err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers, + allowed_ciphers_count); + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CIPHER; + } + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* We want to enable 1/n-1 when using a CBC cipher unless the user + specifically doesn't want us doing that: */ + if(SSLSetSessionOption != NULL) { + SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord, + !data->set.ssl.enable_beast); + SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart, + data->set.ssl.falsestart); /* false start support */ + } +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + char *ssl_sessionid; + size_t ssl_sessionid_len; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, + &ssl_sessionid_len, sockindex)) { + /* we got a session id, use it! */ + err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + Curl_ssl_sessionid_unlock(conn); + if(err != noErr) { + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + /* If there isn't one, then let's make one up! This has to be done prior + to starting the handshake. */ + else { + CURLcode result; + ssl_sessionid = + aprintf("%s:%d:%d:%s:%hu", ssl_cafile, + verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); + ssl_sessionid_len = strlen(ssl_sessionid); + + err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len); + if(err != noErr) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, + sockindex); + Curl_ssl_sessionid_unlock(conn); + if(result) { + failf(data, "failed to store ssl session"); + return result; + } + } + } + + err = SSLSetIOFuncs(BACKEND->ssl_ctx, SocketRead, SocketWrite); + if(err != noErr) { + failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + /* pass the raw socket into the SSL layers */ + /* We need to store the FD in a constant memory address, because + * SSLSetConnection() will not copy that address. I've found that + * conn->sock[sockindex] may change on its own. */ + BACKEND->ssl_sockfd = sockfd; + err = SSLSetConnection(BACKEND->ssl_ctx, connssl); + if(err != noErr) { + failf(data, "SSL: SSLSetConnection() failed: %d", err); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + +static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) +{ + char *sep_start, *sep_end, *cert_start, *cert_end; + size_t i, j, err; + size_t len; + unsigned char *b64; + + /* Jump through the separators at the beginning of the certificate. */ + sep_start = strstr(in, "-----"); + if(sep_start == NULL) + return 0; + cert_start = strstr(sep_start + 1, "-----"); + if(cert_start == NULL) + return -1; + + cert_start += 5; + + /* Find separator after the end of the certificate. */ + cert_end = strstr(cert_start, "-----"); + if(cert_end == NULL) + return -1; + + sep_end = strstr(cert_end + 1, "-----"); + if(sep_end == NULL) + return -1; + sep_end += 5; + + len = cert_end - cert_start; + b64 = malloc(len + 1); + if(!b64) + return -1; + + /* Create base64 string without linefeeds. */ + for(i = 0, j = 0; i < len; i++) { + if(cert_start[i] != '\r' && cert_start[i] != '\n') + b64[j++] = cert_start[i]; + } + b64[j] = '\0'; + + err = Curl_base64_decode((const char *)b64, out, outlen); + free(b64); + if(err) { + free(*out); + return -1; + } + + return sep_end - in; +} + +static int read_cert(const char *file, unsigned char **out, size_t *outlen) +{ + int fd; + ssize_t n, len = 0, cap = 512; + unsigned char buf[512], *data; + + fd = open(file, 0); + if(fd < 0) + return -1; + + data = malloc(cap); + if(!data) { + close(fd); + return -1; + } + + for(;;) { + n = read(fd, buf, sizeof(buf)); + if(n < 0) { + close(fd); + free(data); + return -1; + } + else if(n == 0) { + close(fd); + break; + } + + if(len + n >= cap) { + cap *= 2; + data = Curl_saferealloc(data, cap); + if(!data) { + close(fd); + return -1; + } + } + + memcpy(data + len, buf, n); + len += n; + } + data[len] = '\0'; + + *out = data; + *outlen = len; + + return 0; +} + +static int append_cert_to_array(struct Curl_easy *data, + unsigned char *buf, size_t buflen, + CFMutableArrayRef array) +{ + CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); + char *certp; + CURLcode result; + if(!certdata) { + failf(data, "SSL: failed to allocate array for CA certificate"); + return CURLE_OUT_OF_MEMORY; + } + + SecCertificateRef cacert = + SecCertificateCreateWithData(kCFAllocatorDefault, certdata); + CFRelease(certdata); + if(!cacert) { + failf(data, "SSL: failed to create SecCertificate from CA certificate"); + return CURLE_SSL_CACERT_BADFILE; + } + + /* Check if cacert is valid. */ + result = CopyCertSubject(data, cacert, &certp); + switch(result) { + case CURLE_OK: + break; + case CURLE_PEER_FAILED_VERIFICATION: + return CURLE_SSL_CACERT_BADFILE; + case CURLE_OUT_OF_MEMORY: + default: + return result; + } + free(certp); + + CFArrayAppendValue(array, cacert); + CFRelease(cacert); + + return CURLE_OK; +} + +static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, + SSLContextRef ctx) +{ + int n = 0, rc; + long res; + unsigned char *certbuf, *der; + size_t buflen, derlen, offset = 0; + + if(read_cert(cafile, &certbuf, &buflen) < 0) { + failf(data, "SSL: failed to read or invalid CA certificate"); + return CURLE_SSL_CACERT_BADFILE; + } + + /* + * Certbuf now contains the contents of the certificate file, which can be + * - a single DER certificate, + * - a single PEM certificate or + * - a bunch of PEM certificates (certificate bundle). + * + * Go through certbuf, and convert any PEM certificate in it into DER + * format. + */ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + if(array == NULL) { + free(certbuf); + failf(data, "SSL: out of memory creating CA certificate array"); + return CURLE_OUT_OF_MEMORY; + } + + while(offset < buflen) { + n++; + + /* + * Check if the certificate is in PEM format, and convert it to DER. If + * this fails, we assume the certificate is in DER format. + */ + res = pem_to_der((const char *)certbuf + offset, &der, &derlen); + if(res < 0) { + free(certbuf); + CFRelease(array); + failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle", + n, offset); + return CURLE_SSL_CACERT_BADFILE; + } + offset += res; + + if(res == 0 && offset == 0) { + /* This is not a PEM file, probably a certificate in DER format. */ + rc = append_cert_to_array(data, certbuf, buflen, array); + free(certbuf); + if(rc != CURLE_OK) { + CFRelease(array); + return rc; + } + break; + } + else if(res == 0) { + /* No more certificates in the bundle. */ + free(certbuf); + break; + } + + rc = append_cert_to_array(data, der, derlen, array); + free(der); + if(rc != CURLE_OK) { + free(certbuf); + CFRelease(array); + return rc; + } + } + + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(trust == NULL) { + failf(data, "SSL: error getting certificate chain"); + CFRelease(array); + return CURLE_PEER_FAILED_VERIFICATION; + } + else if(ret != noErr) { + CFRelease(array); + failf(data, "SSLCopyPeerTrust() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + ret = SecTrustSetAnchorCertificates(trust, array); + if(ret != noErr) { + CFRelease(array); + CFRelease(trust); + failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + ret = SecTrustSetAnchorCertificatesOnly(trust, true); + if(ret != noErr) { + CFRelease(array); + CFRelease(trust); + failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + SecTrustResultType trust_eval = 0; + ret = SecTrustEvaluate(trust, &trust_eval); + CFRelease(array); + CFRelease(trust); + if(ret != noErr) { + failf(data, "SecTrustEvaluate() returned error %d", ret); + return CURLE_PEER_FAILED_VERIFICATION; + } + + switch(trust_eval) { + case kSecTrustResultUnspecified: + case kSecTrustResultProceed: + return CURLE_OK; + + case kSecTrustResultRecoverableTrustFailure: + case kSecTrustResultDeny: + default: + failf(data, "SSL: certificate verification failed (result: %d)", + trust_eval); + return CURLE_PEER_FAILED_VERIFICATION; + } +} + +#ifdef SECTRANSP_PINNEDPUBKEY +static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, + SSLContextRef ctx, + const char *pinnedpubkey) +{ /* Scratch */ + size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24; + unsigned char *pubkey = NULL, *realpubkey = NULL; + const unsigned char *spkiHeader = NULL; + CFDataRef publicKeyBits = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + + if(!ctx) + return result; + + do { + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(ret != noErr || trust == NULL) + break; + + SecKeyRef keyRef = SecTrustCopyPublicKey(trust); + CFRelease(trust); + if(keyRef == NULL) + break; + +#ifdef SECTRANSP_PINNEDPUBKEY_V1 + + publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); + CFRelease(keyRef); + if(publicKeyBits == NULL) + break; + +#elif SECTRANSP_PINNEDPUBKEY_V2 + + OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, + &publicKeyBits); + CFRelease(keyRef); + if(success != errSecSuccess || publicKeyBits == NULL) + break; + +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ + + pubkeylen = CFDataGetLength(publicKeyBits); + pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits); + + switch(pubkeylen) { + case 526: + /* 4096 bit RSA pubkeylen == 526 */ + spkiHeader = rsa4096SpkiHeader; + break; + case 270: + /* 2048 bit RSA pubkeylen == 270 */ + spkiHeader = rsa2048SpkiHeader; + break; +#ifdef SECTRANSP_PINNEDPUBKEY_V1 + case 65: + /* ecDSA secp256r1 pubkeylen == 65 */ + spkiHeader = ecDsaSecp256r1SpkiHeader; + spkiHeaderLength = 26; + break; + case 97: + /* ecDSA secp384r1 pubkeylen == 97 */ + spkiHeader = ecDsaSecp384r1SpkiHeader; + spkiHeaderLength = 23; + break; + default: + infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); +#elif SECTRANSP_PINNEDPUBKEY_V2 + default: + /* ecDSA secp256r1 pubkeylen == 91 header already included? + * ecDSA secp384r1 header already included too + * we assume rest of algorithms do same, so do nothing + */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, + pubkeylen); +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ + continue; /* break from loop */ + } + + realpubkeylen = pubkeylen + spkiHeaderLength; + realpubkey = malloc(realpubkeylen); + if(!realpubkey) + break; + + memcpy(realpubkey, spkiHeader, spkiHeaderLength); + memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen); + + result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey, + realpubkeylen); + + } while(0); + + Curl_safefree(realpubkey); + if(publicKeyBits != NULL) + CFRelease(publicKeyBits); + + return result; +} +#endif /* SECTRANSP_PINNEDPUBKEY */ + +static CURLcode +sectransp_connect_step2(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + OSStatus err; + SSLCipherSuite cipher; + SSLProtocol protocol = 0; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + + DEBUGASSERT(ssl_connect_2 == connssl->connecting_state + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); + + /* Here goes nothing: */ + err = SSLHandshake(BACKEND->ssl_ctx); + + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: /* they're not done with us yet */ + connssl->connecting_state = BACKEND->ssl_direction ? + ssl_connect_2_writing : ssl_connect_2_reading; + return CURLE_OK; + + /* The below is errSSLServerAuthCompleted; it's not defined in + Leopard's headers */ + case -9841: + if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { + CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data, + BACKEND->ssl_ctx); + if(result) + return result; + } + /* the documentation says we need to call SSLHandshake() again */ + return sectransp_connect_step2(conn, sockindex); + + /* Problem with encrypt / decrypt */ + case errSSLPeerDecodeError: + failf(data, "Decode failed"); + break; + case errSSLDecryptionFail: + case errSSLPeerDecryptionFail: + failf(data, "Decryption failed"); + break; + case errSSLPeerDecryptError: + failf(data, "A decryption error occurred"); + break; + case errSSLBadCipherSuite: + failf(data, "A bad SSL cipher suite was encountered"); + break; + case errSSLCrypto: + failf(data, "An underlying cryptographic error was encountered"); + break; +#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 + case errSSLWeakPeerEphemeralDHKey: + failf(data, "Indicates a weak ephemeral Diffie-Hellman key"); + break; +#endif + + /* Problem with the message record validation */ + case errSSLBadRecordMac: + case errSSLPeerBadRecordMac: + failf(data, "A record with a bad message authentication code (MAC) " + "was encountered"); + break; + case errSSLRecordOverflow: + case errSSLPeerRecordOverflow: + failf(data, "A record overflow occurred"); + break; + + /* Problem with zlib decompression */ + case errSSLPeerDecompressFail: + failf(data, "Decompression failed"); + break; + + /* Problem with access */ + case errSSLPeerAccessDenied: + failf(data, "Access was denied"); + break; + case errSSLPeerInsufficientSecurity: + failf(data, "There is insufficient security for this operation"); + break; + + /* These are all certificate problems with the server: */ + case errSSLXCertChainInvalid: + failf(data, "SSL certificate problem: Invalid certificate chain"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLUnknownRootCert: + failf(data, "SSL certificate problem: Untrusted root certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLNoRootCert: + failf(data, "SSL certificate problem: No root certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLCertNotYetValid: + failf(data, "SSL certificate problem: The certificate chain had a " + "certificate that is not yet valid"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLCertExpired: + case errSSLPeerCertExpired: + failf(data, "SSL certificate problem: Certificate chain had an " + "expired certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLBadCert: + case errSSLPeerBadCert: + failf(data, "SSL certificate problem: Couldn't understand the server " + "certificate format"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerUnsupportedCert: + failf(data, "SSL certificate problem: An unsupported certificate " + "format was encountered"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerCertRevoked: + failf(data, "SSL certificate problem: The certificate was revoked"); + return CURLE_PEER_FAILED_VERIFICATION; + case errSSLPeerCertUnknown: + failf(data, "SSL certificate problem: The certificate is unknown"); + return CURLE_PEER_FAILED_VERIFICATION; + + /* These are all certificate problems with the client: */ + case errSecAuthFailed: + failf(data, "SSL authentication failed"); + break; + case errSSLPeerHandshakeFail: + failf(data, "SSL peer handshake failed, the server most likely " + "requires a client certificate to connect"); + break; + case errSSLPeerUnknownCA: + failf(data, "SSL server rejected the client certificate due to " + "the certificate being signed by an unknown certificate " + "authority"); + break; + + /* This error is raised if the server's cert didn't match the server's + host name: */ + case errSSLHostNameMismatch: + failf(data, "SSL certificate peer verification failed, the " + "certificate did not match \"%s\"\n", conn->host.dispname); + return CURLE_PEER_FAILED_VERIFICATION; + + /* Problem with SSL / TLS negotiation */ + case errSSLNegotiation: + failf(data, "Could not negotiate an SSL cipher suite with the server"); + break; + case errSSLBadConfiguration: + failf(data, "A configuration error occurred"); + break; + case errSSLProtocol: + failf(data, "SSL protocol error"); + break; + case errSSLPeerProtocolVersion: + failf(data, "A bad protocol version was encountered"); + break; + case errSSLPeerNoRenegotiation: + failf(data, "No renegotiation is allowed"); + break; + + /* Generic handshake errors: */ + case errSSLConnectionRefused: + failf(data, "Server dropped the connection during the SSL handshake"); + break; + case errSSLClosedAbort: + failf(data, "Server aborted the SSL handshake"); + break; + case errSSLClosedGraceful: + failf(data, "The connection closed gracefully"); + break; + case errSSLClosedNoNotify: + failf(data, "The server closed the session with no notification"); + break; + /* Sometimes paramErr happens with buggy ciphers: */ + case paramErr: + case errSSLInternal: + case errSSLPeerInternalError: + failf(data, "Internal SSL engine error encountered during the " + "SSL handshake"); + break; + case errSSLFatalAlert: + failf(data, "Fatal SSL engine error encountered during the SSL " + "handshake"); + break; + /* Unclassified error */ + case errSSLBufferOverflow: + failf(data, "An insufficient buffer was provided"); + break; + case errSSLIllegalParam: + failf(data, "An illegal parameter was encountered"); + break; + case errSSLModuleAttach: + failf(data, "Module attach failure"); + break; + case errSSLSessionNotFound: + failf(data, "An attempt to restore an unknown session failed"); + break; + case errSSLPeerExportRestriction: + failf(data, "An export restriction occurred"); + break; + case errSSLPeerUserCancelled: + failf(data, "The user canceled the operation"); + break; + case errSSLPeerUnexpectedMsg: + failf(data, "Peer rejected unexpected message"); + break; +#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 + /* Treaing non-fatal error as fatal like before */ + case errSSLClientHelloReceived: + failf(data, "A non-fatal result for providing a server name " + "indication"); + break; +#endif + + /* Error codes defined in the enum but should never be returned. + We list them here just in case. */ +#if CURL_BUILD_MAC_10_6 + /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */ + case errSSLClientCertRequested: + failf(data, "The server has requested a client certificate"); + break; +#endif +#if CURL_BUILD_MAC_10_9 + /* Alias for errSSLLast, end of error range */ + case errSSLUnexpectedRecord: + failf(data, "Unexpected (skipped) record in DTLS"); + break; +#endif + default: + /* May also return codes listed in Security Framework Result Codes */ + failf(data, "Unknown SSL protocol error in connection to %s:%d", + hostname, err); + break; + } + return CURLE_SSL_CONNECT_ERROR; + } + else { + /* we have been connected fine, we're not waiting for anything else. */ + connssl->connecting_state = ssl_connect_3; + +#ifdef SECTRANSP_PINNEDPUBKEY + if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { + CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx, + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } +#endif /* SECTRANSP_PINNEDPUBKEY */ + + /* Informational message */ + (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher); + (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol); + switch(protocol) { + case kSSLProtocol2: + infof(data, "SSL 2.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kSSLProtocol3: + infof(data, "SSL 3.0 connection using %s\n", + SSLCipherNameForNumber(cipher)); + break; + case kTLSProtocol1: + infof(data, "TLS 1.0 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + case kTLSProtocol11: + infof(data, "TLS 1.1 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; + case kTLSProtocol12: + infof(data, "TLS 1.2 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + case kTLSProtocol13: + infof(data, "TLS 1.3 connection using %s\n", + TLSCipherNameForNumber(cipher)); + break; +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + default: + infof(data, "Unknown protocol connection\n"); + break; + } + +#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 + if(conn->bits.tls_enable_alpn) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { + CFArrayRef alpnArr = NULL; + CFStringRef chosenProtocol = NULL; + err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr); + + if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1) + chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0); + +#ifdef USE_NGHTTP2 + if(chosenProtocol && + !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID), + 0)) { + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(chosenProtocol && + !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) { + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + else + infof(data, "ALPN, server did not agree to a protocol\n"); + + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + + /* chosenProtocol is a reference to the string within alpnArr + and doesn't need to be freed separately */ + if(alpnArr) + CFRelease(alpnArr); + } + } +#endif + + return CURLE_OK; + } +} + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* This should be called during step3 of the connection at the earliest */ +static void +show_verbose_server_cert(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CFArrayRef server_certs = NULL; + SecCertificateRef server_cert; + OSStatus err; + CFIndex i, count; + SecTrustRef trust = NULL; + + if(!BACKEND->ssl_ctx) + return; + +#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS +#if CURL_BUILD_IOS +#pragma unused(server_certs) + err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + CURLcode result; + char *certp; + server_cert = SecTrustGetCertificateAtIndex(trust, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(trust); + } +#else + /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion. + The function SecTrustGetCertificateAtIndex() is officially present + in Lion, but it is unfortunately also present in Snow Leopard as + private API and doesn't work as expected. So we have to look for + a different symbol to make sure this code is only executed under + Lion or later. */ + if(SecTrustEvaluateAsync != NULL) { +#pragma unused(server_certs) + err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust); + /* For some reason, SSLCopyPeerTrust() can return noErr and yet return + a null trust, so be on guard for that: */ + if(err == noErr && trust) { + count = SecTrustGetCertificateCount(trust); + for(i = 0L ; i < count ; i++) { + char *certp; + CURLcode result; + server_cert = SecTrustGetCertificateAtIndex(trust, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(trust); + } + } + else { +#if CURL_SUPPORT_MAC_10_8 + err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); + /* Just in case SSLCopyPeerCertificates() returns null too... */ + if(err == noErr && server_certs) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + char *certp; + CURLcode result; + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, + i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(server_certs); + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_IOS */ +#else +#pragma unused(trust) + err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs); + if(err == noErr) { + count = CFArrayGetCount(server_certs); + for(i = 0L ; i < count ; i++) { + CURLcode result; + char *certp; + server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s\n", certp); + free(certp); + } + } + CFRelease(server_certs); + } +#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +static CURLcode +sectransp_connect_step3(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + /* There is no step 3! + * Well, okay, if verbose mode is on, let's print the details of the + * server certificates. */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + if(data->set.verbose) + show_verbose_server_cert(conn, sockindex); +#endif + + connssl->connecting_state = ssl_connect_done; + return CURLE_OK; +} + +static Curl_recv sectransp_recv; +static Curl_send sectransp_send; + +static CURLcode +sectransp_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + long timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = sectransp_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading || + connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if this + * connection is done nonblocking and this loop would execute again. This + * permits the owner of a multi handle to abort a connection attempt + * before step2 has completed while ensuring that a client using select() + * or epoll() will always have a valid fdset to wait on. + */ + result = sectransp_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + + } /* repeat step2 until all transactions are done. */ + + + if(ssl_connect_3 == connssl->connecting_state) { + result = sectransp_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = sectransp_recv; + conn->send[sockindex] = sectransp_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + +static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return sectransp_connect_common(conn, sockindex, TRUE, done); +} + +static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = sectransp_connect_common(conn, sockindex, FALSE, &done); + + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static void Curl_sectransp_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->ssl_ctx) { + (void)SSLClose(BACKEND->ssl_ctx); +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLCreateContext != NULL) + CFRelease(BACKEND->ssl_ctx); +#if CURL_SUPPORT_MAC_10_8 + else + (void)SSLDisposeContext(BACKEND->ssl_ctx); +#endif /* CURL_SUPPORT_MAC_10_8 */ +#else + (void)SSLDisposeContext(BACKEND->ssl_ctx); +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + BACKEND->ssl_ctx = NULL; + } + BACKEND->ssl_sockfd = 0; +} + +static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct Curl_easy *data = conn->data; + ssize_t nread; + int what; + int rc; + char buf[120]; + + if(!BACKEND->ssl_ctx) + return 0; + +#ifndef CURL_DISABLE_FTP + if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) + return 0; +#endif + + Curl_sectransp_close(conn, sockindex); + + rc = 0; + + what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); + + for(;;) { + if(what < 0) { + /* anything that gets here is fatally bad */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + rc = -1; + break; + } + + if(!what) { /* timeout */ + failf(data, "SSL shutdown timeout"); + break; + } + + /* Something to read, let's do it and hope that it is the close + notify alert from the server. No way to SSL_Read now, so use read(). */ + + nread = read(conn->sock[sockindex], buf, sizeof(buf)); + + if(nread < 0) { + failf(data, "read: %s", strerror(errno)); + rc = -1; + } + + if(nread <= 0) + break; + + what = SOCKET_READABLE(conn->sock[sockindex], 0); + } + + return rc; +} + +static void Curl_sectransp_session_free(void *ptr) +{ + /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a + cached session ID inside the Security framework. There is a private + function that does this, but I don't want to have to explain to you why I + got your application rejected from the App Store due to the use of a + private API, so the best we can do is free up our own char array that we + created way back in sectransp_connect_step1... */ + Curl_safefree(ptr); +} + +static size_t Curl_sectransp_version(char *buffer, size_t size) +{ + return msnprintf(buffer, size, "SecureTransport"); +} + +/* + * This function uses SSLGetSessionState to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +static int Curl_sectransp_check_cxn(struct connectdata *conn) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + OSStatus err; + SSLSessionState state; + + if(BACKEND->ssl_ctx) { + err = SSLGetSessionState(BACKEND->ssl_ctx, &state); + if(err == noErr) + return state == kSSLConnected || state == kSSLHandshake; + return -1; + } + return 0; +} + +static bool Curl_sectransp_data_pending(const struct connectdata *conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + OSStatus err; + size_t buffer; + + if(BACKEND->ssl_ctx) { /* SSL is in use */ + err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer); + if(err == noErr) + return buffer > 0UL; + return false; + } + else + return false; +} + +static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy, size_t length) +{ + /* arc4random_buf() isn't available on cats older than Lion, so let's + do this manually for the benefit of the older cats. */ + size_t i; + u_int32_t random_number = 0; + + (void)data; + + for(i = 0 ; i < length ; i++) { + if(i % sizeof(u_int32_t) == 0) + random_number = arc4random(); + entropy[i] = random_number & 0xFF; + random_number >>= 8; + } + i = random_number = 0; + return CURLE_OK; +} + +static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + (void)md5len; + (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); + return CURLE_OK; +} + +static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ + assert(sha256len >= CURL_SHA256_DIGEST_LENGTH); + (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum); + return CURLE_OK; +} + +static bool Curl_sectransp_false_start(void) +{ +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + if(SSLSetSessionOption != NULL) + return TRUE; +#endif + return FALSE; +} + +static ssize_t sectransp_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + /*struct Curl_easy *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + size_t processed = 0UL; + OSStatus err; + + /* The SSLWrite() function works a little differently than expected. The + fourth argument (processed) is currently documented in Apple's + documentation as: "On return, the length, in bytes, of the data actually + written." + + Now, one could interpret that as "written to the socket," but actually, + it returns the amount of data that was written to a buffer internal to + the SSLContextRef instead. So it's possible for SSLWrite() to return + errSSLWouldBlock and a number of bytes "written" because those bytes were + encrypted and written to a buffer, not to the socket. + + So if this happens, then we need to keep calling SSLWrite() over and + over again with no new data until it quits returning errSSLWouldBlock. */ + + /* Do we have buffered data to write from the last time we were called? */ + if(BACKEND->ssl_write_buffered_length) { + /* Write the buffered data: */ + err = SSLWrite(BACKEND->ssl_ctx, NULL, 0UL, &processed); + switch(err) { + case noErr: + /* processed is always going to be 0 because we didn't write to + the buffer, so return how much was written to the socket */ + processed = BACKEND->ssl_write_buffered_length; + BACKEND->ssl_write_buffered_length = 0UL; + break; + case errSSLWouldBlock: /* argh, try again */ + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + else { + /* We've got new data to write: */ + err = SSLWrite(BACKEND->ssl_ctx, mem, len, &processed); + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: + /* Data was buffered but not sent, we have to tell the caller + to try sending again, and remember how much was buffered */ + BACKEND->ssl_write_buffered_length = len; + *curlcode = CURLE_AGAIN; + return -1L; + default: + failf(conn->data, "SSLWrite() returned error %d", err); + *curlcode = CURLE_SEND_ERROR; + return -1L; + } + } + } + return (ssize_t)processed; +} + +static ssize_t sectransp_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + /*struct Curl_easy *data = conn->data;*/ + struct ssl_connect_data *connssl = &conn->ssl[num]; + size_t processed = 0UL; + OSStatus err; + + again: + err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed); + + if(err != noErr) { + switch(err) { + case errSSLWouldBlock: /* return how much we read (if anything) */ + if(processed) + return (ssize_t)processed; + *curlcode = CURLE_AGAIN; + return -1L; + break; + + /* errSSLClosedGraceful - server gracefully shut down the SSL session + errSSLClosedNoNotify - server hung up on us instead of sending a + closure alert notice, read() is returning 0 + Either way, inform the caller that the server disconnected. */ + case errSSLClosedGraceful: + case errSSLClosedNoNotify: + *curlcode = CURLE_OK; + return -1L; + break; + + /* The below is errSSLPeerAuthCompleted; it's not defined in + Leopard's headers */ + case -9841: + if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { + CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data, + BACKEND->ssl_ctx); + if(result) + return result; + } + goto again; + default: + failf(conn->data, "SSLRead() return error %d", err); + *curlcode = CURLE_RECV_ERROR; + return -1L; + break; + } + } + return (ssize_t)processed; +} + +static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->ssl_ctx; +} + +const struct Curl_ssl Curl_ssl_sectransp = { + { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ + +#ifdef SECTRANSP_PINNEDPUBKEY + SSLSUPP_PINNEDPUBKEY, +#else + 0, +#endif /* SECTRANSP_PINNEDPUBKEY */ + + sizeof(struct ssl_backend_data), + + Curl_none_init, /* init */ + Curl_none_cleanup, /* cleanup */ + Curl_sectransp_version, /* version */ + Curl_sectransp_check_cxn, /* check_cxn */ + Curl_sectransp_shutdown, /* shutdown */ + Curl_sectransp_data_pending, /* data_pending */ + Curl_sectransp_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_sectransp_connect, /* connect */ + Curl_sectransp_connect_nonblocking, /* connect_nonblocking */ + Curl_sectransp_get_internals, /* get_internals */ + Curl_sectransp_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_sectransp_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_sectransp_false_start, /* false_start */ + Curl_sectransp_md5sum, /* md5sum */ + Curl_sectransp_sha256sum /* sha256sum */ +}; + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif /* USE_SECTRANSP */ diff --git a/libcurl/lib/vtls/sectransp.h b/libcurl/lib/vtls/sectransp.h new file mode 100644 index 0000000..5cec797 --- /dev/null +++ b/libcurl/lib/vtls/sectransp.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_SECTRANSP_H +#define HEADER_CURL_SECTRANSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_SECTRANSP + +extern const struct Curl_ssl Curl_ssl_sectransp; + +#endif /* USE_SECTRANSP */ +#endif /* HEADER_CURL_SECTRANSP_H */ diff --git a/libcurl/lib/vtls/session_cache.cpp b/libcurl/lib/vtls/session_cache.cpp new file mode 100644 index 0000000..87a0934 --- /dev/null +++ b/libcurl/lib/vtls/session_cache.cpp @@ -0,0 +1,155 @@ +#include "session_cache.h" +#include "ssl_debug.h" + +#include +#include + +// KeQuerySystemTime is exported by the Xbox kernel (xboxkrnl.lib) +#ifdef __cplusplus +extern "C" +#endif +void WINAPI KeQuerySystemTime(PLARGE_INTEGER CurrentTime); + +session_cache::session_entry session_cache::entries[SESSION_CACHE_SIZE]; +bool session_cache::initialized = false; + +void session_cache::initialize() +{ + if (initialized) return; + + memset(entries, 0, sizeof(entries)); + initialized = true; + ssl_debug::log_verbose("Session cache initialized (%d slots)\n", SESSION_CACHE_SIZE); +} + +void session_cache::shutdown() +{ + clear(); + initialized = false; +} + +uint32_t session_cache::get_current_time() +{ + LARGE_INTEGER system_time; + KeQuerySystemTime(&system_time); + // Convert 100-nanosecond intervals to seconds + return (uint32_t)(system_time.QuadPart / 10000000ULL); +} + +int session_cache::find_entry(const char* hostname) +{ + for (int i = 0; i < SESSION_CACHE_SIZE; i++) { + if (entries[i].valid && strcmp(entries[i].hostname, hostname) == 0) { + return i; + } + } + return -1; +} + +int session_cache::find_free_slot() +{ + uint32_t current_time = get_current_time(); + int oldest_idx = -1; + uint32_t oldest_time = 0xFFFFFFFF; + + for (int i = 0; i < SESSION_CACHE_SIZE; i++) { + // Free slot + if (!entries[i].valid) { + return i; + } + + // Expired entry - reuse it (guard against RTC going backwards) + if (current_time >= entries[i].timestamp + && current_time - entries[i].timestamp > SESSION_MAX_AGE_SECONDS) { + entries[i].valid = false; + return i; + } + + // Track oldest for LRU eviction + if (entries[i].timestamp < oldest_time) { + oldest_time = entries[i].timestamp; + oldest_idx = i; + } + } + + // Evict oldest entry + if (oldest_idx >= 0) { + ssl_debug::log_verbose("Session cache: evicting entry for %s\n", entries[oldest_idx].hostname); + entries[oldest_idx].valid = false; + return oldest_idx; + } + + return 0; // Fallback to first slot +} + +bool session_cache::get(const char* hostname, br_ssl_session_parameters* params) +{ + if (!initialized) initialize(); + + int idx = find_entry(hostname); + if (idx < 0) { + ssl_debug::log_verbose("Session cache: miss for %s\n", hostname); + return false; + } + + uint32_t current_time = get_current_time(); + if (current_time >= entries[idx].timestamp + && current_time - entries[idx].timestamp > SESSION_MAX_AGE_SECONDS) { + ssl_debug::log_verbose("Session cache: expired entry for %s\n", hostname); + entries[idx].valid = false; + return false; + } + + /* Update timestamp on access for proper LRU eviction */ + entries[idx].timestamp = current_time; + memcpy(params, &entries[idx].params, sizeof(br_ssl_session_parameters)); + ssl_debug::log_info("Session cache: hit for %s\n", hostname); + return true; +} + +void session_cache::store(const char* hostname, const br_ssl_session_parameters* params) +{ + if (!initialized) initialize(); + + // Don't cache if no session ID and no session ticket + if (params->session_id_len == 0 && params->session_ticket_len == 0) { + return; + } + + int idx = find_entry(hostname); + if (idx < 0) { + idx = find_free_slot(); + } + + strncpy(entries[idx].hostname, hostname, 255); + entries[idx].hostname[255] = '\0'; + memcpy(&entries[idx].params, params, sizeof(br_ssl_session_parameters)); + entries[idx].timestamp = get_current_time(); + entries[idx].valid = true; + + ssl_debug::log_info("Session cache: stored session for %s\n", hostname); +} + +void session_cache::remove(const char* hostname) +{ + int idx = find_entry(hostname); + if (idx >= 0) { + entries[idx].valid = false; + ssl_debug::log_verbose("Session cache: removed entry for %s\n", hostname); + } +} + +void session_cache::clear() +{ + memset(entries, 0, sizeof(entries)); + ssl_debug::log_verbose("Session cache: cleared\n"); +} + +int session_cache::get_count() +{ + int count = 0; + for (int i = 0; i < SESSION_CACHE_SIZE; i++) { + if (entries[i].valid) count++; + } + return count; +} diff --git a/libcurl/lib/vtls/session_cache.h b/libcurl/lib/vtls/session_cache.h new file mode 100644 index 0000000..3411892 --- /dev/null +++ b/libcurl/lib/vtls/session_cache.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#define SESSION_CACHE_SIZE 8 +#define SESSION_MAX_AGE_SECONDS 3600 + +class session_cache +{ +public: + static void initialize(); + static void shutdown(); + + static bool get(const char* hostname, br_ssl_session_parameters* params); + static void store(const char* hostname, const br_ssl_session_parameters* params); + static void remove(const char* hostname); + static void clear(); + + static int get_count(); + +private: + struct session_entry { + char hostname[256]; + br_ssl_session_parameters params; + uint32_t timestamp; + bool valid; + }; + + static session_entry entries[SESSION_CACHE_SIZE]; + static bool initialized; + + static int find_entry(const char* hostname); + static int find_free_slot(); + static uint32_t get_current_time(); +}; diff --git a/libcurl/lib/vtls/ssl_debug.cpp b/libcurl/lib/vtls/ssl_debug.cpp new file mode 100644 index 0000000..569437d --- /dev/null +++ b/libcurl/lib/vtls/ssl_debug.cpp @@ -0,0 +1,147 @@ +#include "ssl_debug.h" +#include "ssl_errors.h" +#include "debug_utility.h" + +#include +#include +#include + +ssl_debug_level ssl_debug::current_level = SSL_DEBUG_ERROR; + +void ssl_debug::set_level(ssl_debug_level level) +{ + current_level = level; +} + +ssl_debug_level ssl_debug::get_level() +{ + return current_level; +} + +void ssl_debug::log_error(const char* format, ...) +{ + if (current_level < SSL_DEBUG_ERROR) return; + + debug_utility::debug_print("[SSL ERROR] "); + va_list args; + va_start(args, format); + char buffer[256]; + _vsnprintf(buffer, sizeof(buffer) - 1, format, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + debug_utility::debug_print("%s", buffer); +} + +void ssl_debug::log_info(const char* format, ...) +{ + if (current_level < SSL_DEBUG_INFO) return; + + debug_utility::debug_print("[SSL] "); + va_list args; + va_start(args, format); + char buffer[256]; + _vsnprintf(buffer, sizeof(buffer) - 1, format, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + debug_utility::debug_print("%s", buffer); +} + +void ssl_debug::log_verbose(const char* format, ...) +{ + if (current_level < SSL_DEBUG_VERBOSE) return; + + debug_utility::debug_print("[SSL DEBUG] "); + va_list args; + va_start(args, format); + char buffer[256]; + _vsnprintf(buffer, sizeof(buffer) - 1, format, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + debug_utility::debug_print("%s", buffer); +} + +const char* ssl_debug::version_to_string(unsigned version) +{ + switch (version) { + case BR_TLS10: return "TLS 1.0"; + case BR_TLS11: return "TLS 1.1"; + case BR_TLS12: return "TLS 1.2"; + default: return "Unknown"; + } +} + +const char* ssl_debug::cipher_suite_to_string(uint16_t suite) +{ + switch (suite) { + case BR_TLS_RSA_WITH_AES_128_CBC_SHA: + return "RSA-AES128-CBC-SHA"; + case BR_TLS_RSA_WITH_AES_256_CBC_SHA: + return "RSA-AES256-CBC-SHA"; + case BR_TLS_RSA_WITH_AES_128_CBC_SHA256: + return "RSA-AES128-CBC-SHA256"; + case BR_TLS_RSA_WITH_AES_256_CBC_SHA256: + return "RSA-AES256-CBC-SHA256"; + case BR_TLS_RSA_WITH_AES_128_GCM_SHA256: + return "RSA-AES128-GCM-SHA256"; + case BR_TLS_RSA_WITH_AES_256_GCM_SHA384: + return "RSA-AES256-GCM-SHA384"; + case BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "ECDHE-RSA-AES128-CBC-SHA"; + case BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "ECDHE-RSA-AES256-CBC-SHA"; + case BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return "ECDHE-RSA-AES128-CBC-SHA256"; + case BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return "ECDHE-RSA-AES256-CBC-SHA384"; + case BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + return "ECDHE-RSA-AES128-GCM-SHA256"; + case BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + return "ECDHE-RSA-AES256-GCM-SHA384"; + case BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return "ECDHE-RSA-CHACHA20-POLY1305"; + case BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + return "ECDHE-ECDSA-AES128-GCM-SHA256"; + case BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + return "ECDHE-ECDSA-AES256-GCM-SHA384"; + case BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + return "ECDHE-ECDSA-CHACHA20-POLY1305"; + default: + return "Unknown"; + } +} + +void ssl_debug::log_handshake_result(br_ssl_engine_context* engine) +{ + if (current_level < SSL_DEBUG_INFO) return; + + unsigned version = br_ssl_engine_get_version(engine); + log_info("Handshake complete\n"); + log_info(" Version: %s\n", version_to_string(version)); + + br_ssl_session_parameters params; + br_ssl_engine_get_session_parameters(engine, ¶ms); + log_info(" Cipher: %s\n", cipher_suite_to_string(params.cipher_suite)); + log_info(" Session resumed: %s\n", params.session_id_len > 0 ? "yes" : "no"); +} + +void ssl_debug::log_ssl_error(int error) +{ + if (error == 0) return; + + log_error("SSL error %d: %s\n", error, ssl_errors::error_to_string(error)); + + if (error >= 256 && error < 512) { + int alert = error - 256; + log_error(" Alert: %s\n", ssl_errors::alert_to_string(alert)); + } +} + +void ssl_debug::log_peer_certificate(br_ssl_engine_context* engine) +{ + // Note: BearSSL does not provide a direct API to retrieve the peer certificate + // chain after handshake completion. Certificate inspection would require + // custom X.509 callbacks during validation. This function is a placeholder. + if (current_level < SSL_DEBUG_VERBOSE) return; + log_verbose("Certificate inspection not available (requires X.509 callback)\n"); + (void)engine; // Suppress unused parameter warning +} diff --git a/libcurl/lib/vtls/ssl_debug.h b/libcurl/lib/vtls/ssl_debug.h new file mode 100644 index 0000000..a3541ac --- /dev/null +++ b/libcurl/lib/vtls/ssl_debug.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +enum ssl_debug_level { + SSL_DEBUG_NONE = 0, + SSL_DEBUG_ERROR = 1, + SSL_DEBUG_INFO = 2, + SSL_DEBUG_VERBOSE = 3 +}; + +class ssl_debug +{ +public: + static void set_level(ssl_debug_level level); + static ssl_debug_level get_level(); + + static void log_error(const char* format, ...); + static void log_info(const char* format, ...); + static void log_verbose(const char* format, ...); + + static void log_handshake_result(br_ssl_engine_context* engine); + static void log_ssl_error(int error); + static void log_peer_certificate(br_ssl_engine_context* engine); + + static const char* version_to_string(unsigned version); + static const char* cipher_suite_to_string(uint16_t suite); + +private: + static ssl_debug_level current_level; +}; diff --git a/libcurl/lib/vtls/ssl_errors.cpp b/libcurl/lib/vtls/ssl_errors.cpp new file mode 100644 index 0000000..a72a52c --- /dev/null +++ b/libcurl/lib/vtls/ssl_errors.cpp @@ -0,0 +1,73 @@ +#include "ssl_errors.h" +#include + +const char* ssl_errors::error_to_string(int error) +{ + switch (error) { + case BR_ERR_OK: return "Success"; + case BR_ERR_BAD_PARAM: return "Bad parameter"; + case BR_ERR_BAD_STATE: return "Invalid state"; + case BR_ERR_UNSUPPORTED_VERSION: return "Unsupported TLS version"; + case BR_ERR_BAD_VERSION: return "Bad TLS version"; + case BR_ERR_TOO_LARGE: return "Record too large"; + case BR_ERR_BAD_MAC: return "MAC verification failed"; + case BR_ERR_NO_RANDOM: return "No random seed"; + case BR_ERR_UNKNOWN_TYPE: return "Unknown record type"; + case BR_ERR_UNEXPECTED: return "Unexpected message"; + case BR_ERR_BAD_CCS: return "Bad ChangeCipherSpec"; + case BR_ERR_BAD_ALERT: return "Bad alert"; + case BR_ERR_BAD_HANDSHAKE: return "Bad handshake message"; + case BR_ERR_OVERSIZED_ID: return "Oversized ID"; + case BR_ERR_BAD_CIPHER_SUITE: return "Bad cipher suite"; + case BR_ERR_BAD_COMPRESSION: return "Bad compression"; + case BR_ERR_BAD_FRAGLEN: return "Bad fragment length"; + case BR_ERR_BAD_SECRENEG: return "Bad secure renegotiation"; + case BR_ERR_EXTRA_EXTENSION: return "Extra extension"; + case BR_ERR_BAD_SNI: return "Bad SNI"; + case BR_ERR_BAD_HELLO_DONE: return "Bad HelloDone"; + case BR_ERR_LIMIT_EXCEEDED: return "Limit exceeded"; + case BR_ERR_BAD_FINISHED: return "Bad Finished message"; + case BR_ERR_RESUME_MISMATCH: return "Session resume mismatch"; + case BR_ERR_INVALID_ALGORITHM: return "Invalid algorithm"; + case BR_ERR_BAD_SIGNATURE: return "Bad signature"; + case BR_ERR_WRONG_KEY_USAGE: return "Wrong key usage"; + case BR_ERR_NO_CLIENT_AUTH: return "No client auth"; + case BR_ERR_IO: return "I/O error"; + default: + if (error >= 256 && error < 512) + return "Received fatal alert from server"; + if (error >= 512) + return "Sent fatal alert to server"; + return "Unknown SSL error"; + } +} + +const char* ssl_errors::alert_to_string(int alert_code) +{ + switch (alert_code) { + case 0: return "close_notify"; + case 10: return "unexpected_message"; + case 20: return "bad_record_mac"; + case 21: return "decryption_failed"; + case 22: return "record_overflow"; + case 30: return "decompression_failure"; + case 40: return "handshake_failure"; + case 42: return "bad_certificate"; + case 43: return "unsupported_certificate"; + case 44: return "certificate_revoked"; + case 45: return "certificate_expired"; + case 46: return "certificate_unknown"; + case 47: return "illegal_parameter"; + case 48: return "unknown_ca"; + case 49: return "access_denied"; + case 50: return "decode_error"; + case 51: return "decrypt_error"; + case 70: return "protocol_version"; + case 71: return "insufficient_security"; + case 80: return "internal_error"; + case 90: return "user_canceled"; + case 100: return "no_renegotiation"; + case 110: return "unsupported_extension"; + default: return "unknown_alert"; + } +} diff --git a/libcurl/lib/vtls/ssl_errors.h b/libcurl/lib/vtls/ssl_errors.h new file mode 100644 index 0000000..d764b85 --- /dev/null +++ b/libcurl/lib/vtls/ssl_errors.h @@ -0,0 +1,8 @@ +#pragma once + +class ssl_errors +{ +public: + static const char* error_to_string(int error); + static const char* alert_to_string(int alert_code); +}; diff --git a/libcurl/lib/vtls/ssl_hs_client.c b/libcurl/lib/vtls/ssl_hs_client.c new file mode 100644 index 0000000..3fc96d0 --- /dev/null +++ b/libcurl/lib/vtls/ssl_hs_client.c @@ -0,0 +1,1967 @@ +/* Automatically generated code; do not modify directly. */ + +#include +#include + +typedef struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; +} t0_context; + +static uint32_t +t0_parse7E_unsigned(const unsigned char **p) +{ + uint32_t x; + + x = 0; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + return x; + } + } +} + +static int32_t +t0_parse7E_signed(const unsigned char **p) +{ + int neg; + uint32_t x; + + neg = ((**p) >> 6) & 1; + x = (uint32_t)-neg; + for (;;) { + unsigned y; + + y = *(*p) ++; + x = (x << 7) | (uint32_t)(y & 0x7F); + if (y < 0x80) { + if (neg) { + return -(int32_t)~x - 1; + } else { + return (int32_t)x; + } + } + } +} + +#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) +#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) +#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) +#define T0_INT1(x) T0_FBYTE(x, 0) +#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) +#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) + +/* static const unsigned char t0_datablock[]; */ + + +void br_ssl_hs_client_init_main(void *t0ctx); + +void br_ssl_hs_client_run(void *t0ctx); + + + +#include +#include + +#include "inner.h" + +/* + * This macro evaluates to a pointer to the current engine context. + */ +#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu))) + + + + + +/* + * This macro evaluates to a pointer to the client context, under that + * specific name. It must be noted that since the engine context is the + * first field of the br_ssl_client_context structure ('eng'), then + * pointers values of both types are interchangeable, modulo an + * appropriate cast. This also means that "addresses" computed as offsets + * within the structure work for both kinds of context. + */ +#define CTX ((br_ssl_client_context *)ENG) + +/* + * Generate the pre-master secret for RSA key exchange, and encrypt it + * with the server's public key. Returned value is either the encrypted + * data length (in bytes), or -x on error, with 'x' being an error code. + * + * This code assumes that the public key has been already verified (it + * was properly obtained by the X.509 engine, and it has the right type, + * i.e. it is of type RSA and suitable for encryption). + */ +static int +make_pms_rsa(br_ssl_client_context *ctx, int prf_id) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + const unsigned char *n; + unsigned char *pms; + size_t nlen, u; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + + /* + * Compute actual RSA key length, in case there are leading zeros. + */ + n = pk->key.rsa.n; + nlen = pk->key.rsa.nlen; + while (nlen > 0 && *n == 0) { + n ++; + nlen --; + } + + /* + * We need at least 59 bytes (48 bytes for pre-master secret, and + * 11 bytes for the PKCS#1 type 2 padding). Note that the X.509 + * minimal engine normally blocks RSA keys shorter than 128 bytes, + * so this is mostly for public keys provided explicitly by the + * caller. + */ + if (nlen < 59) { + return -BR_ERR_X509_WEAK_PUBLIC_KEY; + } + if (nlen > sizeof ctx->eng.pad) { + return -BR_ERR_LIMIT_EXCEEDED; + } + + /* + * Make PMS. + */ + pms = ctx->eng.pad + nlen - 48; + br_enc16be(pms, ctx->eng.version_max); + br_hmac_drbg_generate(&ctx->eng.rng, pms + 2, 46); + br_ssl_engine_compute_master(&ctx->eng, prf_id, pms, 48); + + /* + * Apply PKCS#1 type 2 padding. + */ + ctx->eng.pad[0] = 0x00; + ctx->eng.pad[1] = 0x02; + ctx->eng.pad[nlen - 49] = 0x00; + br_hmac_drbg_generate(&ctx->eng.rng, ctx->eng.pad + 2, nlen - 51); + for (u = 2; u < nlen - 49; u ++) { + while (ctx->eng.pad[u] == 0) { + br_hmac_drbg_generate(&ctx->eng.rng, + &ctx->eng.pad[u], 1); + } + } + + /* + * Compute RSA encryption. + */ + if (!ctx->irsapub(ctx->eng.pad, nlen, &pk->key.rsa)) { + return -BR_ERR_LIMIT_EXCEEDED; + } + return (int)nlen; +} + +/* + * OID for hash functions in RSA signatures. + */ +static const unsigned char *HASH_OID[] = { + BR_HASH_OID_SHA1, + BR_HASH_OID_SHA224, + BR_HASH_OID_SHA256, + BR_HASH_OID_SHA384, + BR_HASH_OID_SHA512 +}; + +/* + * 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 +verify_SKE_sig(br_ssl_client_context *ctx, + int hash, int use_rsa, size_t sig_len) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + br_multihash_context mhc; + unsigned char hv[64], head[4]; + size_t hv_len; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + br_multihash_zero(&mhc); + br_multihash_copyimpl(&mhc, &ctx->eng.mhash); + br_multihash_init(&mhc); + br_multihash_update(&mhc, + ctx->eng.client_random, sizeof ctx->eng.client_random); + br_multihash_update(&mhc, + ctx->eng.server_random, sizeof ctx->eng.server_random); + head[0] = 3; + head[1] = 0; + head[2] = ctx->eng.ecdhe_curve; + head[3] = ctx->eng.ecdhe_point_len; + br_multihash_update(&mhc, head, sizeof head); + br_multihash_update(&mhc, + ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len); + if (hash) { + hv_len = br_multihash_out(&mhc, hash, hv); + if (hv_len == 0) { + return BR_ERR_INVALID_ALGORITHM; + } + } else { + if (!br_multihash_out(&mhc, br_md5_ID, hv) + || !br_multihash_out(&mhc, br_sha1_ID, hv + 16)) + { + return BR_ERR_INVALID_ALGORITHM; + } + hv_len = 36; + } + if (use_rsa) { + unsigned char tmp[64]; + const unsigned char *hash_oid; + + if (hash) { + hash_oid = HASH_OID[hash - 2]; + } else { + hash_oid = NULL; + } + 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->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec, + ctx->eng.pad, sig_len)) + { + return BR_ERR_BAD_SIGNATURE; + } + } + return 0; +} + +/* + * Perform client-side ECDH (or ECDHE). The point that should be sent to + * the server is written in the pad; returned value is either the point + * length (in bytes), or -x on error, with 'x' being an error code. + * + * The point _from_ the server is taken from ecdhe_point[] if 'ecdhe' + * is non-zero, or from the X.509 engine context if 'ecdhe' is zero + * (for static ECDH). + */ +static int +make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) +{ + int curve; + unsigned char key[66], point[133]; + const unsigned char *order, *point_src; + size_t glen, olen, point_len, xoff, xlen; + unsigned char mask; + + if (ecdhe) { + curve = ctx->eng.ecdhe_curve; + point_src = ctx->eng.ecdhe_point; + point_len = ctx->eng.ecdhe_point_len; + } else { + const br_x509_class **xc; + const br_x509_pkey *pk; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + curve = pk->key.ec.curve; + point_src = pk->key.ec.q; + point_len = pk->key.ec.qlen; + } + if ((ctx->eng.iec->supported_curves & ((uint32_t)1 << curve)) == 0) { + return -BR_ERR_INVALID_ALGORITHM; + } + + /* + * We need to generate our key, as a non-zero random value which + * is lower than the curve order, in a "large enough" range. We + * force top bit to 0 and bottom bit to 1, which guarantees that + * the value is in the proper range. + */ + order = ctx->eng.iec->order(curve, &olen); + mask = 0xFF; + while (mask >= order[0]) { + mask >>= 1; + } + br_hmac_drbg_generate(&ctx->eng.rng, key, olen); + key[0] &= mask; + key[olen - 1] |= 0x01; + + /* + * Compute the common ECDH point, whose X coordinate is the + * pre-master secret. + */ + ctx->eng.iec->generator(curve, &glen); + if (glen != point_len) { + return -BR_ERR_INVALID_ALGORITHM; + } + + memcpy(point, point_src, glen); + if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) { + return -BR_ERR_INVALID_ALGORITHM; + } + + /* + * The pre-master secret is the X coordinate. + */ + xoff = ctx->eng.iec->xoff(curve, &xlen); + br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen); + + ctx->eng.iec->mulgen(point, key, olen, curve); + memcpy(ctx->eng.pad, point, glen); + return (int)glen; +} + +/* + * Perform full static ECDH. This occurs only in the context of client + * authentication with certificates: the server uses an EC public key, + * the cipher suite is of type ECDH (not ECDHE), the server requested a + * client certificate and accepts static ECDH, the client has a + * certificate with an EC public key in the same curve, and accepts + * static ECDH as well. + * + * Returned value is 0 on success, -1 on error. + */ +static int +make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id) +{ + unsigned char point[133]; + size_t point_len; + const br_x509_class **xc; + const br_x509_pkey *pk; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + point_len = pk->key.ec.qlen; + if (point_len > sizeof point) { + return -1; + } + memcpy(point, pk->key.ec.q, point_len); + if (!(*ctx->client_auth_vtable)->do_keyx( + ctx->client_auth_vtable, point, &point_len)) + { + return -1; + } + br_ssl_engine_compute_master(&ctx->eng, + prf_id, point, point_len); + return 0; +} + +/* + * Compute the client-side signature. This is invoked only when a + * signature-based client authentication was selected. The computed + * signature is in the pad; its length (in bytes) is returned. On + * error, 0 is returned. + */ +static size_t +make_client_sign(br_ssl_client_context *ctx) +{ + size_t hv_len; + + /* + * Compute hash of handshake messages so far. This "cannot" fail + * because the list of supported hash functions provided to the + * client certificate handler was trimmed to include only the + * hash functions that the multi-hasher supports. + */ + if (ctx->hash_id) { + hv_len = br_multihash_out(&ctx->eng.mhash, + ctx->hash_id, ctx->eng.pad); + } else { + br_multihash_out(&ctx->eng.mhash, + br_md5_ID, ctx->eng.pad); + br_multihash_out(&ctx->eng.mhash, + br_sha1_ID, ctx->eng.pad + 16); + hv_len = 36; + } + return (*ctx->client_auth_vtable)->do_sign( + ctx->client_auth_vtable, ctx->hash_id, hv_len, + ctx->eng.pad, sizeof ctx->eng.pad); +} + + + +static const unsigned char t0_datablock[] = { + 0x00, 0x00, 0x0A, 0x00, 0x24, 0x00, 0x2F, 0x01, 0x24, 0x00, 0x35, 0x02, + 0x24, 0x00, 0x3C, 0x01, 0x44, 0x00, 0x3D, 0x02, 0x44, 0x00, 0x9C, 0x03, + 0x04, 0x00, 0x9D, 0x04, 0x05, 0xC0, 0x03, 0x40, 0x24, 0xC0, 0x04, 0x41, + 0x24, 0xC0, 0x05, 0x42, 0x24, 0xC0, 0x08, 0x20, 0x24, 0xC0, 0x09, 0x21, + 0x24, 0xC0, 0x0A, 0x22, 0x24, 0xC0, 0x0D, 0x30, 0x24, 0xC0, 0x0E, 0x31, + 0x24, 0xC0, 0x0F, 0x32, 0x24, 0xC0, 0x12, 0x10, 0x24, 0xC0, 0x13, 0x11, + 0x24, 0xC0, 0x14, 0x12, 0x24, 0xC0, 0x23, 0x21, 0x44, 0xC0, 0x24, 0x22, + 0x55, 0xC0, 0x25, 0x41, 0x44, 0xC0, 0x26, 0x42, 0x55, 0xC0, 0x27, 0x11, + 0x44, 0xC0, 0x28, 0x12, 0x55, 0xC0, 0x29, 0x31, 0x44, 0xC0, 0x2A, 0x32, + 0x55, 0xC0, 0x2B, 0x23, 0x04, 0xC0, 0x2C, 0x24, 0x05, 0xC0, 0x2D, 0x43, + 0x04, 0xC0, 0x2E, 0x44, 0x05, 0xC0, 0x2F, 0x13, 0x04, 0xC0, 0x30, 0x14, + 0x05, 0xC0, 0x31, 0x33, 0x04, 0xC0, 0x32, 0x34, 0x05, 0xC0, 0x9C, 0x06, + 0x04, 0xC0, 0x9D, 0x07, 0x04, 0xC0, 0xA0, 0x08, 0x04, 0xC0, 0xA1, 0x09, + 0x04, 0xC0, 0xAC, 0x26, 0x04, 0xC0, 0xAD, 0x27, 0x04, 0xC0, 0xAE, 0x28, + 0x04, 0xC0, 0xAF, 0x29, 0x04, 0xCC, 0xA8, 0x15, 0x04, 0xCC, 0xA9, 0x25, + 0x04, 0x00, 0x00 +}; + +static const unsigned char t0_codeblock[] = { + 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01, + 0x00, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x01, 0x08, + 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00, + 0x01, 0x02, 0x09, 0x00, 0x00, 0x26, 0x26, 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_CIPHER_SUITE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_COMPRESSION), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_HELLO_DONE), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_BAD_SNI), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_BAD_VERSION), + 0x00, 0x00, 0x01, T0_INT1(BR_ERR_EXTRA_EXTENSION), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK), + 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_RESUME_MISMATCH), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_UNSUPPORTED_VERSION), 0x00, 0x00, 0x01, + T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_client_context, auth_type)), 0x00, 0x00, + 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, client_random)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, close_received)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_curve)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hash_id)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hashes)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_client_context, min_clienthello_len)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, protocol_names_num)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, record_type_in)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, record_type_out)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, reneg)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, saved_finished)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, selected_protocol)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, server_name)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, server_random)), 0x00, 0x00, + 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id_len)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_ticket)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_ticket_len)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session_ticket_ok)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, shutdown_recv)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_buf)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_num)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, version)), + 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_in)), + 0x00, 0x00, 0x01, + T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00, + 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00, + 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)), + 0x00, 0x00, 0x09, 0x27, 0x5A, 0x06, 0x02, 0x6A, 0x29, 0x00, 0x00, 0x06, + 0x08, 0x2D, 0x0E, 0x05, 0x02, 0x73, 0x29, 0x04, 0x01, 0x3E, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x01, 0x03, 0x00, 0x9E, 0x27, 0x60, 0x46, 0xA2, 0x27, + 0x05, 0x04, 0x62, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0E, 0x06, 0x02, 0xA2, + 0x00, 0x60, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x6A, 0x29, 0x00, 0x00, 0x27, + 0x8B, 0x46, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x46, 0x7B, 0x2D, 0xB1, 0x1C, + 0x86, 0x01, 0x0C, 0x32, 0x00, 0x00, 0x27, 0x1F, 0x01, 0x08, 0x0B, 0x46, + 0x5E, 0x1F, 0x08, 0x00, 0x01, 0x03, 0x00, 0x79, 0x2F, 0x02, 0x00, 0x37, + 0x17, 0x01, 0x01, 0x0B, 0x79, 0x40, 0x2A, 0x1A, 0x37, 0x06, 0x07, 0x02, + 0x00, 0xD7, 0x03, 0x00, 0x04, 0x75, 0x01, 0x00, 0xCD, 0x02, 0x00, 0x27, + 0x1A, 0x17, 0x06, 0x02, 0x71, 0x29, 0xD7, 0x04, 0x76, 0x02, 0x01, 0x00, + 0x79, 0x40, 0x01, 0x16, 0x89, 0x40, 0x01, 0x00, 0x8C, 0x3E, 0x01, 0x00, + 0x93, 0x40, 0x35, 0xDD, 0x2A, 0xBC, 0x01, 0x00, 0x03, 0x00, 0x05, 0x34, + 0x93, 0x2F, 0x92, 0x2D, 0x01, 0x00, 0x0F, 0x17, 0x06, 0x28, 0x30, 0x37, + 0x06, 0x0C, 0xD6, 0x01, 0x07, 0x17, 0x27, 0x5C, 0x06, 0x03, 0x26, 0x04, + 0x75, 0x26, 0x88, 0x2F, 0x01, 0x14, 0x0E, 0x06, 0x06, 0x01, 0x7F, 0x03, + 0x00, 0x04, 0x0B, 0x3A, 0x01, 0x04, 0x0E, 0x06, 0x05, 0xBB, 0x01, 0x7F, + 0x03, 0x00, 0x04, 0x04, 0x01, 0x7F, 0x03, 0x00, 0x02, 0x00, 0x06, 0x09, + 0x01, 0x7F, 0xB6, 0x01, 0x7F, 0xDA, 0x04, 0x80, 0x53, 0xB8, 0x7B, 0x2D, + 0xA6, 0x01, T0_INT1(BR_KEYTYPE_SIGN), 0x17, 0x06, 0x01, 0xBD, 0xC0, + 0x27, 0x01, 0x0D, 0x0E, 0x06, 0x07, 0x26, 0xBF, 0xC0, 0x01, 0x7F, 0x04, + 0x02, 0x01, 0x00, 0x03, 0x01, 0x01, 0x0E, 0x0E, 0x05, 0x02, 0x74, 0x29, + 0x06, 0x02, 0x69, 0x29, 0x34, 0x06, 0x02, 0x74, 0x29, 0x02, 0x01, 0x06, + 0x1C, 0xDB, 0x82, 0x2F, 0x01, 0x81, 0x7F, 0x0E, 0x06, 0x0D, 0x26, 0x01, + 0x10, 0xE6, 0x01, 0x00, 0xE5, 0x7B, 0x2D, 0xB1, 0x25, 0x04, 0x04, 0xDE, + 0x06, 0x01, 0xDC, 0x04, 0x01, 0xDE, 0x01, 0x7F, 0xDA, 0x01, 0x7F, 0xB6, + 0x01, 0x01, 0x79, 0x40, 0x01, 0x17, 0x89, 0x40, 0x00, 0x00, 0x39, 0x39, + 0x00, 0x00, 0x9F, 0x01, 0x0C, 0x11, 0x01, 0x00, 0x39, 0x0E, 0x06, 0x05, + 0x26, 0x01, T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX), 0x04, 0x30, + 0x01, 0x01, 0x39, 0x0E, 0x06, 0x05, 0x26, 0x01, + T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN), 0x04, 0x25, 0x01, 0x02, + 0x39, 0x0E, 0x06, 0x05, 0x26, 0x01, + T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_SIGN), 0x04, 0x1A, 0x01, 0x03, + 0x39, 0x0E, 0x06, 0x05, 0x26, 0x01, + T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x0F, 0x01, 0x04, + 0x39, 0x0E, 0x06, 0x05, 0x26, 0x01, + T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x04, 0x01, 0x00, + 0x46, 0x26, 0x00, 0x00, 0x84, 0x2F, 0x01, 0x0E, 0x0E, 0x06, 0x04, 0x01, + 0x00, 0x04, 0x02, 0x01, 0x05, 0x00, 0x00, 0x42, 0x06, 0x04, 0x01, 0x06, + 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x8A, 0x2F, 0x27, 0x06, 0x08, 0x01, + 0x01, 0x09, 0x01, 0x11, 0x07, 0x04, 0x03, 0x26, 0x01, 0x05, 0x00, 0x00, + 0x92, 0x2D, 0x01, 0x04, 0x08, 0x00, 0x01, 0x43, 0x03, 0x00, 0x26, 0x01, + 0x00, 0x45, 0x06, 0x03, 0x02, 0x00, 0x08, 0x44, 0x06, 0x03, 0x02, 0x00, + 0x08, 0x27, 0x06, 0x06, 0x01, 0x01, 0x0B, 0x01, 0x06, 0x08, 0x00, 0x00, + 0x8D, 0x41, 0x27, 0x06, 0x03, 0x01, 0x09, 0x08, 0x00, 0x01, 0x42, 0x27, + 0x06, 0x1E, 0x01, 0x00, 0x03, 0x00, 0x27, 0x06, 0x0E, 0x27, 0x01, 0x01, + 0x17, 0x02, 0x00, 0x08, 0x03, 0x00, 0x01, 0x01, 0x11, 0x04, 0x6F, 0x26, + 0x02, 0x00, 0x01, 0x01, 0x0B, 0x01, 0x06, 0x08, 0x00, 0x00, 0x81, 0x2E, + 0x46, 0x11, 0x01, 0x01, 0x17, 0x36, 0x00, 0x00, 0xA4, 0xD6, 0x27, 0x01, + 0x07, 0x17, 0x01, 0x00, 0x39, 0x0E, 0x06, 0x09, 0x26, 0x01, 0x10, 0x17, + 0x06, 0x01, 0xA4, 0x04, 0x35, 0x01, 0x01, 0x39, 0x0E, 0x06, 0x2C, 0x26, + 0x26, 0x01, 0x00, 0x79, 0x40, 0xBA, 0x8A, 0x2F, 0x01, 0x01, 0x0E, 0x01, + 0x01, 0xAE, 0x38, 0x06, 0x17, 0x2A, 0x1A, 0x37, 0x06, 0x04, 0xD6, 0x26, + 0x04, 0x78, 0x01, 0x80, 0x64, 0xCD, 0x01, 0x01, 0x79, 0x40, 0x01, 0x17, + 0x89, 0x40, 0x04, 0x01, 0xA4, 0x04, 0x03, 0x74, 0x29, 0x26, 0x04, 0xFF, + 0x34, 0x01, 0x27, 0x03, 0x00, 0x09, 0x27, 0x5A, 0x06, 0x02, 0x6A, 0x29, + 0x02, 0x00, 0x00, 0x00, 0x9F, 0x01, 0x0F, 0x17, 0x00, 0x00, 0x78, 0x2F, + 0x01, 0x00, 0x39, 0x0E, 0x06, 0x10, 0x26, 0x27, 0x01, 0x01, 0x0D, 0x06, + 0x03, 0x26, 0x01, 0x02, 0x78, 0x40, 0x01, 0x00, 0x04, 0x21, 0x01, 0x01, + 0x39, 0x0E, 0x06, 0x14, 0x26, 0x01, 0x00, 0x78, 0x40, 0x27, 0x01, 0x80, + 0x64, 0x0E, 0x06, 0x05, 0x01, 0x82, 0x00, 0x08, 0x29, 0x5C, 0x04, 0x07, + 0x26, 0x01, 0x82, 0x00, 0x08, 0x29, 0x26, 0x00, 0x00, 0x01, 0x00, 0x30, + 0x06, 0x05, 0x3C, 0xB2, 0x38, 0x04, 0x78, 0x27, 0x06, 0x04, 0x01, 0x01, + 0x94, 0x40, 0x00, 0x01, 0xC7, 0xB0, 0xC7, 0xB0, 0xC9, 0x86, 0x46, 0x27, + 0x03, 0x00, 0xBE, 0xA0, 0xA0, 0x02, 0x00, 0x4F, 0x27, 0x5A, 0x06, 0x0A, + 0x01, 0x03, 0xAE, 0x06, 0x02, 0x74, 0x29, 0x26, 0x04, 0x03, 0x5E, 0x8C, + 0x3E, 0x00, 0x00, 0x30, 0x06, 0x0B, 0x88, 0x2F, 0x01, 0x14, 0x0D, 0x06, + 0x02, 0x74, 0x29, 0x04, 0x11, 0xD6, 0x01, 0x07, 0x17, 0x27, 0x01, 0x02, + 0x0D, 0x06, 0x06, 0x06, 0x02, 0x74, 0x29, 0x04, 0x70, 0x26, 0xCA, 0x01, + 0x01, 0x0D, 0x34, 0x38, 0x06, 0x02, 0x63, 0x29, 0x27, 0x01, 0x01, 0xD0, + 0x37, 0xB9, 0x00, 0x00, 0x93, 0x2F, 0x06, 0x2A, 0x30, 0x06, 0x0A, 0x88, + 0x2F, 0x01, 0x16, 0x0E, 0x06, 0x01, 0xBB, 0x04, 0x1D, 0xD6, 0x01, 0x07, + 0x17, 0x27, 0x01, 0x01, 0x0E, 0x06, 0x04, 0x26, 0xBB, 0x01, 0x00, 0x27, + 0x01, 0x02, 0x0D, 0x06, 0x08, 0x27, 0x06, 0x02, 0x74, 0x29, 0x26, 0x04, + 0x64, 0x26, 0xB5, 0x00, 0x01, 0xC0, 0x01, 0x0B, 0x0E, 0x05, 0x02, 0x74, + 0x29, 0x27, 0x01, 0x03, 0x0E, 0x06, 0x08, 0xC8, 0x06, 0x02, 0x6A, 0x29, + 0x46, 0x26, 0x00, 0x46, 0x59, 0xC8, 0xB0, 0x27, 0x06, 0x23, 0xC8, 0xB0, + 0x27, 0x58, 0x27, 0x06, 0x18, 0x27, 0x01, 0x82, 0x00, 0x0F, 0x06, 0x05, + 0x01, 0x82, 0x00, 0x04, 0x01, 0x27, 0x03, 0x00, 0x86, 0x02, 0x00, 0xBE, + 0x02, 0x00, 0x55, 0x04, 0x65, 0xA0, 0x56, 0x04, 0x5A, 0xA0, 0xA0, 0x57, + 0x27, 0x06, 0x02, 0x36, 0x00, 0x26, 0x2C, 0x00, 0x00, 0x7B, 0x2D, 0xA6, + 0x01, 0x7F, 0xB7, 0x27, 0x5A, 0x06, 0x02, 0x36, 0x29, 0x27, 0x05, 0x02, + 0x74, 0x29, 0x39, 0x17, 0x0D, 0x06, 0x02, 0x76, 0x29, 0x3D, 0x00, 0x00, + 0xA1, 0xC0, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x74, 0x29, 0x86, 0x01, 0x0C, + 0x08, 0x01, 0x0C, 0xBE, 0xA0, 0x86, 0x27, 0x01, 0x0C, 0x08, 0x01, 0x0C, + 0x31, 0x05, 0x02, 0x66, 0x29, 0x00, 0x00, 0xC1, 0x06, 0x02, 0x74, 0x29, + 0x06, 0x02, 0x68, 0x29, 0x00, 0x01, 0xC0, 0x01, 0x04, 0x0E, 0x05, 0x02, + 0x74, 0x29, 0xC7, 0x26, 0xC7, 0x26, 0xC7, 0x03, 0x00, 0x02, 0x00, 0x01, + 0x88, 0x00, 0x0F, 0x06, 0x09, 0x02, 0x00, 0xCE, 0x01, 0x00, 0x92, 0x3E, + 0x04, 0x08, 0x91, 0x02, 0x00, 0xBE, 0x02, 0x00, 0x92, 0x3E, 0x02, 0x00, + 0x20, 0xA0, 0x00, 0x0B, 0xC0, 0x01, 0x02, 0x0E, 0x05, 0x02, 0x74, 0x29, + 0xC7, 0x03, 0x00, 0x02, 0x00, 0x9A, 0x2D, 0x0A, 0x02, 0x00, 0x99, 0x2D, + 0x0F, 0x38, 0x06, 0x02, 0x75, 0x29, 0x02, 0x00, 0x98, 0x2D, 0x0D, 0x06, + 0x02, 0x6D, 0x29, 0x02, 0x00, 0x9B, 0x3E, 0x8E, 0x01, 0x20, 0xBE, 0x01, + 0x00, 0x03, 0x01, 0xC9, 0x03, 0x02, 0x02, 0x02, 0x01, 0x20, 0x0F, 0x06, + 0x02, 0x72, 0x29, 0x86, 0x02, 0x02, 0xBE, 0x02, 0x02, 0x90, 0x2F, 0x0E, + 0x02, 0x02, 0x01, 0x00, 0x0F, 0x17, 0x06, 0x0B, 0x8F, 0x86, 0x02, 0x02, + 0x31, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x01, 0x8F, 0x86, 0x02, 0x02, 0x32, + 0x02, 0x02, 0x90, 0x40, 0x02, 0x00, 0x97, 0x02, 0x01, 0x9D, 0xC7, 0x27, + 0xCB, 0x5A, 0x06, 0x02, 0x64, 0x29, 0x27, 0xD5, 0x02, 0x00, 0x01, 0x86, + 0x03, 0x0A, 0x17, 0x06, 0x02, 0x64, 0x29, 0x7B, 0x02, 0x01, 0x9D, 0xC9, + 0x06, 0x02, 0x65, 0x29, 0x27, 0x06, 0x81, 0x64, 0xC7, 0xB0, 0xAC, 0x03, + 0x03, 0xA9, 0x03, 0x04, 0xA7, 0x03, 0x05, 0xAB, 0x03, 0x06, 0xAD, 0x03, + 0x07, 0xA8, 0x03, 0x08, 0xAA, 0x03, 0x09, 0x28, 0x03, 0x0A, 0x27, 0x06, + 0x81, 0x32, 0xC7, 0x01, 0x00, 0x39, 0x0E, 0x06, 0x0F, 0x26, 0x02, 0x03, + 0x05, 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, 0x03, 0xC6, 0x04, 0x81, 0x19, + 0x01, 0x01, 0x39, 0x0E, 0x06, 0x0F, 0x26, 0x02, 0x05, 0x05, 0x02, 0x6E, + 0x29, 0x01, 0x00, 0x03, 0x05, 0xC4, 0x04, 0x81, 0x04, 0x01, 0x83, 0xFE, + 0x01, 0x39, 0x0E, 0x06, 0x0F, 0x26, 0x02, 0x04, 0x05, 0x02, 0x6E, 0x29, + 0x01, 0x00, 0x03, 0x04, 0xC5, 0x04, 0x80, 0x6D, 0x01, 0x0D, 0x39, 0x0E, + 0x06, 0x0F, 0x26, 0x02, 0x06, 0x05, 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, + 0x06, 0xC2, 0x04, 0x80, 0x58, 0x01, 0x0A, 0x39, 0x0E, 0x06, 0x0F, 0x26, + 0x02, 0x07, 0x05, 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, 0x07, 0xC2, 0x04, + 0x80, 0x43, 0x01, 0x0B, 0x39, 0x0E, 0x06, 0x0E, 0x26, 0x02, 0x08, 0x05, + 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, 0x08, 0xC2, 0x04, 0x2F, 0x01, 0x10, + 0x39, 0x0E, 0x06, 0x0E, 0x26, 0x02, 0x0A, 0x05, 0x02, 0x6E, 0x29, 0x01, + 0x00, 0x03, 0x0A, 0xB4, 0x04, 0x1B, 0x01, 0x23, 0x39, 0x0E, 0x06, 0x12, + 0x26, 0x02, 0x09, 0x05, 0x02, 0x6E, 0x29, 0x01, 0x00, 0x03, 0x09, 0xC2, + 0x01, 0x01, 0x93, 0x40, 0x04, 0x03, 0x6E, 0x29, 0x26, 0x04, 0xFE, 0x4A, + 0x02, 0x04, 0x06, 0x0D, 0x02, 0x04, 0x01, 0x05, 0x0F, 0x06, 0x02, 0x6B, + 0x29, 0x01, 0x01, 0x8A, 0x40, 0xA0, 0x04, 0x0C, 0xA9, 0x01, 0x05, 0x0F, + 0x06, 0x02, 0x6B, 0x29, 0x01, 0x01, 0x8A, 0x40, 0xA0, 0x02, 0x01, 0x00, + 0x04, 0xC0, 0x01, 0x0C, 0x0E, 0x05, 0x02, 0x74, 0x29, 0xC9, 0x01, 0x03, + 0x0E, 0x05, 0x02, 0x6F, 0x29, 0xC7, 0x27, 0x7E, 0x40, 0x27, 0x01, 0x20, + 0x10, 0x06, 0x02, 0x6F, 0x29, 0x42, 0x46, 0x11, 0x01, 0x01, 0x17, 0x05, + 0x02, 0x6F, 0x29, 0xC9, 0x27, 0x01, 0x81, 0x05, 0x0F, 0x06, 0x02, 0x6F, + 0x29, 0x27, 0x80, 0x40, 0x7F, 0x46, 0xBE, 0x97, 0x2D, 0x01, 0x86, 0x03, + 0x10, 0x03, 0x00, 0x7B, 0x2D, 0xD3, 0x03, 0x01, 0x01, 0x02, 0x03, 0x02, + 0x02, 0x00, 0x06, 0x21, 0xC9, 0x27, 0x27, 0x01, 0x02, 0x0A, 0x46, 0x01, + 0x06, 0x0F, 0x38, 0x06, 0x02, 0x6F, 0x29, 0x03, 0x02, 0xC9, 0x02, 0x01, + 0x01, 0x01, 0x0B, 0x01, 0x03, 0x08, 0x0E, 0x05, 0x02, 0x6F, 0x29, 0x04, + 0x08, 0x02, 0x01, 0x06, 0x04, 0x01, 0x00, 0x03, 0x02, 0xC7, 0x27, 0x03, + 0x03, 0x27, 0x01, 0x84, 0x00, 0x0F, 0x06, 0x02, 0x70, 0x29, 0x86, 0x46, + 0xBE, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x52, 0x27, 0x06, 0x01, 0x29, + 0x26, 0xA0, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00, 0x9C, 0x02, + 0x01, 0x02, 0x00, 0x3B, 0x27, 0x01, 0x00, 0x0E, 0x06, 0x02, 0x62, 0x00, + 0xD8, 0x04, 0x74, 0x02, 0x01, 0x00, 0x03, 0x00, 0xC9, 0xB0, 0x27, 0x06, + 0x80, 0x43, 0xC9, 0x01, 0x01, 0x39, 0x0E, 0x06, 0x06, 0x26, 0x01, 0x81, + 0x7F, 0x04, 0x2E, 0x01, 0x80, 0x40, 0x39, 0x0E, 0x06, 0x07, 0x26, 0x01, + 0x83, 0xFE, 0x00, 0x04, 0x20, 0x01, 0x80, 0x41, 0x39, 0x0E, 0x06, 0x07, + 0x26, 0x01, 0x84, 0x80, 0x00, 0x04, 0x12, 0x01, 0x80, 0x42, 0x39, 0x0E, + 0x06, 0x07, 0x26, 0x01, 0x88, 0x80, 0x00, 0x04, 0x04, 0x01, 0x00, 0x46, + 0x26, 0x02, 0x00, 0x38, 0x03, 0x00, 0x04, 0xFF, 0x39, 0xA0, 0x7B, 0x2D, + 0xD1, 0x05, 0x09, 0x02, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x17, 0x03, 0x00, + 0x97, 0x2D, 0x01, 0x86, 0x03, 0x10, 0x06, 0x3A, 0xC3, 0x27, 0x83, 0x3F, + 0x43, 0x26, 0x27, 0x01, 0x08, 0x0B, 0x38, 0x01, 0x8C, 0x80, 0x00, 0x38, + 0x17, 0x02, 0x00, 0x17, 0x02, 0x00, 0x01, 0x8C, 0x80, 0x00, 0x17, 0x06, + 0x19, 0x27, 0x01, 0x81, 0x7F, 0x17, 0x06, 0x05, 0x01, 0x84, 0x80, 0x00, + 0x38, 0x27, 0x01, 0x83, 0xFE, 0x00, 0x17, 0x06, 0x05, 0x01, 0x88, 0x80, + 0x00, 0x38, 0x03, 0x00, 0x04, 0x09, 0x02, 0x00, 0x01, 0x8C, 0x88, 0x01, + 0x17, 0x03, 0x00, 0x16, 0xC7, 0xB0, 0x27, 0x06, 0x23, 0xC7, 0xB0, 0x27, + 0x15, 0x27, 0x06, 0x18, 0x27, 0x01, 0x82, 0x00, 0x0F, 0x06, 0x05, 0x01, + 0x82, 0x00, 0x04, 0x01, 0x27, 0x03, 0x01, 0x86, 0x02, 0x01, 0xBE, 0x02, + 0x01, 0x12, 0x04, 0x65, 0xA0, 0x13, 0x04, 0x5A, 0xA0, 0x14, 0xA0, 0x02, + 0x00, 0x2B, 0x00, 0x00, 0xC1, 0x27, 0x5C, 0x06, 0x07, 0x26, 0x06, 0x02, + 0x68, 0x29, 0x04, 0x74, 0x00, 0x00, 0xCA, 0x01, 0x03, 0xC8, 0x46, 0x26, + 0x46, 0x00, 0x00, 0xC7, 0xCE, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 0xC7, + 0xB0, 0x27, 0x06, 0x80, 0x50, 0xC9, 0x03, 0x01, 0xC9, 0x03, 0x02, 0x02, + 0x01, 0x01, 0x08, 0x0E, 0x06, 0x16, 0x02, 0x02, 0x01, 0x0F, 0x0C, 0x06, + 0x0D, 0x01, 0x01, 0x02, 0x02, 0x01, 0x10, 0x08, 0x0B, 0x02, 0x00, 0x38, + 0x03, 0x00, 0x04, 0x2A, 0x02, 0x01, 0x01, 0x02, 0x10, 0x02, 0x01, 0x01, + 0x06, 0x0C, 0x17, 0x02, 0x02, 0x01, 0x01, 0x0E, 0x02, 0x02, 0x01, 0x03, + 0x0E, 0x38, 0x17, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x5F, + 0x01, 0x02, 0x0B, 0x02, 0x01, 0x08, 0x0B, 0x38, 0x03, 0x00, 0x04, 0xFF, + 0x2C, 0xA0, 0x02, 0x00, 0x00, 0x00, 0xC7, 0x01, 0x01, 0x0E, 0x05, 0x02, + 0x67, 0x29, 0xC9, 0x01, 0x08, 0x08, 0x84, 0x2F, 0x0E, 0x05, 0x02, 0x67, + 0x29, 0x00, 0x00, 0xC7, 0x8A, 0x2F, 0x05, 0x15, 0x01, 0x01, 0x0E, 0x05, + 0x02, 0x6B, 0x29, 0xC9, 0x01, 0x00, 0x0E, 0x05, 0x02, 0x6B, 0x29, 0x01, + 0x02, 0x8A, 0x40, 0x04, 0x1C, 0x01, 0x19, 0x0E, 0x05, 0x02, 0x6B, 0x29, + 0xC9, 0x01, 0x18, 0x0E, 0x05, 0x02, 0x6B, 0x29, 0x86, 0x01, 0x18, 0xBE, + 0x8B, 0x86, 0x01, 0x18, 0x31, 0x05, 0x02, 0x6B, 0x29, 0x00, 0x00, 0xC7, + 0x06, 0x02, 0x6C, 0x29, 0x00, 0x00, 0x01, 0x02, 0x9C, 0xCA, 0x01, 0x08, + 0x0B, 0xCA, 0x08, 0x00, 0x00, 0x01, 0x03, 0x9C, 0xCA, 0x01, 0x08, 0x0B, + 0xCA, 0x08, 0x01, 0x08, 0x0B, 0xCA, 0x08, 0x00, 0x00, 0x01, 0x01, 0x9C, + 0xCA, 0x00, 0x00, 0x3C, 0x27, 0x5A, 0x05, 0x01, 0x00, 0x26, 0xD8, 0x04, + 0x76, 0x02, 0x03, 0x00, 0x96, 0x2F, 0x03, 0x01, 0x01, 0x00, 0x27, 0x02, + 0x01, 0x0A, 0x06, 0x10, 0x27, 0x01, 0x01, 0x0B, 0x95, 0x08, 0x2D, 0x02, + 0x00, 0x0E, 0x06, 0x01, 0x00, 0x5E, 0x04, 0x6A, 0x26, 0x01, 0x7F, 0x00, + 0x00, 0x01, 0x15, 0x89, 0x40, 0x46, 0x54, 0x26, 0x54, 0x26, 0x2A, 0x00, + 0x00, 0x01, 0x01, 0x46, 0xCC, 0x00, 0x00, 0x46, 0x39, 0x9C, 0x46, 0x27, + 0x06, 0x05, 0xCA, 0x26, 0x5F, 0x04, 0x78, 0x26, 0x00, 0x00, 0x27, 0x01, + 0x81, 0xAC, 0x00, 0x0E, 0x06, 0x04, 0x26, 0x01, 0x7F, 0x00, 0x9F, 0x5B, + 0x00, 0x02, 0x03, 0x00, 0x7B, 0x2D, 0x9F, 0x03, 0x01, 0x02, 0x01, 0x01, + 0x0F, 0x17, 0x02, 0x01, 0x01, 0x04, 0x11, 0x01, 0x0F, 0x17, 0x02, 0x01, + 0x01, 0x08, 0x11, 0x01, 0x0F, 0x17, 0x01, 0x00, 0x39, 0x0E, 0x06, 0x10, + 0x26, 0x01, 0x00, 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x4B, 0x04, 0x01, + 0x4C, 0x04, 0x81, 0x0D, 0x01, 0x01, 0x39, 0x0E, 0x06, 0x10, 0x26, 0x01, + 0x01, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x4B, 0x04, 0x01, 0x4C, 0x04, + 0x80, 0x77, 0x01, 0x02, 0x39, 0x0E, 0x06, 0x10, 0x26, 0x01, 0x01, 0x01, + 0x20, 0x02, 0x00, 0x06, 0x03, 0x4B, 0x04, 0x01, 0x4C, 0x04, 0x80, 0x61, + 0x01, 0x03, 0x39, 0x0E, 0x06, 0x0F, 0x26, 0x26, 0x01, 0x10, 0x02, 0x00, + 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, 0x04, 0x80, 0x4C, 0x01, 0x04, 0x39, + 0x0E, 0x06, 0x0E, 0x26, 0x26, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x49, + 0x04, 0x01, 0x4A, 0x04, 0x38, 0x01, 0x05, 0x39, 0x0E, 0x06, 0x0C, 0x26, + 0x26, 0x02, 0x00, 0x06, 0x03, 0x4D, 0x04, 0x01, 0x4E, 0x04, 0x26, 0x27, + 0x01, 0x09, 0x0F, 0x06, 0x02, 0x6A, 0x29, 0x46, 0x26, 0x27, 0x01, 0x01, + 0x17, 0x01, 0x04, 0x0B, 0x01, 0x10, 0x08, 0x46, 0x01, 0x08, 0x17, 0x01, + 0x10, 0x46, 0x09, 0x02, 0x00, 0x06, 0x03, 0x47, 0x04, 0x01, 0x48, 0x00, + 0x26, 0x00, 0x00, 0x9F, 0x01, 0x0C, 0x11, 0x01, 0x02, 0x0F, 0x00, 0x00, + 0x9F, 0x01, 0x0C, 0x11, 0x27, 0x5D, 0x46, 0x01, 0x03, 0x0A, 0x17, 0x00, + 0x00, 0x9F, 0x01, 0x0C, 0x11, 0x01, 0x01, 0x0E, 0x00, 0x00, 0x9F, 0x01, + 0x0C, 0x11, 0x5C, 0x00, 0x00, 0x9F, 0x01, 0x81, 0x70, 0x17, 0x01, 0x20, + 0x0D, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x77, 0x2F, 0x27, 0x06, 0x22, 0x01, + 0x01, 0x39, 0x0E, 0x06, 0x06, 0x26, 0x01, 0x00, 0xA3, 0x04, 0x14, 0x01, + 0x02, 0x39, 0x0E, 0x06, 0x0D, 0x26, 0x79, 0x2F, 0x01, 0x01, 0x0E, 0x06, + 0x03, 0x01, 0x10, 0x38, 0x04, 0x01, 0x26, 0x04, 0x01, 0x26, 0x7D, 0x2F, + 0x05, 0x33, 0x30, 0x06, 0x30, 0x88, 0x2F, 0x01, 0x14, 0x39, 0x0E, 0x06, + 0x06, 0x26, 0x01, 0x02, 0x38, 0x04, 0x22, 0x01, 0x15, 0x39, 0x0E, 0x06, + 0x09, 0x26, 0xB3, 0x06, 0x03, 0x01, 0x7F, 0xA3, 0x04, 0x13, 0x01, 0x16, + 0x39, 0x0E, 0x06, 0x06, 0x26, 0x01, 0x01, 0x38, 0x04, 0x07, 0x26, 0x01, + 0x04, 0x38, 0x01, 0x00, 0x26, 0x1A, 0x06, 0x03, 0x01, 0x08, 0x38, 0x00, + 0x00, 0x1B, 0x27, 0x05, 0x13, 0x30, 0x06, 0x10, 0x88, 0x2F, 0x01, 0x15, + 0x0E, 0x06, 0x08, 0x26, 0xB3, 0x01, 0x00, 0x79, 0x40, 0x04, 0x01, 0x21, + 0x00, 0x00, 0xD6, 0x01, 0x07, 0x17, 0x01, 0x01, 0x0F, 0x06, 0x02, 0x74, + 0x29, 0x00, 0x01, 0x03, 0x00, 0x2A, 0x1A, 0x06, 0x05, 0x02, 0x00, 0x89, + 0x40, 0x00, 0xD6, 0x26, 0x04, 0x74, 0x00, 0x01, 0x14, 0xD9, 0x01, 0x01, + 0xE6, 0x2A, 0x27, 0x01, 0x00, 0xD0, 0x01, 0x16, 0xD9, 0xDF, 0x2A, 0x00, + 0x00, 0x01, 0x0B, 0xE6, 0x50, 0x27, 0x27, 0x01, 0x03, 0x08, 0xE5, 0xE5, + 0x18, 0x27, 0x5A, 0x06, 0x02, 0x26, 0x00, 0xE5, 0x1D, 0x27, 0x06, 0x05, + 0x86, 0x46, 0xE0, 0x04, 0x77, 0x26, 0x04, 0x6C, 0x00, 0x22, 0x01, 0x0F, + 0xE6, 0x27, 0x97, 0x2D, 0x01, 0x86, 0x03, 0x10, 0x06, 0x0C, 0x01, 0x04, + 0x08, 0xE5, 0x82, 0x2F, 0xE6, 0x7A, 0x2F, 0xE6, 0x04, 0x02, 0x60, 0xE5, + 0x27, 0xE4, 0x86, 0x46, 0xE0, 0x00, 0x02, 0xA9, 0xAC, 0x08, 0xA7, 0x08, + 0xAB, 0x08, 0xAD, 0x08, 0xA8, 0x08, 0x28, 0x08, 0xAA, 0x08, 0x03, 0x00, + 0x01, 0x01, 0xE6, 0x01, 0x27, 0x90, 0x2F, 0x08, 0x96, 0x2F, 0x01, 0x01, + 0x0B, 0x08, 0x02, 0x00, 0x06, 0x04, 0x60, 0x02, 0x00, 0x08, 0x85, 0x2D, + 0x39, 0x09, 0x27, 0x5D, 0x06, 0x24, 0x02, 0x00, 0x05, 0x04, 0x46, 0x60, + 0x46, 0x61, 0x01, 0x04, 0x09, 0x27, 0x5A, 0x06, 0x03, 0x26, 0x01, 0x00, + 0x27, 0x01, 0x04, 0x08, 0x02, 0x00, 0x08, 0x03, 0x00, 0x46, 0x01, 0x04, + 0x08, 0x39, 0x08, 0x46, 0x04, 0x03, 0x26, 0x01, 0x7F, 0x03, 0x01, 0xE5, + 0x99, 0x2D, 0xE4, 0x7C, 0x01, 0x04, 0x19, 0x7C, 0x01, 0x04, 0x08, 0x01, + 0x1C, 0x33, 0x7C, 0x01, 0x20, 0xE0, 0x8F, 0x90, 0x2F, 0xE2, 0x96, 0x2F, + 0x27, 0x01, 0x01, 0x0B, 0xE4, 0x95, 0x46, 0x27, 0x06, 0x0F, 0x5F, 0x39, + 0x2D, 0x27, 0xCF, 0x05, 0x02, 0x64, 0x29, 0xE4, 0x46, 0x60, 0x46, 0x04, + 0x6E, 0x62, 0x01, 0x01, 0xE6, 0x01, 0x00, 0xE6, 0x02, 0x00, 0x06, 0x81, + 0x6A, 0x02, 0x00, 0xE4, 0xA9, 0x06, 0x0E, 0x01, 0x83, 0xFE, 0x01, 0xE4, + 0x8B, 0xA9, 0x01, 0x04, 0x09, 0x27, 0xE4, 0x5F, 0xE2, 0xAC, 0x06, 0x16, + 0x01, 0x00, 0xE4, 0x8D, 0xAC, 0x01, 0x04, 0x09, 0x27, 0xE4, 0x01, 0x02, + 0x09, 0x27, 0xE4, 0x01, 0x00, 0xE6, 0x01, 0x03, 0x09, 0xE1, 0xA7, 0x06, + 0x0C, 0x01, 0x01, 0xE4, 0x01, 0x01, 0xE4, 0x84, 0x2F, 0x01, 0x08, 0x09, + 0xE6, 0xAB, 0x06, 0x19, 0x01, 0x0D, 0xE4, 0xAB, 0x01, 0x04, 0x09, 0x27, + 0xE4, 0x01, 0x02, 0x09, 0xE4, 0x44, 0x06, 0x03, 0x01, 0x03, 0xE3, 0x45, + 0x06, 0x03, 0x01, 0x01, 0xE3, 0xAD, 0x27, 0x06, 0x36, 0x01, 0x0A, 0xE4, + 0x01, 0x04, 0x09, 0x27, 0xE4, 0x61, 0xE4, 0x42, 0x01, 0x00, 0x27, 0x01, + 0x82, 0x80, 0x80, 0x80, 0x00, 0x17, 0x06, 0x0A, 0x01, 0xFD, 0xFF, 0xFF, + 0xFF, 0x7F, 0x17, 0x01, 0x1D, 0xE4, 0x27, 0x01, 0x20, 0x0A, 0x06, 0x0C, + 0xA5, 0x11, 0x01, 0x01, 0x17, 0x06, 0x02, 0x27, 0xE4, 0x5E, 0x04, 0x6E, + 0x62, 0x04, 0x01, 0x26, 0xA8, 0x06, 0x0A, 0x01, 0x0B, 0xE4, 0x01, 0x02, + 0xE4, 0x01, 0x82, 0x00, 0xE4, 0x28, 0x27, 0x06, 0x1F, 0x01, 0x10, 0xE4, + 0x01, 0x04, 0x09, 0x27, 0xE4, 0x61, 0xE4, 0x87, 0x2D, 0x01, 0x00, 0xA5, + 0x0F, 0x06, 0x0A, 0x27, 0x1E, 0x27, 0xE6, 0x86, 0x46, 0xE0, 0x5E, 0x04, + 0x72, 0x62, 0x04, 0x01, 0x26, 0x01, 0x23, 0xE4, 0x92, 0x2D, 0x27, 0xE4, + 0x27, 0x06, 0x05, 0x91, 0x46, 0xE0, 0x04, 0x01, 0x26, 0x02, 0x01, 0x5A, + 0x05, 0x11, 0x01, 0x15, 0xE4, 0x02, 0x01, 0x27, 0xE4, 0x27, 0x06, 0x06, + 0x5F, 0x01, 0x00, 0xE6, 0x04, 0x77, 0x26, 0x00, 0x00, 0x01, 0x10, 0xE6, + 0x7B, 0x2D, 0x27, 0xD4, 0x06, 0x0C, 0xB1, 0x24, 0x27, 0x60, 0xE5, 0x27, + 0xE4, 0x86, 0x46, 0xE0, 0x04, 0x0D, 0x27, 0xD2, 0x46, 0xB1, 0x23, 0x27, + 0x5E, 0xE5, 0x27, 0xE6, 0x86, 0x46, 0xE0, 0x00, 0x00, 0xA1, 0x01, 0x14, + 0xE6, 0x01, 0x0C, 0xE5, 0x86, 0x01, 0x0C, 0xE0, 0x00, 0x00, 0x53, 0x27, + 0x01, 0x00, 0x0E, 0x06, 0x02, 0x62, 0x00, 0xD6, 0x26, 0x04, 0x73, 0x00, + 0x27, 0xE4, 0xE0, 0x00, 0x00, 0x27, 0xE6, 0xE0, 0x00, 0x01, 0x03, 0x00, + 0x43, 0x26, 0x27, 0x01, 0x10, 0x17, 0x06, 0x06, 0x01, 0x04, 0xE6, 0x02, + 0x00, 0xE6, 0x27, 0x01, 0x08, 0x17, 0x06, 0x06, 0x01, 0x03, 0xE6, 0x02, + 0x00, 0xE6, 0x27, 0x01, 0x20, 0x17, 0x06, 0x06, 0x01, 0x05, 0xE6, 0x02, + 0x00, 0xE6, 0x27, 0x01, 0x80, 0x40, 0x17, 0x06, 0x06, 0x01, 0x06, 0xE6, + 0x02, 0x00, 0xE6, 0x01, 0x04, 0x17, 0x06, 0x06, 0x01, 0x02, 0xE6, 0x02, + 0x00, 0xE6, 0x00, 0x00, 0x27, 0x01, 0x08, 0x51, 0xE6, 0xE6, 0x00, 0x00, + 0x27, 0x01, 0x10, 0x51, 0xE6, 0xE4, 0x00, 0x00, 0x27, 0x54, 0x06, 0x02, + 0x26, 0x00, 0xD6, 0x26, 0x04, 0x76 +}; + +static const uint16_t t0_caddr[] = { + 0, + 5, + 10, + 15, + 20, + 25, + 30, + 35, + 40, + 44, + 48, + 52, + 56, + 60, + 64, + 68, + 72, + 76, + 80, + 84, + 88, + 92, + 96, + 100, + 104, + 108, + 112, + 116, + 120, + 124, + 129, + 134, + 139, + 144, + 149, + 154, + 159, + 164, + 169, + 174, + 179, + 184, + 189, + 194, + 199, + 204, + 209, + 214, + 219, + 224, + 229, + 234, + 239, + 244, + 249, + 254, + 259, + 264, + 269, + 274, + 279, + 284, + 289, + 294, + 299, + 304, + 309, + 318, + 331, + 335, + 360, + 366, + 385, + 396, + 437, + 625, + 629, + 694, + 709, + 720, + 738, + 745, + 774, + 784, + 820, + 830, + 908, + 922, + 928, + 987, + 1006, + 1041, + 1090, + 1139, + 1215, + 1242, + 1273, + 1284, + 1330, + 1711, + 1858, + 1882, + 2098, + 2112, + 2121, + 2125, + 2220, + 2241, + 2297, + 2304, + 2315, + 2331, + 2337, + 2348, + 2383, + 2395, + 2401, + 2416, + 2432, + 2625, + 2634, + 2647, + 2656, + 2663, + 2673, + 2779, + 2804, + 2817, + 2833, + 2851, + 2883, + 2917, + 3303, + 3339, + 3352, + 3366, + 3371, + 3376, + 3442, + 3450, + 3458 +}; + +#define T0_INTERPRETED 90 + +#define T0_ENTER(ip, rp, slot) do { \ + const unsigned char *t0_newip; \ + uint32_t t0_lnum; \ + t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ + t0_lnum = t0_parse7E_unsigned(&t0_newip); \ + (rp) += t0_lnum; \ + *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ + (ip) = t0_newip; \ + } while (0) + +#define T0_DEFENTRY(name, slot) \ +void \ +name(void *ctx) \ +{ \ + t0_context *t0ctx = ctx; \ + t0ctx->ip = &t0_codeblock[0]; \ + T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ +} + +T0_DEFENTRY(br_ssl_hs_client_init_main, 175) + +#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) + +void +br_ssl_hs_client_run(void *t0ctx) +{ + uint32_t *dp, *rp; + const unsigned char *ip; + +#define T0_LOCAL(x) (*(rp - 2 - (x))) +#define T0_POP() (*-- dp) +#define T0_POPi() (*(int32_t *)(-- dp)) +#define T0_PEEK(x) (*(dp - 1 - (x))) +#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) +#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) +#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) +#define T0_RPOP() (*-- rp) +#define T0_RPOPi() (*(int32_t *)(-- rp)) +#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) +#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) +#define T0_ROLL(x) do { \ + size_t t0len = (size_t)(x); \ + uint32_t t0tmp = *(dp - 1 - t0len); \ + memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_SWAP() do { \ + uint32_t t0tmp = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_ROT() do { \ + uint32_t t0tmp = *(dp - 3); \ + *(dp - 3) = *(dp - 2); \ + *(dp - 2) = *(dp - 1); \ + *(dp - 1) = t0tmp; \ +} while (0) +#define T0_NROT() do { \ + uint32_t t0tmp = *(dp - 1); \ + *(dp - 1) = *(dp - 2); \ + *(dp - 2) = *(dp - 3); \ + *(dp - 3) = t0tmp; \ +} while (0) +#define T0_PICK(x) do { \ + uint32_t t0depth = (x); \ + T0_PUSH(T0_PEEK(t0depth)); \ +} while (0) +#define T0_CO() do { \ + goto t0_exit; \ +} while (0) +#define T0_RET() goto t0_next + + dp = ((t0_context *)t0ctx)->dp; + rp = ((t0_context *)t0ctx)->rp; + ip = ((t0_context *)t0ctx)->ip; + goto t0_next; + for (;;) { + uint32_t t0x; + + t0_next: + t0x = T0_NEXT(&ip); + if (t0x < T0_INTERPRETED) { + switch (t0x) { + int32_t t0off; + + case 0: /* ret */ + t0x = T0_RPOP(); + rp -= (t0x >> 16); + t0x &= 0xFFFF; + if (t0x == 0) { + ip = NULL; + goto t0_exit; + } + ip = &t0_codeblock[t0x]; + break; + case 1: /* literal constant */ + T0_PUSHi(t0_parse7E_signed(&ip)); + break; + case 2: /* read local */ + T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); + break; + case 3: /* write local */ + T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); + break; + case 4: /* jump */ + t0off = t0_parse7E_signed(&ip); + ip += t0off; + break; + case 5: /* jump if */ + t0off = t0_parse7E_signed(&ip); + if (T0_POP()) { + ip += t0off; + } + break; + case 6: /* jump if not */ + t0off = t0_parse7E_signed(&ip); + if (!T0_POP()) { + ip += t0off; + } + break; + case 7: { + /* * */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a * b); + + } + break; + case 8: { + /* + */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a + b); + + } + break; + case 9: { + /* - */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a - b); + + } + break; + case 10: { + /* < */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a < b)); + + } + break; + case 11: { + /* << */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x << c); + + } + break; + case 12: { + /* <= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a <= b)); + + } + break; + case 13: { + /* <> */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a != b)); + + } + break; + case 14: { + /* = */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(-(uint32_t)(a == b)); + + } + break; + case 15: { + /* > */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a > b)); + + } + break; + case 16: { + /* >= */ + + int32_t b = T0_POPi(); + int32_t a = T0_POPi(); + T0_PUSH(-(uint32_t)(a >= b)); + + } + break; + case 17: { + /* >> */ + + int c = (int)T0_POPi(); + int32_t x = T0_POPi(); + T0_PUSHi(x >> c); + + } + break; + case 18: { + /* anchor-dn-append-name */ + + size_t len; + + len = T0_POP(); + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->append_name( + CTX->client_auth_vtable, ENG->pad, len); + } + + } + break; + case 19: { + /* anchor-dn-end-name */ + + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->end_name( + CTX->client_auth_vtable); + } + + } + break; + case 20: { + /* anchor-dn-end-name-list */ + + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->end_name_list( + CTX->client_auth_vtable); + } + + } + break; + case 21: { + /* anchor-dn-start-name */ + + size_t len; + + len = T0_POP(); + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->start_name( + CTX->client_auth_vtable, len); + } + + } + break; + case 22: { + /* anchor-dn-start-name-list */ + + if (CTX->client_auth_vtable != NULL) { + (*CTX->client_auth_vtable)->start_name_list( + CTX->client_auth_vtable); + } + + } + break; + case 23: { + /* and */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a & b); + + } + break; + case 24: { + /* begin-cert */ + + if (ENG->chain_len == 0) { + T0_PUSHi(-1); + } else { + ENG->cert_cur = ENG->chain->data; + ENG->cert_len = ENG->chain->data_len; + ENG->chain ++; + ENG->chain_len --; + T0_PUSH(ENG->cert_len); + } + + } + break; + case 25: { + /* bzero */ + + size_t len = (size_t)T0_POP(); + void *addr = (unsigned char *)ENG + (size_t)T0_POP(); + memset(addr, 0, len); + + } + break; + case 26: { + /* can-output? */ + + T0_PUSHi(-(ENG->hlen_out > 0)); + + } + break; + case 27: { + /* co */ + T0_CO(); + } + break; + case 28: { + /* compute-Finished-inner */ + + int prf_id = T0_POP(); + int from_client = T0_POPi(); + unsigned char tmp[48]; + br_tls_prf_seed_chunk seed; + + br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id); + seed.data = tmp; + if (ENG->session.version >= BR_TLS12) { + seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp); + } else { + br_multihash_out(&ENG->mhash, br_md5_ID, tmp); + br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16); + seed.len = 36; + } + prf(ENG->pad, 12, ENG->session.master_secret, + sizeof ENG->session.master_secret, + from_client ? "client finished" : "server finished", + 1, &seed); + + } + break; + case 29: { + /* copy-cert-chunk */ + + size_t clen; + + clen = ENG->cert_len; + if (clen > sizeof ENG->pad) { + clen = sizeof ENG->pad; + } + memcpy(ENG->pad, ENG->cert_cur, clen); + ENG->cert_cur += clen; + ENG->cert_len -= clen; + T0_PUSH(clen); + + } + break; + case 30: { + /* copy-protocol-name */ + + size_t idx = T0_POP(); + size_t len = strlen(ENG->protocol_names[idx]); + memcpy(ENG->pad, ENG->protocol_names[idx], len); + T0_PUSH(len); + + } + break; + case 31: { + /* data-get8 */ + + size_t addr = T0_POP(); + T0_PUSH(t0_datablock[addr]); + + } + break; + case 32: { + /* debug-session-ticket */ + + extern void __stdcall OutputDebugStringA(const char *); + extern int sprintf(char *, const char *, ...); + char buf[80]; + size_t len = T0_POP(); + sprintf(buf, "BearSSL: NewSessionTicket received (%u bytes)\r\n", + (unsigned)len); + OutputDebugStringA(buf); + + } + break; + case 33: { + /* discard-input */ + + ENG->hlen_in = 0; + + } + break; + case 34: { + /* do-client-sign */ + + size_t sig_len; + + sig_len = make_client_sign(CTX); + if (sig_len == 0) { + br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM); + T0_CO(); + } + T0_PUSH(sig_len); + + } + break; + case 35: { + /* do-ecdh */ + + unsigned prf_id = T0_POP(); + unsigned ecdhe = T0_POP(); + int x; + + x = make_pms_ecdh(CTX, ecdhe, prf_id); + if (x < 0) { + br_ssl_engine_fail(ENG, -x); + T0_CO(); + } else { + T0_PUSH(x); + } + + } + break; + case 36: { + /* do-rsa-encrypt */ + + int x; + + x = make_pms_rsa(CTX, T0_POP()); + if (x < 0) { + br_ssl_engine_fail(ENG, -x); + T0_CO(); + } else { + T0_PUSH(x); + } + + } + break; + case 37: { + /* do-static-ecdh */ + + unsigned prf_id = T0_POP(); + + if (make_pms_static_ecdh(CTX, prf_id) < 0) { + br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM); + T0_CO(); + } + + } + break; + case 38: { + /* drop */ + (void)T0_POP(); + } + break; + case 39: { + /* dup */ + T0_PUSH(T0_PEEK(0)); + } + break; + case 40: { + /* ext-ALPN-length */ + + size_t u, len; + + if (ENG->protocol_names_num == 0) { + T0_PUSH(0); + T0_RET(); + } + len = 6; + for (u = 0; u < ENG->protocol_names_num; u ++) { + len += 1 + strlen(ENG->protocol_names[u]); + } + T0_PUSH(len); + + } + break; + case 41: { + /* fail */ + + br_ssl_engine_fail(ENG, (int)T0_POPi()); + T0_CO(); + + } + break; + case 42: { + /* flush-record */ + + br_ssl_engine_flush_record(ENG); + + } + break; + case 43: { + /* get-client-chain */ + + uint32_t auth_types; + + auth_types = T0_POP(); + if (CTX->client_auth_vtable != NULL) { + br_ssl_client_certificate ux; + + (*CTX->client_auth_vtable)->choose(CTX->client_auth_vtable, + CTX, auth_types, &ux); + CTX->auth_type = (unsigned char)ux.auth_type; + CTX->hash_id = (unsigned char)ux.hash_id; + ENG->chain = ux.chain; + ENG->chain_len = ux.chain_len; + } else { + CTX->hash_id = 0; + ENG->chain_len = 0; + } + + } + break; + case 44: { + /* get-key-type-usages */ + + const br_x509_class *xc; + const br_x509_pkey *pk; + unsigned usages; + + xc = *(ENG->x509ctx); + pk = xc->get_pkey(ENG->x509ctx, &usages); + if (pk == NULL) { + T0_PUSH(0); + } else { + T0_PUSH(pk->key_type | usages); + } + + } + break; + case 45: { + /* get16 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr)); + + } + break; + case 46: { + /* get32 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr)); + + } + break; + case 47: { + /* get8 */ + + size_t addr = (size_t)T0_POP(); + T0_PUSH(*((unsigned char *)ENG + addr)); + + } + break; + case 48: { + /* has-input? */ + + T0_PUSHi(-(ENG->hlen_in != 0)); + + } + break; + case 49: { + /* memcmp */ + + size_t len = (size_t)T0_POP(); + void *addr2 = (unsigned char *)ENG + (size_t)T0_POP(); + void *addr1 = (unsigned char *)ENG + (size_t)T0_POP(); + int x = memcmp(addr1, addr2, len); + T0_PUSH((uint32_t)-(x == 0)); + + } + break; + case 50: { + /* memcpy */ + + size_t len = (size_t)T0_POP(); + void *src = (unsigned char *)ENG + (size_t)T0_POP(); + void *dst = (unsigned char *)ENG + (size_t)T0_POP(); + memcpy(dst, src, len); + + } + break; + case 51: { + /* mkrand */ + + size_t len = (size_t)T0_POP(); + void *addr = (unsigned char *)ENG + (size_t)T0_POP(); + br_hmac_drbg_generate(&ENG->rng, addr, len); + + } + break; + case 52: { + /* more-incoming-bytes? */ + + T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG)); + + } + break; + case 53: { + /* multihash-init */ + + br_multihash_init(&ENG->mhash); + + } + break; + case 54: { + /* neg */ + + uint32_t a = T0_POP(); + T0_PUSH(-a); + + } + break; + case 55: { + /* not */ + + uint32_t a = T0_POP(); + T0_PUSH(~a); + + } + break; + case 56: { + /* or */ + + uint32_t b = T0_POP(); + uint32_t a = T0_POP(); + T0_PUSH(a | b); + + } + break; + case 57: { + /* over */ + T0_PUSH(T0_PEEK(1)); + } + break; + case 58: { + /* peek-hs-msg-type */ + + if (ENG->hlen_in > 0) { + T0_PUSH(*ENG->hbuf_in); + } else { + T0_PUSHi(-1); + } + + } + break; + case 59: { + /* read-chunk-native */ + + size_t clen = ENG->hlen_in; + if (clen > 0) { + uint32_t addr, len; + + len = T0_POP(); + addr = T0_POP(); + if ((size_t)len < clen) { + clen = (size_t)len; + } + memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); + if (ENG->record_type_in == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen); + } + T0_PUSH(addr + (uint32_t)clen); + T0_PUSH(len - (uint32_t)clen); + ENG->hbuf_in += clen; + ENG->hlen_in -= clen; + } + + } + break; + case 60: { + /* read8-native */ + + if (ENG->hlen_in > 0) { + unsigned char x; + + x = *ENG->hbuf_in ++; + if (ENG->record_type_in == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, &x, 1); + } + T0_PUSH(x); + ENG->hlen_in --; + } else { + T0_PUSHi(-1); + } + + } + break; + case 61: { + /* set-server-curve */ + + const br_x509_class *xc; + const br_x509_pkey *pk; + + xc = *(ENG->x509ctx); + pk = xc->get_pkey(ENG->x509ctx, NULL); + CTX->server_curve = + (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0; + + } + break; + case 62: { + /* set16 */ + + size_t addr = (size_t)T0_POP(); + *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP(); + + } + break; + case 63: { + /* set32 */ + + size_t addr = (size_t)T0_POP(); + *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP(); + + } + break; + case 64: { + /* set8 */ + + size_t addr = (size_t)T0_POP(); + *((unsigned char *)ENG + addr) = (unsigned char)T0_POP(); + + } + break; + case 65: { + /* strlen */ + + void *str = (unsigned char *)ENG + (size_t)T0_POP(); + T0_PUSH((uint32_t)strlen(str)); + + } + break; + case 66: { + /* supported-curves */ + + uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves; + T0_PUSH(x); + + } + break; + case 67: { + /* supported-hash-functions */ + + int i; + unsigned x, num; + + x = 0; + num = 0; + for (i = br_sha1_ID; i <= br_sha512_ID; i ++) { + if (br_multihash_getimpl(&ENG->mhash, i)) { + x |= 1U << i; + num ++; + } + } + T0_PUSH(x); + T0_PUSH(num); + + } + break; + case 68: { + /* supports-ecdsa? */ + + T0_PUSHi(-(ENG->iecdsa != 0)); + + } + break; + case 69: { + /* supports-rsa-sign? */ + + T0_PUSHi(-(ENG->irsavrfy != 0)); + + } + break; + case 70: { + /* swap */ + T0_SWAP(); + } + break; + case 71: { + /* switch-aesccm-in */ + + int is_client, prf_id; + unsigned cipher_key_len, tag_len; + + tag_len = T0_POP(); + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id, + ENG->iaes_ctrcbc, cipher_key_len, tag_len); + + } + break; + case 72: { + /* switch-aesccm-out */ + + int is_client, prf_id; + unsigned cipher_key_len, tag_len; + + tag_len = T0_POP(); + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id, + ENG->iaes_ctrcbc, cipher_key_len, tag_len); + + } + break; + case 73: { + /* switch-aesgcm-in */ + + int is_client, prf_id; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id, + ENG->iaes_ctr, cipher_key_len); + + } + break; + case 74: { + /* switch-aesgcm-out */ + + int is_client, prf_id; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id, + ENG->iaes_ctr, cipher_key_len); + + } + break; + case 75: { + /* switch-cbc-in */ + + int is_client, prf_id, mac_id, aes; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + aes = T0_POP(); + mac_id = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id, + aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len); + + } + break; + case 76: { + /* switch-cbc-out */ + + int is_client, prf_id, mac_id, aes; + unsigned cipher_key_len; + + cipher_key_len = T0_POP(); + aes = T0_POP(); + mac_id = T0_POP(); + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id, + aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len); + + } + break; + case 77: { + /* switch-chapol-in */ + + int is_client, prf_id; + + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id); + + } + break; + case 78: { + /* switch-chapol-out */ + + int is_client, prf_id; + + prf_id = T0_POP(); + is_client = T0_POP(); + br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id); + + } + break; + case 79: { + /* test-protocol-name */ + + size_t len = T0_POP(); + size_t u; + + for (u = 0; u < ENG->protocol_names_num; u ++) { + const char *name; + + name = ENG->protocol_names[u]; + if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) { + T0_PUSH(u); + T0_RET(); + } + } + T0_PUSHi(-1); + + } + break; + case 80: { + /* total-chain-length */ + + size_t u; + uint32_t total; + + total = 0; + for (u = 0; u < ENG->chain_len; u ++) { + total += 3 + (uint32_t)ENG->chain[u].data_len; + } + T0_PUSH(total); + + } + break; + case 81: { + /* u>> */ + + int c = (int)T0_POPi(); + uint32_t x = T0_POP(); + T0_PUSH(x >> c); + + } + break; + case 82: { + /* verify-SKE-sig */ + + size_t sig_len = T0_POP(); + int use_rsa = T0_POPi(); + int hash = T0_POPi(); + + T0_PUSH(verify_SKE_sig(CTX, hash, use_rsa, sig_len)); + + } + break; + case 83: { + /* write-blob-chunk */ + + size_t clen = ENG->hlen_out; + if (clen > 0) { + uint32_t addr, len; + + len = T0_POP(); + addr = T0_POP(); + if ((size_t)len < clen) { + clen = (size_t)len; + } + memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); + if (ENG->record_type_out == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen); + } + T0_PUSH(addr + (uint32_t)clen); + T0_PUSH(len - (uint32_t)clen); + ENG->hbuf_out += clen; + ENG->hlen_out -= clen; + } + + } + break; + case 84: { + /* write8-native */ + + unsigned char x; + + x = (unsigned char)T0_POP(); + if (ENG->hlen_out > 0) { + if (ENG->record_type_out == BR_SSL_HANDSHAKE) { + br_multihash_update(&ENG->mhash, &x, 1); + } + *ENG->hbuf_out ++ = x; + ENG->hlen_out --; + T0_PUSHi(-1); + } else { + T0_PUSHi(0); + } + + } + break; + case 85: { + /* x509-append */ + + const br_x509_class *xc; + size_t len; + + xc = *(ENG->x509ctx); + len = T0_POP(); + xc->append(ENG->x509ctx, ENG->pad, len); + + } + break; + case 86: { + /* x509-end-cert */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + xc->end_cert(ENG->x509ctx); + + } + break; + case 87: { + /* x509-end-chain */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + T0_PUSH(xc->end_chain(ENG->x509ctx)); + + } + break; + case 88: { + /* x509-start-cert */ + + const br_x509_class *xc; + + xc = *(ENG->x509ctx); + xc->start_cert(ENG->x509ctx, T0_POP()); + + } + break; + case 89: { + /* x509-start-chain */ + + const br_x509_class *xc; + uint32_t bc; + + bc = T0_POP(); + xc = *(ENG->x509ctx); + xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL); + + } + break; + } + + } else { + T0_ENTER(ip, rp, t0x); + } + } +t0_exit: + ((t0_context *)t0ctx)->dp = dp; + ((t0_context *)t0ctx)->rp = rp; + ((t0_context *)t0ctx)->ip = ip; +} diff --git a/libcurl/lib/vtls/ssl_hs_client.t0 b/libcurl/lib/vtls/ssl_hs_client.t0 new file mode 100644 index 0000000..69a1d94 --- /dev/null +++ b/libcurl/lib/vtls/ssl_hs_client.t0 @@ -0,0 +1,1398 @@ +\ Copyright (c) 2016 Thomas Pornin +\ +\ 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. + +\ ---------------------------------------------------------------------- +\ Handshake processing code, for the client. +\ The common T0 code (ssl_hs_common.t0) shall be read first. + +preamble { + +/* + * This macro evaluates to a pointer to the client context, under that + * specific name. It must be noted that since the engine context is the + * first field of the br_ssl_client_context structure ('eng'), then + * pointers values of both types are interchangeable, modulo an + * appropriate cast. This also means that "addresses" computed as offsets + * within the structure work for both kinds of context. + */ +#define CTX ((br_ssl_client_context *)ENG) + +/* + * Generate the pre-master secret for RSA key exchange, and encrypt it + * with the server's public key. Returned value is either the encrypted + * data length (in bytes), or -x on error, with 'x' being an error code. + * + * This code assumes that the public key has been already verified (it + * was properly obtained by the X.509 engine, and it has the right type, + * i.e. it is of type RSA and suitable for encryption). + */ +static int +make_pms_rsa(br_ssl_client_context *ctx, int prf_id) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + const unsigned char *n; + unsigned char *pms; + size_t nlen, u; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + + /* + * Compute actual RSA key length, in case there are leading zeros. + */ + n = pk->key.rsa.n; + nlen = pk->key.rsa.nlen; + while (nlen > 0 && *n == 0) { + n ++; + nlen --; + } + + /* + * We need at least 59 bytes (48 bytes for pre-master secret, and + * 11 bytes for the PKCS#1 type 2 padding). Note that the X.509 + * minimal engine normally blocks RSA keys shorter than 128 bytes, + * so this is mostly for public keys provided explicitly by the + * caller. + */ + if (nlen < 59) { + return -BR_ERR_X509_WEAK_PUBLIC_KEY; + } + if (nlen > sizeof ctx->eng.pad) { + return -BR_ERR_LIMIT_EXCEEDED; + } + + /* + * Make PMS. + */ + pms = ctx->eng.pad + nlen - 48; + br_enc16be(pms, ctx->eng.version_max); + br_hmac_drbg_generate(&ctx->eng.rng, pms + 2, 46); + br_ssl_engine_compute_master(&ctx->eng, prf_id, pms, 48); + + /* + * Apply PKCS#1 type 2 padding. + */ + ctx->eng.pad[0] = 0x00; + ctx->eng.pad[1] = 0x02; + ctx->eng.pad[nlen - 49] = 0x00; + br_hmac_drbg_generate(&ctx->eng.rng, ctx->eng.pad + 2, nlen - 51); + for (u = 2; u < nlen - 49; u ++) { + while (ctx->eng.pad[u] == 0) { + br_hmac_drbg_generate(&ctx->eng.rng, + &ctx->eng.pad[u], 1); + } + } + + /* + * Compute RSA encryption. + */ + if (!ctx->irsapub(ctx->eng.pad, nlen, &pk->key.rsa)) { + return -BR_ERR_LIMIT_EXCEEDED; + } + return (int)nlen; +} + +/* + * OID for hash functions in RSA signatures. + */ +static const unsigned char *HASH_OID[] = { + BR_HASH_OID_SHA1, + BR_HASH_OID_SHA224, + BR_HASH_OID_SHA256, + BR_HASH_OID_SHA384, + BR_HASH_OID_SHA512 +}; + +/* + * 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 +verify_SKE_sig(br_ssl_client_context *ctx, + int hash, int use_rsa, size_t sig_len) +{ + const br_x509_class **xc; + const br_x509_pkey *pk; + br_multihash_context mhc; + unsigned char hv[64], head[4]; + size_t hv_len; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + br_multihash_zero(&mhc); + br_multihash_copyimpl(&mhc, &ctx->eng.mhash); + br_multihash_init(&mhc); + br_multihash_update(&mhc, + ctx->eng.client_random, sizeof ctx->eng.client_random); + br_multihash_update(&mhc, + ctx->eng.server_random, sizeof ctx->eng.server_random); + head[0] = 3; + head[1] = 0; + head[2] = ctx->eng.ecdhe_curve; + head[3] = ctx->eng.ecdhe_point_len; + br_multihash_update(&mhc, head, sizeof head); + br_multihash_update(&mhc, + ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len); + if (hash) { + hv_len = br_multihash_out(&mhc, hash, hv); + if (hv_len == 0) { + return BR_ERR_INVALID_ALGORITHM; + } + } else { + if (!br_multihash_out(&mhc, br_md5_ID, hv) + || !br_multihash_out(&mhc, br_sha1_ID, hv + 16)) + { + return BR_ERR_INVALID_ALGORITHM; + } + hv_len = 36; + } + if (use_rsa) { + unsigned char tmp[64]; + const unsigned char *hash_oid; + + if (hash) { + hash_oid = HASH_OID[hash - 2]; + } else { + hash_oid = NULL; + } + 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->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec, + ctx->eng.pad, sig_len)) + { + return BR_ERR_BAD_SIGNATURE; + } + } + return 0; +} + +/* + * Perform client-side ECDH (or ECDHE). The point that should be sent to + * the server is written in the pad; returned value is either the point + * length (in bytes), or -x on error, with 'x' being an error code. + * + * The point _from_ the server is taken from ecdhe_point[] if 'ecdhe' + * is non-zero, or from the X.509 engine context if 'ecdhe' is zero + * (for static ECDH). + */ +static int +make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) +{ + int curve; + unsigned char key[66], point[133]; + const unsigned char *order, *point_src; + size_t glen, olen, point_len, xoff, xlen; + unsigned char mask; + + if (ecdhe) { + curve = ctx->eng.ecdhe_curve; + point_src = ctx->eng.ecdhe_point; + point_len = ctx->eng.ecdhe_point_len; + } else { + const br_x509_class **xc; + const br_x509_pkey *pk; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + curve = pk->key.ec.curve; + point_src = pk->key.ec.q; + point_len = pk->key.ec.qlen; + } + if ((ctx->eng.iec->supported_curves & ((uint32_t)1 << curve)) == 0) { + return -BR_ERR_INVALID_ALGORITHM; + } + + /* + * We need to generate our key, as a non-zero random value which + * is lower than the curve order, in a "large enough" range. We + * force top bit to 0 and bottom bit to 1, which guarantees that + * the value is in the proper range. + */ + order = ctx->eng.iec->order(curve, &olen); + mask = 0xFF; + while (mask >= order[0]) { + mask >>= 1; + } + br_hmac_drbg_generate(&ctx->eng.rng, key, olen); + key[0] &= mask; + key[olen - 1] |= 0x01; + + /* + * Compute the common ECDH point, whose X coordinate is the + * pre-master secret. + */ + ctx->eng.iec->generator(curve, &glen); + if (glen != point_len) { + return -BR_ERR_INVALID_ALGORITHM; + } + + memcpy(point, point_src, glen); + if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) { + return -BR_ERR_INVALID_ALGORITHM; + } + + /* + * The pre-master secret is the X coordinate. + */ + xoff = ctx->eng.iec->xoff(curve, &xlen); + br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen); + + ctx->eng.iec->mulgen(point, key, olen, curve); + memcpy(ctx->eng.pad, point, glen); + return (int)glen; +} + +/* + * Perform full static ECDH. This occurs only in the context of client + * authentication with certificates: the server uses an EC public key, + * the cipher suite is of type ECDH (not ECDHE), the server requested a + * client certificate and accepts static ECDH, the client has a + * certificate with an EC public key in the same curve, and accepts + * static ECDH as well. + * + * Returned value is 0 on success, -1 on error. + */ +static int +make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id) +{ + unsigned char point[133]; + size_t point_len; + const br_x509_class **xc; + const br_x509_pkey *pk; + + xc = ctx->eng.x509ctx; + pk = (*xc)->get_pkey(xc, NULL); + point_len = pk->key.ec.qlen; + if (point_len > sizeof point) { + return -1; + } + memcpy(point, pk->key.ec.q, point_len); + if (!(*ctx->client_auth_vtable)->do_keyx( + ctx->client_auth_vtable, point, &point_len)) + { + return -1; + } + br_ssl_engine_compute_master(&ctx->eng, + prf_id, point, point_len); + 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); +} + +} + +\ ======================================================================= + +: addr-ctx: + next-word { field } + "addr-" field + 0 1 define-word + 0 8191 "offsetof(br_ssl_client_context, " field + ")" + make-CX + 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 +\ extension), or 0 if we know that the server does not support the +\ extension. +: ext-reneg-length ( -- n ) + addr-reneg get8 dup if 1 - 17 * else drop 5 then ; + +\ Length of SNI extension. +: ext-sni-length ( -- len ) + addr-server_name strlen dup if 9 + then ; + +\ Length of Maximum Fragment Length extension. +: ext-frag-length ( -- len ) + addr-log_max_frag_len get8 14 = if 0 else 5 then ; + +\ Length of Signatures extension. +: ext-signatures-length ( -- len ) + supported-hash-functions { num } drop 0 + supports-rsa-sign? if num + then + supports-ecdsa? if num + then + dup if 1 << 6 + then ; + +\ Write supported hash functions ( sign -- ) +: write-hashes + { sign } + supported-hash-functions drop + \ We advertise hash functions in the following preference order: + \ SHA-256 SHA-224 SHA-384 SHA-512 SHA-1 + \ Rationale: + \ -- SHA-256 and SHA-224 are more efficient on 32-bit architectures + \ -- SHA-1 is less than ideally collision-resistant + dup 0x10 and if 4 write8 sign write8 then + dup 0x08 and if 3 write8 sign write8 then + dup 0x20 and if 5 write8 sign write8 then + dup 0x40 and if 6 write8 sign write8 then + 0x04 and if 2 write8 sign write8 then ; + +\ Length of Supported Curves extension. +: ext-supported-curves-length ( -- len ) + supported-curves dup if + 0 { x } + begin dup while + dup 1 and x + >x + 1 >> + repeat + drop x 1 << 6 + + then ; + +\ Length of Supported Point Formats extension. +: ext-point-format-length ( -- len ) + supported-curves if 6 else 0 then ; + +\ Length of ALPN extension. +cc: ext-ALPN-length ( -- len ) { + size_t u, len; + + if (ENG->protocol_names_num == 0) { + T0_PUSH(0); + T0_RET(); + } + len = 6; + for (u = 0; u < ENG->protocol_names_num; u ++) { + len += 1 + strlen(ENG->protocol_names[u]); + } + T0_PUSH(len); +} + +\ Length of Session Ticket extension (RFC 5077). +\ Always sent (to signal support). If we have a stored ticket, include it. +: ext-session-ticket-length ( -- len ) + addr-session_ticket_len get16 4 + ; + +\ Write handshake message: ClientHello +: write-ClientHello ( -- ) + { ; total-ext-length } + + \ Compute length for extensions (without the general two-byte header). + \ This does not take padding extension into account. + ext-reneg-length ext-sni-length + ext-frag-length + + ext-signatures-length + + ext-supported-curves-length + ext-point-format-length + + ext-ALPN-length + + ext-session-ticket-length + + >total-ext-length + + \ ClientHello type + 1 write8 + + \ Compute and write length + 39 addr-session_id_len get8 + addr-suites_num get8 1 << + + total-ext-length if 2+ total-ext-length + then + \ Compute padding (if requested). + addr-min_clienthello_len get16 over - dup 0> if + \ We well add a Pad ClientHello extension, which has its + \ own header (4 bytes) and might be the only extension + \ (2 extra bytes for the extension list header). + total-ext-length ifnot swap 2+ swap 2- then + \ Account for the extension header. + 4 - dup 0< if drop 0 then + \ Adjust total extension length. + dup 4 + total-ext-length + >total-ext-length + \ Adjust ClientHello length. + swap 4 + over + swap + else + drop + -1 + then + { ext-padding-amount } + write24 + + \ Protocol version + addr-version_max get16 write16 + + \ Client random + addr-client_random 4 bzero + addr-client_random 4 + 28 mkrand + addr-client_random 32 write-blob + + \ Session ID + addr-session_id addr-session_id_len get8 write-blob-head8 + + \ Supported cipher suites. We also check here that we indeed + \ support all these suites. + addr-suites_num get8 dup 1 << write16 + addr-suites_buf swap + begin + dup while 1- + over get16 + dup suite-supported? ifnot ERR_BAD_CIPHER_SUITE fail then + write16 + swap 2+ swap + repeat + 2drop + + \ Compression methods (only "null" compression) + 1 write8 0 write8 + + \ Extensions + total-ext-length if + total-ext-length write16 + ext-reneg-length if + 0xFF01 write16 \ extension type (0xFF01) + addr-saved_finished + ext-reneg-length 4 - dup write16 \ extension length + 1- write-blob-head8 \ verify data + then + ext-sni-length if + 0x0000 write16 \ extension type (0) + addr-server_name + ext-sni-length 4 - dup write16 \ extension length + 2 - dup write16 \ ServerNameList length + 0 write8 \ name type: host_name + 3 - write-blob-head16 \ the name itself + then + ext-frag-length if + 0x0001 write16 \ extension type (1) + 0x0001 write16 \ extension length + addr-log_max_frag_len get8 8 - write8 + then + ext-signatures-length if + 0x000D write16 \ extension type (13) + ext-signatures-length 4 - dup write16 \ extension length + 2 - write16 \ list length + supports-ecdsa? if 3 write-hashes then + supports-rsa-sign? if 1 write-hashes then + then + \ TODO: add an API to specify preference order for curves. + \ Right now we send Curve25519 first, then other curves in + \ increasing ID values (hence P-256 in second). + ext-supported-curves-length dup if + 0x000A write16 \ extension type (10) + 4 - dup write16 \ extension length + 2- write16 \ list length + supported-curves 0 + dup 0x20000000 and if + 0xDFFFFFFF and 29 write16 + then + begin dup 32 < while + dup2 >> 1 and if dup write16 then + 1+ + repeat + 2drop + else + drop + then + ext-point-format-length if + 0x000B write16 \ extension type (11) + 0x0002 write16 \ extension length + 0x0100 write16 \ value: 1 format: uncompressed + then + ext-ALPN-length dup if + 0x0010 write16 \ extension type (16) + 4 - dup write16 \ extension length + 2- write16 \ list length + addr-protocol_names_num get16 0 + begin + dup2 > while + dup copy-protocol-name + dup write8 addr-pad swap write-blob + 1+ + repeat + 2drop + else + drop + then + \ Session Ticket extension (RFC 5077). + 0x0023 write16 \ extension type (35) + addr-session_ticket_len get16 + dup write16 \ extension data length + dup if + addr-session_ticket swap write-blob + else + drop + then + ext-padding-amount 0< ifnot + 0x0015 write16 \ extension value (21) + ext-padding-amount + dup write16 \ extension length + begin dup while + 1- 0 write8 repeat \ value (only zeros) + drop + then + then + ; + +\ ======================================================================= + +\ Parse server SNI extension. If present, then it should be empty. +: read-server-sni ( lim -- lim ) + read16 if ERR_BAD_SNI fail then ; + +\ Parse server Max Fragment Length extension. If present, then it should +\ advertise the same length as the client. Note that whether the server +\ sends it or not changes nothing for us: we won't send any record larger +\ than the advertised value anyway, and we will accept incoming records +\ up to our input buffer length. +: read-server-frag ( lim -- lim ) + read16 1 = ifnot ERR_BAD_FRAGLEN fail then + read8 8 + addr-log_max_frag_len get8 = ifnot ERR_BAD_FRAGLEN fail then ; + +\ Parse server Secure Renegotiation extension. This is called only if +\ the client sent that extension, so we only have two cases to +\ distinguish: first handshake, and renegotiation; in the latter case, +\ we know that the server supports the extension, otherwise the client +\ would not have sent it. +: read-server-reneg ( lim -- lim ) + read16 + addr-reneg get8 ifnot + \ "reneg" is 0, so this is a first handshake. The server's + \ extension MUST be empty. We also learn that the server + \ supports the extension. + 1 = ifnot ERR_BAD_SECRENEG fail then + read8 0 = ifnot ERR_BAD_SECRENEG fail then + 2 addr-reneg set8 + else + \ "reneg" is non-zero, and we sent an extension, so it must + \ be 2 and this is a renegotiation. We must verify that + \ the extension contents have length exactly 24 bytes and + \ match the saved client and server "Finished". + 25 = ifnot ERR_BAD_SECRENEG fail then + read8 24 = ifnot ERR_BAD_SECRENEG fail then + addr-pad 24 read-blob + addr-saved_finished addr-pad 24 memcmp ifnot + ERR_BAD_SECRENEG fail + then + then ; + +\ Read the ALPN extension from the server. It must contain a single name, +\ and that name must match one of our names. +: read-ALPN-from-server ( lim -- lim ) + \ Extension contents length. + read16 open-elt + \ Length of list of names. + read16 open-elt + \ There should be a single name. + read8 addr-pad swap dup { len } read-blob + close-elt + close-elt + len test-protocol-name dup 0< if + 3 flag? if ERR_UNEXPECTED fail then + drop + else + 1+ addr-selected_protocol set16 + then ; + +\ Save a value in a 16-bit field, or check it in case of session resumption. +: check-resume ( val addr resume -- ) + if get16 = ifnot ERR_RESUME_MISMATCH fail then else set16 then ; + +cc: DEBUG-BLOB ( addr len -- ) { + extern int printf(const char *fmt, ...); + + size_t len = T0_POP(); + unsigned char *buf = (unsigned char *)CTX + T0_POP(); + size_t u; + + printf("BLOB:"); + for (u = 0; u < len; u ++) { + if (u % 16 == 0) { + printf("\n "); + } + printf(" %02x", buf[u]); + } + printf("\n"); +} + +\ Parse incoming ServerHello. Returned value is true (-1) on session +\ resumption. +: read-ServerHello ( -- bool ) + \ Get header, and check message type. + read-handshake-header 2 = ifnot ERR_UNEXPECTED fail then + + \ Get protocol version. + read16 { version } + version addr-version_min get16 < version addr-version_max get16 > or if + ERR_UNSUPPORTED_VERSION fail + then + + \ Enforce chosen version for subsequent records in both directions. + version addr-version_in get16 <> if ERR_BAD_VERSION fail then + version addr-version_out set16 + + \ Server random. + addr-server_random 32 read-blob + + \ The "session resumption" flag. + 0 { resume } + + \ Session ID. + read8 { idlen } + idlen 32 > if ERR_OVERSIZED_ID fail then + addr-pad idlen read-blob + idlen addr-session_id_len get8 = idlen 0 > and if + addr-session_id addr-pad idlen memcmp if + \ Server session ID is non-empty and matches what + \ we sent, so this is a session resumption. + -1 >resume + then + then + addr-session_id addr-pad idlen memcpy + idlen addr-session_id_len set8 + + \ Record version. + version addr-version resume check-resume + + \ Cipher suite. We check that it is part of the list of cipher + \ suites that we advertised. + read16 + dup scan-suite 0< if ERR_BAD_CIPHER_SUITE fail then + \ Also check that the cipher suite is compatible with the + \ announced version: suites that don't use HMAC/SHA-1 are + \ for TLS-1.2 only, not older versions. + dup use-tls12? version 0x0303 < and if ERR_BAD_CIPHER_SUITE fail then + addr-cipher_suite resume check-resume + + \ Compression method. Should be 0 (no compression). + read8 if ERR_BAD_COMPRESSION fail then + + \ Parse extensions (if any). If there is no extension, then the + \ read limit (on the TOS) should be 0 at that point. + dup if + \ Length of extension list. + \ message size. + read16 open-elt + + \ Enumerate extensions. For each of them, check that we + \ sent an extension of that type, and did not see it + \ yet; and then process it. + ext-sni-length { ok-sni } + ext-reneg-length { ok-reneg } + ext-frag-length { ok-frag } + ext-signatures-length { ok-signatures } + ext-supported-curves-length { ok-curves } + ext-point-format-length { ok-points } + ext-session-ticket-length { ok-session-ticket } + ext-ALPN-length { ok-ALPN } + begin dup while + read16 + case + \ Server Name Indication. The server may + \ send such an extension if it uses the SNI + \ from the client, but that "response + \ extension" is supposed to be empty. + 0x0000 of + ok-sni ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-sni + read-server-sni + endof + + \ Max Frag Length. The contents shall be + \ a single byte whose value matches the one + \ sent by the client. + 0x0001 of + ok-frag ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-frag + read-server-frag + endof + + \ Secure Renegotiation. + 0xFF01 of + ok-reneg ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-reneg + read-server-reneg + endof + + \ Signature Algorithms. + \ Normally, the server should never send this + \ extension (so says RFC 5246 #7.4.1.4.1), + \ but some existing servers do. + 0x000D of + ok-signatures ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-signatures + read-ignore-16 + endof + + \ Supported Curves. + 0x000A of + ok-curves ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-curves + read-ignore-16 + endof + + \ Supported Point Formats. + 0x000B of + ok-points ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-points + read-ignore-16 + endof + + \ ALPN. + 0x0010 of + ok-ALPN ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-ALPN + read-ALPN-from-server + endof + + \ Session Ticket (RFC 5077). + 0x0023 of + ok-session-ticket ifnot + ERR_EXTRA_EXTENSION fail + then + 0 >ok-session-ticket + read-ignore-16 + 1 addr-session_ticket_ok set8 + endof + + ERR_EXTRA_EXTENSION fail + endcase + repeat + + \ If we sent a secure renegotiation extension but did not + \ receive a response, then the server does not support + \ secure renegotiation. This is a hard failure if this + \ is a renegotiation. + ok-reneg if + ok-reneg 5 > if ERR_BAD_SECRENEG fail then + 1 addr-reneg set8 + then + close-elt + else + \ No extension received at all, so the server does not + \ support secure renegotiation. This is a hard failure + \ if the server was previously known to support it (i.e. + \ this is a renegotiation). + ext-reneg-length 5 > if ERR_BAD_SECRENEG fail then + 1 addr-reneg set8 + then + close-elt + resume + ; + +cc: set-server-curve ( -- ) { + const br_x509_class *xc; + const br_x509_pkey *pk; + + xc = *(ENG->x509ctx); + pk = xc->get_pkey(ENG->x509ctx, NULL); + CTX->server_curve = + (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0; +} + +\ Read Certificate message from server. +: read-Certificate-from-server ( -- ) + addr-cipher_suite get16 expected-key-type + -1 read-Certificate + dup 0< if neg fail then + dup ifnot ERR_UNEXPECTED fail then + over and <> if ERR_WRONG_KEY_USAGE fail then + + \ 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) +\ 'use-rsa' is 0 for ECDSA, -1 for for RSA +\ 'sig-len' is the signature length (in bytes) +\ The signature itself is in the pad. +cc: verify-SKE-sig ( hash use-rsa sig-len -- err ) { + size_t sig_len = T0_POP(); + int use_rsa = T0_POPi(); + int hash = T0_POPi(); + + T0_PUSH(verify_SKE_sig(CTX, hash, use_rsa, sig_len)); +} + +\ Parse ServerKeyExchange +: read-ServerKeyExchange ( -- ) + \ Get header, and check message type. + read-handshake-header 12 = ifnot ERR_UNEXPECTED fail then + + \ We expect a named curve, and we must support it. + read8 3 = ifnot ERR_INVALID_ALGORITHM fail then + read16 dup addr-ecdhe_curve set8 + dup 32 >= if ERR_INVALID_ALGORITHM fail then + supported-curves swap >> 1 and ifnot ERR_INVALID_ALGORITHM fail then + + \ Read the server point. + read8 + dup 133 > if ERR_INVALID_ALGORITHM fail then + dup addr-ecdhe_point_len set8 + addr-ecdhe_point swap read-blob + + \ If using TLS-1.2+, then the hash function and signature algorithm + \ are explicitly provided; the signature algorithm must match what + \ the cipher suite specifies. With TLS-1.0 and 1.1, the signature + \ algorithm is inferred from the cipher suite, and the hash is + \ either MD5+SHA-1 (for RSA signatures) or SHA-1 (for ECDSA). + addr-version get16 0x0303 >= { tls1.2+ } + addr-cipher_suite get16 use-rsa-ecdhe? { use-rsa } + 2 { hash } + tls1.2+ if + \ Read hash function; accept only the SHA-* identifiers + \ (from SHA-1 to SHA-512, no MD5 here). + read8 + dup dup 2 < swap 6 > or if ERR_INVALID_ALGORITHM fail then + >hash + read8 + \ Get expected signature algorithm and compare with what + \ the server just sent. Expected value is 1 for RSA, 3 + \ for ECDSA. Note that 'use-rsa' evaluates to -1 for RSA, + \ 0 for ECDSA. + use-rsa 1 << 3 + = ifnot ERR_INVALID_ALGORITHM fail then + else + \ For MD5+SHA-1, we set 'hash' to 0. + use-rsa if 0 >hash then + then + + \ Read signature into the pad. + read16 dup { sig-len } + + dup 512 > if ERR_LIMIT_EXCEEDED fail then + addr-pad swap read-blob + + \ Verify signature. + hash use-rsa sig-len verify-SKE-sig + dup if fail then drop + + 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 -- ) + \ Read supported client authentication 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 set32 + + \ 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 ; + +cc: do-rsa-encrypt ( prf_id -- nlen ) { + int x; + + x = make_pms_rsa(CTX, T0_POP()); + if (x < 0) { + br_ssl_engine_fail(ENG, -x); + T0_CO(); + } else { + T0_PUSH(x); + } +} + +cc: do-ecdh ( echde prf_id -- ulen ) { + unsigned prf_id = T0_POP(); + unsigned ecdhe = T0_POP(); + int x; + + x = make_pms_ecdh(CTX, ecdhe, prf_id); + if (x < 0) { + br_ssl_engine_fail(ENG, -x); + T0_CO(); + } else { + T0_PUSH(x); + } +} + +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 + dup use-rsa-keyx? if + prf-id do-rsa-encrypt + dup 2+ write24 + dup write16 + addr-pad swap write-blob + else + dup use-ecdhe? swap prf-id do-ecdh + dup 1+ write24 + dup write8 + 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 ; + +\ ======================================================================= + +\ Peek at the first byte of the handshake input buffer without consuming +\ it. Returns the byte value, or -1 if the buffer is empty. +cc: peek-hs-msg-type ( -- type ) { + if (ENG->hlen_in > 0) { + T0_PUSH(*ENG->hbuf_in); + } else { + T0_PUSHi(-1); + } +} + +\ Read a NewSessionTicket message (handshake type 4, RFC 5077). +\ Format: uint32 lifetime_hint, opaque ticket<0..2^16-1> +cc: debug-session-ticket ( len -- ) { + extern void __stdcall OutputDebugStringA(const char *); + extern int sprintf(char *, const char *, ...); + char buf[80]; + size_t len = T0_POP(); + sprintf(buf, "BearSSL: NewSessionTicket received (%u bytes)\r\n", + (unsigned)len); + OutputDebugStringA(buf); +} + +: read-NewSessionTicket-message ( -- ) + read-handshake-header 4 = ifnot ERR_UNEXPECTED fail then + \ Skip the 4-byte lifetime_hint. + read16 drop read16 drop + \ Read ticket length, then ticket data. + read16 { tlen } + tlen 1024 > if + \ Ticket too large for our buffer; skip it. + tlen skip-blob + 0 addr-session_ticket_len set16 + else + addr-session_ticket tlen read-blob + tlen addr-session_ticket_len set16 + then + tlen debug-session-ticket + close-elt ; + +\ Read optional NewSessionTicket (RFC 5077) then CCS+Finished. +\ During abbreviated handshakes the server MAY send a renewed ticket +\ before CCS, but it is not guaranteed. We peek at the next record +\ type: if it is a handshake record we read the ticket; if it is CCS +\ we skip straight to read-CCS-Finished. +: read-CCS-Finished-with-ticket ( is-client -- ) + addr-session_ticket_ok get8 if + has-input? if + addr-record_type_in get8 22 = if + read-NewSessionTicket-message + then + else + begin + wait-co 0x07 and + dup 0x01 = if + drop read-NewSessionTicket-message 0 + then + dup 0x02 <> while + dup if ERR_UNEXPECTED fail then + drop + repeat + drop + then + then + read-CCS-Finished ; + +\ Perform a handshake. +: do-handshake ( -- ) + 0 addr-application_data set8 + 22 addr-record_type_out set8 + 0 addr-selected_protocol set16 + 0 addr-session_ticket_ok set8 + multihash-init + + write-ClientHello + flush-record + read-ServerHello + + \ Track whether this is a ticket-based resumption detected by + \ peeking at the next server message (RFC 5077). + 0 { ticket-resume } + + ifnot + \ Not a session ID resumption. Check for ticket-based + \ resumption: if we sent a ticket and the server confirmed + \ ticket support, peek at the next record to decide. + addr-session_ticket_ok get8 + addr-session_ticket_len get16 0 > and if + \ Wait for data from server. + has-input? not if + begin wait-co 0x07 and dup 0= while + drop repeat drop + then + addr-record_type_in get8 20 = if + \ CCS → ticket resumption, no renewed ticket. + -1 >ticket-resume + else + \ Handshake record. Peek at message type. + peek-hs-msg-type 4 = if + \ NewSessionTicket → ticket resumption + \ with a renewed ticket. + read-NewSessionTicket-message + -1 >ticket-resume + then + then + then + else + -1 >ticket-resume + then + + ticket-resume if + \ Session resumption (session-ID or ticket-based). + -1 read-CCS-Finished-with-ticket + -1 write-CCS-Finished + else + \ Full handshake. + + \ 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. + addr-cipher_suite get16 expected-key-type + CX 0 63 { BR_KEYTYPE_SIGN } and if + read-ServerKeyExchange + then + + \ Get next header. + read-handshake-header + + \ If this is a CertificateRequest, parse it, then read + \ next header. + dup 13 = if + drop read-contents-CertificateRequest + read-handshake-header + -1 + else + 0 + then + { seen-CR } + + \ At that point, we should have a ServerHelloDone, + \ whose length must be 0. + 14 = ifnot ERR_UNEXPECTED fail then + if ERR_BAD_HELLO_DONE fail then + + \ There should not be more bytes in the record at that point. + more-incoming-bytes? if ERR_UNEXPECTED fail then + + seen-CR if + \ If the server requested a client certificate, then + \ we must write a Certificate message (it may be + \ empty). + write-Certificate + + \ If using static ECDH, then the ClientKeyExchange + \ is empty, and there is no CertificateVerify. + \ Otherwise, there is a ClientKeyExchange; there + \ will then be a CertificateVerify if a client chain + \ was indeed sent. + addr-hash_id get8 0xFF = if + drop + 16 write8 0 write24 + addr-cipher_suite get16 prf-id do-static-ecdh + else + write-ClientKeyExchange + if write-CertificateVerify then + then + else + write-ClientKeyExchange + then + + -1 write-CCS-Finished + -1 read-CCS-Finished-with-ticket + then + + \ Now we should be invoked only in case of renegotiation. + 1 addr-application_data set8 + 23 addr-record_type_out set8 ; + +\ Read a HelloRequest message. +: read-HelloRequest ( -- ) + \ A HelloRequest has length 0 and type 0. + read-handshake-header-core + if ERR_UNEXPECTED fail then + if ERR_BAD_HANDSHAKE fail then ; + +\ Entry point. +: main ( -- ! ) + \ Perform initial handshake. + do-handshake + + begin + \ Wait for further invocation. At that point, we should + \ get either an explicit call for renegotiation, or + \ an incoming HelloRequest handshake message. + wait-co + dup 0x07 and case + 0x00 of + 0x10 and if + do-handshake + then + endof + 0x01 of + drop + 0 addr-application_data set8 + read-HelloRequest + \ Reject renegotiations if the peer does not + \ support secure renegotiation, or if the + \ "no renegotiation" flag is set. + addr-reneg get8 1 = 1 flag? or if + flush-record + begin can-output? not while + wait-co drop + repeat + 100 send-warning + \ We rejected the renegotiation, + \ but the connection is not dead. + \ We must set back things into + \ working "application data" state. + 1 addr-application_data set8 + 23 addr-record_type_out set8 + else + do-handshake + then + endof + ERR_UNEXPECTED fail + endcase + again + ; diff --git a/libcurl/lib/vtls/trust_anchors.h b/libcurl/lib/vtls/trust_anchors.h new file mode 100644 index 0000000..9ee13fb --- /dev/null +++ b/libcurl/lib/vtls/trust_anchors.h @@ -0,0 +1,33591 @@ +#pragma once + +static const unsigned char TA0_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA0_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA0_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA1_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA1_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA2_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA2_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA2_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA3_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA3_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA3_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA4_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA4_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA5_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA5_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA5_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA6_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA6_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA6_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA7_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA7_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA8_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA8_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA8_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA9_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA9_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA10_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA10_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA10_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA11_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA11_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA12_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA12_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA12_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA13_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA13_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA14_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA14_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA15_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA15_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA16_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA16_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA16_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA17_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA17_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA17_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA18_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA18_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA18_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA19_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA19_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA19_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA20_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA20_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA21_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA21_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA21_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA22_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA22_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA23_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA23_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA24_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA24_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA24_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA25_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA25_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA26_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA26_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA27_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA27_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA27_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA28_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA28_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA28_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA29_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA29_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA29_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA30_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA30_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA30_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA31_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA31_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA31_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA32_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA32_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA32_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA33_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA33_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA33_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA34_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA34_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA34_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA35_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA35_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA35_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA36_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA36_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA37_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA37_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA37_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA38_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA38_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA38_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA39_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA39_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA40_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA40_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA40_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA41_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA41_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA42_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA42_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA42_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA43_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA43_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA43_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA44_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA44_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA44_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA45_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA45_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA46_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA46_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA46_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA47_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA47_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA47_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA48_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA48_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA48_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA49_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA49_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA49_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA50_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA50_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA50_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA51_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA51_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA51_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA52_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA52_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA53_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA53_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA53_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA54_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA54_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA54_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA55_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA55_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA55_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA56_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA56_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA56_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA57_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA57_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA58_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA58_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA58_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA59_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA59_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA59_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA60_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA60_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA61_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA61_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA61_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA62_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA62_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA63_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA63_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA63_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA64_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA64_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA64_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA65_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA65_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA65_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA66_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA66_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA66_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA67_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA67_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA67_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA68_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA68_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA68_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA69_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA69_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA70_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA70_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA70_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA71_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA71_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA71_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA72_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA72_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA72_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA73_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA73_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA73_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA74_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA74_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA75_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA75_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA75_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA76_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA76_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA76_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA77_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA77_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA78_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA78_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA78_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA79_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA79_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA79_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA80_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA80_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA80_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA81_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA81_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA81_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA82_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA82_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA82_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA83_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA83_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA83_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA84_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA84_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA84_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA85_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA85_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA86_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA86_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA87_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA87_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA88_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA88_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA88_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA89_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA89_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA90_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA90_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA90_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA91_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA91_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA91_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA92_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA92_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA92_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA93_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA93_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA93_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA94_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA94_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA94_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA95_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA95_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA95_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA96_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA96_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA97_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA97_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA98_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA98_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA98_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA99_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA99_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA99_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA100_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA100_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA100_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA101_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA101_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA101_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA102_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA102_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA102_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA103_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA103_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA103_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA104_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA104_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA104_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA105_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA105_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA105_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA106_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA106_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA106_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA107_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA107_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA108_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA108_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA109_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA109_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA110_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA110_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA110_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA111_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA111_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA111_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA112_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA112_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA112_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA113_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA113_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA113_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA114_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA114_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA114_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA115_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA115_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA115_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA116_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA116_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA116_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA117_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA117_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA117_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA118_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA118_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA118_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA119_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA119_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA119_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA120_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA120_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA121_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA121_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA122_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA122_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA123_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA123_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA123_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA124_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA124_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA124_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA125_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA125_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA126_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA126_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA126_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA127_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA127_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA128_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA128_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA129_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA129_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA129_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA130_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA130_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA130_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA131_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA131_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA131_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA132_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA132_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA133_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA133_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA133_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA134_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA134_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA134_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA135_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA135_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA136_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA136_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA137_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA137_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA137_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA138_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA138_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA138_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA139_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA139_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA140_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA140_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA141_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA141_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA141_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA142_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA142_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA142_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA143_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA143_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA144_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA144_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA144_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA145_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA145_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA146_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA146_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA147_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA147_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA148_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA148_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA148_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA149_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA149_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA149_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA150_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA150_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA150_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA151_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA151_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA152_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA152_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA152_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA153_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA153_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA154_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA154_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA154_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA155_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA155_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA155_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA156_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA156_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA156_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA157_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA157_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA157_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA158_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA158_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA158_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA159_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA159_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA159_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA160_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA160_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA160_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA161_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA161_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA162_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA162_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA163_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA163_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA163_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA164_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA164_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA164_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA165_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA165_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA165_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA166_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA166_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA167_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA167_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA167_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA168_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA168_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA168_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA169_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA169_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA169_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA170_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA170_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA170_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA171_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA171_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA172_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA172_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA172_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA173_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA173_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA174_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA174_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA174_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA175_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA175_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA176_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA176_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA176_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA177_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA177_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA177_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA178_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA178_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA179_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA179_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA179_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA180_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA180_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA180_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA181_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA181_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA181_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA182_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA182_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA183_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA183_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA184_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA184_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA184_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA185_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA185_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA185_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA186_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA186_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA186_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA187_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA187_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA187_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA188_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA188_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA188_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA189_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA189_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA189_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA190_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA190_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA190_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA191_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA191_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA192_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA192_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA192_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA193_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA193_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA193_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA194_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA194_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA194_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA195_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA195_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA195_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA196_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA196_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA197_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA197_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA197_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA198_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA198_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA198_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA199_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA199_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA199_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA200_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA200_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA201_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA201_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA202_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA202_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA202_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA203_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA203_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA203_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA204_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA204_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA205_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA205_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA205_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA206_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA206_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA206_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA207_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA207_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA208_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA208_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA208_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA209_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA209_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA209_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA210_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA210_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA210_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA211_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA211_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA212_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA212_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA213_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA213_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA213_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA214_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA214_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA214_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA215_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA215_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA215_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA216_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA216_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA217_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA217_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA217_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA218_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA218_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA218_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA219_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA219_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA220_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA220_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA220_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA221_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA221_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA221_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA222_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA222_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA222_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA223_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA223_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA223_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA224_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA224_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA225_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA225_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA225_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA226_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA226_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA226_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA227_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA227_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA227_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA228_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA228_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA228_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA229_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA229_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA229_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA230_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA230_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA230_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA231_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA231_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA231_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA232_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA232_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA233_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA233_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA233_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA234_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA234_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA234_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA235_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA235_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA235_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA236_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA236_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA236_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA237_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA237_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA237_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA238_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA238_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA239_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA239_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA239_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA240_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA240_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA241_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA241_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA241_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA242_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA242_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA242_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA243_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA243_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA243_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA244_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA244_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA244_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA245_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA245_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA246_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA246_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA246_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA247_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA247_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA247_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA248_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA248_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA248_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA249_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA249_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA249_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA250_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA250_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA250_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA251_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA251_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA252_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA252_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA252_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA253_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA253_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA253_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA254_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA254_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA255_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA255_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA256_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA256_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA256_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA257_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA257_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA258_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA258_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA258_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA259_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA259_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA259_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA260_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA260_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA260_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA261_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA261_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA262_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA262_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA262_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA263_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA263_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA263_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA264_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA264_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA264_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA265_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA265_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA265_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA266_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA266_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA266_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA267_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA267_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA267_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA268_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA268_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA269_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA269_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA269_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA270_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA270_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA271_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA271_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA271_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA272_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA272_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA272_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA273_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA273_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA273_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA274_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA274_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA275_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA275_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA275_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA276_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA276_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA276_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA277_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA277_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA277_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA278_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA278_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA279_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA279_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA280_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA280_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA280_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA281_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA281_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA281_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA282_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA282_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA282_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA283_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA283_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA284_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA284_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA284_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA285_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA285_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA286_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA286_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA286_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA287_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA287_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA287_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA288_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA288_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA288_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA289_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA289_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA289_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA290_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA290_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA290_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA291_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA291_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA292_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA292_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA292_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA293_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA293_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA293_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA294_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA294_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA295_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA295_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA295_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA296_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA296_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA297_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA297_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA297_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA298_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA298_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA298_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA299_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA299_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA299_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA300_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA300_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA300_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA301_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA301_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA302_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA302_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA302_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA303_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA303_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA304_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA304_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA304_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA305_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA305_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA305_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA306_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA306_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA306_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA307_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA307_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA307_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA308_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA308_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA309_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA309_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA310_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA310_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA311_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA311_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA312_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA312_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA312_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA313_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA313_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA313_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA314_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA314_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA314_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA315_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA315_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA316_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA316_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA316_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA317_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA317_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA317_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA318_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA318_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA318_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA319_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA319_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA320_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA320_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA320_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA321_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA321_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA322_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA322_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA322_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA323_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA323_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA323_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA324_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA324_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA324_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA325_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA325_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA325_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA326_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA326_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA327_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA327_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA327_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA328_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA328_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA328_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA329_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA329_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA329_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA330_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA330_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA330_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA331_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA331_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA332_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA332_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA332_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA333_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA333_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA333_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA334_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA334_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA334_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA335_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA335_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA335_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA336_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA336_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA337_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA337_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA337_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA338_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA338_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA338_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA339_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA339_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA339_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA340_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA340_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA340_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA341_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA341_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA341_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA342_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA342_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA343_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA343_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA343_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA344_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA344_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA345_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA345_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA345_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA346_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA346_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA347_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA347_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA347_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA348_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA348_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA348_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA349_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA349_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA350_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA350_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA350_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA351_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA351_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA351_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA352_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA352_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA352_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA353_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA353_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA354_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA354_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA354_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA355_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA355_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA355_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA356_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA356_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA357_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA357_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA357_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA358_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA358_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA358_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA359_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA359_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA359_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA360_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA360_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA360_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA361_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA361_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA361_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA362_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA362_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA362_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA363_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA363_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA363_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA364_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA364_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA364_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA365_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA365_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA365_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA366_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA366_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA366_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA367_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA367_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA367_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA368_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA368_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA369_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA369_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA369_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA370_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA370_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA370_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA371_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA371_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA371_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA372_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA372_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA372_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA373_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA373_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA374_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA374_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA374_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA375_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA375_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA376_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA376_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA377_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA377_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA377_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA378_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA378_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA378_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA379_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA379_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA379_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA380_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA380_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA381_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA381_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA381_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA382_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA382_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA382_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA383_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA383_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA383_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA384_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA384_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA384_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA385_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA385_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA386_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA386_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA386_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA387_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA387_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA388_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA388_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA389_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA389_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA389_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA390_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA390_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA390_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA391_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA391_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA392_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA392_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA392_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA393_DN[] = { + 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49, + 0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53 +}; + +static const unsigned char TA393_RSA_N[] = { + 0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A, + 0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F, + 0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54, + 0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A, + 0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0, + 0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09, + 0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD, + 0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85, + 0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2, + 0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0, + 0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D, + 0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA, + 0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D, + 0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5, + 0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7, + 0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8, + 0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A, + 0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05, + 0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB, + 0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92, + 0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13, + 0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6, + 0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC, + 0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97, + 0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E, + 0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12, + 0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43, + 0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE, + 0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08, + 0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD, + 0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB, + 0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3, + 0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5, + 0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99, + 0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0, + 0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A, + 0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE, + 0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8, + 0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66, + 0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93, + 0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F, + 0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E, + 0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65 +}; + +static const unsigned char TA393_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA394_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA394_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA394_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA395_DN[] = { + 0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72, + 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, + 0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36, + 0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, + 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, + 0x4F, 0x53 +}; + +static const unsigned char TA395_EC_Q[] = { + 0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52, + 0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E, + 0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93, + 0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4, + 0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB, + 0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5, + 0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A, + 0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E, + 0x8B +}; + +static const unsigned char TA396_DN[] = { + 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, + 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41, + 0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, + 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, + 0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA396_RSA_N[] = { + 0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72, + 0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7, + 0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6, + 0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E, + 0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8, + 0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2, + 0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F, + 0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE, + 0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9, + 0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D, + 0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4, + 0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00, + 0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F, + 0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64, + 0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24, + 0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45, + 0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD, + 0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0, + 0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77, + 0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1, + 0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7, + 0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE, + 0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD, + 0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F, + 0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B, + 0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC, + 0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99, + 0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D, + 0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A, + 0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B, + 0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B, + 0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1, + 0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C, + 0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73, + 0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF, + 0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D, + 0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F, + 0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40, + 0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE, + 0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C, + 0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB, + 0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5, + 0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F +}; + +static const unsigned char TA396_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA397_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33, + 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C, + 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA397_RSA_N[] = { + 0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0, + 0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38, + 0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F, + 0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8, + 0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08, + 0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51, + 0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3, + 0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47, + 0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D, + 0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65, + 0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3, + 0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83, + 0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9, + 0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D, + 0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5, + 0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F, + 0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35, + 0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1, + 0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB, + 0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50, + 0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24, + 0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81, + 0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE, + 0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53, + 0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC, + 0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61, + 0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2, + 0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B, + 0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45, + 0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF, + 0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84, + 0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2, + 0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19, + 0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F, + 0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC, + 0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07, + 0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B, + 0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28, + 0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC, + 0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA, + 0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7, + 0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C, + 0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B +}; + +static const unsigned char TA397_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA398_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA398_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA398_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA399_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67 +}; + +static const unsigned char TA399_RSA_N[] = { + 0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52, + 0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB, + 0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37, + 0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30, + 0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB, + 0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A, + 0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A, + 0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B, + 0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA, + 0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C, + 0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E, + 0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1, + 0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8, + 0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9, + 0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27, + 0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46, + 0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E, + 0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D, + 0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41, + 0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6, + 0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C, + 0x16, 0xBD, 0xB4, 0x15 +}; + +static const unsigned char TA399_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA400_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA400_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA400_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA401_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA401_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA402_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA402_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA402_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA403_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA403_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA403_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA404_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA404_EC_Q[] = { + 0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01, + 0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2, + 0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B, + 0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80, + 0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5, + 0x67, 0x08, 0xEB, 0x66, 0xDE +}; + +static const unsigned char TA405_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA405_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA406_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA406_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA406_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA407_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA407_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA408_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA408_RSA_N[] = { + 0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D, + 0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE, + 0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F, + 0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6, + 0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B, + 0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96, + 0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38, + 0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E, + 0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5, + 0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B, + 0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A, + 0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3, + 0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0, + 0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0, + 0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08, + 0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A, + 0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9, + 0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9, + 0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5, + 0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45, + 0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D, + 0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E, + 0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E, + 0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36, + 0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1, + 0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA, + 0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7, + 0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E, + 0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB, + 0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58, + 0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44, + 0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7, + 0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09, + 0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B, + 0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33, + 0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98, + 0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF, + 0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94, + 0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C, + 0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90, + 0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B, + 0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C, + 0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71 +}; + +static const unsigned char TA408_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA409_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA409_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA409_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA410_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA410_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA410_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA411_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x32 +}; + +static const unsigned char TA411_EC_Q[] = { + 0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1, + 0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58, + 0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C, + 0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14, + 0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9, + 0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A, + 0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF, + 0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15, + 0x1C +}; + +static const unsigned char TA412_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, + 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, + 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA412_RSA_N[] = { + 0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, + 0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3, + 0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, + 0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88, + 0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, + 0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A, + 0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, + 0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA, + 0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, + 0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70, + 0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, + 0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13, + 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, + 0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5, + 0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, + 0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69, + 0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, + 0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98, + 0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, + 0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78, + 0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, + 0xDC, 0x27, 0x1A, 0x39 +}; + +static const unsigned char TA412_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA413_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA413_RSA_N[] = { + 0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4, + 0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4, + 0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15, + 0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA, + 0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B, + 0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE, + 0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E, + 0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74, + 0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87, + 0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97, + 0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49, + 0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF, + 0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44, + 0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61, + 0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E, + 0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C, + 0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73, + 0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1, + 0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E, + 0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF, + 0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7, + 0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E, + 0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8, + 0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D, + 0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E, + 0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F, + 0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46, + 0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04, + 0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E, + 0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16, + 0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06, + 0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D, + 0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01, + 0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA, + 0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC, + 0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68, + 0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61, + 0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC, + 0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74, + 0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63, + 0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30, + 0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20, + 0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F +}; + +static const unsigned char TA413_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA414_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA414_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA414_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA415_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA415_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA415_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA416_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA416_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA416_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA417_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA417_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA417_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA418_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA418_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA419_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA419_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA419_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA420_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA420_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA421_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA421_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA421_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA422_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA422_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA422_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA423_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA423_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA423_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA424_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA424_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA425_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA425_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA425_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA426_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA426_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA426_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA427_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA427_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA427_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA428_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA428_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA429_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA429_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA430_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA430_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA430_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA431_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA431_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA431_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA432_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA432_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA432_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA433_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA433_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA434_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA434_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA434_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA435_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA435_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA436_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA436_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA436_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA437_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA437_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA437_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA438_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA438_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA438_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA439_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA439_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA439_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA440_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA440_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA440_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA441_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA441_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA442_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA442_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA442_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA443_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA443_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA443_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA444_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA444_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA445_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA445_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA445_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA446_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA446_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA447_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA447_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA447_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA448_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA448_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA448_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA449_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA449_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA449_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA450_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA450_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA450_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA451_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA451_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA452_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA452_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA452_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA453_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA453_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA454_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA454_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA454_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA455_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA455_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA455_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA456_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA456_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA456_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA457_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA457_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA457_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA458_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA458_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA459_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA459_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA460_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA460_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA461_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA461_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA462_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA462_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA462_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA463_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA463_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA463_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA464_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA464_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA464_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA465_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA465_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA466_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA466_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA466_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA467_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA467_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA467_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA468_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA468_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA468_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA469_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA469_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA470_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA470_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA470_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA471_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA471_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA472_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA472_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA472_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA473_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA473_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA473_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA474_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA474_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA474_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA475_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA475_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA475_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA476_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA476_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA477_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA477_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA477_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA478_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA478_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA478_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA479_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA479_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA479_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA480_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA480_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA480_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA481_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA481_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA482_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA482_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA482_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA483_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA483_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA483_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA484_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA484_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA484_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA485_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA485_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA485_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA486_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA486_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA487_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA487_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA487_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA488_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA488_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA488_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA489_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA489_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA489_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA490_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA490_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA490_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA491_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA491_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA491_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA492_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA492_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA493_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA493_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA493_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA494_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA494_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA495_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA495_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA495_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA496_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA496_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA497_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA497_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA497_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA498_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA498_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA498_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA499_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA499_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA500_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA500_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA500_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA501_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA501_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA501_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA502_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA502_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA502_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA503_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA503_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA504_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA504_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA504_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA505_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA505_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA505_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA506_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA506_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA507_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA507_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA507_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA508_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA508_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA508_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA509_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA509_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA509_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA510_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA510_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA510_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA511_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA511_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA511_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA512_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA512_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA512_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA513_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA513_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA513_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA514_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA514_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA514_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA515_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA515_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA515_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA516_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA516_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA516_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA517_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA517_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA517_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA518_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA518_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA519_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA519_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA519_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA520_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA520_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA520_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA521_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA521_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA521_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA522_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA522_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA522_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA523_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA523_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA524_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA524_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA524_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA525_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA525_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA526_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA526_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA527_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA527_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA527_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA528_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA528_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA528_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA529_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA529_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA529_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA530_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA530_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA531_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA531_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA531_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA532_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA532_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA532_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA533_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA533_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA533_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA534_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA534_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA534_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA535_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA535_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA536_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA536_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA536_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA537_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA537_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA538_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA538_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA539_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA539_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA539_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA540_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA540_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA540_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA541_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA541_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA542_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA542_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA542_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA543_DN[] = { + 0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, + 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32 +}; + +static const unsigned char TA543_RSA_N[] = { + 0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6, + 0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB, + 0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C, + 0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41, + 0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4, + 0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC, + 0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19, + 0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3, + 0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C, + 0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC, + 0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9, + 0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2, + 0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25, + 0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8, + 0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51, + 0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4, + 0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC, + 0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56, + 0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E, + 0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A, + 0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90, + 0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD, + 0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D, + 0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05, + 0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17, + 0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3, + 0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44, + 0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D, + 0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD, + 0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D, + 0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7, + 0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1, + 0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11, + 0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11, + 0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50, + 0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A, + 0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32, + 0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34, + 0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE, + 0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A, + 0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0, + 0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C, + 0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D +}; + +static const unsigned char TA543_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA544_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA544_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA544_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA545_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA545_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA546_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA546_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA546_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA547_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA547_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA547_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA548_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA548_EC_Q[] = { + 0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35, + 0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C, + 0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA, + 0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC, + 0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6, + 0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F, + 0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E, + 0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B, + 0x29 +}; + +static const unsigned char TA549_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA549_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA549_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA550_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20, + 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, + 0x4D +}; + +static const unsigned char TA550_RSA_N[] = { + 0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0, + 0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A, + 0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6, + 0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36, + 0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58, + 0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1, + 0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77, + 0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38, + 0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4, + 0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3, + 0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE, + 0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10, + 0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68, + 0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F, + 0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF, + 0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10, + 0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35, + 0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E, + 0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4, + 0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1, + 0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7, + 0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50, + 0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8, + 0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65, + 0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD, + 0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE, + 0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A, + 0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D, + 0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96, + 0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53, + 0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49, + 0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB, + 0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3, + 0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63, + 0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD, + 0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63, + 0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57, + 0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07, + 0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA, + 0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69, + 0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4, + 0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF, + 0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5 +}; + +static const unsigned char TA550_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA551_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA551_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA551_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA552_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x45, 0x31 +}; + +static const unsigned char TA552_EC_Q[] = { + 0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86, + 0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A, + 0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A, + 0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B, + 0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34, + 0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A, + 0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02, + 0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4, + 0x76 +}; + +static const unsigned char TA553_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA553_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA553_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA554_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA554_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA554_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA555_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA555_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA555_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA556_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53, + 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13, + 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, + 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA556_RSA_N[] = { + 0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E, + 0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B, + 0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E, + 0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37, + 0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D, + 0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F, + 0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53, + 0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C, + 0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5, + 0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC, + 0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4, + 0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC, + 0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16, + 0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0, + 0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38, + 0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A, + 0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1, + 0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65, + 0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8, + 0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D, + 0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28, + 0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F, + 0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E, + 0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E, + 0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5, + 0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12, + 0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9, + 0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE, + 0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF, + 0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF, + 0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0, + 0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17, + 0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A, + 0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9, + 0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB, + 0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1, + 0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE, + 0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6, + 0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5, + 0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51, + 0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72, + 0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A, + 0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B +}; + +static const unsigned char TA556_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA557_DN[] = { + 0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72, + 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA557_RSA_N[] = { + 0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28, + 0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93, + 0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84, + 0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE, + 0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79, + 0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8, + 0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B, + 0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65, + 0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D, + 0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2, + 0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F, + 0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82, + 0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49, + 0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B, + 0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6, + 0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1, + 0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C, + 0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94, + 0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA, + 0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2, + 0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE, + 0xAC, 0x33, 0xB3, 0x4F +}; + +static const unsigned char TA557_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA558_DN[] = { + 0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA558_EC_Q[] = { + 0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37, + 0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82, + 0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98, + 0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F, + 0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C, + 0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7, + 0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6, + 0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB, + 0xC2 +}; + +static const unsigned char TA559_DN[] = { + 0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, + 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, + 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, + 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74, + 0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, + 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA559_RSA_N[] = { + 0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B, + 0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB, + 0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42, + 0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B, + 0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB, + 0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97, + 0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A, + 0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A, + 0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31, + 0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60, + 0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0, + 0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1, + 0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89, + 0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2, + 0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD, + 0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD, + 0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3, + 0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16, + 0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E, + 0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6, + 0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE, + 0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE, + 0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15, + 0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40, + 0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A, + 0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67, + 0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5, + 0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3, + 0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80, + 0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52, + 0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B, + 0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD, + 0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA, + 0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC, + 0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C, + 0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A, + 0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46, + 0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42, + 0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5, + 0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10, + 0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48, + 0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F, + 0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7 +}; + +static const unsigned char TA559_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA560_DN[] = { + 0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65, + 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, + 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, + 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65, + 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA560_RSA_N[] = { + 0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5, + 0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F, + 0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6, + 0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7, + 0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59, + 0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8, + 0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F, + 0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4, + 0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83, + 0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19, + 0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD, + 0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49, + 0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12, + 0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16, + 0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9, + 0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E, + 0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA, + 0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34, + 0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D, + 0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07, + 0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50, + 0x45, 0xA9, 0xF9, 0x49 +}; + +static const unsigned char TA560_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA561_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA561_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA561_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA562_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA562_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA562_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA563_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61, + 0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA563_RSA_N[] = { + 0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D, + 0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B, + 0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2, + 0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0, + 0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A, + 0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71, + 0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C, + 0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0, + 0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99, + 0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E, + 0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D, + 0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF, + 0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18, + 0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8, + 0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C, + 0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C, + 0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34, + 0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50, + 0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A, + 0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36, + 0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48, + 0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05, + 0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9, + 0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8, + 0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B, + 0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E, + 0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D, + 0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3, + 0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA, + 0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D, + 0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70, + 0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04, + 0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63, + 0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A, + 0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6, + 0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90, + 0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7, + 0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08, + 0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8, + 0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB, + 0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58, + 0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72, + 0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D +}; + +static const unsigned char TA563_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA564_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA564_EC_Q[] = { + 0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F, + 0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78, + 0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88, + 0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC, + 0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5, + 0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6, + 0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F, + 0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39, + 0x57 +}; + +static const unsigned char TA565_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA565_EC_Q[] = { + 0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F, + 0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30, + 0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9, + 0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED, + 0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F, + 0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8, + 0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19, + 0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22, + 0xF7 +}; + +static const unsigned char TA566_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31 +}; + +static const unsigned char TA566_RSA_N[] = { + 0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84, + 0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76, + 0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC, + 0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD, + 0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9, + 0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F, + 0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71, + 0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97, + 0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46, + 0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62, + 0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46, + 0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D, + 0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73, + 0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66, + 0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95, + 0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2, + 0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81, + 0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4, + 0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE, + 0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A, + 0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E, + 0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B, + 0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D, + 0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D, + 0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E, + 0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D, + 0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C, + 0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A, + 0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81, + 0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63, + 0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77, + 0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D, + 0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2, + 0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87, + 0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF, + 0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A, + 0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09, + 0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07, + 0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57, + 0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5, + 0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE, + 0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A, + 0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3 +}; + +static const unsigned char TA566_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA567_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA567_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA567_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA568_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA568_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA568_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA569_DN[] = { + 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA569_RSA_N[] = { + 0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B, + 0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87, + 0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2, + 0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71, + 0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86, + 0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70, + 0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3, + 0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3, + 0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15, + 0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A, + 0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B, + 0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68, + 0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D, + 0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8, + 0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6, + 0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A, + 0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7, + 0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55, + 0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6, + 0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47, + 0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48, + 0xAC, 0xBB, 0x26, 0xF7 +}; + +static const unsigned char TA569_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA570_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA570_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA571_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA571_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA571_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA572_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA572_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA572_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA573_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, + 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, + 0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49, + 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38 +}; + +static const unsigned char TA573_RSA_N[] = { + 0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F, + 0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E, + 0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A, + 0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B, + 0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62, + 0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E, + 0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29, + 0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A, + 0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77, + 0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D, + 0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC, + 0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81, + 0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66, + 0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E, + 0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14, + 0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20, + 0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6, + 0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0, + 0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B, + 0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26, + 0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93, + 0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01, + 0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C, + 0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F, + 0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB, + 0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93, + 0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C, + 0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF, + 0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D, + 0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99, + 0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7, + 0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10, + 0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42, + 0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B, + 0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5, + 0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5, + 0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C, + 0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39, + 0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F, + 0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F, + 0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E, + 0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44, + 0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB +}; + +static const unsigned char TA573_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA574_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA574_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA574_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA575_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA575_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA575_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA576_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA576_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA577_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA577_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA577_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA578_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA578_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA578_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA579_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA579_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA579_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA580_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA580_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA580_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA581_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA581_RSA_N[] = { + 0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD, + 0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70, + 0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F, + 0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F, + 0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7, + 0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A, + 0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF, + 0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0, + 0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99, + 0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB, + 0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3, + 0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8, + 0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A, + 0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD, + 0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67, + 0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1, + 0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46, + 0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A, + 0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB, + 0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E, + 0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51, + 0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F, + 0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24, + 0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE, + 0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4, + 0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13, + 0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14, + 0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96, + 0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11, + 0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04, + 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91, + 0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52, + 0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28, + 0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE, + 0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE, + 0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6, + 0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88, + 0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE, + 0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A, + 0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98, + 0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0, + 0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF, + 0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53 +}; + +static const unsigned char TA581_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA582_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA582_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA582_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA583_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA583_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA583_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA584_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA584_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA585_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31, + 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65, + 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x52, 0x31 +}; + +static const unsigned char TA585_RSA_N[] = { + 0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB, + 0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C, + 0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA, + 0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4, + 0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE, + 0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB, + 0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A, + 0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31, + 0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5, + 0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03, + 0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4, + 0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B, + 0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7, + 0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8, + 0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2, + 0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30, + 0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05, + 0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2, + 0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02, + 0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71, + 0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F, + 0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1, + 0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28, + 0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF, + 0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56, + 0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89, + 0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59, + 0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C, + 0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C, + 0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91, + 0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5, + 0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35, + 0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40, + 0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B, + 0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7, + 0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06, + 0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7, + 0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC, + 0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F, + 0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB, + 0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB, + 0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7, + 0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23 +}; + +static const unsigned char TA585_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA586_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA586_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA587_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA587_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA587_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA588_DN[] = { + 0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D +}; + +static const unsigned char TA588_RSA_N[] = { + 0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A, + 0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A, + 0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93, + 0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67, + 0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8, + 0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53, + 0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB, + 0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8, + 0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C, + 0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85, + 0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91, + 0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C, + 0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00, + 0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B, + 0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA, + 0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06, + 0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12, + 0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E, + 0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA, + 0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D, + 0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73, + 0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90, + 0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51, + 0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF, + 0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43, + 0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36, + 0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2, + 0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8, + 0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E, + 0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2, + 0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27, + 0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B, + 0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48, + 0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73, + 0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03, + 0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF, + 0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60, + 0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9, + 0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42, + 0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81, + 0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E, + 0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8, + 0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67 +}; + +static const unsigned char TA588_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA589_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA589_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA589_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA590_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA590_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA590_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA591_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA591_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA591_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA592_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA592_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA593_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA593_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA594_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34 +}; + +static const unsigned char TA594_EC_Q[] = { + 0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A, + 0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B, + 0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB, + 0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B, + 0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C, + 0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB, + 0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE, + 0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E, + 0x5C +}; + +static const unsigned char TA595_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA595_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA595_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA596_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA596_RSA_N[] = { + 0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7, + 0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4, + 0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9, + 0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC, + 0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79, + 0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC, + 0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61, + 0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2, + 0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36, + 0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33, + 0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3, + 0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76, + 0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E, + 0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF, + 0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9, + 0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17, + 0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31, + 0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28, + 0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0, + 0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0, + 0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08, + 0x5F, 0x18, 0x77, 0x4F +}; + +static const unsigned char TA596_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA597_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA597_RSA_N[] = { + 0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34, + 0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5, + 0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75, + 0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95, + 0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C, + 0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65, + 0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50, + 0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D, + 0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF, + 0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0, + 0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87, + 0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68, + 0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4, + 0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93, + 0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B, + 0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99, + 0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89, + 0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02, + 0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8, + 0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD, + 0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4, + 0x67, 0x95, 0x31, 0x8D +}; + +static const unsigned char TA597_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA598_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA598_EC_Q[] = { + 0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58, + 0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B, + 0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5, + 0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D, + 0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D, + 0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55, + 0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59, + 0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29, + 0x39 +}; + +static const unsigned char TA599_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA599_RSA_N[] = { + 0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA, + 0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE, + 0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7, + 0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD, + 0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF, + 0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27, + 0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08, + 0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F, + 0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78, + 0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0, + 0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6, + 0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1, + 0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08, + 0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C, + 0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91, + 0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE, + 0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2, + 0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C, + 0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8, + 0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2, + 0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3, + 0x90, 0xC3, 0xAF, 0x27 +}; + +static const unsigned char TA599_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA600_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x32 +}; + +static const unsigned char TA600_RSA_N[] = { + 0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD, + 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54, + 0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A, + 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24, + 0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75, + 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA, + 0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83, + 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, + 0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25, + 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18, + 0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4, + 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, + 0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49, + 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9, + 0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9, + 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14, + 0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C, + 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD, + 0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73, + 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D, + 0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1, + 0x33, 0x83, 0x29, 0x85 +}; + +static const unsigned char TA600_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA601_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA601_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA602_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, + 0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA602_RSA_N[] = { + 0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32, + 0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A, + 0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6, + 0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59, + 0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC, + 0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49, + 0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84, + 0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3, + 0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A, + 0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE, + 0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45, + 0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB, + 0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41, + 0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6, + 0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68, + 0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55, + 0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4, + 0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27, + 0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A, + 0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87, + 0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51, + 0x38, 0xB8, 0x4B, 0xCB +}; + +static const unsigned char TA602_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA603_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA603_EC_Q[] = { + 0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82, + 0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35, + 0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA, + 0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75, + 0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66, + 0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C, + 0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63, + 0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95, + 0xC9 +}; + +static const unsigned char TA604_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35 +}; + +static const unsigned char TA604_RSA_N[] = { + 0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7, + 0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7, + 0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B, + 0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39, + 0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD, + 0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB, + 0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E, + 0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E, + 0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85, + 0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC, + 0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B, + 0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23, + 0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03, + 0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F, + 0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B, + 0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31, + 0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30, + 0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70, + 0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93, + 0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F, + 0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B, + 0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA, + 0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF, + 0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F, + 0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F, + 0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF, + 0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8, + 0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED, + 0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D, + 0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6, + 0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19, + 0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06, + 0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1, + 0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A, + 0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8, + 0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41, + 0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F, + 0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8, + 0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD, + 0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1, + 0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0, + 0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA, + 0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB +}; + +static const unsigned char TA604_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA605_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA605_RSA_N[] = { + 0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30, + 0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D, + 0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76, + 0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B, + 0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79, + 0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52, + 0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59, + 0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A, + 0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07, + 0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20, + 0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8, + 0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B, + 0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A, + 0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58, + 0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B, + 0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA, + 0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90, + 0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03, + 0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82, + 0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04, + 0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B, + 0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40, + 0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD, + 0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24, + 0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D, + 0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0, + 0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E, + 0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00, + 0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94, + 0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00, + 0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7, + 0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63, + 0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8, + 0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4, + 0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2, + 0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE, + 0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9, + 0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5, + 0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC, + 0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F, + 0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F, + 0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D, + 0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B +}; + +static const unsigned char TA605_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA606_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA606_EC_Q[] = { + 0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42, + 0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84, + 0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6, + 0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4, + 0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92, + 0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78, + 0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE, + 0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE, + 0x42 +}; + +static const unsigned char TA607_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA607_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA607_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA608_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30, + 0x32, 0x30 +}; + +static const unsigned char TA608_EC_Q[] = { + 0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8, + 0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB, + 0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89, + 0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0, + 0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D, + 0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A, + 0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64, + 0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49, + 0xAD +}; + +static const unsigned char TA609_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA609_RSA_N[] = { + 0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53, + 0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B, + 0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0, + 0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF, + 0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50, + 0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD, + 0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30, + 0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99, + 0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94, + 0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0, + 0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81, + 0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4, + 0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D, + 0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13, + 0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A, + 0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE, + 0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73, + 0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42, + 0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29, + 0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0, + 0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B, + 0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96, + 0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58, + 0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8, + 0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48, + 0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC, + 0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50, + 0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82, + 0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8, + 0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2, + 0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74, + 0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C, + 0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45, + 0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D, + 0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33, + 0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46, + 0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06, + 0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5, + 0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6, + 0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21, + 0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B, + 0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E, + 0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47 +}; + +static const unsigned char TA609_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA610_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA610_RSA_N[] = { + 0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A, + 0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB, + 0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D, + 0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56, + 0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E, + 0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91, + 0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F, + 0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40, + 0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20, + 0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D, + 0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72, + 0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29, + 0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35, + 0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13, + 0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94, + 0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38, + 0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52, + 0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5, + 0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8, + 0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65, + 0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F, + 0xB0, 0x10, 0x0D, 0xC5 +}; + +static const unsigned char TA610_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA611_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39 +}; + +static const unsigned char TA611_RSA_N[] = { + 0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD, + 0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A, + 0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99, + 0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E, + 0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25, + 0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09, + 0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE, + 0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A, + 0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89, + 0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3, + 0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08, + 0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71, + 0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41, + 0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F, + 0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A, + 0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A, + 0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93, + 0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29, + 0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83, + 0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61, + 0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7, + 0x51, 0xF7, 0x6B, 0xA5 +}; + +static const unsigned char TA611_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA612_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA612_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA612_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA613_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA613_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA613_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA614_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA614_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA614_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA615_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA615_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA615_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA616_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA616_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA616_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA617_DN[] = { + 0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F, + 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x44, 0x45 +}; + +static const unsigned char TA617_RSA_N[] = { + 0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3, + 0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0, + 0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47, + 0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82, + 0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A, + 0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5, + 0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50, + 0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D, + 0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62, + 0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A, + 0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1, + 0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7, + 0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89, + 0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05, + 0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7, + 0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6, + 0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD, + 0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD, + 0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02, + 0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1, + 0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54, + 0x22, 0x7A, 0x8C, 0x07 +}; + +static const unsigned char TA617_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA618_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA618_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA618_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA619_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, + 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C +}; + +static const unsigned char TA619_RSA_N[] = { + 0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB, + 0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49, + 0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32, + 0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86, + 0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85, + 0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A, + 0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE, + 0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05, + 0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B, + 0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99, + 0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45, + 0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B, + 0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A, + 0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4, + 0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8, + 0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79, + 0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66, + 0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D, + 0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC, + 0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22, + 0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3, + 0xDC, 0x0E, 0x79, 0x31 +}; + +static const unsigned char TA619_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA620_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA620_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA620_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA621_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA621_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA622_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31, + 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F, + 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32 +}; + +static const unsigned char TA622_RSA_N[] = { + 0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22, + 0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F, + 0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D, + 0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89, + 0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1, + 0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E, + 0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5, + 0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B, + 0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D, + 0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2, + 0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E, + 0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2, + 0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC, + 0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A, + 0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D, + 0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25, + 0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79, + 0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF, + 0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F, + 0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9, + 0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7, + 0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45, + 0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D, + 0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77, + 0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9, + 0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6, + 0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1, + 0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B, + 0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1, + 0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8, + 0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36, + 0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0, + 0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6, + 0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27, + 0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00, + 0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE, + 0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E, + 0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37, + 0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E, + 0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8, + 0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2, + 0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5, + 0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3 +}; + +static const unsigned char TA622_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA623_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA623_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA623_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA624_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA624_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA625_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, + 0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79, + 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA625_RSA_N[] = { + 0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76, + 0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5, + 0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6, + 0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D, + 0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68, + 0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C, + 0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D, + 0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7, + 0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B, + 0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22, + 0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E, + 0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED, + 0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16, + 0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF, + 0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6, + 0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39, + 0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8, + 0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82, + 0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00, + 0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B, + 0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D, + 0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B, + 0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC, + 0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E, + 0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF, + 0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0, + 0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C, + 0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B, + 0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2, + 0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8, + 0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47, + 0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E, + 0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB, + 0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4, + 0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30, + 0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3, + 0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF, + 0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24, + 0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA, + 0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62, + 0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2, + 0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30, + 0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7 +}; + +static const unsigned char TA625_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA626_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA626_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA627_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x47, 0x33 +}; + +static const unsigned char TA627_EC_Q[] = { + 0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21, + 0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA, + 0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA, + 0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C, + 0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8, + 0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D, + 0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1, + 0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2, + 0x3E +}; + +static const unsigned char TA628_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA628_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA629_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA629_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA629_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA630_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA630_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA630_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA631_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA631_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA632_DN[] = { + 0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61, + 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F, + 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73 +}; + +static const unsigned char TA632_RSA_N[] = { + 0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45, + 0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18, + 0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31, + 0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63, + 0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0, + 0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A, + 0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58, + 0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F, + 0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC, + 0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8, + 0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5, + 0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3, + 0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07, + 0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63, + 0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78, + 0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9, + 0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F, + 0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47, + 0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83, + 0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35, + 0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D, + 0x5E, 0xE8, 0x2F, 0xC9 +}; + +static const unsigned char TA632_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA633_DN[] = { + 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, + 0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66, + 0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20, + 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, + 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA633_EC_Q[] = { + 0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75, + 0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06, + 0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04, + 0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB, + 0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16, + 0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C, + 0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33, + 0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06, + 0xE9 +}; + +static const unsigned char TA634_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA634_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA634_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA635_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20, + 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33 +}; + +static const unsigned char TA635_EC_Q[] = { + 0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22, + 0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC, + 0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46, + 0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE, + 0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62, + 0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22, + 0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6, + 0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2, + 0xA9 +}; + +static const unsigned char TA636_DN[] = { + 0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, + 0x33 +}; + +static const unsigned char TA636_EC_Q[] = { + 0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2, + 0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9, + 0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF, + 0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8, + 0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06, + 0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7, + 0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F, + 0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93, + 0xD1 +}; + +static const unsigned char TA637_DN[] = { + 0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C, + 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x43, 0x31 +}; + +static const unsigned char TA637_RSA_N[] = { + 0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A, + 0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12, + 0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F, + 0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7, + 0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F, + 0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56, + 0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC, + 0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90, + 0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A, + 0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05, + 0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE, + 0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B, + 0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3, + 0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6, + 0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20, + 0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD, + 0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21, + 0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC, + 0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E, + 0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27, + 0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69, + 0x0B, 0xE4, 0xB9, 0x0F +}; + +static const unsigned char TA637_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA638_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA638_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA638_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA639_DN[] = { + 0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, + 0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37, + 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38, + 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20, + 0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73, + 0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, + 0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, + 0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, + 0x34, 0x38, 0x29 +}; + +static const unsigned char TA639_RSA_N[] = { + 0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15, + 0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED, + 0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68, + 0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B, + 0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5, + 0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B, + 0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74, + 0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D, + 0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86, + 0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3, + 0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8, + 0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8, + 0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78, + 0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9, + 0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD, + 0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9, + 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86, + 0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00, + 0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49, + 0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D, + 0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6, + 0xD5, 0xC0, 0x07, 0xE1 +}; + +static const unsigned char TA639_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA640_DN[] = { + 0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45, + 0x43, 0x31 +}; + +static const unsigned char TA640_EC_Q[] = { + 0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0, + 0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47, + 0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B, + 0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27, + 0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27, + 0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D, + 0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2, + 0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC, + 0x20 +}; + +static const unsigned char TA641_DN[] = { + 0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C, + 0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39, + 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, + 0x32 +}; + +static const unsigned char TA641_RSA_N[] = { + 0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30, + 0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61, + 0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06, + 0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6, + 0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80, + 0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27, + 0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65, + 0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32, + 0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE, + 0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE, + 0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98, + 0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2, + 0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25, + 0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B, + 0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11, + 0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4, + 0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7, + 0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7, + 0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A, + 0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C, + 0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94, + 0x63, 0x24, 0xA4, 0x71 +}; + +static const unsigned char TA641_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA642_DN[] = { + 0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69, + 0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, + 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA642_RSA_N[] = { + 0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF, + 0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36, + 0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10, + 0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0, + 0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83, + 0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0, + 0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0, + 0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82, + 0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09, + 0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A, + 0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79, + 0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E, + 0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B, + 0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD, + 0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13, + 0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC, + 0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80, + 0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7, + 0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF, + 0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C, + 0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9, + 0xD3, 0xDA, 0xD8, 0xCB +}; + +static const unsigned char TA642_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA643_DN[] = { + 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA643_RSA_N[] = { + 0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD, + 0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74, + 0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B, + 0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69, + 0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7, + 0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6, + 0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2, + 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2, + 0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42, + 0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02, + 0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13, + 0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33, + 0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78, + 0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34, + 0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC, + 0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21, + 0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46, + 0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3, + 0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A, + 0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E, + 0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24, + 0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99, + 0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45, + 0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C, + 0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0, + 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F, + 0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E, + 0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68, + 0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09, + 0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9, + 0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08, + 0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3, + 0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA, + 0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21, + 0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6, + 0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2, + 0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67, + 0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7, + 0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A, + 0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C, + 0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3, + 0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2, + 0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31 +}; + +static const unsigned char TA643_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA644_DN[] = { + 0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54, + 0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D, + 0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA644_EC_Q[] = { + 0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE, + 0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A, + 0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48, + 0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6, + 0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B, + 0xC5, 0xFE, 0x7C, 0x7A, 0xDA +}; + +static const unsigned char TA645_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA645_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA645_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA646_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA646_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA646_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA647_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA647_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA647_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA648_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA648_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA649_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA649_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA649_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA650_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA650_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA651_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA651_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA651_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA652_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA652_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA652_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA653_DN[] = { + 0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49, + 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65, + 0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69, + 0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA653_RSA_N[] = { + 0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93, + 0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78, + 0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29, + 0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3, + 0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06, + 0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4, + 0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75, + 0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B, + 0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B, + 0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF, + 0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98, + 0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3, + 0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7, + 0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35, + 0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2, + 0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96, + 0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56, + 0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42, + 0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68, + 0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79, + 0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C, + 0x70, 0x8A, 0xC7, 0x85 +}; + +static const unsigned char TA653_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA654_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30, + 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, + 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA654_RSA_N[] = { + 0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C, + 0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF, + 0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED, + 0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9, + 0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A, + 0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C, + 0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56, + 0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6, + 0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C, + 0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D, + 0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E, + 0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10, + 0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2, + 0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD, + 0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0, + 0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64, + 0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18, + 0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD, + 0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C, + 0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53, + 0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37, + 0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D, + 0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6, + 0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84, + 0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57, + 0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB, + 0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30, + 0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9, + 0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3, + 0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16, + 0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8, + 0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE, + 0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04, + 0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D, + 0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99, + 0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD, + 0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17, + 0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45, + 0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90, + 0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86, + 0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2, + 0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30, + 0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F +}; + +static const unsigned char TA654_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA655_DN[] = { + 0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74, + 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E, + 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, + 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA655_RSA_N[] = { + 0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E, + 0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C, + 0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C, + 0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01, + 0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45, + 0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F, + 0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3, + 0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E, + 0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22, + 0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14, + 0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE, + 0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE, + 0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99, + 0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8, + 0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3, + 0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA, + 0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56, + 0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22, + 0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46, + 0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E, + 0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03, + 0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41, + 0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20, + 0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87, + 0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB, + 0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A, + 0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34, + 0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B, + 0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8, + 0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4, + 0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90, + 0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2, + 0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E, + 0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED, + 0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB, + 0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB, + 0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66, + 0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80, + 0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24, + 0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD, + 0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8, + 0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1, + 0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5 +}; + +static const unsigned char TA655_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA656_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA656_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA656_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA657_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA657_RSA_N[] = { + 0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99, + 0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC, + 0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8, + 0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B, + 0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C, + 0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92, + 0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD, + 0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43, + 0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49, + 0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A, + 0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A, + 0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0, + 0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35, + 0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00, + 0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02, + 0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90, + 0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB, + 0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC, + 0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C, + 0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A, + 0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55, + 0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B, + 0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5, + 0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2, + 0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE, + 0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33, + 0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81, + 0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18, + 0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB, + 0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB, + 0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA, + 0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91, + 0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43, + 0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03, + 0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B, + 0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E, + 0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3, + 0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81, + 0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02, + 0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54, + 0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E, + 0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95, + 0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF +}; + +static const unsigned char TA657_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA658_DN[] = { + 0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30, + 0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45 +}; + +static const unsigned char TA658_EC_Q[] = { + 0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24, + 0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82, + 0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76, + 0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE, + 0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83, + 0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56, + 0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32, + 0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19, + 0x80 +}; + +static const unsigned char TA659_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA659_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA659_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA660_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA660_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char TA660_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA661_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA661_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA661_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA662_DN[] = { + 0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61 +}; + +static const unsigned char TA662_RSA_N[] = { + 0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E, + 0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1, + 0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63, + 0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B, + 0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E, + 0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C, + 0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11, + 0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C, + 0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D, + 0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22, + 0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A, + 0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B, + 0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4, + 0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E, + 0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A, + 0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D, + 0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F, + 0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E, + 0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7, + 0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08, + 0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA, + 0x3A, 0x58, 0x06, 0xDF +}; + +static const unsigned char TA662_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA663_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA663_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA663_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA664_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA664_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA665_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA665_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA665_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA666_DN[] = { + 0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, + 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41, 0x31 +}; + +static const unsigned char TA666_RSA_N[] = { + 0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41, + 0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48, + 0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79, + 0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D, + 0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1, + 0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E, + 0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7, + 0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57, + 0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63, + 0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49, + 0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A, + 0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04, + 0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A, + 0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5, + 0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91, + 0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D, + 0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F, + 0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89, + 0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1, + 0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B, + 0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2, + 0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45, + 0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85, + 0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32, + 0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61, + 0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93, + 0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB, + 0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8, + 0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16, + 0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39, + 0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE, + 0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4, + 0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4, + 0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99, + 0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7, + 0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD, + 0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46, + 0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF, + 0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C, + 0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57, + 0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9, + 0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA, + 0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71 +}; + +static const unsigned char TA666_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA667_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D, + 0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, + 0x32, 0x33 +}; + +static const unsigned char TA667_RSA_N[] = { + 0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F, + 0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61, + 0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60, + 0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13, + 0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C, + 0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D, + 0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1, + 0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69, + 0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5, + 0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F, + 0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B, + 0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34, + 0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA, + 0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79, + 0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0, + 0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF, + 0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4, + 0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB, + 0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67, + 0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69, + 0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4, + 0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5, + 0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1, + 0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35, + 0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5, + 0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7, + 0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27, + 0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B, + 0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64, + 0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74, + 0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8, + 0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62, + 0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24, + 0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63, + 0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5, + 0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C, + 0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63, + 0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8, + 0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80, + 0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5, + 0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E, + 0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45, + 0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F +}; + +static const unsigned char TA667_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA668_DN[] = { + 0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65, + 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45, + 0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49, + 0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E, + 0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41, + 0x20, 0x57, 0x45, 0x42 +}; + +static const unsigned char TA668_EC_Q[] = { + 0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3, + 0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9, + 0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0, + 0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D, + 0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A, + 0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C, + 0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F, + 0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7, + 0x94 +}; + +static const unsigned char TA669_DN[] = { + 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, + 0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20, + 0x52, 0x4F, 0x4F, 0x54 +}; + +static const unsigned char TA669_RSA_N[] = { + 0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D, + 0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42, + 0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B, + 0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84, + 0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6, + 0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D, + 0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4, + 0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9, + 0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80, + 0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82, + 0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D, + 0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC, + 0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59, + 0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F, + 0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD, + 0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50, + 0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6, + 0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A, + 0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF, + 0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7, + 0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5, + 0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36, + 0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91, + 0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70, + 0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70, + 0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB, + 0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C, + 0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61, + 0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21, + 0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6, + 0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12, + 0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9, + 0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02, + 0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10, + 0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE, + 0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76, + 0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00, + 0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D, + 0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54, + 0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C, + 0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15, + 0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58, + 0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79 +}; + +static const unsigned char TA669_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA670_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA670_EC_Q[] = { + 0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39, + 0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA, + 0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA, + 0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73, + 0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8, + 0xD4, 0xB9, 0xCE, 0x8C, 0x1D +}; + +static const unsigned char TA671_DN[] = { + 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, + 0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA671_EC_Q[] = { + 0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1, + 0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59, + 0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C, + 0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D, + 0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C, + 0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9, + 0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A, + 0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86, + 0x4A +}; + +static const unsigned char TA672_DN[] = { + 0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA672_RSA_N[] = { + 0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB, + 0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9, + 0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C, + 0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29, + 0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70, + 0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4, + 0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9, + 0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43, + 0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39, + 0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54, + 0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5, + 0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61, + 0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5, + 0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB, + 0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC, + 0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F, + 0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9, + 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41, + 0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A, + 0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07, + 0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F, + 0x7F, 0x93, 0x90, 0xCF +}; + +static const unsigned char TA672_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA673_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA673_RSA_N[] = { + 0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83, + 0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88, + 0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24, + 0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81, + 0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82, + 0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB, + 0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F, + 0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06, + 0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9, + 0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA, + 0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5, + 0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A, + 0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00, + 0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73, + 0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2, + 0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68, + 0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14, + 0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31, + 0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A, + 0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54, + 0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6, + 0x69, 0x85, 0x82, 0x17 +}; + +static const unsigned char TA673_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA674_DN[] = { + 0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, + 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E +}; + +static const unsigned char TA674_RSA_N[] = { + 0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C, + 0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6, + 0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F, + 0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1, + 0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B, + 0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66, + 0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89, + 0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F, + 0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19, + 0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68, + 0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31, + 0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB, + 0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89, + 0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E, + 0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10, + 0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C, + 0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C, + 0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4, + 0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D, + 0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50, + 0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39, + 0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93, + 0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA, + 0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56, + 0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5, + 0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49, + 0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC, + 0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C, + 0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2, + 0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E, + 0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65, + 0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11, + 0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05, + 0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59, + 0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1, + 0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D, + 0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95, + 0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD, + 0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65, + 0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC, + 0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70, + 0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32, + 0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF +}; + +static const unsigned char TA674_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA675_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36 +}; + +static const unsigned char TA675_EC_Q[] = { + 0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34, + 0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27, + 0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97, + 0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2, + 0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37, + 0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C, + 0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB, + 0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C, + 0x20 +}; + +static const unsigned char TA676_DN[] = { + 0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, + 0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, + 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36 +}; + +static const unsigned char TA676_RSA_N[] = { + 0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26, + 0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63, + 0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67, + 0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B, + 0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F, + 0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99, + 0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16, + 0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2, + 0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE, + 0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4, + 0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40, + 0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1, + 0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C, + 0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3, + 0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84, + 0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B, + 0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87, + 0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78, + 0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A, + 0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14, + 0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08, + 0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1, + 0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB, + 0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6, + 0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E, + 0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0, + 0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37, + 0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74, + 0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89, + 0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82, + 0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9, + 0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C, + 0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32, + 0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C, + 0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3, + 0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D, + 0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF, + 0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA, + 0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F, + 0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B, + 0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B, + 0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1, + 0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3 +}; + +static const unsigned char TA676_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA677_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65, + 0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20, + 0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA677_RSA_N[] = { + 0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77, + 0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B, + 0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5, + 0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38, + 0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8, + 0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59, + 0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C, + 0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A, + 0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E, + 0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7, + 0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5, + 0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC, + 0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85, + 0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0, + 0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A, + 0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6, + 0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19, + 0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E, + 0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85, + 0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE, + 0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA, + 0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89, + 0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A, + 0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D, + 0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20, + 0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07, + 0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4, + 0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB, + 0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97, + 0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4, + 0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C, + 0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E, + 0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62, + 0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E, + 0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4, + 0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF, + 0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, + 0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30, + 0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7, + 0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49, + 0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0, + 0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6, + 0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63 +}; + +static const unsigned char TA677_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA678_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, + 0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E, + 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C, + 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA678_RSA_N[] = { + 0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F, + 0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65, + 0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9, + 0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0, + 0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0, + 0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03, + 0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB, + 0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87, + 0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E, + 0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE, + 0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A, + 0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D, + 0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99, + 0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62, + 0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE, + 0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA, + 0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8, + 0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC, + 0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B, + 0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11, + 0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74, + 0xEA, 0x97, 0x1B, 0xAF +}; + +static const unsigned char TA678_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA679_DN[] = { + 0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64, + 0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F, + 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA679_RSA_N[] = { + 0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18, + 0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20, + 0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6, + 0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1, + 0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22, + 0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75, + 0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D, + 0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A, + 0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA, + 0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66, + 0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2, + 0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07, + 0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53, + 0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C, + 0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29, + 0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39, + 0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62, + 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A, + 0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB, + 0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46, + 0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69, + 0x46, 0xB3, 0xE0, 0x47 +}; + +static const unsigned char TA679_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA680_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x31 +}; + +static const unsigned char TA680_RSA_N[] = { + 0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF, + 0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D, + 0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC, + 0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9, + 0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3, + 0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27, + 0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E, + 0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3, + 0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90, + 0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E, + 0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2, + 0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F, + 0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6, + 0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D, + 0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08, + 0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B, + 0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB, + 0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84, + 0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35, + 0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20, + 0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A, + 0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D, + 0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9, + 0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC, + 0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01, + 0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55, + 0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25, + 0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4, + 0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C, + 0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3, + 0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED, + 0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A, + 0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6, + 0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63, + 0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33, + 0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65, + 0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8, + 0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA, + 0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C, + 0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F, + 0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA, + 0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A, + 0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95 +}; + +static const unsigned char TA680_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA681_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA681_RSA_N[] = { + 0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06, + 0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA, + 0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6, + 0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE, + 0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C, + 0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B, + 0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39, + 0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19, + 0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83, + 0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B, + 0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E, + 0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5, + 0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8, + 0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7, + 0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B, + 0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40, + 0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1, + 0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26, + 0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4, + 0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8, + 0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55, + 0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A, + 0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73, + 0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7, + 0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C, + 0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB, + 0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A, + 0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7, + 0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA, + 0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72, + 0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF, + 0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44, + 0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97, + 0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E, + 0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD, + 0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C, + 0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE, + 0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5, + 0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE, + 0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16, + 0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB, + 0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD, + 0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7 +}; + +static const unsigned char TA681_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA682_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x33 +}; + +static const unsigned char TA682_EC_Q[] = { + 0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB, + 0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6, + 0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6, + 0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C, + 0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04, + 0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B, + 0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44, + 0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0, + 0x27 +}; + +static const unsigned char TA683_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, + 0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, + 0x34 +}; + +static const unsigned char TA683_EC_Q[] = { + 0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35, + 0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6, + 0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73, + 0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40, + 0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A, + 0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F, + 0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B, + 0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D, + 0x8A +}; + +static const unsigned char TA684_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, + 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA684_EC_Q[] = { + 0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49, + 0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65, + 0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C, + 0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34, + 0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2, + 0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60, + 0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A, + 0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1, + 0xB7 +}; + +static const unsigned char TA685_DN[] = { + 0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, + 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, + 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, + 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48, + 0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x32, 0x31 +}; + +static const unsigned char TA685_RSA_N[] = { + 0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24, + 0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F, + 0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7, + 0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16, + 0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4, + 0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C, + 0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A, + 0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8, + 0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88, + 0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6, + 0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B, + 0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA, + 0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7, + 0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30, + 0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB, + 0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB, + 0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C, + 0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA, + 0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD, + 0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76, + 0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A, + 0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38, + 0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13, + 0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22, + 0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15, + 0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3, + 0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03, + 0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38, + 0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD, + 0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7, + 0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE, + 0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F, + 0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B, + 0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20, + 0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E, + 0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50, + 0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B, + 0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72, + 0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08, + 0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46, + 0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB, + 0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65, + 0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3 +}; + +static const unsigned char TA685_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA686_DN[] = { + 0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x31, 0x35 +}; + +static const unsigned char TA686_EC_Q[] = { + 0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31, + 0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A, + 0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6, + 0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76, + 0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF, + 0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D, + 0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A, + 0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1, + 0x46 +}; + +static const unsigned char TA687_DN[] = { + 0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30, + 0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, + 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, + 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, + 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, + 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, + 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, + 0x35 +}; + +static const unsigned char TA687_RSA_N[] = { + 0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D, + 0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39, + 0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90, + 0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28, + 0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01, + 0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D, + 0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0, + 0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80, + 0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A, + 0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37, + 0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A, + 0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F, + 0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09, + 0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73, + 0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50, + 0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35, + 0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E, + 0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07, + 0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92, + 0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C, + 0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95, + 0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F, + 0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7, + 0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8, + 0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B, + 0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99, + 0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1, + 0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96, + 0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97, + 0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25, + 0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D, + 0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11, + 0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7, + 0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF, + 0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9, + 0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2, + 0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1, + 0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78, + 0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46, + 0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F, + 0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4, + 0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7, + 0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B +}; + +static const unsigned char TA687_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA688_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31 +}; + +static const unsigned char TA688_RSA_N[] = { + 0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74, + 0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47, + 0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A, + 0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1, + 0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9, + 0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3, + 0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA, + 0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79, + 0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0, + 0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75, + 0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C, + 0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E, + 0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46, + 0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97, + 0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF, + 0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D, + 0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4, + 0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC, + 0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F, + 0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD, + 0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47, + 0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED, + 0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30, + 0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3, + 0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97, + 0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77, + 0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6, + 0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A, + 0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC, + 0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1, + 0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F, + 0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C, + 0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11, + 0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5, + 0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD, + 0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0, + 0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6, + 0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58, + 0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45, + 0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55, + 0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86, + 0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E, + 0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED +}; + +static const unsigned char TA688_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA689_DN[] = { + 0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F, + 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F, + 0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA689_RSA_N[] = { + 0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03, + 0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E, + 0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C, + 0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF, + 0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33, + 0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9, + 0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58, + 0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD, + 0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB, + 0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41, + 0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29, + 0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E, + 0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C, + 0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98, + 0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B, + 0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06, + 0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73, + 0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD, + 0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12, + 0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08, + 0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C, + 0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E, + 0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6, + 0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01, + 0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2, + 0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1, + 0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B, + 0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55, + 0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A, + 0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D, + 0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7, + 0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3, + 0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39, + 0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F, + 0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7, + 0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC, + 0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C, + 0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B, + 0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52, + 0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB, + 0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1, + 0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F, + 0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F +}; + +static const unsigned char TA689_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA690_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA690_RSA_N[] = { + 0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F, + 0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9, + 0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72, + 0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74, + 0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD, + 0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB, + 0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3, + 0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32, + 0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97, + 0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8, + 0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA, + 0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73, + 0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA, + 0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40, + 0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23, + 0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD, + 0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB, + 0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4, + 0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72, + 0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1, + 0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90, + 0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0, + 0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7, + 0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC, + 0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A, + 0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08, + 0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13, + 0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A, + 0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38, + 0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86, + 0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52, + 0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34, + 0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99, + 0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31, + 0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20, + 0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46, + 0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33, + 0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78, + 0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80, + 0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1, + 0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31, + 0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE, + 0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7 +}; + +static const unsigned char TA690_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA691_DN[] = { + 0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, + 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64, + 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C, + 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +static const unsigned char TA691_RSA_N[] = { + 0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB, + 0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A, + 0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26, + 0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8, + 0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76, + 0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0, + 0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0, + 0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4, + 0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24, + 0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F, + 0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB, + 0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A, + 0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97, + 0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20, + 0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF, + 0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72, + 0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6, + 0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36, + 0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56, + 0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4, + 0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1, + 0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44, + 0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC, + 0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D, + 0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01, + 0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D, + 0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A, + 0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC, + 0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E, + 0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5, + 0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1, + 0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC, + 0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5, + 0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB, + 0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F, + 0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46, + 0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA, + 0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29, + 0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06, + 0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4, + 0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95, + 0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0, + 0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7 +}; + +static const unsigned char TA691_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA692_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char TA692_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char TA692_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA693_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32 +}; + +static const unsigned char TA693_EC_Q[] = { + 0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3, + 0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D, + 0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60, + 0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A, + 0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82, + 0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77, + 0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF, + 0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F, + 0xEA +}; + +static const unsigned char TA694_DN[] = { + 0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41, + 0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, + 0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D +}; + +static const unsigned char TA694_RSA_N[] = { + 0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65, + 0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B, + 0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55, + 0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8, + 0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56, + 0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA, + 0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B, + 0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A, + 0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E, + 0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0, + 0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7, + 0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D, + 0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1, + 0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41, + 0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0, + 0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54, + 0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4, + 0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54, + 0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C, + 0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D, + 0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3, + 0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1, + 0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9, + 0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8, + 0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD, + 0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1, + 0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF, + 0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5, + 0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C, + 0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C, + 0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3, + 0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F, + 0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F, + 0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47, + 0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7, + 0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4, + 0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2, + 0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16, + 0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62, + 0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F, + 0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72, + 0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46, + 0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17 +}; + +static const unsigned char TA694_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA695_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69, + 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68, + 0x75 +}; + +static const unsigned char TA695_RSA_N[] = { + 0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42, + 0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD, + 0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44, + 0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74, + 0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF, + 0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F, + 0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99, + 0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D, + 0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75, + 0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0, + 0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9, + 0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7, + 0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF, + 0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E, + 0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50, + 0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C, + 0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE, + 0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1, + 0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51, + 0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82, + 0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF, + 0x0B, 0xB5, 0xFA, 0xB5 +}; + +static const unsigned char TA695_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA696_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA696_EC_Q[] = { + 0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80, + 0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC, + 0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D, + 0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79, + 0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC, + 0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81, + 0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89, + 0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78, + 0xC0 +}; + +static const unsigned char TA697_DN[] = { + 0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37 +}; + +static const unsigned char TA697_RSA_N[] = { + 0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95, + 0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9, + 0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50, + 0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57, + 0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B, + 0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19, + 0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43, + 0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, + 0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50, + 0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6, + 0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60, + 0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F, + 0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05, + 0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC, + 0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33, + 0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91, + 0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70, + 0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B, + 0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78, + 0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22, + 0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F, + 0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49, + 0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B, + 0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27, + 0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3, + 0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9, + 0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B, + 0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51, + 0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6, + 0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57, + 0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98, + 0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F, + 0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3, + 0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC, + 0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57, + 0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6, + 0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69, + 0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4, + 0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81, + 0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2, + 0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB, + 0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08, + 0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5 +}; + +static const unsigned char TA697_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA698_DN[] = { + 0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, + 0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52, + 0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, + 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA698_RSA_N[] = { + 0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90, + 0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B, + 0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75, + 0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33, + 0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26, + 0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E, + 0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02, + 0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6, + 0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A, + 0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6, + 0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15, + 0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29, + 0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90, + 0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72, + 0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0, + 0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8, + 0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71, + 0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C, + 0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C, + 0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94, + 0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71, + 0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2, + 0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87, + 0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE, + 0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76, + 0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D, + 0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0, + 0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D, + 0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2, + 0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA, + 0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F, + 0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D, + 0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC, + 0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7, + 0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C, + 0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60, + 0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5, + 0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3, + 0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8, + 0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30, + 0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51, + 0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62, + 0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D +}; + +static const unsigned char TA698_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA699_DN[] = { + 0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65, + 0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E, + 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B, + 0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63, + 0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61, + 0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91, + 0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, + 0x6E, 0x79 +}; + +static const unsigned char TA699_RSA_N[] = { + 0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3, + 0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64, + 0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3, + 0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F, + 0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2, + 0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70, + 0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70, + 0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1, + 0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE, + 0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43, + 0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79, + 0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01, + 0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A, + 0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55, + 0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F, + 0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96, + 0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97, + 0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7, + 0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D, + 0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7, + 0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2, + 0x42, 0x76, 0xC0, 0x1B +}; + +static const unsigned char TA699_RSA_E[] = { + 0xA8, 0x8B +}; + +static const unsigned char TA700_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA700_RSA_N[] = { + 0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2, + 0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27, + 0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A, + 0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F, + 0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53, + 0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B, + 0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21, + 0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1, + 0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99, + 0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E, + 0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0, + 0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84, + 0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D, + 0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8, + 0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28, + 0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07, + 0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37, + 0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E, + 0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53, + 0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E, + 0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B, + 0xEF, 0x82, 0x48, 0xC7 +}; + +static const unsigned char TA700_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA701_DN[] = { + 0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30, + 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, + 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54, + 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C, + 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA701_EC_Q[] = { + 0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1, + 0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24, + 0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB, + 0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82, + 0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2, + 0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87, + 0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6, + 0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31, + 0x91 +}; + +static const unsigned char TA702_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA702_RSA_N[] = { + 0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C, + 0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B, + 0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE, + 0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87, + 0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC, + 0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35, + 0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01, + 0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8, + 0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC, + 0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E, + 0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88, + 0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18, + 0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5, + 0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A, + 0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09, + 0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82, + 0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81, + 0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5, + 0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD, + 0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3, + 0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0, + 0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF, + 0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69, + 0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF, + 0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9, + 0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9, + 0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91, + 0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16, + 0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76, + 0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F, + 0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89, + 0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95, + 0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF, + 0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74, + 0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D, + 0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB, + 0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF, + 0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2, + 0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6, + 0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F, + 0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7, + 0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03, + 0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53 +}; + +static const unsigned char TA702_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA703_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA703_RSA_N[] = { + 0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB, + 0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21, + 0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D, + 0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B, + 0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5, + 0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3, + 0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17, + 0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72, + 0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2, + 0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC, + 0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87, + 0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25, + 0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0, + 0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB, + 0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3, + 0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F, + 0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC, + 0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14, + 0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1, + 0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE, + 0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43, + 0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD, + 0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13, + 0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22, + 0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55, + 0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2, + 0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E, + 0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB, + 0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34, + 0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85, + 0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1, + 0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72, + 0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32, + 0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77, + 0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B, + 0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2, + 0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42, + 0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D, + 0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF, + 0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16, + 0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50, + 0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02, + 0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7 +}; + +static const unsigned char TA703_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA704_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32 +}; + +static const unsigned char TA704_RSA_N[] = { + 0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A, + 0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB, + 0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF, + 0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C, + 0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11, + 0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18, + 0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10, + 0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E, + 0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B, + 0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B, + 0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D, + 0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76, + 0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05, + 0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC, + 0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5, + 0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44, + 0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73, + 0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1, + 0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7, + 0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75, + 0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D, + 0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF, + 0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF, + 0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F, + 0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4, + 0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0, + 0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9, + 0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88, + 0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23, + 0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6, + 0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D, + 0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63, + 0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3, + 0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C, + 0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23, + 0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95, + 0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C, + 0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A, + 0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A, + 0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B, + 0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44, + 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47, + 0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B +}; + +static const unsigned char TA704_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA705_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, + 0x47, 0x33 +}; + +static const unsigned char TA705_RSA_N[] = { + 0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A, + 0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14, + 0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A, + 0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF, + 0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE, + 0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3, + 0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16, + 0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73, + 0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C, + 0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35, + 0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5, + 0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46, + 0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9, + 0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF, + 0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA, + 0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0, + 0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77, + 0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13, + 0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E, + 0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A, + 0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39, + 0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F, + 0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90, + 0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9, + 0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4, + 0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C, + 0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B, + 0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D, + 0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46, + 0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C, + 0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8, + 0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95, + 0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B, + 0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80, + 0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0, + 0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D, + 0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB, + 0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D, + 0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E, + 0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01, + 0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF, + 0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13, + 0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9 +}; + +static const unsigned char TA705_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA706_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C, + 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33 +}; + +static const unsigned char TA706_RSA_N[] = { + 0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE, + 0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88, + 0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD, + 0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A, + 0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99, + 0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD, + 0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2, + 0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45, + 0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01, + 0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8, + 0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA, + 0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5, + 0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13, + 0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50, + 0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE, + 0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC, + 0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD, + 0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06, + 0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1, + 0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2, + 0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5, + 0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B, + 0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98, + 0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8, + 0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84, + 0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8, + 0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05, + 0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8, + 0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99, + 0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22, + 0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52, + 0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20, + 0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63, + 0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3, + 0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55, + 0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0, + 0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C, + 0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3, + 0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB, + 0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F, + 0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48, + 0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F, + 0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB +}; + +static const unsigned char TA706_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA707_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, + 0x36 +}; + +static const unsigned char TA707_EC_Q[] = { + 0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3, + 0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56, + 0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79, + 0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37, + 0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00, + 0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0, + 0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE, + 0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43, + 0xA3 +}; + +static const unsigned char TA708_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69, + 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, + 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, + 0x36 +}; + +static const unsigned char TA708_RSA_N[] = { + 0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47, + 0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48, + 0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D, + 0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F, + 0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F, + 0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63, + 0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81, + 0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C, + 0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5, + 0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC, + 0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9, + 0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5, + 0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7, + 0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1, + 0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91, + 0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21, + 0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC, + 0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81, + 0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8, + 0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42, + 0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9, + 0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06, + 0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66, + 0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D, + 0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D, + 0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B, + 0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28, + 0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49, + 0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94, + 0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C, + 0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4, + 0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79, + 0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86, + 0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD, + 0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44, + 0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83, + 0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF, + 0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A, + 0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB, + 0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD, + 0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18, + 0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9, + 0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF +}; + +static const unsigned char TA708_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA709_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA709_RSA_N[] = { + 0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13, + 0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38, + 0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C, + 0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29, + 0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98, + 0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB, + 0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1, + 0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98, + 0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4, + 0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7, + 0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0, + 0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5, + 0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10, + 0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39, + 0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98, + 0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06, + 0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA, + 0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04, + 0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42, + 0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18, + 0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73, + 0xE7, 0x8F, 0x7A, 0x43 +}; + +static const unsigned char TA709_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA710_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32 +}; + +static const unsigned char TA710_RSA_N[] = { + 0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4, + 0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE, + 0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C, + 0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF, + 0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07, + 0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5, + 0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79, + 0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13, + 0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA, + 0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF, + 0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7, + 0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25, + 0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1, + 0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16, + 0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44, + 0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B, + 0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE, + 0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26, + 0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5, + 0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C, + 0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11, + 0x12, 0x39, 0xA0, 0xAD +}; + +static const unsigned char TA710_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA711_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34 +}; + +static const unsigned char TA711_RSA_N[] = { + 0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1, + 0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A, + 0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24, + 0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5, + 0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC, + 0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95, + 0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2, + 0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2, + 0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4, + 0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5, + 0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7, + 0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E, + 0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0, + 0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78, + 0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82, + 0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68, + 0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9, + 0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F, + 0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74, + 0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10, + 0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5, + 0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA, + 0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28, + 0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24, + 0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4, + 0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A, + 0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0, + 0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16, + 0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED, + 0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02, + 0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B, + 0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40, + 0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A, + 0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7, + 0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE, + 0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C, + 0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4, + 0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F, + 0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA, + 0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82, + 0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72, + 0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58, + 0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01 +}; + +static const unsigned char TA711_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA712_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20, + 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35 +}; + +static const unsigned char TA712_EC_Q[] = { + 0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60, + 0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D, + 0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14, + 0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95, + 0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D, + 0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01, + 0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B, + 0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69, + 0x8F +}; + +static const unsigned char TA713_DN[] = { + 0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x43, 0x41 +}; + +static const unsigned char TA713_RSA_N[] = { + 0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F, + 0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40, + 0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62, + 0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41, + 0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6, + 0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94, + 0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D, + 0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF, + 0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08, + 0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D, + 0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E, + 0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26, + 0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0, + 0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66, + 0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4, + 0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2, + 0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44, + 0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D, + 0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B, + 0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66, + 0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15, + 0x59, 0x87, 0xBA, 0xBB +}; + +static const unsigned char TA713_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA714_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x43, 0x41, 0x31 +}; + +static const unsigned char TA714_EC_Q[] = { + 0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3, + 0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7, + 0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47, + 0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74, + 0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99, + 0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6, + 0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B, + 0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50, + 0xB1 +}; + +static const unsigned char TA715_DN[] = { + 0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F, + 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA715_RSA_N[] = { + 0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4, + 0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC, + 0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A, + 0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5, + 0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34, + 0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80, + 0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41, + 0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12, + 0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65, + 0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15, + 0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9, + 0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16, + 0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4, + 0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE, + 0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78, + 0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16, + 0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B, + 0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF, + 0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10, + 0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5, + 0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34, + 0x27, 0x1A, 0x75, 0xFB +}; + +static const unsigned char TA715_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA716_DN[] = { + 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA716_EC_Q[] = { + 0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07, + 0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86, + 0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00, + 0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC, + 0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08, + 0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35, + 0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E, + 0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09, + 0x29 +}; + +static const unsigned char TA717_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, + 0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, + 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, + 0x32 +}; + +static const unsigned char TA717_RSA_N[] = { + 0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46, + 0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD, + 0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57, + 0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41, + 0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23, + 0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26, + 0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37, + 0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17, + 0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49, + 0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B, + 0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F, + 0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE, + 0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB, + 0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB, + 0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E, + 0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA, + 0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3, + 0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B, + 0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22, + 0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1, + 0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61, + 0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6, + 0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57, + 0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF, + 0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7, + 0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8, + 0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4, + 0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88, + 0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F, + 0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, + 0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68, + 0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16, + 0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6, + 0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93, + 0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99, + 0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20, + 0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41, + 0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73, + 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5, + 0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B, + 0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F, + 0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57, + 0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77 +}; + +static const unsigned char TA717_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA718_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x43, 0x43 +}; + +static const unsigned char TA718_EC_Q[] = { + 0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28, + 0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC, + 0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47, + 0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27, + 0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F, + 0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D, + 0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95, + 0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47, + 0xD3 +}; + +static const unsigned char TA719_DN[] = { + 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F, + 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, + 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x52, 0x53, 0x41 +}; + +static const unsigned char TA719_RSA_N[] = { + 0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67, + 0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4, + 0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B, + 0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66, + 0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16, + 0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41, + 0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E, + 0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41, + 0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14, + 0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF, + 0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A, + 0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75, + 0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7, + 0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04, + 0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2, + 0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3, + 0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D, + 0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93, + 0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8, + 0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D, + 0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F, + 0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25, + 0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2, + 0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF, + 0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF, + 0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9, + 0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D, + 0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F, + 0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38, + 0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA, + 0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72, + 0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07, + 0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16, + 0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96, + 0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89, + 0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA, + 0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7, + 0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63, + 0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE, + 0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70, + 0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4, + 0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD, + 0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87 +}; + +static const unsigned char TA719_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA720_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA720_EC_Q[] = { + 0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D, + 0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60, + 0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D, + 0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51, + 0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90, + 0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10, + 0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5, + 0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54, + 0x81 +}; + +static const unsigned char TA721_DN[] = { + 0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32 +}; + +static const unsigned char TA721_RSA_N[] = { + 0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23, + 0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D, + 0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25, + 0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63, + 0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F, + 0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE, + 0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64, + 0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC, + 0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39, + 0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD, + 0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72, + 0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59, + 0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82, + 0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3, + 0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0, + 0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53, + 0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E, + 0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D, + 0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4, + 0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1, + 0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2, + 0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28, + 0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3, + 0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52, + 0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C, + 0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE, + 0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32, + 0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E, + 0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0, + 0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B, + 0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1, + 0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05, + 0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96, + 0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F, + 0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36, + 0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0, + 0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF, + 0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9, + 0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5, + 0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8, + 0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67, + 0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48, + 0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F +}; + +static const unsigned char TA721_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA722_DN[] = { + 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA722_RSA_N[] = { + 0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB, + 0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC, + 0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66, + 0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26, + 0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4, + 0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B, + 0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C, + 0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C, + 0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87, + 0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D, + 0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + 0x44, 0xA0, 0x01, 0xAB +}; + +static const unsigned char TA722_RSA_E[] = { + 0x03 +}; + +static const unsigned char TA723_DN[] = { + 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, + 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + 0x47, 0x32 +}; + +static const unsigned char TA723_RSA_N[] = { + 0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B, + 0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18, + 0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1, + 0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77, + 0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC, + 0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89, + 0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5, + 0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4, + 0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71, + 0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4, + 0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E, + 0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB, + 0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82, + 0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E, + 0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F, + 0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76, + 0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4, + 0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8, + 0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B, + 0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26, + 0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3, + 0xEC, 0x1F, 0x90, 0xF1 +}; + +static const unsigned char TA723_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA724_DN[] = { + 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, + 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, + 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, + 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA724_RSA_N[] = { + 0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97, + 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, + 0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63, + 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, + 0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A, + 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, + 0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF, + 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, + 0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84, + 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, + 0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70, + 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, + 0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47, + 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, + 0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9, + 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, + 0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32, + 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, + 0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F, + 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, + 0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, + 0x39, 0x8B, 0x7F, 0x05 +}; + +static const unsigned char TA724_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA725_DN[] = { + 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, + 0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, + 0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32 +}; + +static const unsigned char TA725_RSA_N[] = { + 0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D, + 0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42, + 0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50, + 0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02, + 0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3, + 0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F, + 0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D, + 0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42, + 0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C, + 0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F, + 0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62, + 0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3, + 0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5, + 0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91, + 0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33, + 0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F, + 0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB, + 0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B, + 0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05, + 0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13, + 0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89, + 0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71, + 0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04, + 0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E, + 0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89, + 0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50, + 0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD, + 0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD, + 0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29, + 0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7, + 0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95, + 0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03, + 0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10, + 0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF, + 0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C, + 0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C, + 0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56, + 0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5, + 0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2, + 0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A, + 0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98, + 0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC, + 0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1 +}; + +static const unsigned char TA725_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA726_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A, + 0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E, + 0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46, + 0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32 +}; + +static const unsigned char TA726_RSA_N[] = { + 0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7, + 0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76, + 0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4, + 0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D, + 0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13, + 0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A, + 0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9, + 0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03, + 0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34, + 0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D, + 0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE, + 0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F, + 0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20, + 0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89, + 0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B, + 0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96, + 0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40, + 0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A, + 0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C, + 0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31, + 0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C, + 0x38, 0x8E, 0x58, 0xAF +}; + +static const unsigned char TA726_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA727_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x30 +}; + +static const unsigned char TA727_EC_Q[] = { + 0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A, + 0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15, + 0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE, + 0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE, + 0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50, + 0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49, + 0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF, + 0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2, + 0x1B +}; + +static const unsigned char TA728_DN[] = { + 0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54, + 0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B, + 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x32, 0x30, 0x32, 0x33 +}; + +static const unsigned char TA728_RSA_N[] = { + 0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB, + 0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71, + 0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF, + 0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B, + 0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36, + 0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72, + 0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC, + 0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6, + 0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8, + 0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53, + 0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE, + 0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51, + 0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F, + 0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63, + 0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC, + 0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6, + 0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F, + 0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05, + 0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F, + 0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B, + 0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31, + 0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1, + 0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1, + 0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9, + 0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F, + 0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72, + 0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33, + 0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B, + 0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B, + 0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2, + 0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC, + 0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3, + 0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3, + 0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC, + 0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34, + 0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29, + 0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46, + 0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98, + 0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52, + 0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F, + 0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93, + 0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB, + 0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B +}; + +static const unsigned char TA728_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA729_DN[] = { + 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C, + 0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, + 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32 +}; + +static const unsigned char TA729_RSA_N[] = { + 0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2, + 0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE, + 0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB, + 0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5, + 0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2, + 0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72, + 0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34, + 0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD, + 0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D, + 0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96, + 0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89, + 0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15, + 0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1, + 0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4, + 0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35, + 0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D, + 0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9, + 0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52, + 0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8, + 0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2, + 0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92, + 0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6, + 0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35, + 0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48, + 0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C, + 0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC, + 0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5, + 0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A, + 0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02, + 0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93, + 0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04, + 0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E, + 0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E, + 0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C, + 0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27, + 0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98, + 0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D, + 0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18, + 0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7, + 0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B, + 0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05, + 0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED, + 0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5 +}; + +static const unsigned char TA729_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA730_DN[] = { + 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, + 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52, + 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31 +}; + +static const unsigned char TA730_RSA_N[] = { + 0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E, + 0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80, + 0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3, + 0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C, + 0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC, + 0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B, + 0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8, + 0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B, + 0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4, + 0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55, + 0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E, + 0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18, + 0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23, + 0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19, + 0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB, + 0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D, + 0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C, + 0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39, + 0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD, + 0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5, + 0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18, + 0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16, + 0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D, + 0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17, + 0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8, + 0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C, + 0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63, + 0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32, + 0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50, + 0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F, + 0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA, + 0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D, + 0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F, + 0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79, + 0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F, + 0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F, + 0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B, + 0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12, + 0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69, + 0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16, + 0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F, + 0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E, + 0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D +}; + +static const unsigned char TA730_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA731_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33 +}; + +static const unsigned char TA731_RSA_N[] = { + 0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0, + 0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2, + 0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13, + 0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B, + 0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7, + 0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE, + 0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A, + 0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D, + 0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2, + 0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC, + 0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40, + 0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5, + 0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F, + 0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10, + 0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1, + 0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38, + 0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB, + 0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E, + 0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35, + 0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72, + 0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56, + 0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E, + 0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93, + 0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD, + 0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9, + 0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78, + 0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8, + 0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68, + 0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F, + 0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78, + 0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70, + 0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26, + 0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11, + 0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1, + 0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B, + 0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85, + 0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7, + 0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED, + 0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58, + 0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32, + 0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05, + 0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF, + 0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81 +}; + +static const unsigned char TA731_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA732_DN[] = { + 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, + 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, + 0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34 +}; + +static const unsigned char TA732_EC_Q[] = { + 0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09, + 0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB, + 0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC, + 0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D, + 0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6, + 0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D, + 0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9, + 0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20, + 0x98 +}; + +static const unsigned char TA733_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA733_RSA_N[] = { + 0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD, + 0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5, + 0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2, + 0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3, + 0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93, + 0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D, + 0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89, + 0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE, + 0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F, + 0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC, + 0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0, + 0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5, + 0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C, + 0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4, + 0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B, + 0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3, + 0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE, + 0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27, + 0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E, + 0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26, + 0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C, + 0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54, + 0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C, + 0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46, + 0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B, + 0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4, + 0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2, + 0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84, + 0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4, + 0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14, + 0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2, + 0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72, + 0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D, + 0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B, + 0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6, + 0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05, + 0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72, + 0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6, + 0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35, + 0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7, + 0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90, + 0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7, + 0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB +}; + +static const unsigned char TA733_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA734_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA734_EC_Q[] = { + 0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60, + 0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80, + 0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06, + 0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA, + 0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD, + 0x09, 0x3A, 0xA6, 0x3F, 0xAD +}; + +static const unsigned char TA735_DN[] = { + 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, + 0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20, + 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20, + 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, + 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA735_EC_Q[] = { + 0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45, + 0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3, + 0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97, + 0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A, + 0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4, + 0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E, + 0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9, + 0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65, + 0xA0 +}; + +static const unsigned char TA736_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x32 +}; + +static const unsigned char TA736_RSA_N[] = { + 0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4, + 0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4, + 0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2, + 0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07, + 0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B, + 0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84, + 0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49, + 0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7, + 0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA, + 0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12, + 0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3, + 0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB, + 0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33, + 0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72, + 0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B, + 0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1, + 0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43, + 0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D, + 0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F, + 0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39, + 0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B, + 0x44, 0xA2, 0xD5, 0xC7 +}; + +static const unsigned char TA736_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA737_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, + 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62, + 0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16, + 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54, + 0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + 0x33 +}; + +static const unsigned char TA737_RSA_N[] = { + 0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76, + 0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42, + 0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C, + 0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3, + 0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6, + 0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC, + 0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58, + 0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90, + 0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE, + 0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5, + 0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A, + 0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A, + 0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75, + 0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0, + 0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33, + 0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96, + 0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5, + 0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70, + 0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C, + 0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99, + 0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F, + 0xD6, 0x83, 0x1E, 0xB3 +}; + +static const unsigned char TA737_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA738_DN[] = { + 0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B, + 0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65, + 0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65, + 0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20, + 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75, + 0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, + 0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B, + 0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, + 0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, + 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75, + 0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20, + 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20, + 0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31 +}; + +static const unsigned char TA738_RSA_N[] = { + 0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37, + 0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50, + 0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D, + 0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC, + 0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40, + 0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5, + 0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC, + 0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55, + 0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5, + 0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53, + 0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE, + 0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF, + 0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90, + 0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12, + 0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A, + 0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0, + 0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85, + 0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B, + 0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B, + 0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80, + 0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9, + 0xF9, 0xEC, 0x4F, 0x17 +}; + +static const unsigned char TA738_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA739_DN[] = { + 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, + 0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, + 0x20, 0x43, 0x41 +}; + +static const unsigned char TA739_RSA_N[] = { + 0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5, + 0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F, + 0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4, + 0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC, + 0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4, + 0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8, + 0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26, + 0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD, + 0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A, + 0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57, + 0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E, + 0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35, + 0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56, + 0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A, + 0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9, + 0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47, + 0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29, + 0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96, + 0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F, + 0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7, + 0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2, + 0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF, + 0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10, + 0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23, + 0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2, + 0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79, + 0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9, + 0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24, + 0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6, + 0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32, + 0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E, + 0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD, + 0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23, + 0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F, + 0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B, + 0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6, + 0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4, + 0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC, + 0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97, + 0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C, + 0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14, + 0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7, + 0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97 +}; + +static const unsigned char TA739_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA740_DN[] = { + 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42, + 0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA740_RSA_N[] = { + 0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE, + 0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B, + 0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67, + 0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED, + 0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C, + 0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3, + 0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE, + 0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20, + 0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7, + 0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA, + 0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0, + 0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F, + 0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE, + 0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F, + 0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60, + 0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3, + 0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7, + 0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29, + 0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45, + 0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF, + 0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA, + 0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E, + 0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0, + 0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA, + 0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40, + 0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09, + 0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52, + 0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89, + 0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20, + 0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26, + 0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B, + 0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4, + 0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0, + 0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2, + 0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F, + 0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD, + 0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C, + 0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB, + 0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20, + 0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42, + 0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9, + 0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C, + 0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03 +}; + +static const unsigned char TA740_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA741_DN[] = { + 0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA741_RSA_N[] = { + 0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E, + 0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97, + 0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34, + 0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43, + 0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B, + 0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4, + 0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0, + 0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8, + 0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0, + 0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0, + 0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19, + 0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49, + 0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A, + 0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36, + 0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E, + 0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9, + 0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D, + 0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26, + 0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C, + 0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC, + 0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0, + 0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B, + 0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89, + 0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53, + 0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61, + 0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90, + 0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96, + 0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A, + 0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4, + 0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6, + 0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A, + 0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34, + 0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B, + 0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4, + 0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C, + 0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09, + 0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A, + 0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7, + 0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2, + 0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8, + 0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E, + 0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2, + 0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F +}; + +static const unsigned char TA741_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA742_DN[] = { + 0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA742_RSA_N[] = { + 0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38, + 0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5, + 0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25, + 0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2, + 0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2, + 0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98, + 0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59, + 0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75, + 0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC, + 0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B, + 0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1, + 0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC, + 0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D, + 0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76, + 0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2, + 0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D, + 0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64, + 0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A, + 0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38, + 0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C, + 0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA, + 0x91, 0x1B, 0x89, 0x07 +}; + +static const unsigned char TA742_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA743_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41, + 0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, + 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, + 0x74 +}; + +static const unsigned char TA743_RSA_N[] = { + 0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E, + 0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3, + 0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B, + 0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F, + 0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81, + 0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8, + 0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC, + 0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C, + 0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F, + 0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E, + 0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F, + 0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45, + 0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64, + 0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC, + 0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10, + 0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC, + 0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E, + 0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07, + 0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08, + 0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7, + 0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77, + 0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1, + 0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0, + 0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E, + 0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38, + 0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82, + 0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A, + 0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43, + 0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB, + 0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01, + 0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41, + 0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54, + 0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72, + 0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57, + 0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57, + 0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11, + 0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36, + 0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D, + 0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2, + 0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E, + 0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4, + 0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58, + 0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F +}; + +static const unsigned char TA743_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA744_DN[] = { + 0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41, + 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52, + 0x6F, 0x6F, 0x74 +}; + +static const unsigned char TA744_RSA_N[] = { + 0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24, + 0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87, + 0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9, + 0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93, + 0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93, + 0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45, + 0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A, + 0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B, + 0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D, + 0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33, + 0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D, + 0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6, + 0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82, + 0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F, + 0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F, + 0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0, + 0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71, + 0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59, + 0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58, + 0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D, + 0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E, + 0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B, + 0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F, + 0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50, + 0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73, + 0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D, + 0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92, + 0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B, + 0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21, + 0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78, + 0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26, + 0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03, + 0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1, + 0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D, + 0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD, + 0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91, + 0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29, + 0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26, + 0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06, + 0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25, + 0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47, + 0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B, + 0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65 +}; + +static const unsigned char TA744_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA745_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA745_EC_Q[] = { + 0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5, + 0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1, + 0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0, + 0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2, + 0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D, + 0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F, + 0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E, + 0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79, + 0x79 +}; + +static const unsigned char TA746_DN[] = { + 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65, + 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, + 0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68, + 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79 +}; + +static const unsigned char TA746_RSA_N[] = { + 0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC, + 0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61, + 0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F, + 0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6, + 0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19, + 0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2, + 0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90, + 0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64, + 0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC, + 0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4, + 0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F, + 0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51, + 0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1, + 0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC, + 0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF, + 0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12, + 0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D, + 0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7, + 0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37, + 0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74, + 0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF, + 0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE, + 0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26, + 0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E, + 0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D, + 0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB, + 0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49, + 0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF, + 0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02, + 0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16, + 0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3, + 0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D, + 0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F, + 0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17, + 0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44, + 0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8, + 0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42, + 0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E, + 0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7, + 0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9, + 0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04, + 0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F, + 0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F +}; + +static const unsigned char TA746_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA747_DN[] = { + 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30, + 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, + 0x41 +}; + +static const unsigned char TA747_EC_Q[] = { + 0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08, + 0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94, + 0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF, + 0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85, + 0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD, + 0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7, + 0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7, + 0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1, + 0x10 +}; + +static const unsigned char TA748_DN[] = { + 0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61, + 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75, + 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41 +}; + +static const unsigned char TA748_RSA_N[] = { + 0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE, + 0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90, + 0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22, + 0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC, + 0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63, + 0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8, + 0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03, + 0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C, + 0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B, + 0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0, + 0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A, + 0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94, + 0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7, + 0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08, + 0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0, + 0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1, + 0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60, + 0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1, + 0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E, + 0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09, + 0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC, + 0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4, + 0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27, + 0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A, + 0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE, + 0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8, + 0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3, + 0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8, + 0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A, + 0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62, + 0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4, + 0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A, + 0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9, + 0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14, + 0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52, + 0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5, + 0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D, + 0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA, + 0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39, + 0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B, + 0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76, + 0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C, + 0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57 +}; + +static const unsigned char TA748_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const unsigned char TA749_DN[] = { + 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58, + 0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, + 0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79 +}; + +static const unsigned char TA749_RSA_N[] = { + 0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27, + 0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D, + 0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4, + 0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B, + 0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9, + 0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F, + 0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C, + 0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4, + 0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97, + 0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B, + 0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C, + 0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D, + 0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94, + 0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B, + 0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7, + 0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A, + 0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C, + 0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4, + 0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9, + 0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83, + 0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D, + 0xD3, 0xFD, 0xD4, 0x65 +}; + +static const unsigned char TA749_RSA_E[] = { + 0x01, 0x00, 0x01 +}; diff --git a/libcurl/lib/vtls/vtls.c b/libcurl/lib/vtls/vtls.c new file mode 100644 index 0000000..c293a2e --- /dev/null +++ b/libcurl/lib/vtls/vtls.c @@ -0,0 +1,1354 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This file is for implementing all "generic" SSL functions that all libcurl + internals should use. It is then responsible for calling the proper + "backend" function. + + SSL-functions in libcurl should call functions in this source file, and not + to any specific SSL-layer. + + Curl_ssl_ - prefix for generic ones + + Note that this source code uses the functions of the configured SSL + backend via the global Curl_ssl instance. + + "SSL/TLS Strong Encryption: An Introduction" + https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html +*/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#include "urldata.h" + +#include "vtls.h" /* generic SSL protos etc */ +#include "slist.h" +#include "sendf.h" +#include "strcase.h" +#include "url.h" +#include "progress.h" +#include "share.h" +#include "multiif.h" +#include "timeval.h" +#include "curl_md5.h" +#include "warnless.h" +#include "curl_base64.h" +#include "curl_printf.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* convenience macro to check if this handle is using a shared SSL session */ +#define SSLSESSION_SHARED(data) (data->share && \ + (data->share->specifier & \ + (1<var) { \ + dest->var = strdup(source->var); \ + if(!dest->var) \ + return FALSE; \ + } \ + else \ + dest->var = NULL; + +bool +Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle) +{ + if((data->version == needle->version) && + (data->version_max == needle->version_max) && + (data->verifypeer == needle->verifypeer) && + (data->verifyhost == needle->verifyhost) && + (data->verifystatus == needle->verifystatus) && + Curl_safe_strcasecompare(data->CApath, needle->CApath) && + Curl_safe_strcasecompare(data->CAfile, needle->CAfile) && + Curl_safe_strcasecompare(data->clientcert, needle->clientcert) && + Curl_safe_strcasecompare(data->random_file, needle->random_file) && + Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) && + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && + Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13)) + return TRUE; + + return FALSE; +} + +bool +Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest) +{ + dest->version = source->version; + dest->version_max = source->version_max; + dest->verifypeer = source->verifypeer; + dest->verifyhost = source->verifyhost; + dest->verifystatus = source->verifystatus; + dest->sessionid = source->sessionid; + + CLONE_STRING(CApath); + CLONE_STRING(CAfile); + CLONE_STRING(clientcert); + CLONE_STRING(random_file); + CLONE_STRING(egdsocket); + CLONE_STRING(cipher_list); + CLONE_STRING(cipher_list13); + + return TRUE; +} + +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc) +{ + Curl_safefree(sslc->CApath); + Curl_safefree(sslc->CAfile); + Curl_safefree(sslc->clientcert); + Curl_safefree(sslc->random_file); + Curl_safefree(sslc->egdsocket); + Curl_safefree(sslc->cipher_list); + Curl_safefree(sslc->cipher_list13); +} + +#ifdef USE_SSL +static int multissl_init(const struct Curl_ssl *backend); +#endif + +int Curl_ssl_backend(void) +{ +#ifdef USE_SSL + multissl_init(NULL); + return Curl_ssl->info.id; +#else + return (int)CURLSSLBACKEND_NONE; +#endif +} + +#ifdef USE_SSL + +/* "global" init done? */ +static bool init_ssl = FALSE; + +/** + * Global SSL init + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully + */ +int Curl_ssl_init(void) +{ + /* make sure this is only done once */ + if(init_ssl) + return 1; + init_ssl = TRUE; /* never again */ + + return Curl_ssl->init(); +} + + +/* Global cleanup */ +void Curl_ssl_cleanup(void) +{ + if(init_ssl) { + /* only cleanup if we did a previous init */ + Curl_ssl->cleanup(); + init_ssl = FALSE; + } +} + +static bool ssl_prefs_check(struct Curl_easy *data) +{ + /* check for CURLOPT_SSLVERSION invalid parameter value */ + const long sslver = data->set.ssl.primary.version; + if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) { + failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION"); + return FALSE; + } + + switch(data->set.ssl.primary.version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + break; + + default: + if((data->set.ssl.primary.version_max >> 16) < sslver) { + failf(data, "CURL_SSLVERSION_MAX incompatible with CURL_SSLVERSION"); + return FALSE; + } + } + + return TRUE; +} + +static CURLcode +ssl_connect_init_proxy(struct connectdata *conn, int sockindex) +{ + DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]); + if(ssl_connection_complete == conn->ssl[sockindex].state && + !conn->proxy_ssl[sockindex].use) { + struct ssl_backend_data *pbdata; + + if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)) + return CURLE_NOT_BUILT_IN; + + /* The pointers to the ssl backend data, which is opaque here, are swapped + rather than move the contents. */ + pbdata = conn->proxy_ssl[sockindex].backend; + conn->proxy_ssl[sockindex] = conn->ssl[sockindex]; + + memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex])); + memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data); + + conn->ssl[sockindex].backend = pbdata; + } + return CURLE_OK; +} + +CURLcode +Curl_ssl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + + if(conn->bits.proxy_ssl_connected[sockindex]) { + result = ssl_connect_init_proxy(conn, sockindex); + if(result) + return result; + } + + if(!ssl_prefs_check(conn->data)) + return CURLE_SSL_CONNECT_ERROR; + + /* mark this is being ssl-enabled from here on. */ + conn->ssl[sockindex].use = TRUE; + conn->ssl[sockindex].state = ssl_connection_negotiating; + + result = Curl_ssl->connect_blocking(conn, sockindex); + + if(!result) + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + + return result; +} + +CURLcode +Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, + bool *done) +{ + CURLcode result; + if(conn->bits.proxy_ssl_connected[sockindex]) { + result = ssl_connect_init_proxy(conn, sockindex); + if(result) + return result; + } + + if(!ssl_prefs_check(conn->data)) + return CURLE_SSL_CONNECT_ERROR; + + /* mark this is being ssl requested from here on. */ + conn->ssl[sockindex].use = TRUE; + result = Curl_ssl->connect_nonblocking(conn, sockindex, done); + if(!result && *done) + Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ + return result; +} + +/* + * Lock shared SSL session data + */ +void Curl_ssl_sessionid_lock(struct connectdata *conn) +{ + if(SSLSESSION_SHARED(conn->data)) + Curl_share_lock(conn->data, + CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); +} + +/* + * Unlock shared SSL session data + */ +void Curl_ssl_sessionid_unlock(struct connectdata *conn) +{ + if(SSLSESSION_SHARED(conn->data)) + Curl_share_unlock(conn->data, CURL_LOCK_DATA_SSL_SESSION); +} + +/* + * Check if there's a session ID for the given connection in the cache, and if + * there's one suitable, it is provided. Returns TRUE when no entry matched. + */ +bool Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize, /* set 0 if unknown */ + int sockindex) +{ + struct curl_ssl_session *check; + struct Curl_easy *data = conn->data; + size_t i; + long *general_age; + bool no_match = TRUE; + + const bool isProxy = CONNECT_PROXY_SSL(); + struct ssl_primary_config * const ssl_config = isProxy ? + &conn->proxy_ssl_config : + &conn->ssl_config; + const char * const name = isProxy ? conn->http_proxy.host.name : + conn->host.name; + int port = isProxy ? (int)conn->port : conn->remote_port; + *ssl_sessionid = NULL; + + DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); + + if(!SSL_SET_OPTION(primary.sessionid)) + /* session ID re-use is disabled */ + return TRUE; + + /* Lock if shared */ + if(SSLSESSION_SHARED(data)) + general_age = &data->share->sessionage; + else + general_age = &data->state.sessionage; + + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { + check = &data->state.session[i]; + if(!check->sessionid) + /* not session ID means blank entry */ + continue; + if(strcasecompare(name, check->name) && + ((!conn->bits.conn_to_host && !check->conn_to_host) || + (conn->bits.conn_to_host && check->conn_to_host && + strcasecompare(conn->conn_to_host.name, check->conn_to_host))) && + ((!conn->bits.conn_to_port && check->conn_to_port == -1) || + (conn->bits.conn_to_port && check->conn_to_port != -1 && + conn->conn_to_port == check->conn_to_port)) && + (port == check->remote_port) && + strcasecompare(conn->handler->scheme, check->scheme) && + Curl_ssl_config_matches(ssl_config, &check->ssl_config)) { + /* yes, we have a session ID! */ + (*general_age)++; /* increase general age */ + check->age = *general_age; /* set this as used in this age */ + *ssl_sessionid = check->sessionid; + if(idsize) + *idsize = check->idsize; + no_match = FALSE; + break; + } + } + + return no_match; +} + +/* + * Kill a single session ID entry in the cache. + */ +void Curl_ssl_kill_session(struct curl_ssl_session *session) +{ + if(session->sessionid) { + /* defensive check */ + + /* free the ID the SSL-layer specific way */ + Curl_ssl->session_free(session->sessionid); + + session->sessionid = NULL; + session->age = 0; /* fresh */ + + Curl_free_primary_ssl_config(&session->ssl_config); + + Curl_safefree(session->name); + Curl_safefree(session->conn_to_host); + } +} + +/* + * Delete the given session ID from the cache. + */ +void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) +{ + size_t i; + struct Curl_easy *data = conn->data; + + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { + struct curl_ssl_session *check = &data->state.session[i]; + + if(check->sessionid == ssl_sessionid) { + Curl_ssl_kill_session(check); + break; + } + } +} + +/* + * Store session id in the session cache. The ID passed on to this function + * must already have been extracted and allocated the proper way for the SSL + * layer. Curl_XXXX_session_free() will be called to free/kill the session ID + * later on. + */ +CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize, + int sockindex) +{ + size_t i; + struct Curl_easy *data = conn->data; /* the mother of all structs */ + struct curl_ssl_session *store = &data->state.session[0]; + long oldest_age = data->state.session[0].age; /* zero if unused */ + char *clone_host; + char *clone_conn_to_host; + int conn_to_port; + long *general_age; + const bool isProxy = CONNECT_PROXY_SSL(); + struct ssl_primary_config * const ssl_config = isProxy ? + &conn->proxy_ssl_config : + &conn->ssl_config; + + DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); + + clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name); + if(!clone_host) + return CURLE_OUT_OF_MEMORY; /* bail out */ + + if(conn->bits.conn_to_host) { + clone_conn_to_host = strdup(conn->conn_to_host.name); + if(!clone_conn_to_host) { + free(clone_host); + return CURLE_OUT_OF_MEMORY; /* bail out */ + } + } + else + clone_conn_to_host = NULL; + + if(conn->bits.conn_to_port) + conn_to_port = conn->conn_to_port; + else + conn_to_port = -1; + + /* Now we should add the session ID and the host name to the cache, (remove + the oldest if necessary) */ + + /* If using shared SSL session, lock! */ + if(SSLSESSION_SHARED(data)) { + general_age = &data->share->sessionage; + } + else { + general_age = &data->state.sessionage; + } + + /* find an empty slot for us, or find the oldest */ + for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) && + data->state.session[i].sessionid; i++) { + if(data->state.session[i].age < oldest_age) { + oldest_age = data->state.session[i].age; + store = &data->state.session[i]; + } + } + if(i == data->set.general_ssl.max_ssl_sessions) + /* cache is full, we must "kill" the oldest entry! */ + Curl_ssl_kill_session(store); + else + store = &data->state.session[i]; /* use this slot */ + + /* now init the session struct wisely */ + store->sessionid = ssl_sessionid; + store->idsize = idsize; + store->age = *general_age; /* set current age */ + /* free it if there's one already present */ + free(store->name); + free(store->conn_to_host); + store->name = clone_host; /* clone host name */ + store->conn_to_host = clone_conn_to_host; /* clone connect to host name */ + store->conn_to_port = conn_to_port; /* connect to port number */ + /* port number */ + store->remote_port = isProxy ? (int)conn->port : conn->remote_port; + store->scheme = conn->handler->scheme; + + if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) { + store->sessionid = NULL; /* let caller free sessionid */ + free(clone_host); + free(clone_conn_to_host); + return CURLE_OUT_OF_MEMORY; + } + + return CURLE_OK; +} + + +void Curl_ssl_close_all(struct Curl_easy *data) +{ + /* kill the session ID cache if not shared */ + if(data->state.session && !SSLSESSION_SHARED(data)) { + size_t i; + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) + /* the single-killer function handles empty table slots */ + Curl_ssl_kill_session(&data->state.session[i]); + + /* free the cache data */ + Curl_safefree(data->state.session); + } + + Curl_ssl->close_all(data); +} + +#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ + defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \ + defined(USE_MBEDTLS) || defined(USE_WOLFSSL) +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + + if(!numsocks) + return GETSOCK_BLANK; + + if(connssl->connecting_state == ssl_connect_2_writing) { + /* write mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); + } + if(connssl->connecting_state == ssl_connect_2_reading) { + /* read mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0); + } + + return GETSOCK_BLANK; +} +#else +int Curl_ssl_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */ +#endif + +void Curl_ssl_close(struct connectdata *conn, int sockindex) +{ + DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); + Curl_ssl->close_one(conn, sockindex); +} + +CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) +{ + if(Curl_ssl->shut_down(conn, sockindex)) + return CURLE_SSL_SHUTDOWN_FAILED; + + conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ + conn->ssl[sockindex].state = ssl_connection_none; + + conn->recv[sockindex] = Curl_recv_plain; + conn->send[sockindex] = Curl_send_plain; + + return CURLE_OK; +} + +/* Selects an SSL crypto engine + */ +CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine) +{ + return Curl_ssl->set_engine(data, engine); +} + +/* Selects the default SSL crypto engine + */ +CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data) +{ + return Curl_ssl->set_engine_default(data); +} + +/* Return list of OpenSSL crypto engine names. */ +struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data) +{ + return Curl_ssl->engines_list(data); +} + +/* + * This sets up a session ID cache to the specified size. Make sure this code + * is agnostic to what underlying SSL technology we use. + */ +CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount) +{ + struct curl_ssl_session *session; + + if(data->state.session) + /* this is just a precaution to prevent multiple inits */ + return CURLE_OK; + + session = calloc(amount, sizeof(struct curl_ssl_session)); + if(!session) + return CURLE_OUT_OF_MEMORY; + + /* store the info in the SSL section */ + data->set.general_ssl.max_ssl_sessions = amount; + data->state.session = session; + data->state.sessionage = 1; /* this is brand new */ + return CURLE_OK; +} + +static size_t Curl_multissl_version(char *buffer, size_t size); + +size_t Curl_ssl_version(char *buffer, size_t size) +{ +#ifdef CURL_WITH_MULTI_SSL + return Curl_multissl_version(buffer, size); +#else + return Curl_ssl->version(buffer, size); +#endif +} + +/* + * This function tries to determine connection status. + * + * Return codes: + * 1 means the connection is still in place + * 0 means the connection has been closed + * -1 means the connection status is unknown + */ +int Curl_ssl_check_cxn(struct connectdata *conn) +{ + return Curl_ssl->check_cxn(conn); +} + +bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex) +{ + return Curl_ssl->data_pending(conn, connindex); +} + +void Curl_ssl_free_certinfo(struct Curl_easy *data) +{ + struct curl_certinfo *ci = &data->info.certs; + + if(ci->num_of_certs) { + /* free all individual lists used */ + int i; + for(i = 0; inum_of_certs; i++) { + curl_slist_free_all(ci->certinfo[i]); + ci->certinfo[i] = NULL; + } + + free(ci->certinfo); /* free the actual array too */ + ci->certinfo = NULL; + ci->num_of_certs = 0; + } +} + +CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num) +{ + struct curl_certinfo *ci = &data->info.certs; + struct curl_slist **table; + + /* Free any previous certificate information structures */ + Curl_ssl_free_certinfo(data); + + /* Allocate the required certificate information structures */ + table = calloc((size_t) num, sizeof(struct curl_slist *)); + if(!table) + return CURLE_OUT_OF_MEMORY; + + ci->num_of_certs = num; + ci->certinfo = table; + + return CURLE_OK; +} + +/* + * 'value' is NOT a zero terminated string + */ +CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, + int certnum, + const char *label, + const char *value, + size_t valuelen) +{ + struct curl_certinfo *ci = &data->info.certs; + char *output; + struct curl_slist *nl; + CURLcode result = CURLE_OK; + size_t labellen = strlen(label); + size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ + + output = malloc(outlen); + if(!output) + return CURLE_OUT_OF_MEMORY; + + /* sprintf the label and colon */ + msnprintf(output, outlen, "%s:", label); + + /* memcpy the value (it might not be zero terminated) */ + memcpy(&output[labellen + 1], value, valuelen); + + /* zero terminate the output */ + output[labellen + 1 + valuelen] = 0; + + nl = Curl_slist_append_nodup(ci->certinfo[certnum], output); + if(!nl) { + free(output); + curl_slist_free_all(ci->certinfo[certnum]); + result = CURLE_OUT_OF_MEMORY; + } + + ci->certinfo[certnum] = nl; + return result; +} + +/* + * This is a convenience function for push_certinfo_len that takes a zero + * terminated value. + */ +CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, + int certnum, + const char *label, + const char *value) +{ + size_t valuelen = strlen(value); + + return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); +} + +CURLcode Curl_ssl_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) +{ + return Curl_ssl->random(data, entropy, length); +} + +/* + * Public key pem to der conversion + */ + +static CURLcode pubkey_pem_to_der(const char *pem, + unsigned char **der, size_t *der_len) +{ + char *stripped_pem, *begin_pos, *end_pos; + size_t pem_count, stripped_pem_count = 0, pem_len; + CURLcode result; + + /* if no pem, exit. */ + if(!pem) + return CURLE_BAD_CONTENT_ENCODING; + + begin_pos = strstr(pem, "-----BEGIN PUBLIC KEY-----"); + if(!begin_pos) + return CURLE_BAD_CONTENT_ENCODING; + + pem_count = begin_pos - pem; + /* Invalid if not at beginning AND not directly following \n */ + if(0 != pem_count && '\n' != pem[pem_count - 1]) + return CURLE_BAD_CONTENT_ENCODING; + + /* 26 is length of "-----BEGIN PUBLIC KEY-----" */ + pem_count += 26; + + /* Invalid if not directly following \n */ + end_pos = strstr(pem + pem_count, "\n-----END PUBLIC KEY-----"); + if(!end_pos) + return CURLE_BAD_CONTENT_ENCODING; + + pem_len = end_pos - pem; + + stripped_pem = malloc(pem_len - pem_count + 1); + if(!stripped_pem) + return CURLE_OUT_OF_MEMORY; + + /* + * Here we loop through the pem array one character at a time between the + * correct indices, and place each character that is not '\n' or '\r' + * into the stripped_pem array, which should represent the raw base64 string + */ + while(pem_count < pem_len) { + if('\n' != pem[pem_count] && '\r' != pem[pem_count]) + stripped_pem[stripped_pem_count++] = pem[pem_count]; + ++pem_count; + } + /* Place the null terminator in the correct place */ + stripped_pem[stripped_pem_count] = '\0'; + + result = Curl_base64_decode(stripped_pem, der, der_len); + + Curl_safefree(stripped_pem); + + return result; +} + +/* + * Generic pinned public key check. + */ + +CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, + const char *pinnedpubkey, + const unsigned char *pubkey, size_t pubkeylen) +{ + FILE *fp; + unsigned char *buf = NULL, *pem_ptr = NULL; + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + if(!pubkey || !pubkeylen) + return result; + + /* only do this if pinnedpubkey starts with "sha256//", length 8 */ + if(strncmp(pinnedpubkey, "sha256//", 8) == 0) { + CURLcode encode; + size_t encodedlen, pinkeylen; + char *encoded, *pinkeycopy, *begin_pos, *end_pos; + unsigned char *sha256sumdigest; + + if(!Curl_ssl->sha256sum) { + /* without sha256 support, this cannot match */ + return result; + } + + /* compute sha256sum of public key */ + sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH); + if(!sha256sumdigest) + return CURLE_OUT_OF_MEMORY; + encode = Curl_ssl->sha256sum(pubkey, pubkeylen, + sha256sumdigest, CURL_SHA256_DIGEST_LENGTH); + + if(encode != CURLE_OK) + return encode; + + encode = Curl_base64_encode(data, (char *)sha256sumdigest, + CURL_SHA256_DIGEST_LENGTH, &encoded, + &encodedlen); + Curl_safefree(sha256sumdigest); + + if(encode) + return encode; + + infof(data, "\t public key hash: sha256//%s\n", encoded); + + /* it starts with sha256//, copy so we can modify it */ + pinkeylen = strlen(pinnedpubkey) + 1; + pinkeycopy = malloc(pinkeylen); + if(!pinkeycopy) { + Curl_safefree(encoded); + return CURLE_OUT_OF_MEMORY; + } + memcpy(pinkeycopy, pinnedpubkey, pinkeylen); + /* point begin_pos to the copy, and start extracting keys */ + begin_pos = pinkeycopy; + do { + end_pos = strstr(begin_pos, ";sha256//"); + /* + * if there is an end_pos, null terminate, + * otherwise it'll go to the end of the original string + */ + if(end_pos) + end_pos[0] = '\0'; + + /* compare base64 sha256 digests, 8 is the length of "sha256//" */ + if(encodedlen == strlen(begin_pos + 8) && + !memcmp(encoded, begin_pos + 8, encodedlen)) { + result = CURLE_OK; + break; + } + + /* + * change back the null-terminator we changed earlier, + * and look for next begin + */ + if(end_pos) { + end_pos[0] = ';'; + begin_pos = strstr(end_pos, "sha256//"); + } + } while(end_pos && begin_pos); + Curl_safefree(encoded); + Curl_safefree(pinkeycopy); + return result; + } + + fp = fopen(pinnedpubkey, "rb"); + if(!fp) + return result; + + do { + long filesize; + size_t size, pem_len; + CURLcode pem_read; + + /* Determine the file's size */ + if(fseek(fp, 0, SEEK_END)) + break; + filesize = ftell(fp); + if(fseek(fp, 0, SEEK_SET)) + break; + if(filesize < 0 || filesize > MAX_PINNED_PUBKEY_SIZE) + break; + + /* + * if the size of our certificate is bigger than the file + * size then it can't match + */ + size = curlx_sotouz((curl_off_t) filesize); + if(pubkeylen > size) + break; + + /* + * Allocate buffer for the pinned key + * With 1 additional byte for null terminator in case of PEM key + */ + buf = malloc(size + 1); + if(!buf) + break; + + /* Returns number of elements read, which should be 1 */ + if((int) fread(buf, size, 1, fp) != 1) + break; + + /* If the sizes are the same, it can't be base64 encoded, must be der */ + if(pubkeylen == size) { + if(!memcmp(pubkey, buf, pubkeylen)) + result = CURLE_OK; + break; + } + + /* + * Otherwise we will assume it's PEM and try to decode it + * after placing null terminator + */ + buf[size] = '\0'; + pem_read = pubkey_pem_to_der((const char *)buf, &pem_ptr, &pem_len); + /* if it wasn't read successfully, exit */ + if(pem_read) + break; + + /* + * if the size of our certificate doesn't match the size of + * the decoded file, they can't be the same, otherwise compare + */ + if(pubkeylen == pem_len && !memcmp(pubkey, pem_ptr, pubkeylen)) + result = CURLE_OK; + } while(0); + + Curl_safefree(buf); + Curl_safefree(pem_ptr); + fclose(fp); + + return result; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) +{ + return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len); +} +#endif + +/* + * Check whether the SSL backend supports the status_request extension. + */ +bool Curl_ssl_cert_status_request(void) +{ + return Curl_ssl->cert_status_request(); +} + +/* + * Check whether the SSL backend supports false start. + */ +bool Curl_ssl_false_start(void) +{ + return Curl_ssl->false_start(); +} + +/* + * Check whether the SSL backend supports setting TLS 1.3 cipher suites + */ +bool Curl_ssl_tls13_ciphersuites(void) +{ + return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES; +} + +/* + * Default implementations for unsupported functions. + */ + +int Curl_none_init(void) +{ + return 1; +} + +void Curl_none_cleanup(void) +{ } + +int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM, + int sockindex UNUSED_PARAM) +{ + (void)conn; + (void)sockindex; + return 0; +} + +int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM) +{ + (void)conn; + return -1; +} + +CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM, + unsigned char *entropy UNUSED_PARAM, + size_t length UNUSED_PARAM) +{ + (void)data; + (void)entropy; + (void)length; + return CURLE_NOT_BUILT_IN; +} + +void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM) +{ + (void)data; +} + +void Curl_none_session_free(void *ptr UNUSED_PARAM) +{ + (void)ptr; +} + +bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM, + int connindex UNUSED_PARAM) +{ + (void)conn; + (void)connindex; + return 0; +} + +bool Curl_none_cert_status_request(void) +{ + return FALSE; +} + +CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM, + const char *engine UNUSED_PARAM) +{ + (void)data; + (void)engine; + return CURLE_NOT_BUILT_IN; +} + +CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM) +{ + (void)data; + return CURLE_NOT_BUILT_IN; +} + +struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM) +{ + (void)data; + return (struct curl_slist *)NULL; +} + +bool Curl_none_false_start(void) +{ + return FALSE; +} + +#ifndef CURL_DISABLE_CRYPTO_AUTH +CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5len UNUSED_PARAM) +{ + MD5_context *MD5pw; + + (void)md5len; + + MD5pw = Curl_MD5_init(Curl_DIGEST_MD5); + if(!MD5pw) + return CURLE_OUT_OF_MEMORY; + Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen)); + Curl_MD5_final(MD5pw, md5sum); + return CURLE_OK; +} +#else +CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM, + size_t inputlen UNUSED_PARAM, + unsigned char *md5sum UNUSED_PARAM, + size_t md5len UNUSED_PARAM) +{ + (void)input; + (void)inputlen; + (void)md5sum; + (void)md5len; + return CURLE_NOT_BUILT_IN; +} +#endif + +static int Curl_multissl_init(void) +{ + if(multissl_init(NULL)) + return 1; + return Curl_ssl->init(); +} + +static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex) +{ + if(multissl_init(NULL)) + return CURLE_FAILED_INIT; + return Curl_ssl->connect_blocking(conn, sockindex); +} + +static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + if(multissl_init(NULL)) + return CURLE_FAILED_INIT; + return Curl_ssl->connect_nonblocking(conn, sockindex, done); +} + +static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info) +{ + if(multissl_init(NULL)) + return NULL; + return Curl_ssl->get_internals(connssl, info); +} + +static void Curl_multissl_close(struct connectdata *conn, int sockindex) +{ + if(multissl_init(NULL)) + return; + Curl_ssl->close_one(conn, sockindex); +} + +static const struct Curl_ssl Curl_ssl_multi = { + { CURLSSLBACKEND_NONE, "multi" }, /* info */ + 0, /* supports nothing */ + (size_t)-1, /* something insanely large to be on the safe side */ + + Curl_multissl_init, /* init */ + Curl_none_cleanup, /* cleanup */ + Curl_multissl_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_multissl_connect, /* connect */ + Curl_multissl_connect_nonblocking, /* connect_nonblocking */ + Curl_multissl_get_internals, /* get_internals */ + Curl_multissl_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + NULL /* sha256sum */ +}; + +const struct Curl_ssl *Curl_ssl = +#if defined(CURL_WITH_MULTI_SSL) + &Curl_ssl_multi; +#elif defined(USE_WOLFSSL) + &Curl_ssl_wolfssl; +#elif defined(USE_SECTRANSP) + &Curl_ssl_sectransp; +#elif defined(USE_GNUTLS) + &Curl_ssl_gnutls; +#elif defined(USE_GSKIT) + &Curl_ssl_gskit; +#elif defined(USE_MBEDTLS) + &Curl_ssl_mbedtls; +#elif defined(USE_NSS) + &Curl_ssl_nss; +#elif defined(USE_OPENSSL) + &Curl_ssl_openssl; +#elif defined(USE_POLARSSL) + &Curl_ssl_polarssl; +#elif defined(USE_SCHANNEL) + &Curl_ssl_schannel; +#elif defined(USE_MESALINK) + &Curl_ssl_mesalink; +#elif defined(USE_BEARSSL) + &Curl_ssl_bearssl; +#else +#error "Missing struct Curl_ssl for selected SSL backend" +#endif + +static const struct Curl_ssl *available_backends[] = { +#if defined(USE_WOLFSSL) + &Curl_ssl_wolfssl, +#endif +#if defined(USE_SECTRANSP) + &Curl_ssl_sectransp, +#endif +#if defined(USE_GNUTLS) + &Curl_ssl_gnutls, +#endif +#if defined(USE_GSKIT) + &Curl_ssl_gskit, +#endif +#if defined(USE_MBEDTLS) + &Curl_ssl_mbedtls, +#endif +#if defined(USE_NSS) + &Curl_ssl_nss, +#endif +#if defined(USE_OPENSSL) + &Curl_ssl_openssl, +#endif +#if defined(USE_POLARSSL) + &Curl_ssl_polarssl, +#endif +#if defined(USE_SCHANNEL) + &Curl_ssl_schannel, +#endif +#if defined(USE_MESALINK) + &Curl_ssl_mesalink, +#endif +#if defined(USE_BEARSSL) + &Curl_ssl_bearssl, +#endif + NULL +}; + +static size_t Curl_multissl_version(char *buffer, size_t size) +{ + static const struct Curl_ssl *selected; + static char backends[200]; + static size_t total; + const struct Curl_ssl *current; + + current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl; + + if(current != selected) { + char *p = backends; + char *end = backends + sizeof(backends); + int i; + + selected = current; + + for(i = 0; available_backends[i] && p < (end - 4); i++) { + if(i) + *(p++) = ' '; + if(selected != available_backends[i]) + *(p++) = '('; + p += available_backends[i]->version(p, end - p - 2); + if(selected != available_backends[i]) + *(p++) = ')'; + } + *p = '\0'; + total = p - backends; + } + + if(size > total) + memcpy(buffer, backends, total + 1); + else { + memcpy(buffer, backends, size - 1); + buffer[size - 1] = '\0'; + } + + return CURLMIN(size - 1, total); +} + +static int multissl_init(const struct Curl_ssl *backend) +{ + const char *env; + char *env_tmp; + + if(Curl_ssl != &Curl_ssl_multi) + return 1; + + if(backend) { + Curl_ssl = backend; + return 0; + } + + if(!available_backends[0]) + return 1; + + env = env_tmp = curl_getenv("CURL_SSL_BACKEND"); +#ifdef CURL_DEFAULT_SSL_BACKEND + if(!env) + env = CURL_DEFAULT_SSL_BACKEND; +#endif + if(env) { + int i; + for(i = 0; available_backends[i]; i++) { + if(strcasecompare(env, available_backends[i]->info.name)) { + Curl_ssl = available_backends[i]; + curl_free(env_tmp); + return 0; + } + } + } + + /* Fall back to first available backend */ + Curl_ssl = available_backends[0]; + curl_free(env_tmp); + return 0; +} + +CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail) +{ + int i; + + if(avail) + *avail = (const curl_ssl_backend **)&available_backends; + + if(Curl_ssl != &Curl_ssl_multi) + return id == Curl_ssl->info.id || + (name && strcasecompare(name, Curl_ssl->info.name)) ? + CURLSSLSET_OK : +#if defined(CURL_WITH_MULTI_SSL) + CURLSSLSET_TOO_LATE; +#else + CURLSSLSET_UNKNOWN_BACKEND; +#endif + + for(i = 0; available_backends[i]; i++) { + if(available_backends[i]->info.id == id || + (name && strcasecompare(available_backends[i]->info.name, name))) { + multissl_init(available_backends[i]); + return CURLSSLSET_OK; + } + } + + return CURLSSLSET_UNKNOWN_BACKEND; +} + +#else /* USE_SSL */ +CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail) +{ + (void)id; + (void)name; + (void)avail; + return CURLSSLSET_NO_BACKENDS; +} + +#endif /* !USE_SSL */ diff --git a/libcurl/lib/vtls/vtls.h b/libcurl/lib/vtls/vtls.h new file mode 100644 index 0000000..eae4ced --- /dev/null +++ b/libcurl/lib/vtls/vtls.h @@ -0,0 +1,279 @@ +#ifndef HEADER_CURL_VTLS_H +#define HEADER_CURL_VTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +struct connectdata; +struct ssl_connect_data; + +#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */ +#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */ +#define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */ +#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */ +#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */ +#define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */ + +struct Curl_ssl { + /* + * This *must* be the first entry to allow returning the list of available + * backends in curl_global_sslset(). + */ + curl_ssl_backend info; + unsigned int supports; /* bitfield, see above */ + size_t sizeof_ssl_backend_data; + + int (*init)(void); + void (*cleanup)(void); + + size_t (*version)(char *buffer, size_t size); + int (*check_cxn)(struct connectdata *cxn); + int (*shut_down)(struct connectdata *conn, int sockindex); + bool (*data_pending)(const struct connectdata *conn, + int connindex); + + /* return 0 if a find random is filled in */ + CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy, + size_t length); + bool (*cert_status_request)(void); + + CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex); + CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex, + bool *done); + void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); + void (*close_one)(struct connectdata *conn, int sockindex); + void (*close_all)(struct Curl_easy *data); + void (*session_free)(void *ptr); + + CURLcode (*set_engine)(struct Curl_easy *data, const char *engine); + CURLcode (*set_engine_default)(struct Curl_easy *data); + struct curl_slist *(*engines_list)(struct Curl_easy *data); + + bool (*false_start)(void); + + CURLcode (*md5sum)(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5sumlen); + CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, + unsigned char *sha256sum, size_t sha256sumlen); +}; + +#ifdef USE_SSL +extern const struct Curl_ssl *Curl_ssl; +#endif + +int Curl_none_init(void); +void Curl_none_cleanup(void); +int Curl_none_shutdown(struct connectdata *conn, int sockindex); +int Curl_none_check_cxn(struct connectdata *conn); +CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy, + size_t length); +void Curl_none_close_all(struct Curl_easy *data); +void Curl_none_session_free(void *ptr); +bool Curl_none_data_pending(const struct connectdata *conn, int connindex); +bool Curl_none_cert_status_request(void); +CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine); +CURLcode Curl_none_set_engine_default(struct Curl_easy *data); +struct curl_slist *Curl_none_engines_list(struct Curl_easy *data); +bool Curl_none_false_start(void); +bool Curl_ssl_tls13_ciphersuites(void); +CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5len); + +#include "openssl.h" /* OpenSSL versions */ +#include "gtls.h" /* GnuTLS versions */ +#include "nssg.h" /* NSS versions */ +#include "gskit.h" /* Global Secure ToolKit versions */ +#include "polarssl.h" /* PolarSSL versions */ +#include "wolfssl.h" /* wolfSSL versions */ +#include "schannel.h" /* Schannel SSPI version */ +#include "sectransp.h" /* SecureTransport (Darwin) version */ +#include "mbedtls.h" /* mbedTLS versions */ +#include "mesalink.h" /* MesaLink versions */ +#include "bearssl.h" /* BearSSL versions */ + +#ifndef MAX_PINNED_PUBKEY_SIZE +#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */ +#endif + +#ifndef MD5_DIGEST_LENGTH +#ifndef LIBWOLFSSL_VERSION_HEX /* because WolfSSL borks this */ +#define MD5_DIGEST_LENGTH 16 /* fixed size */ +#endif +#endif + +#ifndef CURL_SHA256_DIGEST_LENGTH +#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ +#endif + +/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */ +#define ALPN_HTTP_1_1_LENGTH 8 +#define ALPN_HTTP_1_1 "http/1.1" + +/* set of helper macros for the backends to access the correct fields. For the + proxy or for the remote host - to properly support HTTPS proxy */ + +#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \ + ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \ + CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state) +#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \ + data->set.ssl.var) +#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ? \ + conn->proxy_ssl_config.var : conn->ssl_config.var) + +bool Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle); +bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest); +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc); +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); + +int Curl_ssl_backend(void); + +#ifdef USE_SSL +int Curl_ssl_init(void); +void Curl_ssl_cleanup(void); +CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +/* tell the SSL stuff to close down all open information regarding + connections (and thus session ID caching etc) */ +void Curl_ssl_close_all(struct Curl_easy *data); +void Curl_ssl_close(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine); +/* Sets engine as default for all SSL operations */ +CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data); +struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data); + +/* init the SSL session ID cache */ +CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t); +size_t Curl_ssl_version(char *buffer, size_t size); +bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex); +int Curl_ssl_check_cxn(struct connectdata *conn); + +/* Certificate information list handling. */ + +void Curl_ssl_free_certinfo(struct Curl_easy *data); +CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num); +CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum, + const char *label, const char *value, + size_t valuelen); +CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum, + const char *label, const char *value); + +/* Functions to be used by SSL library adaptation functions */ + +/* Lock session cache mutex. + * Call this before calling other Curl_ssl_*session* functions + * Caller should unlock this mutex as soon as possible, as it may block + * other SSL connection from making progress. + * The purpose of explicitly locking SSL session cache data is to allow + * individual SSL engines to manage session lifetime in their specific way. + */ +void Curl_ssl_sessionid_lock(struct connectdata *conn); + +/* Unlock session cache mutex */ +void Curl_ssl_sessionid_unlock(struct connectdata *conn); + +/* extract a session ID + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * Caller must make sure that the ownership of returned sessionid object + * is properly taken (e.g. its refcount is incremented + * under sessionid mutex). + */ +bool Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize, /* set 0 if unknown */ + int sockindex); +/* add a new session ID + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * Caller must ensure that it has properly shared ownership of this sessionid + * object with cache (e.g. incrementing refcount on success) + */ +CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize, + int sockindex); +/* Kill a single session ID entry in the cache + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * This will call engine-specific curlssl_session_free function, which must + * take sessionid object ownership from sessionid cache + * (e.g. decrement refcount). + */ +void Curl_ssl_kill_session(struct curl_ssl_session *session); +/* delete a session from the cache + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * This will call engine-specific curlssl_session_free function, which must + * take sessionid object ownership from sessionid cache + * (e.g. decrement refcount). + */ +void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); + +/* get N random bytes into the buffer */ +CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer, + size_t length); +CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); +/* Check pinned public key. */ +CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, + const char *pinnedpubkey, + const unsigned char *pubkey, size_t pubkeylen); + +bool Curl_ssl_cert_status_request(void); + +bool Curl_ssl_false_start(void); + +#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ + +#else /* if not USE_SSL */ + +/* When SSL support is not present, just define away these function calls */ +#define Curl_ssl_init() 1 +#define Curl_ssl_cleanup() Curl_nop_stmt +#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_close_all(x) Curl_nop_stmt +#define Curl_ssl_close(x,y) Curl_nop_stmt +#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN +#define Curl_ssl_engines_list(x) NULL +#define Curl_ssl_send(a,b,c,d,e) -1 +#define Curl_ssl_recv(a,b,c,d,e) -1 +#define Curl_ssl_initsessions(x,y) CURLE_OK +#define Curl_ssl_version(x,y) 0 +#define Curl_ssl_data_pending(x,y) 0 +#define Curl_ssl_check_cxn(x) 0 +#define Curl_ssl_free_certinfo(x) Curl_nop_stmt +#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN +#define Curl_ssl_kill_session(x) Curl_nop_stmt +#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_ssl_cert_status_request() FALSE +#define Curl_ssl_false_start() FALSE +#define Curl_ssl_tls13_ciphersuites() FALSE +#endif + +#endif /* HEADER_CURL_VTLS_H */ diff --git a/libcurl/lib/vtls/wolfssl.c b/libcurl/lib/vtls/wolfssl.c new file mode 100644 index 0000000..890bcbf --- /dev/null +++ b/libcurl/lib/vtls/wolfssl.c @@ -0,0 +1,991 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Source file for all wolfSSL specific code for the TLS/SSL layer. No code + * but vtls.c should ever call or use these functions. + * + */ + +#include "curl_setup.h" + +#ifdef USE_WOLFSSL + +#define WOLFSSL_OPTIONS_IGNORE_SYS +#include +#include + +/* To determine what functions are available we rely on one or both of: + - the user's options.h generated by wolfSSL + - the symbols detected by curl's configure + Since they are markedly different from one another, and one or the other may + not be available, we do some checking below to bring things in sync. */ + +/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */ +#ifndef HAVE_ALPN +#ifdef HAVE_WOLFSSL_USEALPN +#define HAVE_ALPN +#endif +#endif + +/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in + options.h, but is only seen in >= 3.6.6 since that's when they started + disabling SSLv3 by default. */ +#ifndef WOLFSSL_ALLOW_SSLV3 +#if (LIBWOLFSSL_VERSION_HEX < 0x03006006) || \ + defined(HAVE_WOLFSSLV3_CLIENT_METHOD) +#define WOLFSSL_ALLOW_SSLV3 +#endif +#endif + +#include + +#include "urldata.h" +#include "sendf.h" +#include "inet_pton.h" +#include "vtls.h" +#include "parsedate.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "strcase.h" +#include "x509asn1.h" +#include "curl_printf.h" +#include "multiif.h" + +#include +#include +#include +#include "wolfssl.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* KEEP_PEER_CERT is a product of the presence of build time symbol + OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is + in wolfSSL's settings.h, and the latter two are build time symbols in + options.h. */ +#ifndef KEEP_PEER_CERT +#if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \ + (defined(OPENSSL_EXTRA) && !defined(NO_CERTS)) +#define KEEP_PEER_CERT +#endif +#endif + +struct ssl_backend_data { + SSL_CTX* ctx; + SSL* handle; +}; + +#define BACKEND connssl->backend + +static Curl_recv wolfssl_recv; +static Curl_send wolfssl_send; + + +static int do_file_type(const char *type) +{ + if(!type || !type[0]) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "PEM")) + return SSL_FILETYPE_PEM; + if(strcasecompare(type, "DER")) + return SSL_FILETYPE_ASN1; + return -1; +} + +/* + * This function loads all the client/CA certificates and CRLs. Setup the TLS + * layer and do all necessary magic. + */ +static CURLcode +wolfssl_connect_step1(struct connectdata *conn, + int sockindex) +{ + char *ciphers; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + SSL_METHOD* req_method = NULL; + curl_socket_t sockfd = conn->sock[sockindex]; +#ifdef HAVE_SNI + bool sni = FALSE; +#define use_sni(x) sni = (x) +#else +#define use_sni(x) Curl_nop_stmt +#endif + + if(connssl->state == ssl_connection_complete) + return CURLE_OK; + + if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { + failf(data, "wolfSSL does not support to set maximum SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* check to see if we've been told to use an explicit SSL/TLS version */ + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: +#if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ + /* minimum protocol version is set later after the CTX object is created */ + req_method = SSLv23_client_method(); +#else + infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, " + "TLS 1.0 is used exclusively\n"); + req_method = TLSv1_client_method(); +#endif + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_0: +#ifdef WOLFSSL_ALLOW_TLSV10 + req_method = TLSv1_client_method(); + use_sni(TRUE); +#else + failf(data, "wolfSSL does not support TLS 1.0"); + return CURLE_NOT_BUILT_IN; +#endif + break; + case CURL_SSLVERSION_TLSv1_1: + req_method = TLSv1_1_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_2: + req_method = TLSv1_2_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_TLSv1_3: +#ifdef WOLFSSL_TLS13 + req_method = wolfTLSv1_3_client_method(); + use_sni(TRUE); + break; +#else + failf(data, "wolfSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; +#endif + case CURL_SSLVERSION_SSLv3: +#ifdef WOLFSSL_ALLOW_SSLV3 + req_method = SSLv3_client_method(); + use_sni(FALSE); +#else + failf(data, "wolfSSL does not support SSLv3"); + return CURLE_NOT_BUILT_IN; +#endif + break; + case CURL_SSLVERSION_SSLv2: + failf(data, "wolfSSL does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(!req_method) { + failf(data, "SSL: couldn't create a method!"); + return CURLE_OUT_OF_MEMORY; + } + + if(BACKEND->ctx) + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = SSL_CTX_new(req_method); + + if(!BACKEND->ctx) { + failf(data, "SSL: couldn't create a context!"); + return CURLE_OUT_OF_MEMORY; + } + + switch(SSL_CONN_CONFIG(version)) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: +#if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ + /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is + * whatever minimum version of TLS was built in and at least TLS 1.0. For + * later library versions that could change (eg TLS 1.0 built in but + * defaults to TLS 1.1) so we have this short circuit evaluation to find + * the minimum supported TLS version. + */ + if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) && + (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) && + (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1) +#ifdef WOLFSSL_TLS13 + && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_3) != 1) +#endif + ) { + failf(data, "SSL: couldn't set the minimum protocol version"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + break; + } + + ciphers = SSL_CONN_CONFIG(cipher_list); + if(ciphers) { + if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s\n", ciphers); + } + +#ifndef NO_FILESYSTEM + /* load trusted cacert */ + if(SSL_CONN_CONFIG(CAfile)) { + if(1 != SSL_CTX_load_verify_locations(BACKEND->ctx, + SSL_CONN_CONFIG(CAfile), + SSL_CONN_CONFIG(CApath))) { + if(SSL_CONN_CONFIG(verifypeer)) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:\n" + " CAfile: %s\n CApath: %s", + SSL_CONN_CONFIG(CAfile)? + SSL_CONN_CONFIG(CAfile): "none", + SSL_CONN_CONFIG(CApath)? + SSL_CONN_CONFIG(CApath) : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate + verification is required. */ + infof(data, "error setting certificate verify locations," + " continuing anyway:\n"); + } + } + else { + /* Everything is fine. */ + infof(data, "successfully set certificate verify locations:\n"); + } + infof(data, + " CAfile: %s\n" + " CApath: %s\n", + SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): + "none", + SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): + "none"); + } + + /* Load the client certificate, and private key */ + if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { + int file_type = do_file_type(SSL_SET_OPTION(cert_type)); + + if(SSL_CTX_use_certificate_file(BACKEND->ctx, SSL_SET_OPTION(cert), + file_type) != 1) { + failf(data, "unable to use client certificate (no key or wrong pass" + " phrase?)"); + return CURLE_SSL_CONNECT_ERROR; + } + + file_type = do_file_type(SSL_SET_OPTION(key_type)); + if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key), + file_type) != 1) { + failf(data, "unable to set private key"); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* !NO_FILESYSTEM */ + + /* SSL always tries to verify the peer, this only says whether it should + * fail to connect if the verification fails, or if it should continue + * anyway. In the latter case the result of the verification is checked with + * SSL_get_verify_result() below. */ + SSL_CTX_set_verify(BACKEND->ctx, + SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER: + SSL_VERIFY_NONE, + NULL); + +#ifdef HAVE_SNI + if(sni) { + struct in_addr addr4; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + size_t hostname_len = strlen(hostname); + if((hostname_len < USHRT_MAX) && + (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) && +#endif + (wolfSSL_CTX_UseSNI(BACKEND->ctx, WOLFSSL_SNI_HOST_NAME, hostname, + (unsigned short)hostname_len) != 1)) { + infof(data, "WARNING: failed to configure server name indication (SNI) " + "TLS extension\n"); + } + } +#endif + + /* give application a chance to interfere with SSL set up. */ + if(data->set.ssl.fsslctx) { + CURLcode result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, + data->set.ssl.fsslctxp); + if(result) { + failf(data, "error signaled by ssl ctx callback"); + return result; + } + } +#ifdef NO_FILESYSTEM + else if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "SSL: Certificates can't be loaded because wolfSSL was built" + " with \"no filesystem\". Either disable peer verification" + " (insecure) or if you are building an application with libcurl you" + " can load certificates via CURLOPT_SSL_CTX_FUNCTION."); + return CURLE_SSL_CONNECT_ERROR; + } +#endif + + /* Let's make an SSL structure */ + if(BACKEND->handle) + SSL_free(BACKEND->handle); + BACKEND->handle = SSL_new(BACKEND->ctx); + if(!BACKEND->handle) { + failf(data, "SSL: couldn't create a context (handle)!"); + return CURLE_OUT_OF_MEMORY; + } + +#ifdef HAVE_ALPN + if(conn->bits.tls_enable_alpn) { + char protocols[128]; + *protocols = '\0'; + + /* wolfSSL's ALPN protocol name list format is a comma separated string of + protocols in descending order of preference, eg: "h2,http/1.1" */ + +#ifdef USE_NGHTTP2 + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ","); + infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + } +#endif + + strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + + if(wolfSSL_UseALPN(BACKEND->handle, protocols, + (unsigned)strlen(protocols), + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { + failf(data, "SSL: failed setting ALPN protocols"); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* HAVE_ALPN */ + + /* Check if there's a cached ID we can/should use here! */ + if(SSL_SET_OPTION(primary.sessionid)) { + void *ssl_sessionid = NULL; + + Curl_ssl_sessionid_lock(conn); + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { + char error_buffer[WOLFSSL_MAX_ERROR_SZ]; + Curl_ssl_sessionid_unlock(conn); + failf(data, "SSL: SSL_set_session failed: %s", + ERR_error_string(SSL_get_error(BACKEND->handle, 0), + error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + /* Informational message */ + infof(data, "SSL re-using session ID\n"); + } + Curl_ssl_sessionid_unlock(conn); + } + + /* pass the raw socket into the SSL layer */ + if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) { + failf(data, "SSL: SSL_set_fd failed"); + return CURLE_SSL_CONNECT_ERROR; + } + + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; +} + + +static CURLcode +wolfssl_connect_step2(struct connectdata *conn, + int sockindex) +{ + int ret = -1; + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + + conn->recv[sockindex] = wolfssl_recv; + conn->send[sockindex] = wolfssl_send; + + /* Enable RFC2818 checks */ + if(SSL_CONN_CONFIG(verifyhost)) { + ret = wolfSSL_check_domain_name(BACKEND->handle, hostname); + if(ret == SSL_FAILURE) + return CURLE_OUT_OF_MEMORY; + } + + ret = SSL_connect(BACKEND->handle); + if(ret != 1) { + char error_buffer[WOLFSSL_MAX_ERROR_SZ]; + int detail = SSL_get_error(BACKEND->handle, ret); + + if(SSL_ERROR_WANT_READ == detail) { + connssl->connecting_state = ssl_connect_2_reading; + return CURLE_OK; + } + else if(SSL_ERROR_WANT_WRITE == detail) { + connssl->connecting_state = ssl_connect_2_writing; + return CURLE_OK; + } + /* There is no easy way to override only the CN matching. + * This will enable the override of both mismatching SubjectAltNames + * as also mismatching CN fields */ + else if(DOMAIN_NAME_MISMATCH == detail) { +#if 1 + failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", + dispname); + return CURLE_PEER_FAILED_VERIFICATION; +#else + /* When the wolfssl_check_domain_name() is used and you desire to + * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost + * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA + * error. The only way to do this is currently to switch the + * Wolfssl_check_domain_name() in and out based on the + * 'conn->ssl_config.verifyhost' value. */ + if(SSL_CONN_CONFIG(verifyhost)) { + failf(data, + "\tsubject alt name(s) or common name do not match \"%s\"\n", + dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + else { + infof(data, + "\tsubject alt name(s) and/or common name do not match \"%s\"\n", + dispname); + return CURLE_OK; + } +#endif + } +#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ + else if(ASN_NO_SIGNER_E == detail) { + if(SSL_CONN_CONFIG(verifypeer)) { + failf(data, "\tCA signer not available for verification\n"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + /* Just continue with a warning if no strict certificate + verification is required. */ + infof(data, "CA signer not available for verification, " + "continuing anyway\n"); + } + } +#endif + else { + failf(data, "SSL_connect failed with error %d: %s", detail, + ERR_error_string(detail, error_buffer)); + return CURLE_SSL_CONNECT_ERROR; + } + } + + if(pinnedpubkey) { +#ifdef KEEP_PEER_CERT + X509 *x509; + const char *x509_der; + int x509_der_len; + curl_X509certificate x509_parsed; + curl_asn1Element *pubkey; + CURLcode result; + + x509 = SSL_get_peer_certificate(BACKEND->handle); + if(!x509) { + failf(data, "SSL: failed retrieving server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len); + if(!x509_der) { + failf(data, "SSL: failed retrieving ASN.1 server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + memset(&x509_parsed, 0, sizeof(x509_parsed)); + if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + pubkey = &x509_parsed.subjectPublicKeyInfo; + if(!pubkey->header || pubkey->end <= pubkey->header) { + failf(data, "SSL: failed retrieving public key from server certificate"); + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + } + + result = Curl_pin_peer_pubkey(data, + pinnedpubkey, + (const unsigned char *)pubkey->header, + (size_t)(pubkey->end - pubkey->header)); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } +#else + failf(data, "Library lacks pinning support built-in"); + return CURLE_NOT_BUILT_IN; +#endif + } + +#ifdef HAVE_ALPN + if(conn->bits.tls_enable_alpn) { + int rc; + char *protocol = NULL; + unsigned short protocol_len = 0; + + rc = wolfSSL_ALPN_GetProtocol(BACKEND->handle, &protocol, &protocol_len); + + if(rc == SSL_SUCCESS) { + infof(data, "ALPN, server accepted to use %.*s\n", protocol_len, + protocol); + + if(protocol_len == ALPN_HTTP_1_1_LENGTH && + !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) + conn->negnpn = CURL_HTTP_VERSION_1_1; +#ifdef USE_NGHTTP2 + else if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN && + !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN)) + conn->negnpn = CURL_HTTP_VERSION_2; +#endif + else + infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len, + protocol); + Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + } + else if(rc == SSL_ALPN_NOT_FOUND) + infof(data, "ALPN, server did not agree to a protocol\n"); + else { + failf(data, "ALPN, failure getting protocol, error %d", rc); + return CURLE_SSL_CONNECT_ERROR; + } + } +#endif /* HAVE_ALPN */ + + connssl->connecting_state = ssl_connect_3; +#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010) + infof(data, "SSL connection using %s / %s\n", + wolfSSL_get_version(BACKEND->handle), + wolfSSL_get_cipher_name(BACKEND->handle)); +#else + infof(data, "SSL connected\n"); +#endif + + return CURLE_OK; +} + + +static CURLcode +wolfssl_connect_step3(struct connectdata *conn, + int sockindex) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); + + if(SSL_SET_OPTION(primary.sessionid)) { + bool incache; + SSL_SESSION *our_ssl_sessionid; + void *old_ssl_sessionid = NULL; + + our_ssl_sessionid = SSL_get_session(BACKEND->handle); + + Curl_ssl_sessionid_lock(conn); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(conn, old_ssl_sessionid); + incache = FALSE; + } + } + + if(!incache) { + result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, + 0 /* unknown size */, sockindex); + if(result) { + Curl_ssl_sessionid_unlock(conn); + failf(data, "failed to store ssl session"); + return result; + } + } + Curl_ssl_sessionid_unlock(conn); + } + + connssl->connecting_state = ssl_connect_done; + + return result; +} + + +static ssize_t wolfssl_send(struct connectdata *conn, + int sockindex, + const void *mem, + size_t len, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + char error_buffer[WOLFSSL_MAX_ERROR_SZ]; + int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + int rc = SSL_write(BACKEND->handle, mem, memlen); + + if(rc < 0) { + int err = SSL_get_error(BACKEND->handle, rc); + + switch(err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_write() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, "SSL write: %s, errno %d", + ERR_error_string(err, error_buffer), + SOCKERRNO); + *curlcode = CURLE_SEND_ERROR; + return -1; + } + } + return rc; +} + +static void Curl_wolfssl_close(struct connectdata *conn, int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->handle) { + (void)SSL_shutdown(BACKEND->handle); + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + if(BACKEND->ctx) { + SSL_CTX_free(BACKEND->ctx); + BACKEND->ctx = NULL; + } +} + +static ssize_t wolfssl_recv(struct connectdata *conn, + int num, + char *buf, + size_t buffersize, + CURLcode *curlcode) +{ + struct ssl_connect_data *connssl = &conn->ssl[num]; + char error_buffer[WOLFSSL_MAX_ERROR_SZ]; + int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + int nread = SSL_read(BACKEND->handle, buf, buffsize); + + if(nread < 0) { + int err = SSL_get_error(BACKEND->handle, nread); + + switch(err) { + case SSL_ERROR_ZERO_RETURN: /* no more data */ + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* there's data pending, re-invoke SSL_read() */ + *curlcode = CURLE_AGAIN; + return -1; + default: + failf(conn->data, "SSL read: %s, errno %d", + ERR_error_string(err, error_buffer), + SOCKERRNO); + *curlcode = CURLE_RECV_ERROR; + return -1; + } + } + return nread; +} + + +static void Curl_wolfssl_session_free(void *ptr) +{ + (void)ptr; + /* wolfSSL reuses sessions on own, no free */ +} + + +static size_t Curl_wolfssl_version(char *buffer, size_t size) +{ +#if LIBWOLFSSL_VERSION_HEX >= 0x03006000 + return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); +#elif defined(WOLFSSL_VERSION) + return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); +#endif +} + + +static int Curl_wolfssl_init(void) +{ + return (wolfSSL_Init() == SSL_SUCCESS); +} + + +static void Curl_wolfssl_cleanup(void) +{ + wolfSSL_Cleanup(); +} + + +static bool Curl_wolfssl_data_pending(const struct connectdata* conn, + int connindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[connindex]; + if(BACKEND->handle) /* SSL is in use */ + return (0 != SSL_pending(BACKEND->handle)) ? TRUE : FALSE; + else + return FALSE; +} + + +/* + * This function is called to shut down the SSL layer but keep the + * socket open (CCC - Clear Command Channel) + */ +static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex) +{ + int retval = 0; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + if(BACKEND->handle) { + SSL_free(BACKEND->handle); + BACKEND->handle = NULL; + } + return retval; +} + + +static CURLcode +wolfssl_connect_common(struct connectdata *conn, + int sockindex, + bool nonblocking, + bool *done) +{ + CURLcode result; + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + time_t timeout_ms; + int what; + + /* check if the connection has already been established */ + if(ssl_connection_complete == connssl->state) { + *done = TRUE; + return CURLE_OK; + } + + if(ssl_connect_1 == connssl->connecting_state) { + /* Find out how much more time we're allowed */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + result = wolfssl_connect_step1(conn, sockindex); + if(result) + return result; + } + + while(ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state) { + + /* check allowed time left */ + timeout_ms = Curl_timeleft(data, NULL, TRUE); + + if(timeout_ms < 0) { + /* no need to continue if time already is up */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + /* if ssl is expecting something, check if it's available. */ + if(connssl->connecting_state == ssl_connect_2_reading + || connssl->connecting_state == ssl_connect_2_writing) { + + curl_socket_t writefd = ssl_connect_2_writing == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + curl_socket_t readfd = ssl_connect_2_reading == + connssl->connecting_state?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking?0:timeout_ms); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + else if(0 == what) { + if(nonblocking) { + *done = FALSE; + return CURLE_OK; + } + else { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + } + /* socket is readable or writable */ + } + + /* Run transaction, and return to the caller if it failed or if + * this connection is part of a multi handle and this loop would + * execute again. This permits the owner of a multi handle to + * abort a connection attempt before step2 has completed while + * ensuring that a client using select() or epoll() will always + * have a valid fdset to wait on. + */ + result = wolfssl_connect_step2(conn, sockindex); + if(result || (nonblocking && + (ssl_connect_2 == connssl->connecting_state || + ssl_connect_2_reading == connssl->connecting_state || + ssl_connect_2_writing == connssl->connecting_state))) + return result; + } /* repeat step2 until all transactions are done. */ + + if(ssl_connect_3 == connssl->connecting_state) { + result = wolfssl_connect_step3(conn, sockindex); + if(result) + return result; + } + + if(ssl_connect_done == connssl->connecting_state) { + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = wolfssl_recv; + conn->send[sockindex] = wolfssl_send; + *done = TRUE; + } + else + *done = FALSE; + + /* Reset our connect state machine */ + connssl->connecting_state = ssl_connect_1; + + return CURLE_OK; +} + + +static CURLcode Curl_wolfssl_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) +{ + return wolfssl_connect_common(conn, sockindex, TRUE, done); +} + + +static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex) +{ + CURLcode result; + bool done = FALSE; + + result = wolfssl_connect_common(conn, sockindex, FALSE, &done); + if(result) + return result; + + DEBUGASSERT(done); + + return CURLE_OK; +} + +static CURLcode Curl_wolfssl_random(struct Curl_easy *data, + unsigned char *entropy, size_t length) +{ + RNG rng; + (void)data; + if(wc_InitRng(&rng)) + return CURLE_FAILED_INIT; + if(length > UINT_MAX) + return CURLE_FAILED_INIT; + if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length)) + return CURLE_FAILED_INIT; + if(wc_FreeRng(&rng)) + return CURLE_FAILED_INIT; + return CURLE_OK; +} + +static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum /* output */, + size_t unused) +{ + Sha256 SHA256pw; + (void)unused; + wc_InitSha256(&SHA256pw); + wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen); + wc_Sha256Final(&SHA256pw, sha256sum); + return CURLE_OK; +} + +static void *Curl_wolfssl_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_wolfssl = { + { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */ + +#ifdef KEEP_PEER_CERT + SSLSUPP_PINNEDPUBKEY | +#endif + SSLSUPP_SSL_CTX, + + sizeof(struct ssl_backend_data), + + Curl_wolfssl_init, /* init */ + Curl_wolfssl_cleanup, /* cleanup */ + Curl_wolfssl_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_wolfssl_shutdown, /* shutdown */ + Curl_wolfssl_data_pending, /* data_pending */ + Curl_wolfssl_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + Curl_wolfssl_connect, /* connect */ + Curl_wolfssl_connect_nonblocking, /* connect_nonblocking */ + Curl_wolfssl_get_internals, /* get_internals */ + Curl_wolfssl_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_wolfssl_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + Curl_none_md5sum, /* md5sum */ + Curl_wolfssl_sha256sum /* sha256sum */ +}; + +#endif diff --git a/libcurl/lib/vtls/wolfssl.h b/libcurl/lib/vtls/wolfssl.h new file mode 100644 index 0000000..2b9673c --- /dev/null +++ b/libcurl/lib/vtls/wolfssl.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_WOLFSSL_H +#define HEADER_CURL_WOLFSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_WOLFSSL + +extern const struct Curl_ssl Curl_ssl_wolfssl; + +#endif /* USE_WOLFSSL */ +#endif /* HEADER_CURL_WOLFSSL_H */ diff --git a/libcurl/lib/warnless.c b/libcurl/lib/warnless.c new file mode 100644 index 0000000..cfd5e8e --- /dev/null +++ b/libcurl/lib/warnless.c @@ -0,0 +1,508 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#endif /* __INTEL_COMPILER && __unix__ */ + +#define BUILDING_WARNLESS_C 1 + +#include "warnless.h" + +#define CURL_MASK_SCHAR 0x7F +#define CURL_MASK_UCHAR 0xFF + +#if (SIZEOF_SHORT == 2) +# define CURL_MASK_SSHORT 0x7FFF +# define CURL_MASK_USHORT 0xFFFF +#elif (SIZEOF_SHORT == 4) +# define CURL_MASK_SSHORT 0x7FFFFFFF +# define CURL_MASK_USHORT 0xFFFFFFFF +#elif (SIZEOF_SHORT == 8) +# define CURL_MASK_SSHORT 0x7FFFFFFFFFFFFFFF +# define CURL_MASK_USHORT 0xFFFFFFFFFFFFFFFF +#else +# error "SIZEOF_SHORT not defined" +#endif + +#if (SIZEOF_INT == 2) +# define CURL_MASK_SINT 0x7FFF +# define CURL_MASK_UINT 0xFFFF +#elif (SIZEOF_INT == 4) +# define CURL_MASK_SINT 0x7FFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFF +#elif (SIZEOF_INT == 8) +# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFF +#elif (SIZEOF_INT == 16) +# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +#else +# error "SIZEOF_INT not defined" +#endif + +#if (SIZEOF_LONG == 2) +# define CURL_MASK_SLONG 0x7FFFL +# define CURL_MASK_ULONG 0xFFFFUL +#elif (SIZEOF_LONG == 4) +# define CURL_MASK_SLONG 0x7FFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFUL +#elif (SIZEOF_LONG == 8) +# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL +#elif (SIZEOF_LONG == 16) +# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL +# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL +#else +# error "SIZEOF_LONG not defined" +#endif + +#if (SIZEOF_CURL_OFF_T == 2) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFF) +#elif (SIZEOF_CURL_OFF_T == 4) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFF) +#elif (SIZEOF_CURL_OFF_T == 8) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF) +#elif (SIZEOF_CURL_OFF_T == 16) +# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +#else +# error "SIZEOF_CURL_OFF_T not defined" +#endif + +#if (SIZEOF_SIZE_T == SIZEOF_SHORT) +# define CURL_MASK_SSIZE_T CURL_MASK_SSHORT +# define CURL_MASK_USIZE_T CURL_MASK_USHORT +#elif (SIZEOF_SIZE_T == SIZEOF_INT) +# define CURL_MASK_SSIZE_T CURL_MASK_SINT +# define CURL_MASK_USIZE_T CURL_MASK_UINT +#elif (SIZEOF_SIZE_T == SIZEOF_LONG) +# define CURL_MASK_SSIZE_T CURL_MASK_SLONG +# define CURL_MASK_USIZE_T CURL_MASK_ULONG +#elif (SIZEOF_SIZE_T == SIZEOF_CURL_OFF_T) +# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT +# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT +#else +# error "SIZEOF_SIZE_T not defined" +#endif + +/* +** unsigned long to unsigned short +*/ + +unsigned short curlx_ultous(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_USHORT); + return (unsigned short)(ulnum & (unsigned long) CURL_MASK_USHORT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned long to unsigned char +*/ + +unsigned char curlx_ultouc(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_UCHAR); + return (unsigned char)(ulnum & (unsigned long) CURL_MASK_UCHAR); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned long to signed int +*/ + +int curlx_ultosi(unsigned long ulnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_SINT); + return (int)(ulnum & (unsigned long) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed curl_off_t +*/ + +curl_off_t curlx_uztoso(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable:4310) /* cast truncates constant value */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT); + return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT); + +#if defined(__INTEL_COMPILER) || defined(_MSC_VER) +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed int +*/ + +int curlx_uztosi(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SINT); + return (int)(uznum & (size_t) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to unsigned long +*/ + +unsigned long curlx_uztoul(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + +#if (SIZEOF_LONG < SIZEOF_SIZE_T) + DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG); +#endif + return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to unsigned int +*/ + +unsigned int curlx_uztoui(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + +#if (SIZEOF_INT < SIZEOF_SIZE_T) + DEBUGASSERT(uznum <= (size_t) CURL_MASK_UINT); +#endif + return (unsigned int)(uznum & (size_t) CURL_MASK_UINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to signed int +*/ + +int curlx_sltosi(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); +#if (SIZEOF_INT < SIZEOF_LONG) + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT); +#endif + return (int)(slnum & (long) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to unsigned int +*/ + +unsigned int curlx_sltoui(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); +#if (SIZEOF_INT < SIZEOF_LONG) + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT); +#endif + return (unsigned int)(slnum & (long) CURL_MASK_UINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed long to unsigned short +*/ + +unsigned short curlx_sltous(long slnum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(slnum >= 0); + DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_USHORT); + return (unsigned short)(slnum & (long) CURL_MASK_USHORT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned size_t to signed ssize_t +*/ + +ssize_t curlx_uztosz(size_t uznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uznum <= (size_t) CURL_MASK_SSIZE_T); + return (ssize_t)(uznum & (size_t) CURL_MASK_SSIZE_T); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed curl_off_t to unsigned size_t +*/ + +size_t curlx_sotouz(curl_off_t sonum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sonum >= 0); + return (size_t)(sonum & (curl_off_t) CURL_MASK_USIZE_T); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed ssize_t to signed int +*/ + +int curlx_sztosi(ssize_t sznum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sznum >= 0); +#if (SIZEOF_INT < SIZEOF_SIZE_T) + DEBUGASSERT((size_t) sznum <= (size_t) CURL_MASK_SINT); +#endif + return (int)(sznum & (ssize_t) CURL_MASK_SINT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** unsigned int to unsigned short +*/ + +unsigned short curlx_uitous(unsigned int uinum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_USHORT); + return (unsigned short) (uinum & (unsigned int) CURL_MASK_USHORT); + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +/* +** signed int to unsigned size_t +*/ + +size_t curlx_sitouz(int sinum) +{ +#ifdef __INTEL_COMPILER +# pragma warning(push) +# pragma warning(disable:810) /* conversion may lose significant bits */ +#endif + + DEBUGASSERT(sinum >= 0); + return (size_t) sinum; + +#ifdef __INTEL_COMPILER +# pragma warning(pop) +#endif +} + +#ifdef USE_WINSOCK + +/* +** curl_socket_t to signed int +*/ + +int curlx_sktosi(curl_socket_t s) +{ + return (int)((ssize_t) s); +} + +/* +** signed int to curl_socket_t +*/ + +curl_socket_t curlx_sitosk(int i) +{ + return (curl_socket_t)((ssize_t) i); +} + +#endif /* USE_WINSOCK */ + +#if defined(WIN32) || defined(_WIN32) + +ssize_t curlx_read(int fd, void *buf, size_t count) +{ + return (ssize_t)read(fd, buf, curlx_uztoui(count)); +} + +ssize_t curlx_write(int fd, const void *buf, size_t count) +{ + return (ssize_t)write(fd, buf, curlx_uztoui(count)); +} + +#endif /* WIN32 || _WIN32 */ + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +int curlx_FD_ISSET(int fd, fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:1469) /* clobber ignored */ + return FD_ISSET(fd, fdset); + #pragma warning(pop) +} + +void curlx_FD_SET(int fd, fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:1469) /* clobber ignored */ + FD_SET(fd, fdset); + #pragma warning(pop) +} + +void curlx_FD_ZERO(fd_set *fdset) +{ + #pragma warning(push) + #pragma warning(disable:593) /* variable was set but never used */ + FD_ZERO(fdset); + #pragma warning(pop) +} + +unsigned short curlx_htons(unsigned short usnum) +{ +#if (__INTEL_COMPILER == 910) && defined(__i386__) + return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF)); +#else + #pragma warning(push) + #pragma warning(disable:810) /* conversion may lose significant bits */ + return htons(usnum); + #pragma warning(pop) +#endif +} + +unsigned short curlx_ntohs(unsigned short usnum) +{ +#if (__INTEL_COMPILER == 910) && defined(__i386__) + return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF)); +#else + #pragma warning(push) + #pragma warning(disable:810) /* conversion may lose significant bits */ + return ntohs(usnum); + #pragma warning(pop) +#endif +} + +#endif /* __INTEL_COMPILER && __unix__ */ diff --git a/libcurl/lib/warnless.h b/libcurl/lib/warnless.h new file mode 100644 index 0000000..ea4c439 --- /dev/null +++ b/libcurl/lib/warnless.h @@ -0,0 +1,112 @@ +#ifndef HEADER_CURL_WARNLESS_H +#define HEADER_CURL_WARNLESS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_WINSOCK +#include /* for curl_socket_t */ +#endif + +#define CURLX_FUNCTION_CAST(target_type, func) \ + (target_type)(void (*) (void))(func) + +unsigned short curlx_ultous(unsigned long ulnum); + +unsigned char curlx_ultouc(unsigned long ulnum); + +int curlx_ultosi(unsigned long ulnum); + +int curlx_uztosi(size_t uznum); + +curl_off_t curlx_uztoso(size_t uznum); + +unsigned long curlx_uztoul(size_t uznum); + +unsigned int curlx_uztoui(size_t uznum); + +int curlx_sltosi(long slnum); + +unsigned int curlx_sltoui(long slnum); + +unsigned short curlx_sltous(long slnum); + +ssize_t curlx_uztosz(size_t uznum); + +size_t curlx_sotouz(curl_off_t sonum); + +int curlx_sztosi(ssize_t sznum); + +unsigned short curlx_uitous(unsigned int uinum); + +size_t curlx_sitouz(int sinum); + +#ifdef USE_WINSOCK + +int curlx_sktosi(curl_socket_t s); + +curl_socket_t curlx_sitosk(int i); + +#endif /* USE_WINSOCK */ + +#if defined(WIN32) || defined(_WIN32) + +ssize_t curlx_read(int fd, void *buf, size_t count); + +ssize_t curlx_write(int fd, const void *buf, size_t count); + +#ifndef BUILDING_WARNLESS_C +# undef read +# define read(fd, buf, count) curlx_read(fd, buf, count) +# undef write +# define write(fd, buf, count) curlx_write(fd, buf, count) +#endif + +#endif /* WIN32 || _WIN32 */ + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +int curlx_FD_ISSET(int fd, fd_set *fdset); + +void curlx_FD_SET(int fd, fd_set *fdset); + +void curlx_FD_ZERO(fd_set *fdset); + +unsigned short curlx_htons(unsigned short usnum); + +unsigned short curlx_ntohs(unsigned short usnum); + +#ifndef BUILDING_WARNLESS_C +# undef FD_ISSET +# define FD_ISSET(a,b) curlx_FD_ISSET((a),(b)) +# undef FD_SET +# define FD_SET(a,b) curlx_FD_SET((a),(b)) +# undef FD_ZERO +# define FD_ZERO(a) curlx_FD_ZERO((a)) +# undef htons +# define htons(a) curlx_htons((a)) +# undef ntohs +# define ntohs(a) curlx_ntohs((a)) +#endif + +#endif /* __INTEL_COMPILER && __unix__ */ + +#endif /* HEADER_CURL_WARNLESS_H */ diff --git a/libcurl/lib/wildcard.c b/libcurl/lib/wildcard.c new file mode 100644 index 0000000..e94d3c5 --- /dev/null +++ b/libcurl/lib/wildcard.c @@ -0,0 +1,73 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#include "wildcard.h" +#include "llist.h" +#include "fileinfo.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static void fileinfo_dtor(void *user, void *element) +{ + (void)user; + Curl_fileinfo_cleanup(element); +} + +CURLcode Curl_wildcard_init(struct WildcardData *wc) +{ + Curl_llist_init(&wc->filelist, fileinfo_dtor); + wc->state = CURLWC_INIT; + + return CURLE_OK; +} + +void Curl_wildcard_dtor(struct WildcardData *wc) +{ + if(!wc) + return; + + if(wc->dtor) { + wc->dtor(wc->protdata); + wc->dtor = ZERO_NULL; + wc->protdata = NULL; + } + DEBUGASSERT(wc->protdata == NULL); + + Curl_llist_destroy(&wc->filelist, NULL); + + + free(wc->path); + wc->path = NULL; + free(wc->pattern); + wc->pattern = NULL; + + wc->customptr = NULL; + wc->state = CURLWC_INIT; +} + +#endif /* if disabled */ diff --git a/libcurl/lib/wildcard.h b/libcurl/lib/wildcard.h new file mode 100644 index 0000000..306c8c9 --- /dev/null +++ b/libcurl/lib/wildcard.h @@ -0,0 +1,67 @@ +#ifndef HEADER_CURL_WILDCARD_H +#define HEADER_CURL_WILDCARD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP +#include "llist.h" + +/* list of wildcard process states */ +typedef enum { + CURLWC_CLEAR = 0, + CURLWC_INIT = 1, + CURLWC_MATCHING, /* library is trying to get list of addresses for + downloading */ + CURLWC_DOWNLOADING, + CURLWC_CLEAN, /* deallocate resources and reset settings */ + CURLWC_SKIP, /* skip over concrete file */ + CURLWC_ERROR, /* error cases */ + CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop + will end */ +} curl_wildcard_states; + +typedef void (*curl_wildcard_dtor)(void *ptr); + +/* struct keeping information about wildcard download process */ +struct WildcardData { + curl_wildcard_states state; + char *path; /* path to the directory, where we trying wildcard-match */ + char *pattern; /* wildcard pattern */ + struct curl_llist filelist; /* llist with struct Curl_fileinfo */ + void *protdata; /* pointer to protocol specific temporary data */ + curl_wildcard_dtor dtor; + void *customptr; /* for CURLOPT_CHUNK_DATA pointer */ +}; + +CURLcode Curl_wildcard_init(struct WildcardData *wc); +void Curl_wildcard_dtor(struct WildcardData *wc); + +struct Curl_easy; + +#else +/* FTP is disabled */ +#define Curl_wildcard_dtor(x) +#endif + +#endif /* HEADER_CURL_WILDCARD_H */ diff --git a/libcurl/lib/x509asn1.c b/libcurl/lib/x509asn1.c new file mode 100644 index 0000000..ece5364 --- /dev/null +++ b/libcurl/lib/x509asn1.c @@ -0,0 +1,1283 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ + defined(USE_WOLFSSL) || defined(USE_SCHANNEL) + +#include +#include "urldata.h" +#include "strcase.h" +#include "hostcheck.h" +#include "vtls/vtls.h" +#include "sendf.h" +#include "inet_pton.h" +#include "curl_base64.h" +#include "x509asn1.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* ASN.1 OIDs. */ +static const char cnOID[] = "2.5.4.3"; /* Common name. */ +static const char sanOID[] = "2.5.29.17"; /* Subject alternative name. */ + +static const curl_OID OIDtable[] = { + { "1.2.840.10040.4.1", "dsa" }, + { "1.2.840.10040.4.3", "dsa-with-sha1" }, + { "1.2.840.10045.2.1", "ecPublicKey" }, + { "1.2.840.10045.3.0.1", "c2pnb163v1" }, + { "1.2.840.10045.4.1", "ecdsa-with-SHA1" }, + { "1.2.840.10046.2.1", "dhpublicnumber" }, + { "1.2.840.113549.1.1.1", "rsaEncryption" }, + { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" }, + { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" }, + { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" }, + { "1.2.840.113549.1.1.10", "RSASSA-PSS" }, + { "1.2.840.113549.1.1.14", "sha224WithRSAEncryption" }, + { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" }, + { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" }, + { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" }, + { "1.2.840.113549.2.2", "md2" }, + { "1.2.840.113549.2.5", "md5" }, + { "1.3.14.3.2.26", "sha1" }, + { cnOID, "CN" }, + { "2.5.4.4", "SN" }, + { "2.5.4.5", "serialNumber" }, + { "2.5.4.6", "C" }, + { "2.5.4.7", "L" }, + { "2.5.4.8", "ST" }, + { "2.5.4.9", "streetAddress" }, + { "2.5.4.10", "O" }, + { "2.5.4.11", "OU" }, + { "2.5.4.12", "title" }, + { "2.5.4.13", "description" }, + { "2.5.4.17", "postalCode" }, + { "2.5.4.41", "name" }, + { "2.5.4.42", "givenName" }, + { "2.5.4.43", "initials" }, + { "2.5.4.44", "generationQualifier" }, + { "2.5.4.45", "X500UniqueIdentifier" }, + { "2.5.4.46", "dnQualifier" }, + { "2.5.4.65", "pseudonym" }, + { "1.2.840.113549.1.9.1", "emailAddress" }, + { "2.5.4.72", "role" }, + { sanOID, "subjectAltName" }, + { "2.5.29.18", "issuerAltName" }, + { "2.5.29.19", "basicConstraints" }, + { "2.16.840.1.101.3.4.2.4", "sha224" }, + { "2.16.840.1.101.3.4.2.1", "sha256" }, + { "2.16.840.1.101.3.4.2.2", "sha384" }, + { "2.16.840.1.101.3.4.2.3", "sha512" }, + { (const char *) NULL, (const char *) NULL } +}; + +/* + * Lightweight ASN.1 parser. + * In particular, it does not check for syntactic/lexical errors. + * It is intended to support certificate information gathering for SSL backends + * that offer a mean to get certificates as a whole, but do not supply + * entry points to get particular certificate sub-fields. + * Please note there is no pretention here to rewrite a full SSL library. + */ + +static const char *getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end) + WARN_UNUSED_RESULT; + +static const char *getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end) +{ + unsigned char b; + unsigned long len; + curl_asn1Element lelem; + + /* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg' + ending at `end'. + Returns a pointer in source string after the parsed element, or NULL + if an error occurs. */ + if(!beg || !end || beg >= end || !*beg || + (size_t)(end - beg) > CURL_ASN1_MAX) + return NULL; + + /* Process header byte. */ + elem->header = beg; + b = (unsigned char) *beg++; + elem->constructed = (b & 0x20) != 0; + elem->class = (b >> 6) & 3; + b &= 0x1F; + if(b == 0x1F) + return NULL; /* Long tag values not supported here. */ + elem->tag = b; + + /* Process length. */ + if(beg >= end) + return NULL; + b = (unsigned char) *beg++; + if(!(b & 0x80)) + len = b; + else if(!(b &= 0x7F)) { + /* Unspecified length. Since we have all the data, we can determine the + effective length by skipping element until an end element is found. */ + if(!elem->constructed) + return NULL; + elem->beg = beg; + while(beg < end && *beg) { + beg = getASN1Element(&lelem, beg, end); + if(!beg) + return NULL; + } + if(beg >= end) + return NULL; + elem->end = beg; + return beg + 1; + } + else if((unsigned)b > (size_t)(end - beg)) + return NULL; /* Does not fit in source. */ + else { + /* Get long length. */ + len = 0; + do { + if(len & 0xFF000000L) + return NULL; /* Lengths > 32 bits are not supported. */ + len = (len << 8) | (unsigned char) *beg++; + } while(--b); + } + if(len > (size_t)(end - beg)) + return NULL; /* Element data does not fit in source. */ + elem->beg = beg; + elem->end = beg + len; + return elem->end; +} + +/* + * Search the null terminated OID or OID identifier in local table. + * Return the table entry pointer or NULL if not found. + */ +static const curl_OID * searchOID(const char *oid) +{ + const curl_OID *op; + for(op = OIDtable; op->numoid; op++) + if(!strcmp(op->numoid, oid) || strcasecompare(op->textoid, oid)) + return op; + + return NULL; +} + +/* + * Convert an ASN.1 Boolean value into its string representation. Return the + * dynamically allocated string, or NULL if source is not an ASN.1 Boolean + * value. + */ + +static const char *bool2str(const char *beg, const char *end) +{ + if(end - beg != 1) + return NULL; + return strdup(*beg? "TRUE": "FALSE"); +} + +/* + * Convert an ASN.1 octet string to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *octet2str(const char *beg, const char *end) +{ + size_t n = end - beg; + char *buf = NULL; + + if(n <= (SIZE_T_MAX - 1) / 3) { + buf = malloc(3 * n + 1); + if(buf) + for(n = 0; beg < end; n += 3) + msnprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); + } + return buf; +} + +static const char *bit2str(const char *beg, const char *end) +{ + /* Convert an ASN.1 bit string to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + if(++beg > end) + return NULL; + return octet2str(beg, end); +} + +/* + * Convert an ASN.1 integer value into its string representation. + * Return the dynamically allocated string, or NULL if source is not an + * ASN.1 integer value. + */ +static const char *int2str(const char *beg, const char *end) +{ + unsigned long val = 0; + size_t n = end - beg; + + if(!n) + return NULL; + + if(n > 4) + return octet2str(beg, end); + + /* Represent integers <= 32-bit as a single value. */ + if(*beg & 0x80) + val = ~val; + + do + val = (val << 8) | *(const unsigned char *) beg++; + while(beg < end); + return curl_maprintf("%s%lx", val >= 10? "0x": "", val); +} + +/* + * Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the + * destination buffer dynamically. The allocation size will normally be too + * large: this is to avoid buffer overflows. + * Terminate the string with a nul byte and return the converted + * string length. + */ +static ssize_t +utf8asn1str(char **to, int type, const char *from, const char *end) +{ + size_t inlength = end - from; + int size = 1; + size_t outlength; + char *buf; + + *to = NULL; + switch(type) { + case CURL_ASN1_BMP_STRING: + size = 2; + break; + case CURL_ASN1_UNIVERSAL_STRING: + size = 4; + break; + case CURL_ASN1_NUMERIC_STRING: + case CURL_ASN1_PRINTABLE_STRING: + case CURL_ASN1_TELETEX_STRING: + case CURL_ASN1_IA5_STRING: + case CURL_ASN1_VISIBLE_STRING: + case CURL_ASN1_UTF8_STRING: + break; + default: + return -1; /* Conversion not supported. */ + } + + if(inlength % size) + return -1; /* Length inconsistent with character size. */ + if(inlength / size > (SIZE_T_MAX - 1) / 4) + return -1; /* Too big. */ + buf = malloc(4 * (inlength / size) + 1); + if(!buf) + return -1; /* Not enough memory. */ + + if(type == CURL_ASN1_UTF8_STRING) { + /* Just copy. */ + outlength = inlength; + if(outlength) + memcpy(buf, from, outlength); + } + else { + for(outlength = 0; from < end;) { + int charsize; + unsigned int wc; + + wc = 0; + switch(size) { + case 4: + wc = (wc << 8) | *(const unsigned char *) from++; + wc = (wc << 8) | *(const unsigned char *) from++; + /* FALLTHROUGH */ + case 2: + wc = (wc << 8) | *(const unsigned char *) from++; + /* FALLTHROUGH */ + default: /* case 1: */ + wc = (wc << 8) | *(const unsigned char *) from++; + } + charsize = 1; + if(wc >= 0x00000080) { + if(wc >= 0x00000800) { + if(wc >= 0x00010000) { + if(wc >= 0x00200000) { + free(buf); + return -1; /* Invalid char. size for target encoding. */ + } + buf[outlength + 3] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x00010000; + charsize++; + } + buf[outlength + 2] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x00000800; + charsize++; + } + buf[outlength + 1] = (char) (0x80 | (wc & 0x3F)); + wc = (wc >> 6) | 0x000000C0; + charsize++; + } + buf[outlength] = (char) wc; + outlength += charsize; + } + } + buf[outlength] = '\0'; + *to = buf; + return outlength; +} + +/* + * Convert an ASN.1 String into its UTF-8 string representation. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *string2str(int type, const char *beg, const char *end) +{ + char *buf; + if(utf8asn1str(&buf, type, beg, end) < 0) + return NULL; + return buf; +} + +/* + * Decimal ASCII encode unsigned integer `x' into the buflen sized buffer at + * buf. Return the total number of encoded digits, even if larger than + * `buflen'. + */ +static size_t encodeUint(char *buf, size_t buflen, unsigned int x) +{ + size_t i = 0; + unsigned int y = x / 10; + + if(y) { + i = encodeUint(buf, buflen, y); + x -= y * 10; + } + if(i < buflen) + buf[i] = (char) ('0' + x); + i++; + if(i < buflen) + buf[i] = '\0'; /* Store a terminator if possible. */ + return i; +} + +/* + * Convert an ASN.1 OID into its dotted string representation. + * Store the result in th `n'-byte buffer at `buf'. + * Return the converted string length, or 0 on errors. + */ +static size_t encodeOID(char *buf, size_t buflen, + const char *beg, const char *end) +{ + size_t i; + unsigned int x; + unsigned int y; + + /* Process the first two numbers. */ + y = *(const unsigned char *) beg++; + x = y / 40; + y -= x * 40; + i = encodeUint(buf, buflen, x); + if(i < buflen) + buf[i] = '.'; + i++; + if(i >= buflen) + i += encodeUint(NULL, 0, y); + else + i += encodeUint(buf + i, buflen - i, y); + + /* Process the trailing numbers. */ + while(beg < end) { + if(i < buflen) + buf[i] = '.'; + i++; + x = 0; + do { + if(x & 0xFF000000) + return 0; + y = *(const unsigned char *) beg++; + x = (x << 7) | (y & 0x7F); + } while(y & 0x80); + if(i >= buflen) + i += encodeUint(NULL, 0, x); + else + i += encodeUint(buf + i, buflen - i, x); + } + if(i < buflen) + buf[i] = '\0'; + return i; +} + +/* + * Convert an ASN.1 OID into its dotted or symbolic string representation. + * Return the dynamically allocated string, or NULL if an error occurs. + */ + +static const char *OID2str(const char *beg, const char *end, bool symbolic) +{ + char *buf = NULL; + if(beg < end) { + size_t buflen = encodeOID(NULL, 0, beg, end); + if(buflen) { + buf = malloc(buflen + 1); /* one extra for the zero byte */ + if(buf) { + encodeOID(buf, buflen, beg, end); + buf[buflen] = '\0'; + + if(symbolic) { + const curl_OID *op = searchOID(buf); + if(op) { + free(buf); + buf = strdup(op->textoid); + } + } + } + } + } + return buf; +} + +static const char *GTime2str(const char *beg, const char *end) +{ + const char *tzp; + const char *fracp; + char sec1, sec2; + size_t fracl; + size_t tzl; + const char *sep = ""; + + /* Convert an ASN.1 Generalized time to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + + for(fracp = beg; fracp < end && *fracp >= '0' && *fracp <= '9'; fracp++) + ; + + /* Get seconds digits. */ + sec1 = '0'; + switch(fracp - beg - 12) { + case 0: + sec2 = '0'; + break; + case 2: + sec1 = fracp[-2]; + /* FALLTHROUGH */ + case 1: + sec2 = fracp[-1]; + break; + default: + return NULL; + } + + /* Scan for timezone, measure fractional seconds. */ + tzp = fracp; + fracl = 0; + if(fracp < end && (*fracp == '.' || *fracp == ',')) { + fracp++; + do + tzp++; + while(tzp < end && *tzp >= '0' && *tzp <= '9'); + /* Strip leading zeroes in fractional seconds. */ + for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--) + ; + } + + /* Process timezone. */ + if(tzp >= end) + ; /* Nothing to do. */ + else if(*tzp == 'Z') { + tzp = " GMT"; + end = tzp + 4; + } + else { + sep = " "; + tzp++; + } + + tzl = end - tzp; + return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s", + beg, beg + 4, beg + 6, + beg + 8, beg + 10, sec1, sec2, + fracl? ".": "", fracl, fracp, + sep, tzl, tzp); +} + +/* + * Convert an ASN.1 UTC time to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *UTime2str(const char *beg, const char *end) +{ + const char *tzp; + size_t tzl; + const char *sec; + + for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++) + ; + /* Get the seconds. */ + sec = beg + 10; + switch(tzp - sec) { + case 0: + sec = "00"; + case 2: + break; + default: + return NULL; + } + + /* Process timezone. */ + if(tzp >= end) + return NULL; + if(*tzp == 'Z') { + tzp = "GMT"; + end = tzp + 3; + } + else + tzp++; + + tzl = end - tzp; + return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s", + 20 - (*beg >= '5'), beg, beg + 2, beg + 4, + beg + 6, beg + 8, sec, + tzl, tzp); +} + +/* + * Convert an ASN.1 element to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *ASN1tostr(curl_asn1Element *elem, int type) +{ + if(elem->constructed) + return NULL; /* No conversion of structured elements. */ + + if(!type) + type = elem->tag; /* Type not forced: use element tag as type. */ + + switch(type) { + case CURL_ASN1_BOOLEAN: + return bool2str(elem->beg, elem->end); + case CURL_ASN1_INTEGER: + case CURL_ASN1_ENUMERATED: + return int2str(elem->beg, elem->end); + case CURL_ASN1_BIT_STRING: + return bit2str(elem->beg, elem->end); + case CURL_ASN1_OCTET_STRING: + return octet2str(elem->beg, elem->end); + case CURL_ASN1_NULL: + return strdup(""); + case CURL_ASN1_OBJECT_IDENTIFIER: + return OID2str(elem->beg, elem->end, TRUE); + case CURL_ASN1_UTC_TIME: + return UTime2str(elem->beg, elem->end); + case CURL_ASN1_GENERALIZED_TIME: + return GTime2str(elem->beg, elem->end); + case CURL_ASN1_UTF8_STRING: + case CURL_ASN1_NUMERIC_STRING: + case CURL_ASN1_PRINTABLE_STRING: + case CURL_ASN1_TELETEX_STRING: + case CURL_ASN1_IA5_STRING: + case CURL_ASN1_VISIBLE_STRING: + case CURL_ASN1_UNIVERSAL_STRING: + case CURL_ASN1_BMP_STRING: + return string2str(type, elem->beg, elem->end); + } + + return NULL; /* Unsupported. */ +} + +/* + * ASCII encode distinguished name at `dn' into the `buflen'-sized buffer at + * `buf'. Return the total string length, even if larger than `buflen'. + */ +static ssize_t encodeDN(char *buf, size_t buflen, curl_asn1Element *dn) +{ + curl_asn1Element rdn; + curl_asn1Element atv; + curl_asn1Element oid; + curl_asn1Element value; + size_t l = 0; + const char *p1; + const char *p2; + const char *p3; + const char *str; + + for(p1 = dn->beg; p1 < dn->end;) { + p1 = getASN1Element(&rdn, p1, dn->end); + if(!p1) + return -1; + for(p2 = rdn.beg; p2 < rdn.end;) { + p2 = getASN1Element(&atv, p2, rdn.end); + if(!p2) + return -1; + p3 = getASN1Element(&oid, atv.beg, atv.end); + if(!p3) + return -1; + if(!getASN1Element(&value, p3, atv.end)) + return -1; + str = ASN1tostr(&oid, 0); + if(!str) + return -1; + + /* Encode delimiter. + If attribute has a short uppercase name, delimiter is ", ". */ + if(l) { + for(p3 = str; isupper(*p3); p3++) + ; + for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) { + if(l < buflen) + buf[l] = *p3; + l++; + } + } + + /* Encode attribute name. */ + for(p3 = str; *p3; p3++) { + if(l < buflen) + buf[l] = *p3; + l++; + } + free((char *) str); + + /* Generate equal sign. */ + if(l < buflen) + buf[l] = '='; + l++; + + /* Generate value. */ + str = ASN1tostr(&value, 0); + if(!str) + return -1; + for(p3 = str; *p3; p3++) { + if(l < buflen) + buf[l] = *p3; + l++; + } + free((char *) str); + } + } + + return l; +} + +/* + * Convert an ASN.1 distinguished name into a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ +static const char *DNtostr(curl_asn1Element *dn) +{ + char *buf = NULL; + ssize_t buflen = encodeDN(NULL, 0, dn); + + if(buflen >= 0) { + buf = malloc(buflen + 1); + if(buf) { + encodeDN(buf, buflen + 1, dn); + buf[buflen] = '\0'; + } + } + return buf; +} + +/* + * ASN.1 parse an X509 certificate into structure subfields. + * Syntax is assumed to have already been checked by the SSL backend. + * See RFC 5280. + */ +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end) +{ + curl_asn1Element elem; + curl_asn1Element tbsCertificate; + const char *ccp; + static const char defaultVersion = 0; /* v1. */ + + cert->certificate.header = NULL; + cert->certificate.beg = beg; + cert->certificate.end = end; + + /* Get the sequence content. */ + if(!getASN1Element(&elem, beg, end)) + return -1; /* Invalid bounds/size. */ + beg = elem.beg; + end = elem.end; + + /* Get tbsCertificate. */ + beg = getASN1Element(&tbsCertificate, beg, end); + if(!beg) + return -1; + /* Skip the signatureAlgorithm. */ + beg = getASN1Element(&cert->signatureAlgorithm, beg, end); + if(!beg) + return -1; + /* Get the signatureValue. */ + if(!getASN1Element(&cert->signature, beg, end)) + return -1; + + /* Parse TBSCertificate. */ + beg = tbsCertificate.beg; + end = tbsCertificate.end; + /* Get optional version, get serialNumber. */ + cert->version.header = NULL; + cert->version.beg = &defaultVersion; + cert->version.end = &defaultVersion + sizeof(defaultVersion); + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + if(elem.tag == 0) { + if(!getASN1Element(&cert->version, elem.beg, elem.end)) + return -1; + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + } + cert->serialNumber = elem; + /* Get signature algorithm. */ + beg = getASN1Element(&cert->signatureAlgorithm, beg, end); + /* Get issuer. */ + beg = getASN1Element(&cert->issuer, beg, end); + if(!beg) + return -1; + /* Get notBefore and notAfter. */ + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + ccp = getASN1Element(&cert->notBefore, elem.beg, elem.end); + if(!ccp) + return -1; + if(!getASN1Element(&cert->notAfter, ccp, elem.end)) + return -1; + /* Get subject. */ + beg = getASN1Element(&cert->subject, beg, end); + if(!beg) + return -1; + /* Get subjectPublicKeyAlgorithm and subjectPublicKey. */ + beg = getASN1Element(&cert->subjectPublicKeyInfo, beg, end); + if(!beg) + return -1; + ccp = getASN1Element(&cert->subjectPublicKeyAlgorithm, + cert->subjectPublicKeyInfo.beg, + cert->subjectPublicKeyInfo.end); + if(!ccp) + return -1; + if(!getASN1Element(&cert->subjectPublicKey, ccp, + cert->subjectPublicKeyInfo.end)) + return -1; + /* Get optional issuerUiqueID, subjectUniqueID and extensions. */ + cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0; + cert->extensions.tag = elem.tag = 0; + cert->issuerUniqueID.header = cert->subjectUniqueID.header = NULL; + cert->issuerUniqueID.beg = cert->issuerUniqueID.end = ""; + cert->subjectUniqueID.beg = cert->subjectUniqueID.end = ""; + cert->extensions.header = NULL; + cert->extensions.beg = cert->extensions.end = ""; + if(beg < end) { + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + } + if(elem.tag == 1) { + cert->issuerUniqueID = elem; + if(beg < end) { + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + } + } + if(elem.tag == 2) { + cert->subjectUniqueID = elem; + if(beg < end) { + beg = getASN1Element(&elem, beg, end); + if(!beg) + return -1; + } + } + if(elem.tag == 3) + if(!getASN1Element(&cert->extensions, elem.beg, elem.end)) + return -1; + return 0; +} + + +/* + * Copy at most 64-characters, terminate with a newline and returns the + * effective number of stored characters. + */ +static size_t copySubstring(char *to, const char *from) +{ + size_t i; + for(i = 0; i < 64; i++) { + to[i] = *from; + if(!*from++) + break; + } + + to[i++] = '\n'; + return i; +} + +static const char *dumpAlgo(curl_asn1Element *param, + const char *beg, const char *end) +{ + curl_asn1Element oid; + + /* Get algorithm parameters and return algorithm name. */ + + beg = getASN1Element(&oid, beg, end); + if(!beg) + return NULL; + param->header = NULL; + param->tag = 0; + param->beg = param->end = end; + if(beg < end) + if(!getASN1Element(param, beg, end)) + return NULL; + return OID2str(oid.beg, oid.end, TRUE); +} + +static void do_pubkey_field(struct Curl_easy *data, int certnum, + const char *label, curl_asn1Element *elem) +{ + const char *output; + + /* Generate a certificate information record for the public key. */ + + output = ASN1tostr(elem, 0); + if(output) { + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, label, output); + if(!certnum) + infof(data, " %s: %s\n", label, output); + free((char *) output); + } +} + +static void do_pubkey(struct Curl_easy *data, int certnum, + const char *algo, curl_asn1Element *param, + curl_asn1Element *pubkey) +{ + curl_asn1Element elem; + curl_asn1Element pk; + const char *p; + + /* Generate all information records for the public key. */ + + /* Get the public key (single element). */ + if(!getASN1Element(&pk, pubkey->beg + 1, pubkey->end)) + return; + + if(strcasecompare(algo, "rsaEncryption")) { + const char *q; + unsigned long len; + + p = getASN1Element(&elem, pk.beg, pk.end); + if(!p) + return; + + /* Compute key length. */ + for(q = elem.beg; !*q && q < elem.end; q++) + ; + len = (unsigned long)((elem.end - q) * 8); + if(len) { + unsigned int i; + for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1) + len--; + } + if(len > 32) + elem.beg = q; /* Strip leading zero bytes. */ + if(!certnum) + infof(data, " RSA Public Key (%lu bits)\n", len); + if(data->set.ssl.certinfo) { + q = curl_maprintf("%lu", len); + if(q) { + Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q); + free((char *) q); + } + } + /* Generate coefficients. */ + do_pubkey_field(data, certnum, "rsa(n)", &elem); + if(!getASN1Element(&elem, p, pk.end)) + return; + do_pubkey_field(data, certnum, "rsa(e)", &elem); + } + else if(strcasecompare(algo, "dsa")) { + p = getASN1Element(&elem, param->beg, param->end); + if(p) { + do_pubkey_field(data, certnum, "dsa(p)", &elem); + p = getASN1Element(&elem, p, param->end); + if(p) { + do_pubkey_field(data, certnum, "dsa(q)", &elem); + if(getASN1Element(&elem, p, param->end)) { + do_pubkey_field(data, certnum, "dsa(g)", &elem); + do_pubkey_field(data, certnum, "dsa(pub_key)", &pk); + } + } + } + } + else if(strcasecompare(algo, "dhpublicnumber")) { + p = getASN1Element(&elem, param->beg, param->end); + if(p) { + do_pubkey_field(data, certnum, "dh(p)", &elem); + if(getASN1Element(&elem, param->beg, param->end)) { + do_pubkey_field(data, certnum, "dh(g)", &elem); + do_pubkey_field(data, certnum, "dh(pub_key)", &pk); + } + } + } +} + +CURLcode Curl_extract_certinfo(struct connectdata *conn, + int certnum, + const char *beg, + const char *end) +{ + curl_X509certificate cert; + struct Curl_easy *data = conn->data; + curl_asn1Element param; + const char *ccp; + char *cp1; + size_t cl1; + char *cp2; + CURLcode result; + unsigned long version; + size_t i; + size_t j; + + if(!data->set.ssl.certinfo) + if(certnum) + return CURLE_OK; + + /* Prepare the certificate information for curl_easy_getinfo(). */ + + /* Extract the certificate ASN.1 elements. */ + if(Curl_parseX509(&cert, beg, end)) + return CURLE_PEER_FAILED_VERIFICATION; + + /* Subject. */ + ccp = DNtostr(&cert.subject); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Subject", ccp); + if(!certnum) + infof(data, "%2d Subject: %s\n", certnum, ccp); + free((char *) ccp); + + /* Issuer. */ + ccp = DNtostr(&cert.issuer); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp); + if(!certnum) + infof(data, " Issuer: %s\n", ccp); + free((char *) ccp); + + /* Version (always fits in less than 32 bits). */ + version = 0; + for(ccp = cert.version.beg; ccp < cert.version.end; ccp++) + version = (version << 8) | *(const unsigned char *) ccp; + if(data->set.ssl.certinfo) { + ccp = curl_maprintf("%lx", version); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + Curl_ssl_push_certinfo(data, certnum, "Version", ccp); + free((char *) ccp); + } + if(!certnum) + infof(data, " Version: %lu (0x%lx)\n", version + 1, version); + + /* Serial number. */ + ccp = ASN1tostr(&cert.serialNumber, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp); + if(!certnum) + infof(data, " Serial Number: %s\n", ccp); + free((char *) ccp); + + /* Signature algorithm .*/ + ccp = dumpAlgo(¶m, cert.signatureAlgorithm.beg, + cert.signatureAlgorithm.end); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp); + if(!certnum) + infof(data, " Signature Algorithm: %s\n", ccp); + free((char *) ccp); + + /* Start Date. */ + ccp = ASN1tostr(&cert.notBefore, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp); + if(!certnum) + infof(data, " Start Date: %s\n", ccp); + free((char *) ccp); + + /* Expire Date. */ + ccp = ASN1tostr(&cert.notAfter, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp); + if(!certnum) + infof(data, " Expire Date: %s\n", ccp); + free((char *) ccp); + + /* Public Key Algorithm. */ + ccp = dumpAlgo(¶m, cert.subjectPublicKeyAlgorithm.beg, + cert.subjectPublicKeyAlgorithm.end); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp); + if(!certnum) + infof(data, " Public Key Algorithm: %s\n", ccp); + do_pubkey(data, certnum, ccp, ¶m, &cert.subjectPublicKey); + free((char *) ccp); + + /* Signature. */ + ccp = ASN1tostr(&cert.signature, 0); + if(!ccp) + return CURLE_OUT_OF_MEMORY; + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Signature", ccp); + if(!certnum) + infof(data, " Signature: %s\n", ccp); + free((char *) ccp); + + /* Generate PEM certificate. */ + result = Curl_base64_encode(data, cert.certificate.beg, + cert.certificate.end - cert.certificate.beg, + &cp1, &cl1); + if(result) + return result; + /* Compute the number of characters in final certificate string. Format is: + -----BEGIN CERTIFICATE-----\n + \n + . + . + . + -----END CERTIFICATE-----\n + */ + i = 28 + cl1 + (cl1 + 64 - 1) / 64 + 26; + cp2 = malloc(i + 1); + if(!cp2) { + free(cp1); + return CURLE_OUT_OF_MEMORY; + } + /* Build the certificate string. */ + i = copySubstring(cp2, "-----BEGIN CERTIFICATE-----"); + for(j = 0; j < cl1; j += 64) + i += copySubstring(cp2 + i, cp1 + j); + i += copySubstring(cp2 + i, "-----END CERTIFICATE-----"); + cp2[i] = '\0'; + free(cp1); + if(data->set.ssl.certinfo) + Curl_ssl_push_certinfo(data, certnum, "Cert", cp2); + if(!certnum) + infof(data, "%s\n", cp2); + free(cp2); + return CURLE_OK; +} + +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */ + +#if defined(USE_GSKIT) + +static const char *checkOID(const char *beg, const char *end, + const char *oid) +{ + curl_asn1Element e; + const char *ccp; + const char *p; + bool matched; + + /* Check if first ASN.1 element at `beg' is the given OID. + Return a pointer in the source after the OID if found, else NULL. */ + + ccp = getASN1Element(&e, beg, end); + if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER) + return NULL; + + p = OID2str(e.beg, e.end, FALSE); + if(!p) + return NULL; + + matched = !strcmp(p, oid); + free((char *) p); + return matched? ccp: NULL; +} + +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end) +{ + struct Curl_easy *data = conn->data; + curl_X509certificate cert; + curl_asn1Element dn; + curl_asn1Element elem; + curl_asn1Element ext; + curl_asn1Element name; + const char *p; + const char *q; + char *dnsname; + int matched = -1; + size_t addrlen = (size_t) -1; + ssize_t len; + const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: + conn->host.name; + const char * const dispname = SSL_IS_PROXY()? + conn->http_proxy.host.dispname: + conn->host.dispname; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + + /* Verify that connection server matches info in X509 certificate at + `beg'..`end'. */ + + if(!SSL_CONN_CONFIG(verifyhost)) + return CURLE_OK; + + if(Curl_parseX509(&cert, beg, end)) + return CURLE_PEER_FAILED_VERIFICATION; + + /* Get the server IP address. */ +#ifdef ENABLE_IPV6 + if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr)) + addrlen = sizeof(struct in6_addr); + else +#endif + if(Curl_inet_pton(AF_INET, hostname, &addr)) + addrlen = sizeof(struct in_addr); + + /* Process extensions. */ + for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) { + p = getASN1Element(&ext, p, cert.extensions.end); + if(!p) + return CURLE_PEER_FAILED_VERIFICATION; + + /* Check if extension is a subjectAlternativeName. */ + ext.beg = checkOID(ext.beg, ext.end, sanOID); + if(ext.beg) { + ext.beg = getASN1Element(&elem, ext.beg, ext.end); + if(!ext.beg) + return CURLE_PEER_FAILED_VERIFICATION; + /* Skip critical if present. */ + if(elem.tag == CURL_ASN1_BOOLEAN) { + ext.beg = getASN1Element(&elem, ext.beg, ext.end); + if(!ext.beg) + return CURLE_PEER_FAILED_VERIFICATION; + } + /* Parse the octet string contents: is a single sequence. */ + if(!getASN1Element(&elem, elem.beg, elem.end)) + return CURLE_PEER_FAILED_VERIFICATION; + /* Check all GeneralNames. */ + for(q = elem.beg; matched != 1 && q < elem.end;) { + q = getASN1Element(&name, q, elem.end); + if(!q) + break; + switch(name.tag) { + case 2: /* DNS name. */ + len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING, + name.beg, name.end); + if(len > 0 && (size_t)len == strlen(dnsname)) + matched = Curl_cert_hostcheck(dnsname, hostname); + else + matched = 0; + free(dnsname); + break; + + case 7: /* IP address. */ + matched = (size_t) (name.end - name.beg) == addrlen && + !memcmp(&addr, name.beg, addrlen); + break; + } + } + } + } + + switch(matched) { + case 1: + /* an alternative name matched the server hostname */ + infof(data, "\t subjectAltName: %s matched\n", dispname); + return CURLE_OK; + case 0: + /* an alternative name field existed, but didn't match and then + we MUST fail */ + infof(data, "\t subjectAltName does not match %s\n", dispname); + return CURLE_PEER_FAILED_VERIFICATION; + } + + /* Process subject. */ + name.header = NULL; + name.beg = name.end = ""; + q = cert.subject.beg; + /* we have to look to the last occurrence of a commonName in the + distinguished one to get the most significant one. */ + while(q < cert.subject.end) { + q = getASN1Element(&dn, q, cert.subject.end); + if(!q) + break; + for(p = dn.beg; p < dn.end;) { + p = getASN1Element(&elem, p, dn.end); + if(!p) + return CURLE_PEER_FAILED_VERIFICATION; + /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */ + elem.beg = checkOID(elem.beg, elem.end, cnOID); + if(elem.beg) + name = elem; /* Latch CN. */ + } + } + + /* Check the CN if found. */ + if(!getASN1Element(&elem, name.beg, name.end)) + failf(data, "SSL: unable to obtain common name from peer certificate"); + else { + len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end); + if(len < 0) { + free(dnsname); + return CURLE_OUT_OF_MEMORY; + } + if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */ + failf(data, "SSL: illegal cert name field"); + else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) { + infof(data, "\t common name: %s (matched)\n", dnsname); + free(dnsname); + return CURLE_OK; + } + else + failf(data, "SSL: certificate subject name '%s' does not match " + "target host name '%s'", dnsname, dispname); + free(dnsname); + } + + return CURLE_PEER_FAILED_VERIFICATION; +} + +#endif /* USE_GSKIT */ diff --git a/libcurl/lib/x509asn1.h b/libcurl/lib/x509asn1.h new file mode 100644 index 0000000..205fdc0 --- /dev/null +++ b/libcurl/lib/x509asn1.h @@ -0,0 +1,134 @@ +#ifndef HEADER_CURL_X509ASN1_H +#define HEADER_CURL_X509ASN1_H + +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ + defined(USE_WOLFSSL) || defined(USE_SCHANNEL) + +#include "urldata.h" + +/* + * Constants. + */ + +/* Largest supported ASN.1 structure. */ +#define CURL_ASN1_MAX ((size_t) 0x40000) /* 256K */ + +/* ASN.1 classes. */ +#define CURL_ASN1_UNIVERSAL 0 +#define CURL_ASN1_APPLICATION 1 +#define CURL_ASN1_CONTEXT_SPECIFIC 2 +#define CURL_ASN1_PRIVATE 3 + +/* ASN.1 types. */ +#define CURL_ASN1_BOOLEAN 1 +#define CURL_ASN1_INTEGER 2 +#define CURL_ASN1_BIT_STRING 3 +#define CURL_ASN1_OCTET_STRING 4 +#define CURL_ASN1_NULL 5 +#define CURL_ASN1_OBJECT_IDENTIFIER 6 +#define CURL_ASN1_OBJECT_DESCRIPTOR 7 +#define CURL_ASN1_INSTANCE_OF 8 +#define CURL_ASN1_REAL 9 +#define CURL_ASN1_ENUMERATED 10 +#define CURL_ASN1_EMBEDDED 11 +#define CURL_ASN1_UTF8_STRING 12 +#define CURL_ASN1_RELATIVE_OID 13 +#define CURL_ASN1_SEQUENCE 16 +#define CURL_ASN1_SET 17 +#define CURL_ASN1_NUMERIC_STRING 18 +#define CURL_ASN1_PRINTABLE_STRING 19 +#define CURL_ASN1_TELETEX_STRING 20 +#define CURL_ASN1_VIDEOTEX_STRING 21 +#define CURL_ASN1_IA5_STRING 22 +#define CURL_ASN1_UTC_TIME 23 +#define CURL_ASN1_GENERALIZED_TIME 24 +#define CURL_ASN1_GRAPHIC_STRING 25 +#define CURL_ASN1_VISIBLE_STRING 26 +#define CURL_ASN1_GENERAL_STRING 27 +#define CURL_ASN1_UNIVERSAL_STRING 28 +#define CURL_ASN1_CHARACTER_STRING 29 +#define CURL_ASN1_BMP_STRING 30 + + +/* + * Types. + */ + +/* ASN.1 parsed element. */ +typedef struct { + const char * header; /* Pointer to header byte. */ + const char * beg; /* Pointer to element data. */ + const char * end; /* Pointer to 1st byte after element. */ + unsigned char class; /* ASN.1 element class. */ + unsigned char tag; /* ASN.1 element tag. */ + bool constructed; /* Element is constructed. */ +} curl_asn1Element; + + +/* ASN.1 OID table entry. */ +typedef struct { + const char * numoid; /* Dotted-numeric OID. */ + const char * textoid; /* OID name. */ +} curl_OID; + + +/* X509 certificate: RFC 5280. */ +typedef struct { + curl_asn1Element certificate; + curl_asn1Element version; + curl_asn1Element serialNumber; + curl_asn1Element signatureAlgorithm; + curl_asn1Element signature; + curl_asn1Element issuer; + curl_asn1Element notBefore; + curl_asn1Element notAfter; + curl_asn1Element subject; + curl_asn1Element subjectPublicKeyInfo; + curl_asn1Element subjectPublicKeyAlgorithm; + curl_asn1Element subjectPublicKey; + curl_asn1Element issuerUniqueID; + curl_asn1Element subjectUniqueID; + curl_asn1Element extensions; +} curl_X509certificate; + + +/* + * Prototypes. + */ + +const char *Curl_getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end); +const char *Curl_ASN1tostr(curl_asn1Element *elem, int type); +const char *Curl_DNtostr(curl_asn1Element *dn); +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end); +CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, + const char *beg, const char *end); +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end); +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */ +#endif /* HEADER_CURL_X509ASN1_H */ diff --git a/libcurl/libcurl.vcproj b/libcurl/libcurl.vcproj new file mode 100644 index 0000000..797aa1e --- /dev/null +++ b/libcurl/libcurl.vcproj @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/test.cpp b/test/test.cpp new file mode 100644 index 0000000..7b62d0e --- /dev/null +++ b/test/test.cpp @@ -0,0 +1,3555 @@ +/* + * Xbox libcurl + BearSSL Comprehensive Test Suite + * + * Features: + * - On-screen text display with CURL logo + * - Visual pass/fail indicators + * - Comprehensive protocol testing + * - Verbose SSL/TLS debugging + * - Debug output to XBDM + */ + +#include +#include +#include +#include +#include +#include "xbox_console.h" + +/* BearSSL debug support */ +#include +#include "../BearSSL-OG/ssl_debug.h" +#include "../BearSSL-OG/debug_utility.h" +#include "../BearSSL-OG/session_cache.h" +#include "../BearSSL-OG/cert_pinning.h" + +/* VS2003 compatibility: use _snprintf instead of snprintf */ +#define snprintf _snprintf + +/* + * XboxCurl ASCII Art Logo + Xbox Controller + * Controller art from https://asciiart.website/art/2237 + */ +static const char *curl_logo[] = { + " __ __ _ ____ _", + " \\ \\/ / | |__ ___ __ __ / ___| _ _ _ __| |", + " \\ / | '_ \\ / _ \\ \\ \\/ /| | | | | || '__| |", + " / \\ | |_) || (_) | > < | |___ | |_| || | | |", + " /_/\\_\\ |_.__/ \\___/ /_/\\_\\ \\____| \\__,_||_| |_|", + "", + " libcurl 7.65.3 + BearSSL/0.6 for Original Xbox", + NULL +}; + +/* + * Test result tracking + */ +static int tests_passed = 0; +static int tests_failed = 0; +static int tests_skipped = 0; +static size_t total_bytes_received = 0; + +/* + * Verbose debug logging control + */ +static int g_verbose_ssl = 1; /* Enable verbose SSL debugging */ + +/* + * Write callback for receiving data + */ +static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t total = size * nmemb; + total_bytes_received += total; + (void)contents; + (void)userp; + return total; +} + +/* + * Write callback for saving data to a file on disk + */ +struct file_write_data { + FILE *fp; + size_t bytes_written; +}; + +static size_t file_write_callback(void *contents, size_t size, size_t nmemb, void *userp) +{ + struct file_write_data *fwd = (struct file_write_data *)userp; + size_t total = size * nmemb; + size_t written; + + if (!fwd || !fwd->fp) return 0; + + written = fwrite(contents, 1, total, fwd->fp); + fwd->bytes_written += written; + total_bytes_received += written; + return written; +} + +/* + * Write callback that captures response body into a buffer for inspection + */ +struct response_data { + char buffer[8192]; + size_t size; +}; + +static size_t capture_callback(void *contents, size_t size, size_t nmemb, void *userp) +{ + struct response_data *rd = (struct response_data *)userp; + size_t total = size * nmemb; + size_t remaining = sizeof(rd->buffer) - rd->size - 1; + size_t copy_size = total < remaining ? total : remaining; + + if (copy_size > 0) { + memcpy(rd->buffer + rd->size, contents, copy_size); + rd->size += copy_size; + rd->buffer[rd->size] = '\0'; + } + total_bytes_received += total; + return total; +} + +/* + * Debug callback for verbose curl logging + * This captures ALL curl operations including SSL handshake details + */ +static int my_curl_debug_callback(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr) +{ + char buf[512]; + char prefix[16]; + size_t i, print_size; + + (void)handle; + (void)userptr; + + switch (type) { + case CURLINFO_TEXT: + snprintf(prefix, sizeof(prefix), "* "); + break; + case CURLINFO_HEADER_IN: + snprintf(prefix, sizeof(prefix), "< "); + break; + case CURLINFO_HEADER_OUT: + snprintf(prefix, sizeof(prefix), "> "); + break; + case CURLINFO_DATA_IN: + if (g_verbose_ssl) { + snprintf(buf, sizeof(buf), "[DATA IN] %u bytes received\n", (unsigned)size); + OutputDebugStringA(buf); + } + return 0; + case CURLINFO_DATA_OUT: + if (g_verbose_ssl) { + snprintf(buf, sizeof(buf), "[DATA OUT] %u bytes sent\n", (unsigned)size); + OutputDebugStringA(buf); + } + return 0; + case CURLINFO_SSL_DATA_IN: + snprintf(buf, sizeof(buf), "[SSL IN] %u bytes\n", (unsigned)size); + OutputDebugStringA(buf); + /* Print first few bytes as hex for debugging */ + if (size > 0 && g_verbose_ssl) { + char hex[128]; + int hex_len = 0; + for (i = 0; i < size && i < 32 && hex_len < 120; i++) { + hex_len += snprintf(hex + hex_len, sizeof(hex) - hex_len, "%02X ", (unsigned char)data[i]); + } + snprintf(buf, sizeof(buf), " HEX: %s%s\n", hex, size > 32 ? "..." : ""); + OutputDebugStringA(buf); + } + return 0; + case CURLINFO_SSL_DATA_OUT: + snprintf(buf, sizeof(buf), "[SSL OUT] %u bytes\n", (unsigned)size); + OutputDebugStringA(buf); + /* Print first few bytes as hex for debugging */ + if (size > 0 && g_verbose_ssl) { + char hex[128]; + int hex_len = 0; + for (i = 0; i < size && i < 32 && hex_len < 120; i++) { + hex_len += snprintf(hex + hex_len, sizeof(hex) - hex_len, "%02X ", (unsigned char)data[i]); + } + snprintf(buf, sizeof(buf), " HEX: %s%s\n", hex, size > 32 ? "..." : ""); + OutputDebugStringA(buf); + } + return 0; + default: + return 0; + } + + /* Print text/header info - handle multiple lines */ + print_size = size; + if (print_size > 400) print_size = 400; + + /* For HEADER_OUT, log the full request so we can see all headers */ + if (type == CURLINFO_HEADER_OUT) { + char header_log[512]; + snprintf(header_log, sizeof(header_log), "\n=== HTTP REQUEST (%u bytes) ===\n", (unsigned)size); + OutputDebugStringA(header_log); + } + + /* Process each line */ + { + size_t pos = 0; + while (pos < print_size) { + /* Copy one line */ + i = 0; + while (pos < print_size && i < sizeof(buf) - 2) { + char c = data[pos++]; + if (c == '\r') continue; /* Skip CR */ + if (c == '\n') break; /* End of line */ + buf[i++] = c; + } + buf[i] = '\0'; + + if (buf[0] != '\0') { + char out[550]; + snprintf(out, sizeof(out), "%s%s\n", prefix, buf); + OutputDebugStringA(out); + + /* Also show important SSL info on console */ + if (type == CURLINFO_TEXT && g_verbose_ssl) { + /* Check for SSL-related messages */ + if (strstr(buf, "SSL") || strstr(buf, "TLS") || + strstr(buf, "ssl") || strstr(buf, "tls") || + strstr(buf, "certificate") || strstr(buf, "handshake") || + strstr(buf, "cipher") || strstr(buf, "error") || + strstr(buf, "Error") || strstr(buf, "fail")) { + xbox_console_set_colors(CONSOLE_COLOR_MAGENTA, CONSOLE_COLOR_BLACK); + xbox_console_printf(" DBG: %s\n", buf); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_present(); + } + } + } + } + } + + if (type == CURLINFO_HEADER_OUT) { + OutputDebugStringA("=== END HTTP REQUEST ===\n"); + } + + return 0; +} + +/* + * Helper to configure verbose debugging on a curl handle + */ +static void setup_verbose_curl(CURL *curl) +{ + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_curl_debug_callback); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, NULL); +} + +/* + * Display functions + */ +static void display_logo(void) +{ + int i; + + xbox_console_set_colors(CONSOLE_COLOR_CYAN, CONSOLE_COLOR_BLACK); + for (i = 0; curl_logo[i] != NULL; i++) { + xbox_console_println(curl_logo[i]); + } + xbox_console_println(""); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); +} + +static void display_header(const char *title) +{ + xbox_console_println(""); + xbox_console_set_colors(CONSOLE_COLOR_YELLOW, CONSOLE_COLOR_BLACK); + xbox_console_printf(" %s\n", title); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_println(""); + xbox_console_present(); +} + +static void display_test_start(const char *test_name) +{ + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_printf("[ .... ] %s", test_name); + xbox_console_present(); + OutputDebugStringA("Testing: "); + OutputDebugStringA(test_name); + OutputDebugStringA("\n"); +} + +static void display_test_result(int passed, const char *details) +{ + int x, y; + + /* Move cursor back to result position */ + xbox_console_get_cursor(&x, &y); + xbox_console_set_cursor(0, y); + + if (passed) { + xbox_console_set_colors(CONSOLE_COLOR_GREEN, CONSOLE_COLOR_BLACK); + xbox_console_print("[ PASS ]"); + tests_passed++; + } else { + xbox_console_set_colors(CONSOLE_COLOR_RED, CONSOLE_COLOR_BLACK); + xbox_console_print("[ FAIL ]"); + tests_failed++; + } + + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_set_cursor(x, y); + xbox_console_println(""); + + if (details && details[0]) { + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_printf(" %s\n", details); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + } + + xbox_console_present(); +} + +static void display_test_skip(const char *reason) +{ + int x, y; + + xbox_console_get_cursor(&x, &y); + xbox_console_set_cursor(0, y); + + xbox_console_set_colors(CONSOLE_COLOR_YELLOW, CONSOLE_COLOR_BLACK); + xbox_console_print("[ SKIP ]"); + tests_skipped++; + + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_set_cursor(x, y); + xbox_console_println(""); + + if (reason && reason[0]) { + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_printf(" %s\n", reason); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + } + + xbox_console_present(); +} + +static void display_section(const char *section_name) +{ + xbox_console_println(""); + xbox_console_set_colors(CONSOLE_COLOR_CYAN, CONSOLE_COLOR_BLACK); + xbox_console_printf(" %s\n", section_name); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_present(); +} + +static void display_summary(void) +{ + xbox_console_println(""); + xbox_console_set_colors(CONSOLE_COLOR_YELLOW, CONSOLE_COLOR_BLACK); + xbox_console_println(" TEST RESULTS SUMMARY"); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + + xbox_console_set_colors(CONSOLE_COLOR_GREEN, CONSOLE_COLOR_BLACK); + xbox_console_printf(" Passed: %d\n", tests_passed); + + xbox_console_set_colors(CONSOLE_COLOR_RED, CONSOLE_COLOR_BLACK); + xbox_console_printf(" Failed: %d\n", tests_failed); + + xbox_console_set_colors(CONSOLE_COLOR_YELLOW, CONSOLE_COLOR_BLACK); + xbox_console_printf(" Skipped: %d\n", tests_skipped); + + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_printf(" Total: %d\n", tests_passed + tests_failed + tests_skipped); + + xbox_console_println(""); + if (tests_failed == 0) { + xbox_console_set_colors(CONSOLE_COLOR_GREEN, CONSOLE_COLOR_BLACK); + xbox_console_println(" ALL TESTS PASSED!"); + } else { + xbox_console_set_colors(CONSOLE_COLOR_RED, CONSOLE_COLOR_BLACK); + xbox_console_println(" SOME TESTS FAILED"); + } + + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_present(); +} + +/* + * Network initialization + */ +static int wait_for_network(void) +{ + XNetStartupParams xnsp; + WSADATA wsaData; + XNADDR xnaddr; + int timeout = 30; + + xbox_console_println("Initializing network..."); + xbox_console_present(); + + /* Initialize XNet */ + memset(&xnsp, 0, sizeof(xnsp)); + xnsp.cfgSizeOfStruct = sizeof(XNetStartupParams); + xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY; + xnsp.cfgPrivatePoolSizeInPages = 64; + xnsp.cfgEnetReceiveQueueLength = 16; + xnsp.cfgIpFragMaxSimultaneous = 16; + xnsp.cfgIpFragMaxPacketDiv256 = 32; + xnsp.cfgSockMaxSockets = 64; + xnsp.cfgSockDefaultRecvBufsizeInK = 64; + xnsp.cfgSockDefaultSendBufsizeInK = 64; + + XNetStartup(&xnsp); + WSAStartup(MAKEWORD(2, 2), &wsaData); + + /* Wait for ethernet link */ + xbox_console_print(" Waiting for ethernet link..."); + xbox_console_present(); + while (XNetGetEthernetLinkStatus() == 0) { + Sleep(100); + } + xbox_console_set_colors(CONSOLE_COLOR_GREEN, CONSOLE_COLOR_BLACK); + xbox_console_println(" OK"); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + + /* Wait for DHCP */ + xbox_console_print(" Waiting for DHCP..."); + xbox_console_present(); + while (timeout > 0) { + memset(&xnaddr, 0, sizeof(xnaddr)); + if (XNetGetTitleXnAddr(&xnaddr) != XNET_GET_XNADDR_PENDING) { + break; + } + Sleep(1000); + timeout--; + } + + if (timeout <= 0) { + xbox_console_set_colors(CONSOLE_COLOR_RED, CONSOLE_COLOR_BLACK); + xbox_console_println(" TIMEOUT"); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + return 0; + } + + xbox_console_set_colors(CONSOLE_COLOR_GREEN, CONSOLE_COLOR_BLACK); + xbox_console_println(" OK"); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + + /* Display IP address */ + xbox_console_printf(" IP Address: %d.%d.%d.%d\n", + xnaddr.ina.S_un.S_un_b.s_b1, + xnaddr.ina.S_un.S_un_b.s_b2, + xnaddr.ina.S_un.S_un_b.s_b3, + xnaddr.ina.S_un.S_un_b.s_b4); + + xbox_console_println(""); + xbox_console_present(); + return 1; +} + +/* + * Individual Tests + */ + +/* Test 1: Version Information - VERBOSE */ +static void test_version_info(void) +{ + const char *version; + curl_version_info_data *vinfo; + char details[256]; + char log[512]; + + display_test_start("libcurl version information"); + + version = curl_version(); + vinfo = curl_version_info(CURLVERSION_NOW); + + if (version && vinfo && vinfo->version) { + /* Log extensive version info */ + snprintf(log, sizeof(log), + "\n======= CURL VERSION INFO =======\n" + " Version string: %s\n" + " curl version: %s\n" + " SSL version: %s\n" + " Features: 0x%08lx\n" + " Host: %s\n" + "================================\n", + version, + vinfo->version, + vinfo->ssl_version ? vinfo->ssl_version : "NONE (no SSL!)", + (unsigned long)vinfo->features, + vinfo->host ? vinfo->host : "unknown"); + OutputDebugStringA(log); + + /* Check for SSL support */ + if (vinfo->features & CURL_VERSION_SSL) { + OutputDebugStringA(" [OK] SSL support is enabled\n"); + } else { + OutputDebugStringA(" [WARNING] SSL support is NOT enabled!\n"); + } + + /* Show on console too */ + xbox_console_set_colors(CONSOLE_COLOR_CYAN, CONSOLE_COLOR_BLACK); + xbox_console_printf(" curl: %s\n", vinfo->version); + xbox_console_printf(" SSL: %s\n", vinfo->ssl_version ? vinfo->ssl_version : "NONE!"); + + if (!(vinfo->features & CURL_VERSION_SSL)) { + xbox_console_set_colors(CONSOLE_COLOR_RED, CONSOLE_COLOR_BLACK); + xbox_console_println(" WARNING: No SSL support compiled in!"); + } + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_present(); + + snprintf(details, sizeof(details), "curl %s, SSL: %s", + vinfo->version, + vinfo->ssl_version ? vinfo->ssl_version : "NONE"); + display_test_result(vinfo->ssl_version != NULL, details); + } else { + display_test_result(0, "Failed to get version info"); + } +} + +/* Test 2: HTTP GET (by IP - no DNS) */ +static void test_http_get_by_ip(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[128]; + + display_test_start("HTTP GET (direct IP, no DNS)"); + OutputDebugStringA("DEBUG: Starting HTTP test\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + OutputDebugStringA("DEBUG: curl_easy_init done\n"); + + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + OutputDebugStringA("DEBUG: Setting options\n"); + curl_easy_setopt(curl, CURLOPT_URL, "http://1.1.1.1/"); /* Cloudflare - reliable */ + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); + OutputDebugStringA("DEBUG: Options set, calling curl_easy_perform\n"); + + res = curl_easy_perform(curl); + OutputDebugStringA("DEBUG: curl_easy_perform returned\n"); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && response_code >= 200 && response_code < 400) { + snprintf(details, sizeof(details) - 1, "HTTP %ld, %u bytes received", response_code, (unsigned)total_bytes_received); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); + } else { + snprintf(details, sizeof(details) - 1, "Error: %s (HTTP %ld)", curl_easy_strerror(res), response_code); + details[sizeof(details) - 1] = '\0'; + display_test_result(0, details); + } +} + +/* Test 3: HTTP GET with DNS */ +static void test_http_get_dns(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[128]; + + display_test_start("HTTP GET (with DNS resolution)"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/get"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details) - 1, "HTTP %ld, %u bytes received", response_code, (unsigned)total_bytes_received); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); + } else { + snprintf(details, sizeof(details) - 1, "Error: %s (HTTP %ld)", curl_easy_strerror(res), response_code); + details[sizeof(details) - 1] = '\0'; + display_test_result(0, details); + } +} + +/* Test 4: HTTPS GET (certificate verification disabled) - VERBOSE */ +static void test_https_get_no_verify(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + char *effective_url = NULL; + long ssl_verify_result = 0; + DWORD start_time, elapsed; + + display_test_start("HTTPS GET (verify disabled)"); + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Starting HTTPS connection test..."); + xbox_console_present(); + + OutputDebugStringA("\n========== HTTPS TEST (NO VERIFY) START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + /* Setup verbose debugging */ + setup_verbose_curl(curl); + + OutputDebugStringA("Setting HTTPS options...\n"); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); /* Longer timeout for SSL handshake */ + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + /* Try to get more SSL debugging info */ + curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); + + xbox_console_println(" Performing SSL handshake..."); + xbox_console_present(); + OutputDebugStringA("Calling curl_easy_perform for HTTPS...\n"); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + OutputDebugStringA("curl_easy_perform returned.\n"); + + /* Get detailed info */ + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url); + curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, &ssl_verify_result); + + /* Log everything */ + { + char log[512]; + snprintf(log, sizeof(log), + "HTTPS Result:\n" + " CURLcode: %d (%s)\n" + " HTTP Code: %ld\n" + " SSL Verify: %ld\n" + " Bytes: %u\n" + " Time: %lu ms\n" + " URL: %s\n", + res, curl_easy_strerror(res), + response_code, + ssl_verify_result, + (unsigned)total_bytes_received, + elapsed, + effective_url ? effective_url : "NULL"); + OutputDebugStringA(log); + } + + curl_easy_cleanup(curl); + OutputDebugStringA("========== HTTPS TEST (NO VERIFY) END ==========\n\n"); + + /* Show result on console */ + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "HTTPS %ld, %u bytes in %lu ms", response_code, (unsigned)total_bytes_received, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld, %lu ms)", res, curl_easy_strerror(res), response_code, elapsed); + display_test_result(0, details); + + /* Show error details on console */ + xbox_console_set_colors(CONSOLE_COLOR_RED, CONSOLE_COLOR_BLACK); + xbox_console_printf(" SSL verify result: %ld\n", ssl_verify_result); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_present(); + } +} + +/* Test 5: HTTPS GET (certificate verification enabled) - VERBOSE */ +static void test_https_get_with_verify(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + long ssl_verify_result = 0; + DWORD start_time, elapsed; + + display_test_start("HTTPS GET (verify enabled)"); + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Testing certificate verification..."); + xbox_console_present(); + + OutputDebugStringA("\n========== HTTPS TEST (WITH VERIFY) START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + /* Setup verbose debugging */ + setup_verbose_curl(curl); + + OutputDebugStringA("Setting HTTPS options with verification...\n"); + curl_easy_setopt(curl, CURLOPT_URL, "https://www.google.com/"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); + curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); + + xbox_console_println(" Performing verified SSL handshake..."); + xbox_console_present(); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, &ssl_verify_result); + + /* Log everything */ + { + char log[512]; + snprintf(log, sizeof(log), + "HTTPS (Verify) Result:\n" + " CURLcode: %d (%s)\n" + " HTTP Code: %ld\n" + " SSL Verify: %ld\n" + " Bytes: %u\n" + " Time: %lu ms\n", + res, curl_easy_strerror(res), + response_code, + ssl_verify_result, + (unsigned)total_bytes_received, + elapsed); + OutputDebugStringA(log); + } + + curl_easy_cleanup(curl); + OutputDebugStringA("========== HTTPS TEST (WITH VERIFY) END ==========\n\n"); + + if (res == CURLE_OK && response_code >= 200 && response_code < 400) { + snprintf(details, sizeof(details), "HTTPS %ld, cert verified, %lu ms", response_code, elapsed); + display_test_result(1, details); + } else if (res == CURLE_SSL_CACERT || res == CURLE_PEER_FAILED_VERIFICATION) { + snprintf(details, sizeof(details), "Cert verify failed (SSL result: %ld)", ssl_verify_result); + display_test_skip(details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (%lu ms)", res, curl_easy_strerror(res), elapsed); + display_test_result(0, details); + } +} + +/* Test 5-pre: BearSSL Engine Diagnostics */ +static void test_bearssl_diagnostics(void) +{ + br_ssl_client_context sc; + br_x509_minimal_context xc; + char details[256]; + + display_test_start("BearSSL engine initialization"); + + OutputDebugStringA("\n========== BEARSSL DIAGNOSTICS ==========\n"); + + /* Try to initialize BearSSL client context with no trust anchors (for testing) */ + OutputDebugStringA("Initializing br_ssl_client_init_full with NULL trust anchors...\n"); + br_ssl_client_init_full(&sc, &xc, NULL, 0); + + /* Check engine state */ + { + unsigned state = br_ssl_engine_current_state(&sc.eng); + int err = br_ssl_engine_last_error(&sc.eng); + char log[256]; + + snprintf(log, sizeof(log), + "BearSSL state after init:\n" + " State flags: 0x%08x\n" + " Last error: %d\n" + " CLOSED=%d SENDREC=%d RECVREC=%d SENDAPP=%d RECVAPP=%d\n", + state, err, + (state & BR_SSL_CLOSED) ? 1 : 0, + (state & BR_SSL_SENDREC) ? 1 : 0, + (state & BR_SSL_RECVREC) ? 1 : 0, + (state & BR_SSL_SENDAPP) ? 1 : 0, + (state & BR_SSL_RECVAPP) ? 1 : 0); + OutputDebugStringA(log); + + xbox_console_set_colors(CONSOLE_COLOR_CYAN, CONSOLE_COLOR_BLACK); + xbox_console_printf(" BearSSL state: 0x%08x, err: %d\n", state, err); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_present(); + + if (err == BR_ERR_OK) { + snprintf(details, sizeof(details), "Init OK, state=0x%x", state); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Init error: %d", err); + display_test_result(0, details); + } + } + + OutputDebugStringA("========== BEARSSL DIAGNOSTICS END ==========\n\n"); +} + +/* Test 5a: HTTPS to httpbin.org (lenient test server) */ +static void test_https_by_ip(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + + display_test_start("HTTPS to httpbin.org"); + + OutputDebugStringA("\n========== HTTPS HTTPBIN TEST START ==========\n"); + OutputDebugStringA("Testing HTTPS to httpbin.org/get - lenient HTTP/1.1 test server\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + setup_verbose_curl(curl); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Connecting to httpbin.org:443..."); + xbox_console_present(); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== HTTPS HTTPBIN TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code >= 200 && response_code < 400) { + snprintf(details, sizeof(details), "HTTPS %ld, %u bytes, %lu ms", response_code, (unsigned)total_bytes_received, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (%lu ms)", res, curl_easy_strerror(res), elapsed); + display_test_result(0, details); + } +} + +/* Test 5b: HTTPS with explicit TLS options */ +static void test_https_tls_options(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + const char *ssl_version_str = "unknown"; + long ssl_version = 0; + + display_test_start("HTTPS TLS version test"); + + OutputDebugStringA("\n========== HTTPS TLS VERSION TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + setup_verbose_curl(curl); + + /* Try to force TLS 1.2 */ + curl_easy_setopt(curl, CURLOPT_URL, "https://www.howsmyssl.com/a/check"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Testing TLS 1.2 connection..."); + xbox_console_present(); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + +#ifdef CURLINFO_SSL_VERSION + if (curl_easy_getinfo(curl, CURLINFO_SSL_VERSION, &ssl_version) == CURLE_OK) { + switch (ssl_version) { + case CURL_SSLVERSION_TLSv1_0: ssl_version_str = "TLS 1.0"; break; + case CURL_SSLVERSION_TLSv1_1: ssl_version_str = "TLS 1.1"; break; + case CURL_SSLVERSION_TLSv1_2: ssl_version_str = "TLS 1.2"; break; + case CURL_SSLVERSION_TLSv1_3: ssl_version_str = "TLS 1.3"; break; + default: ssl_version_str = "unknown"; break; + } + } +#endif + + { + char log[256]; + snprintf(log, sizeof(log), "TLS test: code=%d, HTTP=%ld, SSL version=%s, time=%lu ms\n", + res, response_code, ssl_version_str, elapsed); + OutputDebugStringA(log); + } + + curl_easy_cleanup(curl); + OutputDebugStringA("========== HTTPS TLS VERSION TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "TLS OK, %s, %lu ms", ssl_version_str, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (%lu ms)", res, curl_easy_strerror(res), elapsed); + display_test_result(0, details); + } +} + +/* Test 5c: Simple HTTPS to a minimal endpoint */ +static void test_https_simple(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + + display_test_start("HTTPS simple (example.com)"); + + OutputDebugStringA("\n========== HTTPS SIMPLE TEST START ==========\n"); + OutputDebugStringA("Testing HTTPS to example.com - minimal, reliable endpoint\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + setup_verbose_curl(curl); + + curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Connecting to example.com:443..."); + xbox_console_present(); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== HTTPS SIMPLE TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code >= 200 && response_code < 400) { + snprintf(details, sizeof(details), "HTTPS %ld, %u bytes, %lu ms", response_code, (unsigned)total_bytes_received, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (%lu ms)", res, curl_easy_strerror(res), elapsed); + display_test_result(0, details); + } +} + +/* Test 5d: Raw TCP connection test to port 443 using XNet DNS */ +/* Pattern based on Microsoft Xbox source: dnslookup.c and logon.cpp */ +static void test_tcp_port_443(void) +{ + SOCKET sock = INVALID_SOCKET; + struct sockaddr_in server; + XNDNS *pxndns = NULL; + HANDLE hEvent = NULL; + DWORD start_time, elapsed; + char details[256]; + int result; + INT dns_status; + + display_test_start("TCP connect to port 443"); + + OutputDebugStringA("\n========== TCP PORT 443 TEST START ==========\n"); + + /* Create event for async DNS completion (Xbox pattern) */ + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (hEvent == NULL) { + snprintf(details, sizeof(details), "CreateEvent failed: %d", GetLastError()); + display_test_result(0, details); + return; + } + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Resolving example.com via XNet..."); + xbox_console_present(); + + /* Use Xbox DNS lookup with event notification */ + dns_status = XNetDnsLookup("example.com", hEvent, &pxndns); + if (dns_status != 0) { + snprintf(details, sizeof(details), "XNetDnsLookup failed: %d", dns_status); + OutputDebugStringA(details); + OutputDebugStringA("\n"); + CloseHandle(hEvent); + display_test_result(0, details); + return; + } + + /* Wait for DNS to complete with 10 second timeout (Xbox pattern) */ + OutputDebugStringA("Waiting for DNS lookup to complete...\n"); + if (WaitForSingleObject(hEvent, 10000) == WAIT_TIMEOUT) { + OutputDebugStringA("DNS lookup timed out\n"); + XNetDnsRelease(pxndns); + CloseHandle(hEvent); + display_test_result(0, "DNS lookup timed out"); + return; + } + + /* Check DNS result status */ + { + char log[128]; + snprintf(log, sizeof(log), "DNS iStatus=%d, cina=%d\n", pxndns->iStatus, pxndns->cina); + OutputDebugStringA(log); + } + + if (pxndns->iStatus != 0) { + snprintf(details, sizeof(details), "DNS failed: status=%d (WSAHOST_NOT_FOUND=%d)", + pxndns->iStatus, WSAHOST_NOT_FOUND); + OutputDebugStringA(details); + OutputDebugStringA("\n"); + XNetDnsRelease(pxndns); + CloseHandle(hEvent); + display_test_result(0, details); + return; + } + + if (pxndns->cina == 0) { + XNetDnsRelease(pxndns); + CloseHandle(hEvent); + display_test_result(0, "DNS returned no addresses"); + return; + } + + { + char log[128]; + snprintf(log, sizeof(log), "Resolved to: %d.%d.%d.%d\n", + pxndns->aina[0].S_un.S_un_b.s_b1, + pxndns->aina[0].S_un.S_un_b.s_b2, + pxndns->aina[0].S_un.S_un_b.s_b3, + pxndns->aina[0].S_un.S_un_b.s_b4); + OutputDebugStringA(log); + + xbox_console_printf(" IP: %d.%d.%d.%d\n", + pxndns->aina[0].S_un.S_un_b.s_b1, + pxndns->aina[0].S_un.S_un_b.s_b2, + pxndns->aina[0].S_un.S_un_b.s_b3, + pxndns->aina[0].S_un.S_un_b.s_b4); + xbox_console_present(); + } + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == INVALID_SOCKET) { + snprintf(details, sizeof(details), "socket() failed: %d", WSAGetLastError()); + XNetDnsRelease(pxndns); + CloseHandle(hEvent); + display_test_result(0, details); + return; + } + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons(443); + server.sin_addr = pxndns->aina[0]; + + /* Release DNS resources before connect (Xbox pattern) */ + XNetDnsRelease(pxndns); + pxndns = NULL; + + xbox_console_println(" Connecting to port 443..."); + xbox_console_present(); + + start_time = GetTickCount(); + result = connect(sock, (struct sockaddr *)&server, sizeof(server)); + elapsed = GetTickCount() - start_time; + + if (result == 0) { + snprintf(details, sizeof(details), "Connected in %lu ms", elapsed); + OutputDebugStringA("TCP connect to port 443 succeeded\n"); + display_test_result(1, details); + } else { + int err = WSAGetLastError(); + snprintf(details, sizeof(details), "Connect failed: WSA error %d (%lu ms)", err, elapsed); + OutputDebugStringA(details); + OutputDebugStringA("\n"); + display_test_result(0, details); + } + + /* Cleanup (Xbox pattern: always close socket properly) */ + closesocket(sock); + CloseHandle(hEvent); + OutputDebugStringA("========== TCP PORT 443 TEST END ==========\n\n"); +} + +/* Test 6: HTTP POST */ +static void test_http_post(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[128]; + const char *post_data = "name=XboxCurl&version=1.0&platform=Xbox"; + + display_test_start("HTTP POST request"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details) - 1, "HTTP %ld, POST data sent successfully", response_code); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); + } else { + snprintf(details, sizeof(details) - 1, "Error: %s (HTTP %ld)", curl_easy_strerror(res), response_code); + details[sizeof(details) - 1] = '\0'; + display_test_result(0, details); + } +} + +/* Test 7: Custom Headers */ +static void test_custom_headers(void) +{ + CURL *curl; + CURLcode res; + struct curl_slist *headers = NULL; + long response_code = 0; + char details[128]; + + display_test_start("Custom HTTP headers"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + headers = curl_slist_append(headers, "X-Custom-Header: XboxCurlTest"); + headers = curl_slist_append(headers, "User-Agent: XboxCurl/1.0 (Xbox)"); + headers = curl_slist_append(headers, "Accept: application/json"); + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/headers"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details) - 1, "HTTP %ld, custom headers sent", response_code); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); + } else { + snprintf(details, sizeof(details) - 1, "Error: %s (HTTP %ld)", curl_easy_strerror(res), response_code); + details[sizeof(details) - 1] = '\0'; + display_test_result(0, details); + } +} + +/* Test 8: HTTP Redirects */ +static void test_http_redirects(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + long redirect_count = 0; + char details[128]; + + display_test_start("HTTP redirect following"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/redirect/2"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redirect_count); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && response_code == 200 && redirect_count >= 2) { + snprintf(details, sizeof(details) - 1, "HTTP %ld after %ld redirects", response_code, redirect_count); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); + } else { + snprintf(details, sizeof(details) - 1, "Error: %s (HTTP %ld, %ld redirects)", + curl_easy_strerror(res), response_code, redirect_count); + details[sizeof(details) - 1] = '\0'; + display_test_result(0, details); + } +} + +/* Test 9: Connection Timeout */ +static void test_connection_timeout(void) +{ + CURL *curl; + CURLcode res; + char details[128]; + DWORD start_time, elapsed; + + display_test_start("Connection timeout handling"); + + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + /* Use a non-routable IP to trigger timeout */ + curl_easy_setopt(curl, CURLOPT_URL, "http://10.255.255.1/"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L); /* 3 second timeout */ + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_cleanup(curl); + + /* We expect a timeout error */ + if (res == CURLE_OPERATION_TIMEDOUT || res == CURLE_COULDNT_CONNECT) { + snprintf(details, sizeof(details) - 1, "Timeout after %lu ms (expected)", elapsed); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); + } else if (res == CURLE_OK) { + display_test_result(0, "Should have timed out but didn't"); + } else { + snprintf(details, sizeof(details) - 1, "Error: %s (%lu ms)", curl_easy_strerror(res), elapsed); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); /* Other errors also acceptable */ + } +} + +/* Test 10: Large File Download */ +static void test_large_download(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + double download_size = 0; + char details[128]; + + display_test_start("Large file download (chunked)"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + /* Request a larger response */ + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/bytes/10000"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &download_size); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && response_code == 200 && total_bytes_received >= 10000) { + snprintf(details, sizeof(details) - 1, "HTTP %ld, %u bytes downloaded", response_code, (unsigned)total_bytes_received); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); + } else { + snprintf(details, sizeof(details) - 1, "Error: %s (%u bytes)", curl_easy_strerror(res), (unsigned)total_bytes_received); + details[sizeof(details) - 1] = '\0'; + display_test_result(0, details); + } +} + +/* Test 11: HTTPS POST - VERBOSE */ +static void test_https_post(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + const char *post_data = "{\"test\":\"XboxCurl\",\"secure\":true}"; + struct curl_slist *headers = NULL; + DWORD start_time, elapsed; + + display_test_start("HTTPS POST with JSON"); + + OutputDebugStringA("\n========== HTTPS POST TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + /* Setup verbose debugging */ + setup_verbose_curl(curl); + + headers = curl_slist_append(headers, "Content-Type: application/json"); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Performing HTTPS POST..."); + xbox_console_present(); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + { + char log[256]; + snprintf(log, sizeof(log), "HTTPS POST: code=%d (%s), HTTP=%ld, time=%lu ms\n", + res, curl_easy_strerror(res), response_code, elapsed); + OutputDebugStringA(log); + } + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== HTTPS POST TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "HTTPS %ld, JSON POST OK, %lu ms", response_code, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* Test 12: User-Agent String */ +static void test_user_agent(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[128]; + + display_test_start("Custom User-Agent string"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/user-agent"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "XboxCurl/1.0 (Xbox; BearSSL)"); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details) - 1, "HTTP %ld, User-Agent sent", response_code); + details[sizeof(details) - 1] = '\0'; + display_test_result(1, details); + } else { + snprintf(details, sizeof(details) - 1, "Error: %s (HTTP %ld)", curl_easy_strerror(res), response_code); + details[sizeof(details) - 1] = '\0'; + display_test_result(0, details); + } +} + +/* + * ============================================================================ + * Session Resumption Tests + * ============================================================================ + * These tests verify that TLS session caching and resumption works correctly. + * Session resumption allows subsequent connections to skip the full TLS + * handshake, significantly reducing connection time. + */ + +/* Test: Session Resumption Basic - Verify cache hit on second connection */ +static void test_session_resumption_basic(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + int cache_count_before, cache_count_after; + const char *test_host = "https://httpbin.org/get"; + + display_test_start("Session resumption (basic)"); + + OutputDebugStringA("\n========== SESSION RESUMPTION BASIC TEST ==========\n"); + + /* Clear session cache to start fresh */ + session_cache::clear(); + cache_count_before = session_cache::get_count(); + + OutputDebugStringA("Session cache cleared, starting fresh\n"); + + /* First connection - should be a full handshake */ + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, test_host); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + OutputDebugStringA("First connection (full handshake expected)...\n"); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + if (res != CURLE_OK || response_code != 200) { + snprintf(details, sizeof(details), "First connection failed: %s (HTTP %ld)", + curl_easy_strerror(res), response_code); + display_test_result(0, details); + return; + } + + /* Check that session was cached */ + cache_count_after = session_cache::get_count(); + { + char log[128]; + snprintf(log, sizeof(log), "Cache count: before=%d, after=%d\n", + cache_count_before, cache_count_after); + OutputDebugStringA(log); + } + + if (cache_count_after <= cache_count_before) { + display_test_result(0, "Session not cached after first connection"); + return; + } + + /* Second connection - should attempt session resumption */ + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed (2nd)"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, test_host); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + OutputDebugStringA("Second connection (session resumption expected)...\n"); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== SESSION RESUMPTION BASIC TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "OK, cache entries: %d", cache_count_after); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Second connection failed: %s", curl_easy_strerror(res)); + display_test_result(0, details); + } +} + +/* Test: Session Resumption Timing - Benchmark first vs resumed handshake */ +static void test_session_resumption_timing(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD time_first, time_resumed; + DWORD start_time; + const char *test_host = "https://httpbin.org/get"; + + display_test_start("Session resumption (timing)"); + + OutputDebugStringA("\n========== SESSION RESUMPTION TIMING TEST ==========\n"); + + /* Clear cache for clean timing measurement */ + session_cache::clear(); + + /* First connection - measure full handshake time */ + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, test_host); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + OutputDebugStringA("First connection timing...\n"); + start_time = GetTickCount(); + res = curl_easy_perform(curl); + time_first = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + if (res != CURLE_OK) { + snprintf(details, sizeof(details), "First connection failed: %s", curl_easy_strerror(res)); + display_test_result(0, details); + return; + } + + { + char log[128]; + snprintf(log, sizeof(log), "First connection: %lu ms\n", time_first); + OutputDebugStringA(log); + } + + /* Second connection - measure resumed handshake time */ + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed (2nd)"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, test_host); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + OutputDebugStringA("Second connection timing (resumed)...\n"); + start_time = GetTickCount(); + res = curl_easy_perform(curl); + time_resumed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + { + char log[256]; + int speedup_pct = 0; + if (time_first > 0) { + speedup_pct = (int)(((time_first - time_resumed) * 100) / time_first); + } + snprintf(log, sizeof(log), + "Session Resumption Timing Results:\n" + " First connection: %lu ms (full handshake)\n" + " Second connection: %lu ms (resumed)\n" + " Speedup: %d%%\n", + time_first, time_resumed, speedup_pct); + OutputDebugStringA(log); + } + + OutputDebugStringA("========== SESSION RESUMPTION TIMING TEST END ==========\n\n"); + + if (res == CURLE_OK) { + int speedup_pct = 0; + if (time_first > 0) { + speedup_pct = (int)(((time_first - time_resumed) * 100) / time_first); + } + snprintf(details, sizeof(details), "1st: %lu ms, 2nd: %lu ms (%d%% speedup)", + time_first, time_resumed, speedup_pct); + /* Pass if second connection succeeded (speedup is informational) */ + display_test_result(1, details); + + /* Show timing info on console */ + xbox_console_set_colors(CONSOLE_COLOR_CYAN, CONSOLE_COLOR_BLACK); + xbox_console_printf(" 1st: %lu ms, 2nd: %lu ms\n", time_first, time_resumed); + xbox_console_set_colors(CONSOLE_COLOR_WHITE, CONSOLE_COLOR_BLACK); + xbox_console_present(); + } else { + snprintf(details, sizeof(details), "Resumed connection failed: %s", curl_easy_strerror(res)); + display_test_result(0, details); + } +} + +/* Test: Session Cache Operations - Test cache management functions */ +static void test_session_cache_operations(void) +{ + char details[256]; + int count; + + display_test_start("Session cache operations"); + + OutputDebugStringA("\n========== SESSION CACHE OPERATIONS TEST ==========\n"); + + /* Initialize if not already */ + session_cache::initialize(); + + /* Test clear operation */ + session_cache::clear(); + count = session_cache::get_count(); + if (count != 0) { + snprintf(details, sizeof(details), "Clear failed, count=%d", count); + display_test_result(0, details); + return; + } + OutputDebugStringA("session_cache::clear() - OK\n"); + + /* Test store and count */ + { + br_ssl_session_parameters params; + memset(¶ms, 0, sizeof(params)); + params.session_id_len = 32; /* Set a valid session ID length */ + memset(params.session_id, 0xAB, 32); /* Fill with test data */ + + session_cache::store("test1.example.com", ¶ms); + count = session_cache::get_count(); + if (count != 1) { + snprintf(details, sizeof(details), "Store failed, count=%d (expected 1)", count); + display_test_result(0, details); + return; + } + OutputDebugStringA("session_cache::store() - OK (count=1)\n"); + + /* Store another */ + session_cache::store("test2.example.com", ¶ms); + count = session_cache::get_count(); + if (count != 2) { + snprintf(details, sizeof(details), "Store 2nd failed, count=%d (expected 2)", count); + display_test_result(0, details); + return; + } + OutputDebugStringA("session_cache::store() 2nd - OK (count=2)\n"); + } + + /* Test get operation */ + { + br_ssl_session_parameters retrieved; + memset(&retrieved, 0, sizeof(retrieved)); + + if (!session_cache::get("test1.example.com", &retrieved)) { + display_test_result(0, "Get failed for existing entry"); + return; + } + if (retrieved.session_id_len != 32 || retrieved.session_id[0] != 0xAB) { + display_test_result(0, "Retrieved data doesn't match stored data"); + return; + } + OutputDebugStringA("session_cache::get() - OK\n"); + } + + /* Test remove operation */ + session_cache::remove("test1.example.com"); + count = session_cache::get_count(); + if (count != 1) { + snprintf(details, sizeof(details), "Remove failed, count=%d (expected 1)", count); + display_test_result(0, details); + return; + } + OutputDebugStringA("session_cache::remove() - OK (count=1)\n"); + + /* Final cleanup */ + session_cache::clear(); + + OutputDebugStringA("========== SESSION CACHE OPERATIONS TEST END ==========\n\n"); + + snprintf(details, sizeof(details), "All cache operations passed"); + display_test_result(1, details); +} + +/* + * ============================================================================ + * Certificate Pinning Tests + * ============================================================================ + * These tests verify the certificate pinning infrastructure. + * Note: Full pin verification requires a custom X.509 callback which is not + * yet implemented. These tests verify the API works correctly. + */ + +/* Test: Certificate Pinning API - Test add/remove/has_pin/clear */ +static void test_cert_pinning_api(void) +{ + char details[256]; + unsigned char test_hash[32]; + + display_test_start("Certificate pinning API"); + + OutputDebugStringA("\n========== CERT PINNING API TEST ==========\n"); + + /* Initialize */ + cert_pinning::initialize(); + cert_pinning::clear(); + + /* Create a test hash */ + memset(test_hash, 0x42, 32); + + /* Test add_pin */ + if (!cert_pinning::add_pin("pintest.example.com", test_hash)) { + display_test_result(0, "add_pin failed"); + return; + } + OutputDebugStringA("cert_pinning::add_pin() - OK\n"); + + /* Test has_pin - should return true */ + if (!cert_pinning::has_pin("pintest.example.com")) { + display_test_result(0, "has_pin returned false for pinned host"); + return; + } + OutputDebugStringA("cert_pinning::has_pin() for pinned host - OK\n"); + + /* Test has_pin - should return false for unpinned host */ + if (cert_pinning::has_pin("unpinned.example.com")) { + display_test_result(0, "has_pin returned true for unpinned host"); + return; + } + OutputDebugStringA("cert_pinning::has_pin() for unpinned host - OK\n"); + + /* Test remove_pin */ + cert_pinning::remove_pin("pintest.example.com"); + if (cert_pinning::has_pin("pintest.example.com")) { + display_test_result(0, "has_pin true after remove"); + return; + } + OutputDebugStringA("cert_pinning::remove_pin() - OK\n"); + + /* Test get_pin_hash */ + { + unsigned char retrieved_hash[32]; + if (!cert_pinning::get_pin_hash("pintest.example.com", retrieved_hash)) { + /* We removed the pin above, so re-add for this test */ + cert_pinning::add_pin("pintest.example.com", test_hash); + if (!cert_pinning::get_pin_hash("pintest.example.com", retrieved_hash)) { + display_test_result(0, "get_pin_hash failed"); + return; + } + } + if (memcmp(retrieved_hash, test_hash, 32) != 0) { + display_test_result(0, "get_pin_hash returned wrong hash"); + return; + } + OutputDebugStringA("cert_pinning::get_pin_hash() - OK\n"); + } + + /* Test verify_hash - matching hash should return true */ + if (!cert_pinning::verify_hash("pintest.example.com", test_hash)) { + display_test_result(0, "verify_hash returned false for correct hash"); + return; + } + OutputDebugStringA("cert_pinning::verify_hash() match - OK\n"); + + /* Test verify_hash - wrong hash should return false */ + { + unsigned char wrong_hash[32]; + memset(wrong_hash, 0xFF, 32); + if (cert_pinning::verify_hash("pintest.example.com", wrong_hash)) { + display_test_result(0, "verify_hash returned true for wrong hash"); + return; + } + } + OutputDebugStringA("cert_pinning::verify_hash() mismatch - OK\n"); + + /* Test verify_hash - unpinned host should return true (allow) */ + if (!cert_pinning::verify_hash("nopins.example.com", test_hash)) { + display_test_result(0, "verify_hash returned false for unpinned host"); + return; + } + OutputDebugStringA("cert_pinning::verify_hash() unpinned - OK\n"); + + cert_pinning::remove_pin("pintest.example.com"); + + /* Test adding multiple pins */ + cert_pinning::add_pin("host1.example.com", test_hash); + cert_pinning::add_pin("host2.example.com", test_hash); + cert_pinning::add_pin("host3.example.com", test_hash); + + if (!cert_pinning::has_pin("host1.example.com") || + !cert_pinning::has_pin("host2.example.com") || + !cert_pinning::has_pin("host3.example.com")) { + display_test_result(0, "Multiple pin add failed"); + return; + } + OutputDebugStringA("Multiple pins added - OK\n"); + + /* Test clear */ + cert_pinning::clear(); + if (cert_pinning::has_pin("host1.example.com") || + cert_pinning::has_pin("host2.example.com") || + cert_pinning::has_pin("host3.example.com")) { + display_test_result(0, "Clear failed, pins still exist"); + return; + } + OutputDebugStringA("cert_pinning::clear() - OK\n"); + + OutputDebugStringA("========== CERT PINNING API TEST END ==========\n\n"); + + snprintf(details, sizeof(details), "All pinning API operations passed"); + display_test_result(1, details); +} + +/* Test: Certificate Pinning Rejection - Wrong pin should block connection */ +static void test_cert_pinning_rejection(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + unsigned char wrong_hash[32]; + + display_test_start("Certificate pinning rejection"); + + OutputDebugStringA("\n========== CERT PINNING REJECTION TEST ==========\n"); + + cert_pinning::initialize(); + cert_pinning::clear(); + + /* Add a pin with the WRONG hash - connection should be rejected */ + memset(wrong_hash, 0xDE, 32); + cert_pinning::add_pin("httpbin.org", wrong_hash); + + OutputDebugStringA("Pin added for httpbin.org with WRONG hash - expect rejection\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + cert_pinning::clear(); + + OutputDebugStringA("========== CERT PINNING REJECTION TEST END ==========\n\n"); + + if (res != CURLE_OK) { + /* Good - connection was rejected due to pin mismatch */ + snprintf(details, sizeof(details), "Rejected as expected: %s", curl_easy_strerror(res)); + display_test_result(1, details); + } else { + /* Bad - wrong pin was accepted */ + snprintf(details, sizeof(details), "ERROR: Wrong pin accepted! HTTP %ld", response_code); + display_test_result(0, details); + } +} + +/* Test: Certificate Pinning Allow - No pin should allow connection */ +static void test_cert_pinning_allow(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + + display_test_start("Certificate pinning (no pin = allow)"); + + OutputDebugStringA("\n========== CERT PINNING ALLOW TEST ==========\n"); + + /* Make sure no pins are set */ + cert_pinning::initialize(); + cert_pinning::clear(); + + OutputDebugStringA("No pins set - connection should succeed\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== CERT PINNING ALLOW TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "Allowed as expected, HTTP %ld", response_code); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Failed: %s (HTTP %ld)", + curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* + * ============================================================================ + * Expanded HTTPS Tests + * ============================================================================ + */ + +/* Test: HTTPS PUT Request */ +static void test_https_put(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + const char *put_data = "{\"method\":\"PUT\",\"from\":\"XboxCurl\"}"; + struct curl_slist *headers = NULL; + DWORD start_time, elapsed; + + display_test_start("HTTPS PUT request"); + + OutputDebugStringA("\n========== HTTPS PUT TEST ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + setup_verbose_curl(curl); + + headers = curl_slist_append(headers, "Content-Type: application/json"); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/put"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, put_data); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== HTTPS PUT TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "HTTPS PUT %ld, %lu ms", response_code, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", + res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* Test: HTTPS with Custom Headers */ +static void test_https_custom_headers(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + struct curl_slist *headers = NULL; + DWORD start_time, elapsed; + + display_test_start("HTTPS custom headers"); + + OutputDebugStringA("\n========== HTTPS CUSTOM HEADERS TEST ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + setup_verbose_curl(curl); + + /* Add multiple custom headers */ + headers = curl_slist_append(headers, "X-Xbox-Client: XboxCurl/1.0"); + headers = curl_slist_append(headers, "X-Test-Header: TestValue123"); + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "X-Request-ID: xbox-test-001"); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/headers"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== HTTPS CUSTOM HEADERS TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "HTTPS %ld, headers sent, %lu ms", response_code, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", + res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* Test: HTTPS DELETE Request */ +static void test_https_delete(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + + display_test_start("HTTPS DELETE request"); + + OutputDebugStringA("\n========== HTTPS DELETE TEST ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + setup_verbose_curl(curl); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/delete"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== HTTPS DELETE TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "HTTPS DELETE %ld, %lu ms", response_code, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", + res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* + * ============================================================================ + * File Upload Tests + * ============================================================================ + * These tests verify multipart form-data file uploads using curl_mime API. + * Uploads are done from memory buffers for simplicity (no test files needed). + */ + +/* Test: HTTP multipart file upload from memory */ +static void test_http_file_upload(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + curl_mime *mime = NULL; + curl_mimepart *part = NULL; + const char *file_data = "Hello from Xbox!\nThis is a test file uploaded via XboxCurl.\nLine 3 of test data.\n"; + size_t file_size = strlen(file_data); + + display_test_start("HTTP multipart file upload"); + + OutputDebugStringA("\n========== HTTP FILE UPLOAD TEST ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + /* Build multipart form with a file field from memory */ + mime = curl_mime_init(curl); + if (!mime) { + curl_easy_cleanup(curl); + display_test_result(0, "curl_mime_init failed"); + return; + } + + part = curl_mime_addpart(mime); + curl_mime_name(part, "file"); + curl_mime_data(part, file_data, file_size); + curl_mime_filename(part, "xbox_test.txt"); + curl_mime_type(part, "text/plain"); + + /* Add a regular form field alongside the file */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "description"); + curl_mime_data(part, "Uploaded from Original Xbox via XboxCurl", CURL_ZERO_TERMINATED); + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + curl_mime_free(mime); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== HTTP FILE UPLOAD TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "HTTP %ld, uploaded %u bytes", + response_code, (unsigned)file_size); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error: %s (HTTP %ld)", + curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* Test: HTTPS multipart file upload from memory */ +static void test_https_file_upload(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + curl_mime *mime = NULL; + curl_mimepart *part = NULL; + DWORD start_time, elapsed; + + /* Binary test data (simulates a small binary file) */ + unsigned char bin_data[256]; + int i; + for (i = 0; i < 256; i++) bin_data[i] = (unsigned char)i; + + display_test_start("HTTPS multipart file upload"); + + OutputDebugStringA("\n========== HTTPS FILE UPLOAD TEST ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + setup_verbose_curl(curl); + + mime = curl_mime_init(curl); + if (!mime) { + curl_easy_cleanup(curl); + display_test_result(0, "curl_mime_init failed"); + return; + } + + /* File field: binary data */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "file"); + curl_mime_data(part, (const char *)bin_data, sizeof(bin_data)); + curl_mime_filename(part, "test_binary.bin"); + curl_mime_type(part, "application/octet-stream"); + + /* Text field: text file from memory */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "readme"); + curl_mime_data(part, "XboxCurl HTTPS upload test\n", CURL_ZERO_TERMINATED); + curl_mime_filename(part, "readme.txt"); + curl_mime_type(part, "text/plain"); + + /* Regular form field */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "platform"); + curl_mime_data(part, "Xbox", CURL_ZERO_TERMINATED); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Uploading via HTTPS..."); + xbox_console_present(); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + curl_mime_free(mime); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== HTTPS FILE UPLOAD TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "HTTPS %ld, uploaded 256+27 bytes, %lu ms", + response_code, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld, %lu ms)", + res, curl_easy_strerror(res), response_code, elapsed); + display_test_result(0, details); + } +} + +/* Test: Large multipart upload with multiple fields */ +static void test_large_file_upload(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + curl_mime *mime = NULL; + curl_mimepart *part = NULL; + DWORD start_time, elapsed; + + /* Generate a 4KB test payload */ + char large_buf[4096]; + int i; + for (i = 0; i < (int)sizeof(large_buf); i++) { + large_buf[i] = 'A' + (i % 26); + } + + display_test_start("Large file upload (4KB)"); + + OutputDebugStringA("\n========== LARGE FILE UPLOAD TEST ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { + display_test_result(0, "curl_easy_init failed"); + return; + } + + mime = curl_mime_init(curl); + if (!mime) { + curl_easy_cleanup(curl); + display_test_result(0, "curl_mime_init failed"); + return; + } + + part = curl_mime_addpart(mime); + curl_mime_name(part, "largefile"); + curl_mime_data(part, large_buf, sizeof(large_buf)); + curl_mime_filename(part, "large_test.dat"); + curl_mime_type(part, "application/octet-stream"); + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + curl_mime_free(mime); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== LARGE FILE UPLOAD TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "HTTP %ld, uploaded 4096 bytes, %lu ms", + response_code, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error: %s (HTTP %ld, %lu ms)", + curl_easy_strerror(res), response_code, elapsed); + display_test_result(0, details); + } +} + +/* + * Test: HTTPS file download to disk + * Downloads a file from xbxbx.ams1.ppn.prutzel.com and saves it to T:\ drive + */ +static void test_https_file_download(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + struct file_write_data fwd; + const char *save_path = "T:\\Eeprom Reader Tools.rar"; + const char *url = "https://xbxbx.ams1.ppn.prutzel.com/" + "?file=community_uploads/xbox_software/" + "Eeprom%20Reader%20Tools.rar"; + + display_test_start("HTTPS file download to T:\\"); + + OutputDebugStringA("\n========== HTTPS FILE DOWNLOAD TEST START ==========\n"); + + total_bytes_received = 0; + memset(&fwd, 0, sizeof(fwd)); + + fwd.fp = fopen(save_path, "wb"); + if (!fwd.fp) { + snprintf(details, sizeof(details), "Failed to open %s for writing", save_path); + display_test_result(0, details); + return; + } + + curl = curl_easy_init(); + if (!curl) { + fclose(fwd.fp); + display_test_result(0, "curl_easy_init failed"); + return; + } + + setup_verbose_curl(curl); + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, file_write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fwd); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L); + + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println(" Downloading Eeprom Reader Tools.rar..."); + xbox_console_present(); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + fclose(fwd.fp); + + if (res == CURLE_OK && response_code == 200 && fwd.bytes_written > 0) { + snprintf(details, sizeof(details), + "Saved %u bytes to T:\\ (%lu ms)", + (unsigned)fwd.bytes_written, elapsed); + display_test_result(1, details); + } else { + /* Remove incomplete file */ + remove(save_path); + snprintf(details, sizeof(details), + "Error %d (HTTP %ld): %s (%lu ms)", + res, response_code, curl_easy_strerror(res), elapsed); + display_test_result(0, details); + } + + OutputDebugStringA("========== HTTPS FILE DOWNLOAD TEST END ==========\n\n"); +} + +/* + * ============================================================================ + * Extended Download Tests + * ============================================================================ + */ + +/* Download exact number of random bytes over HTTPS, verify size */ +static void test_download_binary_exact(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + + display_test_start("HTTPS binary download (5000 bytes)"); + + OutputDebugStringA("\n========== BINARY DOWNLOAD TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/bytes/5000"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== BINARY DOWNLOAD TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200 && total_bytes_received == 5000) { + snprintf(details, sizeof(details), "Got exactly 5000 bytes (%lu ms)", elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Expected 5000, got %u (err %d, HTTP %ld)", + (unsigned)total_bytes_received, res, response_code); + display_test_result(0, details); + } +} + +/* Download streamed bytes (chunked transfer encoding) */ +static void test_download_stream_bytes(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + + display_test_start("HTTPS streamed download (8KB chunked)"); + + OutputDebugStringA("\n========== STREAM BYTES TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + curl_easy_setopt(curl, CURLOPT_URL, + "https://httpbin.org/stream-bytes/8192?chunk_size=1024"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== STREAM BYTES TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200 && total_bytes_received >= 8192) { + snprintf(details, sizeof(details), "Streamed %u bytes in chunks (%lu ms)", + (unsigned)total_bytes_received, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Got %u bytes (err %d, HTTP %ld)", + (unsigned)total_bytes_received, res, response_code); + display_test_result(0, details); + } +} + +/* Large HTTPS download - 100KB binary, measure throughput */ +static void test_download_large_https(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + double speed; + + display_test_start("HTTPS large download (100KB)"); + + OutputDebugStringA("\n========== LARGE HTTPS DOWNLOAD TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/bytes/102400"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== LARGE HTTPS DOWNLOAD TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200 && total_bytes_received >= 102400) { + speed = (elapsed > 0) ? (double)total_bytes_received / elapsed : 0.0; + snprintf(details, sizeof(details), "%u bytes, %lu ms (%.1f KB/s)", + (unsigned)total_bytes_received, elapsed, speed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Got %u of 102400 (err %d, HTTP %ld)", + (unsigned)total_bytes_received, res, response_code); + display_test_result(0, details); + } +} + +/* Download binary to file on T:\ drive */ +static void test_download_binary_to_file(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + struct file_write_data fwd; + const char *save_path = "T:\\download_test.bin"; + + display_test_start("HTTPS download binary to file"); + + OutputDebugStringA("\n========== DOWNLOAD TO FILE TEST START ==========\n"); + + total_bytes_received = 0; + memset(&fwd, 0, sizeof(fwd)); + + fwd.fp = fopen(save_path, "wb"); + if (!fwd.fp) { + display_test_result(0, "Failed to open T:\\download_test.bin"); + return; + } + + curl = curl_easy_init(); + if (!curl) { fclose(fwd.fp); display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/bytes/16384"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, file_write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fwd); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + fclose(fwd.fp); + + OutputDebugStringA("========== DOWNLOAD TO FILE TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200 && fwd.bytes_written == 16384) { + snprintf(details, sizeof(details), "Wrote 16384 bytes to T:\\ (%lu ms)", elapsed); + display_test_result(1, details); + } else { + remove(save_path); + snprintf(details, sizeof(details), "Wrote %u (err %d, HTTP %ld)", + (unsigned)fwd.bytes_written, res, response_code); + display_test_result(0, details); + } + /* Clean up test file */ + remove(save_path); +} + +/* HTTPS redirect chain - follow 3 redirects to final /get */ +static void test_download_redirect_chain(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + long redirect_count = 0; + char details[256]; + DWORD start_time, elapsed; + + display_test_start("HTTPS redirect chain (3 hops)"); + + OutputDebugStringA("\n========== REDIRECT CHAIN TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/redirect/3"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10L); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redirect_count); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== REDIRECT CHAIN TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200 && redirect_count == 3) { + snprintf(details, sizeof(details), + "Followed %ld redirects, %u bytes (%lu ms)", + redirect_count, (unsigned)total_bytes_received, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), + "%ld redirects, HTTP %ld, err %d (%lu ms)", + redirect_count, response_code, res, elapsed); + display_test_result(0, details); + } +} + +/* HTTPS Range request - partial content download (HTTP 206) */ +static void test_download_range_request(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + + display_test_start("HTTPS range request (partial)"); + + OutputDebugStringA("\n========== RANGE REQUEST TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + /* httpbin /range/1024 supports Range header and returns 206 */ + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/range/1024"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_RANGE, "0-511"); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== RANGE REQUEST TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 206 && total_bytes_received == 512) { + snprintf(details, sizeof(details), "HTTP 206, got 512 of 1024 bytes (%lu ms)", elapsed); + display_test_result(1, details); + } else if (res == CURLE_OK && response_code == 200) { + /* Server may ignore Range header - still a pass if we got data */ + snprintf(details, sizeof(details), "HTTP 200 (Range ignored), %u bytes (%lu ms)", + (unsigned)total_bytes_received, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "HTTP %ld, %u bytes, err %d", + response_code, (unsigned)total_bytes_received, res); + display_test_result(0, details); + } +} + +/* Download and verify content - GET /get echoes request details as JSON */ +static void test_download_verify_content(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + struct response_data rd; + struct curl_slist *headers = NULL; + + display_test_start("HTTPS download + verify content"); + + OutputDebugStringA("\n========== DOWNLOAD VERIFY TEST START ==========\n"); + + memset(&rd, 0, sizeof(rd)); + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + headers = curl_slist_append(headers, "X-Xbox-Verify: TestToken42"); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, capture_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rd); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + curl_slist_free_all(headers); + + OutputDebugStringA("========== DOWNLOAD VERIFY TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + /* Verify the server echoed our custom header in the JSON response */ + if (strstr(rd.buffer, "TestToken42") != NULL) { + snprintf(details, sizeof(details), + "Verified echo, %u bytes (%lu ms)", (unsigned)rd.size, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), + "Header not echoed back (%u bytes)", (unsigned)rd.size); + display_test_result(0, details); + } + } else { + snprintf(details, sizeof(details), "Error %d, HTTP %ld", res, response_code); + display_test_result(0, details); + } +} + +/* + * ============================================================================ + * Extended Upload Tests + * ============================================================================ + */ + +/* HTTPS POST with URL-encoded form data */ +static void test_upload_urlencoded(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + struct response_data rd; + + display_test_start("HTTPS POST url-encoded form"); + + OutputDebugStringA("\n========== URLENCODED POST TEST START ==========\n"); + + memset(&rd, 0, sizeof(rd)); + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, capture_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rd); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, + "platform=Xbox&library=XboxCurl&tls=BearSSL&test=urlencoded"); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== URLENCODED POST TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + /* Verify server parsed our form fields */ + if (strstr(rd.buffer, "XboxCurl") && strstr(rd.buffer, "BearSSL")) { + snprintf(details, sizeof(details), "Form data echoed, %lu ms", elapsed); + display_test_result(1, details); + } else { + display_test_result(0, "Form data not echoed in response"); + } + } else { + snprintf(details, sizeof(details), "Error %d, HTTP %ld", res, response_code); + display_test_result(0, details); + } +} + +/* HTTPS PUT with large binary payload */ +static void test_upload_put_large(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + struct curl_slist *headers = NULL; + + /* Generate 16KB binary payload */ + unsigned char payload[16384]; + int i; + for (i = 0; i < (int)sizeof(payload); i++) + payload[i] = (unsigned char)(i * 7 + 13); + + display_test_start("HTTPS PUT large binary (16KB)"); + + OutputDebugStringA("\n========== LARGE PUT TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + headers = curl_slist_append(headers, "Content-Type: application/octet-stream"); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/put"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char *)payload); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)sizeof(payload)); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + curl_slist_free_all(headers); + + OutputDebugStringA("========== LARGE PUT TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), "PUT 16384 bytes, HTTP %ld (%lu ms)", + response_code, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", + res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* HTTPS PATCH request */ +static void test_upload_patch(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + struct curl_slist *headers = NULL; + const char *patch_data = "{\"op\":\"replace\",\"path\":\"/name\",\"value\":\"Xbox\"}"; + struct response_data rd; + + display_test_start("HTTPS PATCH request"); + + OutputDebugStringA("\n========== PATCH TEST START ==========\n"); + + memset(&rd, 0, sizeof(rd)); + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/patch"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, capture_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rd); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH"); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, patch_data); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + curl_slist_free_all(headers); + + OutputDebugStringA("========== PATCH TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200 && strstr(rd.buffer, "replace")) { + snprintf(details, sizeof(details), "PATCH echoed, HTTP %ld (%lu ms)", + response_code, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d, HTTP %ld", res, response_code); + display_test_result(0, details); + } +} + +/* HTTPS multipart upload with multiple files + verify echo */ +static void test_upload_multipart_verified(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + curl_mime *mime = NULL; + curl_mimepart *part = NULL; + struct response_data rd; + + /* Generate distinct test payloads */ + char text_file[] = "Line 1: XboxCurl multipart test\n" + "Line 2: This is file A\n" + "Line 3: Verifying multi-file upload\n"; + unsigned char bin_file[512]; + int i; + for (i = 0; i < (int)sizeof(bin_file); i++) + bin_file[i] = (unsigned char)(i ^ 0xAA); + + display_test_start("HTTPS multipart multi-file upload"); + + OutputDebugStringA("\n========== MULTIPART VERIFIED TEST START ==========\n"); + + memset(&rd, 0, sizeof(rd)); + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + + mime = curl_mime_init(curl); + if (!mime) { curl_easy_cleanup(curl); display_test_result(0, "mime_init failed"); return; } + + /* File 1: text file */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "textfile"); + curl_mime_data(part, text_file, CURL_ZERO_TERMINATED); + curl_mime_filename(part, "notes.txt"); + curl_mime_type(part, "text/plain"); + + /* File 2: binary file */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "binfile"); + curl_mime_data(part, (const char *)bin_file, sizeof(bin_file)); + curl_mime_filename(part, "data.bin"); + curl_mime_type(part, "application/octet-stream"); + + /* File 3: JSON config */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "config"); + curl_mime_data(part, "{\"console\":\"Xbox\",\"version\":1}", CURL_ZERO_TERMINATED); + curl_mime_filename(part, "config.json"); + curl_mime_type(part, "application/json"); + + /* Form field */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "uploader"); + curl_mime_data(part, "XboxCurl-TestSuite", CURL_ZERO_TERMINATED); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, capture_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rd); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_mime_free(mime); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== MULTIPART VERIFIED TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + /* httpbin echoes multipart data keyed by field name (not filename). + * Check for field names and content strings in the JSON response. */ + int has_text = (strstr(rd.buffer, "textfile") != NULL); + int has_bin = (strstr(rd.buffer, "binfile") != NULL); + int has_json = (strstr(rd.buffer, "config") != NULL); + int has_form = (strstr(rd.buffer, "XboxCurl-TestSuite") != NULL); + + if (has_text && has_bin && has_json && has_form) { + snprintf(details, sizeof(details), + "3 files + 1 field echoed (%lu ms)", elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), + "Missing: %s%s%s%s", + has_text ? "" : "text ", + has_bin ? "" : "bin ", + has_json ? "" : "json ", + has_form ? "" : "form"); + display_test_result(0, details); + } + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", + res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* HTTPS POST large JSON payload (16KB) and verify echo */ +static void test_upload_large_json(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + struct curl_slist *headers = NULL; + struct response_data rd; + + /* Build a ~2KB JSON payload with array of items */ + char json_buf[2048]; + int pos, item; + + pos = snprintf(json_buf, sizeof(json_buf), "{\"source\":\"Xbox\",\"items\":["); + for (item = 0; item < 40 && pos < (int)sizeof(json_buf) - 64; item++) { + if (item > 0) json_buf[pos++] = ','; + pos += snprintf(json_buf + pos, sizeof(json_buf) - pos, + "{\"id\":%d,\"name\":\"item_%d\",\"value\":%d}", + item, item, item * 17 + 42); + } + pos += snprintf(json_buf + pos, sizeof(json_buf) - pos, "]}"); + json_buf[sizeof(json_buf) - 1] = '\0'; + + display_test_start("HTTPS POST large JSON"); + + OutputDebugStringA("\n========== LARGE JSON POST TEST START ==========\n"); + + memset(&rd, 0, sizeof(rd)); + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, capture_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rd); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_buf); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + curl_slist_free_all(headers); + + OutputDebugStringA("========== LARGE JSON POST TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + /* Verify the JSON was echoed (httpbin puts it in "data" or "json" field) */ + if (strstr(rd.buffer, "item_0") && strstr(rd.buffer, "item_39")) { + snprintf(details, sizeof(details), + "Sent %u bytes JSON, echoed OK (%lu ms)", + (unsigned)strlen(json_buf), elapsed); + display_test_result(1, details); + } else { + display_test_result(0, "JSON not fully echoed in response"); + } + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", + res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* HTTPS upload from file on disk - read T:\cacert.pem and POST it */ +static void test_upload_from_disk(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + curl_mime *mime = NULL; + curl_mimepart *part = NULL; + FILE *fp; + char read_buf[4096]; + size_t file_bytes; + + display_test_start("HTTPS upload file from T:\\ disk"); + + OutputDebugStringA("\n========== UPLOAD FROM DISK TEST START ==========\n"); + + /* Read first 4KB of cacert.pem from disk */ + fp = fopen("T:\\cacert.pem", "rb"); + if (!fp) { + display_test_result(0, "Cannot open T:\\cacert.pem for reading"); + return; + } + file_bytes = fread(read_buf, 1, sizeof(read_buf), fp); + fclose(fp); + + if (file_bytes == 0) { + display_test_result(0, "T:\\cacert.pem is empty"); + return; + } + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + + mime = curl_mime_init(curl); + if (!mime) { curl_easy_cleanup(curl); display_test_result(0, "mime_init failed"); return; } + + /* Upload the file chunk as a multipart attachment */ + part = curl_mime_addpart(mime); + curl_mime_name(part, "certfile"); + curl_mime_data(part, read_buf, file_bytes); + curl_mime_filename(part, "cacert_snippet.pem"); + curl_mime_type(part, "application/x-pem-file"); + + part = curl_mime_addpart(mime); + curl_mime_name(part, "source"); + curl_mime_data(part, "Xbox T:\\ drive", CURL_ZERO_TERMINATED); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_mime_free(mime); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== UPLOAD FROM DISK TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + snprintf(details, sizeof(details), + "Uploaded %u bytes from disk (%lu ms)", + (unsigned)file_bytes, elapsed); + display_test_result(1, details); + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", + res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* HTTP error status handling - verify we handle 404 gracefully */ +static void test_download_error_status(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + + display_test_start("HTTPS error handling (404)"); + + OutputDebugStringA("\n========== ERROR STATUS TEST START ==========\n"); + + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/status/404"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + + OutputDebugStringA("========== ERROR STATUS TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 404) { + display_test_result(1, "Correctly received HTTP 404"); + } else { + snprintf(details, sizeof(details), "Expected 404, got HTTP %ld (err %d)", + response_code, res); + display_test_result(0, details); + } +} + +/* Round-trip test: upload data, capture response, verify it matches */ +static void test_upload_roundtrip_verify(void) +{ + CURL *curl; + CURLcode res; + long response_code = 0; + char details[256]; + DWORD start_time, elapsed; + struct curl_slist *headers = NULL; + struct response_data rd; + const char *test_string = "XboxCurl-RoundTrip-Verification-12345-ABCDE"; + + display_test_start("HTTPS upload round-trip verify"); + + OutputDebugStringA("\n========== ROUNDTRIP VERIFY TEST START ==========\n"); + + memset(&rd, 0, sizeof(rd)); + total_bytes_received = 0; + curl = curl_easy_init(); + if (!curl) { display_test_result(0, "curl_easy_init failed"); return; } + + setup_verbose_curl(curl); + headers = curl_slist_append(headers, "Content-Type: text/plain"); + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, capture_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rd); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, test_string); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + start_time = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start_time; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_cleanup(curl); + curl_slist_free_all(headers); + + OutputDebugStringA("========== ROUNDTRIP VERIFY TEST END ==========\n\n"); + + if (res == CURLE_OK && response_code == 200) { + /* httpbin echoes POST body in "data" field */ + if (strstr(rd.buffer, test_string) != NULL) { + snprintf(details, sizeof(details), + "Round-trip verified (%u bytes, %lu ms)", + (unsigned)rd.size, elapsed); + display_test_result(1, details); + } else { + display_test_result(0, "Sent data not found in response"); + } + } else { + snprintf(details, sizeof(details), "Error %d: %s (HTTP %ld)", + res, curl_easy_strerror(res), response_code); + display_test_result(0, details); + } +} + +/* + * D3D Diagnostic Test + */ +static void test_d3d_diagnostic(void) +{ + IDirect3D8 *d3d = NULL; + IDirect3DDevice8 *device = NULL; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + + OutputDebugStringA("\n=== D3D DIAGNOSTIC TEST ===\n"); + + d3d = Direct3DCreate8(D3D_SDK_VERSION); + if (!d3d) { + OutputDebugStringA("[FAIL] Direct3DCreate8 failed\n"); + return; + } + OutputDebugStringA("[PASS] Direct3DCreate8 OK\n"); + + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.BackBufferWidth = 640; + d3dpp.BackBufferHeight = 480; + d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; /* Standard swizzled format */ + d3dpp.BackBufferCount = 1; + d3dpp.EnableAutoDepthStencil = FALSE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.FullScreen_RefreshRateInHz = 60; + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; + + hr = d3d->CreateDevice(0, D3DDEVTYPE_HAL, NULL, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + &d3dpp, &device); + if (FAILED(hr)) { + char buf[64]; + _snprintf(buf, sizeof(buf) - 1, "[FAIL] CreateDevice: 0x%08X\n", hr); + buf[sizeof(buf) - 1] = '\0'; + OutputDebugStringA(buf); + d3d->Release(); + return; + } + OutputDebugStringA("[PASS] CreateDevice OK\n"); + + /* Clear with BeginScene/EndScene for proper GPU sync */ + hr = device->BeginScene(); + if (FAILED(hr)) { + char buf[64]; + _snprintf(buf, sizeof(buf) - 1, "[FAIL] BeginScene: 0x%08X\n", hr); + buf[sizeof(buf) - 1] = '\0'; + OutputDebugStringA(buf); + } + + hr = device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0); + if (FAILED(hr)) { + char buf[64]; + _snprintf(buf, sizeof(buf) - 1, "[FAIL] Clear: 0x%08X\n", hr); + buf[sizeof(buf) - 1] = '\0'; + OutputDebugStringA(buf); + } else { + OutputDebugStringA("[PASS] Clear OK\n"); + } + + device->EndScene(); + + hr = device->Present(NULL, NULL, NULL, NULL); + if (FAILED(hr)) { + char buf[64]; + _snprintf(buf, sizeof(buf) - 1, "[FAIL] Present: 0x%08X\n", hr); + buf[sizeof(buf) - 1] = '\0'; + OutputDebugStringA(buf); + } else { + OutputDebugStringA("[PASS] Present OK - should see BLUE screen\n"); + } + + OutputDebugStringA("Waiting 3 seconds to view blue screen...\n"); + Sleep(3000); + + /* Second frame - green */ + device->BeginScene(); + device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0); + device->EndScene(); + device->Present(NULL, NULL, NULL, NULL); + OutputDebugStringA("[INFO] Should see GREEN screen now\n"); + Sleep(2000); + + /* Clean up */ + device->Release(); + d3d->Release(); + OutputDebugStringA("[PASS] D3D cleanup OK\n"); + OutputDebugStringA("D3D diagnostic complete\n\n"); +} + +/* + * Main entry point + */ +void __cdecl main(void) +{ + /* Run D3D diagnostic first */ + test_d3d_diagnostic(); + + /* Initialize console for on-screen display */ + OutputDebugStringA("Initializing xbox_console...\n"); + if (!xbox_console_init(640, 480)) { + OutputDebugStringA("FATAL: Failed to initialize console\n"); + for (;;) Sleep(1000); + } + OutputDebugStringA("xbox_console_init OK\n"); + + /* Clear and show logo */ + xbox_console_clear(CONSOLE_COLOR_BLACK); + display_logo(); + display_header("Xbox libcurl + BearSSL Test Suite"); + + /* Initialize network */ + if (!wait_for_network()) { + xbox_console_set_colors(CONSOLE_COLOR_RED, CONSOLE_COLOR_BLACK); + xbox_console_println("FATAL: Network initialization failed!"); + xbox_console_println("Check ethernet cable and DHCP server."); + xbox_console_present(); + for (;;) Sleep(1000); + } + + /* Initialize libcurl */ + xbox_console_println("Initializing libcurl..."); + xbox_console_present(); + curl_global_init(CURL_GLOBAL_DEFAULT); + + /* Enable verbose BearSSL debugging */ + xbox_console_println("Enabling verbose SSL debugging..."); + xbox_console_present(); + ssl_debug::set_level(SSL_DEBUG_VERBOSE); + OutputDebugStringA("BearSSL debug level set to VERBOSE\n"); + + /* Run test suite */ + display_section("Basic Tests"); + test_version_info(); + test_http_get_by_ip(); + test_http_get_dns(); + + display_section("HTTPS/TLS Tests"); + test_bearssl_diagnostics(); /* BearSSL engine test */ + test_tcp_port_443(); /* First verify raw TCP to 443 works */ + test_https_by_ip(); /* Test HTTPS without DNS/SNI */ + test_https_simple(); /* Test simple endpoint */ + test_https_get_no_verify(); + test_https_tls_options(); /* Test TLS version negotiation */ + test_https_get_with_verify(); + test_https_post(); + + display_section("HTTP Features"); + test_http_post(); + test_custom_headers(); + test_user_agent(); + test_http_redirects(); + + display_section("Advanced Tests"); + test_large_download(); + test_connection_timeout(); + + display_section("Session Resumption Tests"); + test_session_cache_operations(); /* Test cache API first */ + test_session_resumption_basic(); /* Verify cache hit */ + test_session_resumption_timing(); /* Benchmark speedup */ + + display_section("Certificate Pinning Tests"); + test_cert_pinning_api(); /* Test pinning API */ + test_cert_pinning_rejection(); /* Wrong pin should reject */ + test_cert_pinning_allow(); /* No pin should allow */ + + display_section("File Upload Tests"); + test_http_file_upload(); /* HTTP multipart upload */ + test_https_file_upload(); /* HTTPS multipart upload */ + test_large_file_upload(); /* 4KB upload */ + + display_section("Expanded HTTPS Tests"); + test_https_put(); /* HTTPS PUT */ + test_https_custom_headers(); /* HTTPS custom headers */ + test_https_delete(); /* HTTPS DELETE */ + + display_section("Extended Download Tests"); + test_download_binary_exact(); /* Exact byte count download */ + test_download_stream_bytes(); /* Chunked transfer encoding */ + test_download_large_https(); /* 100KB HTTPS throughput */ + test_download_binary_to_file(); /* Binary download to T:\ */ + test_download_redirect_chain(); /* Follow 3 HTTPS redirects */ + test_download_range_request(); /* HTTP 206 partial content */ + test_download_verify_content(); /* Download + verify echo */ + test_download_error_status(); /* Graceful 404 handling */ + + display_section("Extended Upload Tests"); + test_upload_urlencoded(); /* URL-encoded form POST */ + test_upload_put_large(); /* 16KB binary PUT */ + test_upload_patch(); /* HTTPS PATCH method */ + test_upload_multipart_verified(); /* Multi-file upload + verify */ + test_upload_large_json(); /* Large JSON POST */ + test_upload_from_disk(); /* Upload file read from T:\ */ + test_upload_roundtrip_verify(); /* Upload + verify echo match */ + + display_section("External Download Tests"); + test_https_file_download(); /* HTTPS download from xbxbx */ + + /* Show summary */ + display_summary(); + + /* Cleanup */ + curl_global_cleanup(); + WSACleanup(); + XNetCleanup(); + + /* Keep displaying results */ + xbox_console_println(""); + xbox_console_set_colors(CONSOLE_COLOR_GRAY, CONSOLE_COLOR_BLACK); + xbox_console_println("Test complete. Console will remain active."); + xbox_console_present(); + + /* Infinite loop to keep display visible */ + for (;;) { + Sleep(1000); + } +} diff --git a/test/test.vcproj b/test/test.vcproj new file mode 100644 index 0000000..8d1a04c --- /dev/null +++ b/test/test.vcproj @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/test_minimal.cpp b/test/test_minimal.cpp new file mode 100644 index 0000000..548ea6e --- /dev/null +++ b/test/test_minimal.cpp @@ -0,0 +1,578 @@ +/* + * Xbox libcurl + BearSSL Minimal Test + * Uses OutputDebugStringA only - no D3D console + */ + +#include +#include +#include +#include + +/* Test counters */ +static int tests_passed = 0; +static int tests_failed = 0; + +/* Debug print */ +void DebugPrint(const char *fmt, ...) +{ + char buffer[512]; + va_list args; + va_start(args, fmt); + _vsnprintf(buffer, sizeof(buffer) - 1, fmt, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + OutputDebugStringA(buffer); +} + +/* Simple write callback */ +static size_t total_bytes = 0; +size_t WriteCallback(char *buf, size_t size, size_t nmemb, void *userdata) +{ + (void)buf; + (void)userdata; + total_bytes += size * nmemb; + return size * nmemb; +} + +/* Initialize networking */ +int InitNetwork(void) +{ + XNetStartupParams xnsp; + WSADATA wsaData; + XNADDR xna; + int timeout = 0; + + memset(&xnsp, 0, sizeof(xnsp)); + xnsp.cfgSizeOfStruct = sizeof(XNetStartupParams); + xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY; + xnsp.cfgPrivatePoolSizeInPages = 128; + xnsp.cfgEnetReceiveQueueLength = 64; + xnsp.cfgSockMaxSockets = 64; + xnsp.cfgSockDefaultRecvBufsizeInK = 128; + xnsp.cfgSockDefaultSendBufsizeInK = 128; + + XNetStartup(&xnsp); + WSAStartup(MAKEWORD(2, 2), &wsaData); + + DebugPrint("Waiting for network...\n"); + + do { + if (XNetGetTitleXnAddr(&xna) != XNET_GET_XNADDR_PENDING) + break; + Sleep(100); + timeout += 100; + } while (timeout < 10000); + + if (timeout >= 10000) { + DebugPrint("Network timeout!\n"); + return -1; + } + + DebugPrint("Network ready. IP: %d.%d.%d.%d\n", + xna.ina.S_un.S_un_b.s_b1, + xna.ina.S_un.S_un_b.s_b2, + xna.ina.S_un.S_un_b.s_b3, + xna.ina.S_un.S_un_b.s_b4); + + return 0; +} + +/* Test helper */ +void TestResult(const char *name, int passed, const char *details) +{ + if (passed) { + DebugPrint("[PASS] %s - %s\n", name, details); + tests_passed++; + } else { + DebugPrint("[FAIL] %s - %s\n", name, details); + tests_failed++; + } +} + +/* Test: HTTP GET by IP */ +void test_http_get_ip(void) +{ + CURL *curl; + CURLcode res; + long http_code = 0; + char details[128] = {0}; + + DebugPrint("\n--- Test: HTTP GET (by IP) ---\n"); + total_bytes = 0; + + curl = curl_easy_init(); + if (!curl) { + TestResult("HTTP GET IP", 0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "http://1.1.1.1/"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && http_code >= 200 && http_code < 400) { + _snprintf(details, sizeof(details) - 1, "HTTP %ld, %u bytes", http_code, (unsigned)total_bytes); + TestResult("HTTP GET IP", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (HTTP %ld)", curl_easy_strerror(res), http_code); + TestResult("HTTP GET IP", 0, details); + } +} + +/* Test: HTTP GET with DNS */ +void test_http_get_dns(void) +{ + CURL *curl; + CURLcode res; + long http_code = 0; + char details[128] = {0}; + + DebugPrint("\n--- Test: HTTP GET (DNS) ---\n"); + total_bytes = 0; + + curl = curl_easy_init(); + if (!curl) { + TestResult("HTTP GET DNS", 0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/get"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && http_code == 200) { + _snprintf(details, sizeof(details) - 1, "HTTP %ld, %u bytes", http_code, (unsigned)total_bytes); + TestResult("HTTP GET DNS", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (HTTP %ld)", curl_easy_strerror(res), http_code); + TestResult("HTTP GET DNS", 0, details); + } +} + +/* Test: HTTPS GET (no verify) */ +void test_https_get_no_verify(void) +{ + CURL *curl; + CURLcode res; + long http_code = 0; + char details[128] = {0}; + + DebugPrint("\n--- Test: HTTPS GET (no verify) ---\n"); + total_bytes = 0; + + curl = curl_easy_init(); + if (!curl) { + TestResult("HTTPS GET (no verify)", 0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "https://1.1.1.1/"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && http_code >= 200 && http_code < 400) { + _snprintf(details, sizeof(details) - 1, "HTTPS %ld, %u bytes, TLS OK", http_code, (unsigned)total_bytes); + TestResult("HTTPS GET (no verify)", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (HTTP %ld)", curl_easy_strerror(res), http_code); + TestResult("HTTPS GET (no verify)", 0, details); + } +} + +/* Test: HTTPS GET with DNS (no verify) */ +void test_https_get_dns(void) +{ + CURL *curl; + CURLcode res; + long http_code = 0; + char details[128] = {0}; + + DebugPrint("\n--- Test: HTTPS GET DNS (no verify) ---\n"); + total_bytes = 0; + + curl = curl_easy_init(); + if (!curl) { + TestResult("HTTPS GET DNS", 0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && http_code == 200) { + _snprintf(details, sizeof(details) - 1, "HTTPS %ld, %u bytes, TLS OK", http_code, (unsigned)total_bytes); + TestResult("HTTPS GET DNS", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (HTTP %ld)", curl_easy_strerror(res), http_code); + TestResult("HTTPS GET DNS", 0, details); + } +} + +/* Test: HTTP POST */ +void test_http_post(void) +{ + CURL *curl; + CURLcode res; + long http_code = 0; + char details[128] = {0}; + const char *post_data = "name=XboxCurl&test=1"; + + DebugPrint("\n--- Test: HTTP POST ---\n"); + total_bytes = 0; + + curl = curl_easy_init(); + if (!curl) { + TestResult("HTTP POST", 0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && http_code == 200) { + _snprintf(details, sizeof(details) - 1, "HTTP %ld, %u bytes", http_code, (unsigned)total_bytes); + TestResult("HTTP POST", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (HTTP %ld)", curl_easy_strerror(res), http_code); + TestResult("HTTP POST", 0, details); + } +} + +/* Test: HTTPS POST */ +void test_https_post(void) +{ + CURL *curl; + CURLcode res; + long http_code = 0; + char details[128] = {0}; + const char *post_data = "{\"test\":\"XboxCurl\",\"secure\":true}"; + struct curl_slist *headers = NULL; + + DebugPrint("\n--- Test: HTTPS POST (JSON) ---\n"); + total_bytes = 0; + + curl = curl_easy_init(); + if (!curl) { + TestResult("HTTPS POST", 0, "curl_easy_init failed"); + return; + } + + headers = curl_slist_append(headers, "Content-Type: application/json"); + + curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && http_code == 200) { + _snprintf(details, sizeof(details) - 1, "HTTPS %ld, %u bytes, TLS OK", http_code, (unsigned)total_bytes); + TestResult("HTTPS POST", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (HTTP %ld)", curl_easy_strerror(res), http_code); + TestResult("HTTPS POST", 0, details); + } +} + +/* Test: HTTPS GET with certificate verification ENABLED + * This validates the full trust anchor chain works end-to-end. + * Uses a well-known public site with a standard CA-signed certificate. + */ +void test_https_get_verified(void) +{ + CURL *curl; + CURLcode res; + long http_code = 0; + char details[128] = {0}; + + DebugPrint("\n--- Test: HTTPS GET (verified) ---\n"); + total_bytes = 0; + + curl = curl_easy_init(); + if (!curl) { + TestResult("HTTPS GET (verified)", 0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "https://one.one.one.one/"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L); + /* Certificate verification ON - this is the whole point of this test */ + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && http_code >= 200 && http_code < 400) { + _snprintf(details, sizeof(details) - 1, "HTTPS %ld, %u bytes, cert VERIFIED", http_code, (unsigned)total_bytes); + TestResult("HTTPS GET (verified)", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (HTTP %ld)", curl_easy_strerror(res), http_code); + TestResult("HTTPS GET (verified)", 0, details); + } +} + +/* Test: HTTP Redirect */ +void test_http_redirect(void) +{ + CURL *curl; + CURLcode res; + long http_code = 0; + long redirect_count = 0; + char details[128] = {0}; + + DebugPrint("\n--- Test: HTTP Redirect ---\n"); + total_bytes = 0; + + curl = curl_easy_init(); + if (!curl) { + TestResult("HTTP Redirect", 0, "curl_easy_init failed"); + return; + } + + curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/redirect/2"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redirect_count); + curl_easy_cleanup(curl); + + if (res == CURLE_OK && http_code == 200 && redirect_count >= 2) { + _snprintf(details, sizeof(details) - 1, "HTTP %ld after %ld redirects", http_code, redirect_count); + TestResult("HTTP Redirect", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (HTTP %ld, %ld redirects)", curl_easy_strerror(res), http_code, redirect_count); + TestResult("HTTP Redirect", 0, details); + } +} + +/* Test: Connection Timeout */ +void test_timeout(void) +{ + CURL *curl; + CURLcode res; + DWORD start, elapsed; + char details[128] = {0}; + + DebugPrint("\n--- Test: Connection Timeout ---\n"); + + curl = curl_easy_init(); + if (!curl) { + TestResult("Timeout", 0, "curl_easy_init failed"); + return; + } + + /* Non-routable IP to force timeout */ + curl_easy_setopt(curl, CURLOPT_URL, "http://10.255.255.1/"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); + + start = GetTickCount(); + res = curl_easy_perform(curl); + elapsed = GetTickCount() - start; + curl_easy_cleanup(curl); + + if (res == CURLE_OPERATION_TIMEDOUT || res == CURLE_COULDNT_CONNECT) { + _snprintf(details, sizeof(details) - 1, "Timed out after %lu ms (expected)", elapsed); + TestResult("Timeout", 1, details); + } else { + _snprintf(details, sizeof(details) - 1, "%s (%lu ms)", curl_easy_strerror(res), elapsed); + TestResult("Timeout", 1, details); /* Other errors acceptable */ + } +} + +/* Test: D3D Initialization */ +void test_d3d_init(void) +{ + IDirect3D8 *d3d = NULL; + IDirect3DDevice8 *device = NULL; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + char details[128] = {0}; + + DebugPrint("\n--- Test: D3D Initialization ---\n"); + + d3d = Direct3DCreate8(D3D_SDK_VERSION); + if (!d3d) { + TestResult("D3D Create", 0, "Direct3DCreate8 failed"); + return; + } + TestResult("D3D Create", 1, "Direct3DCreate8 OK"); + + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.BackBufferWidth = 640; + d3dpp.BackBufferHeight = 480; + d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; /* Standard swizzled format */ + d3dpp.BackBufferCount = 1; + d3dpp.EnableAutoDepthStencil = FALSE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.FullScreen_RefreshRateInHz = 60; + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; + + hr = d3d->CreateDevice(0, D3DDEVTYPE_HAL, NULL, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + &d3dpp, &device); + if (FAILED(hr)) { + _snprintf(details, sizeof(details) - 1, "CreateDevice failed: 0x%08X", hr); + TestResult("D3D Device", 0, details); + d3d->Release(); + return; + } + TestResult("D3D Device", 1, "CreateDevice OK"); + + /* Clear with BeginScene/EndScene for proper GPU sync */ + hr = device->BeginScene(); + if (FAILED(hr)) { + _snprintf(details, sizeof(details) - 1, "BeginScene failed: 0x%08X", hr); + TestResult("D3D BeginScene", 0, details); + } + + hr = device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0); + if (FAILED(hr)) { + _snprintf(details, sizeof(details) - 1, "Clear failed: 0x%08X", hr); + TestResult("D3D Clear", 0, details); + } else { + TestResult("D3D Clear", 1, "Clear OK (blue)"); + } + + device->EndScene(); + + hr = device->Present(NULL, NULL, NULL, NULL); + if (FAILED(hr)) { + _snprintf(details, sizeof(details) - 1, "Present failed: 0x%08X", hr); + TestResult("D3D Present", 0, details); + } else { + TestResult("D3D Present", 1, "Present OK - should see BLUE"); + } + + /* Wait to see blue screen */ + Sleep(3000); + + /* Second frame - green */ + device->BeginScene(); + device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0); + device->EndScene(); + device->Present(NULL, NULL, NULL, NULL); + DebugPrint("Should see GREEN now\n"); + Sleep(2000); + + /* Clean up */ + device->Release(); + d3d->Release(); + + TestResult("D3D Cleanup", 1, "Released D3D resources"); +} + +void __cdecl main(void) +{ + DebugPrint("\n"); + DebugPrint("========================================\n"); + DebugPrint(" Xbox libcurl + BearSSL Test Suite\n"); + DebugPrint("========================================\n"); + DebugPrint("libcurl version: %s\n", curl_version()); + + /* D3D Test first */ + DebugPrint("\n=== D3D TESTS ===\n"); + test_d3d_init(); + + /* Network init */ + if (InitNetwork() != 0) { + DebugPrint("FATAL: Network init failed\n"); + goto done; + } + + DebugPrint("\nInitializing libcurl...\n"); + if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) { + DebugPrint("FATAL: curl_global_init failed\n"); + goto done; + } + DebugPrint("curl_global_init OK\n"); + + /* HTTP Tests */ + DebugPrint("\n=== HTTP TESTS ===\n"); + test_http_get_ip(); + test_http_get_dns(); + test_http_post(); + test_http_redirect(); + + /* HTTPS Tests */ + DebugPrint("\n=== HTTPS TESTS ===\n"); + test_https_get_no_verify(); + test_https_get_dns(); + test_https_post(); + test_https_get_verified(); + + /* Other Tests */ + DebugPrint("\n=== OTHER TESTS ===\n"); + test_timeout(); + + curl_global_cleanup(); + +done: + DebugPrint("\n========================================\n"); + DebugPrint(" TEST RESULTS\n"); + DebugPrint("========================================\n"); + DebugPrint(" Passed: %d\n", tests_passed); + DebugPrint(" Failed: %d\n", tests_failed); + DebugPrint(" Total: %d\n", tests_passed + tests_failed); + DebugPrint("========================================\n"); + + if (tests_failed == 0) { + DebugPrint(" ALL TESTS PASSED!\n"); + } else { + DebugPrint(" SOME TESTS FAILED\n"); + } + DebugPrint("========================================\n"); + + DebugPrint("\nTest complete. Looping forever.\n"); + while (1) Sleep(1000); +} diff --git a/test/test_minimal.vcproj b/test/test_minimal.vcproj new file mode 100644 index 0000000..acae4ba --- /dev/null +++ b/test/test_minimal.vcproj @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/xbox_console.cpp b/test/xbox_console.cpp new file mode 100644 index 0000000..b2d37b5 --- /dev/null +++ b/test/xbox_console.cpp @@ -0,0 +1,570 @@ +/* + * Xbox Console Text Renderer Implementation + * Direct framebuffer text rendering for Xbox + * + * Based on Microsoft Xbox SDK patterns for direct surface access + */ + +#include "xbox_console.h" +#include +#include +#include + +/* 8x8 bitmap font - ASCII 32-127 */ +static const unsigned char font_8x8[96][8] = { + /* Space (32) */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + /* ! (33) */ + {0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00}, + /* " (34) */ + {0x6C, 0x6C, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00}, + /* # (35) */ + {0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00}, + /* $ (36) */ + {0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0x00}, + /* % (37) */ + {0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00}, + /* & (38) */ + {0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00}, + /* ' (39) */ + {0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, + /* ( (40) */ + {0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00}, + /* ) (41) */ + {0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00}, + /* * (42) */ + {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, + /* + (43) */ + {0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00}, + /* , (44) */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30}, + /* - (45) */ + {0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, + /* . (46) */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00}, + /* / (47) */ + {0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00}, + /* 0 (48) */ + {0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00}, + /* 1 (49) */ + {0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, + /* 2 (50) */ + {0x7C, 0xC6, 0x06, 0x1C, 0x70, 0xC6, 0xFE, 0x00}, + /* 3 (51) */ + {0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00}, + /* 4 (52) */ + {0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00}, + /* 5 (53) */ + {0xFE, 0xC0, 0xFC, 0x06, 0x06, 0xC6, 0x7C, 0x00}, + /* 6 (54) */ + {0x38, 0x60, 0xC0, 0xFC, 0xC6, 0xC6, 0x7C, 0x00}, + /* 7 (55) */ + {0xFE, 0xC6, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00}, + /* 8 (56) */ + {0x7C, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0x7C, 0x00}, + /* 9 (57) */ + {0x7C, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00}, + /* : (58) */ + {0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00}, + /* ; (59) */ + {0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30}, + /* < (60) */ + {0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00}, + /* = (61) */ + {0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00}, + /* > (62) */ + {0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00}, + /* ? (63) */ + {0x7C, 0xC6, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00}, + /* @ (64) */ + {0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00}, + /* A (65) */ + {0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00}, + /* B (66) */ + {0xFC, 0xC6, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0x00}, + /* C (67) */ + {0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00}, + /* D (68) */ + {0xF8, 0xCC, 0xC6, 0xC6, 0xC6, 0xCC, 0xF8, 0x00}, + /* E (69) */ + {0xFE, 0xC0, 0xC0, 0xF8, 0xC0, 0xC0, 0xFE, 0x00}, + /* F (70) */ + {0xFE, 0xC0, 0xC0, 0xF8, 0xC0, 0xC0, 0xC0, 0x00}, + /* G (71) */ + {0x7C, 0xC6, 0xC0, 0xCE, 0xC6, 0xC6, 0x7E, 0x00}, + /* H (72) */ + {0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00}, + /* I (73) */ + {0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, + /* J (74) */ + {0x1E, 0x06, 0x06, 0x06, 0xC6, 0xC6, 0x7C, 0x00}, + /* K (75) */ + {0xC6, 0xCC, 0xD8, 0xF0, 0xD8, 0xCC, 0xC6, 0x00}, + /* L (76) */ + {0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0x00}, + /* M (77) */ + {0xC6, 0xEE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0x00}, + /* N (78) */ + {0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00}, + /* O (79) */ + {0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, + /* P (80) */ + {0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00}, + /* Q (81) */ + {0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x06}, + /* R (82) */ + {0xFC, 0xC6, 0xC6, 0xFC, 0xD8, 0xCC, 0xC6, 0x00}, + /* S (83) */ + {0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00}, + /* T (84) */ + {0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, + /* U (85) */ + {0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, + /* V (86) */ + {0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00}, + /* W (87) */ + {0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00}, + /* X (88) */ + {0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00}, + /* Y (89) */ + {0xC3, 0xC3, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00}, + /* Z (90) */ + {0xFE, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xFE, 0x00}, + /* [ (91) */ + {0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00}, + /* \ (92) */ + {0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00}, + /* ] (93) */ + {0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00}, + /* ^ (94) */ + {0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00}, + /* _ (95) */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, + /* ` (96) */ + {0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}, + /* a (97) */ + {0x00, 0x00, 0x7C, 0x06, 0x7E, 0xC6, 0x7E, 0x00}, + /* b (98) */ + {0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xFC, 0x00}, + /* c (99) */ + {0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x00}, + /* d (100) */ + {0x06, 0x06, 0x7E, 0xC6, 0xC6, 0xC6, 0x7E, 0x00}, + /* e (101) */ + {0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0x7C, 0x00}, + /* f (102) */ + {0x1C, 0x36, 0x30, 0x78, 0x30, 0x30, 0x30, 0x00}, + /* g (103) */ + {0x00, 0x00, 0x7E, 0xC6, 0xC6, 0x7E, 0x06, 0x7C}, + /* h (104) */ + {0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x00}, + /* i (105) */ + {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, + /* j (106) */ + {0x06, 0x00, 0x0E, 0x06, 0x06, 0xC6, 0xC6, 0x7C}, + /* k (107) */ + {0xC0, 0xC0, 0xC6, 0xCC, 0xF8, 0xCC, 0xC6, 0x00}, + /* l (108) */ + {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, + /* m (109) */ + {0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xC6, 0xC6, 0x00}, + /* n (110) */ + {0x00, 0x00, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x00}, + /* o (111) */ + {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, + /* p (112) */ + {0x00, 0x00, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0}, + /* q (113) */ + {0x00, 0x00, 0x7E, 0xC6, 0xC6, 0x7E, 0x06, 0x06}, + /* r (114) */ + {0x00, 0x00, 0xDC, 0xE6, 0xC0, 0xC0, 0xC0, 0x00}, + /* s (115) */ + {0x00, 0x00, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x00}, + /* t (116) */ + {0x30, 0x30, 0x7C, 0x30, 0x30, 0x36, 0x1C, 0x00}, + /* u (117) */ + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x00}, + /* v (118) */ + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00}, + /* w (119) */ + {0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00}, + /* x (120) */ + {0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00}, + /* y (121) */ + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x7C}, + /* z (122) */ + {0x00, 0x00, 0xFE, 0x0C, 0x38, 0x60, 0xFE, 0x00}, + /* { (123) */ + {0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0x00}, + /* | (124) */ + {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, + /* } (125) */ + {0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0x00}, + /* ~ (126) */ + {0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + /* DEL (127) - filled block */ + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} +}; + +/* Console state */ +static struct { + IDirect3D8 *d3d; + IDirect3DDevice8 *device; + int screen_width; + int screen_height; + int cols; + int rows; + int cursor_x; + int cursor_y; + unsigned int fg_color; + unsigned int bg_color; + int initialized; + /* Off-screen buffer for content (we redraw each frame) */ + unsigned int *buffer; + int buffer_size; +} console = {0}; + +#define CHAR_WIDTH 8 +#define CHAR_HEIGHT 8 + +/* Internal: Draw a single character to our buffer */ +static void draw_char_to_buffer(int cx, int cy, char c, unsigned int fg, unsigned int bg) +{ + int idx; + int row, col; + const unsigned char *glyph; + int px, py; + unsigned int *pixel; + + if (!console.buffer) return; + + px = cx * CHAR_WIDTH; + py = cy * CHAR_HEIGHT; + + if (px < 0 || py < 0) return; + if (px + CHAR_WIDTH > console.screen_width) return; + if (py + CHAR_HEIGHT > console.screen_height) return; + + /* Get glyph for character */ + idx = (int)(unsigned char)c - 32; + if (idx < 0 || idx >= 96) idx = 0; /* Default to space */ + glyph = font_8x8[idx]; + + /* Draw the character to buffer */ + for (row = 0; row < CHAR_HEIGHT; row++) { + pixel = console.buffer + (py + row) * console.screen_width + px; + for (col = 0; col < CHAR_WIDTH; col++) { + if (glyph[row] & (0x80 >> col)) { + *pixel = fg; + } else { + *pixel = bg; + } + pixel++; + } + } +} + +int xbox_console_init(int width, int height) +{ + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + + if (console.initialized) return 1; + + console.screen_width = width; + console.screen_height = height; + console.cols = width / CHAR_WIDTH; + console.rows = height / CHAR_HEIGHT; + console.cursor_x = 0; + console.cursor_y = 0; + console.fg_color = CONSOLE_COLOR_WHITE; + console.bg_color = CONSOLE_COLOR_BLACK; + + /* Allocate off-screen buffer */ + console.buffer_size = width * height * sizeof(unsigned int); + console.buffer = (unsigned int *)malloc(console.buffer_size); + if (!console.buffer) { + OutputDebugStringA("Failed to allocate console buffer\n"); + return 0; + } + + /* Create Direct3D object */ + console.d3d = Direct3DCreate8(D3D_SDK_VERSION); + if (!console.d3d) { + OutputDebugStringA("Failed to create Direct3D8\n"); + free(console.buffer); + console.buffer = NULL; + return 0; + } + + /* Setup presentation parameters - match Microsoft SDK patterns */ + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.BackBufferWidth = width; + d3dpp.BackBufferHeight = height; + d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; /* Standard swizzled format */ + d3dpp.BackBufferCount = 1; + d3dpp.EnableAutoDepthStencil = FALSE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.FullScreen_RefreshRateInHz = 60; + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; + + /* Create device */ + hr = console.d3d->CreateDevice(0, D3DDEVTYPE_HAL, NULL, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + &d3dpp, &console.device); + if (FAILED(hr)) { + char buf[64]; + _snprintf(buf, sizeof(buf) - 1, "Failed to create D3D device: 0x%08X\n", hr); + buf[sizeof(buf) - 1] = '\0'; + OutputDebugStringA(buf); + console.d3d->Release(); + console.d3d = NULL; + free(console.buffer); + console.buffer = NULL; + return 0; + } + + console.initialized = 1; + + /* Clear buffer to background color */ + xbox_console_clear(console.bg_color); + + return 1; +} + +void xbox_console_shutdown(void) +{ + if (!console.initialized) return; + + if (console.device) { + console.device->Release(); + console.device = NULL; + } + if (console.d3d) { + console.d3d->Release(); + console.d3d = NULL; + } + if (console.buffer) { + free(console.buffer); + console.buffer = NULL; + } + + console.initialized = 0; +} + +void xbox_console_clear(unsigned int color) +{ + int i; + int total_pixels; + + if (!console.initialized || !console.buffer) return; + + total_pixels = console.screen_width * console.screen_height; + for (i = 0; i < total_pixels; i++) { + console.buffer[i] = color; + } + + console.cursor_x = 0; + console.cursor_y = 0; + console.bg_color = color; +} + +void xbox_console_set_colors(unsigned int foreground, unsigned int background) +{ + console.fg_color = foreground; + console.bg_color = background; +} + +void xbox_console_set_cursor(int x, int y) +{ + if (x >= 0 && x < console.cols) console.cursor_x = x; + if (y >= 0 && y < console.rows) console.cursor_y = y; +} + +void xbox_console_get_cursor(int *x, int *y) +{ + if (x) *x = console.cursor_x; + if (y) *y = console.cursor_y; +} + +void xbox_console_scroll(void) +{ + int row; + unsigned int *src, *dst; + int line_bytes; + + if (!console.initialized || !console.buffer) return; + + /* Move all lines up by one character row */ + line_bytes = console.screen_width * CHAR_HEIGHT * sizeof(unsigned int); + for (row = 0; row < console.rows - 1; row++) { + dst = console.buffer + row * CHAR_HEIGHT * console.screen_width; + src = console.buffer + (row + 1) * CHAR_HEIGHT * console.screen_width; + memcpy(dst, src, line_bytes); + } + + /* Clear the last line */ + dst = console.buffer + (console.rows - 1) * CHAR_HEIGHT * console.screen_width; + for (row = 0; row < CHAR_HEIGHT * console.screen_width; row++) { + dst[row] = console.bg_color; + } +} + +void xbox_console_putchar(char c) +{ + if (!console.initialized) return; + + /* Handle special characters */ + switch (c) { + case '\n': + console.cursor_x = 0; + console.cursor_y++; + break; + case '\r': + console.cursor_x = 0; + break; + case '\t': + console.cursor_x = (console.cursor_x + 4) & ~3; + break; + case '\b': + if (console.cursor_x > 0) console.cursor_x--; + break; + default: + if (c >= 32 && c < 127) { + draw_char_to_buffer(console.cursor_x, console.cursor_y, + c, console.fg_color, console.bg_color); + console.cursor_x++; + } + break; + } + + /* Handle line wrap */ + if (console.cursor_x >= console.cols) { + console.cursor_x = 0; + console.cursor_y++; + } + + /* Handle scroll */ + if (console.cursor_y >= console.rows) { + xbox_console_scroll(); + console.cursor_y = console.rows - 1; + } +} + +void xbox_console_print(const char *str) +{ + if (!str) return; + while (*str) { + xbox_console_putchar(*str++); + } +} + +void xbox_console_println(const char *str) +{ + xbox_console_print(str); + xbox_console_putchar('\n'); +} + +void xbox_console_printf(const char *format, ...) +{ + char buffer[512]; + va_list args; + + va_start(args, format); + _vsnprintf(buffer, sizeof(buffer) - 1, format, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + + xbox_console_print(buffer); +} + +void xbox_console_draw_line(char c, int count) +{ + int i; + for (i = 0; i < count && console.cursor_x < console.cols; i++) { + xbox_console_putchar(c); + } +} + +void xbox_console_draw_box(int x1, int y1, int x2, int y2) +{ + int i; + + /* Top border */ + xbox_console_set_cursor(x1, y1); + xbox_console_putchar('+'); + for (i = x1 + 1; i < x2; i++) { + xbox_console_putchar('-'); + } + xbox_console_putchar('+'); + + /* Side borders */ + for (i = y1 + 1; i < y2; i++) { + xbox_console_set_cursor(x1, i); + xbox_console_putchar('|'); + xbox_console_set_cursor(x2, i); + xbox_console_putchar('|'); + } + + /* Bottom border */ + xbox_console_set_cursor(x1, y2); + xbox_console_putchar('+'); + for (i = x1 + 1; i < x2; i++) { + xbox_console_putchar('-'); + } + xbox_console_putchar('+'); +} + +void xbox_console_present(void) +{ + IDirect3DSurface8 *backbuffer = NULL; + D3DLOCKED_RECT locked; + HRESULT hr; + int y; + unsigned int *src; + unsigned char *dst; + + if (!console.initialized || !console.device || !console.buffer) return; + + /* Get backbuffer fresh each frame (Microsoft pattern) */ + hr = console.device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + if (FAILED(hr) || !backbuffer) { + OutputDebugStringA("GetBackBuffer failed\n"); + return; + } + + /* Lock with D3DLOCK_TILED for linear access to swizzled surface */ + hr = backbuffer->LockRect(&locked, NULL, D3DLOCK_TILED); + if (FAILED(hr)) { + char buf[64]; + _snprintf(buf, sizeof(buf) - 1, "LockRect failed: 0x%08X\n", hr); + buf[sizeof(buf) - 1] = '\0'; + OutputDebugStringA(buf); + backbuffer->Release(); + return; + } + + /* Copy our buffer to backbuffer, respecting pitch */ + src = console.buffer; + dst = (unsigned char *)locked.pBits; + for (y = 0; y < console.screen_height; y++) { + memcpy(dst, src, console.screen_width * sizeof(unsigned int)); + src += console.screen_width; + dst += locked.Pitch; + } + + /* Unlock before present */ + backbuffer->UnlockRect(); + + /* Release backbuffer reference */ + backbuffer->Release(); + + /* Present */ + console.device->Present(NULL, NULL, NULL, NULL); +} + +void xbox_console_get_size(int *cols, int *rows) +{ + if (cols) *cols = console.cols; + if (rows) *rows = console.rows; +} diff --git a/test/xbox_console.h b/test/xbox_console.h new file mode 100644 index 0000000..544a1b9 --- /dev/null +++ b/test/xbox_console.h @@ -0,0 +1,85 @@ +/* + * Xbox Console Text Renderer + * Direct framebuffer text rendering for Xbox + * + * Features: + * - 8x8 bitmap font + * - Color support (ARGB) + * - Automatic scrolling + * - No external dependencies + */ + +#ifndef XBOX_CONSOLE_H +#define XBOX_CONSOLE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Color definitions (ARGB format) */ +#define CONSOLE_COLOR_BLACK 0xFF000000 +#define CONSOLE_COLOR_WHITE 0xFFFFFFFF +#define CONSOLE_COLOR_RED 0xFFFF0000 +#define CONSOLE_COLOR_GREEN 0xFF00FF00 +#define CONSOLE_COLOR_BLUE 0xFF0000FF +#define CONSOLE_COLOR_YELLOW 0xFFFFFF00 +#define CONSOLE_COLOR_CYAN 0xFF00FFFF +#define CONSOLE_COLOR_MAGENTA 0xFFFF00FF +#define CONSOLE_COLOR_ORANGE 0xFFFF8000 +#define CONSOLE_COLOR_GRAY 0xFF808080 +#define CONSOLE_COLOR_DARKGRAY 0xFF404040 +#define CONSOLE_COLOR_LIGHTGRAY 0xFFC0C0C0 + +/* Initialize console with specified resolution */ +/* width/height: 640x480 or 720x480 typically */ +int xbox_console_init(int width, int height); + +/* Clean up console resources */ +void xbox_console_shutdown(void); + +/* Clear screen with specified color */ +void xbox_console_clear(unsigned int color); + +/* Set text colors */ +void xbox_console_set_colors(unsigned int foreground, unsigned int background); + +/* Set cursor position (in character cells) */ +void xbox_console_set_cursor(int x, int y); + +/* Get current cursor position */ +void xbox_console_get_cursor(int *x, int *y); + +/* Print a single character */ +void xbox_console_putchar(char c); + +/* Print a string */ +void xbox_console_print(const char *str); + +/* Print a string with newline */ +void xbox_console_println(const char *str); + +/* Printf-style formatted output */ +void xbox_console_printf(const char *format, ...); + +/* Draw a horizontal line of characters */ +void xbox_console_draw_line(char c, int count); + +/* Draw a box around area (x1,y1) to (x2,y2) */ +void xbox_console_draw_box(int x1, int y1, int x2, int y2); + +/* Present/swap buffers (call after drawing to make visible) */ +void xbox_console_present(void); + +/* Scroll the console up by one line */ +void xbox_console_scroll(void); + +/* Get console dimensions in characters */ +void xbox_console_get_size(int *cols, int *rows); + +#ifdef __cplusplus +} +#endif + +#endif /* XBOX_CONSOLE_H */

$g&g?&Ix@&4*d6V?|2$b%*|Fw=zBu7af1{aQCrxP$;v9{TIyul|-dH zVgE&QAT7G<-Jw6aPqcHrz8c#7CW8SyeFjcW1z`D7BS;C~{3EOHnr9S1 z9t7>L;RgjBTnD^W5|)wD#4L~z10q1IEQS}qL5a3EbZ-D@Tmd3LtSpunJV@RZ#WI=m zng^VDIsS`=K#a)}$f!8YEbt=l_5c6Ix4T^hx;?;MRnQIwi%1Us7I2#8wL%EgQn3oGB7Z7^7XoN1O&b||HjT(V%uCH!NA`#6Vw9u z#@{lLfq~(Fxyb(liLe*yuR(Fb(_AmYQW^%D&I|KVgJiTKxzVCxPp}gguQt53T()0(bkhC=B?jKjK8t7WHChZPd)718T$Y_ z%-VhUHMj8r2XIqe2y^oD#U^Rc)F(&A3{dD9y!!vYI}}uXG+Qy$vULA^&DLAV!(7Dy z>I`(3ii8CPcE@rAzvzQRE@;|W5wv8>q}Poj;D52ii_;CFS^33$Q#>;M1mQkDN^|4SwQmx_eHxXB4RVuQsY;D4z^_zO`U28ImKQ8fQc zHU1a#fE5XVXG9&r69E>j2TIt(171w~3A)}b8r%$Qev<-eDHtCJ|6eN7>H6V+DNl#% zix;c8LA5bxp_Y_#f{brD2r@7p zY`jcK(u+`#(GD`5u3uhweFcr3dka^L<32J$^94K|@uKi+Z&fljB>QuS2WHh{F z7U=e2V|lTU6*MWw-zo@_aQ)DHOu(Vj^@BA#fA23w28P#{yF)<@tJiGZp?|u4e;6O= zti90bdIjQE{?-McbvodHnZ}4WV9FU87%bg+_}lmx85sVTD)hQu0L4XMK(Fh8fEPNT z&TiwA3OWzgzEug)d-N7>5PCVTP%?DUIT_1G2uIVhj18UoR z=&jwbbm`Ki-KBTBYag_Jt5XU3Z{F*=A>hR-P$%#RPwRnFrS4!EzvkmCt>5Y&b^Ctk zc75a6d_bVn_d}=a8*AScrMq5h|1Xv4b)ECS^u_;DmH(v*0T465=}`n+A@T&j_z&JH zZqOb2rQ7$3Q@87l=7S=gp91%3=(D!SDf;`MTLb%YEc+ zL7n@ejBa;@gD;qx>tz^9c~&r%L^RhbFq8(pW?8{lBKji!^Z);y5dts5K?}is|8#nY zymtRzE))EshaD2{C9$v7EZup^6fIn3_*+520\DDZ>+m+}O^r~{?#BML8sKmY&V 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ⅅbjrX43`3s_mtpfsDsUjhHC6}QHcq7!2+o)TMzKJ@PIU0f;47;HNKRG z`NA8l(Ewt(2Lper9AuOvB;bF^R)!Y_q6`e(CqPY69~F<*ll(2mnZZF6!q5$Bm$rC= zf+<8rHa->{H@u zOc5xgzRAK|s0KD}C1{iy6vb;H?FmpadCJJZ!0Do*@{$jv&jGA&A6y^A8K4ekbB#*I zfBsfbJb+V4l`6<=(1>9MIGxUAWMEhcnvCOb1$B{Lf|?o`3&6(Z!;J&QX9+ky7l5jb zHDKugxHMO@kBSY`%NCH_4zQdFT+SKn15j5GJp5n-s+(*AvRFU^8!vKOAZZL#WW6w$ z03M6*>AukIqT5IbO(cgL{k;#&1CmJno`W04joC zf|_+14f$X_CNMn@ojAY)Iw0JD7xg_1495SPj|f=SsKk`X z8h=Zh(CwlU!F(*>#g*6p|GR?*2akaUcw&m4|1VLAc;N@q0IF}nHE;6~7FZ<=tAZ^{ zR7}bg)6&xTSTldiB3V#oz@a#2FFCT~xr;^#2kS z&=@p$<{CDX_2Ld6*y$E8E{icRguXc24IW7Zx1f)RfLe*oKmM1n2mBX}NOWcB?ok1? z9lBjq5{%EhNIMA{Ed;eM4)?N%1-ww~Wnc*FbWw?TA>IQ@i@k3DL8E~RoiQpJ!7rSz zgQ7&_n2X$hhL>5O$pld9E9J@vD0XFd+4%SW|LzhMg&mBbA~Z)OrS%)X%ZJvtJD8an z7&=Q-6!=|USidXg%IE;84*vW9Kd7Xd!@$5`eA4(*r;mz^CGUhTSB4UG;{)FsW^}nS zFqUvM{srkSVs!+`J9QsA_<*H(2S^n|>Ft9LSpr|=gM9m=`3Q^gfzBEg0po9=R*5Am zNJ)vk@yT5v#PC*2HdRtW1Fo2rJFAp*>q;+ml`2uQC9N{tkme#pO0aN#{<{cm%45imw z|MR!>gR6LznBEqZAH3jn5fdKp;^$Owb!yOjM4<6M6Eg!txzo49Or?eyZy;rc$xl$s zvIM+%@Ccm$yJJ)&K*LEW1;+J1|NnnG%u>ppAyDGV@cINO@QlBK>ID~2FSqbgs;jXaT&%n^zqOt<)BuB8JpaB35 z6hke+;w;|}gO*4j8OjI|2Zfwl^Kk*|5ByE%{{8xTZs|E8&cNUV8H0qSoU_nG!F{|%C4!fMLE(S{10>3d6uuo6C;^Gb@G>w=IN-qW z?XUuvpTNt&aN&Rh!;7^O85lZSz@^HIhZ8}=u`hN_1UCX>7&^D8fC`uH5*44$7L_ZK z3=I6Opef+iZzU2L4@$sw&yH`R@1C=B%rDE ze~F4qXuykY>lhfoiymxxTU7RdQ}5;sff@sI!i zGfsdC{As`c|Ic^>s)&2O|Njr^2}8)nH=uZi4PmsXfMU5DlEZpMRJwb>*`GiBKu~Xp z3Qte~zo3hXNFay=^-2{$jj#Wr6CkT8Lb4b#K>0P}!8JDsDPk8G${+73($eRNWziwSn zeabJ-(0aS1y4y{He>+F>Po`4V<^wFRIhucpmzp&n0QCd)vx<9tRBQqRK=Y;V4>B{f z9w^oO%wNZPCC!x~ZQ&gd$$!m7#Uc$~&GG$#{?knto`6^dvyj4*?lJAkOai z40W~%#M%GLc>b4h{4ZnqFFFNO!T)If|G!kY^>&GA22Z*x!;5u_;1QJ9YX8dw{+CIF z{}-K;2$~l8UmDkXyM#AG0;H%DqA2|T)$THx)^Gf+>YxdQ5*2~4|DrvKt_&F}kdaYt znC08=fWnLe5@w)EEgmw^E^-haZlJ|A5Z$e}OC&NJASRsr1a*EX#DrcKa7GmY#bZE5 zT^dV6_y#$;(DZ70e z>^InWy*Nz#FjTw-qW=F!s83cy#Wz62pToo_L&bkU#LvUTtD)jL*7~C5zmK-OGCvua=_+?!^D}P;tmjTdzkp^TM++FfQYNZ#4kg| zZ$QNPVdA@?;tIK7^S^(9hQng0cm_oLK1{qDD!u_CejFxV3>9a{1DmrRCLRqH_koB{ zhlx8w#V0_->tW*BQ1KfO@pPEDFjSla(#i3MiT}O{@oxx3+#DwU7$Oc%6yTHxA&gI2 z^0FLoV}Byh_<*T-2S}2k^o8+(!`&e&9KAfAt(QtTyIFcU z4!ALNGIg``f)pT3ZG3Zu33>g=1yG}?Mdbk#WLeoACI*Jkuuc~hljESW9ke9HA{^A} zN12a@%^x3kQBeRXJMN-_I*oj7I|D=a9+eNE8QE{mM_4*bRCJ8rc9y6ZfM%LOxee4@ zlwo3E2=8@KaR?50!Loyaf%%3uX!zM9;6>SXP^m5e8Y6Cz2K9VFa{?1U!}6dx0V_rZ zhOie&_23q!!i&gykYZ407`!Y7-BB5HI>0e}_8l~(RNesBDl*MSIE??do-ENYzTI7- zBEbB)MC`xW3vQ6HWh^h4>%pCKkSh1)!#vhMi*A9+lozk-K(?_MA9#5bJZH?`vKq9W zr9=g^zChtcO&xfoU8B=Q#R9bWAd4{oJffb(^S?wz<3(->1H)(jIu{j>Zcr1}05rPP z%i@s6e~qQFv!s#Ze~F3(Xb9j%OC19Pc;pnkbfEc&0=l;#!TDOZw?!ouG$8)s5y-(G zK#eFy1_scAA&~W;uy0X`U}Rtb&x(WM0o3tn`}ZHT&OoC?xU)t@V>f6fY(FSgUgrM$ z|G)Jue@i2%x4j1va8uqw1J2?4|NmhxUe$ubUE{^WT5t%dG#?Q#{*Nn3V1(~#koGc` z7mFdfF~YaI78<^p6zsdI(&ugHa<!mum?)wK{b3o_&y{u1{OYm=Fb36Eu zgZV`3rTTZq2dvLSHG`)HK)!&KB_Oi#jSkBCAPvwMX^V;p3j;$iX#Cy+v|cDY!==NO zA+$3`#RgmyKo^{$CqYON0m{+PLO=&fgGc#ah{&)obl(6CVc#w_3C-|;q$ao5(A4zl z3aB82tRDi|3Jv~%ouJ?cIr4BYxH$zXAhH+(UTlzM0k5_YX#G~=8P@Bfq610~IssXX z;L!@qr?3C*a0IC9}Ds3U!^{Qn>P!W^tb;AH@4?5adX1-z1IQWZEQX>`}97<7Mlak+|t zAsE*T$BVC$AWH;5tvGJb3fuoo{7uaa3=9o+2EB2NrPW=`z4`x~A<@rfe8BqZYtxc6 zXw1JTiqU>$e6lk~MWFRko#er{9A4IE%RTtFF+0N}y*o!m!1#dmS^g;pS`U=yWC?)X z)9s^T04f0tIxAR?JAgCAaR>19;BiK9c5nRm|9>xNF-v&Zi$_2I|L?vL))}MX@Pe%h zl%xe(Z}YdrfVzkvtKagstOb?8hgm=_>HZ2CpU$|`;mYv8_|FSt4v-em@*R;I zm{^HTw{fqFicEJk3#33)01eeMFa%_QN<5VpVfo<9tOH$))oB76{t)P_Il%&2hShwS zr}-UYXNihH>4feW6@%8dC2HNDA@)PFT4*JBLE8)8O0X-MkMT6WWh{LZ{KBRZ+~JV{ z%`P4&<@;ZvVv_Nv!A!x+NM@0u(xF~=UlLE{=$MPWV0Zp(RXE^~$)+a!7W}uFg z4yaVoIrxAXRHW#<=&S%I1W+P4R{^qKq5IfN^}mpQM&la+l>7#o>;TP}Nw6?5fbyFH z3uq7@l-)py2YW5+3bLQ!#SsY>$VhtY|5D>%SbqBU9GX-YU4-VR_*l@YV~|D0XI?OF z17#tb5q2(u7`3lNU3NH@lLh_RdC=8fgRCEFZUhF>%&QB(wP6EU* zkU`>5gTVPI{DqY`D5Nd3o7o;guU3c1vD(s z&DMILL^f^0|1y?<424cth8IP5{{QcG(HFLr=z*rE~uYN#9$=xR{`t(k58R?6FQfWLJT0|Uc8 z&>G6HjFe7rL&W77G{!!hhvvSp7oy)lkq27lVEVsAg(V=P0isp{ruN8rkOBeY1E5v0 zAV(RWd7-)mVubbiOLH)_r=b*K(+fFpUWGwM)e#yw+ zdKT2h|5nOn!&J)FTcg7Bn#uTomcfgTGEfK}2hBGzbn|!mvHUOR_+QTQVnQhcL#G=k z_`2OWI^B3)g4SHNg7h<@==Xr?2NgNp?452f{Q(gD5Y7L~1^$=wys!a_33R&)bh?TB zFPHdVF7iSHEGE(IF45^G^S@l-f4R&H5wMs-x4S~8o67%kjsN8;FBrgL8qG&^y4^K8 z-E>~7wSFsQ<==MTHIwmyfQ&hiAUgU48bpQXKtal5{H?o3C4_^4q5BwkW$*b-@K8E) z<_xSp59$#_{5D2`H0VSpCoa=bWO0xE|DUK|C}5-;|GX@wVC z!L-JUwP3{}VK0_|87$yAc5p(45>Wd}*>|M8a%G4+3~K*_$JkUrV{8r#knvdlZB8uK z$4W%ty#SCBhSEo%B;0)n*--F$r33$(f3TEubhES`IpoH0*!TdVP0;*?CpZ+;2|#{FbpU9g5@?)8AozvNcTk{#h89FX&Een|ry)yjyI;KQVgP3m z2~eph68vHkXr0;*P~Q4qQq*k@Uc==zA!AD?Xj2JjdaN0=sf53EDyXS>1T6X;DpM<8PMcB{JQ|(;j6O)!*6E?21XYL26h(*23{8j z24NQm21yqO26-0;22~da25lDy216GI26Gn&23r>g24@!s22U3U27ea^hENv=hG-WD zhC~+!hIAJPhFlj1hGG{7hDsL)hI$tVhE^8`hHe)JhKVi?4AWg4P!`mI))w~$Fm`b` zw45ycseK64%MI?0V(j8_0ttZ9l7RMQ(8?H*7oe>N%|`@~R?D9`18$###%Dyrzzu8W z`^-5i3f8|%+#&6QE_QeReJ5HDl$iHA?r;7f*;}Z<@BXp%TZv}#KZQEE=6|{+lFk3( zOGKLg>6P#||I;twYW}BP!rJ`Ls+7(8cj^@mcP)^DYA<9pp0 z<6@%^$H&DQA3!+C_$0^~9G1Kh6I>Zeq>K+(???c#9N}3NB*9SnBFy-krRjl5t_&q| z#s|6^PE2xT__woB%^FOIZn5H%lu>UmRHS$Rt;WIONrgXU;Ug;Rp^jJ{cC?>7ycG$y?G3n(hJh z_PTRaWOh~bg4afesEEME^P6{o#29)vfT$9OZmaI2DA9EtDXz3HhX#ee$odD$Dgvzs zN-etUSelQqwEizW)$OAq0Gg$CY(69bvKh3-20Vhn+`I$i28PmU@o}-uC;mq_AK^F* zT0b2h7u(C?(9LqRpx2cFEDFwV&2Lm-gSDWQY#}NdAkTEysF*-JQ=$bLBLV3t5rPCc z+=dsg`FdGAyG@RQENuN&Djoz{T${nL8Z_8B1=1VoEm7gV!*GFTrf5p?W6cn~q``0O?B!G|o}8$k*Y9uNR~;PPcqu!HvY zKs*5L9}?w{JF5}?xV;nIAN!!PU@w5myXGHk<%a)NS_M2E7J#Pr&3C zFv&6nBq9PPRlp>;uzBF&!0^n&f#HpZ1H&f|2ZkRW4h;W192i(UA>~5z8;(%px1BjE zES9>Uc;asXH7bI`c7oEM@d3!r0ukeHmXHJ)+x>HI%W7AK)^DZkJ8D+DGQ8$){>QkZ zVYMp*zw6O}7rmE2TaPk2R=YC1XuS0QKWKS-FN<-rO)JPehF%C=dH~daYW~Mq#+%Ut zQW|y%6qqdFHMcK3FZ~D2LP)qa9|UhH0QIPRR79E&v-Ps%f|};cM-M)Lr8553g#Z8l zLw0j;96oa=XwbRqTm{|y3Nt_*=079dskFG8y(9!MF` z-2u|kdb0Fph6_l3|Hc3RyLmx%J!sAuWQwNof&UvE5GKsUFae|*Y(fOcgj%o(p!5SX zK@DWW9Iy!)AQjOUA)(ZL?BD~I?hcUB){~`oU~LLe`vknbiKkoK`dWzt|2`(CPVv?Q zC1$-I`Q0P8UqSO2XRJ{HG6|X-)#p@4H@%jT)y#4?cuRlP=>$TDYpoNf! zps@{zeJ+@+=T9f&Hr^u_<9`~JDIyr z@b9x|{a^aJ`-1kh65U>p|7jDt7+VgMDA_2~N!aL?h}guJ2-xVA@Yv{=aM);DI;pd`)_9~aww7+kz&FhEo+g{cTU4Bq)N^(HezKyVgg=nHA^-Z+^I9f-mjm_iMR zQJ|;_$L;b%n&Ys1foQr<3CrruJf-Jpv7 zHS2CJ&~l9b{QFM0wHzo3g4Ex=ju)DLaF$7cYj4(a)?UYxuep02=QsagEf4Q?T-kb{ zBEb4^txxxP{`IGsPgtKQQZT;MeenBd>*J+j%|HK_2zLME-^b_Hda`s2WZClJ(2NbM z!C|o*yf1?#;6?f&P*{NG;6Q^=hXXSvfJ&0PAon-F5dp2B1`U$HcB6rUSO?ZG1&xhs zfC_;ZPM`q=&~O(h8bBi_ix?OfCV&bSUTA?^ z*s%B(czqVUj7$Y&t4cr?XxF&L3$-|KXW8K3a~9^4jmJTzgBHK?3$XJGvVg`;48ViV zprJFjfX)&Xix*4&fZFt(E}#J+nbzCBDZ;H5Mw z%||#6K4Sqj`(<7%O9wB0H0l1(?E@bEQt0G*@h~0KzUBdSn?TVnayTObVpKBBDE@=s z6cl`&nIRxFi!u1cOPFMnwYL)UXi%P4$Hbys!cFZ9ag8#)AW1 z=!0AJ0@fc&m0Q1+fJUf9!UJANA}is6DJi-8-$g~B`6y3!C`0R|5*d)KuO}k6R9bnu zz%3P?!{ENj8Au`vy9NzcCa@pDYsf*t1>N%k>feE)uS5aV@@G>wo*Rn8x z+Nm|*00J$iE>RKTZ`lA^S-ECCICIRq3U#;FesJ7m9DskMIngU^({_X=C_F6Av&16@G*H1F`fT+6}XF$}o zzzhLMpee%Cp9QPu0awIXOfNWL;#w9rBtrnA zs2!%r7~+DK+a+ch1`xSyn4I`N(5P{vI5>a6-0lmL{kaz$2Hl?zzT;^9R$`Xn0MV`k zQ*dK1Xr9FhRXZO{b{AB;i;4hfbExr2(4g{5P~Urk6lhiZcBX?bc$$B(@VA4;E&r>u zri3^!bi0Z)TQI)d0LnLDCV%TH5IaOgAg#Nl3lu16o$TP%a%q-LJnRe%{LLT*&9xE? zJ3t$Zc7g_Pc7aAf`CU$QAMfO0dMO23cm*`b=I(G6fy-w~v4(2o-1bGc4 z5(w6Q@HGck{Xz)+%?Ft~c?4c7qM0D@njcgYq;sd*zo9XpZ#2E9(8#n2)FFXBCz7y@2o zdN477y7l1wM2&AGP|iC6EzRg|QBi>&djg_6T~t^?!$1cm=rA%c^p>+U{su*3kz)56 z6$?fNhEUMztvBGY&D#MlxWSI#dD+guz|d^RP@?dE3s_ZfMh7GWwq5|ak|p3p;x16I z3xGF-mA?7^zxze=5ti1srNWkM{4Jdz2W0Ho;L7mwBPg%AsE7n~yK?-$@P7+<-#n-! z0S#OSbi4BWzW`dl1zP3Q>!P9&(CsSl|3Y^zOY;$lgKs&SpVoJ~i-0#l@wc>s90i)v z)&d#-;{WUa|G}FMT2Gb=fNT{831`S`bY*y5*A3aAZwuZECD?4oz~Ax(WJd;gCsaIW zG_KoSq#3jsszn9l{eZw1>#{%#K6hjx?T0!B+7HFX-vT;_Dg(S73RIZ}zqpKKw`S|@ z5>=4>lfm0zeLxk?txM(B>zI>)<<}ltEz~9su6}X;k z%^ebRLBqD7#Dh{J?#Pj0V0a-m7kU3uh71E_{}Ol^J!m$j1SE12G#^s~VqJpnUjpx1 z0?)#yfSP!?X7`S}sDM%;!*Lgt3aC2p5mZRW7-WF*ai@<8XkCCzXNZbKr;7?`FOv#r zy)$(05@-(-XfKmbr;ADsXgOA=i%J3L@Bq-PBWQi`aTk>m5F50CiGh`YfgiMg9kPFk zztx5hzF}#_8&D8~hfz0x_MJdBEKNd)&H{--HZ0X3M5{oekPS;|2vN|%5gCvTO93#^ z643St$aa@-kfw-@piLZxaB0Yfr9Kw$Ld*aL{?>NTazq#KhNXa)Dj+R0z*_#jhPo8G z$0;A8MTCLBH3~E_4bdX<@+)X}5M<}lX}A`UBQikY{qhn>8nSa~4O|+sbIA~5B53Cl zXqE`PBP0V{_=0wXKz1%M@-i^I>;su`1MI2{G&2|>X4w4aZ+!#XBcuX1!v?&oWG@c` z!%Hua8IVm(DsVF(du}d5_S}FrG3{XnkCVGV_QzyH7M_AOgtQ*uZ;9dt2bv25e~Uji z1H((u1|8_urHij%fn^BV=+Qd~Vx$iPe`_twS-RlmsvxiVfK1~78LqAG**K&>TCkVZ75u$2xu)UXjMk@c@|Kjd>IQ;1=;YV z4^ze8S`G>d$c86Lm}p5N*xf&vz+MDxWP1!+eT3M4%cv=Qtx(J%3um@W?6Jn(d1Ai-Mw@Nq6 zN>G0vvA=2pI8H(Pt7KXaluUbB4QdWU_B(~b4YU9o7y~g-f`Px)9kSg?0TP{OKK}m? zTF1%(%H*J~$`URHhL?sQlOS82xZx(LflUG}f&!dJ9|{DS{Zm5d>Oqn*rIu)Q3$K6Ij(WkXewuOc`)h zkiAUJjL@T0Q1>z|^ass*gEO_qimU}(CRc`+XF;q7Aa#d9EYKFCmpef$&@Q8w>p?8gMx&QYK`hW- zqnEQmEYOammlHuO(8i;e?I0Ft@6pRz5DUEhs2IcoZ$HWeu|V68UdDr1;N3-`AQpIc zkvE71-bv)h0a`Es+DVkf^y24nXdYO)5t0YYI2agSbbzYz8WjoS+b@OK85lr2TR}~5 zy0II{`dpSyDm8aN#rz=0F` z;{G;xtB$|r186>{Mn#9ABnPC=14P*D01Z;VcI+-MbYED; z9Ej14Fr#%LM!#Il%D}MW&n8!f*Q`5!Y;t7?2+d&F40c5rOeqssDJao9v>pKO;mN?Z zhetXbyoaY?XNNF&>tv?pGJ`9Q#ncMyI;Z;J}3g%R*#tveGa zlr5T%2z2|X$fR|)s4QTEYzbJz#=y|IN5zJdfx#BM3r7yL3x^B53+Lqp7VuV>QZDfJ znwJN`m9L5d$_^We=Ho0Axdx@ajd8Zct|#zP|<{DBlAWgzT?@2zo(OLig7|#I`}ikoMO=#Pi_d zJPeS1HxTh}5OL5xDacls;&@PSy_5ru($=U*K=x)pcX&)W0!>E_>%i&g+W8XnbG-WPTsq z?c?7D*=<$A+5M|?N)Kq<#tkwr0NXlqsj)^y100v!$6Hhc_@J9-YE)!EF@o4WBf^Ke zeMW*0vVG=%iHc2ci;4{7T)2{e7w7DmK$BPwy^tPP^AVoT7L@`%28LF|784FWNP6Po z1E)_9&>0b+jVO@Vcj;_V0c|Jgb^-6Y0j=2uZCUJuY%A#n?d)$+ao`7QO#p3s-?9e0 z1qCz$-nj<61*P=>e+y{v9u!=llnpv^E+xVk`zjN?U8EO;x?7ik8D7t>-vD_&mYLxlcFgO$q& zKoo%6vMMp1Eh>AU{^;DI@8R6v%2cEkKHQ7H*{ zv9y|j0W`F#@xMeR<3&3Y$O)kH3`)R_NzmD_-Lfs9eF(as-3UngHG6$jKpQe6K;aeG z3)wLe81VmcH)!Vte+%fyV9jV!@vDt^9!aD;pP{jrRF=tLA}==@b0G9 zJUc*J1fiy6757e2;gDfq2nq~%aikx-RYW5VVFsvI4U*0fSqqvlP2LX9481KXEHa?; zI8@exi@WrL(99yd8Y1rk-ZTnY8^r+IVR0265$l}5=?&WkA5eG&h6lW;25*-a=>8B6 z*+bg=?|+R2D9v@dsFb{X3tF%ItwcS8W34O03y1e$%U?@mgh0yan+L!G0WVrtfn37@ z%9YKh|A)U&4FpF_#0wb+!{>jAO2`ZTE8sK#VqUP_`TrlZ@m9pLMkS$4+W1?yi%JY= z+imOy+zITp;^xmjpnU5F_^6 zP7DCM3Do5S@3#eY{Xi+{xQhyS&+Ur>h=Ph2=>ZI&^ZGz(p!o<7+78+5UQjGB$$h}yRw8Z=oe!9nvPh#7R$QR5rXIVrFq$aMFB9btUtg=sIyGa&atw?#>Sl6o7cHMvFwl=4CQKjS3$w=*~YU@BDtb-zI~ zOT8{CF8l(_y)h~dASXJs{x1#atWj}!?bZB4ywnDy47728Uw|1T9q^gI&RHN0v?(f~ z+gYMFMg>&$W`LFuxBf2`=NDjguy8d+3hD_e4x`uMWpp@Nm}cH63BL|0?2l& zh8}PpGQ_goDhIUPs^qm8|8{23$aDd8#}z-MC)4Yqk`s_|1TvW-whtOlhn9nb1jml6 zwN+ z?eBk;)(@Eu3_Cz>do8sCv`P21@QwyX28P!>J3w1=U$cU1ev`onbmUJ7<2Y=4(IO#Cra9J;?t9wvSo zDh}P>#SRnS3>D9SnE!q^Gz?}##g{5erjg`twRQJKy#a60WSVvOAo&rTX0+s zlT-#va)6Ih0qx-gZKUOgEH3r~FD?ch1rA;u3|d@V0$yDF?Z4TJ-PivA5BP7E;jzt? z;l;gm|Nn=Fy#V!;n~zAuBdv9|YzLJUps+a%HUzZ77;Z?02}tuoh-UBz+7SU{&41dE zHDjy@-n;`E81aihA;1G&4-A@(Ha_!WKSJ}FGiMs#2rweA59a~ZK0PX+acAQLpy_Gj zx1jofKOA&E7N}v(0Nxt~uF%0F$>9B5py~rO6fDr0qatAmX>9ZN6|yrhbjxgPu+}Z% z0(FxGUfuzX8-Y$q4eqqr_~ODfkn_Ofx|=}~pmE*c7rPLmprdWTC#43zSb`931gQm$ z>juB*Lx^UBL?7&QWe9#z0TTs}>w?Z+V|W<_l70b}jzp0L*X}Q^LDFx)(pGS3Z8z&J z;30Yb-h4&|2Fn^11O8S!PyqR;h;*}T1g$>kwAuKQ38dL(7s%?rSD{`iLDCF570$9o z#e~0AA4RhXNb^z9I8F~(^8sv{L5E#i)~HzUw}OiCZn(`BAkCnjNyZ(p=4QBN4TQ5F zfhI?4RBZTLFM`@VaLqQIHXC32W$5e%x!Dt@6VgpV=-vccKK~YS$N<=4osFRQ1?d$6 zo%8w{G-3r#6JS{v6#=;39u`nT_AP%)3^Qn#J%7tykT*+qyE43H&5+myE^2wUL6hl@ z`QSi%(ZB;bM5g)d|Ci4|L+W34x-z`Jo{_Q3mErY;3>Oe}GGhmbI+QU5MD5Pt02#O? z;|YkjHX{VYTb5x0qUL9ShH!&l_x$i|NpZXUi@?g^-e%L9=C&biGfeC z$zpm@yA|pjO|Wx#UVP++IR`W;09x)-RKj5s#NWD>pnZ;6T)m*R zcL$gQ16~~d$P7Leng^t;x0m7H|No6Y8R{4q_}leB3CBf6po^pBWGOq?tk>3HLqHRX z5JMaS170+MjJVN!gy-8~M*fx`py{~ZjQlO{A+ayeV9CJW3Q81N3@?(bnHWH){j#)v zD^<#vu@xLA6<$IBwle}jry44> z9w^nwcmuKj$7ZPgOXmLnANs=21r$|05LaA;3`}c)I&Pq$n1C1dYzz#c-5*}4LzID9 z&wKv<|Nj!~-5eDOP@JWfaM-x=x1MA`#91;Zik$gdw}Qkx7#%=Cx)0Qkd@TbG(zy(v z`e@PR|No)k!`}zm3y{U|LeGi`yakX2v>xijKTvW)2^Be0Sg2fvgbEipR9-In_y7Nk zkG`NCNIfbbw}ZUz5eRB4#{|6Sum(*Si?kjn<;oD*=F0H07_yB`10?Sf@WO)$6bhhn zvgPid|NmbLhh{9;?aJ`d9dzu^0saPVGTD}Kz{nS6;zM)F+3(I5RsBS$_;$T^$B2yw6mT_V?I5lK#g2sl}9FP*w z^u7jUTZKmO3#A`mG0^CS=b!)oU-CkVNU;7F5dB&({nuuL)q+-?fkr_zf?v2C`u`tv zj2aJU<1{B|F_*dVTac?~f|BZe_<2sy{S`|ufD8cb#&gYp?5&s#7ctJb0^V2A2p3Vb zbWxEhF$>FJ*#q{+qK#00_(9z9S{gi&{lA#we=*C8NbmwR@R1v!RN@L>1>0@X-Ye4% zs{G49<7hFUL1Ihu5~=Rv0WY2$fi7)j>18QvwrOYRWoZZPx|rk0z|fteqSAbXCHO@@ zh~uIn0a}}S+qL^QC|_HzfmA6yA^-mWH+~!ZBFhmJyDY8$OEkgTI>5%a;xOJ8qPY8L zcMo`&3p!c+x(?JJ0M+D&A;ZXXL5H-&s7N%Q{r`FnsNVp?jc+1Q_REKWHp+u0ic^>% z8^b_H1%-nqyM_Oka{Mo4$#}8FmEi^WAi5(w;A24Tpb~FD65tyB3yAe;>Hq)#OBpg` zwz@LBc)Ile{|prn>o$mW1f<|1xaF+ST*tvsD$`uY!%!;LTqnR#D$raf!cfY!1Jtd1 znG0I*09))Q6Yye>7bq{bS%Pv1Xbqu!h7Y8qIJX`er&Tk-NyGR6cvcEzI(X}MDHq5J z{uWSr0<|XtLbDiN_}PHW;pucy5okS7vL)a}tpoUEE*BMvfY9I<`ZnO<8-?a00@eph zR5NNIRwcu%;-3jx2es246k$BZ2VNckrByf39F|C6aKH-#Pn2J#YbXmG%b6`%=*BRtAKy1@qx3uS=v2S|b+;eao844|dk;8h2psD~z` zMKz#=1WF>%RR_VK8w#v>CI;BtrG#AGtleC(Oaj`S)-!U>&Mbt2a+}Dt<&hNQ8DSRQ3{wO(h4icD`9PiF|oc_6o`^oEIahNx)thADK0sOa>DftF<$ z^oD74hNzfW#;`S<0=Z`j$UJ4xAcu>J#(x9QQA_^~GUk9pc_E@UU{RO<1{q60 zqTfMFfn8Jrz@icV4Kmh%L?1##Q~n!(9JvJ~bnfr}{~3EgtS1XWxzgdkS;h+x_v*s` z|1&;-Sf@cO2~c@(5X5o-v9^O)IUv?r5NigAwHU+#mm4#|Mk!dvbCe2O#`Bc&S;h;L za$3fV@VD4AF)+N4G+_dr5*P470m3kNp>D#&5S9fJwD}*R5&_!z=c1wms;O>*rz+ZQ z7#PAp!(b}^LsViw=cl`<=xMbVpi1SQf+o5ETc|^nr^? z07w|r+zWVNZv!6TH0g9vkq8U;AEM#{Dmh$K0{B}CKn=DK6@%_m-G>golsNc8puUN&t58q)$f>cu$|P*DLoSl9&Qs^8#-%Svmot3tYOfYwWcMxp}3f?q5)0het) z%||4x5AwHy$3flUMOP`P3E`vS09qr))BKdN+Z|GLfp#~7imt2RCWwIYi{KZ#tiUCQ z@$Ke%0fthp=6VqZ$O2~2d5WN&)Nt1sm?62YBr)IxKUSA z6Mqa9UjPx8hl!tth(kgfvfq&-JYz-&s3*GV1~dFb0J-1{1IUc?ljYDLnE=)bT5%qI z7*r!kfRD&I3s2==seXIo)A8`eG!k?*$Apl&YS@s zMc9-cqnM*>xIMr z|NlYVj}_*ilw+W?x`=w06K?g{yf{Khb z&;fDX`&d{Q7_5&M`?X%;ZvhS0Y5%bP$?yJ?`B->B(2K|>W`=IC!sa79%*Q*yOzSp~ zo>GzHU>Y=Ne;h0hVu4QdsfBc21OmXjMHB);|BF^6fG+vtZ#e_HSO&hIvqnXLfxl%2 zrt%V~at}};0#Q}O$iR@+T%#hvSeoBlqawpllEJ?(Mn$dpH&=;t^Kae~!RFtbAVQ(W zzxj84i5GMe55)Ds89IAi89HRx{)1imf^qi$|5=PLT$eI41iUc2#LUpW4-^{BM+7>- z0n+#%#4RxdnXUuw`e68_6?ES2f6Tx%*R(NYtbn*88>UShq7CM{ zV3_#-ZZy~FPC$2_I!x{5Zk*0zhN)TK4Q|VeG#}w;JPryQa4_uy`4=3ZpO>aBjgLDV z4>}ftU!H-v*@5ADvjfBOCI^NKO%4ot%?=DLEe;F}tT4dH#LNOqX%M>c%>;M1m_5(cNMdQMpycUpKf(hVFfCC5 zsji2qE`X@M1>P~i67Zr8ruqbu>Oh$44v6YCFx3$-)n|}YE5lSTfT*s6sn&w2zJR3q zD`eADK*kP;>HwJPKb=r_UqMoR9H#mLM70u3^*Na88%U~W!c@P2sQxk^n)nyMRNp~T zoefjXun!z7$6%_9V5%P=skViwmVl_90aNV)Q_aGQ2ycFvY6FPsESPFBm}(v*)ej*% zrUEiNAgXO(s$X;IxTiJ+RJ0%GLudC-7MhZwozA82z?Y;e5XE=qK)v131`el9(4ysJiGJfx&{~KR_3rjHJfNj$9e*IVAv~k#FsxPHMr;WF$tYKkbU@GAc3(oL4;L7mg(-*K8!@^(O z2mzIe94|jJGBA8Q%);LSI=Z>JMn#07q!v6d8~&mdd<-(o89E4Olt7)q-|~%-fuRzs zV?Zk$Kd#25ZT86w{6qhgZ9 z5C}SF4K#A?@Lx0q+O7npa*%NNixq(oBb1@(eqAsE~tbpUtN1A;+H4PI1(HVJ%aJ|fZjt=_a1v?`?G066>Hodu2l&K6KWa)iHd z@B!J&lEo1IqSX(?iHb=0i|al}ISnSHJduMHdjF)%VPfJOiR{~wU?03<4%#Sr%5C3tNZ z$4<~v?bZYQt|tOBen3oqH3Q~Q~jQ^q;pe)d%0&1glAB&5Qk2OB?;#C^FWKWw= z)8W7{t;2y~ZifTIk`Bb)Nl*)@`Hcahf2RXF4hB5Q{~t6YZu}OOYj%T52iW-lu%l2d zYgAnL`#?Fp+hhm$&QsUd3E(@W!j6NEyJcW_@oyU_1VGa?cF;Rd-@rv+cb?vYi@@$Y zJpmKpZvo9_8sC1+3U&Z!2P){kQjP0RROx6Ovu|0Ol8w@cK*VV9d8nhp)8 zyhiW_{Y}$BU9!dCbi}_%5K(9}OdbPO$yNikh^YO5N7oe@2pl(R>aRuwo zMQ0(S`scerMlJvuc?7JJ$N2W^y1~@L)>fn5GKe{<(x+{ts;m0`!9L#_<`E(ZfL1P;40yja%t|9^%Ah&87Rlw90- znvckU(n(7kXfy+~!xmJpW$XbdsRSv$0Al5Xtne2AHJ%**gAZ~01R6C~X?2j;Pi+JLp=3Wx<7AKvi?Vfu_xOgn(F}MGret4!SbDuG~=qqKbC3 zfT-*pQ$SS8jwK)}cE=VF6}ICDi1OcY1w?u5cmkpvcYFa+Ry$Y@xiY*q-XQ{_batqK zDAgS{AWCjW2#6971RsR;;4o;RLN}!8-s_^m5s>i&6iS|*|Nn=DWqbg!Z9D(}&)5QD z8H3eHytd3x0C8175+)#)6hyfTh|LFK*MQheAQfP(KfuL`N`?j~VZZM9|3AY3#Cq5P zK4(b>G%OHjeCCB)A}FCK9Gcbog>uc=sHYC7|uc2fEj&tN<}UH#woK zBR}q<0^ad@+y!z4*l`yX*iPdRQ0ome4FaXXhthOz0bi!kS)u~EQysMV0dyIXL1&4I zNhj!()e;q*&JvZH&Jq=s&Jq=w&Jq=m&JvXfP^+V}M5Us03wSR_XNihUXNgJ<=prc4 zEZgxG@IDO?6I2a$LM{Mlz0Kd}!wS0U2YjOO5g=!R zYRs1xLF<-4>)XO#d|nR@*VY3i!eAw=f1pDyFG20%j626b9jbG1MIvBDkV_rGMzw*A zdIDCp0X8)QveGDr#Ja>Z7-5>+?Q<%%mIo54Wagr|V~;Ib8T*&pbZNr#u9v#2v5 zn~(kA+F&MwFWP#^2{IY70a+Wa#0+e5GQ?yX2L4t*R#5wOE5nQD;0heHOVrn4=Fd$KpSKs}#(f`EYYAz~(#!ZA=20QwcH$vJrVU z+#GkXdwzq4YCvPT{H>r>W4$ga9*~`@k3bW{7eI4=Au2MUf$2Gr{ly*({4En<1}lIJ z-U7b-&I$&IG|vKQhHOmU1J}$0N)gScSYB3uWFZ$c&V$Rs;tR5C zJrbk@wBRlLMKw$bf2*Y+149O6&vGhEw8RbUCQ*pz3>f%ZL4(xr4a5_W_bUg0x5R+< z4}+&dcfyk2j(x-HyomHgIRF1 zw7_QhFhf(V;%1Ou@CM}?=v|DUAb$y30-FK3k5Lb<7n0aiKuKs1q_p5~1>HLdcExju zNu7{#1e|n12Vks(+{!2qa}?<0zYNIs=Bwb{M4;RNjb_G|6B!s7G9cTUx5H&QK`v@O z#q_!?1G1NS4qOW2qB%^^z047y#bObVdl_S1Tor(Bf>_aWapccamUl6-Q1=Kaxc;PS~Jch6G!hAVmJ5vgDJ5vJlv49tS)yUhK zQi`7cFHuQ&0ovsSUaJh=y9C+J1ZKjjAIlPzfHG-V`_Bh-f8Z5q2H5?90pR-seO?@t z2D=M1?s42j1y(;rKG-V9=aw`{KjvA|ol z=Yv?_E!$H;Ebx}??th@m8llGwOzVOMy;BJ&=y_f?fYgCEbSHyYGN5Z9BS9?ihHifl z3%sG*6~qE>=(Yy2z#F;^K`iiwZgmg~d|jk0hy}hbQW(SnZ}R5+_y0fW+QaS`@TGqa z-7zXLoiQpgpwsU=LGz3*DixhEDhAy#Dxk#_p#8u$oiQpVpk1b*+m1o~RB+0QQBeVH z(E<%hf|6$Iw-WmdmE+(vwYL-MvCLwS$2eXTf;Kj`sDL{6pz@*HMWp~_7fAoh381wr zF)AvrS-L}1WI!umz+3J?=dOZo20hmLAF}b@Ma6*M@&A{F%7EBMI{G(k#uj13aF|G zC}DrG+Mj{pHR}r(PVh!^(Df3ajp(To;EtXNxX2U%tp^HGsY&bXQTYMheZEKK7ijl+ zi^>#E28PC;;4RB~pzY_f;O*yGOfU4?p^Tr`JxRnQV6^4 z5h6Iz7aVrq4l95!RfGucfvAM;Mu&)LKolbFMu&($fT#tBXo<&n#HEiA=|b>OBk0~n z7U*Vmhb2~)6Bt#q(U~b(ZDmBfJyB;t7gWOLT5Cpn|54^5xzXN1T zHIMOs=%#8r(57k!2BiC8vFxwr?EcrerN@8|V}~_pKe_=pazXpiGZ6dH!Eu7vkDi0J zA04#A9CV#yw~tBybf-D!%EkofPV*Gd2K2X(K;VTcC z09ANx@PZkn@3dnKtLuW>`Yb{JF+l&Dk~p9Jl^Z~X?j9ya2|MmdlRXM;$P3wMHU>1qA819XEI zXe6cEMMVX4df5LG@CB|2H?NcexkKT#{tJJQUZ`6^fqwwvR*ircMXN}0bKj{J)|&F7ij-JB!#ua*${rl@dl#fbEXNyXR3|LDEXb=Aul>ixt zT2R6|S*i^33+NibfET=_;4z4t-WCYHWNZH#GSY{=Y>9boN2Oi`~{B=LtYEy%>0w2sA6O2b=-dd4eQ)THhj-D6^PB zK?xfFbP34Vu+o7cAj4p#11NbP0qKF>eHrj#ksL@J=%P)~*kQnnphN}+{_q3MM_AJM zgsFZYFsOMU+_^0$hCCY1j3w}Nhn z?{(hW{6mPp9kkhue_MmVO7L2jA1lBi35gm58L-1z5Ab(@7Se#Dh`%Ktv`vNaC1|?= ztlE3A&4PiU`-Jg<){~$MmQL<8IpNCC%hC$kq7<;h<^*IYvbRNL4%l@oWWl8osGSn< z;x^b45wLk#%*P?8V}M31GC=xXmV?G8!9mGwbfBX}WgiCv!)x{~2&46FiB&V`uICct z-YqKgI2ahf3p{%FfX}f2t?sZ=Eg(RmSR;~hH7pCL~S`%wV;C! zpyqb8gjC8fFf<=xZT=;~-y`w=|Nkt_-WC;*)yG;?=EyKGaDl=Lk{^CZgX0SldD_yT zL?Q4JbYL<(?X!W4Ko)pMWnNz zWVKqoZ498}cU+VBz7O9CB4_44Yc|NmbIE&TuA`1Z@p zkN^Mk%QNgVr6AwMO$zb2wE@++Bn6M z#Q>@jW&W3_$Yg!{FA7?05%6EM20WWwq6WH$p!GnB9BAi_6G)**M#wQ&h8KITg4dP_ zG#}xKi#!aHRfI-GiA076#OsG^pn;a31`2M_!31&O!$;4YITHw;&jr`U5}@97)>pXI zpo#2m9~F*n&ej8^nyn{G6fD7ml%Rlu7@P$&SPX7(7~CaSuOCd^c1adTzk?Drh(?hKln*qT)VGyc;SGJx|~` zOuQH>4n0p`Jxn|rDh@qQU^-0P87dAvPoN$qt_>B3o+pqF6BmYxL+_FGhl&4AhWHnH zo`5+_{4rDJ2=L8jp0^LVD&10kE<6w4!=Fc17DDW^az^2e! zRAfNwZCX?`KwFnjf^VGE0WoibPFw{|CZJy>3p*ANHq(wi$qrkZ13R0w(?`Xk(?`Xm z^(}wjURDMM=+t{UXro0y*o(iQiCoCN2>dNuLGqv@uv}DR!a&1;i2MIQeWeqHQaK)4`G4dVs$b zG@}Te+ZRBHf{#!DoxmFQ;@32|+5?~=P0&vLuoq7dqM&oQGgjn-uFX0J6D?78xBkoD zyM~E@!7>K4&3*=?yDQMmvjgN(@Nvf(pz-yv7c=3S)WMn>p-TUo>;SJGdQp)9b3w}@ z76yjbUKyZs0m5D+z%_D#rhY(;me+b2phE$|Ubw*I_*<-*7(hqgg67m2Uh{z#!htus zD}dC4rvE{f_LP8boQ+YD;BQd}5AUmJfMy;*yPTmLq%RADy9o}UgLaO$sF-juFnoCJ z$^Z)d7|?<~E(QjHH?E+yeGXg<3_1{|3l{@J$6K(d2Nwgw5(v|Thk@b1aYv9^3mygr zhlx%grVS4R!-CJQ4BZYapl#F=#{Vs2R3yq=Kr4~|m;7MqH31!E?E$jTr`rK^vU3@z z%^L9E3?vlM?EpI0*+nG+#Ea>65cq$=9ke&7Mn$4%59o*?khn*;gUJ62;4`sZKncnR zBpA@`AOW%wv_ptH;6)X9Qz1+DjqVZ^1<=xcNl>fx8-ELUK>Nula51h>2F=cA;=%Qq z2Wb1?$rS=6@)-=L!7BchLRGASs_6A+Y(B!VLZQT@^<;@e#)}lNvgru}47oi`(GUU7+nws-WZS0x~QhYVVam!>0>ungD2DzTyA>|1(@5^7~-& zSzvh%kh~!HPK**2&@N|X@ctc^fQ%f7`aYO?E3kT=<{A|Xh7y|$pOdZ(FVwOi*AB2) z7W0%zcRPc2mKZ>moWJ180!b?EHksua$C!s&sN{N@C1q!X-N+P<0IY2iMmxy*dvq10LXt3d6C}nlD zK2`M9`cx^4@uk<2-Oeo97x}lbaP*2?{Q(Nm10}3Z7hjbA4$26Cgr!q4GiWnyz>9Y= zpnw3KbZ^q@%o5n`1HQHwwBf(`2+wN;*fDNGF!lSu>N#GdfjXdPA!|`I%A}3|g9a}^ z%TV?vf&B|zhN1zU&`^0{&I~=D4Lm6hna}_;VYLf*Nek?JHj)1(A6~F9!{;+3!1Ea* zFFt~{e!~`bf$AMlUU2BEu5PM4lf?-a-Je+dhY^RcmZT#1Bmqp#3}=^R6vP6 z2gCv=_9U=^fSBVB z6aO3uF~(e2LD=?1>@=rHsa+%C{uof`}I7F!PJEw*J~^#UN3po?q; zKwBLTXNkZ<+X?2vci}KU+OJ?{fQNw+O#U2P9<(1688?Ma#@;s2C~2pg1n9h07KUaw36{X) zZZe0?x-z_Q0v)DvL;$5XaOMoi{h&KPI~!df#_@DEg3fE{brcDB0XjGp))5DJ_6+F0 zN)hlzN`kJy_Z)N^0xKHT^d zBvVu zgavdP9LOH#8!ul#j=>QLco7DYd&dIWd1A* z?{$Ab#&?GOXg>DmWh+FKf4v(-)D0{O8Zzy6`@;z4fmFYY1*`j`i4gGyiTM5LcKgxk z_NUwJOQ+u#kjhTCA1@6+Qb<;THNBJqi~cb_Y3cTZf9^rgPCt-cAU!YtgJz5U{#;Ij zi@XJixIq=qM^StUB<1%*+waf!o6;wdOxX#Nfa#fvqGukm)I1caW@M>3C{h_9DZf9L z>)_4`1Btl(Q3U%4>~t59h~J;)cO2bpovt5xTP>Iv7&?7_fFzH(zG3Qg{qj-)q$cbS zM6TQKNAo)lxKieWoxb3JJLdX^vD5WOXXu}oA3#%5Zh!cj4nLD0P} z&F@)?-#7pNQ{vdgXvI{j-u(Y>iCLE;qm>h5sZ{g-eWr6%3_($Jsz@Bb$%0ybJ|7vK3@Nmw*G*%8n2fjZUyw zi3;3usVv4`9~GTInB`sIV>Li6V}bv@AdC689fJ6q31p<-7jQ=U0`jFFEGxcz4q9CV z3KCG_a?yMPiiMY#;DTLj9WcSYU_o#oA+)df1==TNR`48M0dF!1hnV9?m@z+kuAfgy6Y14H(12ZpxY4h-{mJ233p?Z9w#w*$k6 z-3|;)dmI>)_d76%>~UbQ*yF&EvB!a-W{(3y%N_@YiF+Iv#P>Te80>Xmu;1&z5V+TY zA#Se&!<)Sh3}O2m7z+0}FtqJ+V3@tnfdSld=K(cx1$qk@yAO4mAAG^qeX98ZWAnrM z?>7!UVCO#A_zP4U6v=?jd*;s()3e|6jOMk~(up=S*e}ktp;re%g24-M}ojG%6N5Tn5SCi5W5WI$W+k2@&z-*9D! zYdu-Q(_qO^!rs{d8t*!Mya7ak6hi$7a$oZfusNlYpxJ}glcn6p!3HZaFfbhM>@Z+t zK=L4{ebl@YqFxTtPy*d)1{$pGY_tKL+TbVwTJONX0BINH|G0Ya><{cm-8A`a2 ztbw+spzW_lkom0#N~N23g8jNfnSp^}mmTQJG}l9&VA;dXKNL!tj1NG)fkl7w4}}tr z<{x$?%*F=}cZaBOv|cLV9Iw+k~v#s!c^+CWFw zg0^kH011Kap6qS2-~uTOcyZMQ-0(DLKBCgu1{wYq78)0lYOhqBBNC0CqkG z|29_!*UlUjna&&)k>(#Z#c|zdJ9AW2y03QTsA!~3=>FYVqhj!1rS->U2Zrux9H6ng zOZ=_93=9mN!p(B+#89_#Zwa9?AgHD=K0i8D0{KKYb54c>A2W@O*VBp_w;~H=e zRNmgW?8<;v-b&ypZ!KWuEl3~p)$aG;@)k7w{n7$-yxFf_e@1?JhAwvZmII|f`M0%! z*1&831f9WZ{i9SjJgB!#6SSV-#VrBQ;5}$?lJ7X^(5(N>hgn{}1U0_Ez5@+@H~(NN zN^95$Qm<7S+prI`SXZw!#Q0?E{}R#eHc%im*f8pqusT|wFZv47;n;lOpY~7dpgDC0kQ35CPRLQQXnxDm?aKgb#OJg!fLif6 zDi)wNd=wu8L+=Vu2)uOu2cCE2-{#BEo5k3DvHRe`S8UA>>YE=ie!q3_5j*zgftPIZmbff-Ah)j^BiC9~BFvK0qfk$TKtl zg0>~OGBm$t>CREn=)T|zN+EC)Rl1Kt+uwMchH5Z#C*w>1zp&0g>Q7Kd5@far^NW|} zaB*Ld_-jx{0BoN%Lx~FLPE_U>FNNW1G%?id0I7NT5!Bjp{xS1=^`Fk*AI*pVyu1t% z;a~6kr_&iMau6)?hY`Zt4B=@)cuW8M|39JI`A4_+pHAmL-OgV+oqu$Ce|b3*tO{Z- zL}fKt1k`$WhBWoP!G@=RguVY7?^K> z7K(mz=3wM+Z2>KRZK$!zgXmdvB3YbFaOIvya)wdvv&k^`hdj$VwwNN693Eo{4e|Q z!WJf8y0hCwMWfk8MMS~Dx(yV6oh~XGp#A`VlLx3|ictYu^71q&_n=4cwx9q18=nLn z1m4{Sj^Bfwpo@_lI2id`K#LT+D_EeBD*=fyyzvVPO|3AZkf<%y1Vt+cBw9;B3%pgD5AX!^y1fW^Aqln%ybE|C$mj5I0iCo2 z3KdBB@HYv7>K$0PZ2s~8e|PYoZs#A(uX#X|f}J5MpmozR-Q3NuL8CJ&-F`1_?cio$_dvj2X|kcvj1B1 zRfg}6Ks7q3KJ5P0eQ+m8^84fN8=WC42Hi)$KkPoy{R)%>c7c?Cf5dzq)SGO+%D{ZH z+egKq`69^S8pa29v$^UWVtxq<3gH9HXZLRR>MRnzz`y3A_`z4=-JsznjqguE2?1si z+zuBNjqgw4wt$QQ+0tF3Vgm|OxJ}(LDgw2~_0exBvgU`@n@z8>lP^=xqa)MFHK80-&i(j$>^ST%c$;`|bb#-nJW@ z3=9GPi~sbtfez>oc=7!gBSWY2AJ9gQ`!DB#jLQDg+hzdTK-Vc!fj=8;I>a6?lG6$-AA4qZYYYuR7k?v*D4uBXK5dK2b zl$oKo4I~dSr8Dmj$OPuYprAYE_J*;u?gMC;N%0$~4(t~SYd$I($5rIMBth*6tj|pa1|h$O1t2 zs3F^<0I~-Xz3x0OwLuO%@xRlZ=cNM3RAtlg?Z9&I1xNFP zdPs}qIp|ysNagLK;sFWlV=gK#Or4;cy?nq2Yq~%Rh#%ndb2*?*f^{H`-ajBZx`RQZ zFi`Ex2SElfcKWD*uDA{83{eSry|ei>%S+H19{lp4PBTNd^B;))=^$f*|L||y2a2%9 zLm(%E$Ex^Six@y_gZn_f2UQx_$E$3?bq096$_QF#fXAy;p>+m$yh;L6XOswl$EuwF zfcDqCeES)iJHFolwOe9T3|`*)46d-D3eJ4~|G&E$8ea4Z ziyphbr=*HF_i3e9!>Y&Oh1Qb&4 zppg3cuf!b`QtqIT`uV@a3KUZA%q2!(M~A40fE@17d`JMaj0m*f)cQDo6X?9a?iv+? z{b#@oDv@oPkMK0?16|_6P$C9Z0V^dp zegiGj0<0~QIYO-WbAAM846m;-Rq(v z9{_Wn5UTTJpiXm9kY6?!^L9`43CdFFnm1bz`$_afkFJZ z1B2#q2L^}Z4h(+B9T-xNJ1|rocVL)!+<{@maR-L|#~m2X9(Q24ecXY8<%9#n(~}Mi ze@{6uT)6DOu=|Vy!{aj!3~Xl|7+lUeF!Y~wV9+?{z%b#Q1H+PY4h(zGIWT-X=fI$N z-hsj3yaR*nc?X6Y=N%XhTy|iHx!}N%cfo<-?qLUp`U?&WeHR=UmR@vV*nH7};lM=) zhO$cz3=EeY7{o6-Flb$NV6eXIz~FP)fg$&@14GAU2Zkw^9T=8gMx2=d8ovUK`S7%U zE8*jpXK1iwC}neOe#ck}8W#ZX+HXBj!rfrSP|60{3|IQq`a=nLGPn61OA%W8{~f4* z^6yUxr2T)Z`QP6XSo{BM^S^&3u=f9f=70Z7VD10S;HobUJo*GZFBdd;DgbhoM0o4B z5`F${!oAUq;E|eKM!#OK{mnlmd#e=q-G4Rza4h0z{t;Eq+BxLB}} z(V$JK#s^SO#BF}#0vl{{QE})FQSkvyDEshlV`_fD&%dodfQ^B{`e2FZ4r2xe2GAv= z4#sC*SOPQ#0@`Y0d;n&&Ak^sY{u^KeOGS4WBH8>&7GiU+iwX;h+5Fqv zgV-1tSV7fn0Gb;>?QpPF&7ebf__u8bxu&-t@R>7RE-Du2f(s)jQ524;ouO&Y}mV92Hm@7#JFU zF_tQUmK$X;1|D-XV199f57hbRIDDK%9wdL9MGr(lRlL{*l?8j}O!FJiMZqG+T~t^= zJ!Q~oiXghTaV2QOCW}gM<4F+1MTKJrXkTTTWh3ag!6I?c=>n{!9NiQ5@GvmE=Ifrg z14OfRPu#-8z|hO05|G7|@#a2c9-y~TfE~QJQwOvq?o#s+_-p`VJi5!#pyfa*8#t34 z4&&eUq5D`kDAZV+Uoe*PcL%Ci2I`ctcRO-0A9~FMYN<&dXnw%dP-(rK^L)~Vrl))?{eWAB%Vs5x{rZO<^;tIi}C;0LfwuU z+KwuvAU0cfB?oh*O824W6C5B-hd}Y!eW6sX`5nlHcTA-+pa?9K&^}fo)a}XAeTey7 z^9h00lkxm6hvE)*A2L3P#DxSec)deIr2#_;7bs;Ob2MP+WP}z?U=^V8`-Tbwh7zG~ z4dA3y0$FOaL=ZA707|DE;oWUtKqEnYKe!k`r3sJr!GN$AjDp~3?)FpZ4%4tcRT6IP zr&AKteX#qdwwq3;iwaMPdv_n`FbvS?J^|fs9KF*(JZ3kY0RHW676JU*+)O~#Xwd%) z-99P`-50dOIGT@$FrVrSQ|a{6>HgIjrqO-sHB|^h$aj2Fv!0M$E5hGUXTa3y zr_vdw(dnlX4>7#A?+H5tLvPy$b_NE}ikAWo28O`Swiloz4QX{sWHE$wwy|(CFdTC; zVmQ_YibsZHZJeM`df^QoJppY-0eSxnI6lK(Tm@%B(CVm==6wzzx0M=YF}(P90o-tD zJy0Um+Xp&F5`5zmNEz4hHXBw3&_Q_&$J;;}K;8G|ePFR#k%l@@3OnXzz;K)mG}H)M z90kr!uxb!&H;4e0Um!Q|bO)-Wbry_LAu2C=u*-VqtcY0BySG z04*^BB{{fJAn%+3t#RY&E>YnLd$Ez5fuYOIp!o<#%Yl+4{%r@~hK6?g$#jQFXrC(a z?sj8gK2+kuzs=3K`M?{{1)zHWRazh1bzlIkcbW&@$iNYIxCYRuaJ>Dl1L)KsmWC=Lh7w*-sKMO~@?#j>Jxbk064pgB zrBdBqpd|)8+UG326yo^Zyc9Y)5I*LKgKGzS6-w24IC+>g>;oT`TB7@{?EyOj15>FA_>ix#7a0)0wH_!H%3=z8F_Qyau7C}S zI}A!nV4ESt%WfXfHNg~`W{c2WVk z66`)ulS!c4O@;Y*r<+Qrn})TUPAO;Divn&0Lq+)!}f(TflfP^ z<;=iP#MZlU_dd{}f-GX%=K=yjW=XsNRp!k{MB)yE?oj}l4iXl50m{M6M?^ru173e= zd=lh};IOpg4hGB&kVMhxVV2hEVI1CisZ_wygQc{-!@~e#@9UCo9~BwM>Gv@z60Ijg zI|Ep{U-P@>sHpI}UhE9u0JQ)ZIwN>GGXy4dpX&a8`B|@DsP)StuHHUZMg|7!o5gHi z&A&K{AICQT;wa_nw1|%bc`N#G^Do|G4&n?uc|bG8E*HB`bp(i|U4EX{Ss~IDVQ{=ySk2|P<%826* zIv}do|99h029T`#uih}$UjN_L=lI>OcLr!Q{AMa;0hxfbL>F|wkw7ntbn}mdGSDqC z9N@}S2jpHza6}&lB{3fG7Qx;&4_46j;qMBdRxnS;ycMhr3~?w8`o=e)ll)*!`WBTl zps|q_@I8FpJu0ByU2yjt70?Rx&~C`3(_!5$%{4sWLq!C_J3+_(6tL`IVrF1C_>QCb zS$&#iGq|1uwJ?~wD?wXIWCD6w^qG%=j*|vWN(aAK&H`#P=`|k_U_Q_*V%EGz1vJsZ z(CecjQ^Ll4j`=F{@m?1e8Ss+E?k7A94Bzid|5pZWSCI)11C@X>%!fcD=b<29n)Et5 zKn4xEdsILvvH6I~F=s6dOYC&Hqg29y>1Tww}FnM59oG+ga;@PK`GJ=6duNBUL=4W5d#Sg zBJ8h5*dNh7?FYpE6qx-IAp32Q><2dju{$9ibjajGK2R9IttTx$!1rcC;zOl->l=t$ z6d)1dqoM#x82`6|j_wD=4Dd-4Ryxi{4PJ5Uow@5f(B#+j8As3^>MhUyMn@$N6_#hUEjy4X^!n8I}Zz7-@ z++FD0_lJvtp|cOvWdaXof*We3SbKY*BRN1Di~2xXtbdmHYyV`dljyCJ>2{N_W-m2v zt^>EqK^-N~g(~R%BwqdcQLZQ7Yk~&n7{!~1CuRSP9fl3&T@UAd}hF{F3eBEv=)@~f7Y{%RT z7&kF?yGby+s0eh|DQMTI2z0thbh^oO)+sdqU@bD@Zv~Be1$W1>bTN0h8S`)RX5`;i z&D4GH-~$fsAI(3RON3f3m2g2?>!3A7pnb{w+uh94Kvx@E9|udnj*f>Y0NoZ5cQ~!H z&WwLsH8cM)NXglj@}gB3Ez z9ggm-Q;0wA2I)dUVk_=2$T_84@zB@JG*WK0wzFeeKt-EakgeBA6)&gM(S-2ULaDp8G znmYn@G(hd(fZjGx&o|%&<6cl_SOC)T1+}Q5JrYo|fn%_J4Rr?0r99BY0~!%v>h@D% z_EF*K^i#3+(Zo3w}D!H4IFL^$J;>dp$Qyr3@JYmYa8uE(+X?8GJK{Q=niLtv{IRza--wIYtU zff^MCn;qf4fa(V|%07VggPKDOoNf#+gm!@SvwVWOA9R^d9H^7Wa=Za_i4A0-@r!KG zwbecv_lc#-E@@ zdl`QgW7vy*uR+>5Kv^R&sJ9KIBjAOl2&i7>$@uWli6P^{Lnnr?7uVi^)bSV}uw>(( zasW9(G6Hx(D{B9jsPMdKkOXUlHMPKb=*4R;@I99-osAy63=D@M{pCi`jNmaa363SO zQZNDbe+Fo(K8vB(jVIuRwj?t{h6rdwSR3e6r7VVk7ZQ@pAh}MqUa-*dHqcBlsHP0- zbYnU0#4f{d%Gl1rW;z2RO1F}^lyt5s&-luarXuZ!1 zVFm^UZ7>sbxcsrWc!;-}-w1#j^%9|B;oZjF*(}|`9Gy8T68zhky3aX*wuXRahC!Ra znt#ahHy;9>ZL89H=CcDsx9=a&N>k`wG59i5@Vv)+P=95D#sgP|*W17s)4lk5{{R2( z5EbxAhv02u^Z2(hId%VNeh%Fxrr3Q5+CJgx4FIh)eGc9$_M`g{bfxLDUY5O}j(+!9 z&`vSP){e0MpcN`ipj~1=oZv>ubRXj1MvN(Jos2I**Wf~&7<3+#CP3$P3NT-I`5UtD zOCaEd6-XSuH%y^BLmfYI=B}6EHDSBHge}ST8?;Hdlc+O9?!HY?k`?^4{P7|C`^jyu1dHgG9zj5T|(ocyADY z%We>_TLQG)`y_u0s1p+KG9J_wiTl%ixcP&2_vz-3`n}ovdxJ0ZR?lz#YztnfbmRMN z?i<|)zu)+Nnfu_u*Ye*l^m=_e_(J~s?e8}ZzLal%{Ezzv=#E?Y=EsiTFDRerbu#;Y z6BGo>C%TVw-vp_=(Ch!~;7fVs6TR*--)}0P=spS)_l1hPGJ&q_0L!_k2zEp}Cpe3 z{}(~)N1BiD90zL!l_)Qj|A6)^$+!kRa%E^d49cS5{hEl3D8|2y+qwJTL1_Mi=Dt_G zIeQrnJ{M?w57NT?tNSu2csgqtnvb%)JPlf&dnvxtIIc6BCAKq|Bf9yBz~QtBE8jaX zTzv1q@bbL_gW(4UhLR5s3_Twl7}k7nU^w-`f#Jpn2Zm=K92gisIxz5mbYRf>=)mCo z(SafEqXR?bM+b)Xj}8pGK07c>{pi53@}mR8#*YpR`#w4_JoxCqF!_@M!;()93>!Z= zFg*X{!0`Q(0|Uor2ZkLx9ziNfP~mt6+TO?jtw#k_Km< zl(9kJG8TO&u2T2mG-!E^Yi}>Qd7#pk6|x&wAmGK5laSIjMnwQ*AM=fuFX1Kb36LDT z#MK2YON6R93RklPMa>TQeh8T2m$N`+8oUVZf$*S3a2=TUqucKfC{w$A=>+AwFE7)< z!k`uNZa+X4B9+WOASrmsYzO9nw#b5%Ar-%>APGc~t-+5de!0-4KryNN*r$ zTeL>wK}pcsb!u&14N=hmO*4Z66SR3%9^{4)6%BCz1F}06B+T&_yeQBORJuyM`~@n! zKqae-z!i|jk1t<9L?9YIzPt(MLQC2+AP%U^Wa(}Km8wXaR|VjkS7llclqiP(-vla$ zn-5)KJ{0i6mWvrQ#bg4Rz69N_B*VB1B+q!m==S^4=?30q3QAIcUW$N(LGA|aFm<}p z+a$@vz|iS*qtolo%O9XU5qW>Q<9>99edzXk(_Qza`JF^(j*0?!%L`kl>y_@KtY8hU zH@c5@dfWkXm=7|a>U4e3eY87AMWHj`N%sY)sZn2;4|ZmO*7AxlpYL>f0TE_C*je?a z)9FKRGsvXw7!?`jgUp9IoqoKm0ND?A8)&1e;FXu@U;(6xC=4v{=W^Z;&|Y?r-=M0) z#&yX{(Do}(>BEn@-Bprbo&o!Q*WR3|4B*YKAYI_iuA!is1C)DSz6I@g?KCpJ9oLz~ z65AOCsy#$t8(y10tAFD=jZow`zdA4&esy5*{p!Fl^{WHJqpuDO|GqjfD1CEa@crh% z5dF=8A@iF9L&G-*hS}d77*>9BU^w*6f#L2q2ZkTt92kVZJ1{7IcVH0t<-nl--GRaU zy90yEcLxTJUk(g!zdJDe|L(xR_rrlf`iBEU%MS;JJwF^6F8^>~c>lwJA^)cXL&Hx8 zhKWBRYq&u5!EwfvSFQ~F0;~-nO3*QYUx4+_YgYz-LC1uJZ(h4HbUGFsck}?&zsDVY zKoq3y4XRSWhc$?R+Uo+{aURW&?OWfLgop2N0F6xk)jn)}l;7<~uNw>KtO^RHoN0AfUI7CH#d3X#U+TAt3xk9r&m<(BXq34+o78y9B)W%ErvV zFW?r??N-q1qvCPQ#m1wd`3Micpo@xxJLt50egU@x=JO!FM)QA*GDolvw2ud5F$BJ_ z;9&-hxPzBK`vkn`WCIVt+klJ?33zdfn}H$AqSr+w2Gkeg;Q{rzG+qnuumE*fAO?Kr z1_|=;FS*Oy>!Jc4vvxT6m^lE{Q|XLRsp(v!0xH~I=z|WVINLEt1+?(0`(THUO8vnX z5*;ooHQ?=V9WE-hAO=T=i%MPhVUQH$LL3lVprb{l5fti&K?|E&R6uKVdtFovK(6!% zcwxfLz|dWy0-6HW$YKcydr|zCks*r}bSPUuubV)?i^+c(8M+}CS2Q2d0EM;jnHQVC zgZ2>@Afg+*o`DC{Y2(Ra>2(hX2z#LgF~~guVvaY+9CwfABNE-=KA7{fpp*j99|ket zMb;li29OJS-4n7{1739hVFVpPq60DjbXSJEN2foMIiNY$;|!o}(a`jI+yRm>9l!~b zU(g`{$+hV73*9~{383y`4ru--C%n7Tqxrc#s1*Y`^emH^fgubW@7;c(?^v7y^bv1 zg(2OM5#5nJp>)n<+H}8nSEL`n7!VBR$DWl@BVr4 zA?v~S(%e70&+%_#VE$)(Uiq}~If$AMU^QpEUmkoZe()(L_e;?J3Fi0RXN}J*pEEuW zQS=3@=ydnZgAe%*z82!X*?pFOn*$T`UE|Z8J}L^z=Z(*HyR>L9A7pm=0e1ESk%RAe zxWQ&OA7Ekr+?=B#!U$UM!`}*O+kv_WJ4If*GVE9gDye)_L_l(&VuJ`Yvn#L|5g67m8EUkh;G04uv|e7XA+$U87)pnXEjjvU}90PP9_MFZ!-XX2>- zk%0Qg9~37WA#oxBa{jImke^&s;Bj*H`$g_^AQu>)Wk0hQSiY@p&< z0aj*1bU1?rdAi*_y8V6lmmFk1_<*_7MI{70-rft^J>;Vj6Y!!2WD;nSUm_s*h5Qdj z&?bO_<|88UanZ(SUKD=<`7H#gL;{t699b-&x(>7exp55s2^#0qq6@*T@-R;Q`&Xpju0# zyA*VWQkFnxj*3QiE>FOVpOA(A#wWq++tG_76-aWzD2_k{6{JW46-O^b4nE~UDUMut zbf85N_TtEe#{g0!f%5_=ACO%fsSr^dsW5vXC43ykkqWaH{^CdmS{$h$l0M<$NCtOt z1lr&4@E=?rsW1~)9)YYTR33rU5K$hfFoX7th|r=uQX#TDQUMo}XF-wk^58?RgKxz^ zg(|2_Vt)VqA~&e$S1~@%e6X8{@(Ao}NF70_JOcHPd{j~xEf@<}7&CYnBRHT9oJ;RO z88iZsK_Ts7&|xZwMsNVM5uAXf5e&|4XzgELeC^*qOgP%VLZC7Md}KxksBe3O!}xaV z+tRHdha#MJ1~tEf%EuIN`Iv!PK57KKVEV(vz%Sq)(CwZ8I%(*bi-``X$?FEX;|W(W z>BopDCJh2!fJWrNOk!$&1Ppd&;j{Y5>fa0RtdL51t5PvF9}1YWp` zy+w;VP?vwMq5 z2_pjoxR+tjS)!uTZP%U0(H+N=B>>t)*ImcbT_yl(=IeCEsA#-c{}D992|DfGWEZH1 z#4pd#?V;1_z+&tnV(jt7*yGQ^lk%M&Ce5!HOP_)Eo`WVXUbA%9sHk*bXgoHvvMH+j z@WE5k#z#Rd#P0jd7Y@E>0_CWKkL9@Uch{(hFo(40fLfT$*OZTg27!%_cAq+UQo8#+ z^9iU@h%pDB%5lH%u2E5FJPtCI*{8*z`>^p*=8wvUy3ZLOK6p}^8ML)nfZ3qI4!Q@jxI{&w z`R2SLgQm_lWlriK^nW?Gao$oR1UPt0OUp=6#?$|%?DXQ0|}rNaLqqO z_@;mQ(RO8j9(kSXFl8g{@{Biu$K=RA3pe0j`<@bER2tKpKCl0GW6g{>Bhq#2HdUK zLgAS4(SxU?!442$Cggi#uSg!jz z_YIH@r$OgcD4**-s(iTdC`dW?iQZWt8e{-CksM?8QBh#NdGLW8C;?pN1|<+shqL6SQ9iGHj2o7wEI^UKeDNUEp`g^!U85q=eV+U5!Bf)R$3X}3D4z!V=rzcOgHPoS zzGmWn&Fs@+)7u8Jm-!$leSpp(V?G2*EG{Y{ki=rc-*Xc*R2iZo0}3=71_lOj4w8U4 zruz^mDTJs97#}r022QL8AImYjOwr-K$9%kZ;+1pj~_fI z%?grXc3ET4{hrxHMTYqU#O>XOj1Pkoj{qp~fU=Ft9usC46@}iNU=2UOnWy_aIP*Yl z28D((s0ZjW#iIKf^WlT z!5GQH$jBJT)7_(z!N|Y>*~fVPITJ(U5l|@ys%9YlYtYH-`~s{VZ$N`U4xsU%2+#rS z=w0oE!)HJ>kN~JR%@fvL>e2kno-x*=In;-t^>&G8IKMmtxDnp{Tl*NOKmDWE6*>}h zEZ{}bS4d6B{Jr@IkM{lMe-5QWy{-WPy{;?)FRp@Ti#b3ys+aCTt^%{zL5*V&e!&Qy zhUWpf8dUN_Fr@tFK$QP)aJ8?&YF@~I@6ywiSOXC(xctX-52?P7nkBlOB|u52+ZjB02%bH6 zQ4xS0ef^ppRA2e1$bb)9I>CMLl%(;6?t=$Uuo;7@0TE*t6$#~o-RF!!rO1VYCqc`z z6__V=Efc%IE{q!)<(_`zXvF8RNssM?rSM zZLwgUFahih6$wza%>1kS#K9B1Fk3_*wz#MWKnyz)Vn>9fs87 za9eDcCrp9(MFQ*>8IWH-!EBL0*a8Y*kbfk)uYp=~V0&CtL^xekWV(+r`l!epgvHJ= zh@Xxc9|w;)f#L}iY7Wd3W`O(yngx|%3{es2J`IYm!v|0B8lM0KI4EvhR7AROfWu9K zJ4Qu9IYvc>`v&+p6aj20;JEQI<%8X)jgKEZDF*kF3-g3IATNPTX1>Z8q9TH9zC`y6 zu=z6FIVv*Bueo1<&pZ*qW;&?y2AO}>_!zSJ9?TOKfXqJ%3aaajAu1A}LNxCL1D1afu~&oP?}Xf*nQsE1++Q>6c(V}_8}}j%oCP?%s&n? z{~BY6ij47z?&IB`51wG+{%U+e`FrE%bc#KrGiXbY45Kq>az}#E8FZ|H2%|G7oe3~H z%Ye#0<1;U`9)SvJP|<-}+?{EDlL9MDTp(kc1>pWb32J}9B;duT_mKX;F&7gH(0GXj zXuJeGTEcveU%)*9#FW7pII;Q41R6yE51iNpys-WK|3A1#-~#Fq$bSX3z|jUyxWIzg zdju(}hSWF6_1{*I`sQc#jB~+^sbEd5 zw@ZA&cYvISwHAzdhf)hR{sXBj742;WITBJAz670RdjwJ!ZUdzUgzaa}WU+zj8W4W* z5nN}Y)i<#EunlY;xJ$GW6k=^)Cm!MHo(6Jd9Nb8-dXRBh9FWyq0WWqw1&_$XhoHb( zJNqE|AmIzTh=pH(mEj$7_zFOH(C}4&@Sx#q@D8*v5ab2|;fqwC3S#qL;!|h>Re%903F`C2fTNudppP~@c3apc>FLT;Kidip#0Dd3YTLpCNZEa5d+H-0-!9> z4tBYqi;4ojKs(sof}rb;1=>M&fO3mN^S^>JBXHb8hZ*@kfpd!tXxKj?;DtUT14C9p zuZv0sD7Sq42uhWp+)@CV8iEWn-T@2p7$4}K4hqnNFC@B8b+o8}tS~-s@C9gA=O6&%nSC&@o2^bVS?>(3xHTw}7`b^}49Y1cbgYege*?pdD44ZaI1 z)EMMVHa^{9w2gN{gmTqEDJ_3;CornN;qy%rQu_It-D}`@pS}zdL1~Lb5tZ4I|F$5Tg^bL zzH?Lpx?Mp>;)5=L2G{$ppri3aI$cx}K($V{t3aoZN=&yes7aRrI#jINRie{JC8g6x zMWx#p)WQQ@@NLlTs?hzR(?=zz(?><8+gGO3MWv$KRio2Kr37@7R=2N8_r*@g#9}At zj0;zTP9K$;ZeN{F$YqwDE-D_~t`?m=;0;osXz2De>1+XC8w&2*9O&#(0VU>6P(Rbx zraMO^q_afDqBBIrrn5%{bh!+ucLF+B>NQ7qh>A^jiHb${vF=m+OAd;6-#Yk=@8AP* z((f;B28#^3nYoRB&Ah=u#Z z!Iv`KE-EtI7dt`29B28L9Fzl%*mQqA_>Rf=(!mFE+!qZ)R0Oy`7=qOaLD@w`g&Q=8a+Mp@h!bEw zCwz$cG-&El_;|Mu_*QsaSdIUK!tvm1PUB15KMy_-2g!ni(4hMRCvDS>jDl%8*nI^fJ4!x+egL0*hj@e*+<0y6q=CMAT%83uz(6o;XN#% zQ$) z51=Kyh9xQ<#+N{*fWuV8_!2}dG&H#{9(*8a7@{Hq4o?s8`39h{l;JK>kx>SPJ}CS^ zVd>F*LHQ{6Rb^1TfI?CP9+Dp5kOZBiAOa3a4J;w40}e?IjF8j-holaUkhB5IS{UCl z28G){V;2<@Wgis{Wfv74P-q&vsMvr*QUo57D;O9Ug!iz3E-7Z75daR!5J*Tmbc3=V zC`Gz3#;7O=)~KkUh9pQH9FiiPB`OZxAJIb6#jr%h0UVMZ;E;3yholHt9VlHMd>{!C z2Zy8sIQ4x5hoTQSBtbDL0QQdqJS0UR=>;B=AYCfL$2(nAT)-izfE1DkABcksRTXeZ zDxieqN3b~x#{arOB^D^P@)_Sc_)O^FOFrXE+#p#<`1z=47~cZr6i|3}yQr8LyQt`Z zatJ77!6E4a4@pqPExd;XbW<+#j0kW@#y~>S0(6WPI8E9x#;C{$zsCqi2XHvLfC?{g z_<(Y^jqxS!iwEB^8HT9XfP>BjoJK)r8G_0&P&EFQ?cZH94pX~&dWdA`Wi18(8{s!l6 z?i<}_L89<*1eJk8AQA45#{Z0Ob$>9vbnux__gPRO36cYqk2>I-tpW~b4dtW8J}L^} z@RTtIg{+H;4mb>L;9&^5bX|B4%N_;>2Id(F;4n;qgrNbrBnG8M6UG=73Bei_0gObN|E4j1eGS>6e)ob zk`iF^1rT`~9HOvNQUxrlU=)!x*FDAy}g#V*CwMa--EX2H+qw=`2yvfP^Jd8L4AfqM`xL*#_VotOHJ- zCSY~QDN+Xq1RRz+@UR5w6anXM z9dKBBAcZ9?cZ-0-(gPlrpjsPL+IoOPO9YZKK}ix3mfRnWZ-G;!gfXb3fz;QaI#9s) zC@60j9|fmM9e8Mh8n428SU~Ml<{1Ux&@6$3rUK}2PHOdh0DVs8j*l?E();P#%V~ zfIy|J3nEpbw15P_Ia~ys9$mn7H)tC#C}cg9A$7O}I5bt@p$R%6KzI)esN2LmqXHb7 zHIUE*#estGU&a^}i|!YKHK1Y-oGPEPfZPI>w-g3#u#+`t_e6CHNfSgjxwkn1Zwj@>q>CikpYLH5A!+USK#)K zjPU#B1E7P3eQX;*w^sJ70-bQ`q7uOjn(U5=7e3paqv8|S2_7SiV0KZF==5dj_ECuu z_EC}Pbmi!FQAq#|*mwGZPFze8_EAykbQS1!QORI-QPJr11zl~EBkZH1)9DHtlPO?! zQ8DQB1zieJA`EJGxq=c~1+$BaMW?Syw~tDVu#bvOr>jOcqy^3FqTEDMA7 zD7qSSLmJYc&90rkCf$(MvapW|N2jk%cMrI;)9Gpf?jado0QHbSeIiH?sqqcy^nFDC z2y_N=cZ&*WDR5^CxUUOY4+&a59o{_$Jh0rk1$-_9|28}RZElSG+rn7*xA}2^cf1~a z#KFJKjS0ej2x2pX+5FqwSh+8N<}mrUxv?F5#KC=mf14XSjKRr$f`6ME*TIJzUJWjrP_3Zu z8;A=sud_!5)KBX6Q7JLL*y*EE(wL%B0yf1*rJylIr2uS%k4i>kib@7pzmG~z_o>Dd zl^l?ExQ(C=1ISFU@*WjX;}^sQ>1cceQrX#~0%{6(_kiP}6B08ZPl7F*qVfY2+!rA+ z&KD1Gu;=U!9GO=bbdI93$}iW3aFU_;)1O2oB|nD zxzK$O;u2M;ji9Q$vqc3|YIa}mKBx-T3q3yOpejf!B*;4)G{}yoC>TOX0Eg=thVSI~;VTS-{;OKBbZwolX zGam*GE6uvk1e*ScX+9zWN-y2lkGFu$0F4XvZczah5TLODQ1as6CI=}2@>szoz+(>X z8wbI;p6MWn&A-i!8OC5a_<+Os7AS9q@qo(!P)3Cm7m)nd8KVL^R*RGSgmI3F2D~`v z%u%u6-{yuW5{!LRM8Ks7AGq{@ln`$G#;3a>K7@%T7>B4tbRPnBph2q^z(WtOx({{V z0*5U$t+=R&G(H7|?)PVnk3sR->7$|n9{l*#eenAdaK1BiQBg4d)qV8)5^(;4au0t` zQK^8i8&gyiK=IZ197J{>?5t7o`Tnf?ME9@m!%#DfPZ<9K4J1I#0CSImOaQSUZfSfD zN(!8ylk|>qB1~{m5kWQsWFYADAdo&#s{~;N$QRv*LHZk?gV<0rwm?b%kYhkT02L%~ zy$}yUxgs#5Ktm{y#0D~~`w%#ZcE1A8be-zH)%Y9~P9W18AA;=p{;csS$lsul>;3_1 z?Q|c6gyr`Xl^Ww8h9N2{;J^coL_@hCUw{sBF$Rs8s2CrD_#JFfXN^hgALaB>Nr8J3W(Fv_VP=3d!Ce7z9@LCq;5ot+NHPG~-}n#|FrYOU+y{+oRBXCI zmjI+dqPzP&XgCWJblqFP6$&_%z~$?Gi2a=|Dlv_ZL4gdu2_WSA5=as2qY`5nq7nj{ zIsy+j)~JMhe+KdbIK6>Jpg|nuFaZzbfkF>td}obH2sm|uLJ%~t22u@9oe)DnyFZtJ z%YB#xBxt@b0hj)qJ}NN~_i;iD0!@Veg1QZ?<1o}UAoF3a0Zl4G!UM$^Pyj)Vf#epr zdyYa4fdnwbm~O~5OrT|{#=p8lR4gE2$$hZ<7N|_>J_QP~?pNK=1O+k}lBhuW92^V+K@}2|d-(e^DC=Njii!a!USP(7b6od{ z&Ki{nXs!oUbKt;$xF2K;m<#jPQFxewYCujO6$5yfMs$Pbnnk)nVG1_}6nSt%KzBcY z;|da@&=lvRVgOF}5l~mb;}~uTNZ%509Se2~$Z5~IOH@jrJOg-ehN!rJ0~D0&4Z2T( zi%n4R1j(qJH7XI1)CDROAZZx600kEVCfx_Wr>JCrdgI1Fx#EERazJVAf%XBRG9jJfK;>M#Tgv(?fJZOo8YH1we`l zST`j6p@9x+M}kUSknSzub{aVFK$gM`(fFRC0y6|uR)P%y4UR$Lfcqdc7HYtQr=VdO z3(%l(_lfQo-8Ud%qzX!OkT3@A5rQPS?xUcB;QJC4aH|DWfXZ}(x*9Uymw;O?#y^Zt zfd(+XF9Ek%z+6xU0|_67*bUVTaR6wU1vn+TbVDjFQ1b^IT%dq}8UiXmT~sU(Squ`A zP=h#qR9xTzDg#c97U0wfHwu&*K`kh-xv(Vd0?Usm#(8v-gG;D&%4 z_pEyhxakEp)kVbx5=Gr1Dh}MBO95QK3Go%U{sw1w5lHNPUjn|x24o2&aKY)%qWd6d zTHyN`q3>n{Pf-M~U1U;HpW1@U+HQAmJ*?v(-Ei3YU-cHcWVae!P5 zF&ye%f$vb`K%onYA`tDOA^`CQ)Cf)=6&r}NIcrobzy^T=6V#>z8v_ayPAv-S3Ah;x(c1{F@4SfrCv1SpW_fNMwV97pxi79Re5WaAQE`A{hf} zlfm5rG8JqLq>ck6cu;8oqPu-m0>Hrvno0`*1u|%Sz!)?Qwguex=zh_C0-maFK(aF= zNFWW-gvO^}bB;m^i|^0C!R`PqAsoIh0nfOClP@TAKtoqxj*Cjd_a)%Y1dIz!gU=vI zuhU1x0bE9iK+6cw*cUWNK&>0FL7-p;nF{KYz~mqS#p$CW0?8+wH7X9!0vDtd$rz9W z;KqPL4{pq1NGgID0`eS^ArObdjfqk5F^*AD05^<4hIQwtM8KQ^^B~BXE-Et6G*F}B z00~6U(0zA}N{aD)!x|Nz?iv*zW6;zFsKo+WH58)~10JvgO*?_AI`FWQF{s*iQLzCv z;Ja&7JdDp9)~LuBpEb-;k?DSIoTFl6?4sgh{0iKqk5SP8o%vu461OnEX&j>xUHZ6<9YI5Gy&{|-qq|RmwY#W*DhALJp#adLu!ApIjZYnXFMsi+F{t_C z09w?;e1QAM#h1oEyKjMJo{WDTe9UTm>)=ay&<5dyIVukF2OmrJvIre~CC_~VoC6gO zzF;*zc=3fXC`+qce8GH@8#F9;;$V)7ihMVy19PI+gu(d3!Dp<-AG(iqmZ*3fd?0Cj z9JDqSH2>PmVt??xJog1~e@O#m*rAIrj6pj}WG=p7z66>n1TV_dFus6hjt$5hkgcG3 zUz=W*Tu?ue`v=Iepox^<%m=tnbRP$qc>LlEV-P;k%VKYQ-1z*#2du`&LA4dgghSmI zLDM_n90KXHf(ALj!x}j%pqZx#&{i)#(2XjP(WmYUuR+6ZGTjF|{J^UZ*dR+4+(3ur zyx{0?W9mKxn(YNGWpHBwtpO6~aAO70935_8wGtg}98f)+Aey7YjjO|t8$2g)5Uh;{ zBrMS3#tWi3;ye8KL8EDm3=AD%>>X}=koB(j_kc#!K%;1&5w+0nH_cBzG`=~4vdaGe zXnB8Fcy}mAcdQ8iHYWaUUW}ljBhcUhs8Pqi&4~#-pvAw@Wt$!3Urzdl~+1Uf>}#C)g006Rf}N1R6pU;os&38$xq}4WT)~htO2IeR;ZT zK|2h5__rB?N70^faDM=gqCpwV2cZmB(2P9)Hb;=-I9*gE4yLF`aPV()WCL;dw>h$d z1wb6o+-heFxCz6*%@K4eJrDmjM-I>=V&@icQ|90U4o(*pkSN!|6crvAha1iTA1BfR zZW!@zbL0iB>Ez$$$OF+Qz`xCr?_i3G07xH*!w=?wCtgl;9|P6>s-dBwS37&a?K$QH z-RCa8Ys39jg3Dae8_b01(T|=v9U4t!R`~P{QUg?558n+e8|tw&wua% z3wVXO1V891K99~G6;S2Sed6Lvu)z?s!0G#7BgC{9Oa~tlGK~jp8ffJLsG5hH#(V%` z9+KOj4mz@`~=_CQ)Wl(-FSl1pa~xG@D9y=3KO0F4BJj(7r%WrNo8T7bt! zTvR}r9W=8IDmFzxE8+PCWDk4*@AuW<7f`(bVTyDg0xf{#7ts9x67W&s0Sz>ELe|@W z3PwX06&`RYV*^@wV0@yp2i)xh4dR2xYg|-Zz=EJIk})Vddw`-9G)oI!;Siz%a*vBK z=-ze{&{%M13%L9Cng!$}(6AU^vx|xkcswjd#pZQ-aBqtWC@+Qwyf8kFGX8ajk%0j^ z{&faC{$K|2>*e$K!`y7c-%z=v>|{2=0ng3e~F3-|2BF4ZSIWx z+x%Jhx0Q2%hrqz&V(yS}v4hVz__w*khQ{1kxlb71;@{@Z#=k9`7o4>_V^m`Jx4A>| zIcVKB|2B6{?hnR3Dmwhz+_}J+vC~H-f`6MkH;iM!zs;S;xI{$*RIps=EKv#J-{uY( zBjexZ&JP|I>po^2qGDnU8WanFjW!-OK4^T3U%*8LBmx>90`ITs0grVVpXh`P{&gRM zjyPU?(fA0It3Wv*l=%|(q3#o)oiX6#56(uQ)Ow=(=E2u2jgLW@2%MGv^9w@OpdEb3 z(tYgW3+|g>{f*B+MlpZmK8D?tpAgLlAF>>L&(ioDWE^;|-=g~23j!cXYO> zfG+`tK zqY}U$euF>cBEQBFevMNgAs>|h5Oo|Ru5k#&bWte)bB;nd3H%|lprVLB`~<(oF_74C zF!KnA308XoWLgL>sOW--f$d6B3E&UA$**w^BnGvm1Z4CHeuzCG5I2EM3xC8fFr@_) zHT)V-dka9e2(+|-n!NlWydY14OnT2B{uE?x_%nWu6Z|2n5P$xFs^Hi7z#qa277M$> zA7Tq~6TikI{t#2J7X;_D1b|{d&_^Wzv{*EOKSULzq}Nk{U*lD8kOF^*E?A+)E&dQ_ z5FX_Zk%d`)91^-3S3oYg#vguxU*j-{>7tSV=D4U7fVcX-P)Sq( z4HA&#JrDto;;@VS;dh_~FMs%5Xqn3&a+g2sGPHQ+7o5@p+IiG`fTQ_`0Dn&$=t!s^ zLj1j;jB)S*Q`&^?IV_;$+I_lv3kxW{Li!@0R%rLX?$h0uAsrm(%nzuW1D+M=J_l-* zLpm0nAu0;sm5%rL*ZZi*G(H3MVnGWi8Xto?Gmw5!_hk2V19f1HK`YgCKmsbp7a^GLRW7?oY;`Ri|L%MT~zN|Ah1bxxaUAVF4wn<^wFvKRoz* z9)h;HwWvgZGJcCn41@x0Oa%{-wy4xVL>eFzXj5@FWVd(0GnY3nOUhF}Th28Qh36KKKAVJm+4BQ9#x1TupkpJKdLGBaXhmB8xtpr6U^MUTu$nCv@FPR|b zgKDYI6j;)t(gO;C9`Keo;~q$O^?-eB+ynM1D0LV^!|RxFjEaeI3&g`9pMx}`G$6b8 zs7!!_&wX&vOo0T=9&mUcd`Y#S0gW&}2GzI5r!KxQhBzM-TA{{0Dmfqr+&1n}DPUw^ z;64l*7w>t&K$0BS*Yf`-d|K%>nU zUx3r?Rj{4RCvmkUU@ZXRYb$Z z2q;+^AAHQjeWSYtoS1q=K#gw^&|Pw@#-~7|0|(#9Uwp}Yfcr!DFJsW6RvF_@2cNSV z|6)D>&2gadfC~qoOM;f|g7q;UFh128qGAEk4LYsn;!Cg+&~UQxMdJ&gg|MK@ta^DE zj87bVC4cZCD|iY^=ioz0<^#s(xG!{c5AnnBepspAH!N)Az zhmFtkpJ;yY59HEA-7(dnO@r7O%PUC~d7eV6+ z2SKy)5Svs$!wbj2rFM(T7Dn(zE8y-6XvPaP-T;aUP$O#%xO#O_2>^{W>;~O-I|V#d z0v=~j0bP6zIu}c#g9$_lbT~1BXpRmirj96P@Gffb1_vh=kg!096Dx@3=x}1|h+^-K zQ4s-gB|4lqK(s)I6DNq~=y2i!jV(xYI6=l5;yavpyAO7Ffd(2*fVR|jL~$Q{!4YkI zro)NvMadc_hVG}apm7GsZXwWlR2HDE3Ee&_KHxA4fX#R5KqqcNK7_3&a8Xg|J_H^< z2Y2I8))ly@NOT_pkNJYSSluNm5s(E6;4v)F0@4sjRSCY~+@kR@sM-R}y?25}x_*E! z9_qf={Q@G<2%gLCj8U-wk7ah>>#R}n2!vLZE-D(~kl}YwCj~OD`66W_69Z^B5qNkL zbZdjm{}L68|0OC8FFYYq3Wgyn0meW6m#An2hrTd@2x`Cu4M6wUXuOcw$ix7iTJkYI z1gYmhvz;Kbz%Bt<0XlUDqWJv=sHGpefBi2}0a@wtzeL67#Wje8g7F7qkc0+EKiDmM zArcx;34`F!7povb7EmFP#%G|3K}a(Iq>r;iB>|+DvqmN6MJ+_JNH^5R;LsOY5Fuo{ zd_bOj5eSih+x5Rh1>!mjhy;?2kcJ0{IY2j# z>%5Tq|NlSeWI!3vDDVr=4eY)CpuNulfuId3FF*%ngJ(?w0zsSROJ3XpUG!I?;?iBC zk^s_|(;1?Y@!|+O14B1x_z&a&(40W?5e4vQXhLTTctrwuj@v~Av`GfE)}Z?!XzaMt zMI{3~rUIHLO=goM1ZmoXPmd!Iw-RSx`CzsRq+GyN`FD=3jGyg@4I!mV+-@jBg%%&H|GC@ZrM; zkZLgfqx)?4A^s&-89_EPU%L3x_=54v#z!D~8lQql5Wo8ncnv-i|B|ar{O9>kAAHHw zS))?Y8KY8g@DbDh5|tQ`Do~lx_y}Zo<5Lg`5(Dd8a+L+-j)RX_j4yx&JRgB=erbH6 z@hOPK4{A1O7{BZeQBeVv?K1plJ9AWOUiAL_|NnmpxK0KYiV>Y5Dh41v$etGk5J}Kh zF;IzD09soZ9{eH_Bn-)6-8Z^_{oeu^k(dJ>vHTBOlDG%FtR?h?{?GsayHA6vZqWL> z7tKc;_}Bbo>^|HL>ijP`%y{v=@qOk4#s{Hce_s_G7zevgcmDwOQHTuwCBGqF2ZcO1 z4jP|>yxjO0L>m7vhD6em-yHmFPJmXm9(>6G5^a3W@Sov-<6{sB;zOfSfPcwvfrBpv zKv5~s_?Us=|9_Bd<8u(Ja}IdLjPZ}|Q=K*7kV@%3+I<%kul!4Hfzr}N=G(?MAaQGa z5$dlS-KYMSsN{4X2BjtbCAXMBN$KLj$4nrV;8?ua_!vyz02Mjir#fR)9KfnUX$rB3 zQp4Csr3N}A+U=rJV(g+)5g72|@|h-G_|tcc128av74^A2ET_5Gb{SQ=0JwsOxTa9|Eg_1UEFL8Q*M# zq_qps0KeIN=>HbTurJ6+aH#*^0v^Xb_=p2!G6zTxIM^>hgCAzH0RNg30tX*~!~X(U z6)5;Ysu=!*Hn*4<-vn)j0&PJ6Z7%~C(GD+8eEa{uyGA9z_$2?5pYqK|6uMu4c2`0c zQ5#>p_`>)k_YdO`70~f_3dZmGmmHMu1}#&6Z|tKIa`1t?afph<#n;@2jdN5)x7fsgVB9WVo$J_AkI@h>^Z z$bX*s0Jwd1s}rQaqG2zS(`Y`!N5K6O7C!jSm~21<8UM!XOoA4?dIxb)7-x^RGF< z3fkugYVZ4~NPto-hDTb7k!Y&s~D{E4#8m7WCUlM7sfxJ8RsIrk~q|To`1=8)NJz;T0lPs zXXy*ZKS6hD@-Mm0!oTJt%fUx12j8(6Uo`#)$u^LL1LE_a?>-*Se+sR|1Dk&Ytzbs9 zdO+7icKeESyYh60a)fo43WRt61Wn`}e9zYW(7yY4XNii;!3S*2pl*^#Zy`UZ3vloq z%eRC4C02o;Rs(3vEa1iewM-1%#|}PV(FX0o?u9Hx25oi#H7AlbGl7m4*Xf0d=aGnD}2E*KLq9-m}=QHwaJWk^;xW)$wf$)p`8n5`n9)N6O1P37`5Wax|0UT2N z8rRbJi?4!0=93+GK)m>aC4bm!a2Ol|83_&%jdT3r7a$>_aSJJAF0+Hj)g;32{Rq#PaynxOGu4Y0>w@N3Qiuh0c~`~?HQ z2FT-A`9QoAg5WrZr->^dpMcUt@dbPSu!m5Op9T9hjlUQa`=C^D(Vk!9D1X=~kOwXK zHLilxVM_&{()f$7vGZ$y<{4!mu?>yr=7S3S;UAzu0Z9}eAZZHZ_0M4Mk&pyHUcZ^f zpL35t{39ri3-~o56(H!mcnwxie(Cje;1?)dz%LNEfnOl;0KY)y1yH^L6CXgV2O#1F zfB1K>tE^mHR1yUFHU9ByoB@TDkBS30IsF#o5C6fhaStRGqf)>Cb~H$_f*{z@hd>f8 zDhUjrxD5ZvuW<&Uf&nDwqv8Nfd&l@dsWto)A)<8vxEIye1Qo(tyKKc z4jg7k@%aNB#^CbeHz>~+fE9pKw_r3v_Rag8;vP12~Eg@`oQ!<1aYD$FK1MY|RBwkevp{%QbNHz5_)l zs8B&J9Ux%^jtx*D`5Ba|?fJtmg0lrU1A)uQ4@kiVFDxH}yk~$~X!2|P1?Lz@P=V%+ zKtTh_*O0;!#3L%~{*V)F=fEKa3Oi^`()^B*zxCR`|NlW5z!sEOx_iJY4MEqj@(WtM z@Sll1NCvvk%lPCD(Di@(i^6(KR5&`>K zzN!aQ5ks-@0cb@J<-^Xi5%^!CBGBu`a-2=zqboze3y}rjQ$sr2KvgYLoeY|B1?dq0 z-BSZTPd`M31ANF&^C6bd@ZOC7kZ$I|w=CNKdcFBwtv{A4^}6v}A1;#aKDG`+y(4UqRtK(`Wr)}?@UdGmmqCkzY>!J)k|DstWLv|slIvVcaXKl9fybUT0sfK)&u zx}c+{G(Zf{(Nmfr2I%N1E%2c=&~WI8Q89N;0f#rsT(GAw z@&jl97K*`IUU)MwfChe5{+Fo0u)>RL;3KLO4xc##RVxCe1zzlCLQ${qzeGjh1?a}q z<|82W&2LN)@o4})P1yzHMxSv0ZN3bkQ7!&$v7nJE&?r(UXqXE$ti^re;A0RQG^E9S z0<`p#f14{S_YLs=G*>q80v=GCn17oqJO4Ic9T&P|i$nJd$o*2?B`N~l$3T4`7Zn2#1C-7TK@3njGwMFp;i6&;N_L=x zXaZt@6qte-AO&WiP7X-Q0>l7GS%MfKDJxKy3M6F%Vt}MA0$#Od%+@qY1a4){nfmEI5)yXGT2`#`A};$Hr3UjKR>SPXcq!0FfPw}HoR z{%u}=3_SkuZ}a+V;PJQl9Vq>}sE9Nl2VH$7f z=9DWVs6+taxA7BX%1CJiKsL1pN zGKY8n1l0(j-5>(J5lpV#hrnUleHk2{K`aIye|sHR__u+=^A|WgeXO7X`Ue!CH$c-F zpi?_Q5eA8<7ml+TK^-*ExogdbK?NwNMpzaf7abdka33hIpyuZsaDFzKi9J7qLKCEi zUiF*KYD(+32C#opX5jV@MfF?vIy%>HQ^5Y2G99~r20{H+xf1L&dev|K{h%yIWc{WD zRg6-<@j?Z$*KaGp;jJ1jH)o+iwL78oE)Ng`I z$*SK#*P92tDA|BLKR3P+U_w3*l!u9dp}R)~bYV5*U=$6|)zywHpt)lZGXT=p=>@H> z^-+-t=&Vsuf$i@)?xJD>8s3Mk8b9u$;sWBoP~XDH&^<@R2Hfi9>E`baXX(!8=yvA; zt-|kRU|{fWKE`qIHB0vo=We$j#-P2BGTm-}j1Pg@i`{I-M?n+R-EJ(#$3ctmzwTcXjtK7z(9}V|i`$zR8M^nV zBtXN`nWfvCqdS(kGrUV?~6O`q7nj%(&H{F zF(4Y$S9R!hQE>pT*;N5?LqPptlNZbzz|r6Wik}Qn{Aj@9XFFITAmGJ=_25z`r1^-5 z@zGAVAE3>~p#2n(8#+Oo$3!~Wx?NNvKqr`Yy0L)V8wQGL@V;Zv(l*dxm^mscoo=9G zi8R0~2;6u;tHX?4R6;u4KpjQUUbL7_H<9LJpo51%dpbZ{6-7Xy)cjt7zxB?)|NmbL zfbP}=9XA2mnE~2&A0OAL-RaHI-J=4Enb=Nemd;=v&<#}=+d*jn6o-&B0BReewkJP; z>ra-oxZ)pVAgl}5q5?9hy9b;#!0{fy#J~{V>&OD?jUnRRBjCm34U7!kEh-VvcwYl% zbqjP?uz-5!Au1xBH7cMTEHa?BcO_^)R&S4r8Yp$$)4ti=qY?s2&^{`l=ml*mG3h?Y z58BRe&{?CR(_0C;P|c?MI6tUs0*X%+@LCYiq}2;6P=n7!MFSL(KA?zHfJWp-NDP|< zybxapjz~}r>uga`0a*%J*#RmsK<5p1wy5YpL~S}-RKRH-G&%tFKInv~7H~j=7Vd$T z@&9#skFNVoQxpFHmLjn6_%jImY|q-QIY6%WC=$kDNu1@ z69C#M`Jw|9eLgBKpgYq*_wjVrs3`Dn69jLRgPdd)3EBe31n%;K2NE2a!R+HM;Dg#3 z__sN-g3h7g-xkOMmH=&-gE3%-U^#Mf-{9Zo$aN5Ma*iW6jKSL(qawn;EfO;70N(Wm zRl*Ne(!2+p))_iM$IHgCbeHk)x2*@QeFR-YaR5|$f&0ObwA+0MOoNUm5COA5DOLi^ ziU92=aptzy6(^c&ou{nMb%`1c#iCop>G z-)|@%1a-*4rQZvY)r_F(2vOWQKyyj=TChYwz>ANoz`4W$R1aAggZ6KG{OAt&1Dd!u z4pH#{)ui1OEXFk|5uG(E8ld}XIxV_uR5Us(KsOpGbb9>g4EWQ00F;AuU?sr|f#w<& z1BOmW!B8S*oTH**{L}arC}u$AGiblmYng74pFw+#e}dQl+ybpTHqKEAF)mSw0Y!G} zff7#8I@y<7Aop#90?8o&6gr@==`2x+d10~&>4d zETA&|ZzCw1gYwnkGmURRY7qGg)Mn}KQE>s)&!F{mpezllpF!m?C__Q3Vnn_IogQri zy21){45|j`M7S3kpg#RJUxwx*JdgppP}l%nEJy%4KnFTm&J{912hL-zpabQ6Ksm#e zjenaj2RJ`L#^fMbs@sfzn=2>x3D7~I;NdyQ>2j{Ht+B4W+&4grCBQ>-kR0U-$x)zz zlTOgSa|cj605l>j1FA$oS1*7Di5);q0ZHNpoMMVYNm|->s)gqvC6`Wa&K{bwx zN<^=VicP?a*5%+-=>V#F#hN=Qg?4a%G@DlXvB zC}{Q5?V{oX+DQf~(?QLO78MUrdd3u2B&IZ8DeWaAg3|;FTfAp`(1qL1TP} zz{7yhj00L80+xjC19ye)19#;FjqQP!hCs&zc|bIHO~~O6U(n8Q6|go?j*;nz+}HKhXl$H;1R$Bb)d`x$~52xQR5p>jzQ!fP~{1&5Fr&4 zC<8$=4k!;HG7e}psRpP*GI;TQIU@uAHa>8E0Uf{?2g@&Epc5CN`2{qf?FPv&-D^~0 zKxbKk4q=3hX}ckhX}ht5k5~j{0dW3t;{>0t1{u!=pS=dD<=l8dgXV6q4diZ+acod~ z>J2CZ9PiztqQ%6(pnVLy*hjtrRKSAAs}F-yy8$%yTY#HZE-DU=pyv4ZoBZcMyQjKK zR7AMXLDD{Cuosl}A%nf(w2wU83rhE(VN>Q4pmreCJe_WcJtk0lY@oT!1=Reoa_a_J zBl7(wNtQq>FpYp0!Jv677Zn{)jtKze7#(N@c4`?o$5;fsFjxZ4F*eOdL^@kkplv$? zMBB~+(YABwgtzTLD}2GJz(oag>OClVfR1TFWG?VFO=vSOxjRQirq`Wmp8}}0Hw7Ht z@GJ(IA_5HwV;y3LB!cGS3e7GmG78OaL3_z0Ko<&kLS*<`{XuPgX>dcX2kd_B^Ia^K zz4eR+?*Bo9#h}SYunth=3yxXvOawb<`az(>oe@NHbhtBhAM0?34y(IEw?nu?ht=Jo ztFhdnm6SWQl5&UcgK&rJgXnOFoVn2952}_xfUaM3<2ml4A_Gdz$6ZuZ zptKH@2KVSe{q!yd1_sb50H`7Feeg9)^KlO6?hoDWu>QI`tiR3iy+p+X)JLD%37Q&$98E6}-^thAqapz+xAQnU!&o}q zcp#@$7*>IT4bewOYhQC5XH$W+uXjS**Pw-DNK?j*Z&X;2$3qlYARTiZ76t}T{cpm; zzyPZMZCDr>dYw7K1O9IYnb7N^QW5Zi{}3ZXXs?TkK^9BEi$itbj(QCERx@yq9CXu% zKWL=mJ&QZ6{{kBC09}p@T5aeCtJy@l*`PI>1ZdO)QnShQx~K?%a%TvLun2guaT_>9 zZ314X?*+3QKr7imCk8?t_2T^@u((ga3)a1ipjpV0UKbUU|0OCVp!L%r9PpxhJ7~fI z-1;}^EfYxNuk(8WS(0{xC5^w%?G2Q}0pfh%7xYn4NaHWQ$pcdO1-#zF^8f$;S)ePO zRRTg^_<(%fqXG(^<|D9ylQ|WjNC5@xVa)ij0LO>P4qWlE03|-=urPqer>6)1yl21hhTo^gP^c333&0f2JF1vE#QMadTUg2c7yI4Pn!_l>!uJ8_Cj?l zSibqVK=UyUP-=bN+X7Y^@SE(aPSC;=JUm5;y`2t$z0j0uU9NEgq;MRNuG|AZf zkEP}YXe36bdyUEg76t}>0Us3^{_qo^$kS>5>rj+td;n%1zkmyi4Zna7OAbT} z)gJ~m&p=zo=78q#Kn*_^6`d@BfMC$jj>d}&P+%N(04=_F3p&n6pc7&bIP~~i_x}6; z|D_3N-|JhZouE*HO81uju|CV+{0ej}(LW~sru$%q0Dsd$kS)hl`571*Dp@_6PkeCb zzS3Rg zFW}M(T6D!P=+nyp74+d3VCjaa>+YQcUX2fxi9wQSJ}3aP*7{VCthtK3nsNU%+Kc4!E2EZ3L5m1gdZ~DC&9Qd_PVGfWC?&QTfxG>5b)w-1-Q&&fn4L+{MUiM4b%h$4O{m*GwlOk<}^iR5h%mM z2E_<0N&pRty>)0l?9jPJU}4 z_{@t_MW9p&N=k^4F;JS+zTCwk+#Ahk;QYTCG%^O7K0o-Dh56{~{m@hfI>(uXfgujm z@oqtw0&Cx3rso83dKTFP3Q`^{={W=?JqLgiQ;$jnh-y(ufhOw&P&EOnwsTk@`(t|@ zK~*=bvH+df2-@ojO5C7syT=RHU7#KaH~%(g&@M6V6Wwrz`L}syS9}cY}w&z*<53CbB?7wFRK<_@D*q2U|dMRiGSL0nQC=@sJ*? zLNj=fOoSg)es+hbNbrL;KRI-VsOUg@5-y-<0{3A+<7P5omJeu<05lL303I!q0gsl2 zfJe(f18D+~o(ycX4Af-@ox+GVTBd{Ela~OGmi0om0D|h)jDQy}AtPilpp*_e$rU7A z6Y$~^M7Sd0g$HCtrv{_|yigxBCjiZNJiEZvC+OJUfEV&x7#aR=0avxXE-D33CUmn6 zlnQt;a~&utIsD%Ot_NULi3+H36a#7;1-vK&jfmE$Xn;loVpK$$T~tH_n%Ag+!d0N# z{YSU|pKkH)deB&%59q8zV;>b4&=4MEEUp@qdlW!jh)(Apo!);sg}Y-^G)hE_f51oO zZW_NbE>TfHYy831_5&&xCN4%H?8Ia2fcpj=|u$~N58qcsED0_Ee4C|@ofyyXQ z@c^zVAtg-X8&HEBF+KqhOSK9nr7^)drnDDkh+^ z0(6j~!wbo6Xk~>tysUs16wpFK0bWS(<0>39$Sxef#X`3`3upwX+Z{A6ZqV({lLfl# z!vcDzBIrzr7c(1}Kr=}*Kn4C03DEf7MbPlZ-`-e`-i-gfJt|Qw3=E*vSwCIVCV+;8 z!3PaOM$>KJB?ahSEeQwk_#XJOCeUg=Fwdp?#P^%vbLHS=1gK;Hjiw8rkMtqdyMabL z7(q8WIsX9n8a=wf<9wh|MW1faI3H-lFQ6Md&Zp7oq7u^UqGAC``86OSA>hSg$iQ9* zD6xYoc93vMz>6M;a6!NeCdhPE2}l8`=?uyZ0nprVY%91F0ad2~FK(^}X9!TG@P7+< zhtz+__62B}0yh0cFnEFnQ~-NGFIa_9B`P_f?TrC13|4`#hpz~HigSVg?4K=`HhJK)`I!48yyGF$X zH1Yu&?vvQKoNVfi-oJ#lhMEtviKaFuR>J7M@oX?6f~GG(ZL3y1UlRpK{WVi*W(>- z&;dp_=m4V|bbt}}*{+a!(hXWqx8<<^D!4#(u?wggdJmds zatF=-fW{J4AhiN$af(JaGkBqp4yaB5WgmlH7ZnvysUHC%Yyw_PTnujFI0U?4hfiKY z_CP}&{^I<4u!?|y7f)A$$HyvqT~s{&m#9?yF99EFk`VAB8#HF>q7u^^4Vt})0JVQW z*T9CT7=Zez-~q5W&=DGt!AVfFPayg=XgLaKhDW5+uG0^+iUbsV@ttlgonbuS^#EO| zpuh(OHFDr%-LKLB?*AM)2+A5f80#@Zq37{}&U!<%YCxCRbi4BOg09G7Q2}j;mbnU3Eq;$FX;FIv;*fYsC0?|l}@9)&VpEHK*Z@Zev7-O_yzqw zG{0ahUGQ=p*i~~>K7i>Z;6ukjt^uD-sIdjo_tt>iaRhP|sQtz-z($^fdcd9nIRkQ# zD~NTz`6pK?JJ?mPB|!q9vm5WAy87;EenCFaPNf%&rA^%~Dxf3*x~2%U-GpC|<3)8c zY){t<=>v=m-)~4CPzA;N;WKFcVV2`;Q^4s#Wk3G(06MP`ksd(Tok7wAXo(ODBtZy( z5(Ma=N`dYj&?M0t&WI&Jbo+|5p5$-gWCq1Qhzgj3oS=9w1bmRn0h5UU5wYW~ktss*y61)Rx1tSNBT95|~7%z9k`(g;_153ceaT;)B8 zN{Bj8_64z~fHN|P16(9HoHTVS+1ey;xG{1D1u+>7v6iI`5BaNvE}C#;Qagq zJo1mbe9u5RZyj`MB_uy^0@W(n{(s{(RaFX9AhUt-DL`~o>D3f-X+ z{F*r`3ayv;TTX&5kFOQz^#kW|0no8=8hgNTz^?&`M^G^jN-&^M1dYgmmbpOpLuowa z*EkAVNtniOrSyQAKRiXnpx2!dR4}H1v%sAcaMrq$q5?XL_D%{oYu$m|S_M)CxtR&V zf@ZBd&`Rb6$jk%Gpcppjb!P&paec|aR(#;sh!?|^gaR+ptFVVfUB)n%|Ccb#Xtr; z2N9rSaqog^;k)l&gX?FI=$$3tdGnBu#SK_-IA-MipA z{B`p$hoUNefyfWduN<0>v+xTDc7{suhu;7tCU6aXkzc@5fIs{QzaU%lF$aFZ$Pb`< z<3X7ioF>E1@@wR%DDVpk!jq+-r$F;T2Ux0Xy~N*|^Y{P%?&I-s-90LxOk;fJ1%C`A zn;M_w7hD29LmJc>w*aMb!5;7-(fopIz^9&q^1@=!B-JmDqT=2b5p_le2I~*yV!e=~ zr$Oz%Ubp|uhpb&xM2dqzs|&k7^-cjB+5GH>HstupPzlf-6!7^wP)>!+7WuIMXg`jemh&Q`?z^9*fy9$8HsTYD!VQ}Ge=FFKFtG7eTCr~+rt$f-8 zE}vY$QyRF-C%o;AZdZX$7L{&SjxcZo6ugtW`2b6A7~=#iCN4Kv8zkm|I zfWQvWXgX*+yeh*-R|Zg1gb%dZM+0)h45(2DDT^Ta09>cT!y9~HgarfikQR3S@YA3J zNCfyb4)ceDlRcz*z5{7}+=1qHXsH6t^w7cuQfI@;7)aF(D{2rW0iw`BlnIF92T?j8 z3L-=~0V$H2|8bS_fbt5c(R=sk>u^vu0D_248h1^RDVSx@T1o<4?lD_&{A0!HD7v8xJ@+w&L8l-)F4J0)M?itAG^6=yV zZCyhuW`02><1_q%0xzT@Ai3cTG5sY_a&=K*Av(SKsDRGbx)fr}+gyUSv2AI;#fMQQ{8|LFp}pfR>4;s=phAu$DtA8^V9^~CO8fuu|j z`wr;Tbx5sp4HR8qMW7^m_bMc1g4lQ9?Y+D3GWWi|=bePOx zXi7v&hBumDF!HzV{|7lM<9>V`zo2Ay5BPEcP^=5RPzi&^I;^xi1CRe1DD9~!pzbcX zzZ}sCT8ZNdJwyuDFX}8&5$O$QS zUC^9Rx#1Q`q|F+nUuDGF&E zfy5y9wSidhe$X9ATMQ%ysV+b)$W>w>7UXO%5DU`h0kI$%7sP^$E`V6@jtwGF-&q6h z_<&@WzzU~3@G=)sEZgy0zhR?2`UajU)SoXQWuW^tcA`Z@Fpjrwp3A)SzE(s|r5jrn`sx_F- z5ETPZ6B3knz$QSmGR&3-{F*5$3eB$^_*>Wg`Tzgr4F=F1A)wYHXqXJtdIa^(_yv2w zC&q(XkD$u~K&?m6ag)uzIEoT`>;Ct)h=hZVq5oz5p`5!Hau0#^k774aE53IRxWU=| z3Dj=<0qUp0)@R{sFM`f8v_4g=1zK7RHKCWqQ2Sr^C+&|g{arj3NG-+YUjii(&A${% zc$$A1lnR4FU*R?0ca&EG4&~AxQV3k z$3Relj5hu_36#z>AmbCDP5^Q(3L5bPbrwOjD`A zo#Kud#0DMzAp%-54?YXZM}@-|baE2-JSBg}d@^bNkm@_s@vAgB`TS z#=z}AXwKY#4K!hH09x|z%wpii1e!HBaAO9|l^eLR@NaWwH*jMO5Bk3mWa*2<&5R7) z{w%#^9Np~AM|e8DK@(Uaoy?$fGPqy>PP@|Cb~p#Jj-!*mCvpW z!7m!2ON!b-rZxZLDCG@)u@~IUVTq56KHMA5(Yw8Yk%3{q1Sp#2K?`dc7`om5^agQs zdwuCG`_bw2rPGh4+v`WS8%L+pk4`@h&;dhtL7L$W4$yo#s0|2OpwjK5!r}qi1p(^Y z1+pA`0SXI;aPYAxaiHMn&S!!9t{Jq?*GEOAw~Pb44}#Hv9ke0O!0kKe-Z}%fAN<=K znGM{2g6^s_aQg+?f@k3Nn}3@ln}ORO&_#6yZhxC|R1_FHB|9_0A=4YkQaT+p`HF}w ztmjFAcTvJ4#*y1gzc5}=-K zzzdx{;6-fE6^*TLOA39Pk1-v5%j_BsUZ2Fjjk&k(AIPuHpc9*jP8Gc_Dk9;aDSe6m z8$dR`SiFmop_?6)IQ&^ase`%Gn+3GSe_nidkIDql3N-L?N=6^hL=4DJkWj&zUVOmm zWg~RSIC6UF1+V+1VtQ$O19BT;V+ua_g4qGIw2~*h8 zvquG#8M{3|yQC93d%$N3QaXFUtGc>9cshMlGCCpc%x(|Rp6{H_9`L!v-5w&H zJ}L#BJ>b)KyFDbj9YFVGRCGeRs_SU`K_dcfmz zoju?SYC$)9^0x`FGBEH9KCnIhEp`DlWIz`YLbnZrs#DMqS2tvZ zEVy3;y*&+dG#BLFwF$i@pxx9GpgZ-tPaJ#zI;oob1oO}CckT7FE_)3x+G;v8}>0o^P;0Z}^?1C;^ zkN{~HIQU+G`$w;cKKNt|&~26~-5)@vz7yg80MRaB{DavCyuH()`~Jb_90y-ZaNqA` z5$+CA0qv7^F+K({)dGBlLj=N9=Ih-c0~OE>6k+yJNiYVTN+AGR?;vsTIR`iBU=JB) z(3#et)Ac1_X4-(wOu;ZS0mV$PSt8)$8_t6q_)>!VJm_NCUK_#g>!5Ab#@7y>l5EaV z@nPg|_5S<+KWl15L1K3f_(n)jn+gM^ zwu_1cvkUmtdeHn;H>8Wre0)D>olR#8cXhJi+bMN}CW z7+AjFh?72`>af9)0sZ_^SpQ=O1M;pda53r1(e29<7S1mq&|NFSFAyQn?JDq@zYcWN zg+R9>2Y7}|gkONQ;4}DMR~gVY8G&wB3DA&?0jN9a06Gm@05o140BXX`25ndHSK!z9 z#INy#A9N4o!(E`#8hjS@zw`W{NyRs5{6$v;()f$M3h;-$;n#SY#{cgTsH+)%j9=qI z8h_CTo;3cVOCtPX7x*7)HAKBCRi!Mm=haChRn`@cIUvPLbzsAKh{(sj%)94x>K++(~zX|Y%eMsZ~ z_YQP0bofDjjR!EBuZZx6J>b{)lg9t=7x-}HdujYd-(WW11CLVuy9z!ixZsi>fB2a+ z{({GrSgijrx%m|%e=Ea(&>SgvVaGr4Fyz07Y5f1dBVcL#|7t)peg8^S3_wAe01nOO z9}Yzo`~vKtc^`fOLC6db=o-!NE9eg0b4cbovN(aVgUdT8>dO615_yucJ zD)rX{bx?Mq& zI6T%L_?x|8;RZ5Y`+Tp6U8j!TmhhcGyyLzGcqt_3G_l5GaxbWGO>by7rP)s4Hf%;{r}H=@TFAq5d&r) z6(4>L-iFVv4Ba;mzLaWw4Duqgk4ixILC~of2VY8oJb>8@i%7BVp0*|Ps~0l8O_%iIyrVSFbFVoAOHT4`B?WUP?KmEg98IY^F;<` z7nPjmiwvEhwTj;#F&}Kc1QIHM9Lprre2L-UTPfxjjZeX@c%hu5B4GUD;8PCf9F-F0 ztIf~^77tz<7hNg?+j>x(ftY3Qu&^uV!(U@)J75h z^gTtz0nC;V{?se7|NA2_M+PjR0A@>c#;CY}`5*&cfp+v?$z>#AAl5u-D^}XftthzyZ5MEWnf@X z{Vxx?E0?zuQo48cfcIW>_o$p_0Esg-J_OY$-BZ9fw|5^r_?88(!$n1;@hPZY>4fxZ zyYE8ly2i&KLqXSag3Nf!d+CRigtXjyS!Tm_ zp|Y$6)nv>^yXSyg>Yb2DwO*EOoseF2FUx-DwN||>ozNYsy)2VZ2Pi;0ghA(UfR|uH ztN>MODQW!IAhjj97|J*f=~RF$1Xb!4opZolisO)e1W5SB3nm7J;Qu8mCcTjUJ;<1n zfEO2;pfx5a8bP~eK3;G3ZsRu)kNZXU zzwX1|?}Med|8?K^ew!Oq7R!JIx-Wdc#SJo40K$dsj1qxxKYYK(U817GU817FU817H z{gwMO=*WHU@7*;j2Hc;xKXQNA@k^e8LHl@bKkI}4{|~;9|9t${%{e{(rxx ze6IVDvWtp|@%io&6$|BC2Osb9RPvo!w@DAomK1CT-d;RiwkKm{O3
yOboq{ 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Ȱ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